-2

I am trying to create a State Machine In C. This state machine is dependent on four interlinked events. To represent it I would like to show an array,

StateEventProcess[max_states][no_of_alarm][no_alarm_hsyt][timer_Status];

All the indexes are just some numbers, like 5,2,2,2 respectively.

I want to implement a state machine table by which I can fire Call back function

I have implemented it for State and Condition tuple only.

enum states
{ 
    en_AI_NO_ALARM_s1, en_AI_LOW_ALARM_s2, en_AI_HIGH_ALARM_s3, en_AI_SENSOR_BREAK_s4, en_AI_UNDER_CALIBRATION_s5 
}
current_state;

enum events 
{ 
    COND_1, COND_2, COND_3, COND_4 
} 
new_cond;

void action_s1_c1 (void);
void action_s1_c2 (void);
void action_s1_c3 (void);
void action_s1_c4 (void);

void action_s2_c1 (void);
void action_s2_c2 (void);
void action_s2_c3 (void);
void action_s2_c4 (void);
.
.
.
.

enum events GetNewCond (void)
{
    if(Val < LowAlarm)
        return COND_1;
    if(val > LowAlarm)
        return COND_2;
    if(Val < HighAlarm)
        return COND_3;
    if(val > HighAlarm)
        return COND_4;
}
void (*const state_table [MAX_STATES][MAX_COND]) (void) = {
    { action_s1_c1, action_s1_c2, action_s1_c3, action_s1_c4}, /* procedures for state 1 */
    { action_s2_c1, action_s2_c2, action_s2_c3, action_s2_c4}, /* procedures for state 2 */
    { action_s3_c1, action_s3_c2, action_s3_c3, action_s3_c4}, /* procedures for state 3 */
    { action_s4_c1, action_s4_c2, action_s4_c3, action_s4_c4}, /* procedures for state 4 */
    { action_s5_c1, action_s5_c2, action_s5_c3, action_s5_c4}, /* procedures for state 5 */ 
};

But it's quite confusing for me to handle the 4d array in a way I have handled the 2d array above. Please help me implementing the same.

Anand
  • 1,067
  • 3
  • 11
  • 24
  • 3
    A 4D array is almost certainly not what you want. But either way, you haven't explained what the specific problem is, i.e. it's unclear what you're asking. – Oliver Charlesworth Sep 02 '16 at 11:39
  • Instead of using for loops, I want to use a table which can act as a source to fire a callback for a particular case. Case may be: LOW_ALARM, LOW_ALARM, HIGH_HYST, TIMER_OFF – Anand Sep 02 '16 at 11:41

2 Answers2

2

You have to open 4 braces

#define MAX_ST 5 // max_states
#define MAX_NA 2 // no_of_alarm
#define MAX_AH 2 // no_alarm_hsyt
#define MAX_TS 2 // timer_Status

void (*const state_table[MAX_ST][MAX_NA][MAX_AH][MAX_TS]) (void) = {
    {
        {
            { st0_na0_ah0_ts0, st0_na0_ah0_ts1 }, // state 0, alarm 0, history 0, status 0
            { st0_na0_ah1_ts0, st0_na0_ah1_ts1 }, // state 0, alarm 0, history 0, status 1
        },
        {
            { st0_na1_ah0_ts0, st0_na1_ah0_ts1 },
            { st0_na1_ah1_ts0, st0_na1_ah1_ts1 },
        },
    },
    {
        {
            { st1_na0_ah0_ts0, st1_na0_ah0_ts1 },
            { st1_na0_ah1_ts0, st1_na0_ah1_ts1 },
        },
        {
            { st1_na1_ah0_ts0, st1_na1_ah0_ts1 },
            { st1_na1_ah1_ts0, st1_na1_ah1_ts1 },
        },
    },
    /* ... */
};
pmg
  • 106,608
  • 13
  • 126
  • 198
  • Kindly please explain what is meant by 'st0_na0_ah0_ts0', how I expand it to understand the name. – Anand Sep 02 '16 at 11:45
  • Thanks, It made me think in new ways – Anand Sep 02 '16 at 11:55
  • Glad it helped. – pmg Sep 02 '16 at 11:58
  • Even I am. But there is any way to optimise it, so that it doesn't grow heavily if I add any of the parameters. For example if am supposed to add 2 more states, then it will lead to great growth of the table. Please suggest – Anand Sep 02 '16 at 12:02
0

Implementing state machine using state table is handy for simpler/fewer states. But in your case expanding it up to 4d will be complex and difficult to maintain or read.

Instead I'd suggest you to use lightweight state machine framework. The advantage of framework is that your state machine becomes easy to maintain and extend.

You can refer my previous answer here or visit my GitHub page UML state machine in C framework for further info. You can find the GitHub project here.