Blink My LED Example¶
This second reflex code example highlights some of the syntactical differences in the reflex language from that of basic Ansi C, and introduces you to a couple of the fundamental reflex concepts that make it different from many other embedded languages. In this example we will see the preferred method for writing a timed loop, and we will also introduce the ScratchPad, and its use as shared variable.
Here is the entire reflex file. Enabling the reflex will start the user LED blinking at a half second interval until we disable it.
1// file: flashmyled.reflex
2
3#include <a40PinModule.reflex>
4a40PinModule stem;
5
6// 1/2 second delay
7#define DELAY 500000
8#define ON 1
9#define OFF 0
10
11pad[0:0] unsigned char state;
12
13reflex mapEnable()
14{
15 state = ON;
16 stem.system.setLED(state);
17 stem.timer[0].setMode(timerModeRepeat);
18 stem.timer[0].setExpiration(DELAY);
19
20} // end of mapEnable
21
22reflex timer[0].expiration()
23{
24 if (state == ON) {
25 state = OFF;
26 } else {
27 state = ON;
28 }
29 stem.system.setLED(state);
30
31} // end of timer reflex
32
33reflex mapDisable()
34{
35 stem.timer[0].setExpiration(0);
36 stem.timer[0].setMode(timerModeSingle);
37 stem.system.setLED(OFF);
38
39}
The Timer Entity¶
Timer is a BrainStem entity class that every BrainStem module includes. It allows users to schedule events to be executed at some time in the future. Its range is approximately 1 microsecond to 4200 seconds, and its resolution is in microseconds. There is more information about the timer entity in the BrainStem Entities reference section, however there are two commands that we will use in this example.
timer setExpiration
is the method of scheduling a timer event to occur in the
future, it takes one argument which is a 32bit integer representing the number of
microseconds in the future that the timer should execute.
timer setMode
is the second command we use in the example. Timers have two
modes, single (which is the default) and repeat. Single timers execute once, and,
as you guessed, repeat timers execute on the interval defined in setExpiration.
For a timer in repeat mode, setting the expiration to 0 will stop execution of
the timer event.
stem.timer[0].setMode(timerModeRepeat);
stem.timer[0].setExpiration(DELAY);
Lines 17
and 18
in the code listing set up a repeat timer with an interval
of 500000 microseconds or 1/2 second. You will have noticed the array like syntax
of the command, BrainStem entities sometimes come in groups. There are generally
4 or 8 timers in a BrainStem module, and we address each timer by its index just
as if we had set up an array of timers.
The Timer Reflex¶
reflex timer[0].expiration()
{
if (state == ON) {
state = OFF;
} else {
state = ON;
}
stem.system.setLED(state);
}
This is the first time we have seen an “entity” reflex declaration. This code defines the behavior that should occur when the timer expires and the timer triggers.
reflex timer[0].expiration() { ...
Notice that we declare the timer index we want to attach this behavior to in the declaration. Timers don’t receive any arguments, but other Entity types like analogs and digitals do.
In this case we are setting the User LED either on or off depending on the current state. This leads naturally to the question of how to share state between reflex routines.
The ScratchPad¶
Individual reflex routines are essentially separate processes within the BrainStem system. They have their own execution space, and variable scope. The only way to share information between two reflex routines is to use the shared data space we call the ScratchPad.
pad[0:0] unsigned char state;
Line 11
in the code listing declares a single byte in the pad for use as our
shared LED state variable. We define it as an unsigned char, and we declare its
extents with the array-like syntax [0:0]
. If we were declaring a short or
an int their extents might be something like [0:1]
and [0:3]
respectively.
When declaring multiple pad variables, the extents must be mutually exclusive.
In other words, variables can not overlap. Declaring one variable with the extent
[0:3]
and another with the extent [2:5]
would not make any sense. Generally
pads are around 300 bytes, but this is module specific, so check your data sheet.
Now that we’ve declared our shared variable, it can be used in any of our reflexes.
This doesn’t seem correct. If it is not thread safe there is no guarantee that a read won’t happen in the middle of a write: In general the pad is not safe from multiple concurrent modifications, so the idiomatic pattern is to have one producer which modifies a pad variable, and one or more consumers which read it.
The Rest¶
The rest of the example should be familiar to you if you followed us from the
hello world example. The mapEnable
routine (lines 13-20
) sets up our state,
turns on the userLED, and sets the timer to expire at 1/2 second intervals. The
timer[0].expiration
routine (lines 22-31
) toggles the userLED from off
to on or vice versa. Finally the mapDisable
routine (lines 33-39
) shuts
down the timer, and turns off the userLED.
Now that we have traced through two basic examples, the remainder of the reflex reference describes the reflex language in-depth. For more information about BrainStem entities and capabilities see the Entities section of this reference. The entity concept is useful for those wishing to write host code in C, C++, or Python.
Note
There are few native datatypes in the Reflex language, essentially these are
all numeric values. They are char
, short
and int
, and they all
come in signed
and unsigned
flavors. Types are signed by default
unless specified with unsigned
keyword.