Synchronous Serial Support

 

Supported Clocking Options and Protocols
The SeaMAC V5 driver supports numerous protocols and communication methods. The definition of some protocols is sufficient to allow the driver to completely handle the protocol internally. Others have so many variations that creating a general driver for all cases is impractical. Therefore, Sealevel’s philosophy is to provide the capability for the application to configure the driver such that the driver can return meaningful data back to an application which will then allow the application to perform any validity checking necessary on the returned data and process it as desired. Since these capabilities vary from protocol to protocol, each will be described below. In addition, a code snippet is provided for the more common variations of each protocol.

Please review the information included below carefully to determine if SeaMAC V5 will work properly for your application. If the mode of operation you require is not supported by SeaMAC V5, please contact Sealevel Technical Support for options.

General Clocking Options
One important feature of synchronous (and isochronous) communication is that a clock must exist to allow the synchronization of the data. There can be two sources of this clock. It can come from the outside world and be connected to the card’s DB25 connector, or it can be generated from the internal oscillator on the card. If it is generated internally, it must be provided to the outside world to allow other devices to know when to clock in each bit of data. This clock can either be a physically distinct signal (in addition to the data) or it can be encoded onto the data using one of many different methods. For the driver to either transmit or receive data, it needs to know which clocking method is being used. SeaMAC V5 provides for the above combinations using a few dedicated fields of the SSI_COMM_CONFIG structure.

Encoded Clock
If the clock is encoded onto the data stream, then the clock must be extracted from the stream and then used to decode the data. The device used to do this is a Digital Phase Lock Loop (DPLL). If this method is used, then the method used to encode the clock must be specified. Since a DPLL circuit must know roughly the frequency of the signal to be decoded, this information is provided in the BitRate specification. It must also know the encoding method used. This example assumes Bi-phase Space (FM0). The other options are defined in the SSI_COMM_CONFIG section of this document. This would be done by the following four statements:

CommCfg.RsetSource = ssiTimingDpll ;    // receive timing DPLL
CommCfg.TsetSource = ssiTimingDpll ;    // transmit timing DPLL
CommCfg.BitRate = 19200 ;     // transmit / receive data rate
CommCfg.ClockEncoding = ssiClockEncodingFm0 ; // Clock encoded using FM0 (Bi-phase space)

The above code assumes the transmitter would also be synchronized to the incoming receive signal. The other alternative would be to have the transmitter set to generate its own and encode its transmission based on internal clock. In this case the transmitter would be driven by the onboard oscillator (Baud Rate Generator – BRG) and the above line would be changed to read:

CommCfg.TsetSource = ssiTimingBrg ;    // transmit timing

External Clock
If the clock is not encoded onto the data stream, then it must be provided. For the receiver, the following line of code would select the mode where the clock is provided on the RXC pin(s) of the DB25 connector.

CommCfg.RsetSource = ssiTimingRxc ;    // receive timing from the DB connector on the card

For the transmitter, it is a little more complicated. The transmitter can either be clocked from an external source in which case the following lines would be used:

CommCfg.TsetSource = ssiTimingTxc ;     // transmit timing from the DB connector on the card
CommCfg.TsetFromHere = FALSE ;     // we are not providing an output clock

or the transmitter data rate can be clocked from the internal BRG in which case the lines would read:

CommCfg.TsetSource = ssiTimingBrg ;     // transmit timing from internal baud rate generator (BRG)
CommCfg.BitRate = 19200 ;     // transmit rate
CommCfg.TsetFromHere = TRUE ;     // we are providing an output clock on the TSET pins

HDLC/SDLC
This is a widely used and well-defined protocol that is almost entirely handled by the driver. Data is divided into frames consisting of a special character (called a flag), data, and another flag. The standards define that the first byte of the data portion of the frame will be an address byte, the second byte will be a control byte, and the last two bytes will optionally be a CRC. When transmitting a frame, the SeaMAC V5 driver will automatically send an opening flag, the data provided by the application, optionally calculate a CRC and send it, and then send the closing flag. It should be noted that on transmission, the address and control fields are completely ignored by the driver and just transmitted as data. The application should format the data buffer exactly as required (with the exception of the flags and CRC – note: the CRC is optional). When receiving data, it is possible for the application to specify that it wants the driver / hardware to only respond to a selected address. The driver allows the application to specify if this feature should be enabled the specification of the desired address. Note: If this feature is enabled, then all messages not containing the specified address in the first byte of the data portion of the message will be ignored.

The following is a sample of code that can be used to configure the driver for HDLC operation (It should be noted that the clocking options defined above must also have been specified):

