OOSMOS 2.1.3
1. Get Productive with OOSMOS
2. Example
2.1 State Chart That Uses State Threads
2.2 Generated Code
3. Quick Start
3.1 On Windows
3.2 On an Embedded Device

1. Get Productive with OOSMOS

OOSMOS, the Object-Oriented State Machine Operating System, implements state based concurrency for C/C++. Draw a hierarchical state chart using the open source drawing tool UMLet and then use the OOSMOS code generator to generate C code. Perfect for event driven embedded systems.
Get
OOSMOS
from GitHub

2. Example

What follows is a complete example of an OOSMOS object and its hierarchical state machine that reacts to keystroke events. It demonstrates a feature unique to OOSMOS -- State Threads. That is, a simple thread of execution that you get for free when you enter a state. This powerful feature allows you do things that would otherwise require many states.
In the state chart below, find the Flashing state. While the object is in this state, the POLL event is called continuously by OOSMOS and the FlashingThread is serviced. Following the logic of the state chart, when either a 'b', 'r', or 'q' key are pressed, the Flashing state is exited and the thread is no longer active. State Threads can be nested in your hierarchical state charts. Note that the Flashing state is inside the Running state. Thus, both RunningThread and FlashingThread are active at the same time.
This is the code snippet for the FlashingThread function, which continues to print 'Flashing...' as long as it is active (i.e., in the Flashing state.)
1
2
3
4
5
6
7
8
9
10
11
 
static void FlashingThread(oosmos_sState * pState)
{
oosmos_ThreadBegin();
for (;;) {
printf("Flashing...\n");
oosmos_ThreadDelayMS(50);
}
oosmos_ThreadEnd();
}
 
FlashingThread

2.1 State Chart That Uses State Threads

This state chart represents the exact behavior of your object and doubles as its formal behavioral requirements. Too often, projects will use a drawing tool to draw state charts intended to reflect behavior, but it doesn't reflect how the system actually behaves because code is not generated from the state chart like it is with OOSMOS.
State Chart Using Nested State Threads

2.2 Generated Code

Below is the entire .c file for the example object along with the main function that initializes and drives it. You supply the .c file with four code insertion markers into which the OOSMOS code generator injects its code from the state chart. Note: In this example, we gave the generator the debug option.
Click on the '+' signs to expand each snippet and view the generated code.
1
22
23
29
30
31
32
33
54
55
56
57
58
59
60
61
62
63
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
201
202
203
204
205
206
207
208
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
[GPLv2]
 
[#includes...]
 
typedef struct testTag test;
 
//>>>EVENTS
[Code Generated by OOSMOS]
//<<<EVENTS
 
typedef union {
oosmos_sEvent Event;
} uEvents;
 
struct testTag
{
//>>>DECL
[Code Generated by OOSMOS]
//<<<DECL
};
 
static void RunningThread(oosmos_sState * pState)
{
oosmos_ThreadBegin();
for (;;) {
printf("RUNNING...\n");
oosmos_ThreadDelayMS(750);
}
oosmos_ThreadEnd();
}
 
static void FlashingThread(oosmos_sState * pState)
{
oosmos_ThreadBegin();
for (;;) {
printf("Flashing...\n");
oosmos_ThreadDelayMS(50);
}
oosmos_ThreadEnd();
}
 
static void BeepingThread(oosmos_sState * pState)
{
oosmos_ThreadBegin();
for (;;) {
printf("Beeping...\n");
oosmos_ThreadDelayMS(100);
}
oosmos_ThreadEnd();
}
 
//>>>CODE
[Code Generated by OOSMOS]
//<<<CODE
 
static test * testNew(void)
{
oosmos_Allocate(pTest, test, 1, NULL);
 
//>>>INIT
[Code Generated by OOSMOS]
//<<<INIT
 
return pTest;
}
 
extern int main(void)
{
test * pTest = testNew();
 
pin * p_r_Pin = pinNew('r', pinActiveHigh);
btn * p_r_Button = btnNew(p_r_Pin);
btnSubscribePressedEvent(p_r_Button, oosmos_EventQueue(pTest), ev_r_Pressed, NULL);
btnSubscribeReleasedEvent(p_r_Button, oosmos_EventQueue(pTest), ev_r_Released, NULL);
 
pin * p_b_Pin = pinNew('b', pinActiveHigh);
btn * p_b_Button = btnNew(p_b_Pin);
btnSubscribePressedEvent(p_b_Button, oosmos_EventQueue(pTest), ev_b_Pressed, NULL);
btnSubscribeReleasedEvent(p_b_Button, oosmos_EventQueue(pTest), ev_b_Released, NULL);
 
pin * p_q_Pin = pinNew('q', pinActiveHigh);
btn * p_q_Button = btnNew(p_q_Pin);
btnSubscribePressedEvent(p_q_Button, oosmos_EventQueue(pTest), ev_q_Pressed, NULL);
 
for (;;) {
oosmos_RunStateMachines();
oosmos_DelayMS(1);
}
}
NestedStateThreads.c

3. Quick Start

3.1 On Windows

  1. Clone OOSMOS from GitHub.
  2. Open a command line window and then change directory to oosmos\Examples\NestedStateThreads\Windows.
  3. Run bld.py.
    Prerequisites:
    • Python must be installed.
    • A Microsoft C/C++ command line compiler new enough to compile c99. We currently use Visual Studio Community 2017 (free).
  4. Run NestedStateThreads.exe.
  5. Referring to the state chart above, type any of these keys: r, b, or q.
    To get the full effect, press and hold the r key, then keep pressing and releasing the b key.
    Per the state chart, when in the Idle state, you must press the r key within 7 seconds or the program will terminate.

3.2 On an Embedded Device

  1. Clone OOSMOS from GitHub.
  2. Open a command line window and then change directory to oosmos.
  3. Run populate.py. (Python must be installed.)
  4. Change directory to oosmos\Examples\Blink.
  5. Build one of the Blink examples using the appropriate IDE. If you'd like to see other mainstream boards supported, let us know.
Copyright © 2014-2019  OOSMOS, LLC