This topic briefly outlines the range of configurable options available on the serial port (this does not include the bulk of data on RX and TX buffers, which are described here).
Opening and Closing the Serial Port
The ser.enabled property defines whether the port is opened or closed. The port is closed by default, so you need to open it explicitly. The serial port won't receive or transmit the data when it is closed, but you will still be able to access its RX and TX buffers even at that time.
Serial Port Lines Remapping
Depending on your platform, you may or may not be allowed to remap the RTS/W0out/cout output and CTS/W0&1in/cin input lines (i.e., choose what I/O pins of the device these lines should be on). For more information, refer to your device's platform documentation (for example, the EM1000's is here). If your device supports remapping, you can use the ser.ctsmap and ser.rtsmap properties to select the required mapping. If your device does not support remapping, then its platform will not have these properties. You can only perform remapping when the serial port is closed.
UART, Wiegand, or Clock/Data Mode Selection
The ser.mode property selects the UART, Wiegand, or clock/data mode for the serial port. You can only change the mode when the serial port is closed.
How Incoming Data Is Committed
One important concept you will need to understand is "RX data committing." You already know that the serial port records all incoming data into the RX buffer. The new information is that the data recorded into the buffer is not immediately "reported" to your application. Instead, this buffer remains "uncommitted" until certain conditions are met. Uncommitted data is effectively invisible to your application, as if it is not there at all.
For the UART mode, the data is committed either when the total amount of uncommitted and committed data in the RX buffer exceeds half of this buffer's capacity or when the intercharacter gap, defined by the ser.interchardelay property is exceeded. For the Wiegand and clock/data modes, the first condition is not monitored, so only the intercharacter gap can commit the data.
The intercharacter gap is the time elapsed since the start of the most recent UART character reception in the UART mode or the most recent falling edge on the W0&1in/cin line in the Wiegand and clock/data modes. The idea is that once the data stops coming in, the serial port starts counting the delay. Once the delay exceeds the time set by the ser.interchardelay property, the data is committed and becomes visible to your application.
Another property — ser.autoclose — defines whether the port will be closed (ser.enabled = NO) once the intercharacter gap reaches ser.interchardelay value.
For the UART mode, the intercharacter delay allows your application to process the data more efficiently. By keeping the data invisible for a while, the serial port can accumulate a large chunk of data that your application will be able to process at once. Imagine, for instance, that the data is flowing into the serial port character by character and your application has to also process this stream character by character. The overhead may be significant and the overall performance of your application greatly reduced! Now, if this incoming data is combined into sizeable portions, your application won't have to handle it in small chunks, which will improve performance. Of course, you need to strike a balance here — attempting to combine the data into blocks that are too large may reduce your application's responsiveness and make your program appear sluggish.
Note that the intercharacter gap is not counted when the new data is not being received, because the serial port has set the RTS line to LOW (not ready). This could happen when flow control is enabled (more on flow control below).
For the Wiegand and clock/data modes, the intercharacter delay is the way to detect the end of the incoming data stream. You are recommended to program the gap to about 10 times the data rate. For example, if you are receiving the Wiegand data at a rate of 1 bit per 20ms, then set the delay to 200ms and it will serve as a reliable indicator of transmission end. This is when ser.autoclose will come in handy — once the gap is detected, the port will be closed and this will prevent another Wiegand transmission from entering the RX buffer before your application processes the previous one.
How the Outgoing Data Is Committed
Outgoing data uses a similar "data committing" concept as the incoming data. The objective is to be able to commit the data for sending once, even if the data was prepared bit by bit. This way your application can avoid sending out data in small chunks. The Buffer Memory Status topic details this.
UART Mode Settings
Several settings are unique to the UART mode. The serial port has all the usual UART-related communication parameters: baudrate, parity, 7/8 bits. There is no property to select the number of stop bits. A second stop bit can be emulated by setting ser.parity = 3 — PL_SER_PR_MARK.
The ser.baudrate property actually keeps a divisor value. You can set any baudrate you want by providing the correct divisor. There is even a read-only ser.div9600 property that allows you to calculate the divisor value in a platform-independent way, by returning the required divisor value (for the current platform) to reach 9,600bps.
The actual baudrate is calculated as follows: baudrate = (9600 * ser.div9600) / ser.baudrate. For example, if we need to achieve 38,400bps and ser.div9600 returns 12, then we need to set ser.baudrate = 3, because (9,600 * 12) / 38,400 = 3. This serves as a platform-independent baudrate calculation, as ser.div9600 will return different values for different platforms.
function set_baud(baud as integer) as integer
'baud: 0- 1200, 1-2400, 2-4800, 3- 9600, 4-19200, other-38400
select case baud
case 0: ser.baudrate=ser.div9600*8 '9600/1200=8
case 1: ser.baudrate=ser.div9600*4 '9600/2400=4
case 2: ser.baudrate=ser.div9600*2 '9600/4800=2
case 3: ser.baudrate=ser.div9600 '9600/9600=1
case 4: ser.baudrate=ser.div9600/2 '19200/9600=2
case else: ser.baudrate=ser.div9600/4 '38400/9600=4
On the LTPP3, the ser.baudrate and ser.div9600 properties are replaced by ser.baud.
The serial port can be used in full-duplex or half-duplex mode, as determined by the ser.interface property (see UART Mode for details). In the full-duplex mode, the serial port can optionally use flow control. In the half-duplex mode, you can select the polarity of the direction control signal.
In the UART mode, the serial port can recognize so-called "escape sequences" — they are defined using the ser.esctype and ser.escchar properties. When such a sequence is recognized, a special event (on_ser_esc) is generated and the port is disabled. Of course, this can be achieved programmatically, but it would require you to parse all incoming data and really slow things down. Escape sequences were implemented with efficiency and speed in mind.
Escape sequences are rather arbitrary. They follow the style of escape sequences that Tibbo introduced before. However, they are useful for certain things. For example , if your application has a normal mode and serial "setup" mode, you can use this sequence to switch into setup mode.
Escape sequences will work even if you are using buffer shorting, and that makes them especially powerful. If you are building a device that just routes the data between a serial interface and an Ethernet interface, you will use buffer shorting for performance, but you could still detect the escape sequences to switch into the serial programming mode or perform some other similar task.