CommCfg.Electrical = ssiElectricalRS232 ;     // Set terminated RS-232
CommCfg.Framing = ssiFramingSdlc ;     // Make sure we’re using SDLC
CommCfg.CharacterSize = 8 ;     // regular 8-bit characters
CommCfg.PreTxDelayTime = 0 ;     // Transmit immediately
CommCfg.PostTxDelayTime = 0 ;     // Drop RTS immediately after closing flag
CommCfg.Loopback = FALSE ;     // no loopback
CommCfg.Echo = FALSE ;     // no echo
CommCfg.BrgSourceFromRset = FALSE ;     // bit rate from internal BRG
CommCfg.CrcPolynomial = ssiCrcCcitt ;     // normal SDLC polynomial
CommCfg.CrcPresetOnes = TRUE ;     // normal SDLC preset
CommCfg.IdleMode = ssiIdleSync ;     // idle flags between messages
CommCfg.SdlcAddressMode = ssiAddressModeFromAny ;     // receive from any address
CommCfg.PreambleLength = 0 ;     // no special preamble

Bisync (Binary Synchronous)
While bisync has been around for many years, many people mistakenly assume that there is a standard structure and way of automatically handling it. Unfortunately, the only thing that is absolutely defined is that a valid message will start with two sync characters (hence the name bisync).

Transmitting is more straightforward than receiving. The SeaMAC V5 driver will allow you to format a message and send it. The hardware will automatically insert the sync characters before the beginning of the message and send the data. The driver does not check for any special control characters and therefore the application can create any desired message format.

The receive side is much more complex. The first problem is synchronization. The hardware has the capability of going into “Hunt” mode. In this mode, the hardware will actually examine every bit of incoming data until if finds a 16 bit match with the specified sync characters. Because this sync pattern can exist in either a random data stream or within a valid message, it is possible for the hardware to sync at the wrong place within a data stream. SeaMAC V5 allows an application to re-enter the hunt mode at any point (see the Reference/Functions/DeviceIoControl under Contents in the help file). Once proper synchronization has been established, the question then becomes how much data to read. A normal read specifies how much data should be read and the CommTimeouts allows a timeout to occur if the requested amount of data has not arrived within a specified time period. The problem is that there is no universally accepted method of knowing when the message has ended. At the end of the message, the card goes into an idle condition. It can be either a constant stream of ones, zeros, alternating ones and zeros, sync character(s), etc. Therefore, if you do a 200 character read, and the incoming message is 6 bytes long, the read will not complete until 200 characters have come in. In this case, the data passed to the application will be 6 bytes of good data followed by 194 bytes of something else. This can be a significant problem if the receiver must either expect a long message or a short control message. If the device on the other end of the link is expecting a timely response to a control message and a large read was posted, then the other device may time out before the application receives the control message and trailing extraneous data. SeaMAC V5 attempts to address this by providing two generalized methods of handling this situation. If the framing was specified as

CommCfg.Framing = ssiFramingCharacterSync ;     // Make sure we’re using unformatted bisync

this will allow the application to have full control of message processing. In situations where this poses a problem, SeaMAC V5 provides another option for detecting the end of a message and returning the data immediately to the application. To use this method, specify

CommCfg.Framing = ssiFramingCharacterSyncISO1745 ;     // Terminate on control characters

The above will notify the driver that received messages have a defined ending character. The ISO 1745 standard is a broadly used standard that uses commonly defined control characters. While we intentionally did not fully support this standard (to do so would have precluded applications having the ability to used other standards without driver modifications), we do support their control characters as message terminators. In this mode, the driver will return to the user immediately when it determines the data stream contains one of the following characters:

Characterdecimal code
ETX3
EOT4
ENQ5
ACK6
NAK21
ETB23

When transmitting, each write will be preceded by the specified sync characters and the state of the output data line between transmissions will be determined by:

CommCfg.IdleMode = ssiIdleSync ;     // idle sync character between messages
CommCfg.SyncCharacterSize = 16 ;     // specify bisync(=16) as opposed to monosync(=8)
CommCfg.SyncCharacter = 0x00001610 ;     // in this case, sync is ASCII DLE SYN

The above does impose the restriction that it is impossible to “merge” two outputs together to form one bisync frame using non-overlapped I/O. It is possible to merge outputs together to form one frame if the computer is fast enough to ensure the second frame has been queued to the output queue in the driver before the previous write has completed. To do this, the device must have been opened with overlapped I/O specified and the following must be specified:

CommCfg.MergeFrames = TRUE ;     // attempt to send out data “back to back”

Monosync
While monosync has been around for many years, it is not nearly as widely used as bisync. A potential problem with using monosync is that the sync pattern is only 8 bits long and the possibility of syncing at the wrong place is significant.

When transmitting, the operation is almost identical to bisync except that only one sync character is generated. SeaMAC V5 will allow you to format a message and send it. The hardware will automatically insert the sync characters before the beginning of the message and send the data. SeaMAC V5 does not check for any special control characters and therefore the application can create any desired message format.

