Shop OBEX P1 Docs P2 Docs Learn Events
FullDuplexSerial (dual prop terminal emulator) — Parallax Forums

FullDuplexSerial (dual prop terminal emulator)

SarielSariel Posts: 182
edited 2012-07-16 04:44 in Propeller 1
Good morning Forumistas!
I am starting work on making a propeller program that is going to listen to the new CMUCam4, and I need a program that is running on an independent propeller that listens to the debug port, and passes the info out to the PST, as well as is able to do string comparisons on incoming data for automated manipulation of the camera's features. While I wait for delivery of the cam, I have mocked up a simple transmitter that is loaded onto a prop that just loops a string output. The problem I am having is that the receiver is not catching all of the string and giving me buffer overflow errors. I know that the hardware is good because if I run a receiver program that has no buffering, it works just fine. For the record, I have about 12 inches of wire between the 2, and a good stable ground connecting them since they are running off of the same power supply. Can someone please take a peek and tell me if there is anything that I am missing? I just cannot see the bug after toiling at it for quite some time now. (ashamedly a lot more time than it should take to get something this simple to work).

Here is the transmitter program I am using:
CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000        
  P2PTX         = 1
  P2PRX         = 0
  P2PMODE       = 0
  P2PBAUD       = 19200
              
'************** ASCII Conversion chart
  CR            = 13
              
OBJ
  P2POBJ        : "FullDuplexSerialPlus.spin"
DAT
OutThisThing            Byte    "silly string output",0
      
PUB Start
  P2POBJ.start(P2PRX, P2PTX, P2PMODE, P2PBAUD)          ' start serial transmitter
  repeat                                                ' loop this out     
    P2POBJ.str(@OutThisThing)  
    P2POBJ.tx(CR)    

and here is the reciever code:
CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
  
'************** ASCII Conversion chart                         
  CR            = 13    
'************** Connection info
  DebugTx       = 30
  DebugRx       = 31
  DebugMode     = 0
  DebugBaud     = 19200
  DebugPause    = 2
  P2PTx         = 22
  P2PRx         = 21
  P2PMode       = 0
  P2PBaud       = 19200
'************** Misc. Constants
  BufferMaxSize = 65
VAR            
  
  word  CharPointer             ' Pointer for char position
  byte  CharBuff[BufferMaxSize] ' Buffer space for string analysis
  byte  char                    ' recieved character
OBJ    
  P2PCOM        : "FullDuplexSerialPlus.spin"                 ' P2P Comm object
  DEBUG         : "FullDuplexSerialPlus.spin"                 ' Debug Term object
DAT
'************** Debug msg's
DBugRdy                 Byte    "Debug Term Ready",0
P2PRdy                  Byte    "Prop to Prop com ready",0
BugFlag                 Byte    "*******FLAG*******",0
Error                   Byte    "Error. System Halted.",0
 
'************** System msg's
Overflow                Byte    "Buffer Overflow",0
 
PUB Start
'' inits the object
                                                                                                       
  BufferClear                                           ' clear the character buffer                 
  CharPointer := 0                                      ' ensure pointer starts at 0
                                                                                                         
  if DEBUG.start(DebugRx, DebugTx, DebugMode, DebugBaud)' Start the PST for debugging   
    waitcnt(clkfreq*DebugPause + cnt)                   ' Give user a chance to enable the PST   
    DEBUG.str(@DBugRdy)                                 ' Basic notification
    DEBUG.tx(CR)         
    DEBUG.tx(CR)
  else                                                  ' if error, stop
    halt
    
  if P2PCOM.start(P2PRx, P2PTx, P2PMode, P2PBaud)       ' Start prop to Prop comms      
    waitcnt(clkfreq*DebugPause + cnt)                   ' Give user another chance to enable the PST          
    DEBUG.str(@P2PRdy)                                  ' Basic notification
    DEBUG.tx(CR)   
    DEBUG.tx(CR)
  else                                                  ' if error, stop  
    halt                       
  Main                                                  ' Go to main loop
        
