Time-Ordered Behavior in C Programming
Time-Ordered Behavior in C Programming
com/zybook/Ak78Fta73x/chapter/3/print
Like most programming languages, C was not designed for time-ordered behavior. C uses a
sequential instructions computation model, wherein statements (instructions) in a list are executed
sequentially (one after another) until the list's end is reached. A sequential instructions model is
good for capturing algorithms that transform given input data into output data, known as data
processing behavior. However, the sequential instructions model is poorly-suited for capturing
time-ordered behavior.
For example, consider a system on a carousel (merry-go-round) that increments B whenever the
carousel rotates once, detected by a sensor that brie�y pulses A0 for each rotation. The following
RIMS code captures the system's behavior.
PARTICIPATION
ACTIVITY 3.1.1: Pulse counting code for a carousel.
Animation content:
C program:
#include "RIMS.h"
void main()
{
B = 0;
while (1) {
while (!A0);
B = B + 1;
©zyBooks 11/05/21 13:38 231883
while (A0); Lawrence Nderu
} Ak78Fta73x
}
Animation captions:
1 of 46 11/5/2021, 1:39 PM
Firefox [Link]
The code's statements like while (!A0); may look unusual to a beginning embedded
programmer. The statement loops as long as A0 is 0, and the immediate ; means no statements
execute within the loop. Because C isn't designed to capture such time-oriented behavior, the code
is slightly awkward, but understandable. However, the code becomes less understable as more
©zyBooks
time-oriented behavior is introduced, such as having a button A1 that resets 11/05/21 13:38below.
B, as shown 231883
Lawrence Nderu
Ak78Fta73x
#include "RIMS.h"
void main()
{
B = 0;
while (1) {
while (!A1 && !A0);
if (A1) {
B = 0; // Reset
}
else {
B = B + 1;
while (A0);
}
}
}
The code is becoming harder to understand. The text itself is simple, but how the code interacts
with the inputs over time is not obvious, and requires plenty of mental execution to understand the
system's behavior. With even more time-oriented behavior introduced, the code may become a
spaghetti-like mess whose behavior is extremely hard to understand.
The lesson is this: Capturing time-ordered behavior directly into C's sequential instructions
computation model is challenging. Instead, a computation model better suited
©zyBooks for capturing
11/05/21 time-
13:38 231883
ordered behavior is needed. State machines, introduced in another section,Lawrence Nderu
is one such model.
Ak78Fta73x
PARTICIPATION
ACTIVITY 3.1.2: Time-ordered behavior.
2 of 46 11/5/2021, 1:39 PM
Firefox [Link]
A state machine is a computation model intended for capturing time-ordered behavior. Numerous
kinds of state machines exist. Common features of state machines are a set of inputs and outputs,
a set of states with actions, a set of transitions with conditions, and an initial state. A drawing of a
state machine is called a state diagram.
3 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Consider a simple time-oriented system that turns on a light (by setting B0 = 1) if a user presses a
button (A0 is 1 when pressed). The light stays on even after the button is released. Pressing a
second button (A1 is 1) turns the light off. The following �gure captures that behavior as a state
machine.
PARTICIPATION
ACTIVITY 3.2.1: A basic light toggle SM.
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Animation content: Ak78Fta73x
Shown state machine has input A0 and A1 and output B0, and the states
Unlit (with action B0 = 0) and Lit (with action B0 = 1).
The Unlit state has two transitions with conditions A0 and !A0. The
!A0 condition transitions back to Unlit and A0 transitions to Lit.
The Lit state has two transitions with conditions A1 and !A1. The !A1
condition transitions back to Lit and A1 transitions to Unlit.
Animation captions:
1. The SM has has two inputs, A0 and A1, and one output, B0. The SM has two states Unlit
and Lit. The Unlit state turns off the LED by setting B0 = 0. The Lit state turns on the LED by
setting B0 = 1.
2. The SM implements a basic light toggle that turns on a light if a user presses the button
connected to A0.
3. The light remains on even after the button to A0 is released. Pressing a second button,
connected to A1, turns the light off.
The above animation shows a state machine with inputs A0 and A1 and output B0 (each 1 bit), and
the states Unlit (with action B0 = 0) and Lit (with action B0 = 1). The state machine has four
transitions with conditions !A0, A0, !A1, and A1, and the initial state is Unlit (denoted by the special
"initial transition" arrow).
A system described by a state machine executes as follows. At any time, the system is "in" some
state, called the current state. Upon starting, the transition to the initial state is taken and that
©zyBooks 11/05/21 13:38 231883
state's actions are executed once. The following process then occurs, called a tick of
Lawrence the SM:
Nderu
Ak78Fta73x
• A transition T leaving the current state and having a true condition is taken
• Transition T's target state has its actions executed once and becomes the current state
The ticking process repeats. Each tick takes a tiny but non-zero (perhaps nearly-in�nitesimally
small) amount of time, during which no event is assumed to occur. Ticks are assumed to occur at a
much faster rate than input events, so no input events are missed. The following animation
4 of 46 11/5/2021, 1:39 PM
Firefox [Link]
illustrates SM ticking.
PARTICIPATION
ACTIVITY 3.2.2: SM ticks.
Animation content:
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Shown state machine has input A0 and A1 and output B0,Ak78Fta73x
and the states
Unlit (with action B0 = 0) and Lit (with action B0 = 1).
The Unlit state has two transitions with conditions A0 and !A0. The
!A0 condition transitions back to Unlit and A0 transitions to Lit.
The Lit state has two transitions with conditions A1 and !A1. The !A1
condition transitions back to Lit and A1 transitions to Unlit.
Animation captions:
For the above example, upon startup the system takes the transition to state Unlit and executes B0
= 0 once. For subsequent ticks, if A0 is 0 then the system takes the transition back to state Unlit
and executes B0 = 0 again. At some time, if A0 is 1 then the system takes the transition to state Lit
and executes B0 = 1. The system stays in that state until A1 becomes 1, at which time the system
takes the transition back to state Unlit.
PARTICIPATION
ACTIVITY 3.2.3: Tracing execution of an SM.
Given the following timing diagram and the above light on/off SM, determine the value of
B0 at the speci�ed times.
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
5 of 46 11/5/2021, 1:39 PM
Firefox [Link]
1) 0 s
1
0
2) 1 s
1 ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
0 Ak78Fta73x
3) 2 s
1
0
4) 3 s
1
0
5) 4 s
1
0
6) 5 s
1
0
For the above input sequence, the light was on from about 0.5 seconds when A0's button was
pressed, until about 2.5 seconds when A1's button was pressed.
If none of the current state's transitions has a true condition for a given tick, an implicit transition
back to the state itself is taken (thus causing the state's actions to execute each such tick). Good
practice, however, is to have an explicit transition point back to the same state with the proper
condition, rather than relying on the implicit transition from a state©zyBooks
to itself. The above
11/05/21 system
13:38 has
231883
Lawrence Nderu
an explicit transition with condition !A0 from Unlit back to Unlit, for example, making very clear what
Ak78Fta73x
happens when in state Unlit and A0 is 0.
For a state machine to be precisely de�ned, transitions leaving a particular state should have
mutually exclusive transition conditions, meaning only one condition could possibly be true at any
time (otherwise, which of two transitions with true conditions should be taken? The state machine
becomes non-deterministic in that case). For example, state Unlit transitions have conditions A0
and !A0, only one of which can possibly be true at any time.
6 of 46 11/5/2021, 1:39 PM
Firefox [Link]
A transition may be speci�ed to have a condition of "true" or 1, meaning the transition should
always be taken. That transition of course should be the only one leaving a particular state, else
mutual exclusivity would not exist. A common shorthand notation omits the "true"; a transition with
no condition is known to have a true condition.
A state may have multiple actions, such as B0 = 1; B1 = 1; or may have no actions at all. A
state's actions execute once each time that a tick takes the state machine to that state, even if a
transition points back to the same state. ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
We will use a particular form of a state machine model, referred to in this material just as an SM,
intended for creating C programs that support time-ordered behavior. An SM uses declared C
variables rather than explicit inputs and outputs; the lone exception is the use of RIMS' implicitly-
declared A and B input and output variables though. The SM's state actions consist of C
statements, and the SM's transitions consist of C expressions. Variable values (such as B0 = 1)
persist between ticks.
Using an SM, the earlier section's pulse counting system for a carousel can be captured as follows.
Note how the SM more clearly de�nes the time-oriented behavior, versus the earlier section's
awkward C code.
A reset behavior that returns the state machine to the initial state when A1 is pressed can be easily
added, as shown below.
7 of 46 11/5/2021, 1:39 PM
Firefox [Link]
The following timing diagram shows a sample sequence of inputs to the above SM.
PARTICIPATION
ACTIVITY 3.2.4: Tracing the pulsing counting SM.
Given the above SM input sequence, type the SM's current state at the speci�ed times. At
time 0 ms, the answer is: Init.
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
1) 0 s Ak78Fta73x
2) 0.5 s
8 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Complete the above timing diagram by showing the current state and also the B0 signal value.
Notice that the SM model and the C code from an earlier section have the same
©zyBooks behavior.
11/05/21 However,
13:38 231883
Lawrence Nderu
the SM more explicitly captures the desired time-ordered behavior. This straightforwardness
Ak78Fta73x
can be
further seen by trying to extend the SM.
9 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Extend the pulse counter SM to set B7 = 1 to indicate when the value of B reaches 99 (for
the carousel system, such an indication may tell the ride operator to do a routine safety
check). Note that 99 requires only the lower 7 bits of B, so B7 can©zyBooks
be used 11/05/21
for such13:38 231883
indication. When 99 is reached, counting stops until a rising event on A1Lawrence
resets theNderu
count.
Ak78Fta73x
The following pattern is common in SMs for detecting a rising edge of a signal. The SM stays in the
state while A0 is 0. When A0 becomes one, the transition is taken to another state. Detecting a
falling edge is similar, with the condition swapped.
PARTICIPATION
ACTIVITY 3.2.5: State machines.
10 of 46 11/5/2021, 1:39 PM
Firefox [Link]
0
1
Many
In�nite
3) In the SM model, which is true about
ticks and input events? ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Input events may occur faster Ak78Fta73x
than ticks.
Two events may occur between
ticks.
An event may occur in the
middle of a tick.
Ticks occur faster than events.
Exploring further:
3.3 RIBS
The RIBS (Riverside-Irvine Builder of State machines) tool supports graphical state diagram capture
of SMs.
PARTICIPATION
ACTIVITY 3.3.1: RIBS: Low and high example. Full screen
11 of 46 11/5/2021, 1:39 PM
Firefox [Link]
LoHi +
A0 0
A1 0
A2 0
©zyBooks 11/05/21 13:38 231883
A3 0 Lawrence Nderu
Ak78Fta73x
A4 0
A5 0
A6 0
A7 0
A = 0
PARTICIPATION
ACTIVITY 3.3.2: RIBS basics.
12 of 46 11/5/2021, 1:39 PM
Firefox [Link]
True
4) When False
an SM is executing (by pressing
"Simulate"), the values of inputs A0,
A1, A2, ..., cannot be changed.
True
False ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
PARTICIPATION
ACTIVITY 3.3.3: RIBS with export/import. Full screen
• SMs can be saved. Press "Export" and copy-paste the exported text. Modify the SM
somehow. Then paste the text into the box and press "Import" -- the previously-
exported SM is restored. (Users can save the exported text in a �le or email for
future use.)
LoHi +
A0 0
A1 0
A2 0
A3 0
A4 0
A5 0
A6 0
A7 0
13 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Export to RIMS
Export Import Lo hi
PARTICIPATION
ACTIVITY 3.3.4: RIBS with export.
3.4 Implementing an SM in C
Because microprocessors typically have C compilers but not SM compilers, implementing an SM in
C is necessary. Using a standard method for implementing an SM to C enhances the readability
and correctness of the resulting C code. The following illustrates such a method for the given SM
named Latch (abbreviated as LA), which saves (or "latches") the value of A1 onto B0 whenever A0 is
1.
14 of 46 11/5/2021, 1:39 PM
Firefox [Link]
#include "RIMS.h"
void TickFct_Latch()
{
switch(LA_State) { // Transitions
case LA_SMStart: // Initial transition
LA_State = LA_s0;
break;
case LA_s0:
if (!A0) {
LA_State = LA_s0;
}
else if (A0) {
LA_State = LA_s1;
}
break;
case LA_s1:
if (!A0) {
LA_State = LA_s0;
}
else if (A0) {
LA_State = LA_s1;
}
break;
default:
LA_State = LA_SMStart; ©zyBooks 11/05/21 13:38 231883
break;
Lawrence Nderu
} // Transitions
Ak78Fta73x
switch(LA_State) { // State actions
case LA_s0:
break;
case LA_s1:
B0 = A1;
break;
default:
break;
15 of 46 11/5/2021, 1:39 PM
Firefox [Link]
TickFct_Latch();
}
}
While the code may seem imposing, the code follows a simple pattern:
State variable declaration: The �rst line creates a new enum data type LA_States de�ned to have
possible values of LA_SMStart, LA_s0 and LA_s1. That same code line declares global variable
LA_State to be of type LA_States. enum is a C construct for de�ning a new data type, in contrast to
built-in types like char or short, whose value can be one of an "enumerated" list of values. The
programmer provides the enumeration list, as in { LA_SMStart, LA_s0, LA_s1 } above. In C, each
item in the list becomes a new constant, with the �rst item having value 0, the second item having
value 1, etc.
Tick function: The SM's tick function carries out one tick of the SM. This SM's tick function is
named TickFct_Latch(). For the current state LA_State, the tick function's �rst switch statement
takes the appropriate transition to a new current state; if LA_State is LA_SMStart, the transition is to
the SM's initial state. The second switch statement then executes the actions for the new current
state.
main loop that calls tick function: main() �rst initializes outputs; good practice for any embedded
program, whether implementing an SM or not, is to start the main function by initializing all outputs.
main() then sets the current state to a value of LA_SMStart. main() then enters the normal in�nite
"while (1)" loop, which just repeatedly calls the function TickFct_Latch() to repeatedly tick the Latch
SM.
Run the above code in RIMS. Press "Break" and then repeatedly press "Step" (setting A0
accordingly), observing how the code executes each tick of the state machine.
16 of 46 11/5/2021, 1:39 PM
Firefox [Link]
A0 0
A1 0
A2 0
A3 0
©zyBooks 11/05/21 13:38 231883
A4 0 Lawrence Nderu
Ak78Fta73x
A5 0
A6 0
A7 0
A = 0
1 #include "RIMS.h"
2 int main() {
3 while(1) {
4 B0 = A0 && A1;
5 }
6 return 0;
7 }
17 of 46 11/5/2021, 1:39 PM
Firefox [Link]
B0 0
B1 0
B2 0
B3 0
©zyBooks 11/05/21 13:38 231883
B4 0 Lawrence Nderu
Ak78Fta73x
B5 0
B6 0
B7 0
B = 0
The transition switch statement's default case should never actually execute, but good practice is
to always include a default case for a switch statement, in case something bad happens. For a
state machine, the default case should be included for safety if the state variable ever somehow
gets corrupted. The default case commonly has a transition to the initial state, causing the SM to
start over rather than getting stuck.
Capturing behavior as an SM and then converting to C using the above method typically results in
more code than capturing behavior directly in C. However, more code does not mean worse code.
The C code generated from an SM may be more likely to be correct, may be more easily extensible
and maintainable, and has other major bene�ts that will be seen later.
18 of 46 11/5/2021, 1:39 PM
Firefox [Link]
#include "RIMS.h"
void TickFct_Carousel()
{
switch(CR_State) { // Transitions
case CR_SMStart: // Initial transition
CR_State = CR_Init;
break;
case CR_Init:
CR_State = CR_WaitRise;
break;
case CR_WaitRise:
if (A1) {
CR_State = CR_Init;
}
else if (!A1 && !A0) {
CR_State = CR_WaitRise;
}
else if (!A1 && A0) {
CR_State = CR_Increment;
}
break;
case CR_Increment:
CR_State = CR_WaitFall;
break;
case CR_WaitFall:
if (!A0) {
CR_State = CR_WaitRise;
}
else if (A0) {
CR_State = CR_WaitFall;
} ©zyBooks 11/05/21 13:38 231883
break; Lawrence Nderu
Ak78Fta73x
default:
CR_State = CR_SMStart;
break;
} // Transitions
19 of 46 11/5/2021, 1:39 PM
Firefox [Link]
} // State actions
}
void main() {
B = 0x00; // Initialize outputs
CR_State = CR_SMStart; // Indicates initial call
while(1) {
TickFct_Carousel();
}
}
PARTICIPATION
ACTIVITY 3.4.2: Method for implementing an SM in C.
20 of 46 11/5/2021, 1:39 PM
Firefox [Link]
PARTICIPATION
ACTIVITY 3.4.3: C code for SM.
21 of 46 11/5/2021, 1:39 PM
Firefox [Link]
True
False
6) If a state has no actions, the state
should be omitted from the second
case statement.
True
False ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
7) The break statements could be
removed from the switch statements
without changing behavior, but should
be included for clarity.
True
False
PARTICIPATION
ACTIVITY 3.4.4: SM to C for the light toggle system. Full screen
Strictly following the above method for implementing an SM in C, implement the above
light toggle SM in C.
22 of 46 11/5/2021, 1:39 PM
Firefox [Link]
A0 0
A1 0
A2 0
A3 0
©zyBooks 11/05/21 13:38 231883
A4 0 Lawrence Nderu
Ak78Fta73x
A5 0
A6 0
A7 0
A = 0
1 #include "RIMS.h"
2 int main() {
3 while(1) {
4 B0 = A0 && A1;
5 }
6 return 0;
7 }
23 of 46 11/5/2021, 1:39 PM
Firefox [Link]
B0 0
B1 0
B2 0
B3 0
©zyBooks 11/05/21 13:38 231883
B4 0 Lawrence Nderu
Ak78Fta73x
B5 0
B6 0
B7 0
B = 0
CHALLENGE
ACTIVITY 3.4.1: Complete SM for given behavior. Full screen
90524.463766.qx3zqy7
Start
A0 0
A1 0
A2 0
A3 0
A4 0
A5 0
A6 0
24 of 46 11/5/2021, 1:39 PM
Firefox [Link]
B0 0
B1 0
B2 0
B3 0
B4 0
B5 0
B6 0
B7 0
B = 0
0.00 s
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
25 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Variable sum maintains the sum of all 4-bit numbers seen so far, de�ned as a short to reduce
likelihood of over�ow. Variable cnt counts the number of times A7 has risen. Variable inNum stores
A3..A0, that variable used just to improve code readability. (Note: A reset for the above system,
perhaps using A6, is omitted for brevity).
In RIMS, the input/output variables like A0 or B can be thought of as having been declared as
unsigned char variables.
While the variables could be initialized when declared (e.g., unsigned short sum=0;),
©zyBooks 11/05/21 good
13:38 practice
231883
Lawrence Nderu
is to create a state named Init to carry out initializations of variables and also outputs. In this way,
Ak78Fta73x
not only are all initializations in one place, but the system can be re-initialized merely by
transitioning back to the Init state.
26 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Consider an applause-meter system intended for a game show. A sound sensor measures
sound on a scale of 0 to 7 (0 means quiet, 7 means loud), outputting a three-bit binary
number, connected to RIM's A2-A0. A button connected to A3 can be pressed
©zyBooks by the
11/05/21 game
13:38 231883
Lawrence Nderu
show host to save (when A3 rises) the current sound level, which will then be displayed on
Ak78Fta73x
B. The system's behavior can be captured as an SM with a variable, as shown.
When converting to C, the SM variables can be implemented as global variables above the SM's tick
function.
PARTICIPATION
ACTIVITY 3.5.1: SM variables.
27 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Statements
The statements that can appear in actions can include more than just assignment statements. Any
C statements can appear, such as if-else statements, loops, and function calls. However, for this
material's purposes, good practice is to ensure that actions don't wait on an external input value,
such as while (!A0) {};. Waiting behavior should be captured as states and transitions so
that all time-ordered behavior is visible at the transition level. Also, a state with actions that wait
could cause the SM to violate the basic assumption that SM ticks occur faster than events so that
no events are missed.
The following example changes RIMS' output LED pattern from 00000001 to 00000010 to
00000100, etc., each time A0 rises. When 10000000 is reached, the pattern wraps back to
00000001.
28 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Extend the above applause meter SM so that if A4 becomes 1 while in the WaitRise state,
the system outputs the maximum value seen so far. When A4 is returned to 0, the system
outputs the most-recently-saved value as before. Use a variable for the most-recently-
©zyBooks 11/05/21 13:38 231883
saved value and another for the max value, and an if-else statement. Lawrence Nderu
Ak78Fta73x
Create an SM that waits for A0 to rise, upon which the SM counts the number of 1s on
A1..A7 and outputs the count on B. That count stays on B until A0 rises again. Use the
GetBit function from an earlier section, and a for loop, as the actions of a state that counts
the 1s on A1..A7.
PARTICIPATION
ACTIVITY 3.5.2: SM statements.
False
29 of 46 11/5/2021, 1:39 PM
Firefox [Link]
True
Conditions
• Exactly one—no more, no fewer—of a state's exiting transitions should have a condition that
©zyBooks 11/05/21 13:38 231883
evaluates to true at a given time. In this way, the next state for each tick is precisely
Lawrence Nderu and
clearly de�ned. Ak78Fta73x
A common error is to create transitions leaving a state whose conditions are not mutually
exclusive, like one transition with condition A0 and another with condition A1, both of which could
be true simultaneously. Another common error is to create transitions such that sometimes no
transition has a true condition, like one transition with condition A0 and another with condition !A0
&& A1, which fail to cover the situation !A0 && !A1. Technically, neither situation is actually an error.
In the �rst case, the SM becomes non-deterministic, because the model does not de�ne which of
two true transitions will be taken. In the second case, the SM will implicitly take a transition back to
the same state, but explicit transitions are preferable for clarity.
For convenience, the SM's in this material use a condition named other to indicate the transition
that should be taken if none of the state's normal transition conditions are true. For example, the
following system opens a swinging door when a person approaches the front (A0 is 1) and nobody
is directly behind the door (A1 is 0). Note that the transition that remains in the WaitPerson state is
simply "other" rather than being !(A0 && !A1), which clutters the SM and detracts the readers
attention away from the more important transition A0 && !A1 from WaitPerson to Open. Once
opening the door, the system keeps the door open as long as the person is detected near the door
as indicated by A0 || A1, again using "other" for the opposite condition.
When implementing an SM in C, the "other" transition may be implemented as a last else branch
(with no expression) in the state's transitions if-else code.
PARTICIPATION
ACTIVITY 3.5.3: SM conditions.
30 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Transition conditions are expressions, not statements, so should not end with a
semicolon. For each, write the most direct answer.
Ex: For "A1 and A0 are true", write
A1 && A0
without parentheses, semicolons, and without == .
©zyBooks 11/05/21 13:38 231883
1) Write the condition: either A1 or Lawrence Nderu
Ak78Fta73x
A0 is true.
31 of 46 11/5/2021, 1:39 PM
Firefox [Link]
32 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Figure 3.6.1: Mealy SMs can reduce states and more intuitively
represent some behavior.
The following implements an applause meter system (from an earlier section), using a Mealy
action on the transition that detects a rising A3, thus preventing having an additional state.
33 of 46 11/5/2021, 1:39 PM
Firefox [Link]
When translating to C, a transition's actions appear in the transition switch statement, in the
appropriate if-else branch.
Capture a toggle light system using an SM. A button connects to A0. B0 connects to a
light, initially off. Pressing the button (rising A0) changes the light from off to on. Another
press changes the light from on to off. And so on. First try capturing with a Moore SM.
Then try with an SM having Mealy actions, and notice that fewer states are required.
PARTICIPATION
ACTIVITY 3.6.1: Mealy actions.
34 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Step 1: A �rst step is to list the system's basic states, adding actions if known:
Step 2: A second step of the process is to add transitions to each state to achieve the desired
behavior. Clearly the �rst state to enter after initialization is the Unarmed state, so we add a
35 of 46 11/5/2021, 1:39 PM
Firefox [Link]
conditionless (true) transition from Init to Unarmed. We add a transition to stay in Unarmed while
A0 is 0, and another transition to go to Armed when A0 is 1. We add a transition to stay in Armed
while the door is closed (A1 is 0), and another transition to go to Alarm if the door is opened. Finally,
we add a transition to stay in Alarm while the system is still armed (A0 is 1), and when disarmed
(A0 is 0) we could go to either Init or Unarmed; Unarmed seems reasonable so we add a transition
to there.
©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Figure 3.7.2: Emergency exit door system: Ak78Fta73x
Adding transitions (�rst attempt).
Step 3: The third step is to mentally check the behavior of the captured SM. This step may result in
adding more transitions, or even more states. Minimally, for each state, we should check that
exactly one transition's condition will be true, modifying the conditions or adding transitions if
necessary. Even more importantly, we should also determine whether the SM's behavior is as
desired, by mentally executing the SM and thinking what input sequences might occur. In doing so
for the above SM, we consider the possibility that a user might want to disarm the system while
armed, and notice that is not possible in the SM. Thus, we may add transitions, such as !A0 from
Armed to Unarmed (requiring that the other two transitions be modi�ed, otherwise the state's
outgoing conditions would not be mutually exclusive).
When mentally executing, one might focus on a particular state, and then for each input not
explicitly on the transitions one might ask: "Does that input's value matter for this state's behavior?"
For example, the above system has two inputs, A0 and A1. For state Unarmed, does input A1's
value matter? It does not for that state. For state Armed, does input A0 matter? It does, so we need
to add transitions. For state Alarm, does A1's value matter? It does not; once the door has been
opened, the alarm continues sounding whether the door stays open or closed.
Capturing time-ordered behavior is hard. Good designers will spend much time mentally executing
©zyBooks 11/05/21 13:38 231883
their SM and thinking of possible input sequences that need to be addressed. Re�ning
Lawrence an SM many
Nderu
times is commonplace. Ak78Fta73x
PARTICIPATION
ACTIVITY 3.7.1: Capturing behavior as an SM.
36 of 46 11/5/2021, 1:39 PM
Firefox [Link]
A doorway is for exit only. Sensors A0, A1, A2 detect a person passing through. A proper
exit causes A2A1A0 to be 000, then 100, then 010, then 001, then 000. Any other sequence
causes a buzzer to sound (B0=1) until 000.
Design an SM using RIBS that captures the doorway behavior, and simulate using RIMS.
37 of 46 11/5/2021, 1:39 PM
Firefox [Link]
An automatic door at a store has a sensor in front (A0) and behind (A1). The door opens
(B0=1) when a person approaches from the front, and stays open as long as a person is
detected in front or behind. If the door is closed and a person approaches from the13:38
©zyBooks 11/05/21 behind,
231883
Lawrence Nderu
the door does not open. If the door is closed and a person approaches from the front but a
Ak78Fta73x
person is also detected behind, the door does not open, to prevent hitting the person that
is behind.
Design an SM using RIBS that captures the automatic door behavior, and simulate using
RIMS.
A dimmer light system has increase (A0) and decrease (A1) buttons. B sets the light
intensity, 0 is off, 255 is the maximum intensity, and:
Design an SM using RIBS that captures the dimmer light behavior, and simulate using
RIMS.
An amusement park ride has sensor mats on the left (A0) and right (A1) of a ride car. A
ride operator starts the ride by pressing a button (A7); each unique press toggles the ride
from stopped to started (B0=1) and vice-versa. If anyone leaves the ride car and steps on a
sensor mat, the ride stops and an alarm sounds (B1=1). The alarm ©zyBooks 11/05/21 13:38
stops sounding when231883
Lawrence Nderu
the person gets off the sensor mat. The only way for the ride to restart is for the operator
Ak78Fta73x
to press the button again. The ride never starts if someone is on the sensor mat.
Design an SM using RIBS that captures the amusement ride behavior, and simulate using
RIMS.
38 of 46 11/5/2021, 1:39 PM
Firefox [Link]
3.8 Testing an SM
Testing time-ordered behavior requires generating a good set of input scenarios, where a scenario
is a sequence of inputs that should cause a particular sequence of state. Such testing is in contrast
to merely generating a good set of input combinations for a system lacking internal states, each
©zyBooks 11/05/21 13:38 231883
input combination known as a test vector. Lawrence Nderu
Ak78Fta73x
A testing process for time-ordered behavior may consist of:
1. Decide what scenarios to test, including normal cases as well as border cases.
2. Devise a sequence of test vectors to test each scenario.
39 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Table 3.8.1: A few test scenarios for the emergency door system.
Each row indicates the assumed starting state (same as previous row's �nal state), describes the
system's input scenario and the expected system behavior, lists the expected �nal state and output,
and �nally lists the test vectors that will generate the scenario. For example, the scenario 2 starts in
state Unarmed, then arms to the system, which should cause a change to state Armed and output
B0=1. Arming the system is achieved by A1A0 being 01, which is the test vector. Scenario 5 carries
out a longer sequence, requiring several test vectors.
Scenario 6 arms and then unarms the system. Testing with the given test vectors will yield the
correct �nal output of 0, but the �nal state will be Armed rather than Unarmed. Thus, testing
uncovers a problem, namely that Armed is missing a transition with condition
©zyBooks !A0 going
11/05/21 back
13:38 to
231883
Unarmed . Lawrence Nderu
Ak78Fta73x
As with testing systems with combinational behavior, testing a system with time-ordered behavior
should involve normal cases and border cases. Border cases speci�cally test unusual situations,
like all inputs changing from 0s to 1s simultaneously, or an input changing back and forth from 0 to
1 repeatedly.
When testing an SM, test vectors should ensure that each state and each transition is executed at
least once. Furthermore, if a state's action code has branches, then test vectors should also ensure
40 of 46 11/5/2021, 1:39 PM
Firefox [Link]
that every statement is executed at least once. Even more ideally, every path through the SM would
also be tested, but achieving complete path coverage is hard because huge numbers of paths may
exist.
In testing terminology, black-box testing refers to checking for correct outputs only, as in checking
the value of B0 in the above example. In white-box testing, internal values of the system are also
checked, such as the current state. One can see the advantage of white-box testing in the above
example, where the output was correct but the state was not. Further©zyBooks 11/05/21
black-box 13:38
testing 231883
might
Lawrence Nderu
discover the above problem too, but white-box is more likely to detect problems. Of course, white-
Ak78Fta73x
box testing is harder because a mechanism is necessary to access internal values.
Designing good test vectors can take much effort, both to formulate the scenarios, and to properly
create the test vectors. Testing is as important as capturing the SM. Good practice is to plan to
spend nearly as much time for testing a system as for designing a system. New programmers
rarely follow this practice, believing testing is just a "sanity check" step at the end of design.
PARTICIPATION
ACTIVITY 3.8.1: Creating test vectors for the emergency door system.
Match the test vectors with the desired test scenario for the above emergency door
system. Assume each set of test vectors is applied immediately after starting the system,
so the starting state is always Unarmed. Each vector is for A1A0, so 01 means A1 is 0 and
A0 is 1.
Reset
41 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Even in the absence of a tool like RIBS, programmers can (and should) capture time-ordered
behavior as an SM, typically drawing the SM on paper �rst, and then converting to C. All
modi�cations are done by changing the SM (capture), and then updating the C code (convert). An
experienced programmer can work with SMs in C without always having to see a state diagram,
and can see or draw a state diagram from C code.
The concept of thinking of program behavior as state machines, even though the actual code is in C,
is the most important concept in this book. ©zyBooks 11/05/21 13:38 231883
Lawrence Nderu
Ak78Fta73x
42 of 46 11/5/2021, 1:39 PM
Firefox [Link]
43 of 46 11/5/2021, 1:39 PM
Firefox [Link]
void TickFct_Example() {
switch(EX_State) { // Transitions
case EX_SMStart:
EX_State = EX_S0;
break;
case EX_S0:
if (1) {
EX_State = EX_S1;
}
break;
case EX_S2:
if (A3) {
EX_State = EX_S2;
}
else if (!A3) {
EX_State = EX_S1;
}
break;
case EX_S1:
if (!A3) {
EX_State = EX_S1;
}
else if (A3) {
EX_State = EX_S2;
x = A & 0x07;
B = x;
}
break;
default:
EX_State = EX_SMStart;
break;
}
void main() {
EX_State = EX_SMStart; // Initial state
B = 0; // Init outputs
while(1) {
TickFct_Example();
}
44 of 46 11/5/2021, 1:39 PM
Firefox [Link]
Note that the RIBS tool does not run a C compiler on the C code in actions/conditions/declarations,
but rather just generates a new C program that contains that code. Any syntax errors will only be
determined upon running a C compiler on that program, requiring a RIBS user to correlate the error
©zyBooks 11/05/21 13:38 231883
message to the SM code. Lawrence Nderu
Ak78Fta73x
For any working example in RIBS having an action in a state, introduce a C syntax error by
removing the semicolon after an action. Save, generate C, then press "RIMS Simulation".
Note the error message that is generated, and strive to correlate that with the RIBS SM. Fix
the error and this time introduce an error by adding a semicolon after a transition
condition, and try running again.
The SM model in this chapter is a basic state machine model speci�cally intended to aid the
capture of time-ordered behavior and for conversion to C. Many other state machine models exist,
such as UML state machines. Some state machine models have a more formal mathematical
basis, but translation to C is more cumbersome and the code harder to maintain. Another common
category of computation model involves data�ow models, which are well suited to digital signal
processing applications but are beyond our scope.
PARTICIPATION
ACTIVITY 3.9.1: Capture/convert process.
45 of 46 11/5/2021, 1:39 PM
Firefox [Link]
False
Exploring further:
46 of 46 11/5/2021, 1:39 PM
Within a state machine, each state has defined transitions, which are routes it can follow under certain conditions. These conditions determine if a transition should be taken. When a condition for a particular transition is true, the state machine moves to the target state, executing the target state's actions. This mechanism enforces a system behavior that responds predictably to specific inputs .
In a state machine, a 'state' represents a specific configuration or mode the machine is in, while 'action' refers to operations executed upon entering a state. These concepts collectively drive the machine's execution, as the machine transitions between states and performs actions based on input conditions, thereby executing the defined behavior consistently .
Loop iteration in a C implementation of a state machine is managed using an infinite loop that repeatedly calls the state machine's tick function. This loop ensures continuous execution and state evaluation, allowing the machine to process inputs and transit through states accordingly .
Capturing time-ordered behavior into C's sequential instruction computation model is challenging because it results in a system that may become a spaghetti-like mess, making its behavior extremely hard to understand .
A state machine enhances modeling of time-ordered behaviors by structuring the system into distinct states and transitions based on conditions, allowing for clear depiction of time-ordered activities. Unlike sequential computation models, state machines can directly capture the flow of events and actions as they occur over time .
Including a default transition case in a state machine's C implementation is a safety measure to handle unexpected scenarios where the state variable might become corrupted. This ensures that the machine defaults back to a starting state, preventing it from halting or behaving unpredictably .
Exporting and importing state machines is beneficial in their development and use because it facilitates saving and restoring the machine's configurations. This capability allows programmers to modify, share, and debug designs more efficiently, enhancing collaborative efforts and reiterative development processes .
State machines handle variables by declaring them at the scope level, accessible to all actions and conditions. Operations involving input updates are typically managed through computational states, where values are calculated based on specific conditions or transitions. This design supports complex operations, such as computing averages of inputs, within a predictable framework .
Defining a state machine in C provides advantages such as improved readability, correctness, and maintainability over directly coding the behavior. This structured approach allows for easier understanding and extension of the code, as it follows a predictable state transition model rather than scattered conditional statements .
Mutually exclusive transition conditions are crucial because they ensure determinism in a state machine. If multiple transitions from a state can be true simultaneously, it leads to ambiguity on which transition to take, making the machine's behavior non-deterministic. By enforcing mutual exclusivity, each condition evaluates independently, ensuring only one valid transition path at any tick of the machine .