SlideShare a Scribd company logo
Handling Asynchronous Events in MCUs
The Finite-State Machine Design Pattern
Corrado Santoro
ARSLAB - Autonomous and Robotic Systems Laboratory
Dipartimento di Matematica e Informatica - Universit`a di Catania, Italy
santoro@dmi.unict.it
L.A.P. 1 Course
Corrado Santoro The FSM Design Pattern
The “toggle” Example
We want to toggle LED in RB0 each time the button in RA3 is
pressed.
Electrical considerations:
the logic of the LED is inverted
LATBbits.LATB0 = 1; implies LED off;
LATBbits.LATB0 = 0; implies LED on;
the logic of the pushbutton is also inverted
Button pressed implies PORTAbits.RA3 == 0;
Button NOT pressed implies PORTAbits.RA3 == 1;
Corrado Santoro The FSM Design Pattern
The “toggle” example
The listing
✞
main()
{
TRISAbits.TRISA3 = 1; // RA3 as input
TRISBbits.TRISB0 = 0; // RB0 as output
LATBbits.LATB0 = 1; // turn led off initially
for (;;) { // loop forever
if (PORTAbits.RA3 == 0)
LATBbits.LATB0 = !LATBbits.LATB0;
}
}
✡✝ ✆
This code won’t work: the loop is executed a very high speed,
so the “if” is true many times and the LED toggles continuously!
Corrado Santoro The FSM Design Pattern
Let’s analyse the signal...
Pressing/releasing a button implies the following timing:
We have to identify the PRESSED event, i.e.a transition from
high-to-low.
Solution 1
Identify that the button is pressed (check that RA3 is “0”)
Do the proper actions (i.e. toggle the LED)
wait for button release before continuing (ensure that
RA3 is “1”)
Corrado Santoro The FSM Design Pattern
Let’s analyse the signal...
Solution 1
Identify that the button is pressed (check that RA3 is “0”)
Do the proper actions (i.e. toggle the LED)
wait for button release before continuing (ensure that RA3 is “1”)
✞
main()
{
TRISAbits.TRISA3 = 1; // RA3 as input
TRISBbits.TRISB0 = 0; // RB0 as output
LATBbits.LATB0 = 1; // turn led off initially
for (;;) { // loop forever
if (PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
while (PORTAbits.RA3 == 0) {} // busy-wait for release
}
}
}
✡✝ ✆Corrado Santoro The FSM Design Pattern
The “toggle” Example v2
We want to:
Toggle LED in RB0 each time the button in RA3 is pressed.
Toggle LED in RB1 each time the button in RA2 is pressed.
The solution is quite simple now: let’s duplicate the code!
Corrado Santoro The FSM Design Pattern
The “toggle” Example v2
✞
main()
{
TRISAbits.TRISA3 = 1; // RA3 as input
TRISAbits.TRISA2 = 1; // RA2 as input
TRISBbits.TRISB0 = 0; // RB0 as output
TRISBbits.TRISB1 = 0; // RB1 as output
LATBbits.LATB0 = 1; // turn led off initially
LATBbits.LATB1 = 1; // turn led off initially
for (;;) { // loop forever
if (PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
while (PORTAbits.RA3 == 0) {} // busy-wait for release
}
else if (PORTAbits.RA2 == 0) {
LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led
while (PORTAbits.RA2 == 0) {} // busy-wait for release
}
}
}
✡✝ ✆Corrado Santoro The FSM Design Pattern
The “toggle” Example v3
We want to:
Toggle LED in RB0 each time the button in RA3 is pressed.
Toggle LED in RB1 each time the button in RA2 is pressed.
...meanwhile, we want to make LED in RB2 flash at a
certain frequency!!
To do this, we should employ a hardware or software timer, but
it won’t work since we have busy-waits!!!
Indeed, during busy-waits, the program cannot do anything
else: I could leave my finger on the button for a very long
time!!!! :-D
Corrado Santoro The FSM Design Pattern
The non-working “toggle” Example v3
✞
main()
{
long count = 0; // 32 bit is better!
// ... set-up ports by TRIS registers
for (;;) { // loop forever
if (PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
while (PORTAbits.RA3 == 0) {} // busy-wait for release
}
else if (PORTAbits.RA2 == 0) {
LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led
while (PORTAbits.RA2 == 0) {} // busy-wait for release
}
++count;
if (count == MAX) {
LATBbits.LATB2 = !LATBbits.LATB2; // toggle the led
count = 0;
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
No Busy-Waits!!
In the previous solution the variable count won’t be
incremented during busy-waits, so the flashing frequency is not
guaranteed!
Solution 2: Let’s encode a STATE
Use a variable to represent the button state you wish to
identify, e.g. CHECK FOR PRESS,
CHECK FOR RELEASE
Check the button’s state according to the state variable
Update the state variable
Corrado Santoro The FSM Design Pattern
No Busy-Waits
✞
#define CHECK_FOR_PRESS ...
#define CHECK_FOR_RELEASE ...
main()
{
int state = CHECK_FOR_PRESS;
// ... set-up ports by TRIS registers
for (;;) { // loop forever
...
if (state == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) {
// OK!! We have got button press
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
// now we have to check only released
state = CHECK_FOR_RELEASE;
}
else if (state == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) {
// OK!! We have got button release
// let us update the state
state = CHECK_FOR_PRESS;
}
...
}
}
✡✝ ✆Corrado Santoro The FSM Design Pattern
No Busy-Waits with two buttons
✞
#define CHECK_FOR_PRESS ...
#define CHECK_FOR_RELEASE ...
main()
{
int state1 = CHECK_FOR_PRESS, state2 = CHECK_FOR_PRESS;
// ... set-up ports by TRIS registers
for (;;) { // loop forever
...
if (state1 == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
state1 = CHECK_FOR_RELEASE;
}
else if (state1 == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) {
state1 = CHECK_FOR_PRESS;
}
if (state2 == CHECK_FOR_PRESS && PORTAbits.RA2 == 0) {
LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led
state2 = CHECK_FOR_RELEASE;
}
else if (state2 == CHECK_FOR_RELEASE && PORTAbits.RA2 == 1) {
state2 = CHECK_FOR_PRESS;
}
...
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
No Busy-Waits with two buttons and flash
✞
#define CHECK_FOR_PRESS ...
#define CHECK_FOR_RELEASE ...
main()
{
int state1 = CHECK_FOR_PRESS, state2 = CHECK_FOR_PRESS;
long count = 0; // 32 bit is better!
// ... set-up ports by TRIS registers
for (;;) { // loop forever
if (state1 == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led
state1 = CHECK_FOR_RELEASE;
}
else if (state1 == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) {
state1 = CHECK_FOR_PRESS;
}
if (state2 == CHECK_FOR_PRESS && PORTAbits.RA2 == 0) {
LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led
state2 = CHECK_FOR_RELEASE;
}
else if (state2 == CHECK_FOR_RELEASE && PORTAbits.RA2 == 1) {
state2 = CHECK_FOR_PRESS;
}
++count;
if (count == MAX) {
LATBbits.LATB2 = !LATBbits.LATB2; // toggle the led
count = 0;
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
The Finite-State Machine Abstraction
Systems which behave by responding to events which cause actions
are usually programmed using the finite-state machine (FSM)
abstraction/design pattern.
A finite-state machine can be formulated as
A set of states S;
A set of events E;
A set of action A;
A function f(s, e) → (a, s′
) which, given the current state s ∈ S
and the event occurred e ∈ E, gives the action a ∈ A to be
performed and the new state s′
∈ S.
A FSM is usually represented graphically by means of a directed
graph in which:
Vertices are states
Edges are state transitions
Corrado Santoro The FSM Design Pattern
The FSM of our “keyboard”
Corrado Santoro The FSM Design Pattern
The FSM in action
✞
#define IDLE ...
#define KEY_A ...
#define KEY_B ...
#define KEY_C ...
main()
{
int state = IDLE;
// ... set-ups
for (;;) { // loop forever
switch (state) {
case IDLE:
// check events related to IDLE state and change state
break;
case KEY_A:
// check events related to KEY_A state and change state
break;
case KEY_B:
// check events related to KEY_B state and change state
break;
case KEY_C:
// check events related to KEY_C state and change state
break;
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
The FSM in action (1)
✞
main()
{
int state = IDLE;
// ... set-ups
for (;;) { // loop forever
switch (state) {
case IDLE:
if (PORTAbits.RA3 == 0) {
LATBbits.LATB0 = !LATBbits.LATB0;
state = KEY_A;
}
else if (PORTAbits.RA2 == 0) {
LATBbits.LATB1 = !LATBbits.LATB1;
state = KEY_B;
}
else if (PORTAbits.RC2 == 0) {
// ....
state = KEY_C;
}
break;
...
}
}
}
✝ ✆Corrado Santoro The FSM Design Pattern
The FSM in action (2)
✞
main()
{
int state = IDLE;
// ... set-ups
for (;;) { // loop forever
switch (state) {
...
case KEY_A:
if (PORTAbits.RA3 == 1) {
state = IDLE;
}
break;
case KEY_B:
if (PORTAbits.RA2 == 1) {
state = IDLE;
}
break;
...
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
The FSM in action (3)
✞
main()
{
int state = IDLE;
// ... set-ups
for (;;) { // loop forever
switch (state) {
...
case KEY_C:
if (PORTAbits.RC2 == 1) {
state = IDLE;
}
break;
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Exercise!!
Toggle LED in RB0 each time the button in RA3 is pressed.
Toggle LED in RB1 each time the button in RA2 is pressed.
Cycle LEDs from RB2 to RB5 each time button RC2 is
pressed.
Turn off all leds after about 4 seconds of inactivity.
Corrado Santoro The FSM Design Pattern
Execise, a top-down approach
✞
main()
{
init_ports();
init_soft_timer();
for (;;) {
switch(get_key_event()) {
case EV_KEY_A: toggle_led(0); clear_timer(); break;
case EV_KEY_B: toggle_led(1); clear_timer(); break;
case EV_KEY_C: cycle_leds(); clear_timer(); break;
}
if (timer_elapsed()) {
all_leds_off();
clear_timer();
}
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, ports and leds
✞
void init_ports(void)
{
TRISAbits.TRISA3 = 1;
TRISAbits.TRISA2 = 1;
TRISCbits.TRISC2 = 1;
TRISB = 0xc0; // B0-->B5 = outputs, B6, B7 = inputs
LATB = 0xff; // all leds off
}
void toggle_led(int led)
{
if (led == 0) LATBbits.LATB0 = !LATBbits.LATB0;
else if (led == 1) LATBbits.LATB1 = !LATBbits.LATB1;
}
void all_leds_off(void)
{
LATB = 0xff;
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, ports and leds
✞
int cycle = 0;
void cycle_leds(void)
{
if (cycle == 0) {
LATBbits.LATB2 = 0;
LATBbits.LATB3 = 1;
LATBbits.LATB4 = 1;
LATBbits.LATB5 = 1;
cycle = 1;
}
else if (cycle == 1) {
LATBbits.LATB2 = 1;
LATBbits.LATB3 = 0;
LATBbits.LATB4 = 1;
LATBbits.LATB5 = 1;
cycle = 2;
}
else if (cycle == 2) {
LATBbits.LATB2 = 1;
LATBbits.LATB3 = 1;
LATBbits.LATB4 = 0;
LATBbits.LATB5 = 1;
cycle = 3;
}
else if (cycle == 3) {
LATBbits.LATB2 = 1;
LATBbits.LATB3 = 1;
LATBbits.LATB4 = 1;
LATBbits.LATB5 = 0;
cycle = 0;
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, ports and leds
✞
int cycle = 0;
void cycle_leds(void)
{
LATB = (LATB & 0xc3) | (˜(0x4 << cycle) & 0x3c);
cycle = (cycle + 1) % 4;
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, key events
✞
// events
#define EV_NONE ....
#define EV_KEY_A ....
#define EV_KEY_B ....
#define EV_KEY_C ....
// states
#define IDLE ...
#define KEY_A ...
#define KEY_B ...
#define KEY_C ...
int key_state = IDLE;
int get_key_event(void)
{
switch (key_state) {
case KEY_A:
...
break;
....
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, key events
✞
int get_key_event(void)
{
switch (key_state) {
case IDLE:
if (PORTAbits.RA3 == 0) {
key_state = KEY_A;
return EV_KEY_A;
}
else if (PORTAbits.RA2 == 0) {
key_state = KEY_B;
return EV_KEY_B;
}
else if (PORTAbits.RC2 == 0) {
key_state = KEY_C;
return EV_KEY_C;
}
else
return EV_NONE;
break;
...
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, key events
✞
int get_key_event(void)
{
switch (key_state) {
....
case KEY_A:
if (PORTAbits.RA3 == 1) {
key_state = IDLE;
}
return EV_NONE;
break;
case KEY_B:
if (PORTAbits.RA2 == 1) {
key_state = IDLE;
}
return EV_NONE;
break;
case KEY_C:
if (PORTAbits.RC2 == 1) {
key_state = IDLE;
}
return EV_NONE;
break;
}
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Execise, soft timer
✞
long soft_timer = 0;
void init_soft_timer(void)
{
soft_timer = 0;
}
void clear_timer(void)
{
soft_timer = 0;
}
int timer_elapsed(void)
{
++soft_timer;
if (soft_timer > MAX_TIMER)
return 1;
else
return 0;
}
✡✝ ✆
Corrado Santoro The FSM Design Pattern
Handling Asynchronous Events in MCUs
The Finite-State Machine Design Pattern
Corrado Santoro
ARSLAB - Autonomous and Robotic Systems Laboratory
Dipartimento di Matematica e Informatica - Universit`a di Catania, Italy
santoro@dmi.unict.it
L.A.P. 1 Course
Corrado Santoro The FSM Design Pattern

