Sie sind auf Seite 1von 15

A SIMPLE USB OSCILLOSCOPE FOR THE PC

PART I
By Dr Eddie Insam
Copyright 2002 Eddy Insam - email: edinsam@eix.co.uk

Published In Electronics World: February/March 2002

Printed Copies of this article can be obtained from Electronics World.


Anne Boleyn House. 9-13 Ewell Road, Cheam Surrey SM3 8BZ UK or by email: jackie.lowe@cumulusmedia.co.uk

No part can be copied without the express authority from the author

Abstract Box

If you are thinking about adding a USB interface between your project and a PC, read on. Implementing USB is now easier than you
think. Eddy Insam will show you how.

The USB (Universal Serial Bus) provides a new way of interfacing low and medium speed peripherals to personal computers. That
old workhorse, the RS232 connector, is fast becoming obsolete, even becoming absent in newly purchased PCs.

The new USB standards are rather complex when compared to RS232. To make things worse, there is no easy route for designers
wanting to add USB capabilities to their products that need to communicate with PCs. Fortunately, this situation is changing. New
devices are available that make this job easier. So easy in fact, that now you do not need to know anything about USB.

In Part I of this article, I shall cover the very basics of USB and show in simple sketches how it all works. In Part II, I shall use, as a
practical example, a simple oscilloscope project to show how easy it is to implement USB in your own designs.

What is USB - In a Nutshell

I shall not be describing the inner workings of USB in any precise detail. For this, refer to the excellent article by Tom Wong
mentioned in the reference section. I shall only cover here those aspects that are relevant to an applications designer.

USB uses a time-shared serial data stream. The PC acts as a master by polling all connected peripherals at regular intervals of one
mS. Each peripheral responds by placing its data on the time multiplexed bus at their allocated time within this 1mS frame. An
addressing scheme allows up to 127 devices to be connected to the bus.

The current version of USB (V1.1) supports two speed modes (12Mbit/s and 1.5Mbit/s). These are selected in the hardware by tying
one of the data lines to a supply via a pull-up resistor. The two speeds can live together, fast and slow speed bursts can co-exist on
the same wire.

USB uses a four-wire cable system. Two leads are used for power (5volt and gnd), the other two for differential data. Unbalanced
data patterns are used to transfer special end codes. Different physical connectors are used for upstream and downstream
connections. This is to avoid the user getting confused. Fig1.

Peripherals are not just wired together, but are connected to the PC via a tree of hubs. A typical PC will have an internal hub
supporting two USB sockets on its back plane. If you need to attach more than two USB peripherals, you must purchase an external
hub and attach it to one of the spare ports on your PC, then connect your peripheral to the new hub, this is somewhat like a mains
extension lead.

The above is, as you would expect, only the simple version of events, with many extras and options under the surface. If you are
new to USB, you should not be surprised to hear that there is already a new version of the standard with even more capabilities
(Version 2). For the moment, we shall concentrate only on the present version (Ver1.1).

The Protocol

As already mentioned, the USB is a single master bus, with all requests for activity originating from the PC. Data is transferred in
packet bursts contained within frames separated by 1 mS. Low speed devices operate at a rate of 1.5Mbit/s, and the bit length is
667nS. Similarly, fast speed devices operate at 12Mbit/s and the bit length is 83.3nS.

USB peripherals have to synchronise their outputs to the frame start, so internal buffers are generally necessary to maintain a
constant flow of data. The bit rate clock is recovered from the NRZI encoded data stream Fig2.

A typical USB peripheral may have more than one endpoint. Endpoints are nothing more than different destination registers
sharing the same device address. Different endpoints can be used for initialisation and control, and for ordinary data transfers. USB
uses the term pipe to denote a data transfer from the PC to a particular endpoint. To increase data rate, a peripheral may occupy
more than one pipe at a time.

There are four basic methods of transferring information between a PC and a USB peripheral:

