State Machine
I am trying to setup a simple state machine which activates two pins at a time (to be used eventually in a switching circuit). For now I am hooking up pins 0 through 4 to LEDs on my PDB. I want them to scroll through, with speed determined by a delay, and direction, by a variable. Perhaps someone can point out where I'm going wrong. I currently see no output. Any help is much appreciated. Thanks!
(I eventually want this running on its own dedicated cog, but that's another issue i suppose)
var
Long machine_delay
byte direction
pub run_machine(current_state)
dira[noparse][[/noparse]0..4]~~
repeat
if current_state > 5
current_state := 1
case direction
1:
case current_state
1 : outa[noparse][[/noparse]0..4] := %11000
2 : outa[noparse][[/noparse]0..4] := %01100
3 : outa[noparse][[/noparse]0..4] := %00110
4 : outa[noparse][[/noparse]0..4] := %00011
5 : outa[noparse][[/noparse]0..4] := %10001
current_state++
waitcnt(machine_delay + cnt)
2:
case current_state
1 : outa[noparse][[/noparse]0..4] := %11000
2 : outa[noparse][[/noparse]0..4] := %10001
3 : outa[noparse][[/noparse]0..4] := %00011
4 : outa[noparse][[/noparse]0..4] := %00110
5 : outa[noparse][[/noparse]0..4] := %01100
current_state++
waitcnt(machine_delay + cnt)
pub get_direction
return direction
pub set_direction (dir)
direction := dir
pub get_delay
return machine_delay
pub set_delay(del)
machine_delay := del
PUB MainLoop machine.set_delay(2_000_000) machine.set_direction(1) 'cognew(machine.run_machine(1), @Stack) machine.run_machine(1) waitcnt(300_000_000 + cnt) machine.set_direction(2)
(I eventually want this running on its own dedicated cog, but that's another issue i suppose)

Comments
You have to indent the whole stuff inside the repeat, otherwise your program ends faster than you can see the LED blink.
PS: Ok ... you won ;o)
BTW:
This is not a state-machine. State-machines have states and events (or transitions).
In your case, you wouldn't increment the state (state++), but send an event "forward" or "backward". The current state will then decide what the next state will be.
<http://en.wikipedia.org/wiki/Finite-state_machine>
case state 1 : case event forward: state:= 2; backward: state:= 6; stop: return; 2 : case event forward: ....Note that you have to generate events outside of the outer case. This might be polling a switch, or a timer generating events or ... whatever
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
"The FSM uses only entry actions, i.e., output depends only on the state."
Technically this is a Mealy machine because of the directional operator, but its more easily thought of in one direction, as a Moore.
The only way I would really update my code to make it any more like your example (and this is trivial) is in each case "state" to change the value of current_state to the next number, instead of incrementing up.
Post Edited (mminasian) : 7/7/2009 7:42:51 PM GMT
It looks quite degenerated.
Seems as if you could use an array of patterns and move along it with incrementing/decrementing an index that wraps around at the ends. Would be more compact.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
pub run_machine dira[noparse][[/noparse]0..4]~~ repeat case current_state 1 : outa[noparse][[/noparse]0..4] := %11000 case direction 1: current_state := 2 2: current_state := 5 2 : outa[noparse][[/noparse]0..4] := %01100 case direction 1: current_state := 3 2: current_state := 1 3 : outa[noparse][[/noparse]0..4] := %00110 case direction 1: current_state := 4 2: current_state := 2 4 : outa[noparse][[/noparse]0..4] := %00011 case direction 1: current_state := 5 2: current_state := 3 5 : outa[noparse][[/noparse]0..4] := %10001 case direction 1: current_state := 1 2: current_state := 4 waitcnt(machine_delay + cnt)HAPPY!?! haha
Perfect, but it looks soooo ugly.
I see a shifting pattern, this SHOUTS for a different solution. Look for ROL and ROR.
byte pattern = %11001100;
if forward
pattern<-= 1;
if backward
pattern->= 1;
Hope ROL and ROR works on bytes.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
Byte current_state dira[noparse][[/noparse]0..4]~~ current_state := %11000 repeat outa[noparse][[/noparse]0..4] := current_state if(direction == 1) current_state ->= 1 if (direction ==2) current_state <-= 1Then it is a SHL / SHR
If you draw each pattern below the other (I didn't), it gets most obvious what has to be done.
Patterns! Patterns! Gang of three (bad book).
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
11000
01100
00110
00011
10001
This should be a rotate, using shift yields the same result
You'll notice the minor difference after more than one pass on the round robbin.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
Like a 74595 that has the SerIN connectet to the SerOUT or not (register preloaded, of course).
Connected: ROL/ROR
Disconnected: SHL/SHR
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO