In PureBasic the Visual Designer is a free add-on to help a few 'NEW' people to get started with simple Windows forms. Used how it was intended, it's perfectly adequate. Besides PureBasic is 'MILES' ahead of PowerBASIC in many areas. PureBasic has many included libraries: - 2D and Engine3D libs - CGI - Cipher - Database - Dialog - DragDrop. Since all the serial ports are a subset of the printer ports, all I have to do is filter out those that are not COM ports, are already in use (see Note below), or cannot be opened. I present the list of available ports in a menu for the user to select a port. This has proven to be reliable and (thanks to ABB's help) it's working under PB/Windows.
- Purebasic Serial Port Example Using
- Purebasic Serial Port Example Software
- Purebasic Serial Port Example
- Purebasic Serial Port Example Pdf
- Purebasic Serial Port Examples
The Asynchronous Serial Interface
The vast majority of general-purpose microcomputers, except some entirely self-contained portable models, once used a serial interface to communicate with remote peripherals such as CRT terminals. The serial interface, that moves information from point-to-point one bit at a time, is generally preferred to the parallel interface, that is able to move a group of bits simultaneously. This preference is not due to the high performance of a serial data link, but to its low-cost, simplicity and ease of use. We first describe how information is transmitted serially and then examine a first-generation parallel-to-serial and serial-to-parallel chip that forms the interface between a microprocessor and a serial data link. Finally, we look at a more modern high-performance serial interface. Note that the serial interface is rarely used in new equipment (having been rendered obsolete by USB). However, we have included it here because of its importance and its continued use in legacy systems.
Figure 1 illustrates the basic serial data link between a computer and a CRT terminal. A CRT terminal requires a two-way data link, because information from the keyboard is transmitted to the computer and information from the computer is transmitted to the screen. The transmitted data from the computer becomes the received data at the CRT terminal. The heart of the data link is the box labeled serial interface that translates data between the form in which it is stored within the computer and the form in which it is transmitted over the data link. This function is often performed by a single device called an asynchronous communications interface adaptor (ACIA).
Figure 1 Functional units of a serial data link
The line drivers in figure 1 translate the voltage levels processed by the ACIA into a suitable form for sending over the transmission path. The transmission path itself is normally a twisted pair of conductors which accounts for its very low cost. Some systems employ more esoteric transmission paths such as fiber optics, or infra-red (IR) links. The connection between the line drivers and transmission path is labeled plug and socket in figure 1 to emphasize that such mundane things as plugs become very important if interchangeability is required. International specifications cover this and other aspects of the data link.
The two items at the computer end of the data link enclosed in clouds in figure 1 represent the software components of the data link. The lower cloud contains the software that directly controls the serial interface itself. This software performs operations such as transmitting a single character, or receiving a character and checking it for certain types of error. On top of this layer sits the application-level software, that uses the primitive operations executed by the lower-level software to carry out actions such as listing a file on the screen.
Here we introduce the chip that converts information between the parallel form in which it is processed by the computer and the form in which it is transmitted over the data link. A serial data link operates in one of two modes: asynchronous or synchronous. We describe only the asynchronous data link because synchronous serial data links are best left to texts on networks.
The term character refers to the basic unit of information transmitted over an asynchronous data link. Many data links transmit information in the form of text and the unit of information corresponds to a printed character.
Asynchronous Serial Data Transmission
Until the introduction of USB the most popular serial interface between a computer and its CRT terminal is the asynchronous serial interface. It is so called because the transmitted data and the received data are not synchronized over any extended period and therefore no special means of synchronizing the clocks at the transmitter and receiver is necessary. In fact, the asynchronous serial data link is a very old form of data transmission system and has its origin in the era of the teleprinter.
Serial data transmission systems have been around for a long time and are found in the telephone (human speech), Morse code, semaphore and even the smoke signals once used by Native Americans. The fundamental problem encountered by all serial data transmission systems is how to split the incoming data-stream into individual units (i.e., bits) and how to group these units into characters. For example, in Morse code the dots and dashes of a character are separated by an inter-symbol space, whereas the individual characters are separated by an inter-character space which is three times the duration of an inter-symbol space.
First we examine how the data stream is divided into individual bits and the bits grouped into characters in an asynchronous serial data link. The key to the operation of this type of link is both simple and ingenious. Figure 2 gives the format of data transmitted over such a link.
Figure 2 Format of asynchronous serial data
An asynchronous serial data link is character oriented, because information is transmitted in the form of groups of bits called characters. These characters are invariably units comprising seven or eight bits of information plus two to four control bits. Asynchronous data is often transmitted in the form of ASCII-encoded characters. Initially, when no information is being transmitted, the line is in an idle state. Traditionally, the idle state is referred to as the mark level, which, by convention, corresponds to a logical one level.
When the transmitter wishes to send data, it first places the line in a space level (i.e., the complement of a mark) for one element period. This element is called the start bit and has a duration of T seconds. The transmitter then sends the character, one bit at a time, by placing each successive bit on the line for a duration of T seconds, until all bits have been transmitted. After this has been done, a single parity bit is calculated by the transmitter and sent after the data bits. Finally, the transmitter sends a stop bit at a mark level (i.e., the same level as the idle state) for one or two bit periods. Now the transmitter may send another character whenever it wishes. The only purpose of the stop bit is to provide a rest period for the receiver between consecutive characters. This stop bit is a relic of the days of electromechanical receivers, and is not now strictly required for technical reasons. It is there for the purpose of compatibility with older equipment.
As the data word length may be 7 or 8 bits with odd, even, or no parity bit, plus either one or two stop bits, there are a total of 12 different possible formats for serial data transmission. And this is before we consider that there are about seven commonly used values of T, the element duration. Consequently, connecting one serial link with another may be difficult because so many options are available.
At the receiving end of an asynchronous serial data link, the receiver continually monitors the line looking for a start bit. Once the start bit has been detected, the receiver waits until the end of the start bit and then samples the next N bits at their centers, using a clock generated locally by the receiver. As each incoming bit is sampled, it is used to construct a new character. When the received character has been assembled, its parity is calculated and compared with the received parity bit following the character. If they are not equal, a parity error flag is set to indicate a transmission error.
The most obvious disadvantage of asynchronous data transmission is the need for a start, parity and stop bit for each transmitted character. If 7-bit characters are used, the overall efficiency is only 7/(7+3)x100 = 70%. A less obvious disadvantage is due to the character-oriented nature of the data link. Whenever the data link connects a CRT terminal to a computer few problems arise, as the terminal is itself character-oriented. However, if the data link is being used to, say, dump binary data to a magnetic tape, we run into a difficulty. If the data is arranged as 8-bit bytes with all 256 possible values corresponding to valid data elements, it is difficult (but not impossible) to embed control characters (e.g., tape start or stop) within the data stream, because the same character must be used both as pure data (i.e. part of the message) and for control purposes. If 7-bit characters are used, pure binary data cannot be transmitted in the form of one character per byte. Two characters are needed to record each byte which is clearly inefficient.
The 6850 Asynchronous Communications Interface Adaptor (ACIA)
One of the first general-purpose interface devices produced by semiconductor manufacturers was the asynchronous communications interface adaptor, or ACIA. This device relieves the system software of all the basic tasks involved in converting data between serial and parallel forms. That is, the ACIA contains almost all the logic necessary to provide an asynchronous data link between a computer and an external system.
The 6850 ACIA is illustrated in figure 3. I am using this ACIA because it is much easier to understand than newer serial interfaces. Once you understand how the 6850 ACIA operates, you can read the data sheet of any other ACIA.
From the designer's point of view, the 6850's hardware can be subdivided into three sections: the CPU side, the transmitter side and the receiver side. Figure 3 illustrates the functional parts of the 6850 and its internal registers.
Figure 3 The 6850 ACIA
The CPU Side
NOTE: This material is taken from articles I wrote on the 68K microprocessor. Consequently, we describe its interface to the 68K.
The ACIA is a byte-oriented device and can be interfaced to either the 68000's lower-order byte or to its upper-order byte. The ACIA has a single register select line, RS, that determines the internal location (i.e., register) addressed by the processor. The 6850 has an interrupt request output, IRQ*, that can be connected to any of the 68000's seven levels of interrupt request input.
Unusually, the 6850 does not have a hardware reset input (i.e., a pin that can be used to clear its internal registers). . Some sections of the ACIA are reset automatically by an internal power-on-reset circuit. Afterwards, a secondary reset can be performed by software, as we shall describe later.
The Receiver and Transmitter Sides of the ACIA
One of the great advantages of peripherals like the 6850 ACIA is that they isolate the CPU from the outside world both physically and logically. The physical isolation means that the engineer who is connecting a peripheral device to a microprocessor system does not have to worry about the electrical and timing requirements of the CPU itself. That is, all the engineer needs to understand about the ACIA is the nature of its transmitter- and receiver-side interfaces. Similarly, the peripheral performs a logical isolation by hiding the details of information transfer across it. For example, you can perform the operation of transmitting a character from an ACIA by the instruction MOVE.B D0,ACIA_DATA, where register D0 contains the character to be transmitted and ACIA_DATA is the address of the data register in the ACIA. All the actions necessary to serialize the data and append start, parity and stop bits are carried out automatically (i.e., invisibly) by the ACIA.
Here, only the essential details of the ACIA's transmitter and receiver sides are presented, because the way in which they function is described more fully when we come to the logical organization of the 6850. The peripheral-side interface of the 6850 is divided into two entirely separate groups - the receiver group that forms the interface between the ACIA and a source of incoming data, and the transmitter group that forms the interface between the ACIA and the destination for outgoing data. Incoming and outgoing are used with respect to the ACIA. The nature of these signals is strongly affected by one particular role of the ACIA, its role as an interface between a computer and the public switched telephone network via a modem.
Receiver side
Incoming data to the ACIA is handled by three pins, RxD, RxCLK, DCD*. The RxD (receiver data input) pin receives serial data from the transmission path to which the ACIA is connected. A receiver clock must be provided at the RxCLK input pin by the systems designer. This clock may be either one-, sixteen- or sixty-four times the rate at which bits are received at the data input terminal. Many modern ACIAs include on-chip receiver and transmitter clocks, relieving the system designer of the necessity of providing an additional external oscillator.
The third and last component of the receiver group is an active-low DCD*, data carrier detect, input. This input is intended for use in conjunction with a modem and, when low, indicates to the ACIA that the incoming data is valid. When inactive-high, DCD* indicates that the incoming data might be erroneous. This situation may arise if the level (i.e., signal strength) of the data received at the end of a telephone line drops below a pre-determined value, or if the connection itself is broken. The negation of DCD* is used to disable the ACIA's receiver.
Transmitter side
The transmitter side of the ACIA comprises four pins: TxCLK, TxD, RTS* and CTS*. The transmitter clock input (TxCLK) provides a timing signal from which the ACIA derives the timing of the transmitted signal elements. In most applications of the ACIA, the transmitter and receiver clocks are connected together and a common oscillator used for both transmitter and receiver sides of the ACIA. Serial data is transmitted from the TxD (transmit data) pin of the ACIA to the serial transmission path.
An active-low request-to-send (RTS*) output indicates that the ACIA is ready to transmit information. This output is set or cleared under software control and can be used to switch on any equipment needed to transmit the serial data over the data link.
An active-low clear-to-send (CTS*) input indicates to the transmitter side of ACIA that the external equipment used to transmit the serial data is ready. When negated, this input inhibits the transmission of data by the ACIA. CTS* is a modem signal which indicates that the transmitter carrier is present and that transmission may go ahead.
Operation of the 6850 ACIA
The software model of the 6850 has four user-accessible registers as defined in table 1. These are: a transmit data register (TDR), a receive data register (RDR), a system control register (CR), and a system status register (SR). As there are four registers and yet the ACIA has only a single register select input, RS, a way must be found to distinguish between registers. The ACIA uses its read/write input to do this. Two registers are read-only (i.e., RDR, SR) and two are write-only (TDR, CR). This is a perfectly logical, indeed an elegant, thing to do. But I don't like it. I am perfectly happy to accept read-only registers, but I am suspicious of the write-only variety because it is impossible to verify the contents of a write-only register. Suppose you have a program with a bug that executes an unintended write to a write-only register. You cannot detect the change by reading back the contents of the register. Moreover, certain 68000 instructions would play havoc with such an arrangement. For example, the OR instruction would read the contents of the ACIA's status register, perform a logical OR and then write the result back to its control register.
Table 1 also gives the address of each register, assuming that the base address of the ACIA is $00 E001 and that it is connected to the low-order byte of the 68000's data bus. The purpose of this exercise is two-fold. It shows that the address of the lower-order byte is odd, and that the pairs of read-only and write-only registers are separated by two (i.e., $00E001 and $00E003).
Table 1 Register selection scheme of the 6850
Control Register
Because the ACIA is a versatile device that can be operated in any of several different modes, the control register permits the programmer to define its operational characteristics. This operation can even be performed dynamically, if the need ever arises. However, in almost all applications the ACIA is normally configured once only. Table 2 shows how the eight bits of the control register are grouped into four logical fields.
Bits CR0 and CR1 determine the ratio between the transmitted or received bit rates and the transmitter and receiver clocks, respectively. The clocks operate at 1, 16, or 64 times the data rate. Most applications of the 6850 employ a receiver and transmitter clock at 16 times the data rate with CR1 = 0 and CR0 = 1. For example, if you wish to receive data at 1,200 baud, you must provide a receiver clock input of 16 x 1,200 = 19,200 Hz.
Setting CR1 = CR2 = 1 is a special case and performs a software reset of the ACIA. This operation clears all internal status bits, with the exception of the CTS and DCD bits of the status register. A software reset to the 6850 is invariably carried out during the initialization phase of the host processor's reset procedures.
Table 2 Structure of the ACIA's control register
The word select field, bits CR2, CR3, CR4, determines the format of the received or transmitted characters. The eight possible data formats are given in table 2. These bits select also the type of parity (if any) and the number of stop bits. Possibly the most common data format for the transmission of information between a processor and a CRT terminal is: start bit + 7 data bits + even parity + 1 stop bit. The corresponding value of CR4, CR3, CR2 is 0,1,0.
The transmitter control field, CR5 and CR6, selects the state of the active-low request-to-send (RTS*) output, and determines whether or not the transmitter section of the ACIA may generate an interrupt by asserting its IRQ* output. In most systems RTS* is set active-low whenever the ACIA is transmitting, because RTS* is used to activate equipment connected to the ACIA.
IUf the transmitter interrupt is enabled, an interrupt is generated by the transmitter whenever the transmit data register (TDR) is empty, signifying the need for new data from the CPU. When the ACIA's clear-to-send input, CTS*, is inactive-high, the TDR empty flag of the status register is held low, inhibiting any transmitter interrupt. If the ACIA is operated in a polled-data mode, interrupts are not necessary.
Setting both CR6 and CR5 to a logical one simultaneously creates a special case. When both these bits are high, a break is transmitted by the transmitter data output pin. A break is a condition in which the transmitter output is held at the active level (i.e., space or TTL logical zero) continuously. This condition may be employed to force an interrupt at a distant receiver, because the asynchronous serial format precludes the existence of a space level for longer than about ten bit periods. The term break originates from the old current-loop data transmission system when a break was affected by disrupting (i.e., breaking) the flow of current round a loop.
The receiver interrupt enable field consists of one bit, CR7, that enables the generation of interrupts by the receiver when it is set (CR7 = 1) and disables receiver interrupts when it is clear (CR7 = 0). The receiver asserts its IRQ* output, assuming CR7 = 1, when the receiver data register full (RDRF) bit of the status register is set, indicating the presence of a new data character ready for the CPU to read. Two other circumstances also force a receiver interrupt. An overrun (see later) sets the RDRF bit and generates an interrupt. Finally, a receiver interrupt can also be generated by a high-to-low transition at the active-low data-carrier-detect (DCD*) input, signifying a loss of the carrier from a modem. Note that CR7 is a composite interrupt enable bit and enables all the three forms of receiver interrupt described above. It is impossible to enable either an interrupt caused by the RDR being empty or an interrupt caused by a positive transition at the DCD* pin alone.
Status Register
The eight bits of the read-only status register are depicted in table 3 and serve to indicate the status of both the transmitter and receiver portions of the ACIA at any instant.
Table 3 Format of the status register
SR0 - Receiver data register full (RDRF) When set, this bit indicates that the receiver data register (RDR) is full, and a new word has been received. If the receiver interrupt is enabled by CR7 = 1, a logical one in SR0 also sets the interrupt status bit SR7 (i.e., IRQ). The RDRF bit is cleared either by reading the data in the receiver data register or by carrying out a software reset on the control register. Whenever the data-carrier-detect (DCD*) input is inactive-high, the RDRF bit remains clamped at a logical zero, indicating the absence of any valid input.
SR1 - Transmitter data register empty (TDRE) This is the transmitter counterpart of the RDRF bit. A logical one in SR1 indicates that the contents of the transmit data register (TDR) have been sent to the transmitter and that the register is now ready for new data from the processor. This bit is cleared either by loading the transmit data register or by performing a software reset. If the transmitter interrupt is enabled, a logical one in bit SR1 also sets bit SR7, IRQ, of the status word. Note again that SR7 is a composite interrupt bit because it is also set by an interrupt originating from the receiver side of the ACIA. If the clear-to-send input (CTS*) is inactive-high, the TDRE bit is held low, indicating that the terminal equipment is not ready for data.
SR2 - Data carrier detect (DCD) This status bit, associated with the receiver side of the ACIA, is normally employed when the ACIA is connected to the telephone network via a modem. Whenever the DCD* input to the ACIA is inactive-high, SR2 is set. A logical one on the DCD* line generally signifies that the incoming serial data is faulty. This also has the effect of clearing the SR0 (i.e., RDRF) bit, as possible erroneous input should not be interpreted as valid data.
When the DCD* input makes a low-to-high transition, not only is SR2 set, but the composite interrupt request bit, SR7, is also set if the receiver interrupt is enabled. Note that SR2 remains set even if the DCD* input later returns active-low. This is done to trap any occurrence of DCD* high, even if it goes high only briefly. To clear SR2, the CPU must read the contents of the status register and then the contents of the data register.
SR3 - Clear-to-send (CTS) The CTS bit directly reflects the status of the CTS* input on the ACIA's transmitter side. An active-low level on the CTS* input indicates that the transmitting device (i.e., the modem) is ready to receive serial data from the ACIA. If the CTS* input and therefore the CTS status bit are high, the transmit data register empty bit, SR1, is inhibited (clamped at a logical zero), and no data may be transmitted by the ACIA. Unlike the DCD status bit, the logical value of the CTS status bit is determined only by the CTS* input and is not affected by any software operation on the ACIA.
SR4 - Framing error (FE) A framing error is detected by the absence of a stop bit and indicates a synchronization (i.e., timing) error, a faulty transmission, or a break condition. The framing error status bit, SR4, is set whenever the ACIA determines that a received character is incorrectly framed by a start bit and a stop bit. The framing error status bit is automatically cleared or set during the receiver data transfer time and is present throughout the time that the associated character is available.
SR5 - Receiver overrun (OVRN) The receiver overrun status bit is set when a character is received by the ACIA but is not read by the CPU before a subsequent character is received, over-writing the last character, which is now lost. Consequently, the receiver overrun bit indicates that one or more characters in the data stream have been lost. This status bit is set at the midpoint of the last bit of the second character received in succession without a read of the RDR having occurred. Synchronization of the incoming data is not affected by an overrun error. The error is due to the CPU not having read a character, rather than by any fault in the transmission and reception process. The overrun bit is cleared after reading data from the RDR or by a software reset.
SR6 - Parity error (PE) The parity error status bit is set whenever the received parity bit in the current character does not match the parity bit of the character generated locally in the ACIA from the received data bits. Odd or even parity may be selected by writing the appropriate code into bits CR2, CR3 and CR4 of the control register. If no parity is selected, then both the ACIA's transmitter parity generator and receiver parity checker are disabled. Once a parity error has been detected and the parity error status bit set, it remains set as long as the erroneous data remains in the receiver register.
SR7 - Interrupt request (IRQ) The interrupt request status bit is a composite active-high (note!) interrupt request flag, and is set whenever the ACIA wishes to interrupt the CPU, for whatever reason. The IRQ bit is set active-high by any of the following events:
- Receiver data register full (SR0 set) and receiver interrupt enabled.
- Transmitter data register empty (SR1 set) and transmitter interrupt enabled.
- Data-carrier-detect status bit (SR2) set and receiver interrupt enabled.
Whenever SR7 is active-high, the IRQ* output from the ACIA is pulled low. The IRQ bit is cleared by a read from the RDR, or by a write to the TDR, or by a software master reset.
Purebasic Serial Port Example Using
Using the 6850 ACIA
The most daunting thing about many microprocessor interface chips is their sheer complexity. Often this complexity is more imaginary than real, because such peripherals are usually operated in only one of the many different modes that are software selectable. This is particularly true of the 6850 ACIA. Figure 4 shows how the 6850 is operated in a minimal mode. Only its serial data input, RxD, and output, TxD, are connected to an external system. The request to send output, RTS*, output is left unconnected and clear to send, CTS*, and data carrier detect, DCD*, inputs are both strapped to ground at the ACIA.
In a minimal, non-interrupt mode, bits 2 to 7 of the status register can be ignored. Of course, this throws away the error-detecting facilities of the ACIA. The software necessary to drive the ACIA in this minimal mode consists of three subroutines: an initialization, an input and an output routine.
ACIAC EQU $E0001 Address of control/status registers
ACIAD EQU ACIAC+2 Address of the Tx/Rx data registers
RDRF EQU 0 Receiver data register full
TDRE EQU 1 Transmitter data register empty
INITIALIZE MOVE.B #%00000011,ACIAC Reset the ACIA
MOVE.B #%00011001,ACIAC Set up control word - disable
RTS interrupts, 8 data bits, even
parity
INPUT BTST #RDRF,ACIAC REPEAT
BEQ INPUT Poll RDRF bit
MOVE.B ACIAD,D0 UNTIL ACIA has data ready
RTS Copy input to D0 and return
OUTPUT BTST #TDRE,ACIAC REPEAT
BEQ OUTPUT Poll TDRE bit
MOVE.B D0,ACIAD UNTIL ACIA is ready for new data
RTS
Figure 4 Using the ACIA in its minimal mode
The INITIALIZE routine is called once before either input or output is carried out and has the effect of executing a software reset on the ACIA followed by setting up its control register. The control word %00011001 (see table 2) defines an 8-bit word with even parity and a clock rate (TxCLK, RxCLK) sixteen times the data rate of the transmitted and received data.
The INPUT and OUTPUT routines are both entirely straightforward. Each routine tests the appropriate status bit and then reads data from or writes data to the ACIA's data register.
It is also possible to operate the ACIA in a minimal interrupt-driven mode. The IRQ* output is connected to one of the 68000's seven levels of interrupt request input. Both transmitter and receiver interrupts are enabled by writing 1,0,1 into bits CR7, CR6, CR5 of the status register.
When a transmitter or receiver interrupt is initiated, it is still necessary to examine the RDRF and TDRE bits of the status register to determine that the ACIA did indeed request the interrupt and to distinguish between transmitter and receiver requests for service. The effect of interrupt-driven I/O is to eliminate the time-wasting polling routines required by programmed I/O. Figure 5 shows how the ACIA can be operated in a more sophisticated mode. The reader may be tempted to ask, 'Why bother with a complex operating mode if the 6850 works quite happily in a basic mode?' The answer is that the operating mode in figure 5 provides more facilities than the basic mode of figure 4.
Figure 5 General-purpose interface using the 6850 ACIA
In figure 5 the transmitter side of the ACIA sends an RTS* signal and receives a CTS* signal from the remote terminal equipment. Now the ACIA is able to say, 'I am going to transmit data to you' by asserting RTS*, and 'I know you are ready to receive my data' by detecting CTS* asserted. In the cut-down mode of figure 4, the ACIA simply sends data and hopes for the best!
Similarly, the receiver side of the ACIA uses the data carrier detect (DCD*) input to signal to the host computer that the receiver circuit is in a position to receive data. If DCD* is negated, the terminal equipment is unable to send data to the ACIA.
The software necessary to receive data when operating the 6850 in its more sophisticated mode is considerably more complex than that of the previous example. It is not possible to provide a full input routine here, as such a routine would include recovery procedures from the errors detected by the 6850 ACIA. These procedures are, of course, dependent on the nature of the system and the protocol used to move data between a transmitter and receiver. However, the following fragment of an input routine gives some idea of how the 6850's status register is used.
ACIAC EQU <ACIA address>
ACIAD EQU ACIA+2
RDRF EQU 0 Receiver_data_register_full
TDRE EQU 1 Transmitter_data_register_empty
DCD EQU 2 Data_carrier_detect
CTS EQU 3 Clear_to_send
FE EQU 4 Framing_error
OVRN EQU 5 Over_run
PE EQU 6 Parity_error
INPUT MOVE.B ACIAC,D0 Get status from ACIA
BTST #RDRF,D0 Test for received character
BNE ERROR_CHECK If char received then test SR
BTST #DCD,D0 Else test for loss of signal
BEQ INPUT Repeat loop while CTS clear
BRA DCD_ERROR Else deal with loss of signal
ERROR_CHECK BTST #FE,D0 Test for framing error
BNE FE_ERROR If framing error, deal with it
BTST #OVRN,D0 Test for overrun
BNE OVRN_ERROR If overrun, deal with it
BTST #PE,D0 Test for parity error
BNE PE_ERROR If parity error deal with it
MOVE.B ACIAD,D0 Load the input into D0
BRA.S EXIT
DCD_ERROR Deal with loss of signal
BRA EXIT
FE_ERROR Deal with framing error
BRA EXIT
OVRN_ERROR Deal with overrun error
BRA EXIT
Purebasic Serial Port Example Software
PE_ERROR Deal with parity error
EXIT RTS
The 68681 DUART
The 6850 ACIA is a first-generation interface device designed in the 1970s to work with the 8-bit 6800 microprocessor and is now rather long in the tooth. Designers required a more sophisticated asynchronous serial interface. The 68681 (called a DUART) performs the same basic functions as a pair of 6850s plus a baud-rate generator. Its features:
- The DUART provides two independent asynchronous serial channels and replaces two 6850 ACIAs.
- The DUART has a full 68000 asynchronous bus interface which means that it supports asynchronous data transfers and can supply a vector number during an interrupt acknowledge cycle.
- The DUART has an on-chip programmable baud-rate generator, that saves both the cost and board space of a separate baud-rate generator. Moreover, the DUART's baud-rate generator can be programmed simply by loading an appropriate value into a clock select register. This feature makes it very easy to connect a system with a DUART to a communications system with an unknown baud rate. Communications systems based on the 6850 have to change their baud rate by altering links on the board, making it tedious to change the baud rate frequently. The DUART can receive and transmit at different baud rates (as can the 6850).
- The DUART has a quadruple buffered input so that up to four characters can be received in a burst before the host processor has to read the input stream. The host computer has to read each character from a 6850 as it is received (otherwise an overrun will occur and characters will be lost). Similarly, the DUART has a double-buffered output, permitting one character to be transmitted while another is being loaded by the CPU.
- The DUART has 14 I/O pins (six input, eight output) that can be used as modem-control pins, clock input and outputs, or as general-purpose input/output pins.
- The DUART can support several operating modes (e.g., a self-test loop-back mode).
Figure 6 illustrates the internal organization of a 68681 DUART.
Figure 6 Internal organization of a 68681 DUART
The DUART's Registers
The DUART has 16 addressable registers, as illustrated in table 4. Some registers are read-only, some write-only and some read/write. For our current purposes, we concentrate on the DUART's five control registers that must be configured before it can be used as a transmitter or a receiver (the 6850 has just a single control register). Note that some registers are global and affect the operation of both the DUART's serial channels while others are local to channel A or to channel B. In what follows, we use channel A registers to illustrate the DUART's operation.
The five control registers are: MR1A (master register 1), MR2A (master register 2), CSRA (clock select register), CRA (command register) and ACR (auxiliary control register). Note that MR1A and MR2A share the same address. After a reset, control register MR1A is selected at the base address of the DUART. When MR1A is loaded with data by the host processor, MR2A is automatically selected at the same address (you can access MR1A again only by resetting the DUART or by executing a special select MR1A command. That is, the first time you write to the PI/T's base address following a reset, you access register MR1A. Further writes to the same address access register MR2A.
Table 7 provides a simplified extract from the DUART's data sheet that describes the five control registers. Modes of no interest to us here, such as the DUART's parallel I/O capabilities, have not been included in table 7. The following notes provide sufficient details about the DUART's registers to enable you to use it in its basic operating mode.
The auxiliary control register, ACR, selects the DUART's clock source (internal or external), its baud rate set (there are two sets), and controls certain parallel input pins. Setting bit ACR7 to 0 selects baud rate set 1 and setting ACR7 to 1 selects set 2. For our purposes, ACR can be loaded with $80 to select baud rate set 2 and then forgotten about.
Table 7 The DUART's registers
The clock-select register(s), CSRA and CSRB, permit the programmer to select the DUART's baud rate (CSRA selects the channel A baud rate and CSRB the channel B baud rate). Table 7 demonstrates that it is possible to select independent baud rates for transmission and reception. The values below can be loaded into the appropriate clock-select register to select the following popular baud rates (for both transmission and reception). These data rates are very low indeed compared to USB rates.
Value loaded in CSRA Baud rate (Tx and Rx)
0x55 300
0x66 1,200
0x88 2,400
0x99 4,800
0xBB 9,600
0xCC 19,200
Each baud-rate value loaded into a clock-select register consists of two 4-bit values (bits 0 to 3 select the transmitter baud rate and bits 4 to 7 select the receiver baud rate). For example, the instruction MOVE.B #$B8,CSRA selects a receive rate of 9,600 baud and a transmit rate of 2,400 baud.
Table 8 Structure of the DUART's registers
The channel mode control registers define the operating mode of the DUART (MR1A, MR2A for channel A and MR1B, MR2B for channel B). Table 9.21 provides a simplified account of these bits. To operate the DUART in its normal, 8-bit character mode, with no parity, one stop bit, and no modem control functions activated, MR1A is loaded with 1316 and MR2A with 0716. Remember that these registers share the same address and that MR2A is selected automatically after MR1A has been loaded. That is:
MR1A EQU DUART_BASE
MR2A EQU MR1A MR1A and MR2A have same address
MOVE.B #$13,MR1A Load MR1A - no parity, 8 bits
MOVE.B #$07,MR2A Now load MR2A - normal mode, 1 stop bit
The command registers (CRA and CRB) permit the programmer to enable and disable a channel's receiver or transmitter, and to issue certain commands to the DUART. The command CRA(6:4) = 001 resets the master register pointer to MR1A. You can load CRA with 0A16 to disable both channels during its setting up phase and then load it with 0516 to enable its transmitter and receiver ports once its other registers have been set up.
The DUART's status registers (SRA and SRB) are very similar to their 6850 counterpart. The DUART's major innovations are SRA7 that detects when a break has been received, SRA3 (TxEMT) that indicates when the transmitter buffer is empty (i.e., there are no characters in the DUART's buffer waiting to be transmitted), and SRA1 (FFULL) that indicates when the receiver buffer is full (there are four received characters waiting to be read). You can, of course, forget about these new bits and operate the DUART exactly like the ACIA just be using the TxRDY and RxRDY bits of its status register.
The difference between the status-bits FFULL and TxRDY is that the FFULL flag is applied to the whole receiver buffer, while RxRDY tells us that there is at least one free place in the receiver buffer. Similarly, TxEMT tells us that there is no character in the transmitter buffer and that the buffer is completely empty, while TxRDY tells us that the DUART is ready for another character.
The DUART has sophisticated interrupt control and handling facilities (figure 7). The interrupt vector register, IVR, provides a vector number when the DUART generates an interrupt and receives an IACK response from the 68000. If the IVR has not been loaded by the programmer since the last time the DUART was reset, the DUART supplies an uninitialized vector number during an IACK cycle.
The DUART has two interrupt control registers with identical formats: ISR is an interrupt status register whose bits are set when interrupt generating activities take place. IMR is an interrupt mask register whose bits are set by the programmer to enable an interrupt, or cleared to mask the interrupt. For example, ISR0 is set if TxRDYA is asserted to indicate that the channel A transmitter is ready for a character. If IMR0 is set to 1, the DUART will generate an interrupt when channel A is ready to transmit a character.
Figure 7 The DUART's interrupt control registers
We said earlier that the DUART has multi-purpose I/O pins that can be used as simple I/O pins or used to perform special functions. Input pins IP0 to IP5 are configured by bits in the CSRA, CSRB and ACR registers. These pins can be programmed to provide inputs for the DUART's timer/counter, its baud-rate generator, and its clear to send modem control. When MR2A4 = 1, pin IP0 acts as a channel A active-low clear to send input, CTS*. Similarly, IP1 can be configured as channel B's CTS* input by setting MR2B4 to 1. If the DUART is programmed to use its CTS* pins (i.e., MRSA/B4 = 1), data is not transmitted by the DUART whenever CTS* is high. That is, the remote receiver can negate CTS* to stop the DUART sending further data. Figure 8 demonstrates how CTS* is used in conjunction with RTS*. The following code demonstrates how the DUART is configured to perform flow control.
* Set MR2A4 = 1 and MR2A5 = 1 to configure OP0 as RTS output
MOVE.B #$83,MR1A
MOVE.B #$27,MR2A
*
* Note that RTS* must be asserted initially manually - after that
* RTS* is asserted auomatically whenever the receiver is ready to
* receive more data. Note also that the contents of the DUART's
* output port register are inverted before they are fed to the output
* pins. That is, to assert RTS* low, it is necessary to load a one
* into the appropriate bit of the OPR.
*
MOVE.B #$01,OPR Set OPR0 to assert RTS*
Figure 8 Performing flow control with CTS* and RTS*
The eight-bit output port is controlled by an output port configuration register, OPCR, and certain bits of the ACR, MR1A, MR2A, MR1B and MR2B registers. Output bits can be programmed as: simple outputs cleared and set under programmer control, timer and clock outputs, and status outputs. Some of the output functions that can be selected are:
Pin Function Action
OP0 RxRTSA* Asserted if channel A Rx is able to receive a character
OP1 TxRTSA* Negated if channel A Tx has nothing to transmit
OP2 RxRTSB* Asserted if channel B Rx is able to receive a character
OP3 TxRTSB* Negated if channel B Tx has nothing to transmit
OP4 RxRDYA Asserted if channel A Rx has received a character
OP5 RxRDYB Asserted if channel B Rx has received a character
OP6 TxRDYA Asserted if channel A Tx ready for data
OP7 TxRDYB Asserted if channel B Tx ready for data
Note the difference between the RxRTS* and TxRTS* functions. RxRTS* is used by a receiver to indicate to the remote transmitter that it (the receiver) is able to accept data. RxRTS* is connected to the transmitter's CTS* input to perform flow control (figure 8). The TxRTS* function is used to indicate to a modem that the DUART has further data to transmit.
Programming the DUART
Once the DUART has been configured it can be used to transmit and receive characters exactly like the 6850. The following fragment of code provides basic initialization, receive and transmit routines for the DUART.
* DUART equates
MR1A EQU 1 Mode register 1
MR2A EQU 1 Mode register 2 (same address as MR2A)
SRA EQU 3 Status register
CSRA EQU 3 Clock select register
CRA EQU 5 Command register
RBA EQU 7 Receiver buffer register (i.e., serial data in)
TBA EQU 7 Transmitter buffer register (i.e., data out)
IPCR EQU 9 Input port change register
ACR EQU 9 Auxiliary control register
ISR EQU 11 Interrupt status register
IMR EQU 11 Interrupt mask register
IVR EQU 25 Interrupt vector register
*
* Initialize the DUART
*
INITIAL LEA DUART,A0 A0 points at DUART base address
*
* Note the following three instructions are not necessary
* after a hardware reset to the DUART. They are included to
* show how the DUART is reset.
*
MOVE.B #$30,(CRA,A0) Reset Port A transmitter
MOVE.B #$20,(CRA,A0) Reset Port A receiver
MOVE.B #$10,(CRA,A0) Reset Port A MR (mode register) pointer
*
Purebasic Serial Port Example
* Select baud rate, data format and operating modes by
* setting up the ACR, MR1 and MR2 registers
*
MOVE.B #$00,(CACR,A0) Select baud rate set 1
MOVE.B #$BB,(CSRA,A0) Set both Rx and Tx speeds to 9600 baud
MOVE.B #$93,(MR1A,A0) Set Port A to 8-bits, no parity, 1 stop bit,
* enable RxRTS output
MOVE.B #$37,(MR2A,A0) Select normal operating mode, enable
* TxRTS, TxCTS, one stop bit
MOVE.B #$05,(CRA,A0) Enable Port A transmitter and receiver
RTS
*
* Input a single character from Port A (polled mode) into D2
*
PUT_CHAR MOVEM.L D0-D1/A0,-(SP) Save working registers
LEA DUART,A0 A0 points to DUART base address
Input_poll MOVE.B (SRA,A0),D1 Read the Port A status register
BTST #RxRDY,D1 Test receiver ready status
BEQ Input_poll UNTIL character received
MOVE.B (RBA,A0),D2 Read the character received by Port A
MOVEM.L (SP)+,D0-D1/A0 Restore working registers
RTS
*
Purebasic Serial Port Example Pdf
* Transmit a single character in D0 from Port A (polled mode)
*
PUT_CHAR MOVEM.L D0-D1/A0,-(SP) Save working registers
LEA DUART,A0 A0 points to DUART base address
Out_poll MOVE.B (SRA,A0),D1 Read Port A status register
BTST #TxRDY,D1 Test transmitter ready status
BEQ Out_poll UNTIL transmitter ready
MOVE.B D0,(TBA,A0) Transmit the character from Port A
MOVEM.L (SP)+,D0-D1/A0 Restore working registers
RTS
*
In spite of the DUART's complexity, you can see that it may be operated in a simple, non-interrupt-driven, character-by-character input/output mode, exactly like the ACIA, once its register have been set up. On at least one occasion I have tested software written for a 6850-based system on a board with a DUART by making the following modifications to the 6850's I/O routines.
6850 I/O DUART I/O
SETUP LEA ACIA,A0 SETUP LEA DUART,A0
MOVE.B #$03,(A0) MOVE.B #$13,(A0)
MOVE.B #$15,(A0) MOVE.B #$07,(A0)
RTS MOVE.B #$BB,(2,A0)
MOVE.B #$05,(4,A0)
RTS
LEA ACIA,A0 LEA DUART,A0
INPUT BTST.B #0,0(A0) INPUT BTST.B #0,(2,A0)
BNE INPUT BNE INPUT
MOVE.B (2,A0),D0 MOVE.B (6,A0),D0
RTS RTS
OUTPUT BTST.B #1,(0,A0) OUTPUT BTST.B #2,(2,A0)
Purebasic Serial Port Examples
BNE OUTPUT BNE OUTPUT
MOVE.B D0,(2,A0) MOVE.B D0,(6,A0)