Control -Transfer: Used mainly to send control signals to the peripheral. These have high priority and incorporate inbuilt error
protection. It is mainly used for transferring initialisation information, but can also be used for general-purpose low speed data
transfers. All USB devices must support Control Transfers.

Bulk - Transfer: Used mainly by storage devices to transfer large amounts of data in a time independent manner. This is useful for
printers, disk drivers etc. This method has low priority on the bus.

Interrupt - Transfer: Used mainly by low speed data peripherals such as mice and keyboards that need to send small amounts of
data quickly and periodically to the PC.

Isochronous - Transfer: Used by peripherals transferring large amounts of data at a defined data rate, e.g. soundcards. No error
protection is included. The system must assume that some data may be lost.

The above are summarised in the following table. Even though USB is rated at 12Mbit/s, the final effective data rate in some cases
can be quite low. For an error protected control link using the low speed bus for example, the guaranteed data rate is limited to only
800 bytes per second.

Transfer Type Control Bulk Interrupt Isochronous


Data bytes/millisecond per 832, in thirteen 1216, in nineteen 64 1023
transfer, maximum possible 64-byte transactions 64-byte transactions
per pipe (full speed)
Data bytes/millisecond per 24, in three 8-byte not allowed 0.8, 8 bytes per 10 not allowed
transfer, maximum possible transactions milliseconds
per pipe (low speed)
Reserved bandwidth for all 10% none 90% 90%
transfers of the type, max %
Int & Iso combined Int & Iso combined
Error correction? yes yes yes yes
Guaranteed Delivery rate? no no no yes
Guaranteed latency (max time no no yes yes
between transfers)?

THE PC Side of Things

Most PCs now include one or two USB connector sockets at the back. Support for USB is via kernel level device drivers in the
operating system. Therefore, if you do not have a driver installed, the USB port will not be available to you. This is very different from
the good old times of parallel and serial ports where you could access the interface chips directly from your applications program.
Each USB peripheral requires a driver of its own class. These low level drivers are usually supplied with the peripheral when
purchased. Peripherals are recognised one by one by the operating system during the boot-up sequence, which also causes the
right drivers to be loaded. USB is a hot wire protocol. The PC can also recognise when a peripheral has been plugged or
unplugged during normal work, and is able to load or unload the corresponding driver at the same time. This makes USB more or
less transparent to the user.

In case you have not thought about the situation, most BIOS will also include some form of built in primitive USB support for
keyboard and mice, so these can be recognised as such before the boot sequence and before Windows starts.

Windows includes a number of ready made USB drivers for interfaces going under the generic name of HID (human interface
devices). These consist of mice, keyboards, pointers and joysticks. This allows a generic product such as a mouse, to be plugged in
without having to install a special driver.

The installation procedure is very simple. When the peripheral is plugged in, a polling signal by the hub causes Windows to send
signals on the USB asking for identification. The peripheral responds with its own PID and VID (Product and Vendor IDs). Windows
then searches its directories for the correct driver assigned to that particular peripheral. If it cannot find one, it pops up a message
requesting the user to install one. The drivers are usually supplied on floppy or CD. Once the driver is installed, the application
program carries on as normal.

How to Implement USB in your Project

If you wanted to add an RS232 interface to your product, you only needed to write simple comms software to drive or emulate a
UART, add a small amount of RS232 level shifting hardware and then write some simple protocol to transfer the data, perhaps using
some simple error correction scheme.

Adding USB is a lot more difficult. You have few choices. You could obtain a micro controller with built in USB capabilities and
develop your project around it, i.e. using its hardware functions and instruction set. On the other hand, you could buy a USB device
designed as a peripheral, and interface it into your project. In both cases, you need to understand quite a bit about USB.

