- 1 Understanding the hardware
- 2 UART registers
- 3 Using Qbasic to interface
- 4 Using Linux to interface
- 5 Using PalmOS to interface
Understanding the hardware
The ALDL port on OBDI saturns uses 8192 baud communications for communication. The data format is standard 8 data bits, 1 stop bit and no parity. However unlike a standard RS-232 port the voltage levels are around +/- 5v where the standard RS-232 is around +/- 12v. Due to this fact you will need a level converter to communicate with the PCM. Commercial cables are out there, but they are not much more than This DIY cable. Additionally the ALDL port puts both Receive and Transmit on the same wire.
Now that we have a proper cable, lets look a little more at the details of the communication protocol. starting with the data/stop/parity stuff.
The diagram above shows 8-N-1. There is one start bit, 8 data bits and 1 stop bit. This is how the equipment on either end knows the start and end of a byte.
The most important variable for communicating with another device is the data speed, or baud rate. The PC BIOS usually controls this, however the BIOS usually only supports 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600 and 115200 (assuming the 16550 or better UART is being used). well those speeds will not do for 8192. This is where UART clock divisor comes in. The standard clock rate for the 16500 is 115200hz this needs to be divided to achieve a usable speed. For this we use a divisor of 14. Which puts the baud around 8229 which leaves only a difference about 36, this is a small enough difference that the start and stop bit cycle will keep everything in sync.
The standard RS-232 port has more functions than just the data wires. but the data pins are the only ones used for the 8192 interface. For reference, the pin assignments for the standard port is below.
|Data Terminal Ready||DTR||20||4|
|Data Set Ready||DSR||6||6|
|Request To Send||RTS||4||7|
|Clear To Send||CTS||5||8|
The UART (Universal Asynchronous Receiver and Transmitter) is the heart of the serial interface. Understanding how to control this device at a lower level than the BIOS is key to communicating with 8192 baud devices. This is handled through a set of hardware registers or memory addresses that can be read or written to control how the UART functions. The table below lists the common register addresses of the first two serial ports.
|Read mode||Write mode||First port||Second port|
|Receive holding||Transmit Holding/Divisor LSB||0x3F8||0x2F8|
|Interrupt Status||FIFO control||0x3FA||0x2FA|
The first two registers are dual purposed for write mode, the mode of these two is controlled by the MSB of the Line Control Register. When the bit is set high the Divisor register is accessible when it is low the first register will be the Receive and Transmit Holding Registers and the second register will have no function.
This is where the data speed is controlled, this register spans across two addresses due to the fact that this register is 16 bits wide. In order to access this register the eighth bit of the Line control register needs to be set high. after that the register can be programmed via the first two addresses. "1111111111111111" = 65536 (or the speed 115200/65536=1.7baud) "0000000000000001" = 1 (or the speed 115200/1=115200)
When the Divisor Access bit is NOT set this register holds the last byte received (non-FIFO) or the las byte not read (FIFO)
When the Divisor Access bit is not set this register will send it's contents on the wire.
|2||Receiver Line Status|
|3||Modem Status Register|
|1||0=Modem status change, 0=Transmitter holding register empty, 0=Received data available, 0=Line status change, 1=Character timeout (16550)|
|2||0=Modem status change, 0=Transmitter holding register empty, 0=Received data available, 0=Line status change, 1=Character timeout (16550)|
|3||0=Modem status change, 1=Transmitter holding register empty, 0=Received data available, 1=Line status change, 0=Character timeout (16550)|
|6||0=No FIFO, 1=Unusable FIFO (16550 only), 1=FIFO enabled|
|7||0=No FIFO, 0=Unusable FIFO (16550 only), 1=FIFO enabled|
|1||Set high to clear Receive Buffer|
|2||Set high to clear Transmit Buffer|
|3||Select DMA mode 0 or 1|
|6||0=one byte buffer, 1=four byte buffer, 0=eight byte buffer, 1=fourteen byte buffer|
|7||0=one byte buffer, 0=four byte buffer, 1=eight byte buffer, 1=fourteen byte buffer|
|0||0=five data bits, 1=six data bits, 0=seven data bits, 1=eight data bits|
|1||0=five data bits, 0=six data bits, 1=seven data bits, 1=eight data bits|
|2||0=one stop bit, 1=1.5(for 5 data bits) or 2(for the rest) stop bits|
|4||0=odd parity, 1=even parity, 0=high parity, 1=low parity|
|5||0=odd parity, 0=even parity, 1=high parity, 1=low parity|
|6||Disable/Enable Break signal|
|0||Data terminal ready|
|1||Request to send|
|2||Auxiliary output 1|
|3||Auxiliary output 2|
|4||Break signal received|
|5||Transmit Holding is empty|
|6||Transmit Holding is empty, and line is idle|
|7||Errornous data in FIFO|
|0||Clear to send has changed|
|1||Data set ready has changed|
|2||Ring indicator has changed|
|3||Carrier detect has changed|
|4||Clear to send|
|5||Data set ready|
This is a painfully useless register, never seen a use for it aside from testing for an XT style UART. And if you are using an XT, your PCM may just be faster!
Using Qbasic to interface
Okay, I know, Qbasic WTF!?!?! This is the only programming (The term is used lightly) language I have access to for windows. Or care to for that matter, I do not own a current Windows system, nor have I owned one since 1995 when I beta tested Win95 (Yes, It was that bad!)
The key functions you will be needing is OUT and INP, they do pretty much the same thing in QBasic as they do in X86 ASM.
|Code： Reading and Writing Hardware Ports|
%byte = INP(&H3F8) '(this reads a byte from the Receive Holding Register) OUT &H3F8, %byte '(this writes that byte back to the Transmit Holding Register)
|Code： initialize the first port for 8192baud 8,n,1|
OUT &H3FB, 131 OUT &H3F8, 14 OUT &H3F8, 0 OUT &H3FB, 3
In order to read and write data you will need to use the registers directly with the INP and OUT functions. Using the Transmit Buffer Empty flag will be a good idea when sending data, and using a FIFO is suggested.
Using Linux to interface
Linux makes this type of thing easy, considering BIOS is generally a last resort for anything with the Linux kernel.
From the command line (as root) just run "setserial /dev/ttyS0 baud_base 115200 divisor 14 spd_cust" or change /dev/ttyS0 to the port of your choice, then open the port at 38400.
Now you should be able to communicate at 8192 just as you would anything else using a serial port.
Using PalmOS to interface
Things are a little different here, the PalmOS devices do not use a standard UART and at that not all PamlOS devices use the same UARTS. The older devices are based on the DragonBall processors from Motorolla. Some of the later devices use ARM and even more exotic microcontrollers. As I get started on this, I will be looking at the older DB based devices. At first glance the UART divisor registers in these devices are only 3 bits. However the divisor is based on the main clock, leaving the option of altering the primary clock rate and then using a divisor to drop the UART speed right on 8192 baud.