FSM: Programming

Let's try creating code to represent the passcode lock example. Generally, there's a straightforward process to creating most FSMs.

The first step is to declare an enum for the states of the machine.

typedef enum {SX, S2, S25, S253, S2534} passcode_state_t;

Next, declare a static variable with the initial state. The reason why we want this variable to be static is because FSMs will typically be encapsulated in functions. As a result, you want to keep track of the current state of the machine throughout each function call; the state shouldn't be resetting and instead should be static across every function call.

static passcode_state_t currentState = SX;

The next step is to make boolean variables for each output, making sure to also give them default values. This output should not be static.

bool unlocked = false;

Afterward, create an empty switch-case statement, where each state is its own case.

switch (currentState) {

    case SX:

        break;

    case S2:

        break;

    case S25:

        break;

    case S253:

        break;

    case S2534:

        break;

}

Now, we implement the transition arcs for each state. Each case should assign output values if they differ from the default and assign the next state.

switch (currentState) {

    case SX:

        if (guess == 2)

            currentState = S2;

        break;


    case S2:

        if (guess == 5)

            currentState = S25;

        else

            currentState = SX;

        break;


    case S25:

        if (guess == 3)

            currentState = S253;

        else

            currentState = SX;

        break;


    case S253:

        if (guess == 4)

            currentState = S2534;

            unlocked = true;

        else

            currentState = SX;

        break;


    case S2534:

        currentState = SX;

        break;

}

Once the switch-case statement has been evaluated, take any necessary actions from the resulting outputs. For example,

if (unlocked)

    openLock();

else

    closeLock();

Finally, if the FSM functions utilizes one of the outputs as a return value, return the output value.

return unlocked;

If we put this all together, we could have something like the following:

typedef enum {SX, S2, S25, S253, S2534} passcode_state_t;


int main(void) {

    while (1) {

        // the getGuessInput() function will halt the program

        // until an input is received

        int input = getGuessInput();


        // passcodeFSM() is the function containing the FSM

        bool isUnlocked = passcodeFSM(input);

    

        if (isUnlocked)

            playUnlockJingle();

    }

}


bool passcodeFSM(int guess) {

    static passcode_state_t currentState = SX;

    

    bool unlocked = false;


    switch (currentState) {

        case SX:

            if (guess == 2)

                currentState = S2;

            break;


        case S2:

            if (guess == 5)

                currentState = S25;

            else

                currentState = SX;

            break;


        case S25:

            if (guess == 3)

                currentState = S253;

            else

                currentState = SX;

            break;


        case S253:

            if (guess == 4) {

                currentState = S2534;

                unlocked = true; }

            else

                currentState = SX;

            break;


        case S2534:

            currentState = SX;

            break;

    }


    if (unlocked)

        openLock();

    else

        closeLock();


    return unlocked;

}

Note that this code is not synthesizable on its own. In its current state, many of the functions are not defined and will not compile if you simply copy/paste this into CCS. The intent of this example code is to demonstrate what a typical FSM would look like and how it would be implemented. Instead, use the text above as a reference or skeleton for your FSM.

Nonetheless, we recommend that you debug the above code on your board to get a deeper understanding of how it works. You can download a compilable version of this project from GitHub here.