Cport Serial Communications Library for C/C++ Version 2.0 Copyright (c) 1993 Bri Productions - all rights reserved Cport is a registered trademark of Bri Productions. All other product and brand names are trademarks or registered trademarks of their respective holders. i Contents ======== Introduction ------------ General Description ............................. 1-1 Disclaimer ...................................... 1-2 Evaluation Copy ................................. 1-2 Purchase Version ................................ 1-2 Contacting Bri Productions ..................... 1-2 Terminology ..................................... 1-3 Using Cport ----------- Basics .......................................... 2-1 Buffered Input .................................. 2-3 Buffered Output ................................. 2-5 Handshaking ..................................... 2-7 Direct Transmit Mode ............................ 2-10 Theory of Operation ------------------- The UART ........................................ 3-1 The Transmitter and Receiver .................... 3-1 The Transmit and Receive Queues ................. 3-2 Input and Output Functions ...................... 3-2 Control and Status Functions .................... 3-2 Direct Transmit mode ............................ 3-2 C Reference ----------- Typedefs and Structures ......................... 4-1 COM .......................................... 4-2 CPARAM ....................................... 4-2 byte ......................................... 4-3 Global Variables ................................ 4-4 comopen_errno ................................ 4-4 Control Functions ............................... 4-5 ComOpen ...................................... 4-6 ComOpenS ..................................... 4-8 ComClose ..................................... 4-8 ComCloseAll .................................. 4-9 ComHandshake ................................. 4-9 ComParam ..................................... 4-10 ComBaud ...................................... 4-11 ComMode ...................................... 4-12 ComRxQ ....................................... 4-13 ComTxQ ....................................... 4-14 ComTx ........................................ 4-15 ComNS550 ..................................... 4-15 ComTurbo ..................................... 4-16 ii Input Functions ................................. 4-18 ComGetc ...................................... 4-19 ComGets ...................................... 4-19 ComIn ........................................ 4-20 ComFlushRx ................................... 4-21 ComLenRx ..................................... 4-22 ComPeek ...................................... 4-22 ComRxScan .................................... 4-23 Output Functions ................................ 4-25 ComPutc ...................................... 4-26 ComPuts ...................................... 4-26 ComOut ....................................... 4-27 ComFlushTx ................................... 4-28 ComLenTx ..................................... 4-29 ComTxWait .................................... 4-29 Status Functions ................................ 4-31 ComError ..................................... 4-32 ComStatus .................................... 4-33 ComRts ....................................... 4-33 ComDtr ....................................... 4-34 ComOut1 ...................................... 4-35 ComUart ...................................... 4-35 Data Integrity .................................. 4-37 ComChecksum .................................. 4-38 ComCrc16 ..................................... 4-38 ComCrc32 ..................................... 4-39 Misc Functions .................................. 4-41 ComSetBreak .................................. 4-42 ComClrBreak .................................. 4-42 ComPutScrtch ................................. 4-43 ComGetScrtch ................................. 4-43 C++ Reference ------------- Control Functions ............................... 5-1 Cport::Cport ................................. 5-2 Cport::operator int .......................... 5-4 Cport::Handshake ............................. 5-5 Cport::Param ................................. 5-6 Cport::Baud .................................. 5-6 Cport::Mode .................................. 5-7 Cport::RxQ ................................... 5-8 Cport::TxQ ................................... 5-9 Cport::Tx .................................... 5-10 Cport::NS550 ................................. 5-10 Cport::Turbo ................................. 5-11 iii Input Functions ................................. 5-13 Cport::Get ................................... 5-14 Cport::In .................................... 5-15 Cport::FlushRx ............................... 5-16 Cport::LenRx ................................. 5-17 Cport::Peek .................................. 5-17 Cport::RxScan ................................ 5-18 Output Functions ................................ 5-19 Cport::Put ................................... 5-20 Cport::Out ................................... 5-21 Cport::FlushTx ............................... 5-22 Cport::LenTx ................................. 5-22 Cport::TxWait ................................ 5-23 Status Functions ................................ 5-24 Cport::Error ................................. 5-25 Cport::Status ................................ 5-25 Cport::Rts ................................... 5-26 Cport::Dtr ................................... 5-27 Cport::Out1 .................................. 5-28 Cport::Uart .................................. 5-28 Data Integrity .................................. 5-29 Cport::Checksum .............................. 5-30 Cport::Crc16 ................................. 5-30 Cport::Crc32 ................................. 5-31 Misc Functions .................................. 5-33 Cport::SetBreak .............................. 5-34 Cport::ClrBreak .............................. 5-34 Cport::Scratch ............................... 5-35 File Transfer ------------- Xmodem .......................................... 6-1 XmodemTx ........................................ 6-2 XmodemRx ........................................ 6-3 Xcallback ....................................... 6-4 Callback Function ............................... 6-5 Xmodem Tables of Values ......................... 6-7 Appendix -------- Appendix A - Tables of Values ................... A-1 Appendix B - Compiling and Linking .............. B-1 Appendix C - Order form ......................... C-1 1-1 Introduction ============ General Description ------------------- Cport is a general purpose C/C++ serial communications library for 80x86 Intel processor-based systems and the National Semiconductor family of UARTs. This includes IBM and compatible computers and potentially 80x86 processor-based embedded applications. The latter is usually possible with few no modifications. Cport features: þ Support for COM 1 to COM 4 and custom configurations þ Simultaneous serial communications. þ Baud rates from 50 to 115200 baud. þ Built-in hardware and software handshaking. þ Both transmitter and receiver are interrupt-driven. þ Adjustable transmit and receive queues. þ Queues as large as 65534 bytes each. þ Transmit and receive queues are handled internally. þ Supports the NS16550 UART automatically. þ Developed in assembly language for optimum speed and efficiency. Cport provides a middle level C/C++ interface for general purpose serial communications. The library is lean and fast, so as to provide programs with high performance serial communications without significantly increasing its size. Cport can be used to develop higher level interfaces for specific types of serial devices or as is for more generic types of serial communications applications. An example of a higher level interface might be a set of functions that communicate with a serial printer. This interface would have more knowledge of the type of data, controls codes, protocol, etc. that relate to a serial printer. An example of a more generic application would be a terminal program since, like Cport, a terminal program is indifferent to the actual significance of the data. The design philosophy of Cport is to provide as many features as possible without hindering its most important attributes: speed and size. Many of the details, in addition to the actual hardware interface itself, are provided in order to facilitate serial communications software development. This includes the internal buffering (queues), hardware and software handshaking and different flavors of input/output functions. These features would either need to be implemented externally anyway, or do not add overhead unless used. Many features, such as timeouts, can additionally be easily implemented as needed at the middle, C/C++ level. Many techniques and features are demonstrated in the next section (Using Cport) and in examples throughout this document. Examples and techniques will continue to be compiled and made available in the future. 1-2 DISCLAIMER ---------- Cport is provided AS IS. Bri Productions specifically disclaims any and all warranties, expressed or implied, including but not limited to any implied warranties including fitness for a particular purpose. Use this product at your own risk. Evaluation Copy --------------- This is an evaluation copy of Cport. This evaluation copy is provided to you at no charge* so that you may properly evaluate Cport prior to purchasing it. This evaluation copy has a fully functional small model library and contains no cripples. Redistribution of this evaluation copy, unaltered and without charge, is encouraged. We feel it is important that you be able to try a product prior to paying for it. This ensures that you will be able to determine the quality of a product and if it fits your needs. It avoids the hassle of money back guarantees which would otherwise waste your time and ours. We also feel that the producers of a product are entitled to be compensated for their hard work. This enables them to continue to provide a high quality product. If you intend to use Cport beyond the purpose evaluation, you are obligated to purchase a license. * Disk distributors may charge a minimum (reasonable) fee for distribution of this evaluation copy. Licensing --------- When you purchase a license for Cport, you will receive the small, medium, compact, large and huge model libraries; Library source code; Printed manual; and examples. You will also be entitled to technical support and low cost upgrades. When you license Cport you may incorporate any part of it into your own executable programs without additional royalties as long as they bear your own valid Copyright notice. Each lisense covers usage by a single person at a time. An order form is provided in Appendix C. Contacting Bri Productions --------------------------- Bri Productions may be contacted by any of the following means: Telephone: (510) 794-0616 CompuServe: 76635,2246 U.S. mail: Bri Productions P.O.Box 7121 Fremont, CA 94537-7121 1-3 Terminology ----------- This section defines some of the terminology used in this and other Cport documentation. The 'computer' refers to the machine on which Cport is running. 'Remote device' refers to the device the computer is communicating with. The actual device may be a modem, serial printer or other communications device. If a serial port is, 'open' it is currently performing or ready to perform serial communications. All 'open' serial ports have a 'handle' which is assigned when it is 'opened'. This 'handle' is passed to Cport functions in order to identify the 'open' serial port the function is to act upon. (In C++, instances of the Cport class are used instead of handles). Individual units of 'data' that are transmitted and received may be referred to as 'characters' or 'bytes'. Technically, there is no difference between 'characters' and bytes, however; 'characters' usually refer to 7 or 8 bit ASCII values and 'bytes' typically refer to 8 bit binary data. 'Data' refers to 'characters'/'bytes' in general. A 'signal' may refer to software (i.e. control characters) as well as actual hardware lines. This mainly refers to XON (ctrl-Q) and XOFF (ctrl-S), which are used in software handshaking. 'Signals' may be either inputs or outputs. A 'signal' is said to be 'asserted' if it is in a true/on state and 'inhibited' if it is in a false/off state. This stems from the idea that a 'signal' can be used to allow (assert) or preclude (inhibit) something such as the transmission of 'data'. 2-1 Using Cport =========== Basics ------ Before a serial port can be accessed, it must be opened. The open functions identify the serial port by it's port address and interrupt request line. The parameter id contains the port base address in the lower 12 bits and the irq number in the upper 4 bits of id. The open functions also take parameters that describe the baud rate, word length, number of stop bits, parity check, and transmit and receive queue sizes. If a serial port is successfully opened, a handle to the newly opened serial port is returned to the caller. This handle is used to reference the serial port in subsequent calls to Cport functions. (C++ uses instances of the Cport class instead of handles). If the serial port cannot be opened, the open function returns NULL and sets the global variable 'comopen_errno' to an error code. (C++ uses an int typecast instead of the global variable to hold the error code). Before a program terminates, the serial port must be closed to make certain restorations. Failing to close a serial port will leave these restorations undone and almost certainly cause the system to lock up. In C++, the serial port is closed automatically when it goes out of scope (destructor). 2-2 C Example: #include #include "cport.h" int main(void) { COM com; /* declare a serial port handle */ /* Open the serial port and get/store the serial port handle */ com = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); /* Check for a NULL handle. If the handle is NULL check // comopen_errno for the cause */ if(com == NULL) { puts("ERROR: unable to open serial port"); return(comopen_errno); } /* Put a string to the newly opened serial port */ ComPuts(com, "Hello Cport"); ... The rest of the program here /* Close the serial port before exiting */ ComClose(com); return(0); } C++ Example: #include #include "cport.h" int main(void) { Cport com(COM1, B9600, W8|S1|NONE, 1024, 512); if((int)com != NO_ERR) // uses int typecast { cout << "ERROR: unable to open serial port" << endl; return(com); } com.Put("Hello Cport"); ... The rest of the program here // The serial port is closed automatically by // the destructor. return(0); } 2-3 Buffered Input -------------- When data is received, it is placed into the receive queue and stays there until an input function retrieves it. Input functions will only fetch whatever data is existing in the receive queue at the time the input function is called. If a specified length of data is expected, the receive queue can be queried to determine if enough data is available to call an input function. This is a common case with serial devices that send specific length messages terminated by a specific character (often '\n' or '\r'). In the examples, the function fetches a message only if one is available. If the message is not available, it returns a zero, If a message is available, the measurement is copied to the caller's buffer and a 1 is returned. C Example: #define MSG_LEN 24 #define TERM_C '\n' int GetMessage(COM com, char *buf) { if(ComLenRx(com) > MSG_LEN) { ComGets(com, buf, MSG_LEN, TERM_C); return(1); } return(0); } C++ Example: #define MSG_LEN 24 #define TERM_C '\n' int GetMessage(Cport& com, char *buf) { if(com.LenRx() > MSG_LEN) { com.Get(buf, MSG_LEN, TERM_C); return(1); } return(0); } If the messages are not of a specific length, the receive queue can be scanned for a particular character, namely the termination character. Scanning for a character is also possible with specific length messages but is slower than checking the length of the receive queue. In the following examples, the function fetches a message only if one is available. If the message is not available it returns a zero, If a message is available, the measurement is copied to the caller's buffer and a 1 is returned. If the message is longer that the specified maximum message length, a -1 is returned. 2-4 C Example: #define MAX_MSG_LEN 80 #define TERM_C '\n' int GetMessage(COM com, char *buf) { int len; len = ComRxScan(com, TERM_C); if(len > MAX_MSG_LEN) return(-1); else if(len > 0) ComGets(com, buf, MAX_MSG_LEN, TERM_C); return(len != 0); } C++ Example: #define MAX_MSG_LEN 80 #define TERM_C '\n' int GetMessage(Cport& com, char *buf) { int len; len = com.RxScan(TERM_C); if(len > MAX_MSG_LEN) return(-1); else if(len > 0) com.Get(buf, MAX_MSG_LEN, TERM_C); return(len != 0); } The previous examples are ideal for event driven routines. They do not wait for a message to be received if one is not ready. This allows a program to process other tasks instead of holding up program execution while waiting for a message. On the contrary, one may want to wait for a message, perhaps within a certain time frame. Revisiting the first example, we can add a timeout using the ANSI C compatible function, clock. 2-5 C Example: #include #define MSG_LEN 24 #define TERM_C '\n' int GetMessage(COM com, char *buf, clock_t timeout) { timeout += clock(); while(ComLenRx(com) <= MSG_LEN) { if(clock() > timeout) return(0); } ComGets(com, buf, MSG_LEN, TERM_C); return(1); } C++ Example: #include #define MSG_LEN 24 #define TERM_C '\n' int GetMessage(Cport& com, char *buf, clock_t timeout) { timeout += clock(); while(com.LenRx() <= MSG_LEN) { if(clock() > timeout) return(0); } com.Get(buf, MSG_LEN, TERM_C); return(1); } Buffered Output --------------- When an output function inserts data into the transmit queue, it does not wait for the data to be transmitted before the function returns. Instead the transmitter will subsequently remove the data, one byte/character at a time, in the order in which it was inserted and transmit them in the background. This allows the program to continue with more important tasks instead of waiting for the data to transmit at a relatively slow rate (compared to the processor). At certain points in a program, one may want to ensure that all the data thus far has been transmitted. To do this the transmit queue can be queried to determine how many bytes/characters still reside there. The following examples make sure all data finishes transmitting before the program is terminated. 2-6 C Example: int main(void) { COM com; com = ComOpen(COM2,B9600,W8|S1|NONE,512,2048); if(com == NULL) return(comopen_errno); ComPuts(com, "Welcome to Bri Productions"); while(ComLenTx(com) != 0); ComClose(com); return(0); } C++ Example: int main(void) { Cport com(COM2, B9600, W8|S1|NONE, 512, 2048); if((int)com != NO_ERR) return(com); com.Put("Welcome to Bri Productions"); while(com.LenTx() != 0); // The serial port is closed automatically by // the destructor. return(0); } Querying the transmit queue can also be useful in determining if there is enough room for new data. In the following, example a message is sent only if there is enough room for the whole message. The value returned should always be 0 (if not enough room) or the length of the message (number of characters put by ComPuts). C Example: #include #define TXSIZE 1024 int PutMessage(COM com, const char *buffer) { if(TXSIZE - ComLenTx(com) < strlen(buffer)) return(0); return(ComPuts(com, buffer)); } 2-7 C++ Example: #include #define TXSIZE 1024 int PutMessage(Cport& com, const char *buffer) { if(TXSIZE - com.LenTx() < strlen(buffer)) return(0); return(com.Put(buffer)); } If the transmit queue length is not checked and an output function is called without enough room for all the data, the number of byte/characters that did fit is returned. This value can be used as an offset into the data to determine the first byte/character that there was no room for. The following examples will not return until all the characters in the message are put to the queue. C Example: void PutMessage(COM com, const char *buffer) { const char *_buffer = buffer; while(*_buffer != '\0') _buffer += ComPuts(com, _buffer); } C++ Example: void PutMessage(Cport& com, const char *buffer) { const char *_buffer = buffer; while(*_buffer != '\0') _buffer += com.Put(_buffer); } Handshaking ----------- There are number of built-in options available for implementing handshaking. The options can be divided into two categories. One is hardware handshaking and the other is software handshaking. In hardware handshaking, one or more of the hardware lines is used. In software handshaking, XON and XOFF characters are used. 2-8 Hardware Handshaking -------------------- In hardware handshaking, any combination of the hardware signals RTS, DTR, DSR, CTS, and DCD can be used to achieve handshaking. RTS and/or DTR are used by the receiver to signal the remote device to suspend or resume transmitting. Similarly, DSR, CTS, and/or DCD can be used by the remote device's receiver to signal the transmitter to suspend or resume transmitting. Software Handshaking -------------------- In software handshaking, the control characters XON (ctrl-Q) and XOFF (ctrl-S) are used to achieve handshaking. When receiver software handshaking (S_RX) is enabled, XON and XOFF characters are transmitted to signal the remote device to suspend or resume it's transmission. Notice that even though the XON and XOFF characters are sent by the transmitter, it is the receiver that exercises the handshaking in order to preclude a receive queue overflow. In transmit software handshaking (S_TX), the remote device sends XON and XOFF characters to suspend and resume the computer's transmission. Notice that even though the XON and XOFF characters are received, it is the transmitter that is affected. Both receive and transmit handshaking can be enabled simultaneously. The Receiver ------------ When receive software (S_RX) and/or hardware handshaking (DTR and/or RTS) are enabled, the receiver monitors the length of the receive queue. If the length exceeds the specified threshold, the receiver will take the appropriate action to signal the remote device to suspend transmitting. When the length of the receive queue subsequently falls below half of the set threshold, the appropriate action is taken to signal the remote device to resume transmitting. The Transmitter --------------- When transmit software (S_TX) and/or hardware handshaking (DSR, CTS, and/or DCD) are enabled and the computer is signaled to suspend transmitting with the corresponding handshaking enabled, the transmitter will stop transmitting. Subsequently, when the computer is signaled to resume transmitting, the transmitter will pick up where it left off. User Handshaking ---------------- Another option for implementing handshaking is for the programmer to implement their own handshaking scheme. To accomplish this, Cport provides the function ComTx. ComTx allows the programmer to turn the transmitter on and off. When the transmitter is turned off, transmitting halts immediately. If any characters still reside in the transmit queue, they will remain there until the transmitter is turned back on or the transmit queue is flushed. More characters may be put into the transmit queue while the transmitter is turned off. 2-9 Cooperation ----------- In any handshaking scheme, it is imperative that the computer and the remote device recognize the same handshaking scheme. For instance, if the remote device recognizes hardware handshaking and the computer does not, the computer will ignore any requests by the remote device to suspend transmitting. If the remote device recognized software handshaking and the computer did not, bogus XON and XOFF characters might corrupt the received data. In the first example, the transmitter will not transmit unless CTS and DSR are asserted. The receiver will inhibit RTS if the receive queue exceeds 768 bytes/characters and assert it when it subsequently falls below 768 / 2. In the second example, the transmitter will stop if an XOFF character is received and restart when an XON character is received. If the receive queue length exceeds 768 bytes/characters, an XOFF character will be transmitted and when the length subsequently falls below 768 / 2, an XON character is transmitted. C Example 1 int main(void) { COM com; com = ComOpen(COM1, B9600, W7|S1|EVEN, 1024,256); if(com == NULL) return(comopen_errno); ComHandshake(com, CTS | DSR | RTS, 768); /* rest of the program */ ComClose(com); return(0); } C++ Example 1 int main(void) { Cport com(COM1, B9600, W7|S1|EVEN, 1024, 256, CTS|DSR|RTS, 768); if((int)com) return(com); // rest of the program return(0); } 2-10 C Example 2 int main(void) { COM com; com = ComOpen(COM1, B9600, W7|S1|EVEN, 1024, 256); if(com == NULL) return(comopen_errno); ComHandshake(com, SOFT, 768); /* SOFT == S_RX | S_TX */ /* rest of the program */ ComClose(com); return(0); } C++ Example 2 int main(void) { // SOFT == S_RX | S_TX Cport com(COM1, B9600, W7|S1|EVEN, 1024, 256, SOFT, 768); if((int)com) return(com); // rest of the program return(0); } Direct Transmit Mode -------------------- In direct transmit mode, data is sent directly to the serial port. The output functions will only return after all the data has been transmitted or when a handshaking signal is inhibited. Direct mode is ideal for transmit intensive routines such as file transfers, where the main task is transmitting data. Otherwise direct transmit mode is not normally preferred. There are two ways to get into direct transmit mode. The first is to set the transmit queue size in the call to the open function (or constructor in C++) to zero. This method sets direct transmit mode permanently. To set direct transmit mode temporarily, turn the transmitter off with ComTx with the TX_DIRECT option. 2-11 C Example 1 int main(void) { COM com; /* transmit queue 0 = direct transmit mode */ com = ComOpen(COM1, B9600, W8 | S1 | NONE, 4096, 0); if(com == NULL) return(comopen_errno); /* continued */ ComClose(com); return(0); } C++ Example 1 int main(void) { // transmit queue 0 = direct transmit mode Cport com(COM1, B9600, W8 | S1 | NONE, 4096, 0); // continued return(0); } In this examples, the transmitter is put into direct mode while a block of data is transmitted. The transmitter is subsequently restored to its previous state. The block of data is completely transmitted before the function returns (assumes no transmit handshaking is enabled). C Example 2 #define BLOCK_SIZE 1024 int SendBlock(COM com, byte *block) { int tx, rv; tx = ComTx(com, OFF | TX_DIRECT); rv = ComOut(com, block, BLOCK_SIZE); ComTx(com, tx); return(rv); } 2-12 C Example 2 #define BLOCK_SIZE 1024 int SendBlock(Cport& com, byte *block) { int tx, rv; tx = com.Tx( OFF | TX_DIRECT); rv = com.Out(block, BLOCK_SIZE); com.Tx(tx); return(rv); } Handshaking in Direct Transmit Mode ----------------------------------- Transmit handshaking works a bit differently in direct transmit mode. In normal transmit handshaking, output functions will always succeed in putting the data as long as there is room in the transmit queue, even if transmit handshaking is in an inhibited state. In direct transmit mode, there is no transmit queue to buffer the output data during the inhibited state of transmit handshaking. Therefore, in direct transmit mode, an output function may not complete a transmission of the data if transmit handshaking changes to an inhibited state. The return value of the output functions should always be tested when transmit handshaking is used in direct transmit mode to ensure that all of the data has been transmitted. The return value can subsequently be used to transmit the remaining data when the transmit handshaking returns to an asserted state. This is demonstrated in the following example. In this example, it is assumed that DSR handshaking is enabled and the transmitter is in direct mode. C Example: void SendData(COM com, char *buf) { char *_buf = buf; while(*_buf != '\0') { _buf += ComPuts(com, _buf); if(*_buf != '\0') while(!ComStatus(com) & DSR); /* wait for DSR */ } } 2-13 C++ Example void SendData(Cport& com, char *buf) { char *_buf = buf; while(*_buf != '\0') { _buf += com.Put(_buf); if(*_buf != '\0') while(!com.Status() & DSR); // wait for DSR } } Receive handshaking will always function the same regardless of the current mode of the transmitter. 3-1 Theory of Operation =================== The UART -------- The UART (Universal Asynchronous Receiver/Transmitter) is a single integrated circuit peripheral chip, which is specially designed for asynchronous serial communications. It is responsible for many of the electronic details of serial communications. The UART converts parallel data (bytes/characters) to and from serial signals at the correct baud rate, and with the assigned word length, stop bits and parity. It also monitors and controls the hardware status lines. Cport interfaces intimately with the serial port's UART. The name UART is a generic name used to describe a type of integrated circuit. serial communications in IBM and compatible computers is based on the National Semiconductor family of UARTs. These chips include: INS8250 INS8250-B INS8250A INS82C50A NS16450 NS16C450 NS16550A The latest and greatest is the NS16550A, which features transmitter and receiver FIFO's. If a NS16550 UART is detected by Cport when a serial port is opened, Cport will automatically take advantage of it's advanced features. These feature greatly improve performance. The Transmitter and Receiver ---------------------------- The transmitter and receiver interact intimately with the serial port's UART to coordinate data exchanges between it and the transmit and receive queues. They also coordinate and control any enabled handshaking. The transmitter and receiver together constitute an interrupt service routine that the program will branch to any time the serial port's UART generates an interrupt. When the UART is ready for another byte/character, the transmitter will transfer another byte/character (if available) to the UART. In addition, it sends XON/XOFF characters at the request of the receiver when software handshaking is enabled, and monitors the status of the input hardware lines when hardware handshaking in enables. When the UART receives a new byte/character, the receiver fetches it from the UART and stores it in the receive queue. It also monitors the amount of data in the receive queue when handshaking is enabled, in order to perform the enabled handshaking and avoid a receive queue overflow. In software handshaking, requests to the transmitter are made to send the XON/XOFF characters. In hardware handshaking, the receiver manipulates the hardware line(s) directly. 3-2 The Transmit and Receive Queues ------------------------------- The receive and transmit queues provide the interface/buffering between the Cport input and output functions and the receiver and transmitter respectively. This allows the transmitter/receiver to operate independently from the input/output functions and vice versa. The transmitter is concerned only with the head of the transmit queue while the output functions are only concerned with the tail of the transmit queue. Similarly, the receiver is only concerned with the tail of the receive queue while the input functions are only concerned with the head of the receive queue. Input and Output Functions -------------------------- Input functions retrieve data from the receive queue in the order in which it is placed into the receive queue by the receiver. Since the data is buffered, the program does not need to worry about the incoming data until it is ready to fetch it. The output functions insert data into the transmit queue and will be transmitted by the transmitter in the order in which the data is inserted. Control and Status Functions ---------------------------- Control functions manipulate both the transmitter/receiver and the UART. The queues are independent of the control functions except when the queues are created and destroyed when the serial port is opened and close respectively. Status functions retrieve information from the transmitter/receiver and the UART. They also manipulate the UART to set status (to the remote unit). Direct Transmit Mode -------------------- In direct transmit mode, the transmitter and transmit queue are removed. The output functions write directly to the UART. The output functions will return only after all it's data is written to the UART, or transmit handshaking is enabled and in an inhibited state. This holds up program execution but may be desirable when there are no other tasks to perform, since otherwise, the transmitter and receiver share available background time. An example of when direct transmit mode might be advantageous is a dedicated file transfer routine where the only interest is to transmit data. 4-1 C Reference =========== Typedefs and Structures ----------------------- Basic COM is a typedef used for storing a serial port handle. CPARAM is a structure type used for storing a serial port's parameters. byte is a typedef userd for storing a byte size value. 4-2 COM ------------------------------------------------------------------ Function Data type for storing a serial port handle. Syntax #include "cport.h" typedef void* COM; Remarks COM is a type used to store a serial port handle. The open functions (ComOpen and ComOpenS) return values of type COM and all serial port specific functions take a parameter of type COM. Example Open a serial port. int main(void) { COM com1; com1 = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); if(com1 == NULL) { /* error */ } ...continued CPARAM ------------------------------------------------------------------ Function Data type for storing a serial port's parameters. Syntax #include "cport.h" typedef struct { unsigned id; int baud; byte mode; unsigned rxQ; unsigned txQ; byte htype; unsigned thresh; }CPARAM; id - Value that identifies the serial port. The upper 4 bits define the interrupt request line while the lower 12 bits define the port address. This technique allows for the possibility of custom configurations. See Table A-1 in Appendix A for a list of predefined values. baud - Value that defines the baud rate. The actual value is the baud rate divisor, which allows for the possibility of custom baud rates. The baud rate divisor = f / (16 * baud rate) where f is 1.8432e+6. See Table A-2 in Appendix A for a list of predefined baud rate divisors. mode - Bit ORed value defining the word length, number of stop bits and the parity. See Table A-3 in Appendix A for a list of mode components. 4-3 * rxQ - Size, in bytes, of the receive queue. * txQ - Size in bytes, of the transmit queue. * Limited to 32K in small and medium memory models. htype - Type of handshaking to be used. See Table A-5 in Appendix A for a list of handshaking components. thresh - Receive queue threshold. Remarks CPARAM is a structure type that holds the parameters of a serial port. This structure is mainly used with the alternate open function ComOpenS and with the function ComParam. Example Open COM2 at 9600 baud, 8 bits, 1 stop bit, no parity, a receive queue of 1024 bytes, a transmit queue of 512 bytes and software handshaking (XON/XOFF) with a receive queue threshold of 3072 bytes. int main(void) { CPARAM param= {COM2, B9600, W8|S1|NONE, 4096, 512, SOFT, 3072}; COM com2; com2 = ComOpenS(¶m); if(com2 == NULL) { /* error */ } ...continued byte ------------------------------------------------------------------ Function Data type used for storing byte size values. Syntax #include "cport.h" typedef unsigned character byte; Remarks The byte data type is used for storing byte size values. Some of the Cport functions take parameters of type byte and some return values of type byte. Example Use a byte data type for the mode parameter. static byte mode = W8|S1|NONE; byte Mode(COM terminal, byte newmode) { byte temp; ComMode(terminal, newmode); temp = mode; mode = newmode; return(temp); /* return previous mode */ } 4-4 Global Variables ---------------- comopen_errno ------------------------------------------------------------------ Function Holds the error code from the last attempt to open a serial port. Syntax #include "cport.h" extern int comopen_errno; Remarks Comopen_errno holds the error code from the last attempt to open a serial port via a call to ComOpen or ComOpenS. If the last opened serial port was successfully opened, comopen_errno will be 0. If an error occurred while attempting to open the serial port the value of comopen_errno will be non-zero. See Table A-4 in Appendix A for a list of possible values for comopen_errno. Example Attempt to open COM1. If an error occurs, check comopen_errno for the cause. int main(void) { COM com1; com1 = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); if(com1 == NULL) { switch(comopen_errno) { case RX_ALC: case TX_ALC: case GEN_ALC: /* memory allocation error */ break; case NO_UART: /* no UART at that address */ break; default: /* all other errors */ break; } } ...continued 4-5 Control Functions ----------------- Basic ComOpen opens a serial port using discrete parameters. ComOpenS opens a serial port using a structure of parameters. ComClose closes a currently open serial port. ComCloseAll closes all open serial ports. ComHandshake determines if and what type of handshaking scheme will be enabled and sets the receiver threshold. Intermediate ComParam reports on the current parameters and handshaking under which the specified serial port is currently operating. ComBaud changes the serial port's baud rate. ComMode changes the serial port's word length, number of stop bits and parity. Advanced ComRxQ resizes the receive queue. ComTxQ resizes the transmit queue. ComTx allows advanced control over the Cport transmitter. ComNS550 sets the receive fifo threshold of an NS16550 UART. ComTurbo temporarily disables/re-enables selected high priority interrupts that may impede high speed transfers. 4-6 ComOpen ------------------------------------------------------------------ Function Opens a serial port for communications. Syntax #include "cport.h" COM ComOpen(unsigned id, int baud, byte mode, unsigned rxQ, unsigned txQ); Parameters id - Value that identifies the serial port. The upper 4 bits define the interrupt request line, while the lower 12 bits define the port address. This technique allows for possibility of custom configurations. See Table A-1 in Appendix A for a list of predefined values. baud - Value that defines the baud rate. The actual value is the baud rate divisor, which allows for the possibility of custom baud rates. The baud rate divisor = f / (16 * baud rate) where f is 1.8432e+6. See Table A-2 in Appendix A for a list of predefined baud rate divisors. mode - Bit ORed value defining the word length, number of stop bits and the parity. See Table A-3 in Appendix A for a list of mode components. * rxQ - Size, in bytes, of the receive queue. * txQ - Size, in bytes, of the transmit queue. * Limited to 32K in small and medium memory models. Remarks ComOpen opens the specified serial port and returns a handle used to identify the newly opened serial port. If ComOpen fails to open the specified serial port, it returns NULL and sets comopen_errno to an error code. The 4 most significant bits in id represent the interrupt vector, while the lower 12 bits represent the port address. Constants are provided in cport.h to facilitate the formulation of the id parameter. The COMx values will work in most cases; however, the IRQx values can be ORed with the PORTx or BIOSx values to produce other combinations. The PORTx values are actual port addresses where the serial ports are normally located. The BIOSx values are actually macros, which fetch the port address from the BIOS data area. Usually the BIOSx and PORTx values will be the same, but it is not guaranteed. Quite often the values at BIOS2 and BIOS3 (com 3 and com 4) will be set to 0 regardless if com3 or com4 exist. See Table A-1 in Appendix A for a list of predefined values for formulating the id parameter. The parameter baud is the baud rate divisor that determines the baud rate. Achieving baud rates above 19200 is depends on many variables such as machine speed, cable length, handshaking activity, degree bidirectional transfers, number of open serial ports, the type UART(s) used and activity of other hardware interrupts. 4-7 The parameter mode determines the word length, number of stop bits and parity. Bits 0 and 1 determine the word length, bit 2 determines the number of stop bits, bit 3 enables parity and bits 4 and 5 determine the type of parity check. RxQ and txQ set the size of the receive and transmit queues respectively. RxQ should be at least four times larger than the largest string or block of data the programmer intends to fetch from the queue at once. TxQ can be set as small as 1, but is not recommended. In the small and medium memory models, where all data is limited to 64K, the size queues are limited. In the compact and large memory models, each queue can be as large as 64K-1 (65534 bytes). Return value If successful, ComOpen returns a handle to the newly opened serial port. In the event of an error, it returns NULL and sets the global variable comopen_errno to an error code. See Table A-4 in Appendix A for a list of possible values for comopen_errno. See also ComOpenS, ComClose, ComCloseAll, ComBaud, ComMode, COM, comopen_errno Example Open COM1 at 9600 baud with 8 bit words, 1 stop bit, no parity, a 1024 byte receiver and a 512 byte transmitter. int main(void) { COM com1; com1 = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); if(com1 == NULL) { switch(comopen_errno) { case RX_ALC: case TX_ALC: case GEN_ALC: /* allocation error */ break; case NO_UART: /* no UART */ break; default: /* all other errors */ break; } } ...continued 4-8 ComOpenS ------------------------------------------------------------------ Function Opens a serial port for communications. Syntax #include "cport.h" COM ComOpenS(const CPARAM *param); Parameters param - Pointer to a type CPARAM that contains the serial port parameters. Remarks ComOpenS is an alternative to ComOpen for opening a serial port. It takes a pointer to a type CPARAM. CPARAM is a structure that contains the serial port parameters. Return value If successful, ComOpenS returns a handle to the newly opened serial port. In the event of an error, it returns NULL and sets the global variable comopen_errno to an error code. See Table A-4 in Appendix A for a list of possible values for comopen_errno. See also ComOpen, ComClose, ComCloseAll, ComParam, COM, comopen_errno Example Open COM2 at 9600 baud, 8 bits, 1 stop bit, no parity, a receive queue of 1024 bytes, with a transmit queue of 512 bytes and software handshaking (XON/XOFF) with a receive queue threshold of 3072 bytes. int main(void) { CPARAM param = {COM2, B9600, W8|S1|NONE, 4096, 512, SOFT, 3072}; COM com2; com2 = ComOpenS(¶m); if(com2 == NULL) { /* error */ } ...continued ComClose ------------------------------------------------------------------ Function Closes the specified serial port. Syntax #include "cport.h" void ComClose(COM); Parameters COM - Handle of the serial port to be closed. 4-9 Remarks ComClose closes the specified serial port. Failing to close all serial ports before a program is terminated will cause the system to lock up. See also ComCloseAll, ComOpen, ComOpenS, COM Example Close the serial port prior to terminating. int main(void) { COM com1; com1 = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); if(com1 == NULL) /* error */ ...later ComClose(com1); return(0); } ComCloseAll ------------------------------------------------------------------ Function Closes all currently opened serial ports. Syntax #include "cport.h" void ComCloseAll(void); Remarks ComCloseAll closes all the currently opened serial ports. Failing to close all serial ports before a program is terminated will cause the system to lock up. ComCloseAll is convenient for ensuring all serial ports are closed prior to a program's termination. See also ComClose, ComOpen, ComOpenS Example Make sure all serial ports are closed prior to terminating. void ErrorExit(void) { ComCloseAll(); exit(-1); } ComHandshake ------------------------------------------------------------------ Function Enables or disables handshaking (flow control) for the specified serial port. Syntax #include "cport.h" void ComHandshake(COM, byte htype, unsigned thresh); 4-10 Parameters COM - Handle of the serial port. htype - Type of handshaking to be used. See Table A-5 in Appendix A for a list of handshaking components. thresh - Receive queue threshold. Remarks ComHandshake enables or disables software and/or hardware handshaking for the specified serial port. In software handshaking, XON and XOFF characters are used to suspend and resume communications. Hardware handshaking uses any or all of the DTR, DSR, RTS, CTS and DCD lines to suspend and resume communications. Thresh determines when the receiver will assert or inhibit the corresponding handshaking signals. If no receive handshaking is specified (RTS, DTR or S_RX), the threshold is not used and may be set to zero. See also ComParam, ComOpenS, ComTx Example If COM1 is successfully opened, turn on some hardware handshaking and set the receiver threshold to 3/4 of the receiver's full size. The transmitter will not transmit unless both DSR and DCD are asserted. The receiver will inhibit DTR if the receive queue length exceeds the threshold. int main(void) { COM com1; com1 = ComOpen(COM1, B9600, W8|S1|NONE, 1024, 512); if(com1 == NULL) { /* error */ } ComHandshake(com1, DSR|DTR|DCD, 768); ...continued ComClose(com1); return(0); } ComParam ------------------------------------------------------------------ Function Retrieves the parameters of the specified serial port. Syntax #include "cport.h" void ComParam(COM, CPARAM *param); Parameters COM - Handle of the serial port from which to get the parameters. 4-11 param - Pointer to a type CPARAM where the parameters will be stored. Remarks ComParam retrieves the parameters and handshaking status of the specified serial port and stores them in a type CPARAM. See also CPARAM, ComOpen, ComOpenS, ComMode, ComBaud Example Open a serial port with the same configuration as one that is already opened. COM ComOpenCopy(unsigned id, COM copyme) { CPARAM param; ComParam(copyme, ¶m); param.id = id; return(ComOpenS(¶m)); } ComBaud ------------------------------------------------------------------ Function Changes the baud rate of the specified serial port. Syntax #include "cport.h" void ComBaud(COM, int baud); Parameters COM - Handle of the serial port. baud - Value that defines the baud rate. The actual value is the baud rate divisor, which allows for possibility of custom baud rates. The baud rate divisor = f / (16 * baud rate) where f is 1.8432e+6. See Table A-2 in Appendix A for a list of predefined baud rate divisors. Remarks ComBaud changes the baud rate of the specified serial port. The parameter baud is the baud rate divisor that determines the baud rate. See also ComOpen, ComOpenS, ComParam, ComMode Example Set the specified serial port to a new baud rate. 4-12 #define NBAUD 4 int SetBaud(COM com, unsigned n) { int baud[NBAUD] = { B9600, B2400, B1200, B300 }; if(n < NBAUD) { ComBaud(com, baud[n]); return(0); } else return(-1); } ComMode ------------------------------------------------------------------ Function Changes the word length, number of stop bits and parity of the specified serial port. Syntax #include "cport.h" void ComMode(COM, byte mode); Parameters COM - Handle of the serial port. mode - Bit ORed value defining the word length, number of stop bits and the parity. See Table A-3 in Appendix A for a list of mode components. Remarks ComMode changes the word length, number of stop bits and parity of the specified serial port. The parameter mode determines the word length, number of stop bits and parity of the specified serial port. Bits 0 and 1 determine the word length, bit 2 determines the number of stop bits, bit 3 enables parity and bits 4 and 5 determine the type of parity check. See also ComOpen, ComOpenS, ComParam, ComBaud Example Set the serial port to a new mode. #define NMODE 2 int SetMode(COM com, unsigned n) { byte mode[NMODE] = { W8|S1|NONE, W7|S1|EVEN }; if(n < NMODE) { ComMode(com, mode[n]); return(0); } return(-1); } 4-13 ComRxQ ------------------------------------------------------------------ Function Resizes the specified serial port's receive queue. Syntax #include "cport.h" unsigned ComRxQ(COM, unsigned size); Parameters COM - Handle of the serial port. size - New receive queue size. Remarks ComRxQ resizes the specified serial port's receive queue. The memory currently allocated for the receive queue is freed, and new memory is allocated. If ComRxQ is unable to allocate the specified amount memory, it will try to reallocate memory for the previous size. ComRxQ returns the new queue size. If memory was successfully allocated for the new size, the return value will be size. If the previous size is reallocated, the return value will be the previous size. If no memory could be allocated, ComRxQ returns zero. No data can be received while the new receive queue is being resized. However, data in the transmit queue will continue to be transmitted normally. Return value ComRxQ returns the new receive queue size. See also ComTxQ, ComOpen, ComOpenS Example Enlarge the receive queue for a file transfer. #define LARGE_RX 4096 int ReceiveFile(COM com, const char *filename) { CPARAM param; ComParam(com, ¶m); if(ComRxQ(com, LARGE_RX) != LARGE_RX) return(-1); ... transfer file here /* Restore original size */ if(ComRxQ(com, param.rxQ) != param.rxQ) return(-2); else return(0); } 4-14 ComTxQ ------------------------------------------------------------------ Function Resizes the specified serial port's transmit queue. Syntax #include "cport.h" unsigned ComTxQ(COM, unsigned size); Parameters COM - Handle of the serial port. size - New transmit queue size. Remarks ComTxQ resizes the specified serial port's transmit queue. The memory currently allocated for the transmit queue is freed, and new memory is allocated. If ComTxQ is unable to allocate the specified amount memory, it will try to reallocate memory for the previous size. ComTxQ returns the new queue size. If memory was successfully allocated for the new size, the return value will be size. If the previous size is reallocated, the return value will be the previous size. If no memory could be allocated, ComTxQ returns zero. No data can be transmitted while the new transmit queue is being resized. However, data to the receive queue will continue to be received normally. Return value ComTxQ returns the new transmit queue size. See also ComRxQ, ComOpen, ComOpenS Example Enlarge the transmit queue for a file transfer. #define LARGE_TX 4096 int TransmitFile(COM com, const char *filename) { CPARAM param; ComParam(com, ¶m); if(ComTxQ(com, LARGE_TX) != LARGE_TX) return(-1); ... transfer file here /* Restore original size */ if(ComTxQ(com, param.txQ) != param.txQ) return(-2); else return(0); } 4-15 ComTx ------------------------------------------------------------------ Function Transmitter control. Syntax #include "cport.h" int ComTx(COM, int cmnd); Parameters COM - Handle of the serial port. cmnd - Determines the action to be taken on the transmitter See Table A-9 in Appendix A for a list of transmitter options. Remarks ComTx allows advanced control of the Cport transmitter The transmitter can be turned on and off to suspend and resume transmissions. This function can be very useful when implementing your own handshaking scheme. In addition, it can inform the output functions to transmit directly when the transmitter is turned off. Return value ComTx returns the previous status of the transmitter See also ComHandshake, ComOpenS, ComParam Example Put a priority character directly to the serial port. void PriorityPutc(COM com, char c) { int tx; tx = ComTx(com, TX_DIRECT | OFF); ComPutc(com, c); ComTx(com, tx); /* restore original state */ } ComNS550 ------------------------------------------------------------------ Function NS16550 UART setup. Syntax #include "cport.h" void ComNS550(COM, int trigger); Parameters COM - Handle of the serial port. trigger - Trigger threshold for the UART receive fifo. See Table A-12 in Appendix A for a list of trigger thresholds. Remarks If Cport detects an NS16550 UART when a serial port is opened, Cport automatically takes advantage of it's advanced capabilities. 4-16 The receive fifo threshold is the number of bytes in the receive fifo that will cause an interrupt to be generated. By default, the receive fifo threshold is set to 14 bytes. ComNS550 allows this receive fifo trigger threshold to be changed. See Also ComUart Example If the specified serial port is an NS16550 set the trigger level to 1 byte. void SetThreshIf550(COM com) { if(ComUart(com) == NS16550) ComNS550(com, T550_1); } ComTurbo ------------------------------------------------------------------ Function Disables/re-enables high priority interrupts. Syntax #include "cport.h" void ComTurbo(int options); Parameters options - Bit mask of options. See Table A-6 in Appendix A for possible options. Remarks During high speed data exchanges, certain events that cause high priority interrupts can inhibit serial communications and possibly cause (over run) errors. This is especially true of the timer, which periodically uses extra time and the keyboard, if keys are pressed. ComTurbo disables selected high priority interrupts or restores all of them. The high priority interrupts should never be disabled permanently or for long periods of time. The timer interrupt is not actually disabled but diverted, allowing the system clock to continue to update. All other options are actually disabled when specified. Example Disable the keyboard and divert the timer while a block is transferred at high speed. #include #define BLK_SZ 128 4-17 int GetBlock(COM com, byte* block, clock_t timeout) { int rv; /* assume 115200 baud */ ComTurbo(TIMER | KEYBOARD); timeout += clock(); while(ComLenRx(com) < BLK_SZ) { if(clock() > timeout) { ComTurbo(OFF); return(0); } } rv = ComIn(com, block, BLK_SZ); ComTurbo(OFF); return(rv); } 4-18 Input Functions --------------- Basic ComGetc gets a character from the receive queue. ComGets gets a string of characters from the receive. ComIn gets a block of data from the receive queue. ComFlushRx flushes the receive queue and receiver. ComLenRx calculates the number of characters/bytes in the receive queue. Intermediate ComPeek returns a copy of the head character/byte without removing it from the receive queue. ComRxScan scans the receive queue for a specified character. 4-19 ComGetc ------------------------------------------------------------------ Function Fetches a character from the specified serial port's receive queue. Syntax #include "cport.h" char ComGetc(COM); Remarks ComGetc fetches the head character from the specified serial port's receive queue. If there are no characters in the receive queue, ComGetc returns a NULL character ('\0'). Parameters COM - Handle of the serial port. Return value If successful, ComGetc returns the character from the receive queue. If it fails, it returns a NULL character ('\0'). See also ComPutc, ComGets, ComIn, ComPeek Example Get a character from the modem and test if it is a start of header control character. #define SOH 1 int CheckForSOH(COM modem) { char c; c = ComGetc(modem); return(c == SOH); } ComGets ------------------------------------------------------------------ Function Fetches a string of characters from the specified serial port's receive queue. Syntax #include "cport.h" char *ComGets(COM, char *str, int maxc, char termc); Parameters COM - Handle of the serial port. str - Pointer to the buffer where the string of characters will be stored. maxc - Maximum number of characters to fetch. termc - Termination character. ComGets will return if this character is encountered. Remarks ComGets fetches a string of characters from the specified serial port's receive queue. The string will be stored in str. Str must be at least maxc + 1 characters long to allow for the 4-20 NULL terminator. ComGets will return on the first occurrence of one of three conditions: 1) the character termc is encountered; 2) maxc characters are reached; or 3) no more characters are available in the receive queue. Return value ComGets returns a pointer to the NULL terminated string. See also ComPuts, ComGetc, ComIn, ComLenRx Example Get a measurement from the specified instrument if one is ready. #define MEAS_SIZ 24 char* GetMeasurment(COM instrument, char* buf) { if(ComLenRx(instrument) > MEAS_SIZ) return(ComGets(instrument, buf, MEAS_SIZ, '\n')); else return(NULL); } ComIn ------------------------------------------------------------------ Function Fetches a block of bytes from the specified serial port's receive queue. Syntax #include "cport.h" unsigned ComIn(COM, void *abyte, unsigned nbyte); Parameters COM - Handle of the serial port. abyte - Pointer to a buffer where the block of bytes will be stored. nbyte - Number of bytes to get from the receive queue. Remarks ComIn fetches a block of bytes from the specified serial port's the receive queue and stores it in abyte. ComIn will always fetch num_byte bytes unless not enough bytes are available. ComIn is well suited for receiving binary data. Return value ComIn returns the number of bytes actually fetched. See also ComOut, ComGetc, ComGets, ComLenRx 4-21 Example Get a block of 1024 bytes from the serial port. #include #define BLK_SZ 1024 #define TIMEOUT -1 int GetBlock(COM datalink, byte* buf, clock_t timeout) { timeout += clock(); while(ComLenRx(datalink) < BLK_SZ) { if(clock() > timeout) return(TIMEOUT); } return(ComIn(datalink, buf, BLK_SZ)); } ComFlushRx ------------------------------------------------------------------ Function Flushes the specified serial port's receiver and receive queue. Syntax #include "cport.h" void ComFlushRx(COM); Parameters COM - Handle of the serial port. Remarks ComFlushRx deletes the specified serial port's receive queue and the UART of any existing characters/bytes. See also ComLenRx, ComFlushTx Example If a receive flush command is in order, flush the receiver. void RemoteCommand(COM com, int command) { switch(command) { case TX_FLUSH: ComFlushTx(com); break; case RX_FLUSH: ComFlushRx(com); break; ...continued } } 4-22 ComLenRx ------------------------------------------------------------------ Function Calculates the number of characters/bytes in the specified serial port's receive queue. Syntax #include "cport.h" unsigned ComLenRx(COM); Parameters COM - Handle of the serial port. Remarks ComLenRx calculates the number of characters/bytes in the specified serial port's receive queue. Return value ComLenRx returns the number of characters/bytes residing in the receive queue. See also ComFlushRx, ComLenTx Example Get a measurement from the specified instrument if one is ready. #define MEAS_SIZ 24 char* GetMeasurment(COM instrument, char* buf) { if(ComLenRx(instrument) > MEAS_SIZ) { ComGets(instrument, buf, MEAS_SIZ, '\n'); return(buf); } else return(NULL); } ComPeek ------------------------------------------------------------------ Function Fetches a copy of the head character from the specified serial port's receive queue. Syntax #include "cport.h" char ComPeek(COM); Parameters COM - Handle of the serial port. Remarks ComPeek fetches a copy of the head character from the specified serial port's receive queue. ComPeek will not remove the character from the queue. Return value ComPeek returns the copy of the head character. 4-23 See also ComGetc, ComRxScan Example Get the head character, if it is a control character. #include char GetIfControl(COM com) { char peek; peek = ComPeek(com); if(iscntrl(peek)) return(ComGetc(com)); else return('\0'); } ComRxScan ------------------------------------------------------------------ Function Scans the receive queue of the specified serial port for a specific character. Syntax #include "cport.h" unsigned ComRxScan(COM, char c); Parameters COM - Handle of the serial port. c - Character to scan for. Remarks ComRxScan searches for the character c in the specified serial port's receive queue. If the character is not found, ComRxScan returns a zero. Otherwise it returns the offset into the receive queue of the first occurrence of c starting at 1 for the first character. This is the number of characters that must be fetched to get all data up to and including the character scanned for. Return value ComRxScan returns the offset into the receive queue to the first occurrence of c. If c does not exist, ComRxScan returns a zero. See also ComPeek 4-24 Example Get the next line terminated with a '\n'. char *GetLine(COM com, char *buffer) { int n; n = ComRxScan(com, '\n'); if(n > 0 && n < 80) return(ComGets(com, buffer, n, '\n')); else return(NULL); } Example Get the next message terminated with a EOT control character. #define EOT 0x4 int GetMessage(COM com, byte *buffer) { int n; n = ComRxScan(com, EOT); if(n > 0 && n < 80) return(ComIn(com, buffer, n)); else return(0); } 4-25 Output Functions ---------------- Basic ComPutc puts a character to the transmit queue. ComPuts puts a string of characters to the transmit queue. ComOut puts a block of data to the transmit queue. ComFlushTx flushes the transmit queue and transmitter. ComLenTx calculates the number of characters in the transmit queue. Advanced ComTxWait pauses program execution until the transmitter has emptied. 4-26 ComPutc ------------------------------------------------------------------ Function Puts a character into the specified serial port's transmit queue. Syntax #include "cport.h" int ComPutc(COM, char c); Parameters COM - Handle of the serial port. c - Character to be put into the transmit queue. Remarks ComPutc puts a character into the specified serial port's transmit queue to be transmitted. If the transmit queue is full, the character is not put and ComPutc returns a 0. Return value On success, ComPutc returns a 1. If it fails, it returns 0. See also ComGetc, ComPuts, ComOut Example Echo the keyboard to the serial port when fetching a keystroke. #include static COM echo; char GetKey(void) { char c; if(kbhit()) { c = getch(); ComPutc(echo, c); return(c); } else return('\0'); } ComPuts ------------------------------------------------------------------ Function Puts a string of characters into the specified serial port's transmit queue. Syntax #include "cport.h" int ComPuts(COM, const char *str); 4-27 Parameters COM - Handle of the serial port. str - Pointer to the string to be put into the transmit queue. Remarks ComPuts puts the string str into the specified serial port's transmit queue to be transmitted. If the transmit queue becomes full, ComPuts will not attempt to put any more characters in the queue. Return value ComPuts returns the actual number of characters put into the transmit queue. See also ComGets, ComPutc, ComOut Example Dial a number on the modem. #include void ModDial(COM modem, const char* number) { char dial[24] = "ATDT"; strcat(dial, number); strcat(dial, "\r"); ComPuts(modem, dial); } ComOut ------------------------------------------------------------------ Function Puts a block of bytes into the specified serial port's transmit queue. Syntax #include "cport.h" unsigned ComOut(COM, const void *abyte, unsigned nbyte); Parameters COM - Handle of the serial port. abyte - Pointer to the block of data to be put into the transmit queue. nbyte - Number of bytes to be put into the transmit queue. Remarks ComOut puts the block of bytes pointed to by abyte into the specified serial port's transmit queue to be transmitted. Return value ComOut returns the number of bytes actually put into the transmit queue. See also ComIn, ComPutc, ComPuts 4-28 Example Send a block of 128 bytes to the transmitter. #define BLK_SZ 128 int SendBlock(COM com, const byte* block) { int rv; rv = ComOut(com, block, BLK_SZ); if(rv < BLK_SZ) return(-1); else return(0); } ComFlushTx ------------------------------------------------------------------ Function Flushes the specified serial port's transmit queue. Syntax #include "cport.h" void ComFlushTx(COM); Parameters COM - Handle of the serial port. Remarks ComFlushTx deletes any existing characters in the specified serial port's transmit queue. See also ComFlushRx, ComLenTx Example If a transmit flush command is in order, flush the transmit queue. void RemoteCommand(COM com, int command) { switch(command) { case TX_FLUSH: ComFlushTx(com); break; case RX_FLUSH: ComFlushRx(com); break; ...continued } } 4-29 ComLenTx ------------------------------------------------------------------ Function Calculates the number of characters/bytes in the specified serial port's transmit queue. Syntax #include "cport.h" unsigned ComLenTx(COM); Parameters COM - Handle of the serial port. Remarks ComLenTx calculates the number of characters/bytes in the specified serial port's transmit queue. Return value ComLenTx returns the number of characters/bytes in the transmit queue. See also ComLenRx, ComFlushTx Example Check if the transmitter has reached 3/4 of its capacity. #define TX_SIZE 1024 int IsAboveThresh(COM sprinter) { return(ComLenTx(sprinter) > (TX_SIZE * 3 / 4)); } ComTxWait ------------------------------------------------------------------ Function Waits for the specified serial port's transmitter to empty Syntax #include "cport.h" void ComTxWait(COM); Parameters COM - Handle of the serial port. Remarks When a transmit queue becomes empty, the UART may not have actually transmitted the last of the bytes. A program may need to know when all the data has actually been transmitted so that it may, for example, change the state of the hardware lines during half duplex communications. ComTxWait will return after the UART has been emptied of data. See Also ComLenTx 4-30 Example Send a string to a half duplex device. This examples assumes that the device is monitoring our RTS line to determine a transmit or receive state. void SendMessage(COM device, const char* msg) { ComRts(device, ON); ComPuts(device, msg); while(ComLenTx(device)); ComTxWait(device); ComRts(device, OFF); } 4-31 Status Functions ---------------- Basic ComError detects hardware and software errors. Intermediate ComStatus returns the status of the software and input hardware lines. ComRts controls the RTS output line. ComDtr controls the DTR output line. Advanced ComOut1 controls the general purpose OUT1 output line. ComUart determines what type of UART chip is residing at a serial port. 4-32 ComError ------------------------------------------------------------------ Function Determines if any errors have occurred on the specified serial port since the last call to ComError. Syntax #include "cport.h" unsigned ComError(COM); Parameters COM - Handle of the serial port. Remarks ComError determines if any errors are pending on the specified serial port. After a call to ComError, the errors are cleared. ComError returns a bit ORed error word. See Table A-7 in Appendix A for a list of bit definitions. Return value If an error has occurred, ComError returns an error word. If no errors have occurred, it returns a 0. See also ComStatus Example Determine the source of the error if one has occurred. #define HARDWARE (PARITY | FRAMING | BREAK | RX_FIFO) void CheckForErrors(COM dvm) { unsigned err; if((err = ComError(dvm)) == 0) return; else if(err & OVERUN) { /* over run error */ } else if(err & HARDWARE) { /* hardware errors */ } else if(err & (TXFULL | RXFULL)) { /* queue errors */ } } 4-33 ComStatus ------------------------------------------------------------------ Function Retrieves the status of the specified serial port's software and hardware lines. Syntax #include "cport.h" unsigned ComStatus(COM); Parameters COM - Handle of the serial port. Remarks ComStatus retrieves the status of the specified serial port's software and hardware lines. ComStatus returns a bit ORed status word. See Table A-8 in Appendix A for a list of bit definitions. Return value ComStatus returns the status word of the software and hardware lines. See also ComError, ComRts, ComDtr Example Test if the modem is powered up and ready. #include int CheckModem(COM modem) { ComDtr(modem, ON); delay(40); return((ComStatus(modem) & DSR) != 0); } ComRts ------------------------------------------------------------------ Function Asserts or inhibits the specified serial port's Request to Send line. Syntax #include "cport.h" void ComRts(COM, byte on_off); Parameters COM - Handle of the serial port. on_off - Determines whether RTS is to be asserted or inhibited. See Table A-10 in Appendix A. Remarks ComRts asserts or inhibits the specified serial port's RTS line depending on the value of on_off. If the value of on_off is ON, RTS is asserted. If the value of on_off is OFF, RTS is inhibited. In many cases, this signal will be looked at by the 4-34 remote device to determine if it is safe to transmit. This gives the programmer the ability to turn off the remote device's transmitter. NOTE: ComRts should never be called when RTS hardware handshaking is enabled. See also ComDtr, ComStatus, ComHandshake Example Put the device in an on or off line state. (Assumes the remote device will not send data without our RTS asserted) void OffLine(COM device) { ComRts(device, OFF); } void OnLine(COM device) { ComRts(device, ON); } ComDtr ------------------------------------------------------------------ Function Asserts or inhibits the specified serial port's Data Terminal Ready line. Syntax #include "cport.h" void ComDtr(COM, byte on_off); Parameters COM - Handle of the serial port. on_off - Determines whether DTR is to be asserted or inhibited. See Table A-10 in Appendix A. Remarks ComDtr asserts or inhibits the specified serial port's DTR line depending on the value of on_off. If the value of on_off is ON, DTR is asserted. If the value of on_off is OFF, DTR is inhibited. In many cases, this signal will be looked at by the remote device to determine if it is safe to transmit. This gives the programmer the ability to turn off the remote device's transmitter. NOTE: ComDtr should never be called when DTR hardware handshaking is enabled. See also ComRts, ComStatus, ComHandshake 4-35 Example Put the device in an on or off line state. (Assumes the remote device will not send data without our DTR asserted). void OffLine(COM device) { ComDtr(device, OFF); } void OnLine(COM device) { ComDtr(device, ON); } ComOut1 ------------------------------------------------------------------ Function Asserts or inhibits the specified serial port's Out1 line. Syntax #include "cport.h" void ComOut1(COM, byte on_off); Parameters COM - Handle of the serial port. on_off - Determines whether OUT1 is to be asserted or inhibited. See Table A-10 in Appendix A. Remarks ComOut1 asserts or inhibits the specified serial port's general purpose OUT1 line depending on the value of on_off. If the value of on_off is ON, OUT1 is asserted. If the value of on_off is OFF, OUT1 is inhibited. OUT1 is a general purpose output sometimes utilized by a device for a special feature or reset. See also ComRts, ComDtr Example Reset a smart modem. void SmartReset(COM modem) { ComOut1(modem, ON); delay(50); ComOut1(modem, OFF); } ComUart ------------------------------------------------------------------ Function Determines the type of UART at the specified serial port. Syntax #include "cport.h" int ComUart(COM); 4-36 Parameters COM - Handle of the serial port. Remarks ComUart determines the type of UART chip that resides at the specified serial port. See Table A-11 in Appendix A for a list of UART types. Return value ComUart returns a value representative of the type of UART that was detected. See Also ComNS550 Example If the specified serial port has an NS16550 UART, set the trigger level to 1 byte. void SetThreshIf550(COM com) { if(ComUart(com) == NS16550) ComNS550(com, T550_1); } 4-37 Data Integrity -------------- Intermediate ComChecksum calculates a byte checksum of a block of data. ComCrc16 calculates a 16 bit cyclic redundancy check (CRC) on a block of data. ComCrc32 calculates a 32 bit cyclic redundancy check (CRC) on a block of data. 4-38 ComChecksum ------------------------------------------------------------------ Function Performs a byte checksum calculation on a block of data. Syntax #include "cport.h" byte ComChecksum(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the checksum is to be performed. nbyte - Number of bytes in the block. Remarks ComChecksum performs a byte checksum on the block of bytes pointed to by abyte. The checksum is calculated by summing all the bytes in the block. Return value ComChecksum returns a one byte checksum. See also ComCrc16, ComCrc32, ComIn, ComOut Example Verify that the actual checksum matches the received checksum. struct Xblock{ byte num; byte _num; byte data[128]; byte checksum; }block; int GetXblock(COM com, Xblock *block) { ComIn(com, block, sizeof(Xblock)); if((ComChecksum(block->data, 128) - block->checksum) != 0) return(-1); else return(0); } ComCrc16 ------------------------------------------------------------------ Function Performs a 16 bit cyclic redundancy check on a block of data. Syntax #include "cport.h" unsigned ComCrc16(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the 16 bit cyclic redundancy check is to be performed. nbyte - Number of bytes in the block. 4-39 Remarks ComCrc16 performs a 16 bit cyclic redundancy check on the block of data pointed to by abyte. Return value ComCrc16 returns the 16 bit CRC value. See also ComCrc32, ComChecksum, ComIn, ComOut Example Verify that the actual CRC matches the received CRC. struct Xblock{ byte num; byte _num; byte data[128]; unsigned crc; }block; int GetXblock(COM com, Xblock *block) { ComIn(com, block, sizeof(Xblock)); /* Check the calculated CRC against the block's CRC. */ if(ComCrc16(block->data, 128) != block->crc) return(-1); else return(0); } ComCrc32 ------------------------------------------------------------------ Function Performs a 32 bit cyclic redundancy check on a block of data. Syntax #include "cport.h" unsigned long ComCrc32(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the 32 bit cyclic redundancy check is to be performed. nbyte - Number of bytes in the block. Remarks ComCrc32 performs a 32 bit cyclic redundancy check on the block of data pointed to by abyte. Return value ComCrc32 returns the 32 bit CRC value. See also ComCrc16, ComChecksum, ComIn, ComOut 4-40 Example Verify that the actual CRC matches the received CRC. struct Packet { byte num; byte data[1024]; unsigned long crc; }packet; int GetBlock(COM com, Packet* packet) { ComIn(com, packet, sizeof(Packet)); /* Check the calculated CRC against the packet's CRC. */ if(ComCrc32(packet->data, 1024) != packet->crc) return(-1); else return(0); } 4-41 Misc Functions -------------- Advanced ComSetBreak sets a break condition. ComClrBreak clears a break condition. ComPutScrtch writes to the UART's scratch register. ComGetScrtch reads the UART's scratch register. 4-42 ComSetBreak ------------------------------------------------------------------ Function Set a break condition on the specified serial port. Syntax #include "cport.h" void ComSetBreak(COM); Parameters COM - Handle of the serial port. Remarks ComSetBreak sets a break condition on the specified serial port. The break condition will stay in effect until a subsequent call to ComClrBreak is made. See also ComClrBreak Example If the an abort condition has been declared, set a break condition. When it clears, release the break condition. void Abort(COM com, int abrt) { static int brkflg; if(abrt && !brkflg) ComSetBreak(com); else if(!abrt && brkflg) ComClrBreak(com); } ComClrBreak ------------------------------------------------------------------ Function Clears a previously set break condition on the specified serial port. Syntax #include "cport.h" void ComClrBreak(COM); Parameters COM - Handle of the serial port. Remarks ComClrBreak clears a previously set break condition on the specified serial port. See also ComSetBreak 4-43 Example If the an abort condition has been declared, set a break condition. When it clears, release the break condition. void Abort(COM com, int abrt) { static int brkflg; if(abrt && !brkflg) ComSetBreak(com); else if(!abrt && brkflg) ComClrBreak(com); } ComPutScrtch ------------------------------------------------------------------ Function Writes a byte to the specified serial port's scratch register. Syntax #include "cport.h" void ComPutScrtch(COM, byte abyte); Parameters COM - Handle of the serial port. abyte - The byte to be written to the scratch register. Remarks ComPutScrtch writes the byte value abyte to the specified serial port's UART scratch register. Not all UARTs have a scratch register. See also ComGetScrtch Example Exchange a value with the scratch register. byte ScratchExchange(COM com, byte value) { byte rv; rv = ComGetScrtch(com); /* read the scratch register */ ComPutScrtch(com, value); /* write to the scratch register */ return(rv); } ComGetScrtch ------------------------------------------------------------------ Function Fetches the byte stored in the specified serial port's scratch register. Syntax #include "cport.h" byte ComGetScrtch(COM); 4-44 Parameters COM - Handle of the serial port. Remarks ComGetScratch reads the byte in the specified serial port's UART scratch register. Not all UARTs have a scratch register. Return value ComGetScrtch returns the byte read from the UART scratch register. See also ComPutScrtch Example Exchange a value with the scratch register. byte ScratchExchange(COM com, byte value) { byte rv; rv = ComGetScrtch(com); /* read the scratch register */ ComPutScrtch(com, value); /* write to the scratch register */ return(rv); } 5-1 C++ Reference ============= Control Functions ----------------- Basic Cport::Cport constructs serial port instance with either discrete parameters or a structure of parameters. Cport::operator int returns the results of constructing a serial port instance. Cport::Handshake determines if and what type of handshaking scheme will be enabled and sets the receive queue threshold. Intermediate Cport::Param reports on the current parameters and handshaking under which a serial port is currently operating. Cport::Baud changes the baud rate. Cport::Mode changes the word length, number of stop bits and parity. Advanced Cport::RxQ resizes the receive queue. Cport::TxQ resizes the transmit queue. Cport::Tx allows advanced control over the transmitter. Cport::NS550 sets the receive fifo threshold of an NS16550 UART. Cport::Turbo temporarily disables/re-enables selected high priority interrupts that may impede high speed communications. 5-2 Cport::Cport ------------------------------------------------------------------ Function Constructor. Syntax #include "cport.h" Cport::Cport(unsigned id, int baud, byte mode = W8|S1|NONE, unsigned rxQ = 1024, unsigned txQ = 512, byte htype = OFF); or Cport::Cport(unsigned id, int baud, byte mode, unsigned rxQ, unsigned txQ, byte htype, unsigned thresh); or Cport::Cport(const CPARAM& param) Parameters id - Value that identifies the serial port. The upper 4 bits define the interrupt request line, while the lower 12 bits define the port address. This technique allows for possibility of custom configurations. See Table A-1 in Appendix A for a list of predefined values. baud - Value that defines the baud rate. The actual value is the baud rate divisor, which allows for the possibility of custom baud rates. The baud rate divisor = f / (16 * baud rate) where f is 1.8432e+6. See Table A-2 in Appendix A for a list of predefined baud rate divisors. mode - Bit ORed value defining the word length, number of stop bits and the parity. See Table A-3 in Appendix A for a list of mode components. * rxQ - Size, in bytes, of the receive queue. * txQ - Size, in bytes, of the transmit queue. * Limited to 32K in small and medium memory models. htype - Type of handshaking to be used. See Table A-5 in Appendix A for a list of handshaking components. thresh - Receive queue threshold. Remarks The constructor creates an instance of the specified serial port. If the constructor is unable to open the specified serial port, the instance of the serial port will return an error code when casted to an integer. If the port is successfully opened, the instance will return a zero when casted to an integer. The 4 most significant bits in id represent the interrupt vector. The lower 12 bits represent the port address. Constants are provided to facilitate the formulation of the id parameter. The COMx values will work in most cases, however, 5-3 the IRQx values can be ORed with the PORTx or BIOSx values to produce other combinations. The PORTx values are actual port addresses where the serial ports are normally located. The BIOSx values are actually macros, which fetch the port address from the BIOS data area. The parameter baud is the baud rate divisor, that determines the baud rate. Achieving baud rates above 19200 is largely dependent on many variables, such as machine speed, cable length, handshaking activity, degree bidirectional transfers, number of open serial ports, the type UART(s) used and activity of other hardware interrupts. The parameter mode determines the word length, number of stop bits and parity. Bits 0 and 1 determine the word length, bit 2 determines the number of stop bits, bit 3 enables parity and bits 4 and 5 determine the type of parity check. RxQ and txQ set the size of the receive and transmit queues respectively. RxQ should be at least 4 times larger than the largest string or block of data expected. TxQ can be set as small as 1, but it is not recommended. In the small and medium memory models where all data is limited to 64K, the size of the queues are limited. In the compact and large memory models, each queue can be as large as 64K -1 (65534 bytes). See Also Cport::operator int Example Open COM1 at 9600 baud with 8 bit words, 1 stop bit, no parity, a 1024 byte receiver and a 512 byte transmitter. int main(void) { Cport com1(COM1, B9600, W8|S1|NONE, 1024, 512); if((int)com1 != NO_ERR) { switch(com1) { case RX_ALC: case TX_ALC: case GEN_ALC: // allocation error break; case NO_UART: // no UART break; default: // all other errors break; } } ...continued 5-4 Cport::operator int ------------------------------------------------------------------ Function Gets the error code from when the instance of the serial port was constructed. Syntax #include "cport.h" Cport::operator int() Remarks When an instance of a serial port is constructed, the specified serial port is not necessarily successfully opened. Cport::operator int is an integer typecast used for procuring the error code from when an instance of the serial port was constructed. The actual typecasting may or may not be necessary, but is recommended. Return value Cport::operator int returns an error code from when the instance of the serial port was constructed. See Table A-4 in Appendix A for a list of possible return values. See Also Cport::Cport Example Check for errors after instance of a serial port is constructed. int main(void) { Cport com1(COM1, B9600, W8|S1|NONE, 1024, 512); // The instance 'com1' is casted to an int to procure the // error code. // if((int)com1 != NO_ERR) { switch(com1) { case RX_ALC: case TX_ALC: case GEN_ALC: // allocation error break; case NO_UART: // no UART break; default: // all other errors break; } } ...continued 5-5 Cport::Handshake ------------------------------------------------------------------ Function Enables or disables handshaking (flow control ) for a serial port. Syntax #include "cport.h" void Cport::Handshake(byte htype, unsigned thresh); Parameters htype - Type of handshaking to be used. See Table A-5 in Appendix A for a list of handshaking components. thresh - Receive queue threshold. Remarks Cport::Handshake enables or disables software and/or hardware handshaking for the serial port instance. In software handshaking, XON and XOFF characters are used to suspend and resume communications. Hardware handshaking uses any or all of the DTR, DSR, RTS, CTS and DCD lines to suspend and resume communications. Thresh determines when the receiver will assert and inhibit the corresponding handshaking. If no receive handshaking is specified (RTS, DTR or S_RX), the threshold is not used and may be set to zero. See also Cport::Param, Cport::Cport, Cport::Tx Example If COM1 is successfully opened, turn on some hardware handshaking and set the receiver threshold to 3/4 of the receiver's full size. The transmitter will not transmit unless both DSR and DCD are asserted. The receiver will inhibit DTR if the receive queue length exceeds the threshold. int main(void) { Cport com1(COM1, B9600, W8|S1|NONE, 1024, 512); if((int)com1 != NO_ERR) { // error } com1.Handshake(DSR|DTR|DCD, 768); ...continued return(0); } 5-6 Cport::Param ------------------------------------------------------------------ Function Retrieves the parameters of a serial port. Syntax #include "cport.h" Cport::Param(CPARAM& param) Parameters param - Reference to a type CPARAM where the parameters will be stored. Remarks Cport::Param retrieves the parameters and handshaking status of the serial port instance and stores them in a type CPARAM. See also CPARAM, Cport::Cport Example Create an instance of a serial port with the same configuration as one that already exists. Cport OpenCopy(int id, Cport& copyme) { CPARAM param; copyme.Param(param); param.id = id; return(Cport(param)); } Cport::Baud ------------------------------------------------------------------ Function Changes the baud rate of a serial port. Syntax #include "cport.h" void Cport::Baud(int baud); Parameters baud - Value that defines the baud rate. The actual value is the baud rate divisor, which allows for possibility of custom baud rates. The baud rate divisor = f / (16 * baud rate) where f is 1.8432e+6. See Table A-2 in Appendix A for a list of predefined baud rate divisors. Remarks Cport::Baud changes the baud rate of the serial port instance. The parameter baud is the baud rate divisor that determines the baud rate. See also Cport::Cport, Cport::Param, Cport::Mode 5-7 Example Set the specified serial port to a new baud rate. #define NBAUD 4 int SetBaud(Cport& com, unsigned n) { int baud[NBAUD] = { B9600, B2400, B1200, B300 }; if(n < NBAUD) { com.Baud(baud[n]); return(0); } else return(-1); } Cport::Mode ------------------------------------------------------------------ Function Changes the word length, number of stop bits and parity of a serial port. Syntax #include "cport.h" void Cport::Mode(byte mode); Parameters mode - Bit ORed value defining the word length, number of stop bits and the parity. See Table A-3 in Appendix A for a list of mode components. Remarks Cport::Mode changes the word length, number of stop bits and parity of the serial port instance. The parameter mode determines the word length, number of stop bits and parity of the serial port instance. Bits 0 and 1 determine the word length, bit 2 determines the number of stop bits, bit 3 enables parity and bits 4 and 5 determine the type of parity check. See also Cport::Cport, Cport::Param, Cport::Baud Example Set the serial port to a new mode. #define NMODE 2 int SetMode(Cport& com, unsigned n) { int mode[NMODE] = { W8|S1|NONE, W7|S1|EVEN }; if(n < NMODE) { com.Mode(mode[n]); return(0); } return(-1); } 5-8 Cport::RxQ ------------------------------------------------------------------ Function Resizes the receive queue of a serial port. Syntax #include "cport.h" unsigned Cport::RxQ(unsigned size); Parameters size - New receive queue size. Remarks Cport::RxQ resizes the receive queue of the serial port instance. The memory currently allocated for the receive queue is freed and new memory is allocated. If Cport::RxQ is unable to allocate the specified amount memory, it will try to reallocate memory for the previous size. Cport::RxQ returns the new queue size. If memory was successfully allocated for the new size, the return value will be size. If the previous size is reallocated, the return value will be the previous size. If no memory could be allocated, Cport::RxQ returns zero. No data can be received while the new receive queue is being resized. However, data in the transmit queue will continue to be transmitted normally. Return value Cport::RxQ returns the new receive queue size. See also Cport::TxQ, Cport::Cport Example Enlarge the receive queue for a file transfer. #define LARGE_RX 4096 int ReceiveFile(Cport& com, const char *filename) { CPARAM param; com.Param(param); if(com.RxQ(LARGE_RX) != LARGE_RX) return(-1); ... transfer file here // Restore original size if(com.RxQ(param.rxQ) != param.rxQ) return(-2); else return(0); } 5-9 Cport::TxQ ------------------------------------------------------------------ Function Resizes the transmit queue of a serial port. Syntax #include "cport.h" unsigned Cport::TxQ(unsigned size); Parameters size - New transmit queue size. Remarks Cport::TxQ resizes the transmit queue of the serial port instance. The memory currently allocated for the transmit queue is freed and new memory is allocated. If Cport::TxQ is unable to allocate the specified amount memory, it will try to reallocate memory for the previous size. Cport::TxQ returns the new queue size. If memory was successfully allocated for the new size, the return value will be size. If the previous size is reallocated, the return value will be the previous size. If no memory could be allocated, Cport::TxQ returns zero. No data can be transmitted while the new transmit queue is being resized. However, data in the receive queue will continue to be received normally. Return value ComTxQ returns the new transmit queue size. See also Cport::RxQ, Cport::Cport Example Enlarge the transmit queue for a file transfer. #define LARGE_TX 4096 int TransmitFile(Cport& com, const char *filename) { CPARAM param; com.Param(param); if(com.TxQ(LARGE_TX) != LARGE_TX) return(-1); ... transfer file here // Restore original size if(com.TxQ(param.txQ) != param.txQ) return(-2); else return(0); } 5-10 Cport::Tx ------------------------------------------------------------------ Function Transmitter control. Syntax #include "cport.h" int Cport::Tx(int cmnd); Parameters cmnd - Determines the action to be taken on the transmitter See Table A-9 in Appendix A for a list of transmitter options. Remarks Cport::Tx allows advanced control of the Cport transmitter The transmitter can be turned off and on to suspend and resume transmissions. This function can be very useful when implementing your own handshaking scheme. In addition, it can inform the output functions to transmit directly when the transmitter is turned off. Return value Cport::Tx returns the previous status of the transmitter. See also Cport::Handshake, Cport::Cport, Cport::Param Example Put a priority character directly to the serial port. void PriorityPutc(Cport& com, char c) { int tx; tx = com.Tx(TX_DIRECT | OFF); com.Put(c); com.Tx(tx); } Cport::NS550 ------------------------------------------------------------------ Function NS16550 UART setup. Syntax #include "cport.h" void Cport::NS550(int trigger); Parameters trigger - Trigger threshold for the UART receive fifo. See Table A-12 in Appendix A for a list of trigger levels. Remarks If Cport detects an NS16550 UART when a serial port is opened, Cport automatically takes advantage of it's advanced capabilities. The receive fifo threshold is the number of bytes in the receive fifo that will cause an interrupt to be generated. By default, the receive fifo threshold is set to 14 bytes. Cport::NS550 allows this receive fifo trigger threshold to be changed. 5-11 See Also Cport::Uart Example If the specified serial port is an NS16550, set the trigger level to 1 byte. void SetThreshIf550(Cport& com) { if(com.Uart() == NS16550) com.NS550(T550_1); } Cport::Turbo ------------------------------------------------------------------ Function Disables/re-enables high priority interrupts. Syntax #include "cport.h" static void Cport::Turbo(int options); Parameters options - Bit mask of options. See Table A-6 in Appendix A for a list of turbo options. Remarks During high speed data exchanges certain events that cause high priority interrupts can impede serial communications and possibly cause (over run) errors. This is especially true of the timer, which periodically uses extra time, and the keyboard, if keys are pressed. Cport::Turbo disables selected high priority interrupts or restores all of them. The high priority interrupts should never be disabled permanently or for long periods of time. The timer interrupt is not actually disabled but divert, allowing the system clock to continue to update. All other options are actually disabled when specified. Cport::Turbo is a static function. Although not very useful, it can be called prior to and/or independent of any instance of a serial port by specifying it's full name: Cport::Turbo(options). Example Disable the keyboard and divert the timer while a block is transferred at high speed. 5-12 #include #define BLK_SZ 128 int GetBlock(Cport& com, byte* block, clock_t timeout) { int rv; // assume 115200 baud // com.Turbo(TIMER | KEYBOARD); timeout += clock(); while(com.LenRx() < BLK_SZ) { if(clock() > timeout) { com.Turbo(OFF); return(0); } } rv = com.In(block, BLK_SZ); com.Turbo(OFF); return(rv); } 5-13 Input Functions --------------- Basic Cport::Get gets a character or string of characters from the receive queue. Cport::In gets a block of data from the receive queue. Cport::FlushRx flushes the receive queue and receiver. Cport::LenRx calculates the number of characters/bytes in the receive queue. Intermediate Cport::Peek returns a copy of the head character/byte without removing it from the receive queue. Cport::RxScan scans the receive queue for a specified character. 5-14 Cport::Get ------------------------------------------------------------------ Function Fetches a character or string of characters from a serial port's receive queue. Syntax #include "cport.h" char* Cport::Get(char *str, int maxc, char termc = '\n'); or char Cport::Get(); Parameters str - Pointer to the buffer where the string of characters will be stored. maxc - Maximum number of characters to fetch. termc - Termination character. Cport::Get will return if this character is encountered. Remarks Cport::Get fetches a character or string of characters from the serial port instance's receive queue. If Cport::Get is called with no parameters, it will fetch one character from the head of the serial port instance's receive queue. If there are no characters in the receive queue, Cport::Get returns a NULL character ('\0'). If Cport::Get is called with parameters, it fetches a string of characters from the serial port instance's receive queue. The string will be stored in str. Str must be at least maxc + 1 characters long to allow for the NULL terminator. Cport::Get will return on the first occurrence of one of three conditions: 1) the character termc is encountered; 2) maxc characters are reached; or 3) no more characters are available in the receive queue. Return value When Cport:Get is called with no parameters, on success it returns the character from the receive queue. If it fails, it returns a NULL character ('\0'). When it is called with parameters, Cport::Get returns a pointer to the NULL terminated string. See also Cport::In, Cport::LenRx, Cport::Put 5-15 Example Get a measurement from the specified instrument if one is ready. #define MEAS_SIZ 24 char* GetMeasurment(Cport& instrument, char* buf) { if(instrument.LenRx() > MEAS_SIZ) { instrument.Get(buf, MEAS_SIZ, '\n'); return(buf); } else return(NULL); } Example Get a character from the modem and test if it is a start of header control character. #define SOH 1 int CheckForSOH(Cport& modem) { char c; c = modem.Get(); return(c == SOH); } Cport::In ------------------------------------------------------------------ Function Fetches a block of bytes from a serial port's receive queue. Syntax #include "cport.h" unsigned Cport::In(void *abyte, unsigned nbyte); Parameters abyte - Pointer to a buffer where the block of bytes will be stored. nbyte - Number of bytes to get from the receive queue. Remarks Cport::In fetches a block of bytes from the serial port instance's receive queue and stores it in abyte. Cport::In will always fetch num_byte bytes unless not enough bytes are available. Cport::In is well suited for receiving binary data. Return value Cport::In returns the number of bytes actually fetched. See also Cport::Out, Cport::Get, Cport::LenRx 5-16 Example Get a block of 1024 bytes from the serial port. #include #define BLK_SZ 1024 #define TIMEOUT -1 int GetBlock(Cport& datalink, byte* buf, clock_t timeout) { timeout += clock(); while(datalink.LenRx() < BLK_SZ) { if(clock() > timeout) return(TIMEOUT); } return(datalink.In(buf, BLK_SZ)); } Cport::FlushRx ------------------------------------------------------------------ Function Flushes a serial port's receiver and receive queue. Syntax #include "cport.h" void Cport::FlushRx(); Remarks Cport::FlushRx deletes all existing characters/bytes in the serial port instance's receive queue and receiver. See also Cport::LenRx, Cport::FlushTx Example If a receive flush command is in order, flush the receiver. void RemoteCommand(Cport& com, int command) { switch(command) { case TX_FLUSH: com.FlushTx(); break; case RX_FLUSH: com.FlushRx(); break; ...continued } } 5-17 Cport::LenRx ------------------------------------------------------------------ Function Calculates the number of characters/bytes in the receive queue of a serial port. Syntax #include "cport.h" unsigned Cport::LenRx(); Remarks Cport::LenRx calculates the number of characters/bytes in the receive queue of the serial port instance. Return value Cport::LenRx returns the number of characters/bytes residing in the receive queue. See also Cport::FlushRx, Cport::LenTx Example Get a measurement from the specified instrument if one is ready. #define MEAS_SIZ 24 char* GetMeasurment(Cport& instrument, char* buf) { if(instrument.LenRx() > MEAS_SIZ) { instrument.Get(buf, MEAS_SIZ, '\n'); return(buf); } else return(NULL); } Cport::Peek ------------------------------------------------------------------ Function Fetches a copy of the head character from a serial port's receive queue. Syntax #include "cport.h" char Cport::Peek(); Remarks Cport::Peek fetches a copy of the head character from the serial port instance's receive queue. Cport::Peek will not remove the character from the queue. Return value Cport::Peek returns the copy of the head character. See also Cport::Get, Cport::RxScan 5-18 Example Get the head character if it is a control character. #include char GetIfControl(Cport& com) { char peek; peek = com.Peek(); if(iscntrl(peek)) return(com.Get()); else return('\0'); } Cport::RxScan ------------------------------------------------------------------ Function Scans the receive queue of a serial port for a specific character. Syntax #include "cport.h" unsigned Cport::RxScan(char c); Parameters c - Character to scan for. Remarks Cport::RxScan searches for the character c in the serial port instance's receive queue. If the character is not found, Cport::RxScan returns a zero. Otherwise, it returns the offset into the receive queue of the first occurrence of c starting at 1 for the head character. This is the number of characters that must be fetched to get all data up to and including the character scanned for. Return value Cport::Peek returns the offset into the receive queue to the first occurrence of c. If c does not exist, Cport::RxScan returns a zero. See also Cport::Peek, Cport::Get Example Get the next line terminated with a '\n'. char *GetLine(Cport& com, char *buffer) { int n; n = com.RxScan('\n'); if(n > 0 && n < 80) return(com.Get(buffer, n, '\n')); else return(NULL); } 5-19 Output Functions ---------------- Basic Cport::Put puts a character or a string of characters to the transmit queue. Cport::Out puts a block of data to the transmit queue. Cport::FlushTx flushes the transmit queue and transmitter. Cport::LenTx calculates the number of characters/bytes in the transmit queue. Advanced Cport::TxWait pauses program execution until the transmitter has emptied. 5-20 Cport::Put ------------------------------------------------------------------ Function Puts a character or a string of characters into the serial port's transmit queue. Syntax #include "cport.h" int Cport::Put(const char *str); or int Cport::Put(char c); Parameters str - Pointer to the string to be put into the transmit queue. c - Character to be put into the transmit queue. Remarks Cport::Put puts a character (c) or a string of characters (str) into the serial port a instance's transmit queue to be transmitted. If the transmit queue becomes full, Cport::Put will not attempt to put any more characters in the queue. Return value Cport::Put returns the actual number of characters put into the transmit queue. For single characters, this value will be either 0 or 1. See also Cport::Out, Cport::Get, Cport::LenTx Example Echo the keyboard to the serial port when fetching a keystroke. #include static Cport echo(COM2, B9600, W8|S1|NONE ,1024 , 64); char GetKey(void) { char c; if(kbhit()) { c = getch(); echo.Put(c); return(c); } else return('\0'); } 5-21 Example Dial a number on the modem. #include void ModDial(Cport& modem, const char* number) { char dial[24] = "ATDT"; strcat(dial, number); strcat(dial, "\r"); modem.Put(dial); } Cport::Out ------------------------------------------------------------------ Function Puts a block of bytes into a serial port's transmit queue. Syntax #include "cport.h" unsigned Cport::Out(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block to be put into the transmit queue. nbyte - Number of bytes to be put into the transmit queue. Remarks Cport::Out puts the block of bytes pointed to by abyte into the serial port instance's transmit queue to be transmitted. Return value Cport::Out returns the number of bytes actually put into the transmit queue. See also Cport::In, Cport::Put, Cport::LenTx Example Send a block of 128 bytes to the transmitter. #define BLK_SZ 128 int SendBlock(Cport& com, byte* block) { int rv; rv = com.Out(block, BLK_SZ); if(rv < BLK_SZ) return(-1); else return(0); } 5-22 Cport::FlushTx ------------------------------------------------------------------ Function Flushes a serial port's transmit queue. Syntax #include "cport.h" void Cport::FlushTx(); Remarks Cport::FlushTx deletes any existing characters in the serial port instance's transmit queue. See also Cport::FlushRx, Cport::LenTx Example If a transmit flush command is in order, flush the transmit queue. void RemoteCommand(Cport& com, int command) { switch(command) { case TX_FLUSH: com.FlushTx(); break; case RX_FLUSH: com.FlushRx(); break; ...continued } } Cport::LenTx ------------------------------------------------------------------ Function Calculates the number of characters/bytes in a serial port's transmit queue. Syntax #include "cport.h" unsigned Cport::LenTx(); Remarks Cport::LenTx calculates the number of characters/bytes in the serial port instance's transmit queue. Return value Cport::LenTx returns the number of characters/bytes in the transmit queue. See also Cport::LenRx, Cport::FlushTx Example Check if the transmitter has reached 3/4 of capacity. #define TX_SIZE 1024 int IsAboveThresh(Cport& sprinter) { return(sprinter.LenTx() > (TX_SIZE * 3 / 4)); } 5-23 Cport::TxWait ------------------------------------------------------------------ Function Waits for a serial port's transmitter to empty Syntax #include "cport.h" void Cport::TxWait(); Remarks When a transmit queue becomes empty, the UART may not have actually transmitted the last of the bytes. A program may need to know when all the data has actually been transmitted so that it may, for example, change the state of the hardware lines. Cport::TxWait will return after the UART has been emptied of data. See Also Cport::LenTx Example Send a string to a half duplex device. This examples assumes that the device is monitoring our RTS line to determine a transmit or receive state. void SendMessage(Cport device, const char* msg) { device.Rts(ON); device.Put(msg); while(device.LenTx()); device.TxWait(); device.Rts(OFF); } 5-24 Status Functions ---------------- Basic Cport::Error detects hardware and software errors. Intermediate Cport::Status returns the status of the software and input hardware lines. Cport::Rts controls the RTS output line. Cport::Dtr controls the DTR output line. Advanced Cport::Out1 controls the general purpose OUT1 output line. Cport::Uart determines what type of UART chip is residing at a serial port. 5-25 Cport::Error ------------------------------------------------------------------ Function Determines if any errors have occurred on a serial port since the last call to Cport::Error. Syntax #include "cport.h" unsigned Cport::Error(); Remarks Cport::Error determines if any errors are pending on the serial port instance. After a call to Cport::Error, the errors are cleared. Cport::Error returns a bit ORed error word. See Table A-7 on Appendix A for a list of bit definitions. Return value If an error has occurred, Cport::Error returns an error word. If no errors have occurred, it returns a 0. See also Cport::Status Example Determine the source of the error if one has occurred. #define HARDWARE (PARITY | FRAMING | BREAK | RX_FIFO) void CheckForErrors(Cport& dvm) { unsigned err; if((err = dvm.Error()) == 0) return; else if(err & OVERUN) { // over run error } else if(err & HARDWARE) { // hardware errors } else if(err & (TXFULL | RXFULL)) { // queue errors } } Cport::Status ------------------------------------------------------------------ Function Retrieves the status of a serial port's software and hardware lines. Syntax #include "cport.h" unsigned Cport::Status(); 5-26 Remarks Cport::Status retrieves the status of the serial port instance's software and hardware lines. Cport::Status returns a bit ORed status word. See Table A-8 in Appendix A for a list of bit definitions. Return value Cport::Status returns the status word of the software and hardware lines. See also Cport::Error, Cport::Rts, Cport::Dtr Example Test if the modem is powered up and ready. #include int CheckModem(Cport& modem) { modem.Dtr(ON); delay(40); return((modem.Status() & DSR) != 0); } Cport::Rts ------------------------------------------------------------------ Function Sets or clears a serial port's Request to Send line. Syntax #include "cport.h" void Cport::Rts(byte on_off); Parameters on_off - Determines whether RTS is to be set or cleared. See Table A-10 in Appendix A. Remarks Cport::Rts sets or clears the serial port instance's RTS line, depending on the value of on_off. If the value of on_off is ON, RTS is asserted. If the value of on_off is OFF, RTS is inhibited. In many cases, this signal will be looked at by the remote device to determine if it is safe to transmit. This gives the programmer the ability to turn off the remote device's transmitter. NOTE: Cport::Rts should never be called when RTS hardware handshaking is enabled. See also Cport::Dtr, Cport::Status, Cport::Handshake 5-27 Example Put the device in an on or off line state. (Assumes the remote device will not send data without our RTS asserted) void OffLine(Cport& device) { device.Rts(OFF); } void OnLine(Cport& device) { device.Rts(ON); } Cport::Dtr ------------------------------------------------------------------ Function Sets or clears a serial port's Data Terminal Ready line. Syntax #include "cport.h" void Cport::Dtr(byte on_off); Parameters on_off - Determines whether DTR is to be asserted or inhibited. See Table A-10 in Appendix A. Remarks Cport::Dtr set or clears the serial port instance's DTR line, depending on the value of on_off. If the value of on_off is ON, DTR is asserted. If the value of on_off is OFF, DTR is inhibited. In many cases, this signal will be looked at by the remote device to determine if it is safe to transmit. This gives the programmer the ability to turn off the remote device's transmitter. NOTE: Cport::Dtr should never be called when DTR hardware handshaking is enabled. See also Cport::Rts, Cport::Status, Cport::Handshake Example Put the device in an on or off line state. (Assumes the remote device will not send data without our DTR asserted). void OffLine(Cport& device) { device.Dtr(OFF); } void OnLine(Cport& device) { device.Dtr(ON); } 5-28 Cport::Out1 ------------------------------------------------------------------ Function Sets or clears a serial port's Out1 line. Syntax #include "cport.h" void Cport::Out1(byte on_off); Parameters on_off - Determines whether OUT1 is to be asserted or inhibited. See Table A-10 in Appendix A. Remarks Cport::Out1 sets or clears the serial port instance's general purpose OUT1 line depending on the value of on_off. If the value of on_off is ON, OUT1 is asserted. If the value of on_off is OFF, OUT1 is inhibited. OUT1 is a general purpose output sometimes utilized by a device for a special feature or reset. See also Cport::Rts, Cport::Dtr Example Reset a smart modem. void SmartReset(Cport& modem) { modem.Out1(ON); delay(50); modem.Out1(OFF); } Cport::Uart ------------------------------------------------------------------ Function Determines the type of UART at a serial port. Syntax #include "cport.h" int Cport::Uart(); Remarks Cport::Uart determines the type of UART chip that resides at the instance's serial port. See Table A-11 for a list of UART types. Return value Cport::Uart returns a value representative of the type of UART that was detected. See Also Cport::NS550 Example If the serial port instance has an NS16550 UART, set the trigger level to 1 byte. void SetThreshIf550(Cport& com) { if(com.Uart() == NS16550) com.NS550(T550_1); } 5-29 Data Integrity -------------- Intermediate Cport::Checksum calculates a byte checksum of a block of data. Cport::Crc16 calculates a 16 bit cyclic redundancy check (CRC) on a block of data. Cport::Crc32.calculates a 32 bit cyclic redundancy check (CRC) on a block of data. 5-30 Cport::Checksum ------------------------------------------------------------------ Function Performs a byte checksum calculation on a block of data. Syntax #include "cport.h" static byte Cport::Checksum(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the checksum is to be performed. nbyte - Number of bytes in the block. Remarks Cport::Checksum performs a byte checksum on the block of bytes pointed to by abyte. The checksum is calculated by summing all the bytes in the block. Return value Cport::Checksum returns a one byte checksum. See also Cport::Crc16, Cport::Crc32, Cport::In, Cport::Out Example Verify that the actual checksum matches the received checksum. struct Xblock { byte num; byte _num; byte data[128]; byte checksum; }block; int GetXblock(Cport& com, Xblock& block) { com.In(&block, sizeof(Xblock)); if((com.Checksum(block.data, 128) - block.checksum) != 0) return(-1); else return(0); } Cport::Crc16 ------------------------------------------------------------------ Function Performs a 16 bit cyclic redundancy check on a block of data. Syntax #include "cport.h" static unsigned ComCrc16(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the 16 bit cyclic redundancy check is to be performed. 5-31 nbyte - Number of bytes in the block. Remarks Cport::Crc16 performs a 16 bit cyclic redundancy check on the block of data pointed to by abyte. Return value Cport::Crc16 returns the 16 bit CRC value. See also Cport::Crc32, Cport::Checksum, Cport::In, Cport::Out Example Verify that the actual CRC matches the received CRC. struct Xblock{ byte num; byte _num; byte data[128]; unsigned crc; }block; int GetXblock(Cport& com, Xblock& block) { com.In(&block, sizeof(Xblock)); // Check the calculated CRC against the block CRC. // if(com.Crc16(block.data, 128) != block.crc) return(-1); else return(0); } Cport::Crc32 ------------------------------------------------------------------ Function Performs a 32 bit cyclic redundancy check on a block of data. Syntax #include "cport.h" static unsigned long ComCrc32(const void *abyte, unsigned nbyte); Parameters abyte - Pointer to the block on which the 32 bit cyclic redundancy check is to be performed. nbyte - Number of bytes in the block. Remarks Cport::Crc32 performs a 32 bit cyclic redundancy check on the block of data pointed to by abyte. Return value Cport::Crc32 returns the 32 bit CRC value. See also Cport::Crc16, Cport::Checksum, Cport::In, Cport::Out 5-32 Example Verify that the actual CRC matches the received CRC. struct Packet { byte num; byte data[1024]; unsigned long crc; }packet; int GetPacket(Cport& com, Packet& packet) { com.In(&packet, sizeof(Packet)); // Check the calculated CRC against the packet's CRC. // if(com.Crc32(packet.data, 1024) != packet.crc) return(-1); else return(0); } 5-33 Misc Functions -------------- Advanced Cport::SetBreak sets a break condition. Cport::ClrBreak clears a break condition. Cport::Scratch writes to or reads from the UART's scratch register. 5-34 Cport::SetBreak ------------------------------------------------------------------ Function Set a break condition on a serial port. Syntax #include "cport.h" void Cport::SetBreak(); Remarks Cport::SetBreak sets a break condition on the serial port instance. The break condition will stay in effect until a subsequent call to Cport::ClrBreak is made. See also Cport::ClrBreak Example If the an abort condition has been declared, set a break condition. When it clears, release the break condition. void Abort(Cport& com, int abrt) { static int brkflg; if(abrt && !brkflg) com.SetBreak(); else if(!abrt && brkflg) com.ClrBreak(); } Cport::ClrBreak ------------------------------------------------------------------ Function Clears a previously set break condition on a serial port. Syntax #include "cport.h" void Cport::ClrBreak(); Remarks Cport::ClrBreak clears a previously set break condition on the serial port instance. See also Cport::SetBreak Example If the an abort condition has been declared, set a break condition. When it clears, release the break condition. void Abort(Cport& com, int abrt) { static int brkflg; if(abrt && !brkflg) com.SetBreak(); else if(!abrt && brkflg) com.ClrBreak(); } 5-35 Cport::Scratch ------------------------------------------------------------------ Function Writes a byte to, or reads a byte from the serial port's scratch register. Syntax #include "cport.h" void Cport::Scratch(byte abyte); or byte Cport::Scratch(); Parameters abyte - The byte to be written to the scratch register. Remarks If a parameter is specified, Cport::Scratch writes the byte value abyte to the serial port instance's UART scratch register. If Cport::Scratch is called with no parameters, it reads the byte in the UART scratch register. Not all UARTs have a scratch register. Example Exchange a value with the scratch register. byte ScratchExchange(Cport& com, byte value) { byte rv; rv = com.Scratch(); // read the scratch register com.Scratch(value); // write to the scratch register return(rv); } 6-1 File Transfer ============= Xmodem ------ XmodemTx transmits a file using the Xmodem file transfer protocol. XmodemRx receives a file using the Xmodem file transfer protocol. Xcallback is the default callback function for XmodemTx and XmodemRx. 6-2 XmodemTx ------------------------------------------------------------------ Function Transmits a file with the Xmodem file transfer protocol. Syntax #include "xmodem.h" int XmodemTx(COM, const char* file, int (*cb)(int msg, XPARAM param)); or int XmodemTx(Cport&, const char* file, int (*cb)(int msg, XPARAM param)); Parameters COM - Handle of the serial port (C). Cport - Reference to a serial port instance (C++). file - Path/name of the file to be transferred. cb - Pointer to the callback function. Remarks XmodemTx transmits the file file via the serial port specified by COM or Cport. It will make calls back to the function cb if one is specified. If you specify NULL for cb, a default callback function will be used. See the following discussion on the callback function for a complete explanation of the callback function. Return value XmodemTx returns zero if the file was transferred successfully. Otherwise, it returns non-zero. See Table 6-1 for a list of return codes. See also XmodemRx, Xcallback Example Transfer the file cport.zip via the modem. (C) /* callback function prototype */ int myCallback(int msg, XPARAM param); int main(void) { COM modem; int rv; modem = ComOpen(COM1, B2400, W8|S1|NONE, 1024, 512); if(comopen_errno != NO_ERR) return(-comopen_errno); rv = XmodemTx(modem, "cport.zip", myCallback); ComClose(modem); return(rv); } 6-3 Example Transfer the file cport.zip via the modem. (C++) // callback function prototype int myCallback(int msg, XPARAM param); int main(void) { Cport modem(COM1, B2400); // uses default parameters if((int)modem != NO_ERR) return(-((int)modem)); return(XmodemTx(modem, "cport.zip", myCallback)); } XmodemRx ------------------------------------------------------------------ Function Receives a file with the Xmodem file transfer protocol. Syntax #include "xmodem.h" int XmodemRx(COM, const char* file, int (*cb)(int msg, XPARAM param)); or int XmodemRx(Cport&, const char* file, int (*cb)(int msg, XPARAM param)); Parameters COM - Handle of the serial port (C). Cport - Reference to a serial port instance (C++). file - Path/name of the file to be transferred. cb - Pointer to the callback function. Remarks XmodemRx receives the file file via the serial port specified by COM or Cport. It will make calls back to the function cb if one is specified. If you specify NULL for cb, a default callback function will be used. See the following discussion on the callback function for a complete explanation of the callback function. Return value XmodemTx returns zero if the file was transferred successfully. Otherwise, it returns non-zero. See Table 6-1 for a list of return codes. See also XmodemTx, Xcallback 6-4 Example Receive the file cport.zip via the modem. (C) /* callback function prototype */ int myCallback(int msg, XPARAM param); int main(void) { COM modem; int rv; modem = ComOpen(COM1, B2400, W8|S1|NONE, 1024, 512); if(comopen_errno != NO_ERR) return(-comopen_errno); rv = XmodemRx(modem, "cport.zip", myCallback); ComClose(modem); return(rv); } Example Receive the file cport.zip via the modem. (C++) // callback function prototype int myCallback(int msg, XPARAM param); int main(void) { Cport modem(COM1, B2400); // uses default parameters if((int)modem != NO_ERR) return(-((int)modem)); return(XmodemRx(modem, "cport.zip", myCallback)); } Xcallback ------------------------------------------------------------------ Function Default callback function. Syntax #include "xmodem.h" int Xcallback(int msg, XPARAM param); Parameters msg - Callback message number. (See Table 6-2). param - Message specific parameter. (See Table 6-2 and 6-3) Remarks Xcallback is the default Xmodem callback function. When NULL is specified as the callback function in a call to XmodemTx or XmodemRx, Xcallback will be used. Xcallback only keeps track of errors to decide if the transfer should be aborted. You can chain callback functions by specifying a callback function and then calling Xcallback directly. You would do this if you were only interested in the information provided 6-5 to the callback function and did not want to affect the functionality of the transfer. Return value When a callback function returns zero, the transfer continues. If it returns non-zero, the transfer is canceled, and XmodemRx or XmodemTx will return with a non-zero return code. See also XmodemTx, XmodemRx Example Use the default callback when receiving the file cport.zip via the modem. This results in a blind transfer. int main(void) { COM modem; int rv; modem = ComOpen(COM1, B2400, W8|S1|NONE, 1024, 512); if(comopen_errno != NO_ERR) return(-comopen_errno); rv = XmodemRx(modem, "cport.zip", NULL); ComClose(modem); return(rv); } Example Establish a callback function for procuring information for screen updates only. int myCallback(int msg, XPARAM param) { switch(msg) { case XM_BLOCKCHECK: /* Update the screen */ break; case XM_BLOCK: /* Update the screen */ break; case... } /* chain to the default callback for functionality */ return(Xcallback(msg, param)); } Callback Function ------------------------------------------------------------------ Since it usually takes time to transfer a file, there must be a mechanism for monitoring and optionally canceling the transfer. To accomplish this, the Xmodem transmit and receive functions accept a parameter, which is a pointer to a callback function. This function will be called at certain 6-6 points during the file transfer. Your callback function can be used to update the screen, cancel the transfer, etc. Your callback function must have the exact prototype: int function_name(int msg, XPARAM param); Msg is the message number that identifies why the callback was made. The value of param depends on the message. It provides additional information for a specific message. Anytime param is not used, it is set to zero. The following is a list of messages and their descriptions. XM_IDLE (0) - Idle time. This message is sent during idle time to give the callback the opportunity to do something, such as checking to see if the user wishes to cancel the transfer. XM_START (1) - Start of transfer. This message is sent, at most, one time. It signals that the transfer has been successfully prepared and will now attempt to make contact with the remote station. XM_BLOCKCHECK (2) - Block check determined. Once the block check has been determined, this message is sent to inform the callback if the block check will be checksum (param == 0) or CRC16 (param != 0). This message is sent, at most, one time during a transfer. It is mostly informative . XM_BLOCK (3) - New block transferred. This message is sent each time a new block (128 bytes) is successfully transferred. For this message, param contains the block number. This message is primarily an informative message. XM_EOT (4) - End of transmission. This message is sent when an end of transmission is being established. Usually there will be only one of these messages, however, if problems arise, the EOT may be retried. XM_DONE (5) - Transfer done. This message is sent at the end of a transmission whether the transmission was successful or canceled. It is sent exactly one time if XM_START was previously sent. Otherwise, it will not be sent. XM_ERROR (6) - Error detected. This message is sent when an error is detected in the data. Param contains the error code. The lower 12 bits of param is the bit ORed errors returned by the function ComError. The upper 4 bits is the extended Xmodem error code (not bit ORed). The extended Xmodem error code (upper 4 bits) should always be non-zero. The ComError bits (lower 12 bits) may or may not indicate errors. Usually the ComError portion of the error code takes precedence over the extended Xmodem code, since it is likely to be the source of the error. The extended Xmodem errors are explained here. See ComError or Cport::Error for information on the lower 12 bits of the error code: XE_BADBLOCK (0x1000) - Bad block. This error occurs when a block was determined to be corrupted. Occasional bad block errors may occur. If the transfer is not canceled by the callback function, Xmodem will attempt to recover from this error (usually succeeding) by retrying the block. 6-7 XE_BADCHECK (0x2000) - Bad block check. This error occurs when the block is not detected as bad (XE_BADBLOCK) but the block check (CRC or checksum) does not match the data. This error can only be detected when receiving a file. XE_TIMEOUT (0x3000) - Timeout. Xmodem timed out waiting for a block or for protocol exchange. If the callback function does not cancel the transfer, Xmodem will retry whatever timed out. Successful recovery from this error depends on the reason (usually unknown) for the timeout. XE_CANCEL (0x4000) - Transmission canceled. This message is sent when the transmission is canceled by either the callback function, by the remote station or for other internal reasons. Xmodem Tables of Values ------------------------------------------------------------------ name value description ----------------------------------------------- XR_NOERR (0) No error. XR_FILEERR (1) File error. XR_CANCEL (2) Transfer canceled. XR_ALLOC (3) Memory allocation error. Table 6-1 - XmodemRx/XmodemTx return values. name value description XPARAM ------------------------------------------------------------------------- XM_IDLE (0) Idle time. 0. XM_START (1) Start of transfer 0. XM_BLOCKCHECK (2) Block check determined 0 if checksum, 1 if CRC16. XM_BLOCK (3) New block transferred Block number. XM_EOT (4) End of transmission 0. XM_DONE (5) Transfer complete 0. XM_ERROR (6) Error has been detected Error code. Table 6-2 - Xmodem callback messages. name value description ------------------------------------------------------------ XE_BADBLOCK (0x1000) Bad block. XE_BADCHECK (0x2000) Bad block check (CRC or checksum). XE_TIMEOUT (0x3000) Timeout. XE_CANCEL (0x4000) Transfer canceled. Table 6-3 - Extended Xmodem error codes. A-1 Appendix A ========== name value ----------------------- * COM1 (PORT0 | IRQ4) * COM2 (PORT1 | IRQ3) * COM3 (PORT2 | IRQ4) * COM4 (PORT3 | IRQ3) PORT0 (0x03F8) PORT1 (0x02F8) PORT2 (0x03E8) PORT3 (0x02E8) IRQ2 (0x2000) IRQ3 (0x3000) IRQ4 (0x4000) IRQ5 (0x5000) IRQ6 (0x6000) IRQ7 (0x7000) BIOS0 (*(int far *)0x400000l) BIOS1 (*(int far *)0x400002l) BIOS2 (*(int far *)0x400004l) BIOS3 (*(int far *)0x400006l) * The COMx constants are usually sufficient. Table A-1 - Serial port id. name value --------------- B115200 (1) B57600 (2) B38400 (3) B19200 (6) B9600 (12) B7200 (16) B4800 (24) B3600 (32) B2400 (48) B2000 (58) B1800 (64) B1200 (96) B600 (192) B300 (384) B150 (768) B110 (1047) B75 (1536) B50 (2304) Table A-2 - Baud rate divisors. A-2 name value description ---------------------------------------- W8 (0x03) 8 bit words. W7 (0x02) 7 bit words. W6 (0x01) 6 bit words. W5 (0x00) 5 bit words. S1 (0x00) 1 stop bit. S2 (0x04) 2 stop bits. NONE (0x00) No parity. ODD (0x08) Odd parity. EVEN (0x18) Even parity. MARK (0x28) Mark parity (logic 1). SPACE (0x38) Space parity (logic 0). WMASK (0x03) Word mask. SMASK (0x04) Stop bit mask. PMASK (0x38) Parity mask. Table A-3 - Bit ORed mode components. name value description --------------------------------------------------------------- NO_ERR (0) No errors. OPENED (1) Serial port is already opened. BAD_ID (2) Invalid id parameter. NO_UART (3) No UART chip was detected. RX_ALC (4) Receive queue allocation error. TX_ALC (5) Transmit queue allocation error. MAX_PORT (6) The maximum number of serial ports are opened. IRQ_CTN (7) The irq contends with another open serial port. GEN_ALC (8) General memory allocation error. Table A-4 - Open error values. name value description --------------------------------------------------- OFF (0x00) No handshaking. DTR (0x01) The receiver uses DTR. RTS (0x02) The receiver uses RTS. S_RX (0x04) The receiver uses XON/XOFF. CTS (0x10) CTS is checked by the transmitter. DSR (0x20) DSR is checked by the transmitter. DCD (0x80) DCD is checked by the transmitter. S_TX (0x08) The transmitter honors XON/XOFF. SOFT (0x0C) Same as (S_RX | S_TX). HARD1 (0x21) Same as (DTR | DSR). HARD2 (0x12) Same as (RTS | CTS). Table A-5 - Bit ORed handshaking options. A-3 name value description ----------------------------------- TIMER (0x01) divert timer (irq0). KEYBOARD (0x02) disable keyboard (irq1). CASCADE (0x04) disable irq2. OFF (0x00) restore all interrupts. Table A-6 - Turbo options. name value description ----------------------------------------- OVERUN (0x0002) Overrun error. PARITY (0x0004) Parity error. FRAMING (0x0008) Framing error. BREAK (0x0010) Break detect. RX_FIFO (0x0080) Rx fifo error. TXFULL (0x0100) Transmit queue overflow. RXFULL (0x0200) Receive queue overflow. (unused) (0xF000) Designated as unused. Table A-7 - Bit ORed error code. name value description ----------------------------------------------- DCTS (0x001) Change in clear to send. DDSR (0x002) Change in data set ready. TERI (0x004) Trailing edge ring indicator. DDCD (0x008) Change in data carrier detect. CTS (0x010) Clear to send asserted. DSR (0x020) Data set ready asserted. RI (0x040) Ring indicator asserted. DCD (0x080) Data carrier detect asserted. S_TX_OFF (0x100) Transmitter off (XOFF state). U_TX_OFF (0x200) Transmitter off (ComTx). S_RX_OFF (0x400) Receiver off (XOFF state). Table A-8 - Bit ORed status word. name value description ---------------------------------------------- ON (1) Turns the transmitter on. OFF (0) Turns the transmitter off. TX_DIRECT (0x2) Use direct mode when off. Table A-9 - Transmitter options. A-4 name value description ------------------------------------- ON (1) Signal asserted. OFF (0) Signal inhibited. Table A-10 - On/off values. name value description -------------------------------------- INS8250 (1) INS8250 or INS8250-B. NS16450 (2) NS16450 or INS8250A. NS16550 (3) NS16550. I82510 (4) 82510 (Intel). Table A-11 - UART types. name value description -------------------------------- T550_1 (0x00) 1 byte. T550_4 (0x400 4 bytes. T550_8 (0x80) 8 bytes. T550_14 (0xC0) 14 bytes. Table A-12- NS550 trigger thresholds. B-1 Appendix B ========== Compiling --------- 1) Make sure the header file(s) are included in any modules (source files) which make calls to Cport library functions. Example: #include "cport.h" 2) Make sure your compiler knows where to find the header file(s). Borland C/C++: bcc -c -Ic:\cport\include your_file Microsoft C/C++: cl /c /Ic:\cport\include your_file NOTE: cl will also look at the INCLUDE environment variable for the include directories. Example: set INCLUDE=c:\c600\include;c:\cport\include; 3) Make sure your compiler is generating byte alignments when generating structures. This is only a concern when using Cport functions, which involve structures such as CPARAM. For Borland and Microsoft compilers, this is taken care of. If you are using another compiler, consult your user's manual on how to generate byte alignments. Borland C/C++: (uses byte alignment by default) Microsoft C/C++: cl /c /Zp1 /Ic:\cport\include your_file Linking ------- 1) Make sure the appropriate Cport library is included in the list of libraries. The last letter in the file name of the libraries indicates the memory model: cports.lib - small model cportm.lib - medium model cportc.lib - compact model cportl.lib - large model cporth.lib - huge model 2) Make sure the linker knows where to find the library files. Borland C/C++: tlink /Lc:\cport\lib c0s objs, exe_name, map_name, cports cs Microsoft C/C++: link objs, exe_name, map_name, cports slibce; NOTE: link looks at the LIB environment variable for the library directories: Example: set LIB=c:\c600\lib;c:\cport\lib; C-1 Appendix C ========== Cport v2.0 Order Form Name: ___________________________________________________________ Company: ________________________________________________________ Address: ________________________________________________________ City: _________________________________ State: _________________ Zip Code: _________________ Phone # : __________________________ CompuServe # : __________________________________________________ How did you acquire Cport ? _____________________________________ Compiler(s): ____________________________________________________ Computer(s): ____________________________________________________ Operating system(s): ____________________________________________ Single Licence .... $65.00 2 Licenses ........ $59.00 each 3 to 4 Licenses ... $54.00 each 5 to 9 licenses ... $48.00 each 10+ licenses ...... $41.00 each Quantity price each Subtotal _________ X __________ = $________ California residents add sales tax ( 8.25% ) $________ Shipping outside continental U.S. add ( $ 5.00) $________ Total: $________ All Payments Must be in U.S. Dollars Make check or money order payable to: Bri Productions P.O. Box 7121 Fremont, CA 94537-7121 Other payment/shipping arrangements may be available. C-2 We want to hear from you! ------------------------- In order to improve Cport and add valuable features, we need to know what features you need most. This information is important in order to provide you with the best possible product. Please take a moment to answer the following questions. Indicate your need for the following features by checking the choice which best describes your need for the feature: very | nice | don't important | to have | need it ----------- -------- --------- Multi port Serial Boards: ____ ____ ____ Board name(s) ______________ Modem support: ____ ____ ____ Zmodem file transfer: ____ ____ ____ Other file transfer __________: ____ ____ ____ Other file transfer __________: ____ ____ ____ Windows support: ____ ____ ____ Other ________________________: ____ ____ ____ Other ________________________: ____ ____ ____ Other ________________________: ____ ____ ____ What other types of libraries would you find useful ? _____ ___Game Port ___Expanded Memory ___Sound effects Others______________________________________________________ Other Comments______________________________________________ ____________________________________________________________ ____________________________________________________________ Bri Productions, P.O. Box 7121, Fremont, CA 94537, (510) 794-0616