Shop OBEX P1 Docs P2 Docs Learn Events
Operating Simple_Serial at faster data rates or slower clock speeds — Parallax Forums

Operating Simple_Serial at faster data rates or slower clock speeds

Bobb FwedBobb Fwed Posts: 1,119
edited 2013-03-15 19:42 in Propeller 1
I have a project that is a bit power conscious, and thus runs at 20MHz.
It needs to transmit some information at 9600 baud, but I don't want to launch another cog to do it (for power consumption reasons). So I tried the Simple_Serial object and found it didn't function (as the documentation expressed). But I did find that it was awful close (somewhere in the neighborhood of 15% off). So I worked on it a little and came up with this:
PUB tx(txByte) | t, i
{{ Transmit a byte; blocks caller until byte transmitted. }}

  if txOkay
    DIRB := ((txByte | $100) << 1) ^ inverted           ' add stop bit, set mode
  
    outa[sout] := !inverted                             ' set idle state
    t := cnt                                            ' sync
    dira[sout]~~                                        ' make tx pin an output        

    waitcnt(t += bitTime)                               ' wait bit time
    outa[sout] := DIRB[0]                               ' output bit
    waitcnt(t += bitTime)                             
    outa[sout] := DIRB[1]                               
    waitcnt(t += bitTime)                             
    outa[sout] := DIRB[2]                              
    waitcnt(t += bitTime)                             
    outa[sout] := DIRB[3]                               
    waitcnt(t += bitTime)                         
    outa[sout] := DIRB[4]                 
    waitcnt(t += bitTime)                     
    outa[sout] := DIRB[5]                 
    waitcnt(t += bitTime)                        
    outa[sout] := DIRB[6]                 
    waitcnt(t += bitTime)                       
    outa[sout] := DIRB[7]                 
    waitcnt(t += bitTime)                           
    outa[sout] := DIRB[8]                
    waitcnt(t += bitTime)                         
    outa[sout] := DIRB[9]                
    
    if sout == sin
      dira[sout]~                                       ' release to pull-up/pull-down
It will transmit at 9600 baud at 20MHz, and thus will also transmit at 38.4Kbaud at 80MHz (actually it will go up to 47.0Kbaud).

Thought other may find this useful for some project or another. I don't need the cog to receive at the moment, (and I have no real way to test it anyway), but doing something similar to the RX method may give similar results.

Comments

  • lonesocklonesock Posts: 917
    edited 2013-03-14 14:19
    Nice! Instead of using the loop and array at the beginning to segregate the bits, maybe just use the DIRB register? Then Spin lets you access one bit at a time.

    Jonathan
  • Mike GreenMike Green Posts: 23,101
    edited 2013-03-14 14:21
    Receiving is harder than transmitting in that you have to look for the edge of the start bit (1->0) then set up the timing based on the middle of the start bit. If you do it properly, you also check for a 0 state in the middle of the start bit and give up on that pulse edge (as noise) if the 0 is not still there. You can unroll the bit loop for reception the same way you did it for transmission. If you do it properly, you also check for a valid (1) stop bit as the 9th bit.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-14 14:43
    lonesock wrote: »
    Nice! Instead of using the loop and array at the beginning to segregate the bits, maybe just use the DIRB register? Then Spin lets you access one bit at a time.

    Jonathan
    Thanks. There, now it's in as you said.
  • JonnyMacJonnyMac Posts: 9,108
    edited 2013-03-15 19:42
    I'm with Mike: unroll the code -- you'll get better performance.
Sign In or Register to comment.