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

1. ## Re: How to make the PST faster than 115,200 bps?

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

Code:
```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)```

2. ## Re: How to make the PST faster than 115,200 bps?

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.

3. ## Re: How to make the PST faster than 115,200 bps?

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?

Originally Posted by Dave Hein
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.

4. ## Re: How to make the PST faster than 115,200 bps?

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 :

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 :

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

Code:
```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

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

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

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

1165520

697088
Value 1: 1
Value 2: 2
Value 3: 3
Value 4: 4
Value 5: 5
Value 6: 6
Value 7: 7
}```

5. ## Re: How to make the PST faster than 115,200 bps?

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.

6. ## Re: How to make the PST faster than 115,200 bps?

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?

Code:
```PUB main

ser.start(31, 30, 0, 1_000_000)
waitcnt(clkfreq*3+cnt)

RunTest(@teststr)

repeat

PUB RunTest(ptr) | len, start, stop

len := strsize(ptr)

start := cnt
ser.txblock(ptr, len)
stop := cnt
ser.dec(start)
ser.tx(13)```

7. ## Re: How to make the PST faster than 115,200 bps?

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)

8. ## Re: How to make the PST faster than 115,200 bps?

Originally Posted by pjv
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.

9. ## Re: How to make the PST faster than 115,200 bps?

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?

10. ## Re: How to make the PST faster than 115,200 bps?

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"?

11. ## Re: How to make the PST faster than 115,200 bps?

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.

Originally Posted by Tracy Allen
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"?

12. ## Re: How to make the PST faster than 115,200 bps?

Originally Posted by turbosupra
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?
Yes, the overhead of calling the Spin tx method one byte at a time will limit you to less than 125000bps. If you do anything else in the loop is slows it down even more, so 53000bps is a typical rate.

I want to make it clear that in my test program I am only transmitting and not receiving anything. If I would have received a keystroke during the test it would have messed up the serial output since FDS is not capable of full-duplex 1mbps. Peter's driver would be a good choice for high-rate full-duplex operation, or using a single port in the 4-port serial object would work also.

13. ## Re: How to make the PST faster than 115,200 bps?

Hi TurboSupra;

Sorry to hi-jack your thread here, but there are some serious issues or misconceptions that I would like to expound on for a bit. It all relates to higher speed serial communications, and the tests that Dave Hein has run.

Dave, please understand that my comments here are totally intended to be in good faith, and no ill will is intended, but my belief is that the test results you are basing your statemants on are seriously flawed.

Firstly, baud rate and throughput are two different things. one cannot calculate the baud rate by dividing the total number of bits sent, by the time it takes the send them. That does not allow for any possible inter-character time. Baud rate is simply the inverse of the shortest signalling time element.

Secondly the method of time measurement in your test is somehow incorrect. In running your "FOX" test at 115200 baud, (screen shots 003,004) it reports 69 characters in 927 usec. The blue oscilloscope cursor indicates that it takes 6.73 msec.; quite a difference.

So obviously the (incorrect) "baud rate" calculation is also reported in error.

Next I ran the test at 1,000,000 bits per second, and the scope (screens 005,006,007) could not reliably decode the data sent because some of the bits were quite a ways from the expected 1 usec duration. In fact, varying from typically 900 nanosec to 1100 nanosec (008..012), with the occasional 2000 nanosec thrown in. So, then setting the scope to capture for 800,000 baud, allowed me to at least catch some of the data stream.

For clarity I added a bit-clock toggle (blue trace) to the assembler part of the code to output where the bit edges were expected to land.

Then I changed the driver to the one I had modified for "improvement", and, it being based on the same original "FullDuplexSerial" object from long ago, was flawed with the same bit-width issues. As a result, though it is improved, as I stated in its release, it still is not really op to snuff for reliable fast comms... 460800 should generally be OK.

It surprises me that people are actually using the FDS driver at high speed..... it simply does not work reliably over 460800, and even that is "iffy". I suspect that some may be getting away with it if they alo use that same driver for receiving the data. The receive routine uses the same timing mechanism, and perhaps the transmit and receive timing errors are aligned, and disappear. Not so when talking to a differt family of devices, such as evidenced by my oscilloscope captures.

Again, please take these observations and comments in a positive view as I'm looking to add to the general forum knowledge base. So thanks for listening.

Cheers,

Peter (pjv)

14. ## Re: How to make the PST faster than 115,200 bps?

I gave up on attempting to do high speed serial commas with FDS. After about 380400 bps,(IIRC) even with tweaked versions, it was not reliable. I changed hardware to the the FTDI 245, as I had the pins to spare. Wrote a binary compatible version of FDS for it, and never has an issue again. I use it to send DMX 512 data to the prop from a PC. I verify each frame sent to the prop. It is sent at 3Mbps. The code is in my sig.

15. ## Re: How to make the PST faster than 115,200 bps?

Peter, thanks for your explanation. The "baud rate" value I compute in my test program was an attempt at expressing the data transfer rate in terms of a serial baud rate. It would be clearer if I just displayed the number of bytes divided by time. I used FDS because it is in the Spin library. I didn't have much time to spend on this code so I haven't tried your serial driver or the 4-port serial driver yet. I'll do that if I get a chance this weekend.

16. ## Re: How to make the PST faster than 115,200 bps?

So is a better solution to take hub ram addresses and pass them to a PASM loop that reads those addresses and writes the serial bits?

17. ## Re: How to make the PST faster than 115,200 bps?

Hi Dave;

I fully understand your intent, and I agree that a throughput number of bytes per second would be a measure of combined baud rate as well as effectiveness of the Spin program that feeds the assemby byte driver.

As for my "improved" version, it still has problems at high speed because it is based on the standard FDS code that was created years ago. What I should do, is spend some time to re-write that completely.... it is quite likely that the offending pieces that cause the variance in bit timing can be rectified..

Cheers,

Peter (pjv)

18. ## Re: How to make the PST faster than 115,200 bps?

You mean buffer the data and send it when ready... Yes. IIRC, same advice given on one of your similar posts.