diff --git a/test-microbit/Makefile b/test-microbit/Makefile
index 99923e2..b8e4e32 100644
--- a/test-microbit/Makefile
+++ b/test-microbit/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 Free Software Foundation, Inc.
+# Copyright (C) 2018, 2020 Free Software Foundation, Inc.
#
# This file is part of the Cortex GNAT RTS package.
#
@@ -16,12 +16,15 @@
# along with this program; see the file COPYING3. If not, see
# .
-all: seconds.hex testbed.hex
+all: circle.hex events.hex seconds.hex
-seconds testbed: force
- gprbuild -p -P testbed
+circle events seconds: rebuild.stamp
+rebuild.stamp: force
+ gprbuild -p -P tests
+ touch $@
clean::
- gprclean -P testbed
+ gprclean -P tests
+ rm -f rebuild.stamp
clean::
-rm *~ *.ali *.o *.hex
diff --git a/test-microbit/README.md b/test-microbit/README.md
new file mode 100644
index 0000000..710b18a
--- /dev/null
+++ b/test-microbit/README.md
@@ -0,0 +1,66 @@
+# micro:bit tests and demos #
+
+There are three programs built by `make` (or `gprbuild`, but `make` goes on to build hex files that can be dropped onto the micro:bit):
+
+* `circle` displays a circle running round the LEDs: pressing button A alters the speed, button B alters the direction (clockwise/anticlockwise). The buttons are interrupt-driven.
+
+* `events` demonstrates `Timing_Events`. The top-left LED (row 1, column 1) flashes every 2 seconds, the LED in row 4, column 5 flashes every 5 seconds. _Why not the bottom right LED? because of the complicated mapping of GPIOs to LEDS_.
+
+* `seconds` checks out `Clock` functionality by flashing the centre LED once a second. You get to time a number of flashes with a stopwatch to make sure it really is once a second.
+
+The tests interact with the micro:bit hardware using the [Ada\_Drivers\_Library](https://github.com/AdaCore/Ada_Drivers_Library). Configure it using that library's `project_wizard.py`:
+```
+Welcome to the Ada Drivers Library (ADL) project wizard. This script will
+ask you some questions to define the ADL configuration of your project. It will
+then generate the different files required to use ADL based on this
+configuration.
+Board
+ - (0) Custom_Board
+ - (1) STM32F407_Discovery
+ - (2) STM32F429_Discovery
+ - (3) STM32F469_Discovery
+ - (4) STM32F746_Discovery
+ - (5) STM32F769_Discovery
+ - (6) STM32_H405
+ - (7) NUCLEO_F446ZE
+ - (8) Crazyflie
+ - (9) Feather_STM32F405
+ - (10) OpenMV2
+ - (11) MicroBit
+ - (12) NRF52_DK
+ - (13) HiFive1
+ - (14) HiFive1_rev_B
+ - (15) Unleashed
+ - (16) Native
+? 11
+For key 'Architecture', take value 'ARM' from board definition
+For key 'Vendor', take value 'Nordic' from board definition
+For key 'Device_Family', take value 'nRF51' from board definition
+For key 'Device_Name', take value 'nRF51822xxAA' from board definition
+For key 'Number_Of_Interrupts', take value '32' from MCU definition
+For key 'Has_ZFP_Runtime', take value 'True' from board definition
+For key 'Has_Ravenscar_SFP_Runtime', take value 'False' from board definition
+For key 'Has_Ravenscar_Full_Runtime', take value 'False' from board definition
+Runtime_Profile
+ - (0) zfp
+?
+For key 'Runtime_Name_Suffix', take value 'cortex-m0' from board definition
+Runtime_Name [default: 'zfp-cortex-m0']
+? ../../../local/microbit
+Use_Startup_Gen [y/N]
+
+Boot_Memory [default: 'flash']
+?
+Max_Path_Length [default: 1024]
+
+Max_Mount_Points [default: 2]
+
+Max_Mount_Name_Length [default: 128]
+
+The configuration is now finished.
+Let's generate some files:
+ -> Writing gprbuild project file.
+ -> Writing the Ada configuration file.
+Your Ada Drivers Library project is now ready to use.
+```
+After selecting the `MicroBit`, the default (RET) is OK for most answers. The only odd one is that for `Runtime_Name`; the output files are created in the directory `Ada_Drivers_Library`, so the generated `ada_drivers_library.gpr` is one level down, and to select the locally-installed runtime you have to go up three levels and down 2.
diff --git a/test-microbit/buttons.adb b/test-microbit/buttons.adb
index d710974..73f8cc8 100644
--- a/test-microbit/buttons.adb
+++ b/test-microbit/buttons.adb
@@ -1,4 +1,4 @@
--- Copyright (C) 2018 Free Software Foundation, Inc.
+-- Copyright (C) 2018, 2020 Free Software Foundation, Inc.
-- This file is part of the Cortex GNAT RTS package.
--
@@ -18,8 +18,7 @@
with Ada.Interrupts.Names;
with Ada.Real_Time;
-with nrf51.GPIO;
-with nrf51.GPIOTE;
+with nRF.GPIO.Tasks_And_Events;
package body Buttons is
@@ -27,6 +26,7 @@ package body Buttons is
for Button_Rep use (Button_A => 17, Button_B => 26);
type Button_Data is record
+ Point : nRF.GPIO.GPIO_Point;
State : Toggle := Off;
Last_Time : Ada.Real_Time.Time := Ada.Real_Time.Time_First;
end record;
@@ -34,9 +34,17 @@ package body Buttons is
type Buttons_Data is array (Button_Rep) of Button_Data;
protected Button_Handler is
+ -- Only call one of these.
+ procedure Enable_Channel_Interrupts;
+ procedure Enable_Port_Interrupts;
+
function Button_State (Btn : Button_Rep) return Toggle;
private
- State : Buttons_Data;
+ State : Buttons_Data :=
+ (Button_A => (Point => (Pin => Button_A'Enum_Rep),
+ others => <>),
+ Button_B => (Point => (Pin => Button_B'Enum_Rep),
+ others => <>));
procedure Handler
with Attach_Handler => Ada.Interrupts.Names.GPIOTE_IRQ;
end Button_Handler;
@@ -47,51 +55,80 @@ package body Buttons is
when B => Button_B));
protected body Button_Handler is
+
+ procedure Enable_Channel_Interrupts is
+ use nRF.GPIO.Tasks_And_Events;
+ begin
+ Enable_Event (Chan => 0,
+ GPIO_Pin => Button_A'Enum_Rep,
+ Polarity => Falling_Edge);
+ Enable_Channel_Interrupt (Chan => 0);
+ Enable_Event (Chan => 1,
+ GPIO_Pin => Button_B'Enum_Rep,
+ Polarity => Falling_Edge);
+ Enable_Channel_Interrupt (Chan => 1);
+ end Enable_Channel_Interrupts;
+
+ procedure Enable_Port_Interrupts is
+ begin
+ nRF.GPIO.Tasks_And_Events.Enable_Port_Interrupt;
+ end Enable_Port_Interrupts;
+
function Button_State (Btn : Button_Rep) return Toggle is
(State (Btn).State);
procedure Handler is
- begin
- nrf51.GPIOTE.GPIOTE_Periph.EVENTS_PORT := 0;
- declare
+ use nRF.GPIO;
+ procedure Process_Event (For_Button : Button_Rep);
+ procedure Process_Event (For_Button : Button_Rep) is
Now : constant Ada.Real_Time.Time := Ada.Real_Time.Clock;
Other : constant array (Toggle) of Toggle := (Off => On,
On => Off);
- use nrf51.GPIO;
use type Ada.Real_Time.Time;
use type Ada.Real_Time.Time_Span;
begin
- for B in State'Range loop
- if GPIO_Periph.IN_k.Arr (B'Enum_Rep) = Low
- and then Now - State (B).Last_Time
- > Ada.Real_Time.Milliseconds (25)
- then
- State (B).State := Other (State (B).State);
- State (B).Last_Time := Now;
- end if;
- end loop;
- end;
+ if not State (For_Button).Point.Set
+ and then Now - State (For_Button).Last_Time
+ > Ada.Real_Time.Milliseconds (50) -- debouncing
+ then
+ State (For_Button).State := Other (State (For_Button).State);
+ State (For_Button).Last_Time := Now;
+ end if;
+ end Process_Event;
+ begin
+ if Tasks_And_Events.Channel_Event_Set (Chan => 0) then
+ Tasks_And_Events.Acknowledge_Channel_Interrupt (Chan => 0);
+ Process_Event (Button_A);
+ end if;
+ if Tasks_And_Events.Channel_Event_Set (Chan => 1) then
+ Tasks_And_Events.Acknowledge_Channel_Interrupt (Chan => 1);
+ Process_Event (Button_B);
+ end if;
+ if Tasks_And_Events.Port_Event_Set then
+ Tasks_And_Events.Acknowledge_Port_Interrupt;
+ Process_Event (Button_A);
+ Process_Event (Button_B);
+ end if;
end Handler;
end Button_Handler;
procedure Initialize;
procedure Initialize is
- use nrf51.GPIO;
- use nrf51.GPIOTE;
+ use nRF.GPIO;
+ Config : constant GPIO_Configuration :=
+ (Mode => Mode_In,
+ Resistors => Pull_Up,
+ Input_Buffer => Input_Buffer_Connect,
+ Sense => Sense_For_Low_Level,
+ others => <>);
begin
-- Buttons
- GPIO_Periph.PIN_CNF (Button_A'Enum_Rep) := (DIR => Input,
- INPUT => Connect,
- PULL => Pullup,
- SENSE => Low,
- others => <>);
- GPIO_Periph.PIN_CNF (Button_B'Enum_Rep) := (DIR => Input,
- INPUT => Connect,
- PULL => Pullup,
- SENSE => Low,
- others => <>);
-
- GPIOTE_Periph.INTENSET.PORT := Set;
+ Configure_IO (This => (Pin => Button_A'Enum_Rep),
+ Config => Config);
+ Configure_IO (This => (Pin => Button_B'Enum_Rep),
+ Config => Config);
+
+ Button_Handler.Enable_Channel_Interrupts;
end Initialize;
begin
diff --git a/test-microbit/testbed.adb b/test-microbit/circle.adb
similarity index 94%
rename from test-microbit/testbed.adb
rename to test-microbit/circle.adb
index b41f66f..cb0f8fe 100644
--- a/test-microbit/testbed.adb
+++ b/test-microbit/circle.adb
@@ -1,4 +1,4 @@
--- Copyright (C) 2018 Free Software Foundation, Inc.
+-- Copyright (C) 2018,2020 Free Software Foundation, Inc.
-- This file is part of the Cortex GNAT RTS package.
--
@@ -24,7 +24,7 @@ pragma Unreferenced (Lights);
with Ada.Real_Time;
-procedure Testbed is
+procedure Circle is
-- These are the default values of the stack control parameters.
@@ -51,4 +51,4 @@ procedure Testbed is
begin
delay until Ada.Real_Time.Time_Last;
-end Testbed;
+end Circle;
diff --git a/test-microbit/event_support.adb b/test-microbit/event_support.adb
new file mode 100644
index 0000000..f11ca28
--- /dev/null
+++ b/test-microbit/event_support.adb
@@ -0,0 +1,55 @@
+-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+-- This file is part of the Cortex GNAT RTS package.
+--
+-- The Cortex GNAT RTS package is free software; you can redistribute
+-- it and/or modify it under the terms of the GNU General Public
+-- License as published by the Free Software Foundation; either
+-- version 3 of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; see the file COPYING3. If not, see
+-- .
+
+package body Event_Support is
+
+ protected body LED_Event_Handling is
+
+ procedure Handle
+ (Event : in out Ada.Real_Time.Timing_Events.Timing_Event)
+ is
+ Our_Event : LED_Event
+ renames LED_Event
+ (Ada.Real_Time.Timing_Events.Timing_Event'Class (Event));
+ New_State : constant Boolean := Our_Event.State;
+ Flash : constant Milliseconds := 250;
+ use type Ada.Real_Time.Time;
+ begin
+ Set_LEDs (Our_Event.Row, Our_Event.Col) := New_State;
+ Our_Event.State := not New_State;
+ LEDs.Clear_All_LEDs;
+ for R in LEDs.Coord loop
+ for C in LEDs.Coord loop
+ if Set_LEDs (R, C) then
+ LEDs.Set_One_LED (R, C);
+ end if;
+ end loop;
+ end loop;
+ -- turn off after Flash, turn on after the event's Period
+ -- minus Flash
+ Event.Set_Handler
+ (Handler => Handler,
+ At_Time => Ada.Real_Time.Clock
+ + Ada.Real_Time.Milliseconds (if New_State
+ then Flash
+ else Our_Event.Period - Flash));
+ end Handle;
+
+ end LED_Event_Handling;
+
+end Event_Support;
diff --git a/test-microbit/event_support.ads b/test-microbit/event_support.ads
new file mode 100644
index 0000000..c5cde7a
--- /dev/null
+++ b/test-microbit/event_support.ads
@@ -0,0 +1,54 @@
+-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+-- This file is part of the Cortex GNAT RTS package.
+--
+-- The Cortex GNAT RTS package is free software; you can redistribute
+-- it and/or modify it under the terms of the GNU General Public
+-- License as published by the Free Software Foundation; either
+-- version 3 of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; see the file COPYING3. If not, see
+-- .
+
+with LEDs;
+with Ada.Real_Time.Timing_Events;
+package Event_Support is
+
+ subtype Milliseconds is Natural;
+
+ type LED_Event is new Ada.Real_Time.Timing_Events.Timing_Event
+ with record
+ Row : LEDs.Coord;
+ Col : LEDs.Coord;
+ Period : Milliseconds;
+ State : Boolean;
+ end record;
+
+ Slow : LED_Event :=
+ (Ada.Real_Time.Timing_Events.Timing_Event
+ with 4, 5, 5000, True);
+ Quick : LED_Event :=
+ (Ada.Real_Time.Timing_Events.Timing_Event
+ with 1, 1, 2000, True);
+
+ type LEDs_Status is array (LEDs.Coord, LEDs.Coord) of Boolean;
+ -- (Row, Col)
+
+ protected LED_Event_Handling is
+ pragma Interrupt_Priority;
+ procedure Handle
+ (Event : in out Ada.Real_Time.Timing_Events.Timing_Event);
+ private
+ Set_LEDs : LEDs_Status := (others => (others => False));
+ end LED_Event_Handling;
+
+ Handler : constant Ada.Real_Time.Timing_Events.Timing_Event_Handler
+ := LED_Event_Handling.Handle'Access;
+
+end Event_Support;
diff --git a/test-microbit/events.adb b/test-microbit/events.adb
new file mode 100644
index 0000000..dea22c9
--- /dev/null
+++ b/test-microbit/events.adb
@@ -0,0 +1,40 @@
+-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+-- This file is part of the Cortex GNAT RTS package.
+--
+-- The Cortex GNAT RTS package is free software; you can redistribute
+-- it and/or modify it under the terms of the GNU General Public
+-- License as published by the Free Software Foundation; either
+-- version 3 of the License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; see the file COPYING3. If not, see
+-- .
+
+with Event_Support;
+with Ada.Real_Time.Timing_Events;
+-- with Hardfault_Handling;
+-- pragma Unreferenced (Hardfault_Handling);
+procedure Events is
+ -- Environment_Task_Storage_Size : constant Natural := 1536
+ -- with
+ -- Export,
+ -- Convention => Ada,
+ -- External_Name => "_environment_task_storage_size";
+ -- Default_Initial_Stack : constant Natural := 4096
+ -- with
+ -- Export,
+ -- Convention => Ada,
+ -- External_Name => "_default_initial_stack";
+begin
+ Event_Support.LED_Event_Handling.Handle
+ (Ada.Real_Time.Timing_Events.Timing_Event (Event_Support.Slow));
+ Event_Support.Handler
+ (Ada.Real_Time.Timing_Events.Timing_Event (Event_Support.Quick));
+ delay until Ada.Real_Time.Time_Last;
+end Events;
diff --git a/test-microbit/leds.adb b/test-microbit/leds.adb
index 77d3525..d97d220 100644
--- a/test-microbit/leds.adb
+++ b/test-microbit/leds.adb
@@ -16,7 +16,7 @@
-- along with this program; see the file COPYING3. If not, see
-- .
-with nrf51.GPIO;
+with nRF.GPIO;
package body LEDs is
@@ -31,10 +31,26 @@ package body LEDs is
type Row_Pin is (R1, R2, R3);
for Row_Pin use (R1 => 13, R2 => 14, R3 => 15);
+ Row_Points : array (Row_Pin) of nRF.GPIO.GPIO_Point
+ := (R1 => (Pin => R1'Enum_Rep),
+ R2 => (Pin => R2'Enum_Rep),
+ R3 => (Pin => R3'Enum_Rep));
+
type Col_Pin is (C1, C2, C3, C4, C5, C6, C7, C8, C9);
for Col_Pin use (C1 => 4, C2 => 5, C3 => 6, C4 => 7, C5 => 8,
C6 => 9, C7 => 10, C8 => 11, C9 => 12);
+ Col_Points : array (Col_Pin) of nRF.GPIO.GPIO_Point
+ := (C1 => (Pin => C1'Enum_Rep),
+ C2 => (Pin => C2'Enum_Rep),
+ C3 => (Pin => C3'Enum_Rep),
+ C4 => (Pin => C4'Enum_Rep),
+ C5 => (Pin => C5'Enum_Rep),
+ C6 => (Pin => C6'Enum_Rep),
+ C7 => (Pin => C7'Enum_Rep),
+ C8 => (Pin => C8'Enum_Rep),
+ C9 => (Pin => C9'Enum_Rep));
+
type LED_Pins is record
R : Row_Pin;
C : Col_Pin;
@@ -48,38 +64,39 @@ package body LEDs is
((R3, C3), (R2, C7), (R3, C1), (R2, C6), (R3, C2)));
procedure Clear_All_LEDs is
- use nrf51.GPIO;
+ use nRF.GPIO;
begin
for R in Row_Pin loop
- GPIO_Periph.OUT_k.Arr (R'Enum_Rep) := Low;
+ Row_Points (R).Clear;
end loop;
for C in Col_Pin loop
- GPIO_Periph.OUT_k.Arr (C'Enum_Rep) := High;
+ Col_Points (C).Set;
end loop;
end Clear_All_LEDs;
procedure Set_One_LED (Row, Col : Coord) is
Pins : constant LED_Pins := LEDs (Row, Col);
- use nrf51.GPIO;
+ use nRF.GPIO;
begin
- GPIO_Periph.OUT_k.Arr (Pins.R'Enum_Rep) := High;
- GPIO_Periph.OUT_k.Arr (Pins.C'Enum_Rep) := Low;
+ Row_Points (Pins.R).Set;
+ Col_Points (Pins.C).Clear;
end Set_One_LED;
procedure Initialize;
procedure Initialize is
- use nrf51.GPIO;
+ use nRF.GPIO;
+ Config : constant GPIO_Configuration := (Mode => Mode_Out,
+ Resistors => Pull_Up,
+ others => <>);
begin
-- LED matrix
for R in Row_Pin loop
- GPIO_Periph.PIN_CNF (R'Enum_Rep) := (DIR => Output,
- PULL => Pullup,
- others => <>);
+ Configure_IO (This => (Pin => R'Enum_Rep),
+ Config => Config);
end loop;
for C in Col_Pin loop
- GPIO_Periph.PIN_CNF (C'Enum_Rep) := (DIR => Output,
- PULL => Pullup,
- others => <>);
+ Configure_IO (This => (Pin => C'Enum_Rep),
+ Config => Config);
end loop;
Clear_All_LEDs;
diff --git a/test-microbit/lights.adb b/test-microbit/lights.adb
index 70afa14..c823c84 100644
--- a/test-microbit/lights.adb
+++ b/test-microbit/lights.adb
@@ -1,4 +1,4 @@
--- Copyright (C) 2018 Free Software Foundation, Inc.
+-- Copyright (C) 2018, 2020 Free Software Foundation, Inc.
-- This file is part of the Cortex GNAT RTS package.
--
@@ -34,19 +34,13 @@ package body Lights is
type Coord_Pair is record
R : Coord;
C : Coord;
- Scaling : Positive; -- multiplies basic interval
end record;
type LED_Sequence is array (Positive range <>) of Coord_Pair;
- Spiral_Clockwise : constant LED_Sequence :=
- ((1, 1, 1), (1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1),
- (2, 5, 1), (3, 5, 1), (4, 5, 1), (5, 5, 1),
- (5, 4, 1), (5, 3, 1), (5, 2, 1), (5, 1, 1),
- (4, 1, 1), (3, 1, 1), (2, 1, 1),
- (2, 2, 2), (2, 3, 2), (2, 4, 2),
- (3, 4, 2), (4, 4, 2),
- (4, 3, 2), (4, 2, 2),
- (3, 2, 3),
- (3, 3, 4));
+ Clockwise : constant LED_Sequence :=
+ ((1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
+ (2, 5), (3, 5), (4, 5), (5, 5),
+ (5, 4), (5, 3), (5, 2), (5, 1),
+ (4, 1), (3, 1), (2, 1));
function Interval return Ada.Real_Time.Time_Span is
(case Buttons.Button_State (Buttons.A) is
@@ -60,18 +54,18 @@ package body Lights is
loop
case Buttons.Button_State (Buttons.B) is
when Buttons.Off =>
- for S of Spiral_Clockwise loop
+ for S of Clockwise loop
exit when Buttons.Button_State (Buttons.B) = Buttons.On;
Clear_All_LEDs;
Set_One_LED (S.R, S.C);
- delay until Ada.Real_Time.Clock + Interval * S.Scaling;
+ delay until Ada.Real_Time.Clock + Interval;
end loop;
when Buttons.On =>
- for S of reverse Spiral_Clockwise loop
+ for S of reverse Clockwise loop
exit when Buttons.Button_State (Buttons.B) = Buttons.Off;
Clear_All_LEDs;
Set_One_LED (S.R, S.C);
- delay until Ada.Real_Time.Clock + Interval * S.Scaling;
+ delay until Ada.Real_Time.Clock + Interval;
end loop;
end case;
end loop;
diff --git a/test-microbit/testbed.gpr b/test-microbit/tests.gpr
similarity index 90%
rename from test-microbit/testbed.gpr
rename to test-microbit/tests.gpr
index 6db7da4..1458c82 100644
--- a/test-microbit/testbed.gpr
+++ b/test-microbit/tests.gpr
@@ -1,4 +1,4 @@
--- Copyright (C) 2018 Free Software Foundation, Inc.
+-- Copyright (C) 2018, 2020 Free Software Foundation, Inc.
--
-- This file is part of the Cortex GNAT RTS package.
--
@@ -16,9 +16,11 @@
-- along with this program; see the file COPYING3. If not, see
-- .
-project Testbed is
+with "Ada_Drivers_Library/ada_drivers_library";
- for Main use ("seconds.adb", "testbed.adb");
+project Tests is
+
+ for Main use ("circle.adb", "events.adb", "seconds.adb");
for Languages use ("Ada");
for Source_Dirs use (".", "../test-common");
for Object_Dir use ".build";
@@ -62,4 +64,4 @@ project Testbed is
for Communication_Protocol use "remote";
end IDE;
-end Testbed;
+end Tests;