More Related Content

PDF
UART MCU
PDF
Handling Interrupts in Microchip MCUs
PDF
Exercises with timers and UART
PDF
Using Ready-for-PIC and SDR Libraries
PDF
Using Timer1 and CCP
PDF
Using Timers in PIC18F Microcontrollers
PDF
Using Timer2 in Microchip MCUs
UART MCU
Handling Interrupts in Microchip MCUs
Exercises with timers and UART
Using Ready-for-PIC and SDR Libraries
Using Timer1 and CCP
Using Timers in PIC18F Microcontrollers
Using Timer2 in Microchip MCUs

What's hot (20)

PDF
Programming the Digital I/O Interface of a PIC microcontroller
PPTX
Interfacing with Atmega 16
PPTX
Timer counter in arm7(lpc2148)
PPTX
Interrupts at AVR
PDF
Lecture7
PDF
Microcontroller part 2
DOCX
Uart
PDF
PDF
Microcontroller Instruction Set atmel
PPT
PIC timer programming
PDF
Interrupt
PDF
Lecture 2 timers, pwm, state machine IN PIC
PDF
Pt 51 kit - Peripheral self-test
PPT
I o ports and timers of 8051
PDF
Microcontroller part 3
PDF
8051-mazidi-solution
PPT
PDF
89c5131datasheet
PPT
Uart VHDL RTL design tutorial
Programming the Digital I/O Interface of a PIC microcontroller
Interfacing with Atmega 16
Timer counter in arm7(lpc2148)
Interrupts at AVR
Lecture7
Microcontroller part 2
Uart
Microcontroller Instruction Set atmel
PIC timer programming
Interrupt
Lecture 2 timers, pwm, state machine IN PIC
Pt 51 kit - Peripheral self-test
I o ports and timers of 8051
Microcontroller part 3
8051-mazidi-solution
89c5131datasheet
Uart VHDL RTL design tutorial
Ad