Pub Main
'' Main loop of the program.
  repeat
    char := P2PCOM.rxcheck                              ' Get the character from otehr prop
    if Char <> -1                                       ' if character found (anything but -1)
      if Char == CR                                     ' if it is CR
        CharBuff[CharPointer] := 0                      ' null terminate the buffer
        PSTOut                                          ' display the buffer in PST
        BufferClear                                     ' clear the buffer 
        CharPointer := 0                                ' reset the pointer addy
      else                                              ' if anything but CR or -1
        CharBuff[CharPointer] := Char                   ' store the char in buffer
        CharPointer++
        if CharPointer > BufferMaxSize                  ' if pointer is at final null termination
          DEBUG.str(@Overflow)                          ' Consider it an overflow
          DEBUG.tx(CR)                                  
          CharPointer := 0                              ' reset pointer
          BufferClear                  
  halt                                                  ' security blanket halt
PUB PSTOut
'' Method for outputting the data to debug window.
  DEBUG.str(@CharBuff)
  DEBUG.tx(CR)
  
PUB BufferClear
'' Ensure the char buffer is null terminated                                 
  bytefill(@CharBuff, 0, BufferMaxSize)
    
PUB Halt
'' Fatal error stop. Halts no cogs, just suspends current one.
  DEBUG.str(@Error)     
  repeat
    waitcnt(clkfreq+cnt)

And the PST output with the transmitter not running just repeats "Buffer Overflow", and with it running always looks like this:
Debug Term Ready
Prop to Prop com ready
ring output
silly string outpuÿÿÿÿÿÿtÿÿÿÿÿÿÿ
put
silly string oÿÿÿuÿÿÿÿÿÿÿtÿÿÿÿÿÿÿpÿÿÿÿÿÿuÿÿÿÿÿÿÿtÿÿÿÿÿÿ
Buffer Overflow
put
Buffer Overflow
ut
Buffer Overflow
put
Buffer Overflow
put
Buffer Overflow
put
Buffer Overflow
put
Buffer Overflow
put
Buffer Overflow
put

