EmbeddedRelated.com
Forums
Memfault Beyond the Launch

BX-24P and DTMF decocer (8870)

Started by meenbombs January 14, 2006
I have pulled out the last strand of hair and cannot find the
problem. I essentially have an 8870 DTMF decoder with the binary
output pins connected to pins on the BX. There is a resistor to
ground at that junction which if I remember correctly is 100K. Here
is clipping of the code.

If ((Getpin(5) = 1) AND (Getpin(6) = 0) AND (Getpin(8) =0) AND
(Getpin(7) = 0)) then
Debug.print "Violation A1 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
(sec))
A1+1
F=1
end if

If ((Getpin(5) = 0) AND (Getpin(6) = 1) AND (Getpin(8) =0) AND
(Getpin(7) = 0))then
Debug.print "Violation A2 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
(sec))
A2+1
F=1
end if

If ((Getpin(5) = 1) AND (Getpin(6) = 1) AND (Getpin(8) =0) AND
(Getpin(7) = 0))then
Debug.print "Violation A3 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
(sec))
A3+1
F=1
end if

This goes on until 15 of the 16 potential combinations are covered.
The BX just loops indenfinetly through this code until the DTMF
receiver receives a signal. The problem is that about 1 out of 10
times that a tone is sent to the DTMF receiver the BX gives me the
violation associated with the inverse of whatever the violation was
supposed to be. For example if the DTMF receiver was supposed to
output on pins one and two(1,1,0,0) I will get the violation
associated with the DTMF receiver outputing on 3 and 4 (0,0,1,1). I
don't know if the DTMF receiver is jacked or there is some timing
issue or what. Any suggestions would be appreciated. I have
already tried to make the BX recognize that one or more of the DTMF
receiver pins is up, wait a short delay, then decide which digit is
supposed to be represented in case there was an issue with the DTMF
decoder outputting the inverse for a very short amount of time prior
to outputting the correct binary code. Thanks.


--- In basicx@basi..., "meenbombs" <szczepaniec@g...> wrote:
>If ((Getpin(5) = 1) AND (Getpin(6) = 0) AND (Getpin(8) =0) AND
> (Getpin(7) = 0)) then

I haven't yet studied your code enough to suggest an answer. I
wanted to point out, however, that it would simplify your code a lot
(not to mention making it smaller and faster) to read all 4 pins at
once. For example:

Dim code as Byte

code = (Register.PinC \ 16) And &H0f

This gets the 4 pin values into the low 4 bits of the 'code'
variable where you can easily use it in an If or Select Case, etc.

This will work best if pin 5 is the most significant of the input
bits and the other bits are in order of decreasing significance. If
they are in the other order, use:

code = FlipBits(Register.PinC) And &H0f

If they are not in order, I would suggest changing your circuit so
that they are.

Don



I had started a write-up of Decoding DTMF with a ZX-24, but never
quite got it completely finished; the text follows. There are pictures to
go with it, if you're interested I could find some way to post the article
- pics and all. I had all this working on a breadboard, but my need for
decoding DTMF went away before I built a final version. Good Luck!
Ken_S.

---
Introduction
DTMF is fairly easy for a CPU to generate, but harder to decode
(especially if there is noise and/or distortion involved.) Decoding purely
in software is very difficult because you have to account for variations in
tone frequency, amplitude (ratio of high and low tone amplitudes), noise,
and distortion. Fortunately, there are lots of inexpensive DTMF Decoder
chips out there. Most operate similarly, even if the pin numbers change.

Receiver Chips
MC145436A, SSI-204, M-8870, M-8880, M-8888, PCD331x series, ZL490xx
series, MTx27x series, more

DTMF Sources and Destinations
DTMF signals can have several Sources, Transport Mediums, and
Destinations. Mix and match Source, Transport Medium, and Destinations as
your application requires (use your imagination.)

Source Transport Medium Destination
Source Transport
Medium Destination
Telephone Phone Lines ZX-24
ZX-24 (FreqOut) Cell Phone Other
PC Sound Card Wireless
Other Infrared
Cassette Recorder
Other

Once a ZX-24 can detect DTMF, there are lots of things you can do;
such as

* Call from anywhere in the world (like from work) and control it.

* Remote operation or data transfer over a Wireless Radio Link.

* Send and/or receive information over an infrared link.

* Save data on a Cassette Recorder and retrieve it later (like the early
home computers did.) DTMF for Sending/Receiving Data
For the purpose of sending and receiving data, we dont have to get in
to the details of DTMF too much Absolute Minimum detection times are 40mS
of tone, and 40mS between tones; in practice you should use no less than
50mS tone and 50mS between tones. If your Transport Medium adds noise
and/or distortion, you could try extending the tone up to about 200mS long,
with 50mS between tones.

