Help with serial output event scheduling

I am reading 2 digital inputs, one of which is a reasonably fast continuous pulse, the other which is a state changing logic hi/lo, what I need to do is have the continuous pulse always send a serial event on every high and nothing when low, and the other pin will send a serial event for each state but only when the state changes, so if it is high it sends the high serial event once, then when the state changes to low it send the low serial event once. I kind of have it working, but because I am using a loop each time the loop restarts the pins are being read as expected but sending the message regardless of the last sent state. It is probably simple to do but I can't figure it out, timing is critical as this is to be used for midi clock generation. Here is my code

Code:
main:
IF rs_in = 0 THEN 
	hserout 0,(0xFc)
ENDIF
IF rs_in = 1 THEN
	hserout 0,(0xFa) 
ENDIF

IF clk_in= 1 THEN
	hserout 0,(0xF8) 
	DO UNTIL clk_in =0
		LOOP
	ENDIF
	GOTO main
 

hippy

Technical Support
Staff member
This is where I would start from, using bit0 and bit1 to track the previous states of the inputs -

Code:
Do

  If rs_in <> bit0 Then
    bit0 = bit0 ^ 1
    If bit0 = 0 Then 
      HSerOut 0,(0xFc)
    Else
      HSerOut 0,(0xFa)
    End If
  End If

  If clk_in <> bit1 Then
    bit1 = bit1 ^ 1
    If bit1 = 1 Then
      HSerOut 0,(0xF8)
    End If
  End If

Loop
Note that the pins are only compared with the last state in the bitX variable. The bitX variable is then inverted to reflect what the pin state must have been when compared, and the output determined from that bitX state. This will more reliably handle pin states which changes while the code is executing.

It would also be possible to have a finite state machine with 'where it is executing' providing the memory of previous state. That would be more responsive but use more code. Untested ...

Code:
State00: ; RS=0 CK=0

  b0 = rs_in * 2 | clk_in
  Select Case b0
    Case %00 :                           Goto State00
    Case %01 : HSerOut 0, (      $F8 ) : Goto State01
    Case %10 : HSerOut 0, ( $FA      ) : Goto State10
    Case %11 : HSerOut 0, ( $FA, $F8 ) : Goto State11
  End Select

State01: ; RS=0 CK=1

  b0 = rs_in * 2 | clk_in
  Select Case b0
    Case %00 :                           Goto State00
    Case %01 :                           Goto State01
    Case %10 : HSerOut 0, ( $FA      ) : Goto State10
    Case %11 : HSerOut 0, ( $FA      ) : Goto State11
  End Select

State10: ; RS=1 CK=0

  b0 = rs_in * 2 | clk_in
  Select Case b0
    Case %00 : HSerOut 0, ( $FC      ) : Goto State00
    Case %01 : HSerOut 0, ( $FC, $F8 ) : Goto State01
    Case %10 :                           Goto State10
    Case %11 : HSerOut 0, (      $F8 ) : Goto State11
  End Select

State11: ; RS=1 CK=1

  b0 = rs_in * 2 | clk_in
  Select Case b0
    Case %00 : HSerOut 0, ( $FC      ) : Goto State00
    Case %01 : HSerOut 0, ( $FC      ) : Goto State01
    Case %10 :                           Goto State10
    Case %11 :                           Goto State11
  End Select
That can be optimised to be even faster but would be more complicated.
 

hippy

Technical Support
Staff member
Another finite state machine option, untested ...

Code:
State00: ; RS=0 CK=0

  b0 = rs_in * 2 | clk_in
  If bit1 = 1 Then
    HSerOut 0, ( $FA )
  End If
  If bit0 = 1 Then 
    HSerOut 0, ( $F8 )
  End If
  On b0 Goto State00, State01, State10, State11

State01: ; RS=0 CK=1

  b0 = rs_in * 2 | clk_in
  If bit1 = 1 Then 
    HSerOut 0, ( $FA )
  End If
  On b0 Goto State00, State01, State10, State11
  
State10: ; RS=1 CK=0

  b0 = rs_in * 2 | clk_in
  If bit1 = 0 Then 
    HSerOut 0, ( $FC )
  End If
  If bit0 = 1 Then 
    HSerOut 0, ( $F8 )
  End If
  On b0 Goto State00, State01, State10, State11

State11: ; RS=1 CK=1

  b0 = rs_in * 2 | clk_in
  If bit1 = 0 Then 
    HSerOut 0, ( $FC )
  End If
  On b0 Goto State00, State01, State10, State11
You would need to test each to see which were faster or which delivered a suitable response to your inputs.
 
Much obliged hippy, both versions seem to do what I wanted and work fine, further testing and possibly some more questions to follow, thank you.
 
Further testing reveals little difference in performance between the 3 methods, all of them give some fairly regular jitter, albeit quite small (0.1-0.2 bpm fluctuation about every 1 second on the output) but ideally I'd like to eliminate any jitter, can you think of anything that might be causing this?

I'm running the 08m2 at 32mhz and using the disconnect command, can you think of anything else that I could do to optimize? I am using pull downs on the inputs to eliminate any chance of false pin readings and the power supply is filtered using capacitors as per the recommendation in the manual.
 
Following up, it seems that the jitter is present before the picaxe in the chain, so I must look into eliminating this before anything else.
 
Top