Viewers also liked (15)

PDF
Integrating Cloud Services in Behaviour Programming for Autonomous Robots
PDF
Presentation @ WOA 2015
PDF
Reactive Autonomous System Programming using the PROFETA tool
PDF
Pillole di C++
PDF
Pulse Width Modulation Signal Generation with MCUs
PDF
Introduction to microcontrollers
PDF
Introduction to Erlang
PDF
Introduction to shell scripting
PDF
Presentation @ Miniscuola WOA 2015
PDF
Analog to digital converter
PDF
The I2C Interface
PPTX
Quadcopter
PDF
QUAD COPTERS FULL PPT
PDF
Drone (Quadcopter) full project report by Er. ASHWANI DIXIT
PDF
How does a Quadrotor fly? A journey from physics, mathematics, control system...
Integrating Cloud Services in Behaviour Programming for Autonomous Robots
Presentation @ WOA 2015
Reactive Autonomous System Programming using the PROFETA tool
Pillole di C++
Pulse Width Modulation Signal Generation with MCUs
Introduction to microcontrollers
Introduction to Erlang
Introduction to shell scripting
Presentation @ Miniscuola WOA 2015
Analog to digital converter
The I2C Interface
Quadcopter
QUAD COPTERS FULL PPT
Drone (Quadcopter) full project report by Er. ASHWANI DIXIT
How does a Quadrotor fly? A journey from physics, mathematics, control system...
Ad

