HSerSetUp Background Receive

dennis

Member
I have a multiplexed 4 digit 7seg LED display direct driven by a 20X2 at 64MHz. It is flicker free apart from a single brief black out when updating with new values. The updating takes place via Serin at 9800 Baud from an 08M and the interrupt routine seems to cause the flicker.

Is it possible to eliminate the interrupt and instead use background receive. In pseudo code the main display loop would be :

Do
get digit 1 from scratchpad. Pulsout to display
get digit 2 from scratchpad. Pulsout to display
etc
Loop

With no need for any interrupts.


I have made some experiments with HSerSetUp with a 28X1
The problem is to get the incoming bytes (sets of 4) into the right positions on the scratchpad. If left to free run the bytes seem to fill the scratchpad in sequence (as expected) until the hserptr rolls over at 127 (unexpected).
Setting the hseptr to zero at the beginning of the loop only works if an udesirable large delay is introduced into the loop.

I estimate that at 9600 Baud each byte takes about 1ms to send. Does background receive just halt program operation until the 4 bytes are acquired or how does it work ?


Dennis
 

Andrew Cowan

Senior Member
Background receive in works completly in the background, and program operation continues as normal.

hserptr-1 is equal to the last byte received, and the hserin flag is set when data is recieved.

Therefore, to stop it overflowing, you would need to reset hserptr to zero whenever all four digits info has been received. This should ensure that data is always in the same place.

If you are waiting for four bytes, add this to your code:
if hserptr=4 then
let hserptr=0
endif

This will ensure that the next four bytes overwrite the first ones.

A
 

hippy

Technical Support
Staff member
Each byte at 9600 baud will take around 1ms to send, but the receiver will only have to do something every 1ms ( at most ) as each byte is received. That will be very short if bytes are placed in scratchpad with no interrupt, but longer if an interrupt is called. There may still be some flicker though but it should be minimised; it depends on how long your multiplex pulses/strobes are in comparison with the internal time it takes to store the received byte in the scratchpad.

To handle scratchpad without interrupts, as Andrew suggests checking the hSerPtr then zeroing it after the main multiplexing loop has completed will work. If the incoming data is more frequent than that you'll need to keep track of where you were compared to where hSerPtr is and let hSerPtr roll round of its own accord.

This will echo back all data sent even during the 1 second period ( assuming you don't send more than a scratchpad full of data ) ...

Code:
#Picaxe 20X2
#No_Table
HSerSetup B9600_8, %xx1
Do
  Pause 1000
  Do While ptr <> hSerPtr
     HSerOut 0,( @ptrinc )
  Loop
Loop
What you ideally need is to wait until there are four bytes in the scratchpad but this can get complicated having to deal with 'ptr' and 'hSerPtr' which wraparound from 0 to 127 and vice versa when adding or subtracting. The easiest option is to use another index variable to take each byte as received store them away, then update the actual digit storage the multiplex is using when every four bytes are received. This echoes in groups of four, using 'b0' to 'b3' and 'bptr' to select those variables ...

Code:
#Picaxe 20X2
#No_Table
HSerSetup B9600_8, %xx1
Do
  Pause 1000
  Do While ptr <> hSerPtr
    @bPtrInc = @ptrInc
    If bPtr = 4 Then
      HSerOut 0, ( b0, b1, b2, b3, CR, LF )
      bPtr = 0
    End If
  Loop
Loop
This is a slightly more complicated example, with the pause extended to 5 seconds and it displaying what the last four sets of digits received were. Your multiplexor would effectively always display 'b4' to 'b7. "Type "0000" wait for that to be displayed, then quickly type "123456789" the display will show "5678", then type "876" and then you will see "9876" ...

Code:
#Picaxe 20X2
#No_Table
HSerSetup B9600_8, %xx1
b4 = "?"
b5 = "?"
b6 = "?"
b7 = "?"
Do
  HSerOut 0, ( b4, b5, b6, b7, CR, LF )
  Pause 5000
  Do While ptr <> hSerPtr
    @bPtrInc = @ptrInc
    If bPtr = 4 Then
      b4 = b0
      b5 = b1
      b6 = b2
      b7 = b3
      bPtr = 0
    End If
  Loop
Loop
So this shows the display always working no matter how slowly or quickly the data is sent. Whether the check is done when four digits received, or when only some digits have been received.

It always displays the correct data, never mangled data such as if you were displaying "1234" then received "99" with another "99" to come later, which could otherwise end up as showing "1234", "9934" then "9999".

This technique is called 'double-buffering' and avoids the above mangled data problems which you can have when displaying directly from the scratchpad.

Finally, synchronsisation; how to deal with turning the display on and missing some data sent; "1234", "5678", "9999", "0000" could end up displayed as "3456", "7899", "9900". This is solved by prefixing all data with a character which would not normally be sent, "X" in this case. So send "X1234", "X5678", "X9999", "X0000" and even if we miss the "X12" it will skip the "34" and sync up on the "X5678".

Code:
#Picaxe 20X2
#No_Table
HSerSetup B9600_8, %111
b4 = "?"
b5 = "?"
b6 = "?"
b7 = "?"
Do
  HSerOut 0, ( b4, b5, b6, b7, CR, LF )
  Pause 5000
  Do While ptr <> hSerPtr
    If b8 = 0 Then
      If @ptrInc = "X" Then
        b8 = 1
        bPtr = 0
      End If
    Else
      b8 = @ptrInc 
      If b8 = "X" Then
        b8 = 0
      Else
        @bPtrInc = b8
        If bPtr = 4 Then
          b4 = b0
          b5 = b1
          b6 = b2
          b7 = b3
          b8 = 0
        End If
      End If
    End If
  Loop
Loop
 
Last edited:

dennis

Member
Hippy - Thanks very much for the code examples. I managed to understand some of the concepts.

I now have a 20X2 directly driving a 4 digit 7 seg display and updating using the background receive HSerSetUp command. Data is sent from an 08M basically using your original driver program but with a 5th indicator byte.

It is very satisfying to see it counting up without even the merest hint of a suggestion of even the beginnings of an incipient flicker on the non changing digits.

Do you think your original code should be preserved and moved into one of the finished projects and maybe the ASCII segment mapping table duplicated into useful code snippets. It would be a pity if this stuff got lost.

Thanks again Dennis
 
Top