Many manufacturers offer microprocessor with built in USB capabilities. Cypress, Microchip and Philips among them. These range
from simple devices with just enough memory and processing power for the simplest of tasks, i.e. keyboard or mouse, to devices
built around more advanced cores such as the 8051 with a varied range of features. USB support is provided in the form of firmware
subroutines, which you link into your own code. In practice, the USB add-ons can take quite a big chunk of the microprocessors
memory space and power.

Your involvement also includes creating the Product and Vendor description tables. Most of the information here will be provided by
the chip manufacturer, and may need to be customised for your mode of operation. You will need to obtain your own unique Vendor
and Product IDs. These numbers make your peripheral uniquely recognisable by the operating system in order to load the right
driver. For development and testing you can use the IDs allocated to the USB interface chip you are using, this is perfectly legal
(more on this later).

The USB cable can provide some power for the peripheral. However, you should be conversant with the USB specifications, which
allow for up to 500mA to be drawn when the peripheral is active, but only 500uA when inactive. This means you have to provide for
means of switching the power off while the USB is in the suspend state.

As I shall be discussing soon, there is now the option of incorporating USB without any frills. This becomes no more complicated
than adding an 8 bit parallel port buffer to your micro. You need to know nothing about USB, or even how it works. So, you can more
or less forget everything I said.

How about the PC end?

Having developed your USB hardware and firmware on your peripheral, you will still need to write a bit of software to go at the PC
end. You will need to write a low level driver. You will need a different driver for each type of platform. Fortunately, there is a certain
degree of commonality among Windows versions, so the same driver could be used for Windows 98, ME and 2000. (Native NT
does not support USB). A different set of drivers will be needed for Mac and Unix/Linux however.

Windows supports a range of basic ready made HID (human interface device) drivers off the peg, so if your project is one of these,
call yourself lucky as you will not need to craft your own driver. In addition to HIDs, there are standard USB classes for sound cards,
frame grabbers and printers. Most likely, your project will not fit into any of these categories, so you will need to brew your own.

If you need to develop your own driver, there is some limited help available. The DDK Device Development Kit from Microsoft
contains templates and samples of drivers for the most common USB applications. In addition, many samples and information notes
are available for downloading from the Internet. Still, writing a device driver is not a trivial exercise. Poorly written drivers can cause
unexpected crashes and can make life very difficult for the inexperienced programmer.

Writing the driver is not the end of the story. You will need to adapt your application program to communicate with the driver.
Windows programmer can use the CreateFile and DeviceIOControl API functions to communicate with USB peripherals.
Fortunately, these are relatively easy to use.

Ready to Bake USB

As I mentioned before, there is now a simple no brains way of adding USB to your project. By this, I mean at both ends - the PC
software too - is reduced to the lowest level of simplicity.

The project in this article is based on the FT8U245AM device manufactured by FTDI Ltd in Scotland, (www.ftdichip.com). This chip
comes as a 32 pin surface mount MQFP miniature package. To work, the chip only requires a 6MHz crystal, some passives and the
USB socket, Fig3. The chip interfaces to an external microprocessor via an 8 bit parallel port and four read write and control lines.
From the micros point of view, the FT245 chip looks like a 384 byte FIFO buffer for transmit, and a 128 byte FIFO buffer on receive.
The FT245 works in the full USB speed mode and can transfer data at around 1 Megabyte per second.

Using this chip is as simple as connecting a 74HC245 buffer to one of your micro parallel ports (maybe this has something to do with
the naming of the device). The FTDI chip hides all the USB intricacies from the user. To transmit a byte, you place your 8 bit data
on the parallel bus, poll the transmit buffer available signal (/TXE) until it goes low, and then pulse the WR control line to push your
byte into the transmit FIFO. To receive a byte, you poll the byte available signal RXE. This tells you that a byte is available for
reading. You read it by pulsing the RD control line. That is all there is to it. Nothing could be simpler.