Similar to Handling Asynchronous Events in MCUs (20)

PPT
chap8 synchronous sequential circuit design.ppt
PPTX
Sometimes tells me funny stories from his childhood
PPTX
ASIC Design Laboratory Finite State Machines State Diagrams vs. Algorithmic S...
PPTX
bbbbbbbbbbbbbcsdasdabcddksrekkdkfjdslsdfrd
PPT
Introduction state machine
PPTX
Finite State Machines Digital Logic Design .pptx
PPT
lec4-FSM.ppt
PPT
Ver6.ppt
PPT
PDF
Introduction to Finite State Machines in Embedded Systems
PPT
Sequential Logic Design_____________.ppt
PDF
lecture23.pdf
PDF
Synchronous sequential Circuits
PDF
System Modeling and Hardware Software Co-Design
PPTX
FSM and ASM
PPT
19-MooreMealy.ppt
PDF
CArcMOOC 03.03 - Sequential circuits
PPT
Finite State Machine by M. Arokiasamy
DOCX
UNIT-IV .FINITE STATE MACHINES
chap8 synchronous sequential circuit design.ppt
Sometimes tells me funny stories from his childhood
ASIC Design Laboratory Finite State Machines State Diagrams vs. Algorithmic S...
bbbbbbbbbbbbbcsdasdabcddksrekkdkfjdslsdfrd
Introduction state machine
Finite State Machines Digital Logic Design .pptx
lec4-FSM.ppt
Ver6.ppt
Introduction to Finite State Machines in Embedded Systems
Sequential Logic Design_____________.ppt
lecture23.pdf
Synchronous sequential Circuits
System Modeling and Hardware Software Co-Design
FSM and ASM
19-MooreMealy.ppt
CArcMOOC 03.03 - Sequential circuits
Finite State Machine by M. Arokiasamy
UNIT-IV .FINITE STATE MACHINES