The receive side is much more complex. As with bisync, the first problem is synchronization. The hardware has the capability of going into “Hunt” mode. In this mode, the hardware will actually examine every bit of incoming data until it finds an 8-bit match with the specified sync character. Because this sync pattern can exist in either a random data stream or within a valid message, it is possible for the hardware to sync at the wrong place within a data stream. SeaMAC V5 allows an application to re-enter the hunt mode at any point (see the Reference/Functions/DeviceIoControl under Contents in the help file). Once proper synchronization has been established, the question then becomes how much data to read. A normal read specifies how much data should be read and the CommTimeouts allows a timeout to occur if the requested amount of data has not arrived within a specified time period). The problem is that there is no universally accepted method of knowing when the message has ended. At the end of the message, the card goes into an idle condition. It can be either a constant stream of ones, zeros, alternating ones and zeros, sync character(s), etc. Therefore, if you do a 200 character read, and the incoming message is 6 bytes long, the read will not complete until 200 characters have been received. In this case, the data passed to the application will be 6 bytes of valid data followed by 194 bytes of something else. This can be a significant problem if the receiver must understand various message sizes. If the device on the other end of the link is expecting a timely response to a control message and a large read was posted, then the other device may time out before the application receives the control message and trailing extraneous data. Unlike bisync mode, the driver does not support control characters to terminate the message before the character count or timeout is reached.

Raw Mode
Raw mode is a completely unformatted mode of operation used primarily for receiving although transmission is possible. In this mode, the incoming data is simply grouped into 8 bit bytes and passed to the application. There is no way to ensure any byte alignment of the incoming data. All byte alignment, sync character detection, etc. must be done entirely by the application. Since there is no way for the driver to determine when to stop, it will continue to read until the requested number of bytes have been read or a timeout period expires.

CommCfg.Framing = ssiFramingRaw ;     // Make sure we’re using raw mode
CommCfg.MergeFrames = TRUE ;     // merge frames for output

Transmission is possible but has the same limitation on continuous transmission as bisync.

External Sync
External sync mode is exactly like raw mode with one exception. A sync signal must be asserted on a specific modem control signal. This input signal will indicate when the first bit of the first byte of the frame begins. This signal must be left asserted until the last character is being received. The exact timing of this signal is defined in the Zilog Z16C32, Z85230, or Z85233 manuals. On cards based on the Zilog Z16C32, the signal should be provided on the DCD pin(s). On cards based on the Z85230/Z85233, it should be provided on the CTS pin(s). Since there is no way for the driver to determine when to stop, it will continue to read until the requested number of bytes has been read or a timeout period expires. Simply de-asserting the CTS or DCD signal will not terminate the read, although it will stop the receiver from assembling characters.

CommCfg.Framing = ssiFramingExternalSync ;     // Make sure we’re using external sync mode
CommCfg.MergeFrames = TRUE ;     // merge frames for output

Transmission is possible but has the same limitation on continuous transmission as bisync.

Asynchronous / Isochronous
The driver will also support “standard” async communications at normal data rates. This can be selected with the following statements:

CommCfg.Framing = ssiFramingAsync ;     // select asynchronous communications
CommCfg.RsetSource = ssiTimingBrg ;     // transmit timing from internal baud rate generator (BRG)
CommCfg.TsetSource = ssiTimingBrg ;     // transmit timing from internal baud rate generator (BRG)
CommCfg.BitRate = 19200 ;     // selected data rate
CommCfg.TsetFromHere = FALSE ;     // no output clock is being provided

Isochronous mode is selected as a subset of normal asynchronous mode.  The major difference is that rather than have the internal clock used to decode the incoming bits, an external clock can be provided to clock both the receiver and the transmitter. To enable this mode, specify:

CommCfg.Framing = ssiFramingAsync ;     // select asynchronous communications
CommCfg.RsetSource = ssiTimingRset ;     // receive timing from RXC pin
CommCfg.TsetSource = ssiTimingTset;     // transmit timing from TXC pin
CommCfg.TsetFromHere = FALSE ;     // no clocking involved

In addition, it is possible to receive using an external clock and transmit based on the BRG. In this case, the card will produce a 1X output bit clock on the TSET pin(s). To select this mode, specify:

CommCfg.Framing = ssiFramingAsync ;     // select asynchronous communications
CommCfg.RsetSource = ssiTimingRset ;     // transmit timing from internal baud rate generator (BRG)
CommCfg.TsetSource = ssiTimingBrg ;     // transmit timing from internal baud rate generator (BRG)
CommCfg.BitRate = 19200 ;     // selected data rate for transmitter
CommCfg.TsetFromHere = TRUE ;     // provide a 1X clock output on the TSET pin(s)

API and I/O control functions
These API and I/O control functions report and set the configuration of a SeaMAC device:

  • GetCommState
  • SetCommState
  • IOCTL_SSI_GET_COMM_CONFIG
  • IOCTL_SSI_SET_COMM_CONFIG
  • IOCTL_SSI_SAVE_COMM_CONFIG

A further description of these functions is contained in the SeaMAC Driver API documentation in the section “Configuring a SeaMAC Device”.