Check for char from SimpleIDE Terminal without waiting
Andy Lindsay (Parallax)
Posts: 1,919
The default code that the simpletools library loads for communicating with SimpleIDE Terminal does not have a way to timeout or check if a character was received without waiting. We'll look into changing that, but in the meantime, here is an example of a way to set up your terminal to check for a character without waiting. This program will display a count to 15 in the SimpleIDE Terminal, unless you click the terminal and press the 'q' key on your keyboard.
This code has #include "fdserial.h" to make it use the fdserial (full duplex serial) library. Unlike the simpletools default, which runs in the same cog, this code runs in another cog, which means that it can be watching for serial messages all the time, not just when you call scan, getChar, etc. The fdserial library buffers any serial data and has functions for checking if serial data is in the buffer as well as checking for data until a timeout.
At the start of the program, simpleterm_close disables the simpletools default code for talking with the terminal. Then, fdserial *term = fdserial_open(31, 30, 0, 115200) starts a full duplex serial process in another cog that communicates with the P31 and P30 (programming/terminal port pins) at a buad rate of 115.2 kb/s.
Functions that work with fdserial are slightly different; they expect the pointer fdserial_open returned. This code stored that in term. Then, instead of print("n = %d\n", n), we use dprint(term, "n = %d\n" n). Note that the the first parameter is term, which is the same term from fdserial *term = fdserial_open(31, 30, 0, 115200).
i-box: The term value is a text_t device pointer -a pointer to a structure that holds all the serial information for that process.
the great thing about text_t device pointers is that you can use them with certain functions to pick which serial process you are communicating with. This is especially important when the propeller is communicating with multiple devices. dprint, which is short for device-print expects a text_t device pointer for its first parameter. When sending to SimpleIDE terminal, we use term. Keep in mind that you can use it for other devices too. For example, you could add fdserial *xbee = fdserial_open(11, 10, 0, 9600). Then, you would have a choice of sending messages to term or xbee. If you want to instead print to the xbee, you could use dprint(xbee, "Hello XBee world!").
The if(fdserial_rxCheck(term) == 'q') break statement is another one that uses the device pointer. This statement checks the serial process named term to find out if there is any data in its rx (receive) buffer. If yes, then break out of the do...while loop.
fdserial_rxCheck is part of the fdserial library, which has fundamental functions for transmitting and receiving serial data. Then, there's the simpletext library, which simpletools includes because it has functions like print and dprint. In addition to dprint, it has more than 20 different functions for transmitting and receiving various types of formatted data with text_t devices like fdserial. (Just look for functions with text_t *device in their parameter lists.)
Where can you find documentation on fdsrial and simpletext? Click SimpleIDE Help, then select Simple Library Reference. Then, follow the simpletext and fdserial links. If a web page doesn't open when you select Simple Library Reference, here are the direct paths in your documents folders.
...Documents/SimpleIDE/Learn/Simple Libraries/Text Devices/libfdserial/Documentation fdserial Library.html
Documents/SimpleIDE/Learn/Simple Libraries/Text Devices/libsimpletext/Documentation simpletext Library.html
#include "simpletools.h" #include "fdserial.h" void main() { simpleterm_close(); fdserial *term = fdserial_open(31, 30, 0, 115200); int n = 1; do { dprint(term, "n = %d\n", n); pause(1000); if(fdserial_rxCheck(term) == 'q') break; }while(n++ < 15); dprint(term, "\nAll done."); }
This code has #include "fdserial.h" to make it use the fdserial (full duplex serial) library. Unlike the simpletools default, which runs in the same cog, this code runs in another cog, which means that it can be watching for serial messages all the time, not just when you call scan, getChar, etc. The fdserial library buffers any serial data and has functions for checking if serial data is in the buffer as well as checking for data until a timeout.
At the start of the program, simpleterm_close disables the simpletools default code for talking with the terminal. Then, fdserial *term = fdserial_open(31, 30, 0, 115200) starts a full duplex serial process in another cog that communicates with the P31 and P30 (programming/terminal port pins) at a buad rate of 115.2 kb/s.
Functions that work with fdserial are slightly different; they expect the pointer fdserial_open returned. This code stored that in term. Then, instead of print("n = %d\n", n), we use dprint(term, "n = %d\n" n). Note that the the first parameter is term, which is the same term from fdserial *term = fdserial_open(31, 30, 0, 115200).
i-box: The term value is a text_t device pointer -a pointer to a structure that holds all the serial information for that process.
the great thing about text_t device pointers is that you can use them with certain functions to pick which serial process you are communicating with. This is especially important when the propeller is communicating with multiple devices. dprint, which is short for device-print expects a text_t device pointer for its first parameter. When sending to SimpleIDE terminal, we use term. Keep in mind that you can use it for other devices too. For example, you could add fdserial *xbee = fdserial_open(11, 10, 0, 9600). Then, you would have a choice of sending messages to term or xbee. If you want to instead print to the xbee, you could use dprint(xbee, "Hello XBee world!").
The if(fdserial_rxCheck(term) == 'q') break statement is another one that uses the device pointer. This statement checks the serial process named term to find out if there is any data in its rx (receive) buffer. If yes, then break out of the do...while loop.
fdserial_rxCheck is part of the fdserial library, which has fundamental functions for transmitting and receiving serial data. Then, there's the simpletext library, which simpletools includes because it has functions like print and dprint. In addition to dprint, it has more than 20 different functions for transmitting and receiving various types of formatted data with text_t devices like fdserial. (Just look for functions with text_t *device in their parameter lists.)
Where can you find documentation on fdsrial and simpletext? Click SimpleIDE Help, then select Simple Library Reference. Then, follow the simpletext and fdserial links. If a web page doesn't open when you select Simple Library Reference, here are the direct paths in your documents folders.
...Documents/SimpleIDE/Learn/Simple Libraries/Text Devices/libfdserial/Documentation fdserial Library.html
Documents/SimpleIDE/Learn/Simple Libraries/Text Devices/libsimpletext/Documentation simpletext Library.html
Comments
1. What means the third parameter (mode)? Has it somthing to do with the dataformat(nmb databits, parity)?
2. Whats the dprint variant for gets (dgets)?
Thanks, regards...
About 2. The problem with dscan is that it breaks after a whitespace
Regards...
1. The third parameter is reserved as a mode word. At the moment it does nothing.
2. There is a test of all simpletext functions for examples in Documents\SimpleIDE\Learn\Simple Libraries\Text Devices\libsimpletext\libsimpletext.c (.side) Maybe the read*(term) functions will be more helpful ?
A split function would be great for better parsing if anyone has time to write one.
Great subject Andy
You have weekend service , thanks for your help.
1. But is there a way to specify the standard uart params as: nmb of databits (7 or 8), parity (none, odd or even), nmb stopbits (1, 1.5 or 2)? And what are the defaults? The Command Line Interpreter have to talk to LabView and/or Matlab/Simulink. There you have to set those params.
2. The gets function gets a whole string, and must be ended with a return on the terminal side. To save RAM this string is only hold ones (in main.c) , so to and in de CLI I use pointers to the different parts (command, param_1, param_2 ... param_n) of the string. In libsimpletext.c are only examples for the not text_t devices and don't work for a serial interface in a separate cog (see the first text in this thread of Andy).
I wil start a new tread for my implementation of a CLI today.
Regards...
Wijnand
For Matlab/Simulink, etc, just set the software to 8-bits, no parity, 1 stop bit, and whatever baud rate you plan to use. Then, in fdserial_open, use 31, 30, 0, and the baud rate.
The fdserial_open function's documentation is in:
Documents/SimpleIDE/Learn/Simple Libraries/Text Devices/libfdserial/Documentation fdserial Library.html
I see that it is missing an explanation of the mode parameter. Sorry; we'll update that. In the meantime:
Mode has bits for setting these signaling behaviors:
bit 0 - inverts rx.
bit 1 - inverts tx.
bit 2 - open drain/source tx.
bit 3 - ignore tx echo on rx.
At this point, the Full Duplex Serial PASM driver object under the fdserial library does not support 7-bit, which is why the fdserial library does not offer it as an option.
Andy
It works as expected.
I have still one question: can I use anny pair of unused pins in fdserial_open?
Regards...
Your project is the first one to alert us that custom string terminators are needed. I'm sorry we did not have it for you, but we do plan to make it an option for an upcoming revision.
In answer to your question, yes, the library supports using any pair of Propeller I/O pins for full duplex serial communication. You can also create multiple full duplex serial instances that use different pairs of pins by declaring multiple serial types.
If you want only buffered serial input, you can also use -1 for the txpin parameter in fdserial_open.
Andy