To make life even simpler, a piggyback module known as USBMOD2 is available from FTDI. This incorporates the FT245 chip, a
6MHZ crystal, a USB socket, and the required passive components onto a 23 pin piggyback module. This is ideal for prototyping as
it can plug directly into a 32 pin bread-boarding socket Fig 4.

You may be wondering whether you still need to be involved in writing device drivers. There is no need, the drivers supplied by FTDI
makes the USB interface appear to your PC as a regular comms port. Therefore, if your PC project software was written with the
serial port in mind, you will have little work to do.

Instant Satisfaction - Testing The Module

On receiving the module, it took me less than a few minutes to install the driver on my Windows PC. I was able to go to the Control
Panel, under Device Manager, and see a new entry (COM3) added to the listing of my available comms ports.

I plugged the module into a breadboard plug-in strip. I then connected a few LEDs directly to the data ports, and a 100n capacitor to
crudely generate a RD pulse from the RXE line Fig5. No power supply was necessary as the USB module is powered from the
cable itself. I then went to my PC and opened a simple terminal program opened on COM3, typing some characters. The LEDs
flickered in perfect harmony. Total time, less than fifteen minutes. Not bad.

Next month I shall describe the circuit required to turn this module into a simple fast voltmeter/oscilloscope.

Obtaining the parts

The USB module is available from FTDI in the UK for 23.50 inc VAT and pp. The company has local Agents in the US and
Australia. Check their website www.ftdichip.com for more up to date details on pricing and availability.

An alternative device FT232 provides a serial output instead of a parallel one. This could be used as a direct replacement for
systems using legacy RS232 interfaces. Full information is available from the FTDI website.

The Author

Dr Eddy Insam is a consultant in innovative applications of telecommunications and specialises in graphics and signal processing.
He can be reached on edinsam@eix.co.uk.

For More Information

Tony Wong Understanding USB Electronics World, November 1999. A very good article describing the inner workings of USB.

http://www.usb.org The website of the USB organisation.

http://www.ftdichip.com For more information on the USB chip and module.

J. Hyde USB Design by Example Wiley, NY 1999. http://www.usb-by-example.com


j. Axelson USB Complete Lakeview Research 1999. http://www.lvr.com

These are two good reference books on USB. They contain many examples and background information.
A SIMPLE USB OSCILLOSCOPE FOR THE PC
PART II
Eddy Insam
In Part I, I described the basics of USB. This month I shall show how simple it is to convert this into a useful product, in this case a
simple oscilloscope probe. The sampling rate may not be very exciting for RF people, but can be perfectly acceptable for audio and
teaching work.

Fig 6 shows the basic concept. I used a Texas Instruments TLC5510 flash A/D Converter (you can also use the faster version
TLC5540). These are cheap, fast CMOS devices that take very little current. They also require the minimum of interfacing as can be
seen. As all the chips are surface mount, and the whole circuit is small enough to fit into a hand held probe.

The circuit works as follows: the 74HC132 Schmitt trigger chain forms a simple relaxation oscillator gated by the TXE buffer data
available signal from the USB module. This simple arrangement produces write clock pulses for the module and in slightly delayed
form, for the A/D converter. The gating ensures clocks are only generated when the USB module is ready to accept them.

When testing, note that the clock will only run if there is a program at the PC end reading the data, otherwise the transmit FIFO fills
up and the module just stops taking data. The oscillator frequency sets the A/D sampling rate. Because of USB transfer limits, the
maximum rate will be about 1MHz. However, the application program in your PC may not be able to accept this data continuously,
especially if you have other fast USB peripherals connected (e.g. sound cards or video grabbers).

