Yikes, It's been a while since I last posted.  GTA5 got in the way, then I got very bored of GTA5 and then I played Skyrim all the way through again to get my head right.  GTA5 has almost zero re-play appeal.
Anyway...
For no good reason I wanted to see how fast I could signal asynchronous serial data from a single Cog on a Propeller chip. Like one does.
Studious observers might realise that I'm aiming for minimal code-space usage. This code is pretty compact but I think I can do better.
In fact I think I can reach much faster Baud rates. This code is limited by the waitcnt instruction, which is a little cumbersome when one is trying to wring out every last instruction cycle from a Cog.
By using one or both of a Cog's Counter features (CNTA and CNTB), it might be possible to get something close to 18 MBit of UART speed! This will be at the expense of code size though.
It is interesting to note that Mr Nyquist's observations determine that TX and RX do not necessarily share the same theoretical maximum baud rate. TXing is stateless (effectively) but RXing is stateful because we need to be able to notice edge transitions and compare them to the bit rate we are expecting. Even if I can hammer out TX rates of 18MHz, I'll probably be limited to RX rates of about a quarter of that, maybe less.
Science!
                           
                       
                     Anyway...
For no good reason I wanted to see how fast I could signal asynchronous serial data from a single Cog on a Propeller chip. Like one does.
CON
  _clkmode = XTAL1 | PLL16x
  _clkfreq = 5_000_000
PUB Main 
  coginit(0, @ENTRY_POINT, 0)
DAT            
                        org     0
ENTRY_POINT                                         
                        or      outa, TX  'idle high
                        or      dira, TX  'output
                        mov     byte_to_send, #$41
                        CALL    #SERIAL_SEND_BYTE
                        mov     byte_to_send, #$42
                        CALL    #SERIAL_SEND_BYTE
                        mov     byte_to_send, #$43
                        CALL    #SERIAL_SEND_BYTE
                        mov     byte_to_send, #$44
                        CALL    #SERIAL_SEND_BYTE
                        mov     byte_to_send, #$45
                        CALL    #SERIAL_SEND_BYTE
                        mov     byte_to_send, #$46
                        CALL    #SERIAL_SEND_BYTE
                        waitpeq $, #0                    'hang forever
SERIAL_SEND_BYTE        mov     ser_bitcount, #10        '8 data bits + start bit + stop bit == 10 bits total to send
                        mov     ser_bitbuf, byte_to_send
                        or      ser_bitbuf, #%1_00000000 '(binary) append the stop bit (we're sending this data LSB first don't forget!)
                        shl     ser_bitbuf, #1           'prepend the start bit  (shl shifts in a zero bit on the LSB)      
                        mov     ser_time, cnt
                        add     ser_time, #30            '30 clock cycles == approx 2_666_667 baud at 80_000_000MHz !
:ser_loop               rcr     ser_bitbuf, #1 WC
                        muxc    outa, TX
                        waitcnt ser_time, #30            '30 clock cycles == approx 2_666_667 baud at 80_000_000MHz ! 
                        djnz    ser_bitcount, #:ser_loop
SERIAL_SEND_BYTE_ret    ret
TX                      long    |< 4          
ser_time                res     1
ser_bitcount            res     1
ser_bitbuf              res     1
byte_to_send            res     1
                        fit
As long as you have a 5MHz external crystal on the Prop then you should have something pretty close to 2666667 Baud serial output on pin P4 (crystal accuracy does matter at these speeds!).  If not then you'll want to change the "#30" constants to alter the baud rate (keep both values the same and you'll be fine) to compensate for your chosen clock speed.Studious observers might realise that I'm aiming for minimal code-space usage. This code is pretty compact but I think I can do better.
In fact I think I can reach much faster Baud rates. This code is limited by the waitcnt instruction, which is a little cumbersome when one is trying to wring out every last instruction cycle from a Cog.
By using one or both of a Cog's Counter features (CNTA and CNTB), it might be possible to get something close to 18 MBit of UART speed! This will be at the expense of code size though.
It is interesting to note that Mr Nyquist's observations determine that TX and RX do not necessarily share the same theoretical maximum baud rate. TXing is stateless (effectively) but RXing is stateful because we need to be able to notice edge transitions and compare them to the bit rate we are expecting. Even if I can hammer out TX rates of 18MHz, I'll probably be limited to RX rates of about a quarter of that, maybe less.
Science!