Recently uploaded (20)

PDF
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PDF
Classroom Observation Tools for Teachers
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PDF
01-Introduction-to-Information-Management.pdf
PPTX
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
PPTX
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PPTX
Cell Types and Its function , kingdom of life
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
GDM (1) (1).pptx small presentation for students
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PDF
VCE English Exam - Section C Student Revision Booklet
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PDF
Complications of Minimal Access Surgery at WLH
PDF
Anesthesia in Laparoscopic Surgery in India
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
Basic Mud Logging Guide for educational purpose
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
O5-L3 Freight Transport Ops (International) V1.pdf
Classroom Observation Tools for Teachers
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
01-Introduction-to-Information-Management.pdf
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
Cell Types and Its function , kingdom of life
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Supply Chain Operations Speaking Notes -ICLT Program
GDM (1) (1).pptx small presentation for students
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
VCE English Exam - Section C Student Revision Booklet
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Complications of Minimal Access Surgery at WLH
Anesthesia in Laparoscopic Surgery in India
O7-L3 Supply Chain Operations - ICLT Program
Basic Mud Logging Guide for educational purpose
2.FourierTransform-ShortQuestionswithAnswers.pdf

Handling Asynchronous Events in MCUs

  • 1. Handling Asynchronous Events in MCUs The Finite-State Machine Design Pattern Corrado Santoro ARSLAB - Autonomous and Robotic Systems Laboratory Dipartimento di Matematica e Informatica - Universit`a di Catania, Italy santoro@dmi.unict.it L.A.P. 1 Course Corrado Santoro The FSM Design Pattern
  • 2. The “toggle” Example We want to toggle LED in RB0 each time the button in RA3 is pressed. Electrical considerations: the logic of the LED is inverted LATBbits.LATB0 = 1; implies LED off; LATBbits.LATB0 = 0; implies LED on; the logic of the pushbutton is also inverted Button pressed implies PORTAbits.RA3 == 0; Button NOT pressed implies PORTAbits.RA3 == 1; Corrado Santoro The FSM Design Pattern
  • 3. The “toggle” example The listing ✞ main() { TRISAbits.TRISA3 = 1; // RA3 as input TRISBbits.TRISB0 = 0; // RB0 as output LATBbits.LATB0 = 1; // turn led off initially for (;;) { // loop forever if (PORTAbits.RA3 == 0) LATBbits.LATB0 = !LATBbits.LATB0; } } ✡✝ ✆ This code won’t work: the loop is executed a very high speed, so the “if” is true many times and the LED toggles continuously! Corrado Santoro The FSM Design Pattern
  • 4. Let’s analyse the signal... Pressing/releasing a button implies the following timing: We have to identify the PRESSED event, i.e.a transition from high-to-low. Solution 1 Identify that the button is pressed (check that RA3 is “0”) Do the proper actions (i.e. toggle the LED) wait for button release before continuing (ensure that RA3 is “1”) Corrado Santoro The FSM Design Pattern
  • 5. Let’s analyse the signal... Solution 1 Identify that the button is pressed (check that RA3 is “0”) Do the proper actions (i.e. toggle the LED) wait for button release before continuing (ensure that RA3 is “1”) ✞ main() { TRISAbits.TRISA3 = 1; // RA3 as input TRISBbits.TRISB0 = 0; // RB0 as output LATBbits.LATB0 = 1; // turn led off initially for (;;) { // loop forever if (PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led while (PORTAbits.RA3 == 0) {} // busy-wait for release } } } ✡✝ ✆Corrado Santoro The FSM Design Pattern
  • 6. The “toggle” Example v2 We want to: Toggle LED in RB0 each time the button in RA3 is pressed. Toggle LED in RB1 each time the button in RA2 is pressed. The solution is quite simple now: let’s duplicate the code! Corrado Santoro The FSM Design Pattern
  • 7. The “toggle” Example v2 ✞ main() { TRISAbits.TRISA3 = 1; // RA3 as input TRISAbits.TRISA2 = 1; // RA2 as input TRISBbits.TRISB0 = 0; // RB0 as output TRISBbits.TRISB1 = 0; // RB1 as output LATBbits.LATB0 = 1; // turn led off initially LATBbits.LATB1 = 1; // turn led off initially for (;;) { // loop forever if (PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led while (PORTAbits.RA3 == 0) {} // busy-wait for release } else if (PORTAbits.RA2 == 0) { LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led while (PORTAbits.RA2 == 0) {} // busy-wait for release } } } ✡✝ ✆Corrado Santoro The FSM Design Pattern
  • 8. The “toggle” Example v3 We want to: Toggle LED in RB0 each time the button in RA3 is pressed. Toggle LED in RB1 each time the button in RA2 is pressed. ...meanwhile, we want to make LED in RB2 flash at a certain frequency!! To do this, we should employ a hardware or software timer, but it won’t work since we have busy-waits!!! Indeed, during busy-waits, the program cannot do anything else: I could leave my finger on the button for a very long time!!!! :-D Corrado Santoro The FSM Design Pattern
  • 9. The non-working “toggle” Example v3 ✞ main() { long count = 0; // 32 bit is better! // ... set-up ports by TRIS registers for (;;) { // loop forever if (PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led while (PORTAbits.RA3 == 0) {} // busy-wait for release } else if (PORTAbits.RA2 == 0) { LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led while (PORTAbits.RA2 == 0) {} // busy-wait for release } ++count; if (count == MAX) { LATBbits.LATB2 = !LATBbits.LATB2; // toggle the led count = 0; } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 10. No Busy-Waits!! In the previous solution the variable count won’t be incremented during busy-waits, so the flashing frequency is not guaranteed! Solution 2: Let’s encode a STATE Use a variable to represent the button state you wish to identify, e.g. CHECK FOR PRESS, CHECK FOR RELEASE Check the button’s state according to the state variable Update the state variable Corrado Santoro The FSM Design Pattern
  • 11. No Busy-Waits ✞ #define CHECK_FOR_PRESS ... #define CHECK_FOR_RELEASE ... main() { int state = CHECK_FOR_PRESS; // ... set-up ports by TRIS registers for (;;) { // loop forever ... if (state == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) { // OK!! We have got button press LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led // now we have to check only released state = CHECK_FOR_RELEASE; } else if (state == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) { // OK!! We have got button release // let us update the state state = CHECK_FOR_PRESS; } ... } } ✡✝ ✆Corrado Santoro The FSM Design Pattern
  • 12. No Busy-Waits with two buttons ✞ #define CHECK_FOR_PRESS ... #define CHECK_FOR_RELEASE ... main() { int state1 = CHECK_FOR_PRESS, state2 = CHECK_FOR_PRESS; // ... set-up ports by TRIS registers for (;;) { // loop forever ... if (state1 == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led state1 = CHECK_FOR_RELEASE; } else if (state1 == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) { state1 = CHECK_FOR_PRESS; } if (state2 == CHECK_FOR_PRESS && PORTAbits.RA2 == 0) { LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led state2 = CHECK_FOR_RELEASE; } else if (state2 == CHECK_FOR_RELEASE && PORTAbits.RA2 == 1) { state2 = CHECK_FOR_PRESS; } ... } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 13. No Busy-Waits with two buttons and flash ✞ #define CHECK_FOR_PRESS ... #define CHECK_FOR_RELEASE ... main() { int state1 = CHECK_FOR_PRESS, state2 = CHECK_FOR_PRESS; long count = 0; // 32 bit is better! // ... set-up ports by TRIS registers for (;;) { // loop forever if (state1 == CHECK_FOR_PRESS && PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; // toggle the led state1 = CHECK_FOR_RELEASE; } else if (state1 == CHECK_FOR_RELEASE && PORTAbits.RA3 == 1) { state1 = CHECK_FOR_PRESS; } if (state2 == CHECK_FOR_PRESS && PORTAbits.RA2 == 0) { LATBbits.LATB1 = !LATBbits.LATB1; // toggle the led state2 = CHECK_FOR_RELEASE; } else if (state2 == CHECK_FOR_RELEASE && PORTAbits.RA2 == 1) { state2 = CHECK_FOR_PRESS; } ++count; if (count == MAX) { LATBbits.LATB2 = !LATBbits.LATB2; // toggle the led count = 0; } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 14. The Finite-State Machine Abstraction Systems which behave by responding to events which cause actions are usually programmed using the finite-state machine (FSM) abstraction/design pattern. A finite-state machine can be formulated as A set of states S; A set of events E; A set of action A; A function f(s, e) → (a, s′ ) which, given the current state s ∈ S and the event occurred e ∈ E, gives the action a ∈ A to be performed and the new state s′ ∈ S. A FSM is usually represented graphically by means of a directed graph in which: Vertices are states Edges are state transitions Corrado Santoro The FSM Design Pattern
  • 15. The FSM of our “keyboard” Corrado Santoro The FSM Design Pattern
  • 16. The FSM in action ✞ #define IDLE ... #define KEY_A ... #define KEY_B ... #define KEY_C ... main() { int state = IDLE; // ... set-ups for (;;) { // loop forever switch (state) { case IDLE: // check events related to IDLE state and change state break; case KEY_A: // check events related to KEY_A state and change state break; case KEY_B: // check events related to KEY_B state and change state break; case KEY_C: // check events related to KEY_C state and change state break; } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 17. The FSM in action (1) ✞ main() { int state = IDLE; // ... set-ups for (;;) { // loop forever switch (state) { case IDLE: if (PORTAbits.RA3 == 0) { LATBbits.LATB0 = !LATBbits.LATB0; state = KEY_A; } else if (PORTAbits.RA2 == 0) { LATBbits.LATB1 = !LATBbits.LATB1; state = KEY_B; } else if (PORTAbits.RC2 == 0) { // .... state = KEY_C; } break; ... } } } ✝ ✆Corrado Santoro The FSM Design Pattern
  • 18. The FSM in action (2) ✞ main() { int state = IDLE; // ... set-ups for (;;) { // loop forever switch (state) { ... case KEY_A: if (PORTAbits.RA3 == 1) { state = IDLE; } break; case KEY_B: if (PORTAbits.RA2 == 1) { state = IDLE; } break; ... } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 19. The FSM in action (3) ✞ main() { int state = IDLE; // ... set-ups for (;;) { // loop forever switch (state) { ... case KEY_C: if (PORTAbits.RC2 == 1) { state = IDLE; } break; } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 20. Exercise!! Toggle LED in RB0 each time the button in RA3 is pressed. Toggle LED in RB1 each time the button in RA2 is pressed. Cycle LEDs from RB2 to RB5 each time button RC2 is pressed. Turn off all leds after about 4 seconds of inactivity. Corrado Santoro The FSM Design Pattern
  • 21. Execise, a top-down approach ✞ main() { init_ports(); init_soft_timer(); for (;;) { switch(get_key_event()) { case EV_KEY_A: toggle_led(0); clear_timer(); break; case EV_KEY_B: toggle_led(1); clear_timer(); break; case EV_KEY_C: cycle_leds(); clear_timer(); break; } if (timer_elapsed()) { all_leds_off(); clear_timer(); } } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 22. Execise, ports and leds ✞ void init_ports(void) { TRISAbits.TRISA3 = 1; TRISAbits.TRISA2 = 1; TRISCbits.TRISC2 = 1; TRISB = 0xc0; // B0-->B5 = outputs, B6, B7 = inputs LATB = 0xff; // all leds off } void toggle_led(int led) { if (led == 0) LATBbits.LATB0 = !LATBbits.LATB0; else if (led == 1) LATBbits.LATB1 = !LATBbits.LATB1; } void all_leds_off(void) { LATB = 0xff; } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 23. Execise, ports and leds ✞ int cycle = 0; void cycle_leds(void) { if (cycle == 0) { LATBbits.LATB2 = 0; LATBbits.LATB3 = 1; LATBbits.LATB4 = 1; LATBbits.LATB5 = 1; cycle = 1; } else if (cycle == 1) { LATBbits.LATB2 = 1; LATBbits.LATB3 = 0; LATBbits.LATB4 = 1; LATBbits.LATB5 = 1; cycle = 2; } else if (cycle == 2) { LATBbits.LATB2 = 1; LATBbits.LATB3 = 1; LATBbits.LATB4 = 0; LATBbits.LATB5 = 1; cycle = 3; } else if (cycle == 3) { LATBbits.LATB2 = 1; LATBbits.LATB3 = 1; LATBbits.LATB4 = 1; LATBbits.LATB5 = 0; cycle = 0; } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 24. Execise, ports and leds ✞ int cycle = 0; void cycle_leds(void) { LATB = (LATB & 0xc3) | (˜(0x4 << cycle) & 0x3c); cycle = (cycle + 1) % 4; } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 25. Execise, key events ✞ // events #define EV_NONE .... #define EV_KEY_A .... #define EV_KEY_B .... #define EV_KEY_C .... // states #define IDLE ... #define KEY_A ... #define KEY_B ... #define KEY_C ... int key_state = IDLE; int get_key_event(void) { switch (key_state) { case KEY_A: ... break; .... } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 26. Execise, key events ✞ int get_key_event(void) { switch (key_state) { case IDLE: if (PORTAbits.RA3 == 0) { key_state = KEY_A; return EV_KEY_A; } else if (PORTAbits.RA2 == 0) { key_state = KEY_B; return EV_KEY_B; } else if (PORTAbits.RC2 == 0) { key_state = KEY_C; return EV_KEY_C; } else return EV_NONE; break; ... } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 27. Execise, key events ✞ int get_key_event(void) { switch (key_state) { .... case KEY_A: if (PORTAbits.RA3 == 1) { key_state = IDLE; } return EV_NONE; break; case KEY_B: if (PORTAbits.RA2 == 1) { key_state = IDLE; } return EV_NONE; break; case KEY_C: if (PORTAbits.RC2 == 1) { key_state = IDLE; } return EV_NONE; break; } } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 28. Execise, soft timer ✞ long soft_timer = 0; void init_soft_timer(void) { soft_timer = 0; } void clear_timer(void) { soft_timer = 0; } int timer_elapsed(void) { ++soft_timer; if (soft_timer > MAX_TIMER) return 1; else return 0; } ✡✝ ✆ Corrado Santoro The FSM Design Pattern
  • 29. Handling Asynchronous Events in MCUs The Finite-State Machine Design Pattern Corrado Santoro ARSLAB - Autonomous and Robotic Systems Laboratory Dipartimento di Matematica e Informatica - Universit`a di Catania, Italy santoro@dmi.unict.it L.A.P. 1 Course Corrado Santoro The FSM Design Pattern