Fig7 shows a section of the same circuit showing how a two-trace version of the scope could be implemented. I have used two A/D
converters, as it is easier (and possibly cheaper) to do it this way than try to arrange for an analogue switch on the input. As we now
need to take two readings per sample, the overall sampling rate will be halved, reducing the effective bandwidth to 250KHz, still
good enough for audio work. The principle can be extended to 4 or more traces by simply adding more D flip-flops. One
disadvantage of this method is that the PC does not know which sample corresponds to which input. I cheated by adding a button on
the software to switch the traces around.
A similar arrangement can be used to read from higher resolution 12, 14 or 16 bit A/D converters, by selecting between the most
significant and least significant bytes of a single, wide A/D device. If the converter has less than 16 bits, one of the spare bits can be
used as an external trigger input. Alternatively, the unused bits can be set to a fixed data pattern. This may enable the PC software
to synchronise to the correct byte order by analysing the repetition patterns in the byte pairs received.

Both the A/D and the FT device can operate at up to 10MHz in burst mode. It is therefore possible to run the scope ten times faster
by filling the transmit FIFO buffer at the higher clock rates, and dumping to the PC at the normal 1MHz transfer rate. The 384 byte
FIFO may not be large enough for some applications. However, it is quite easy to add an external FIFO RAM (such as a 256K TV
frame grabber FIFO). The buffer is connected between the A/D and the USB. Clocking and gating arrangements are relatively
straightforward. This would allows the scope to run at up to 5MHz bandwidth in burst mode. This can also form the basis of a simple
USB video frame grabber.

Input Circuit

All configurations share the same input circuitry. This is shown in detail in Fig8. The TLC5510 has an adjustable analogue input
span that is determined by the externally applied voltages at pins REFT and REFB. The chip includes a number of internal resistors
that allow designers to choose a set of gap options without adding external circuitry. The chip was designed mainly for video
conversion, and the two main range options are either 0.0 - 2.3 volts, and 0.6 to 2.6 volts.

However, we have a little problem here. The USB cable provides a variable supply voltage between 4.2 and 5.25 volts. The simple
resistor divider inside the chip will not give us an accurate reference (it also draws about 10mA quiescent). As an alternative, I used
an external 2.5 reference diode, dispensing with the internal resistors.
The analogue input to the A/D is internally connected to various capacitor switches, and ideally, requires a low impedance source.
We also need some means of shifting the voltage levels so that the probe input can measure negative voltages. We also need some
means of trimming the overall gain and zero points. I used two op-amps in the simple configuration shown. You may prefer to use
some other arrangement as long as it eventually provides an output of 0 to 2.5 volts at low impedance into the A/D converter. The
op-amp should be a high impedance, high frequency type, enough to give a gain of at least ten at 10MHz. Be aware that some
op-amps have limited top saturation voltages and with a positive supply of 5 volts they may clip below the 2.5 volts needed. I used
an LF353 for no other reason that I happened to have one available at the time. This seemed to work very well.

All power is derived from the USB wire. The FT device, the Texas CMOS A/D converter and the op amp all require very little current
and can happily work off these voltages at all times, even when the USB is inactive. However, in order to generate the negative
supply for the op-amp I needed to include a DC-to-DC converter, which robbed nearly 15mA from the 5-volt supply. I found myself
adding a simple circuit using a PNP transistor to remove power to the DC converter and to the op-amp when the USB is inactive.
The FT module does not provide a specific power down output, so I crudely derived this from the TXE signal. If you use a more
efficient low power DC-to-DC converter, you may not need this part of the circuit. It may be possible to derive the negative supply
from the clock. I assume it should work as the op-amp takes little power. I have not tried this.

The TLC5510 chip is incredibly sensitive to noise and supply glitches. This shows as bumps and spikes on the displayed
waveforms, especially during 0111111 to 100000 type transitions. The application notes suggest the use of separate connections for
digital and analogue supplies. You DO need these if you want a clean output. If you are creating your own PCB layout, make sure
you download the datasheets from the Texas website including all application notes. They contain very useful recommendations on
noise suppression.

For my prototype, I used air to air wiring for all pin connections on the Texas chip. This at least guaranteed that no PCB cross talk
noise would be present.

I might have spent ten minutes getting the USB module to work but I am not saying how much time I spent trying to minimise
analogue noise problems.

