Shop Learn
TAQOZ Reloaded v2.8 - State machine using Mini-OOF — Parallax Forums

TAQOZ Reloaded v2.8 - State machine using Mini-OOF

bob_g4bbybob_g4bby Posts: 311
edited 2022-04-16 18:57 in Forth

This code allows one or more state machines to run in a state-multiplexed fashion on one cog - in effect multi-tasked state machines. The code is hopefully cog-safe, so a number of cogs can run clones of the same state machine too. A demo MAIN shows two state machines running on one cog, stopping when the user hits a key. Not bad for 414 bytes.

  1. Class SM is not a complete state machine - it's just the 'program counter' and 'state launcher'
  2. A number of states is then defined for an SM object to run
  3. The demo shows how this is integrated in a small program

Of course, class SM isn't very useful as-is. Further child classes can be made from SM that have more variables and do real tasks. These children inherit all the methods of SM to step between states, jump to a new state etc.

NB The Mini-OOF code must be loaded before loading this code. Here's the code so far:-

--- State machine class using Mini-OOF ver 1 for Taqoz Reloaded v2.8 - Bob Edwards April 2022
--- N.B. Requires Mini-OOF to be loaded before loading this code
--- https://forums.parallax.com/discussion/174520/taqoz-reloaded-v2-8-mini-oof-object-oriented-programming-revisited
--- Dedicates the L stack to a state stack to enable call / return of states

IFDEF *StateM/C*
    FORGET *StateM/C*
}
pub *StateM/C* ." State machine using Mini-OOF ver 1" ;

--- Word to create a prototype state - it's just a constant set to 0 for now 
--- later set to point to some code. So 0 indicates an unassigned or 'idle' state
pre STATE
    0 [C] [G] [C] := [C] [G]
;

--- State machine class SM
--- This is just a 'program counter' and 'word launcher' - not a complete state machine
OBJECT CLASS
    2 VARI NEXTSTATE
    METHOD SMGOTO
    METHOD SMCALL
    METHOD SMRETURN
    METHOD SMSTEP
END-CLASS SM

--- save state in the state machine 'progam counter'
pri NEXTSTATE!              ( state -- )
    THIS NEXTSTATE W!
;

--- read the state machine 'program counter'
pri NEXTSTATE@              ( -- state )
    THIS NEXTSTATE W@
;

--- Jump to 'state' - no need to return
pri noname WITH                 ( state -- )
    NEXTSTATE!
; ANON SM DEFINES SMGOTO

--- Push the return point on the L stack, call the new state, 
pri noname WITH             ( state -- )
    NEXTSTATE@ >L           --- save the present state on the L stack
    NEXTSTATE!              --- load the program counter with 'state'
; ANON SM DEFINES SMCALL

--- Pop the return point from the L stack and execute that state again
pri noname WITH
    L> NEXTSTATE!           --- recall saved state from the L stack
; ANON SM DEFINES SMRETURN

--- Execute one state in the state machine
pri noname WITH
    NEXTSTATE@
    DUP 0<> IF EXECUTE THEN     --- if the state has been assigned code, execute it
; ANON SM DEFINES SMSTEP

--- End of class SM


--- We need some states for a state machine engine based on SM to work with so here they are
STATE STATE1
STATE STATE2
STATE STATE3

--- STATE1 to STATE3 need to do stuff, so we define that here
--- The start address of an anonymous word is stored in each STATE
--- For demo, each state displays it's identity and sets NEXTSTATE up for the next step
--- The states are set to run STATE1 -> STATE2 -> STATE3 -> STATE1 -> STATE2 ....
pub noname 
    ." State 1 "
    STATE2 NEXTSTATE!           --- STATE1 unconditionally sets STATE2 to run next
; ANON ' STATE1 :=!
pub noname
    ." State 2 "
    STATE3 NEXTSTATE!           --- STATE2 unconditionally sets STATE3 to run next
; ANON ' STATE2 :=!
pub noname
    ." State 3 "
    STATE1 NEXTSTATE!           --- STATE3 unconditionally sets STATE1 to run next
; ANON ' STATE3 :=!

--- End of state definitions 



--- this small demo runs SM1 starting at STATE3, SM2 starting at STATE1

SM NEW := SM1
SM NEW := SM2

pub MAIN                        ( -- )
    STATE3 SM1 SMGOTO           --- We initialise SM1 to start at STATE3 
    STATE1 SM2 SMGOTO           --- and SM2 to start at STATE1
    BEGIN
        CRLF ." SM1 "
        SM1 SMSTEP              --- execute one state of SM1
        CRLF ." SM2 "
        SM2 SMSTEP              --- execute one step of SM2
        500 ms                  --- and loop until
        KEY                     --- the user presses a key
    UNTIL
;



An application that uses class SM to define tasks will run more slowly than in non-OOF code. However, getting a single cog to do multiple tasks simultaneously may make it's use worth while. If faster execution is essential, then many words in the SM class could be rewritten in assembly language to gain speed. The present code is a proof of concept, if you like.

Sign In or Register to comment.