www.angelfire.com/dragon/letstry
cwave04 at yahoo dot com
Free Guestbook
My Guestbook

A practical use

The last page talked about continuous time state machines, and menioned that they are useful in hardwares and softwares that interact directly with hardwares. In this page we shall see an example of the latter.

A phone line decoder

Many phone companies offer a caller id facility: the caller's number is sent to the callee during the ringing. The callee's phone can read this number from the line and display it suitably (or do something more exotic, like provide selective answers or just hang up if the number is in some black list). The phone company sends the information using a encoding scheme called DTMF (Dual Tone Multi-Frequency) and there are specialised chips (very inexpensive) that decode the information and output the digits via its pins. We shall consider phone numbers that is made of only the digits 0 to 9 (and not *'s or #'s). So there are 10 distict digits to consider, and since 10 is between 23 and 24, we need 4 bits to represent these digits. So it is only natural that a typical DTMF decoder chip has 4 pins (Q0,Q1,Q2 and Q3) dedicated for this purpose. Now there is also another configuration (other than the 10 digits) that the chip needs to report: the situation when there is no number in the line. DTMF decoder chips have a fifth pin (STD) for this, which remains low during the idle period. Everytime a digit is detected in the phone line, the digit is output via the 4 Q-pins, and the STD pin goes high. Thus each rising edge (i.e., 0 to 1 transition) of the STD pin denotes a digit. The states of the Q-pins at that moment gives the digit. Here is a typical timing diagram that you may get if the caller's number is 23.

Notice that the Q-pins are meant to be read only at the rising edges of the STD pin. Also, there is a little gap between the consecutive digits. There is another point of importance: the end of the number is not signalled by any special character. So we have to deduce that the end has been reached when the STD line remains low for period longer than the inter-digit gap. Typically inter-digit gaps are much less than 1 sec. So if the STD line remains 0 for more than 1 sec after a digit, we may safely deduce that this was the last digit of the phone number.

Our job is to program a microcontroller in such a way that it can pick up the complete phone number (and possibly do interesting things with it). This is a very typical example of software interacting directly with hardware, and the principles that we shall illustrate here find application everywhere in robotics.

The set up

This is not a tutorial on microcontrollar projects. So we shall not go into the details of what microcontroller to use and how to set up the circuit. It suffices to know that the microcontroller is a computer that can read the 5 pins Q0-Q3 and STD. We shall use the generic form read(pin) to denote a function that reads a specified pin (and returns 0 or 1).

Designing the DFA

Before we go into the details of the DFA let us informally think of the flow of action. We have no way of knowing when the phone rings (we shall not discuss the possibility of hooking up a separate ring-detector circuit to the microcontroller, as it will not change the underlying principle of DFA design), so we have to continuously monitor (or "poll", to use a technical term) the STD line. The moment it becomes 1, we have to read Q0-Q3 to get the digit. This will be over much before the STD line goes low. So we have to now poll the STD line again, this time waiting for it to go low. When it does go low, we basically do nothing, except start waiting for it go high again. When it goes high eventually we repeat the same process to get the next digit.

There is, however, a little catch in it. If we merely follow the above prcedure we shall never know when we come to the end of the number. So everytime we wait for the next digit we must time our wait. If the wait duration exceeds a threshold we should consider that as the end of the number. We should then stop waiting, and do whatever we want with the number. After that we have to return to polling for the next number.

Now we are in a position to turn this vague description into a formal DFA. You have no doubt noticed the numerous "wait"s or "polling"s that are strewn throughout the description. It should not be difficult to see that these will translate into the self-loops that are the trademark of a continuous time DFA. In fact, it will help if we name each state of our DFA as "waiting for this or that".

One state is obviously "waiting for a digit" (i.e., for STD to go high). We shall abbreviate the name to just "digit". We come to this state whenever STD goes low. So we must have a self-loop accordingly (we shall ignore the outputs for the time being). When we get STD=1, we exit this state.

We now finish reading the digit, and go into the next state: "nodigit" (which means "waiting for the digit to go away"). This state has its trademark selfloop.

Where do we go when STD becomes low again? Well, we go back to "waiting for a digit", which is also the initial state (assuming that the entire process did not start right in the midst of an incoming call!)

This looks like a pretty simple continuous time DFA. But we have to remember that little point about timing our wait in order to detect the end of the number. Making timed waits at various points is a very common requirement in robotics (and sometimes a contributor of confusion). We need a way to incorporate the concept of a timed wait within the framework of a continuous time DFA. We shall use a "timer" that we can start, and which will "time out" after a specific amount of time. Those of you who know some microcontroller programming may be tempted to think about timer interrupts and all that. But often a much simpler expedient works quite well. Of course, we may use a hardware timer built into the microcontroller (or even an external timer chip), but a counter incremented in a simple C loop will be enough for most purposes, since the exact length of the delay is not very critical as long as it is within a permissible range. Most external devices (including phone lines and human operators) are much slower than the microcontroller itself. So the permissible range is usually very wide.

The timer contributes a new output, "Timer on", and a new input "Timed out". In fact, there is another output that is also needed: "Stop timer". Imagine waking up one morning before the alarm clock goes off. Then we must switch off the alarm to prevent it from going off unnecessarily. Forgetting to turn off unused timers may cause all sorts of wierd things to happen.

This is all the change we need to our traditional concept of a DFA in order to accommodate timed waits.

The DFA for our example now looks like this.

Here X denotes the action that we want to take when we become aware of the presence of a digit, and Y denotes the action to be taken at the end of a complete number. Notice that we allow the (ineffectual) possibility of stopping a timer before it is started.

So far our exposition has been quite abstract. We have used the DFA formalism to express our ideas. In the next page we shall learn ways to implement the DFA using C.

PrevNext
© Arnab Chakraborty (2008)

free html visitor counters
hit counter