Since there are 16 tone pairs, we can conveniently use it to send
information a Nibble (four bits) at a time. Decoder chips typically have
five output lines; four to hold the Nibble of Information received, and one
to indicate that Data is Valid (however some use an I2C interface, or other
custom interface.)

DTMF reception Solution #1
The easiest is to connect the five lines directly to a ZX-24 as
shown. The components in gray are optional, use if Filtering is needed
(recommended.) Private Const DATA_D1_PIN As Byte = 5
Private Const DATA_D2_PIN As Byte = 6
Private Const DATA_D4_PIN As Byte = 7
Private Const DATA_D8_PIN As Byte = 8
Private Const DATA_DV_PIN As Byte = 9

Public Sub Main()
Dim x As Byte

Do
'*** Wait for DataValid = True ***
Do While ( GetPin(DATA_DV_PIN) = 0 )
Loop

'*** Get Data ***
x = (GetPin(DATA_D1_PIN) * &H0001) + _
(GetPin(DATA_D2_PIN) * &H0002) + _
(GetPin(DATA_D4_PIN) * &H0004) + _
(GetPin(DATA_D8_PIN) * &H0008)
Debug.Print CStr(x)

'*** Wait for DataValid = False ***
Do While ( GetPin(DATA_DV_PIN) = 1 )
Loop
Loop
End Sub

Thats nice, but tying up five I/O lines is rather expensive. It
would be nice to have a DTMF Receiver chip that had a serial output. I
scoured the Web, but couldnt find a DTMF in/Serial out chip (doesnt mean
it doesnt exist, I just couldnt find one.) I have two solutions that
amount to building a simple DTMF in/Serial out module.

DTMF reception Solution #2 DTMF in/Serial out Module
You can get a PicAxe 18X inexpensively on E-Bay, and the programming
software is free from www.PicAxe.Co.UK. (Note that the 08M doesnt have
enough input pins, so I had to move up to the 18X.) '*** PicAxe 18X DTMF to Serial Converter ***
symbol SerialOutPin = 0

WaitForDataValid:
if pin7 = 0 then WaitForDataValid

b0 = pins
bit3 = bit6
b0 = b0 AND %00001111
sertxd (#b0, 13, 10)
serout SerialOutPin, N4800, (b0)

WaitForDataInValid:
if pin7 = 1 then WaitForDataInValid

goto WaitForDataValid
end

DTMF reception Solution #3 DTMF in/Serial out Module
I wouldnt buy one just for this purpose, but if you already have a
PIC Programmer (or can justify buying it for future use) then this is a
better way to go. The Proton Compiler is free from www.PicBasic.Org, but
this (crippled) version only targets a select few chips. The PIC 12F675 is
even smaller (8 pins) and cheaper than a PicAxe 18X, and can be programmed
with the Proton Compiler. '*** Pic12F675 | SSI-204
'*** ----------+--------
'*** GP0 | D1
'*** GP1 | D2
'*** GP2 | D4
'*** GP3 | D8
'*** GP4 | DV (Data Valid)
'*** GP5 | Serial Out to ZX-24

OPTIMISER_LEVEL = 0 Device = 12F675
XTAL = 4 '*** 4MHz Internal ***
PORTB_PULLUPS = On
ALL_DIGITAL = TRUE

RSOUT_PIN = PORTB.5 '*** Leg 2 ***
RSOUT_MODE INVERTED
SERIAL_BAUD 19200
RSOUT_PACE = 0

'**********************************************
WaitForDataValid:
'*** Wait from Data Valid = 1 ***
While PORTB.4 = 0 : Wend

'*** Send Low-Order Bits ***
RSOut PORTB & %00001111

'*** Wait for Data Valid = 0 ***
While PORTB.4 = 1 : Wend

GoTo WaitForDataValid
End
'**********************************************

Single Component Serial in/DTMF out Generator
Cant generate DTMF with your favorite processor? Have a source of
Serial Data you need to send over a Transport Medium? If you have access
to a PIC Programmer, then you can build this Serial in/DTMF out module
using a PIC 12F675 and the free Proton Compiler listed above. If you use
the External Clock it will produce a better quality signal, so be sure to
change the code to XTAL = 20. The use of optional Filtering is
recommended, but may not be necessary for your application. OPTIMISER_LEVEL = 0
Device = 12F675
XTAL = 4 '20 '*** 20MHz ***
PORTB_PULLUPS = On
ALL_DIGITAL = TRUE

RSIN_PIN = PORTB.0 '*** PORTB.0 Leg 7 ***
RSIN_MODE INVERTED
SERIAL_BAUD 4800
RSIN_TIMEOUT = 1000 '*** Timeout in 1 Second(s) ***

Symbol MAXBYTES = 36

Dim bytData[MAXBYTES] As Byte
Dim bytNumReceived As Byte
Dim bytNumSent As Byte

Restart:
bytNumReceived = 0
While bytNumReceived < MAXBYTES
bytData[bytNumReceived] = RSIn, { SendDTMF }
Inc bytNumReceived
Wend

SendDTMF:
'*** Test for Any Data to Send ***
If bytNumReceived > 0 Then
bytNumSent = 0
While bytNumSent < bytNumReceived
'*** Test for Valid DTMF Value ***
If bytData[bytNumSent] >= 0 And bytData[bytNumSent] <= 15 Then
DTMFOut PORTB.1, [bytData[bytNumSent]] '*** PORTB.1 Leg 6 ***
End If
Inc bytNumSent
Wend
End If

GoTo Restart
End

At 10:53 PM 1/13/2006, you wrote:
>I have pulled out the last strand of hair and cannot find the
>problem. I essentially have an 8870 DTMF decoder with the binary
>output pins connected to pins on the BX. There is a resistor to
>ground at that junction which if I remember correctly is 100K. Here
>is clipping of the code.
>
>If ((Getpin(5) = 1) AND (Getpin(6) = 0) AND (Getpin(8) =0) AND
>(Getpin(7) = 0)) then
>Debug.print "Violation A1 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
>(sec))
>A1+1
>F=1
>end if
>
>If ((Getpin(5) = 0) AND (Getpin(6) = 1) AND (Getpin(8) =0) AND
>(Getpin(7) = 0))then
>Debug.print "Violation A2 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
>(sec))
>A2+1
>F=1
>end if
>
>If ((Getpin(5) = 1) AND (Getpin(6) = 1) AND (Getpin(8) =0) AND
>(Getpin(7) = 0))then
>Debug.print "Violation A3 "; Cstr(hr);":"; Cstr(min);":"; Cstr(cint
>(sec))
>A3+1
>F=1
>end if
>
>This goes on until 15 of the 16 potential combinations are covered.
>The BX just loops indenfinetly through this code until the DTMF
>receiver receives a signal. The problem is that about 1 out of 10
>times that a tone is sent to the DTMF receiver the BX gives me the
>violation associated with the inverse of whatever the violation was
>supposed to be. For example if the DTMF receiver was supposed to
>output on pins one and two(1,1,0,0) I will get the violation
>associated with the DTMF receiver outputing on 3 and 4 (0,0,1,1). I
>don't know if the DTMF receiver is jacked or there is some timing
>issue or what. Any suggestions would be appreciated. I have
>already tried to make the BX recognize that one or more of the DTMF
>receiver pins is up, wait a short delay, then decide which digit is
>supposed to be represented in case there was an issue with the DTMF
>decoder outputting the inverse for a very short amount of time prior
>to outputting the correct binary code. Thanks.




