Potential bug in pspDebugSioSetBaud ?
Potential bug in pspDebugSioSetBaud ?
I've discovered an interesting phenomenon while compiling the LUA v0.20 player code.
Since I ran into the problem of lost characters when calling sioRead() in LUA at every baud rate, I have recompiled the LUA source without the call to pspDebugSioSetBaud() that is normally executed within LUA's sioInit().
Interestingly, when pspDebugSioSetBaud() is NOT called, the LUA command works fine (entire string is received). However, when pspDebugSioSetBaud(4800) is called (note that the baud rate is left unchanged from it's default), the situation changes and only the first character is returned by the LUA call to sioRead().
To make things short: Initializing the serial port without calling baud rate adjustment delivers the expected result. As soon as the baud rate command is touched, the character delay/truncated transmission phenomenon is encountered.
I suspect there is a problem in pspDebugSioSetBaud(). Can anyone confirm this?
Since I ran into the problem of lost characters when calling sioRead() in LUA at every baud rate, I have recompiled the LUA source without the call to pspDebugSioSetBaud() that is normally executed within LUA's sioInit().
Interestingly, when pspDebugSioSetBaud() is NOT called, the LUA command works fine (entire string is received). However, when pspDebugSioSetBaud(4800) is called (note that the baud rate is left unchanged from it's default), the situation changes and only the first character is returned by the LUA call to sioRead().
To make things short: Initializing the serial port without calling baud rate adjustment delivers the expected result. As soon as the baud rate command is touched, the character delay/truncated transmission phenomenon is encountered.
I suspect there is a problem in pspDebugSioSetBaud(). Can anyone confirm this?
To illustrate the setBaudBug
If you'd like to test it out yourself, download the zip file below. It contains two versions of the LUA player, one compiled with the call to pspDebugSioSetBaud(4800) and one without. Read the Howto.txt file included in the archive.
www.essentializer.com/BugInSetBaud.zip
www.essentializer.com/BugInSetBaud.zip
There are other reasons why the serial port plays up in LUA.
I have spoken to Shine about this.
The same routine to recieve serial comms in C doesn't work in LUA.
It's very slow, and loses bytes in the transmission.
The only way I achieved good comms was to force the sending station to
send one byte at a time (like a Human tapping on a terminal keyboard)
with a big delay inbetween.
The serial FIFO buffer doesn't seem to work at all in LUA.
Art.
I have spoken to Shine about this.
The same routine to recieve serial comms in C doesn't work in LUA.
It's very slow, and loses bytes in the transmission.
The only way I achieved good comms was to force the sending station to
send one byte at a time (like a Human tapping on a terminal keyboard)
with a big delay inbetween.
The serial FIFO buffer doesn't seem to work at all in LUA.
Art.
Aware of that
I'm aware of your delay circuit and I know that this is one way to fix the problem. But how do you explain that the LUA code actually works fine (without delaying the characters) when pspDebugSioSetBaud is never called?
When the serial port is opened, it's set to 4800 baud. If the port is opened without a call to pspDebugSioSetBaud the FIFO buffer works fine! Try out my code attached to my previous post to see for yourself.
However, even when pspDebugSioSetBaud is called with 4800 as parameter, the FIFO breaks. Technically we should not be changing any registers with this call, since it corresponds to the initial baud rate....
Get my point?
When the serial port is opened, it's set to 4800 baud. If the port is opened without a call to pspDebugSioSetBaud the FIFO buffer works fine! Try out my code attached to my previous post to see for yourself.
However, even when pspDebugSioSetBaud is called with 4800 as parameter, the FIFO breaks. Technically we should not be changing any registers with this call, since it corresponds to the initial baud rate....
Get my point?
You could have..
Yes, you could have but only when using the modified LUA version. 4800 baud without 15 ms character delay is still faster than 38400 baud with 15 ms character spacing.
I'm sure the same thing happens in C as long as PSPSDK is used. I'll try to write a minimal code snippet to demonstrate the effect in C++.
What I think is happening is that setBaud messes up timing registers to some extent and the FIFO buffer get's garbled. So if you send "Hello", the FIFO might look like this: H****l**l*****o, where * denotes an invalid character that will return -1 on read. First read loop might return "H" only. The next time read is executed, the buffer might look like this: **l******o****, thus the first "l" was pushed out of the FIFO by the garbled chars and we'll end up with an incomplete transmission.
So what I'll try to prove the effect is this (pseudo code):
I'll let you know when I'm done with the C-example.
I'm sure the same thing happens in C as long as PSPSDK is used. I'll try to write a minimal code snippet to demonstrate the effect in C++.
What I think is happening is that setBaud messes up timing registers to some extent and the FIFO buffer get's garbled. So if you send "Hello", the FIFO might look like this: H****l**l*****o, where * denotes an invalid character that will return -1 on read. First read loop might return "H" only. The next time read is executed, the buffer might look like this: **l******o****, thus the first "l" was pushed out of the FIFO by the garbled chars and we'll end up with an incomplete transmission.
So what I'll try to prove the effect is this (pseudo code):
Code: Select all
initializeSerial()
// Execute twice: Once before call to setBaud and once after
for i=0 to 1
{
wait for button press{
// let user send a string to the FIFO (e.g. "Hello") and have
// him/her press a button when done
}
// Expect to print "Hello" on first (i==0) run
// and garbled text on second run, after setBaudRate has
// been called below
do{
ch = readChar()
print(ch)
}
while(ch !=-1)
setBaudRate(4800) // According to my theory, this will scew up the FIFO
}
C-Example program to demonstrate setBaud() bug
OK, I'm done writing the example program to demonstrate the bug in pspDebugSioSetBaud(). Guess what? It's exactly as I said. Serial input works fine as long as setBaud is not called. This holds true for all applications based on the PSPSDK, inlcuding LUA.
Get the example application below and see for yourself. Let me see how I can report that bug to our PSPSDK dev team...
http://www.essentializer.com/setBaudBug.zip
Get the example application below and see for yourself. Let me see how I can report that bug to our PSPSDK dev team...
http://www.essentializer.com/setBaudBug.zip
Your code is definitely relying on the FIFO. Another, usually better way to handle the input would be to set up a serial interrupt and read each byte as it's received. However, that still doesn't explain why the fifo is disabled, and I don't see a reason for it either. If you check the pspDebugSioSetBaud() source it only writes the baudrate to the DIV1 and DIV2 registers, and 0x60 to the CTRL register. The uart4.prx code also writes 0x60 to the CTRL register, but hpremote.prx uses 0x70 instead -- but I tested 0x70 and that doesn't seem to change the results. I also tried to send the full init sequence that hpremote.prx uses, with no difference.
So my suggestion for now would be to use interrupts (see psplink sio) or look deeper into sony's prxes and figure out what we're doing wrong.
So my suggestion for now would be to use interrupts (see psplink sio) or look deeper into sony's prxes and figure out what we're doing wrong.
Ahem...
I'm still reading in strings of up to 15 characters sent at 9600 baud
straight from the barcode acanner: http://www.youtube.com/watch?v=ZO7HENwIvPs
What's the difference between SetBaud and DebugSetBaud?
Or is my program just returning to read the serial port often enough
so that it doesn't miss any characters?
Art.
Code: Select all
pspDebugSioInit();
pspDebugSioSetBaud(9600);
straight from the barcode acanner: http://www.youtube.com/watch?v=ZO7HENwIvPs
What's the difference between SetBaud and DebugSetBaud?
Or is my program just returning to read the serial port often enough
so that it doesn't miss any characters?
Art.
SetBaud of course works, tons of programs use it. You and all of the other working programs are most likely reading characters often enough. makai's code is a bit strange in that he just sits there waiting for the FIFO to fill and then finds out that it only was one character deep. I don't know why SetBaud seems to put the serial port in that mode.
Fair enough.
There is an obvious drawback in that method as well in that the serial
recieving routine ends up ruling the whole program, with no time for
screen updates, etc. while waiting for a possible transmission.
I have a feeling Deniska is working that way in his mapping program,
since the screen wouldn't need to be updated until a new NMEA sentence
is recieved from the GPS unit.
There is an obvious drawback in that method as well in that the serial
recieving routine ends up ruling the whole program, with no time for
screen updates, etc. while waiting for a possible transmission.
I have a feeling Deniska is working that way in his mapping program,
since the screen wouldn't need to be updated until a new NMEA sentence
is recieved from the GPS unit.
Well, of course I'd prefer the interupt version for serial reads. But I don't see how this could be integrated into LUA, which is definitely a drawback.
In MapThis it doesn't make a big difference, since updates are relatively slow. I'm working on an application where data is continuosly sent at 38400 baud with about 1 kbyte per second. So constantly polling due to a non-working FIFO is not an option and interrupt based sioReads() will force me to port my code from LUA to C++ (and it's a LOT of LUA code...)
As I said before: I don't think that data acutally gets lost, since constant polling always return all characters.
My theory is that the FIFO buffer is constantly filled with invalid data between valid characters (remember the H****l***l***o example in my post above) and as soon as an invalid "*" character is encountered, sioRead() returns -1. Now if you keep polling, you will eventually get the rest of the characters. But if you continue reading only after a delay, the invalid characters constantly entering the buffer will gradually kick out the valid chars. This may explain why at times you end up with "H" only, sometimes also "Hl" or "Hlo", depending on how long you wait between subsequent reads. Again, this is only a theory...
Is there a way to compare the serial registers before and after the call to pspDebugSioSetBaud()? I'm not really familiar with C, I usually code in Java...
In MapThis it doesn't make a big difference, since updates are relatively slow. I'm working on an application where data is continuosly sent at 38400 baud with about 1 kbyte per second. So constantly polling due to a non-working FIFO is not an option and interrupt based sioReads() will force me to port my code from LUA to C++ (and it's a LOT of LUA code...)
As I said before: I don't think that data acutally gets lost, since constant polling always return all characters.
My theory is that the FIFO buffer is constantly filled with invalid data between valid characters (remember the H****l***l***o example in my post above) and as soon as an invalid "*" character is encountered, sioRead() returns -1. Now if you keep polling, you will eventually get the rest of the characters. But if you continue reading only after a delay, the invalid characters constantly entering the buffer will gradually kick out the valid chars. This may explain why at times you end up with "H" only, sometimes also "Hl" or "Hlo", depending on how long you wait between subsequent reads. Again, this is only a theory...
Is there a way to compare the serial registers before and after the call to pspDebugSioSetBaud()? I'm not really familiar with C, I usually code in Java...
MapThis uses the serial port interrupt.Art wrote:Fair enough.
There is an obvious drawback in that method as well in that the serial
recieving routine ends up ruling the whole program, with no time for
screen updates, etc. while waiting for a possible transmission.
I have a feeling Deniska is working that way in his mapping program,
since the screen wouldn't need to be updated until a new NMEA sentence
is recieved from the GPS unit.