Like Thoreau, I rejoice that there are owls. Part of the reason is that owls eat mice, and thus make a certain number of cats unnecessary, which is always a plus. But the better part of it is that owls seem to live by design, unlike English sparrows and house finches, which hop madly around in dead bushes, burning their calories in manic random motion to no good purpose.
A great horned owl has staked out our piece of desert as his turf, and he sits on the gnarly saguaro outside the master bedroom window, hooting mournfully all night long. It's not silence, but it beats drag-racing teenagers, and come summer the air conditioner will doubtless drown him out. Actually, we've become so fond of Mr. Horny that we held a party in his honor, and invited all our friends to come by and see him emerge from hiding at dusk and begin scanning the yard for mice.
So we had 20 people up on the sundeck, drinking beer and eating hors d'oerves and telling Saddam Hussein jokes, and dusk came and went with no sign of Mr. Horny. This was a surprise, since we had seen him every night for a very long time, and seems to point up a sort of Heisenberg's Uncertainty Principle about owls: Inviting 20 rowdy people to your sundeck to look for owls will almost certainly affect the likelihood of actually seeing one.
The owl has been gone for awhile, and we suspect Mr. Horny moved to Cave Creek, having deemed our slice of Scottsdale uninhabitable. The lesson: Owls only show up when you don't expect them. So don't expect them to appear--and rejoice when they do.
There's some considerable rejoicing to be done: Borland has announced and is shipping Turbo Pascal for Windows, and OWL. TPW (which is an entirely separate product from text-only Turbo Pascal 6.0) is Windows-hosted (that is, the product operates only under Windows) and generates only Windows applications. So if you've already decided that you hate Windows, pass it by. On the other hand, if you're a competent Turbo Pascal programmer and want a handhold on the exploding Windows market, you must get this product. Contrary to even my own expectations, it is good beyond imagining.
The reasons, like the product, are a little complex. Much of TPW's value lies in something called the Object Windows Library (OWL), which is an application framework for Windows, just as the Turbo Vision (TV) library (bundled with Turbo Pascal 6.0) is an application framework for text mode under DOS. I haven't had the chance to do much with Turbo Vision in this column (my list of topics-to-be-covered now runs down the hall and into the garage) but that might be just as well. TV and OWL are remarkably similar from a height, and implement identical ideas for two very different platforms. Both provide the underpinnings of an event-driven application, along with a rich collection of software components for building user- and system-interface code.
Both OWL and TV are inescapably object oriented. The idea behind an application framework is to inherit a boilerplate application that does nothing on its own, and add to it the specific code that lets it do the work you require of some particular application. The framework contains all the hooks on which you hang an application, divided along the classic OOP axis of generality versus specificity. The parent objects are so general that they have the potential to do almost anything, but too general to perform any useful task. So you define and implement child objects that do one specific thing, using as much of the parent's general code as possible.
If you've ever implemented a menuing system you'll probably know what I mean. Rather than hard-code specific menus into an application, the smart thing to do is create a general-purpose menuing machine, to which you feed some sort of menu-definition table that works with the menuing engine to create a particular menu with a particular set of options. There are numerous ways to do this (I presented one pre-OOP implementation in the Third Edition of Complete Turbo Pascal) and the OOP notion of inheritance is tailor-made for such things.
OWL and TV are both general-purpose "application engines" in that same sense. You inherit what may in fact be thousands of lines of general-purpose code from the application framework object and boilerplate window and control objects, and can create a very polished-looking application in what might be only a few hundred lines instead of many thousands. This is especially true of OWL under Windows, where the stuff that you inherit encapsulates some of the most violently difficult system-level code that one could imagine. (And I have a legendary imagination.)
Because let's face it: Microsoft Windows 3.0 was designed to do the impossible and comes pretty damned close. It breaks the 640K DOS memory barrier, and it adds multitasking to an operating system that isn't even reentrant. It isn't perfect and never will be, but what minor problems I've had with it (once I got it to run at all) are well worth the remarkable things it allows me to do.
Windows is an event-driven platform. Much or most of what Windows does, in fact, is manage the keyboard, mouse, serial port, error, and other system-generated events. Much or most of the work of writing a Windows application is creating machinery that responds to the events that Windows generates.
I could characterize Turbo Pascal for Windows programming, in fact, as the process of attaching object methods to the events that Windows generates. It's all very asynchronous: At unpredictable times, the user may press the left mouse button. Windows detects this and sends an event bubbling up from the depths to your application, saying, in effect, "Somebody pressed the left mouse button. What are you going to do about it?"
The left-mouse-button-pressed event is a little package of information that contains the location of the mouse cursor when the mouse button was pressed. This allows you to respond to the event in different ways depending on where the mouse cursor was when the user pressed the button.
In reality, Windows breaks down events into numerous special cases, and dispatches what it calls messages to your application rather than whole mouse events. (A rough count shows about 25 different messages relating to mouse clicks alone.) A message is a code number rather than some sort of text string, and parsing the message's code number is done automatically by OWL, as I'll explain a little later.
You might as well think of messages as Windows events (in the sense that I defined events in my December 1990 column) as long as you understand that the word "event" in a Windows context actually stands for the physical occurrence that gives rise to one or more messages. A quick example: Double-clicking on the left mouse button (which is what Windows considers the "event") gives rise to a down-click message, an up-click message, a double-click message, and a second up-click message.
If you're like me, one of the first things you'll find yourself wondering in looking at an event-driven programming model is, what's the flow of control? Where does execution start, and where does it end? One thing's for sure, using OWL is not like ordinary Pascal programming for DOS. (This also applies to Turbo Vision, as those who have used TV will readily agree.) We're used to seeing statements flowing one after the other in front of our eyes, like the Shenandoah River taking its curves and leaving its oxbows as it meanders toward its marriage with the Potomac.
Instead, what we have now is a network of underground code rivers that only occasionally spill out of a crack in the cliff, to run for a while and then vanish again into what seems like a bottomless pit. Typically, you the programmer only see the side streams that you create. The bulk of the river's flow is far beneath your feet.
OWL provides an application framework class called TApplication. To create your own TPW application, you define a child class of TApplication, and extend the child class with the specific methods your application needs to do its work. TApplication contains a message loop, which is in fact where execution remains most of the time. This message loop is hidden from you, and you inherit it whole and with no need to override or extend it. The loop runs in circles, continually asking Windows if any events are pending. When they are, the message loop parses a message, sees if you have defined a method to respond to that particular message, and if so, calls the method attached to the message.
This is how control is handled in an OWL application. The main message loop looks for messages, and calls the methods you have written as appropriate.
Attaching a method to a Windows message involves a new extension to the Turbo Pascal object syntax. The modifier VIRTUAL may be followed by a numeric constant or literal. This value specifies a Windows message to which that method is attached. Only virtual methods may be attached to messages in this way.
Something new that Windows brings to Pascal programming is the notion of resources, a collective name for field-replaceable program elements that include fonts, icons, bitmaps, menus, accelerator keys (which I generally call "shortcut" keys), graphics cursors, dialog boxes, and ordinary text strings. Resources are deliberately defined outside the code in a relatively code-independent fashion so that applications may be made language or even alphabet-independent with relatively little fiddling in source code. Ninety-five percent of moving your application from English to French lies in recreating the application's resources in the French language. Resources are stored in a program's .EXE image, but are not embedded in actual machine code.
Turbo Pascal for Windows includes a separate utility for creating, browsing and editing most Windows resources. This is the Whitewater Resource Toolkit, licensed from the Actor folks. Working with resources is a lot of fun, and the WRT is beautifully designed and highly intuitive.
Separating most program display elements off as resources applies a certain design discipline to the TPW programming process. Creating a menu structure as a resource requires that you design your menus before you start writing your code, which generally means that you have to specify your feature set (which is accessed through the menus) before you start pounding Pascal into the keyboard. This is all to the good. I expect that in very short order, third-party prototyping systems will appear for TPW, and you'll basically draw your application interactively, then push a button and generate OWL code to implement the bulk of the application, including resources. Such products exist for both C and C++, and the appearance of TPW opens up whole new markets for Windows prototyping and resource generation tools.
For all the fact that the Turbo Pascal Windows documentation is highly detailed and four inches thick, my instincts tell me that I could write several books on the product, and probably should. It's a very detailed subject, and although OWL manages the complexity of the Windows API to an amazing degree, there is a limit to how much complexity you can hide without beginning to "dumb down" the available resources of Windows itself.
Confronting a product such as TPW from a dead stop presents a feeling of nameless dread that I call "looking for the front door." There's so much technology there that it's far from clear what a newcomer should do first. I'm still burrowing through it myself, and will be for some time. However, let me offer a strategy for getting to know this thing:
I had expected something a little different from Turbo Pascal for Windows when I first heard that it was in the works. I expected something higher-level, a little more insulated from the Windows API, and a little easier to swallow in one gulp. I expected something, in short, to meet Actor nose-to-nose, especially since I knew that the Whitewater Resource Toolkit would be part of the deal.
On the other hand, there already is an Actor. Why make another one? What Borland in fact did is way more ambitious: They created a language that can do anything with Windows that C can do, and yet be only a little more difficult to learn than DOS-based Pascal. TPW allows you to make any API call, and responds to any Windows message, just as you can in C--yet it gives you the OWL library to do as much of the gritty work for you as possible. It creates DLLs. It supports the Multiple Document Interface. It does lots of things I don't quite understand yet. My instincts tell me clearly, however, that nothing is missing, and nothing has been hidden away irretrievably. If Windows can do it, TPW can make it happen.
I've used Windows since 1986, when it was still in beta test, and I've seen a lot of SDK versions come and go. I've seen the potential in Windows, and seen it buried beneath a monolithic hodge-podge of unmanaged and undifferentiated detail. Actor, when I discovered it, was a delight--but Actor never really caught on, largely for reasons of price and its proprietary nature.
Turbo Pascal for Windows is the first mainstream language (by that I mean C, Pascal, Basic, Modula-2, and Fortran) delivered in a form that runs under Windows, for Windows. At the risk of blathering, let me say that it is the second-finest product that Borland has ever introduced, equalled only by their groundbreaking Turbo Pascal 1.0. The compiler is fast, the environment beautiful, but OWL is the key--and if you give a hoot at all about Windows, you should rejoice that somebody finally made it happen.
In last month's column, I presented the view of the UART's register set from a height. This month, we'll take a closer and more detailed look at some of the registers' various bit fields and little-known lore.
In the following paragraphs I'll be describing each of the UART registers in a little more detail. Refer to the chart in Figure 1 in last month's column for COM port addresses and offsets for each named register.
Receive Buffer Register (RBR) When the UART has finished assembling a character out of serial bits arriving from a remote system, it places the completed character in RBR. You can read the character from RBR more than once, but don't bother reading it unless the Data Ready (DR) flag in the Line Status register (LSR) has been raised to a 1-bit, indicating that a character is complete and ready to read in RBR. What RBR contains when DR is 0 is undefined, and you should consider it a garbage value.
The UART has the ability to generate a hardware interrupt when a complete character is available in RBR. In professional-quality comm software, RBR is read only by such an interrupt service routine. We'll get into those in a later column.
Transmit Holding Register (THR) When you want to transmit a character to a remote system through the UART, you place the outbound character in THR. The UART then converts the character to a stream of bits placed on the serial port's single data line.
It is possible to stuff characters into THR faster than the UART can convert the characters to bits and move them out to the serial port. If this happens, you'll send bits flying all over the place and mess over your transmission in a serious fashion. Fortunately, there is a flag in LSR called Transmit Holding Register Empty (THRE) that indicates, in a fashion similar to DR, that THR is empty and that a new character may safely be written to it.
The UART can also generate an interrupt when THR becomes empty, and this feature allows you to write an interrupt routine that automatically stuffs characters from a buffer into the UART as fast as the UART can accept them.
Interrupt Enable Register (IER) The UART can operate in either interrupt driven or polled mode. I demonstrated polled mode last month with the POLLTERM.PAS program. Interrupt-driven mode is infinitely more useful, if considerably more tangled in how it must be set up.
The UART can in fact generate an interrupt on any of four different conditions: When an incoming character is ready to be read; when the UART is ready to send another character out; when any of four error bits in the LSR go to a value of 1; and when any of three status bits in the Modem Status register (MSR) change state. These four interrupts can be enabled and disabled independently of one another, by setting the appropriate bit to a 1 value and leaving the others at 0. (Keep in mind that interrupts must also be turned on for the adapter as a whole by setting yet another bit called OUT2 in the Modem Control Register. No one ever promised that life would be simple.)
I'll explain how these bits affect the interrupts in more detail when we cover communication interrupts in a future column.
Interrupt ID Register (IIR) Because the UART can generate any of four different interrupts for different conditions, it's possible for more than one interrupt to be "hanging fire" at one time. The CPU can eventually service them all, but it has to know which ones are pending at what time. When multiple interrupts are pending, the UART prioritizes them and lets the CPU know what's up next through a 3-bit code in IIR. Once a given pending interrupt has been serviced and cleared, the next one in priority is reflected in the code in the IIR. When finally bit O of IIR goes to 1, no more interrupts are pending.
Yes, this is confusing business. Again, we'll cover all registers connected with interrupt generation in more detail in a future column.
FIFO Control Register (FCR) This register is available only on the UART chip present in IBM PS/2s and PS/2 compatibles. A FIFO (First In First Out) is a register that allows you to queue up data inside the UART chip itself on both transmit and receive. It's like making both RBR and THR 16 characters deep. This is very handy when your interrupt service routines are complex and take a long time to execute, as they might in a protected-mode operating system. For DOS applications on fast machines they simply aren't necessary. (If they are, I suspect it means you don't know how to write a terse enough interrupt service routine.)
Unfortunately, the bulk of the PCs out there don't have the advanced UART chip containing the FIFOs, so it's unwise to rely on their being present in any given machine, although you can test for them. I won't be covering use of the FIFOs in this series; if you really need them, get the manufacturer's data sheets on the 16550 UART chip.
Line Control Register (LCR) This is a very useful register, entirely divided into bit fields, some of which represent 2- or 3-bit binary codes. I've summarized the different fields in Figure 1.
Bits 0 (WLS0) and 1 (WLS1) represent a 2-bit code specifying the number of bits in the "word length" (actually, the character length) to be used in data transmission, not counting start, parity, or stop bits. The acronyms are Word Length Select 0 and 1. The UART can send data using any of four different character lengths: 5, 6, 7, or 8 bits per character. 5 and 6 are rarely used anymore, and are a holdover from the bad old days of teletype. The bit codes corresponding to the various word lengths are shown in Figure 1.
Bit 2 (STB) controls the number of stop bits. The UART can transmit either one, two, or (again, in a throwback to Teletype days) one-and-a-half stop bits. If STB=0, one stop bit is used. If STB=1, two stop bits are used. However, if WLS0 and WLS1 specify that 5 data bits are to be used, a 1 bit in STB will specify one-and-a-half stop bits.
Bit 3 (PEN) enables and disables parity checking. When PEN=0, parity is disabled and no parity bit is sent or expected. When PEN=1, a parity scheme is enabled, the nature of which is dictated by bits 4 and 5.
Bit 4 (EPS) specifies "even" or "odd" parity. (If parity is disabled by setting PEN to 0, the state of EPS is ignored.) For lack of space, I won't explain parity in detail here, but it's a limited, character-by-character form of data validation. If you have parity enabled and a noise pulse blasts one of the bits in a character you're transmitting, chances are good the parity system will detect the damaged character and issue a parity error.
Bit 5 (STP) specifies whether or not "stick parity" is to be used. Stick parity means that the parity bit is "stuck" to either 1 or 0, irrespective of whether or not the character meets the parity-checking algorithm. Stick parity is actually a way of sending a parity bit without doing any parity checking, and is rarely used anymore.
Bits 3, 4, and 5 comprise a matrix that defines all the different parity modes that the UART can support. The matrix is included in Figure 1.
Bit 6 (BRK) is used to carry a signal to the UART that a "break" condition is to be created. To form a break condition, the data line is forced to the space condition without changing for a period of time longer than one character. Your program is responsible for setting the time; as long as BRK is set to 1, a break condition will be maintained. You set it, and you clear it--or it doesn't get cleared.
Bit 7 (DLAB) is the Divisor Latch Access Bit. This bit arbitrates between the two uses of the registers at offset 0 and 1 from the UART base address. Its value defaults to 0. Normally, the register at offset 0 is the RBR register, and the register at offset 1 is the THR register. However, when DLAB is set to 1, the register at offset 0 is used to access the low byte of the divisor value, and the register at offset 1 is used to access the high byte of the divisor value. The divisor value actually sets the baud rate; it is a constant by which an internal clock is divided to produce the master series of pulses that the UART modulates into serial characters.
I'll have more to say about baud rates and divisors next issue. I had hoped to cover all of the registers in one column, but Turbo Pascal for Windows intervened. Ahh, so much technology--so little time!
Turbo Pascal for Windows Borland International 1800 Green Hills Road Scotts Valley, CA 95066 408-438-8400 $249.95
Copyright © 1991, Dr. Dobb's JournalSpotting OWL
In the Belly of the Beast
Underground Code Rivers
Resources
Finding the Front Door
Once you get started, the force of accumulated experience builds quickly. The manual set is very good, but I did find some notable lapses. The worst of these is that while Windows' communications port support is documented piecemeal, nothing tells you how to put the pieces together to access the port. Windows apparently contains its own interrupt-driven serial port code, and will generate messages corresponding to various changes in the state of the port (including the appearance of an incoming character) but no matter how I arranged the pieces, the port would not come alive for me. If any of you can tell me how to access the serial port from within Windows, please tell me so I can explain it to everybody else.The Start of an Era
The UART Registers Dissected
Products Mentioned