I agree with Don, this a far better way of handlinng the 8870 outputs.
Also, it does not appears that you are uusing the Std output of the 8870
( pin15). You should monitor this pin and only examine the 4 data
outputs when pin 15 is true. I assume you have the OE permanently true
and not floating?
neil

Don Kinzer wrote:

> --- In basicx@basi..., "meenbombs" <szczepaniec@g...> wrote:
> >If ((Getpin(5) = 1) AND (Getpin(6) = 0) AND (Getpin(8) =0) AND
> > (Getpin(7) = 0)) then
>
> I haven't yet studied your code enough to suggest an answer. I
> wanted to point out, however, that it would simplify your code a lot
> (not to mention making it smaller and faster) to read all 4 pins at
> once. For example:
>
> Dim code as Byte
>
> code = (Register.PinC \ 16) And &H0f
>
> This gets the 4 pin values into the low 4 bits of the 'code'
> variable where you can easily use it in an If or Select Case, etc.
>
> This will work best if pin 5 is the most significant of the input
> bits and the other bits are in order of decreasing significance. If
> they are in the other order, use:
>
> code = FlipBits(Register.PinC) And &H0f
>
> If they are not in order, I would suggest changing your circuit so
> that they are.
>
> Don >
> >. >
>




This was my second project and have since thought of better ways for the
programming, however, I have no time to do it again before this box 'O' hell
needs to be shipped. I have not used the Std output pin of the 8870 because
it reguires a fifth input pin on the BX. My logic was that the BX can
recognize 15 of 16 tones (through decoder) with four pins and adding the
fifth pin only gets one more tone. I have the BX in a box with 4 sets of 4
connectors to the input pins and if I used the Std pin it would require me
to use 3 of those four sets and negate the ability to plug some other things
in to the box. I cannot figure out what you are referring to as the "OE"
but if it is the fifth pin that we are discussing, I do have it floating.
Should it put put in a high or low state? I saw no note in the data sheet
stating that it had to be put in a particular configuration for use but if
somebody knows that is does please fill me in. Thanks.

[]




Memfault Beyond the Launch