Comments

  • SarielSariel Posts: 182
    edited 2012-07-13 08:55
    Well, I ended up figuring it out, but I am not exactly sure why this worked. Maybe a puzzle for all of you out there that like this sort of "unanswerable question" problems. What I did was replace:
    else                                              ' if anything but CR or -1
            CharBuff[CharPointer] := Char                   ' store the char in buffer
            CharPointer++
            if CharPointer > BufferMaxSize                  ' if pointer is at final null termination
              DEBUG.str(@Overflow)                          ' Consider it an overflow
              DEBUG.tx(CR)                                  
              CharPointer := 0                              ' reset pointer
              BufferClear                  
    

    with:
    if char >31 and char < 128                        ' if char is a valid character
            CharBuff[CharPointer] := Char                   ' store the char in buffer
            CharPointer++
            if CharPointer > BufferMaxSize                  ' if pointer is at final null termination
              DEBUG.str(@Overflow)                          ' Consider it an overflow
              DEBUG.tx(CR)                                  
              CharPointer := 0                              ' reset pointer
              BufferClear
    

    I am not sure why it is doing that, but excluding everything that is not a regular ASCII character did the trick. can anyone out there tell me why that might be? As a side note, in my troubleshooting, I tried to tie the transmit and recieve lines to ground, then +3.3v to see if it was a noise problem, and that changed nothing. Any ideas out there? Seems like a dumb fix for something that should not be broken.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2012-07-13 11:05
    I was going to say that the rapid-fire 19200 baud from your send routine is going to overrun the 128 byte receive buffer on the other end. There is no flow control, and your receive routine has a lot to do.

    But the error with the "ÿ" character happens soon after start, before any possible overflow. What is the ascii value of that "ÿ" character? It is not found in the Parallax font I think, and in some fonts it is ascii value 152. Why that.

    This is a good point at which to simplify the program, and on the receive end simply relay the input bytes to the DEBUG port. This is a situation where something like the Saleae logic analyzer that Parallax sells can help, to see what is happening on the serial line.
  • groggorygroggory Posts: 205
    edited 2012-07-13 11:42
    I've seen that character come up before. I think I got that character when I didn't set the serial invert line properly.

    A logic analyzer would really help you here. That's how I figured out that problem.

    PS. The Saleae logic analyzer is my #1 favorite tool for embedded work. Money VERY well spent.
  • SarielSariel Posts: 182
    edited 2012-07-13 11:54
    I was going to say that the rapid-fire 19200 baud from your send routine is going to overrun the 128 byte receive buffer on the other end. There is no flow control, and your receive routine has a lot to do.

    But the error with the "ÿ" character happens soon after start, before any possible overflow. What is the ASCII value of that "ÿ" character? It is not found in the Parallax font I think, and in some fonts it is ASCII value 152. Why that.

    This is a good point at which to simplify the program, and on the receive end simply relay the input bytes to the DEBUG port. This is a situation where something like the Saleae logic analyzer that Parallax sells can help, to see what is happening on the serial line.

    That is what was stumping me too. the "umlaut-Y" char is not even anywhere in the program area when you hit F8 of either program, so I was thinking it could be errors from jitter or cross-talk. I was using a 2 wire twisted pair for the connection from board to board, but using single discrete wires did not change it either. And neither did trying pull up and pull down's.

    And I did try a "Buffer less" receive program, and that would work fine that was basically the same program, but it did just what you were suggesting. Just mirror the byte from the other prop to the PST without any modifications, and the "umlaut-Y" was not there.

    Crazy stuff. I hope the bug does not resurface later on with the little band-aid I put on it. It just bugs me that there is no reason for it, but it was obviously there. Can anyone out there with 2 prop boards reproduce this error with the original code in my first post? I would be most curious to find out. Maybe the prop in one of my boards is still working, but becoming defective. *shrug* But now I am just grasping at straws.

    I think I will talk to the boss and see if he will loosen the purse strings a little to let me get that analyzer
  • SarielSariel Posts: 182
    edited 2012-07-13 11:57
    I think I got that character when I didn't set the serial invert line properly.

    I did not think I had to worry about that kind of stuff, and that it was all taken care of in FullDuplexSerial. the mode settings are identical for both props, so I did not even think that would factor in.
  • KyeKye Posts: 2,200
    edited 2012-07-13 16:48
    The y thing is 255. So... that's generated by some error or noise.

    Thanks,
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2012-07-13 17:38
    Have you tried running the transmission at a lower pace? For example, put a one second delay at the end of each "silly" packet.

    There are different versions of fullDuplexSerialPlus floating around. Oh my, I just searched my Mac and find that I have 33 different copies with various creation dates. Some have the original pitifully small 16 byte buffers. The most recent seems to be version 3.01 which has a lot of updates by Andy Lindsay, including 128 byte buffers and instructions for adjusting the buffer size. Another thing, v3.01 has the variables declared as DAT rather than VAR, so that it can be used like serial mirror, one instance across objects. However, that (if you have it) would jinx your program, because you are trying to use two separate instances, one for prop2prop and another for debug.

    One minor issue in your code
    [SIZE=1][FONT=courier new]   CharBuff[CharPointer] := Char
       CharPointer++
       if CharPointer [COLOR=#ff0000]>[/COLOR] BufferMaxSize
       ...[/FONT][/SIZE]
    

    I think it should be ==. No big consequence though, because it would just write char over itself.
  • SarielSariel Posts: 182
    edited 2012-07-16 04:44
    I wanted to get it working running full board at the speed I have it at because I wanted to try to write a receiver that would go full pace without error for the CMUcam4, so I did not even think to try it at a lower pace. And as for the "==" thing, thank you. Good catch there, but I am most likely going to change it to
    [FONT=courier new][SIZE=1]
       [COLOR=#020fc0][SIZE=1]if CharPointer [/SIZE][/COLOR][/SIZE][/FONT][COLOR=#020fc0][SIZE=1]==[/SIZE][/COLOR][FONT=courier new][SIZE=1][COLOR=#020fc0][SIZE=1] (BufferMaxSize -1)[/SIZE][/COLOR]
    [/SIZE][/FONT]
    
    to ensure that the last char in my buffer is always null terminated. Good catch on the ==. I have a bad habit of overlooking those pesky non-bugs. :tongue:
    [The y thing is 255. So... that's generated by some error or noise./QUOTE]

    That is very good to know Kye. I will have to remember that one just in case that bugger comes up again somewhere.

    No matter tho. The code works well now, so I think I am not going to break it too much more. Just in case anyone out there is interested in it I will post the transmitter and receiver. I know every once in a while there are folks looking for Prop to Prop communication protocols that are quick and dirty.

    Thanks again for your help everyone.

    SimpleRx.spin
    SimpleTX.spin
Sign In or Register to comment.