PC Application software

On the PC, you only need to install the FTDI comms emulation driver (VCP). All the relevant drivers are downloadable from their
website. These are available for all relevant versions of Windows, Mac and Unix/Linux. Detailed installation instructions are also
available from the website. They are very simple, and you may not want to read them. Especially if you are like me, who likes to try
things first, and only read the documentation later when things do not work.
After installation, you will notice that an extra COM port has been added to the existing list in your control panel. Note that this COM
port is only enabled when the USB module is active. So, if you want to change the number for example, ensure the USB module is
plugged in.

Writing software for the PC is quite simple. Many of you will be conversant with software programming, whether in Basic, Borland or
Microsoft tools. If you have written software for the serial port, read no further! The only thing you will need to know is that the FT
module looks in all respects like a comms port. Only that speed parameters are ignored. The chip runs at full speed.

For those of you using Basic, there are a number of plug in ActiveX and DLL component modules you can get for driving the serial
port. I have not tried any of these, but considering the high data rates involved, I would not be surprised if some of these are not able
to keep up with the incoming stream from the FT module.

However, there is an alternative, FTDI also supplies a set of drivers that will allow you faster and more direct access to the chip
resources. These drivers (known as D2XXX) are provided in the form of separate DLL files that present a relatively simple interface
to VB, VC++, C+ Builder, Delphi etc. You just link it to your software project.

For those of you using C or C++, you can use any of the many Windows API functions. Listing 1 shows some very simple plain
vanilla code you can include in your application when using the FTDI serial emulator interface. The only two functions required are
com_Init() and com_Exit(). These are used to initialise and terminate the comms service. These should be called once at the
beginning of the program and once at the end.

The initialisation program starts a thread. This is a section of code that runs transparently in parallel with the main user program.
The thread keeps a watch on incoming serial port bytes, and calls a function in the main user program whenever there is a quantity
of bytes to transfer. We call this a callback function. In this way, the main program does not need to spend time reading the
comms port, usually a cause for hangs and clumsy behaviour in some Windows programs.

I have made the code in the thread very simple, and have not resorted to advanced methods such as events or overlapped
functions. I wanted to make it easily readable and understood by those not fully conversant with advanced programming topics. The
thread consists of an infinite loop, which is only terminated when an error occurs or when a global flag is set. This follows the normal
practice that threads should terminate themselves. The loop within the thread first calls a comms API to find out how many bytes are
there in the comms buffer. This has the seemingly inappropriate name of ClearCommError(). In our case, this function will nominally
return either 4k (This is the default transfer size for the FT driver as specified in the INF file) or zero. If there are bytes to read, we
call the ReadFile() function to move these into our circular buffer, and then call a function in the user program. I have called this
function CommReadCB(). If there are no bytes to transfer, I put the thread to sleep for 10mSecs. The Sleep() API Function is a
simple and efficient way of blocking a thread for a fixed time, as it manages the multi-tasking using very few CPU cycles. This
blocking ensures the thread does not run continuously and hog large chunks of the CPU time.

In my version of the program, I have extra code within the thread for interpolation of arrays, and for detecting a trigger point to
emulate a triggered scope. These are written around the Read and Sleep function to maximise usage of spare time. I have not
shown these as they may reduce readability of the relevant sections of code.

The callback function in the main program is used to process the incoming array. For example, rearranging data arrays for display
bitmaps, performing filtering and processing etc.

One important point for software developers: You must avoid calling certain Windows API functions, especially graphic functions
from within the thread or the user callback, you may cause very odd effects including crashes. Windows provides the PostMessage
function for this.

The FTDI driver defaults to 4kbytes transfers. There can be up to 250 calls to the callback routine in the main program every
second. Some PCs can handle this rate quite happily. With my simple demo program, my 300MHz PC had enough time to display
each array received on an oscilloscope graphics, and also compute and display the same data as a 1024 point FFT (including
integer to float interpolation).

