Skip to content

Commit

Permalink
Rework micro:bit tests to use Ada Drivers Library.
Browse files Browse the repository at this point in the history
  * test-microbit/buttons.adb: use ADL interrupt facilities. Allow use
      of either Port or Channel interrupts (Channel is better).
  * test-microbit/circle.adb: renamed from testbed.adb. Draw a circle
      round the edge LEDs (the spiral design made it hard to check the
      speed changes).
  * test-microbit/event_support.adb: new.
  * test-microbit/event_support.ads: new.
  * test-microbit/events.adb: new.
  * test-microbit/leds.adb: use ADL.
  * test-microbit/lights.adb: Now that the display only involves edge
      LEDs, no need for the scale factor.
  * test-microbit/tests.gpr: renamed from testbed.gpr.
  * test-microbit/Makefile: build circle (x testbed) and events.
  * test-microbit/README.md: new.
  • Loading branch information
simonjwright committed Sep 24, 2020
1 parent 122f3d3 commit 37663e5
Show file tree
Hide file tree
Showing 10 changed files with 342 additions and 74 deletions.
13 changes: 8 additions & 5 deletions test-microbit/Makefile
Original file line number Diff line number Diff line change
@@ -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.
#
Expand All @@ -16,12 +16,15 @@
# along with this program; see the file COPYING3. If not, see
# <http://www.gnu.org/licenses/>.

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
Expand Down
66 changes: 66 additions & 0 deletions test-microbit/README.md
Original file line number Diff line number Diff line change
@@ -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.
101 changes: 69 additions & 32 deletions test-microbit/buttons.adb
Original file line number Diff line number Diff line change
@@ -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.
--
Expand All @@ -18,25 +18,33 @@

with Ada.Interrupts.Names;
with Ada.Real_Time;
with nrf51.GPIO;
with nrf51.GPIOTE;
with nRF.GPIO.Tasks_And_Events;

package body Buttons is

type Button_Rep is (Button_A, Button_B);
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;

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;
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions test-microbit/testbed.adb → test-microbit/circle.adb
Original file line number Diff line number Diff line change
@@ -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.
--
Expand All @@ -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.

Expand All @@ -51,4 +51,4 @@ procedure Testbed is

begin
delay until Ada.Real_Time.Time_Last;
end Testbed;
end Circle;
55 changes: 55 additions & 0 deletions test-microbit/event_support.adb
Original file line number Diff line number Diff line change
@@ -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
-- <http://www.gnu.org/licenses/>.

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;
54 changes: 54 additions & 0 deletions test-microbit/event_support.ads
Original file line number Diff line number Diff line change
@@ -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
-- <http://www.gnu.org/licenses/>.

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;
Loading

0 comments on commit 37663e5

Please sign in to comment.