Shop OBEX P1 Docs P2 Docs Learn Events
How to make the PST faster than 115,200 bps? — Parallax Forums

How to make the PST faster than 115,200 bps?

turbosupraturbosupra Posts: 1,088
edited 2012-04-27 21:07 in Propeller 1
I've tried going beyond 115200 and not had success, has anyone done this besides viewport which I believe is around a gbps.

Does something in the actual object need to be modified as well? I'd like to go up to 250000 or 460800, I need to compare a bunch of data all at once to chase down an issue I'm having.
«1

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-04-24 11:47
    PST is based on the FullDuplexSerial driver for its serial I/O and this is not designed to run faster than 230KBps. ViewPort uses a specially designed serial driver to get the speeds it uses. FullDuplexSerial4Port in the ObEx can handle speeds up to 750KBps (see the documentation in the program) with a single serial port, so you might try that.
  • JonnyMacJonnyMac Posts: 8,912
    edited 2012-04-24 12:02
    If you're only doing output -- that is, you don't need to send keystrokes back in -- then you can use a half-duplex transmit-only driver. I've attached (an old) one that I have used for my own projects. As it only does one thing it can run quite fast.
  • SRLMSRLM Posts: 5,045
    edited 2012-04-24 12:05
    Just be aware that anything above 57600 is too fast for spin programs. IE, the spin program cannot put the data in the buffer fast enough to make use of the higher speed (even if the strings are already in the hub...). So it's pointless to run it faster, unless you're writing your own assembly.

    For the computer side, try using a different terminal program.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-24 12:45
    I am using PASM to write values and spin has it's own communication loop/cog where it calls the PASM object and reads the PASM values and prints it to screen. Do you think it'll go faster than 57600 this way?

    Is it still too slow, maybe I'll have to try and write a PASM com program?
    SRLM wrote: »
    Just be aware that anything above 57600 is too fast for spin programs. IE, the spin program cannot put the data in the buffer fast enough to make use of the higher speed (even if the strings are already in the hub...). So it's pointless to run it faster, unless you're writing your own assembly.

    For the computer side, try using a different terminal program.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-24 12:46
    Sweet, thanks Jon!
    JonnyMac wrote: »
    If you're only doing output -- that is, you don't need to send keystrokes back in -- then you can use a half-duplex transmit-only driver. I've attached (an old) one that I have used for my own projects. As it only does one thing it can run quite fast.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-24 13:09
    I believe I read a little on this, it uses 4 pins right? Am I still limited by the speed of spin with this object?
    Mike Green wrote: »
    PST is based on the FullDuplexSerial driver for its serial I/O and this is not designed to run faster than 230KBps. ViewPort uses a specially designed serial driver to get the speeds it uses. FullDuplexSerial4Port in the ObEx can handle speeds up to 750KBps (see the documentation in the program) with a single serial port, so you might try that.
  • SRLMSRLM Posts: 5,045
    edited 2012-04-24 13:18
    The PASM cog driver is plenty fast enough (at least in the 4 port object, which I use). It's just that the spin TX routine is too slow. It is this routine that puts the characters into the TX buffer that the PASM driver then reads, and it is this routine that limits the speed. If you have an assembly program to put data into the TX buffer then you don't need to worry about the limitations.

    In any case, FullDuplexSerialPlus and FullDuplexSerial4Port both use only two pins per serial coms: one TX pin and one RX pin. With the four port, you need a pair for each port. I don't know if ViewPort uses 4 pins, but I doubt it: the FTDI chip has only RX and TX.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-24 14:05
    The main speed bottleneck is the Spin code, as SRLM said. There is quite a bit of overhead when calling the tx or rx routine. In a tight loop that calls the rx routine and writes into a byte buffer, the Spin code runs at about 125,000 bits/second on an 80 MHz processor. If you do anything else in the loop it will slow it down even more. In my YMODEM receive program I receive 1 KB packets, and store them in a buffer. The loop also does time-out detection, so this limits it to about 57,600. I'm able to run at 115,200 by using a 512-byte buffer in FDS. The buffer is just below full after receiving 1 KB of data at 115,200.

    I wrote an rxblock routine that is able to handle 2 mega-bits/second. It uses bytemove to move data from the FDS receive buffer to a data buffer. I plan on integrating this into my YMODEM code at some point. A similar technique could be used for transmit to speed that up also.
    PUB rxblock(ptr, num) | num1, num2, rxhead
      rxhead := rx_head
      if rxhead => rx_tail
        num1 := rxhead - rx_tail
        num2 := 0
      else
        num1 := 128 - rx_tail
        num2 := rxhead
      if num1 > num
        num1 := num
        num2 := 0
      elseif num1 + num2 > num
        num2 := num - num1
      bytemove(ptr, rx_buffer + rx_tail, num1)
      bytemove(ptr + num1, rx_buffer, num2)
      result := num1 + num2
      rx_tail := (rx_tail + result) & 127
    

    EDIT: This routine handles a buffer size of 128. Other sizes can be handled by changing the values of 128 and 127 to the buffer size and the mask. The buffer size must be a power of 2. The return value indicates the number of bytes read, which is between 0 and num.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-04-24 14:07
    SRLM wrote: »
    Just be aware that anything above 57600 is too fast for spin programs. IE, the spin program cannot put the data in the buffer fast enough to make use of the higher speed (even if the strings are already in the hub...). So it's pointless to run it faster, unless you're writing your own assembly.

    For the computer side, try using a different terminal program.

    I just timed a program at two different bauds.

    At 57600 baud the loop to display the PlayStation 2 controller information (after removing any waitcnt statements) took 47.8 million clock cycles. At 115200 baud the same loop only took 2.99 million clock cycles.

    I think 57600 is still below the maximum useful baud rate for the Prop (using Spin).

    Edit: I think 115200 is approaching the limit for Spin. I changed the baud to 230400 and the loop time changed to 2.89 million cycles. Not much better than the time at 115200. The loop time didn't change when I increased the baud to 250,000.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-24 14:23
    Duane, How many bytes did you print out? I'm guessing it was around 400 bytes, correct?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-04-24 14:42
    Dave Hein wrote: »
    Duane, How many bytes did you print out? I'm guessing it was around 400 bytes, correct?

    Actually, much of the screen isn't printed each loop.

    I counted 285 characters displayed each loop.
  • pjvpjv Posts: 1,903
    edited 2012-04-24 15:14
    Turbosupra;

    Some while ago I made some improvements to the Full Duplex Serial driver to speed it up a bit. The following thread speaks about it.

    http://forums.parallax.com/showthread.php?126569-Fast-Full-Duplex-Serial-to-921600

    Somewhere in this forum I have also posted a 5 Megabit/sec assembly based full duplex driver, taking data from/to a hub buffer of any desired size. Would take some digging to find it I suppose. Be happy to do that if it is of interest to you.

    Cheers,

    Peter (pjv)
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-24 15:47
    Duane Degn wrote: »
    I counted 285 characters displayed each loop.
    That works out to about 80,000 bits/second, which is consistent with the other numbers we've seen.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-24 19:50
    Thank you, this should make for good reading tomorrow!


    pjv wrote: »
    Turbosupra;

    Some while ago I made some improvements to the Full Duplex Serial driver to speed it up a bit. The following thread speaks about it.

    http://forums.parallax.com/showthread.php?126569-Fast-Full-Duplex-Serial-to-921600

    Somewhere in this forum I have also posted a 5 Megabit/sec assembly based full duplex driver, taking data from/to a hub buffer of any desired size. Would take some digging to find it I suppose. Be happy to do that if it is of interest to you.

    Cheers,

    Peter (pjv)
  • LawsonLawson Posts: 870
    edited 2012-04-25 11:13
    pjv wrote: »
    Turbosupra;

    Some while ago I made some improvements to the Full Duplex Serial driver to speed it up a bit. The following thread speaks about it.

    http://forums.parallax.com/showthread.php?126569-Fast-Full-Duplex-Serial-to-921600

    Somewhere in this forum I have also posted a 5 Megabit/sec assembly based full duplex driver, taking data from/to a hub buffer of any desired size. Would take some digging to find it I suppose. Be happy to do that if it is of interest to you.

    Cheers,

    Peter (pjv)

    I'd be VERY interested in a 2Mbps full duplex driver. Most of the stuff I make hangs off a FTDI USB adaptor, and I have times when it'd be far easier to blast out an ascii .csv data file over the serial port at 2Mbps than switch to a packed binary format that needs decoding software on the PC. (though it sounds like I'd need to make some ASM formatting code [and a faster terminal program] to truly use this speed.)

    You can search for your own posts if you click on you name in the top left of a post. Also you can see everything you've ever attached to a forum post in the dialog to attach a new file.

    Lawson
  • pjvpjv Posts: 1,903
    edited 2012-04-25 18:15
    Hi Lawson;

    Thanks for the tip on how to quickly examine all posts I have made. It was a great help to track down the 5Megabit/sec routines I was referring to. The link is here.

    http://forums.parallax.com/showthread.php?120125-5Mbit-sec-ASCII-streaming-from-to-Hub-RAM

    Holler if you have any questions.

    Cheers,

    Peter (pjv)
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-25 23:12
    Hi Peter,

    Looking at your code, I'm only a PASM novice and a little overwhelmed trying to follow the logic, do you think you could give an example of how to use it?


    CON
            _clkmode        = xtal1 + pll16x
            _xinfreq        = 5_000_000
    
    PUB  main
         cognew(@MainProg, 0)
    
    CON
    ScopeBit0       = 1 <<0
    ScopeBit1       = 1 <<1
    ScopeBit2       = 1 <<2
    ScopeBit3       = 1 <<3
    ScopeBit4       = 1 <<4
    ScopeBit5       = 1 <<5
    ScopeBit6       = 1 <<6
    ScopeBit7       = 1 <<7
    ScopeBit8       = 1 <<8
    ScopeBit9       = 1 <<9
    
    RxSearchLong    = 500                                   'how long to search for first received START
    RxSearchShort   = 8                                     'end of message time-out....how long to search for following STARTs 
    RxSampleTime1   = ScopeBit1                             'show when Rx sample is taken 
    
    RxHubAddrExp    = 11                                    'hub receive buffer... arbitrarily at $800
    
    'RxByteExp       = 0                                     'receive 1 byte
    RxByteExp      = 4                                      'receive 16 bytes
    'RxByteExp      = 8                                      'receive 256 bytes
    'RxByteExp      = 14                                     'receive 16K bytes
    'RxByteExp      = 16                                     'receive 64K bytes
    
    
    TxLine4         = ScopeBit4                             'transmit data line
    TxCommence5     = ScopeBit5                             'show duration transmission active
    TxBitTime6      = ScopeBit6                             'show bit duration.... actual position is 2 instructions later
    
    TxHubAddrExp    = 11                                    'hub transmit buffer... arbitrarily at $800
    
    'TxByteExp      = 0                                      'dump 1 byte
    TxByteExp      = 4                                      'dump 16 bytes
    'TxByteExp      = 8                                      'dump 256 bytes
    'TxByteExp      = 14                                     'dump 16K bytes
    'TxByteExp      = 16                                     'dump 64K bytes
    
    
    
    DAT
    'MainProg ==============================================
    'Fast serial ASCII receiver dumps to main ram at 5 Mbits/sec (2 usec per byte) in one continuous stream
    'Then re-transmits the received dump for oscilloscope confirmation of data
    
                  org       0
    MainProg      mov       dira,#$FE                       'port bit 0 input
                  or        outa,#TxLine4                   'set transmit uart to stop condition
    
    ReceiveInit   mov       HubAddr,#1
                  shr       HubAddr,#RxHubAddrExp           'start dump into main   
                  mov       ByteCtr,#1
                  shl       ByteCtr,#RxByteExp              'read selected number of receive bytes
                  mov       SearchCtr,#RxSearchLong         'how long to wait for receive data before returning
                  call      #HubRx5Mbs              wz      'clear zero and for start in receive stream from other prop
    
    TransmitInit  mov       HubAddr,#1
                  shr       HubAddr,#TxHubAddrExp           'start dump from main  
                  mov       ByteCtr,#1
                  shl       ByteCtr,#TxByteExp              'dump selected number of transmit bytes
                  xor       outa,#TxCommence5               'show transmit string commence pulse on scope
                  call      #HubTx5Mbs              wz      'clear zero and send the stream
                  jmp       #ReceiveInit                    'do it again
                  
    
    'Receive Routine =======================================
    HubRx5Mbs     rdbyte    Shifter,#0                      'sync hub
                  sub       HubAddr,#1                      'pre-dec address
                  nop                                       'set hub sweet spot
    StartSearch   jmp       #SrchForStart                   'entry point
    OneBit        mov       SearchCtr,#RxSearchShort        'load number of loops to search for        nop
    FirstBit      and       RxLine0,ina             wc,nr   'parity sample into carry              
                  rcr       Shifter,#1                      'pull sample into shifter
                  djnz      BitCtr,#OneBit                  'test for 7 bits done
                  and       RxLine0,ina             wc,nr   'parity sample bit 8 into carry              
                  rcr       Shifter,#25                     'pull sample into shifter and bit0 justify
                  wrbyte    Shifter,HubAddr                 'save byte in main ram buffer
                  djnz      ByteCtr,#SrchForStart           'track received bytes
                  jmp       #HubRx5Mbs_ret                  'exit on all received            '
    SrchForStart  and       RxLine0,ina             wc,nr   'test for low start condition
            if_c  djnz      SearchCtr,#SrchForStart wz      '2x oversample start bit... zero on time-out
                  mov       BitCtr,#7                       'how many bits... 8th bit is unrolled
                  add       HubAddr,#1                      'next address
            if_nz jmp       #FirstBit                       'look to receive a byte
    HubRx5Mbs_ret ret                                       'exit on search timed out
    
    
    'Transmit Streamer Routine ============================
    TxOneBit      xor       outa,#TxBitTime6                'optional scope bit time indicator.. replace with nop
                  shr       Shifter,#1              wc      'get bit
                  muxc      outa,#TxLine4                   'output it
                  djnz      BitCtr,#TxOneBit                'test for 8 bits done
                  sub       ByteCtr,#1              wz      'keep track of how many done
    HubTx5Mbs     or        outa,#TxLine4                   'stop condition
                  rdbyte    Shifter,HubAddr                 'get value from Hub RAM
    'optionally   rdbyte    Shifter,HubAddr          wz      'get value from Hub RAM and exit on zero terminated string
                  add       HubAddr,#1                      'next byte address
    OneByte if_nz andn      outa,#TxLine4                   'start condition
                  mov       BitCtr,#8                       'how many bits
            if_nz jmp       #TxOneBit +1                    'loop for another byte
    HubTx5Mbs_ret ret                                       'done
    
    RxLine0       long      1                               'receive pin mask... Pin0
    HubAddr       long      0                               'location in main RAM
    ByteCtr       long      0                               'how many bytes to receive/transmit
    SearchCtr     long      0                               'keep track of search time for START condition
    BitCtr        long      0                               '
    Shifter       long      0                               '
       
    
  • frank freedmanfrank freedman Posts: 1,974
    edited 2012-04-25 23:44
    turbosupra wrote: »
    I've tried going beyond 115200 and not had success, has anyone done this besides viewport which I believe is around a gbps.

    Does something in the actual object need to be modified as well? I'd like to go up to 250000 or 460800, I need to compare a bunch of data all at once to chase down an issue I'm having.

    Just an aside since a fast scan of this thread revolves around hacking the serial object without mentioning some other limitstions.

    You should take a look at the RS-232 standards regarding handshake and the fact that you must derate the speed as the line distance increases. Since your project seems to be instrumenting and controlling an engine, in another thread, depending on how you lay out your comms may affect the speeds you can communicate to your data collection system (laptop?) You may need to implement hardware rts/cts or software (xon/xoff) so that you don't overflow and get giberish.

    Although it costs more it may be worth going CAN for the speed, increased distance and noise immunity inherent in CAN. NXP or TI may be a good source of sample devices. I may be mis-crediting, but it seems Jonnymac has threads regarding CAN as well. All of the OEM medical imaging systems I work with use CAN for high-speed non-real time data.

    FF
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-25 23:53
    I went through this code, how would you suggest I test it with spin, I noticed in your last response to that post (quoted below) that no one ever tested it for you with spin.

    I'd like to do that, but what are you looking for me to test with? Just a loop that does a cnt print screen? Am I missing something? They seem pretty close?

    regularPST wrote:
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008
    73040
    73008

    fastPst wrote:
    80080
    69520
    70528
    80080
    69520
    70528
    80080
    69520
    70528
    80080
    69520
    70528
    80080
    69520
    70528

    pjv wrote: »
    Turbosupra;

    Some while ago I made some improvements to the Full Duplex Serial driver to speed it up a bit. The following thread speaks about it.

    http://forums.parallax.com/showthread.php?126569-Fast-Full-Duplex-Serial-to-921600

    Cheers,

    Peter (pjv)
    I have now tested the assembly portion for speed, and can confirm:

    The original FDX assemby ran at best -no data, just searching for a start bit- at 900 nanoseconds for an Rx/Tx ping-pong.

    The minor mods I made now have it running at 500 nano seconds for a ping-pong.

    So now it should be able to find that start bit whenever it comes. I have not actually set up an SX to pump it yet, so don't know what the Spin part does when an actual character is received. The 16 byte buffer will fill in 16-ish uSec, and that is probably a stretch for Spin.

    Hopefully someone out there can actually test this.

    Cheers,

    Peter (pjv)
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-26 08:38
    Alright, I must be doing something wrong with my testing procedure, I changed the parent object a little to the code posted below, the other code (in the previously attached zip file) is still the same


    I'm getting the same results against PST, FDS and FastFDS?
    75376 or 0.0009422 seconds average, FastFDS was set to 921600, the others to 115200.

    FastFDS

    80080
    69520
    76528
    80080
    69520
    76528
    80080



    FDS

    76528
    80080
    69520
    76528
    80080
    69520
    76528
    80080
    69520



    PST

    80080
    69520
    76528
    80080
    69520
    76528
    80080
    69520
    76528
    80080

    CON
      _CLKMODE      = XTAL1 + PLL16X                        
      _CLKFREQ      = 80_000_000
      
    
    VAR
    
    
      long  testPstStack[100]
      long  testFastPstStack[100]
      long  testFastFdsStack[100]
    
    
    OBJ
    
      pst : "Parallax Serial Terminal"
      fds : "FullDuplexSerial"
      fastpst : "FastFullDuplexSerial"
    
    PUB Main
    
      pst.start(115200)
      cognew(testPst, @testPstStack)
    
      'fastpst.start(31,30,0,921600)
      'cognew(testFastPst, @testFastPstStack)
    
      'fds.start(31,30,0,115200)
      'cognew(testFastFds, @testFastFdsStack)
      
      
     
    PUB testPst | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        pst.dec(currCnt - prevCnt)
        pst.char(13)
    
    
    
    
    PUB testFastPst | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        fastpst.dec(currCnt - prevCnt)
        fastpst.tx(13)
        'fastpst.char(13)
    
    
    
    PUB testFastFds | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        fds.dec(currCnt - prevCnt)
        fds.tx(13)
        'fastpst.char(13)
         
    
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-26 09:52
    You're timing how long it takes to do the dec routine. This has virtually nothing to do with the actual serial output unless you run at a very low baud rate. You would get better measurements if you printed a string using the str method. However, this will max out around 125,000 bps. As I said a couple of days ago, the limiting factor is the Spin code.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-26 10:25
    Hi Dave,

    I remember you writing that and that has been lingering in the back of my head ever since you did. The way this object was presented, it seemed as if this driver had a way around that.

    Would my com loop have to run completely in PASM to get faster than 125k bps?

    Dave Hein wrote: »
    You're timing how long it takes to do the dec routine. This has virtually nothing to do with the actual serial output unless you run at a very low baud rate. You would get better measurements if you printed a string using the str method. However, this will max out around 125,000 bps. As I said a couple of days ago, the limiting factor is the Spin code.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-26 12:54
    I don't know if this was any better of a test, if so, the quickest for each test are bolded.

    jm_txserial won 2 of the tests (seems to be faster with small values or numbers followed by carriage returns)
    FastFullDuplexSerial won 2 of the tests (seems to be faster with long strings)

    Now, how to correlate this to bps?





    Test bits sent :
    "string " + (previous cnt - current cnt) + carriage return

    Fast Full Duplex Serial (by PJV) - 126176 clk cycles between loops
    Full Duplex Serial - 126176 clk cycles between loops
    Parallax Serial Terminal - 126176 clk cycles between loops
    jm_txserial - 115872 clk cycles between loops





    Test bits sent :
    "string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd " + "string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd " + (previous cnt - current cnt) + carriage return

    Fast Full Duplex Serial (by PJV) 832784 - clk cycles between loops
    Full Duplex Serial - 1175120 clk cycles between loops
    Parallax Serial Terminal - 1173520 clk cycles between loops
    jm_txserial - 1165520 clk cycles between loops





    Test bits sent :
    "Value 1: " + "1" + "Value 2: " + "2" + "Value 3: " + "3" + "Value 4: " + "4" + "Value 5: " + "5" + "Value 6: " + "6" + "Value 7: " + "7" + (previous cnt - current cnt) + carriage return

    Fast Full Duplex Serial (by PJV) - 751504 clk cycles between loops
    Full Duplex Serial - 751504 clk cycles between loops
    Parallax Serial Terminal - 751504 clk cycles between loops
    jm_txserial - 697088 clk cycles between loops





    Test bits sent :
    adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfa
    sfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfa
    sdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdf
    asfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasf
    asdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfad
    fasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfa
    dfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadf
    adfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfad
    fadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfas
    dfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfas
    dfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfa
    dfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfa
    sdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfa
    dsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfa
    dsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfa
    sdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
    adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfa
    sfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfa
    sdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdf
    asfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasf
    asdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfad
    fasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfa
    dfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadf
    adfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfad
    fadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfas
    dfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfas
    dfasdfadfadfadfadfadfasfasdfasfasdfasfd adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd+ (previous cnt - current cnt) + carriage return

    Fast Full Duplex Serial (by PJV) - 17520096 clk cycles between loops
    Full Duplex Serial - 26043840 clk cycles between loops
    Parallax Serial Terminal - 25679456 clk cycles between loops
    jm_txserial - 25830368 clk cycles between loops




    CON
    
      _CLKMODE      = XTAL1 + PLL16X                        
      _CLKFREQ      = 80_000_000
    
    
    VAR
    
      long  testPstStack[200]
      long  testFastPstStack[200]
      long  testFastFdsStack[200]
      long  testJmHdsStack[200]
    
    
    OBJ
      
      fastFds : "FastFullDuplexSerial"
      fds : "FullDuplexSerial"
      pst : "Parallax Serial Terminal"
      jmHds : "jm_txserial" 
    
    PUB Main
    
      'fastFds.start(31,30,0,921600)
      'cognew(testFastFds, @testFastPstStack)
    
      'fds.start(31,30,0,115200)
      'cognew(testFds, @testFastFdsStack)
    
      'pst.start(115200)
      'cognew(testPst, @testPstStack)
    
      'jmHds.start(30,115200)
      'cognew(testJmHds, @testJmHdsStack)
     
    PUB testFastFds | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        fastFds.str(string("Value 1: "))
        fastFds.dec(1)
        fastFds.tx(13)
        fastFds.str(string("Value 2: "))
        fastFds.dec(2)
        fastFds.tx(13)
        fastFds.str(string("Value 3: "))
        fastFds.dec(3)
        fastFds.tx(13)
        fastFds.str(string("Value 4: "))
        fastFds.dec(4)
        fastFds.tx(13)
        fastFds.str(string("Value 5: "))
        fastFds.dec(5)
        fastFds.tx(13)
        fastFds.str(string("Value 6: "))
        fastFds.dec(6)
        fastFds.tx(13)
        fastFds.str(string("Value 7: "))
        fastFds.dec(7)
        fastFds.tx(13)   
        fastFds.dec(currCnt - prevCnt)
        fastFds.tx(13)
    
      {
        string 126176
    
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        832784
    
        Value 1: 1
        Value 2: 2
        Value 3: 3
        Value 4: 4
        Value 5: 5
        Value 6: 6
        Value 7: 7
        751504
      }
    
    PUB testFds | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        fds.str(string("Value 1: "))
        fds.dec(1)
        fds.tx(13)
        fds.str(string("Value 2: "))
        fds.dec(2)
        fds.tx(13)
        fds.str(string("Value 3: "))
        fds.dec(3)
        fds.tx(13)
        fds.str(string("Value 4: "))
        fds.dec(4)
        fds.tx(13)
        fds.str(string("Value 5: "))
        fds.dec(5)
        fds.tx(13)
        fds.str(string("Value 6: "))
        fds.dec(6)
        fds.tx(13)
        fds.str(string("Value 7: "))
        fds.dec(7)
        fds.tx(13)
        fds.dec(currCnt - prevCnt)
        fds.tx(13)
      
      {
        string 126176
    
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        1175120
    
        Value 1: 1
        Value 2: 2
        Value 3: 3
        Value 4: 4
        Value 5: 5
        Value 6: 6
        Value 7: 7
        751504
      }
    
    PUB testPst | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        pst.str(string("Value 1: "))
        pst.dec(1)
        pst.char(13)
        pst.str(string("Value 2: "))
        pst.dec(2)
        pst.char(13)
        pst.str(string("Value 3: "))
        pst.dec(3)
        pst.char(13)
        pst.str(string("Value 4: "))
        pst.dec(4)
        pst.char(13)
        pst.str(string("Value 5: "))
        pst.dec(5)
        pst.char(13)
        pst.str(string("Value 6: "))
        pst.dec(6)
        pst.char(13)
        pst.str(string("Value 7: "))
        pst.dec(7)
        pst.char(13)
        pst.dec(currCnt - prevCnt)
        pst.char(13)
    
      {
        string 126176
    
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        1173520
    
        Value 1: 1
        Value 2: 2
        Value 3: 3
        Value 4: 4
        Value 5: 5
        Value 6: 6
        Value 7: 7
        751504
      }
    
    PUB testJmHds | prevCnt, currCnt
    
      repeat
    
        prevCnt := currCnt
        currCnt := cnt
        jmHds.str(string("Value 1: "))
        jmHds.dec(1)
        jmHds.tx(13)
        jmHds.str(string("Value 2: "))
        jmHds.dec(2)
        jmHds.tx(13)
        jmHds.str(string("Value 3: "))
        jmHds.dec(3)
        jmHds.tx(13)
        jmHds.str(string("Value 4: "))
        jmHds.dec(4)
        jmHds.tx(13)
        jmHds.str(string("Value 5: "))
        jmHds.dec(5)
        jmHds.str(string("Value 6: "))
        jmHds.dec(6)
        jmHds.tx(13)
        jmHds.str(string("Value 7: "))
        jmHds.dec(7)
        jmHds.tx(13)
        jmHds.tx(13)
        jmHds.dec(currCnt - prevCnt)
        jmHds.tx(13)
        
      {
        string 115872
    
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        string adfasdfadsfadsfasdfadfasdfasdfadfadfadfadfadfasfasdfasfasdfasfd
        1165520
    
       697088
        Value 1: 1
        Value 2: 2
        Value 3: 3
        Value 4: 4
        Value 5: 5
        Value 6: 6
        Value 7: 7
      }
    
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-26 20:23
    I added a txblock method to FDS, and I'm able to get an effective transmit rate of over 500,000 baud when the actual baud rate is at 1,000,000. My test code is attched below. The txblock method calls txchunk, which uses bytemove to copy the data from the data buffer to the transmit buffer.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-26 21:44
    That's pretty awesome, thanks Dave!

    I think I understand what you meant earlier about spin being the limitation. I tried your MIT license in a spin loop (modified your code with the section posted below) and the best I could get from cnt measurement to cnt measurement was 2530592 clk cycles 0.0316324 seconds, which is about 53110 bps, backing up what you said earlier. I believe you said nothing could be done about this if spin were used.

    Could something be written where when a program is loaded, a bunch of spin long addresses are passed to a pasm com cog that could loop and write their values to the terminal? And therefore effectively circumvent the spin loop bottleneck?

    PUB main
    
      ser.start(31, 30, 0, 1_000_000)
      waitcnt(clkfreq*3+cnt)
    
      RunTest(@teststr)
      RunTest(@license)
    
      repeat
        RunTest(@license)
      
    
    PUB RunTest(ptr) | len, start, stop
    
      len := strsize(ptr)
    
      start := cnt
      ser.txblock(ptr, len)
      stop := cnt
      ser.dec(start)
      ser.tx(13)
    
  • pjvpjv Posts: 1,903
    edited 2012-04-26 22:17
    Hi Supra;

    I took your code and ran it on one of my QuickStart boards while my scope was attached to capture the data streams.

    The scope is set to decode the streams into ascii (or hex) characters, and I have 5 screen shots for you.

    The first (000) is your standard FullDuplex driver at 115200. Notice the 100-ish usec space between characters, and 300 odd usec between packets.

    The second (001) is the FastFullDuplex driver at 921600, using the same 200 usec horizontal resolution. The charactes appear as merely horizontal "ticks", with a varying 100 to 200 usec of time between them. There is insufficient resolution for the ascii decoder to display the text. As pointed out earlier in the thread by Dave and others, this idle time between characters is the time consumed by Spin to process and render the data.

    The third screen (002) is the same data, but zoomed (the bracketed section from the upper non-zoomed part) to 40 usec per division. The individual characters are now clearly visible.

    The fourth (003) is again the same data, but the bracketed section is moved over a couple of characters.

    The last shot (004) is again the same data, but zoomed to 20 usec, and displaying the characters as hex instead of ascii. Also I forgot to turn the capture details off, so the scope menu and parameters are visible.

    As you can see, the Fast Duplex (transmitter at least) works at the specified speed; it is Spin that throttles things so markedly. If you need truly fast communications, Spin cannot be part of your rendering loop. You will need to capture the data into a file in hub, then dump it out via an assembler routine.

    If assembler is not part of your repertoire, then 115200 is about the fastest that Spin can manage.

    Hope this helps.

    Cheers,

    Peter (pjv)
    480 x 234 - 6K
    480 x 234 - 5K
    480 x 234 - 6K
    480 x 234 - 6K
    480 x 234 - 7K
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-04-27 07:14
    pjv wrote: »
    If assembler is not part of your repertoire, then 115200 is about the fastest that Spin can manage.
    Peter, it appears that you have not read any of my posts. Here's a modified version of my previous code that uses a constant to define the size of the FDS buffers. This version uses a buffer size of 64. The test program transmit a short string, and a long string. The effecitve transmit speed of the large string is 750,000 baud. The smaller string is actually transferred at a rate greater than 1 mega-baud because the transmit buffer is empty initially.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-27 07:34
    Hi Dave,

    I tested your program and saw as you stated, am I correct about the reason when it looped inside of a spin loop it would only update at 53000bps?
  • Tracy AllenTracy Allen Posts: 6,656
    edited 2012-04-27 09:26
    Turbo,
    In scanning this thread I was left wondering what you are trying to accomplish. The first post says, "I'd like to go up to 250000 or 460800, I need to compare a bunch of data all at once to chase down an issue I'm having." It appears from what follows that you only need to transmit data, not receive. What means, "compare a bunch of data"?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-04-27 10:00
    I have actually found my issue, but would like to be able to do this in the future if I run into this again.

    A "bunch of data" is technical jargon for longs from different pasm cogs :)

    In a perfect world, I'd have something that was 460800 or 921600, that could send and receive data, the receive would be 2% of the bandwidth (occasional key stroke updates) and the send 98% of the duplex bandwidth. Maybe a PASM object that could be preloaded with an array of longs to read and send? And it could loop and update the values as fast as my heart desired? I would even attempt to write this on my own (if possible) if I were a little better with PASM and had a push in the right direction.
    Turbo,
    In scanning this thread I was left wondering what you are trying to accomplish. The first post says, "I'd like to go up to 250000 or 460800, I need to compare a bunch of data all at once to chase down an issue I'm having." It appears from what follows that you only need to transmit data, not receive. What means, "compare a bunch of data"?
Sign In or Register to comment.