I am not much of an artistic person when it comes to designing front panels; Fig9 shows my crude attempts of displaying the scope
output on a PC. I am sure you will be able to come up with much more attractive designs.
Taking it Further

If you intend to commercialise your product using USB you must register your own VID and PID with the USB organisation
(www.usb.org). Becoming a member of this Forum costs $2,500 per year, although you can obtain an ID number without joining the
organisation for $1,500. Check their website for more details.

Alternatively, you could use the default VID and PID of the FT245 device. This has the disadvantage that connecting multiple FT
devices to the same computer may confuse the drivers. However, FTDI maintains a book of unique PIDs that can be uniquely
allocated to you at no cost. Please email fred.dart@ftdchip.com for more details. The only downside of going this route is that you
cannot apply for USB certification for your products, or use the new trademarked USB logo on your packaging - to do so, you must
apply for your own VID.

You may be wondering how the PID is stored within the FT chip. The FTDI device contains its own hardwired VID (0403hex) and
PID codes (0601hex). When adding your own, you store these in a separate 93C46 EEPROM chip that connects directly to the
FT245 chip. This is the little box shown in Fig3.

Obtaining the parts

The Texas A/D converter is available from Farnell at about 4 each in small quantities. The USB module is available from FTDI in
the UK for 23.50, which includes VAT and pp. The company has local Agents in the US and Australia. Check their website
www.ftdichip.co.uk for more up to date details on pricing and availability.

An alternative device FT232, provides a serial output instead of a parallel one. This could be used as a direct replacement for
systems using legacy RS232 interfaces. Full information is available from the FTDI website.

The Author

Dr Eddy Insam is a consultant in innovative applications of telecommunications and specialises in graphics and signal processing.
He can be reached on edinsam@eix.co.uk.

For More Information

http://www.ftdichip.com For more information on the USB module.

http://www.Farnell.co.uk

http://focus.ti.com/docs/analog/analoghomepage.jhtml Texas Instruments datasheets on AD converters and application notes.


Listing 1, Page 1
//**************************************************************************

//** User Entry points:

int com_Init (int port, int bsize);

int com_Exit ();


//**************************************************************************

//** Local variables, user does not need to access these

HANDLE com_handle= NULL; // comms port handle

int com_thrstop=0; // flag to order thread to stop

int com_bmask= 0; // max buffer size mask, i.e. 0x3FFF

int com_bsize= 0; // circular buffer size = bmask+1

int com_bindx= 0; // circular index to last written data

PBYTE com_bdata= NULL; // ptr to rx data buffer

char com_zerror [256]; // stores error messages


//**************************************************************************

//** - The main running thread. This is called by the Init function, and

// made to stop by the Exit function. User does not call this.

// - Uses NON_OVERLAPPED mode with simple sleep delay for simplicity

static DWORD WINAPI com_Thr(LPVOID p)

{ COMSTAT comstat; DWORD errmask;


//** Initialise and validate.................................................

com_thrstop=0;

com_bindx= 0;
//** Do the forever loop.(till stop flag is set externally)................

while ( (com_thrstop==0) && (com_handle!=NULL) &&(pDlg!=NULL) )

{ //** Add any extra operations here,

//

//* Get nr of bytes in rx queue to read

ClearCommError(com_handle,&errmask,&comstat);

int ntr=comstat.cbInQue; // this gives the Q size

//

if (ntr>0)

{ //* align for wraparound in circular buffer

if ( (ntr + com_bindx) > com_bsize) ntr = com_bsize - com_bindx;

PBYTE ptr = com_bdata + com_bindx;

//* Read the bytes to our buffer

DWORD nrd;

int ne=ReadFile(com_handle,ptr,ntr,&nrd,NULL);

//* Handle errors, if any..........................................

if (ne==0)
Listing 1, Page 2