-
Notifications
You must be signed in to change notification settings - Fork 0
State machines

Loviisa lets you define state machines in a declarative style, simplifying your code and making it unified, compact and predictable.
State machine is described as a single multi-block description that is actual within a single C file.
The following primitives let you describe and manage state machines (name is always a name of the state machine):
LVS_DEFINE_STATES(name) - starts states descriptions section
LVS_STATE(state) is used to introduce the new state name within the section
LVS_DEFINE_ACTIONS(name) - ends states description and starts actions description
LVS_ACTION(action) introduces new action within the actions section
LVS_DEFINE_REACTIONS(name) - ends actions description and starts reactions description. Reactions description contains multiple definitions of what shall be done in a given state upon the given action
Special variables state and action are available within this section to access current state and action. These variables can be compared with values retrieved from the name of a state or an action with using LVS_GET_STATE or LVS_GET_ACTION.
LVS_ON_ACTION(state, action) starts statements to be performed in a given state if given action happens
LVS_ON_ANY_ACTION(state) starts statements that shall be performed on any action in this state. This block is only executed if no special LVS_ON_ACTION is defined earlier for this state and action
LVS_ON_UNDEFINED_STATE() is performed if the machine is in initial or undefined state
LVS_SWITCH_STATE(state) is used within the reactions section to initiate the transition to the new state
LVS_END_DEFINITION(name) finishes state machine definition
LVS_DO_ACTION(name, action) sends the given action to the state machine
Below is a real example of the state machine use:
LVS_DEFINE_STATES(msg_to_write)
LVS_STATE(preamble)
LVS_STATE(length)
LVS_STATE(timestamp)
LVS_STATE(prop_no)
LVS_STATE(value)
LVS_STATE(checksum)
LVS_STATE(bypass)
LVS_DEFINE_ACTIONS(msg_to_write)
LVS_ACTION(new_char)
LVS_DEFINE_REACTIONS(msg_to_write)
LVS_ON_UNDEFINED_STATE()
if (__value == 0xC0)
{
LVS_SWITCH_STATE(preamble)
__counter = 1;
}
else
LVS_SWITCH_STATE(bypass)
LVS_ON_ANY_ACTION(preamble)
if (__value == 0xC0)
{
LVS_SWITCH_STATE(length)
__counter = 0;
}
else
LVS_SWITCH_STATE(bypass)
LVS_ON_ANY_ACTION(length)
__length <<= 8;
__length |= __value;
__counter += 1;
if (__counter == 2)
{
LVS_SWITCH_STATE(timestamp)
__counter = 0;
}
LVS_ON_ANY_ACTION(timestamp)
__counter += 1;
if (__counter == 6)
{
LVS_SWITCH_STATE(prop_no)
__counter = 0;
}
LVS_ON_ANY_ACTION(prop_no)
__prop_num <<= 8;
__prop_num |= __value;
__counter += 1;
if (__counter == 2)
{
LVS_SWITCH_STATE(value)
__counter = 0;
}
LVS_ON_ANY_ACTION(value)
int idx = __counter / 2;
__prop_vals[idx] <<= 8;
__prop_vals[idx] |= __value;
__counter += 1;
if (__counter >= (__length - 8 + 1) * 2)
{
LVS_SWITCH_STATE(checksum);
__counter = 0;
};
LVS_ON_ANY_ACTION(checksum)
boiler_WriteProperty(__prop_num, 0x01, __prop_vals);
LVS_SWITCH_STATE(bypass)
LVS_ON_ANY_ACTION(bypass)
if (__value == 0xC0)
{
LVS_SWITCH_STATE(preamble);
__counter = 1;
};
LVS_END_DEFINITION(msg_to_write);