DTMF Decoder Bit Bang

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For starters - I know there are perfectly working IC:s for decoding the DTMF and that those are very easy to use.

but ...

I have more than 300 Atmega32 MCU:s sitting on my shelf and not a single DTMF decoder.

So I really did a search to this forum and found a zippo. Googel, however, revealed the following thread:
https://www.avrfreaks.net/index.p...

There was an interestinng document, actually a TI application note which contains some assembler code to do this. The assembler is not for AVR but I don't think it will be a big issue to convert it to C.

So, my question is: Have You ever fiddled with software-only DTMF decoder? Any luck with it?

I am NOT asking for code - I am just asking for trouble - or merely early warnings. Be aware though - I am a stubborn idiot who does not take warnings too seriously.

Edit: I was really considering to start this in another part of this forum - but as I will do this in GCC - I thought that this is a proper place after all. However, feel free to move this to another place if needed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

eskoilola wrote:
Have You ever fiddled with software-only DTMF decoder?
I haven't experimented with this myself but there is a guy by the name of Scott Dattalo who has posted a page detailing the theory and the PIC code to do just that.

http://www.dattalo.com/technical...

Too bad, though, that he wastes his time in the PIC domain ;)

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't check the provided references if this was already mentioned somewhere http://en.wikipedia.org/wiki/Goe...

You'd probably have to run some numbers and count cycles to figure out if it can be done in an AVR. I am to lazy to do it.

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would probably start doing it in assembly and using
the code of the AVR200 app.-note for fast multiplication and addition.
There is also a app. note about FIR filters using
the AVR. I think these notes make it possible to
estimate the runtime of the algorithms.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Microchip has a very useful app note on decoding DTMF:

http://search.microchip.com/searchapp/searchhome.aspx?id=2&q=AN257%20-%20DTMF%20Detection%20Using%20PIC18%20Microcontrollers&ac=1

It's included in the zip file, together with the source code and a DTMF simulator. They also have DTMF libraries. Why doesn't Atmel do that sort of thing?

Leon Heller G1HSM

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the replies. And especially thanks for not introducing me with
a wonderful IC that propably brews the espresso while decoding DTMF.

So let's start from the beginning. The A/D part must have constant and
known sample rate. This in turn involves use of a timer. I have read that
the result will become better as the sample rate increases. If there is no
buffering between the actual calculations and the A/D then there will be
some restrictions on execution times for the mathematics.

On the other hand I have also read that a reliable result does not need too many
samples. The one I found was using only 20 and most of these are doing this with
less than 50 samples. I quess this depends on the sample frequency.

So, why not let the thing do sampling into a round-robin buffer so that the sampling
and the calculations are asynchronous. Then there is no demand for extremely fast
and sleek code. Then I can toss the assembler. (hopefully).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay. The first thing I always do is the header. Here is the header I came up to:

// -----------------------------------------------------------------------
// Dtmf.h
// Definitions and declarations for DTMF encoder and decoder
// -----------------------------------------------------------------------
#ifndef	Dtmf_h
#define	Dtmf_h

// -----------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------
// The buffer size must be bigger than DTMF_MIN_SAMPLES
#define	DTMF_BUFFER_SIZE	32

// Minimum samples to achieve a reliable result
#define	DTMF_MIN_SAMPLES	20

// The sample rate should be as near as possible to this value
// The value is in samples per second
#define	DTMF_SAMPLE_RATE	3640

// -----------------------------------------------------------------------
// Some global data
// -----------------------------------------------------------------------
extern				uint16_t	DtmfBuffer	[DTMF_BUFFER_SIZE];
extern	volatile	uint8_t		DtmfBufferWp;

// -----------------------------------------------------------------------
// Macro for putting the sample into the DTMF decoder buffer.
// This should be sitting in an ISR to achieve constant sample rate and
// to allow the mathematics run in parallel with sampling.
// Note that the sample is a 16 bit unsigned value directly from the
// ADC. The code assumes that the sample has 10 bit resolution.
// Usage example: DtmfDecoderSample( ADCW );
// -----------------------------------------------------------------------
#define	DtmfDecoderSample(aValue)	\
	DtmfBuffer[DtmfBufferWp] = (aValue); \
	if	( DtmfBufferWp < (DTMF_BUFFER_SIZE-1) ) DtmfBufferWp++

// -----------------------------------------------------------------------
// Delay routine for the decoder. This routine is not implemented
// in the library. It should be implemented in the host application.
// It is used to detect whether or not there are DTMF samples coming
// in into the decoder.
// -----------------------------------------------------------------------
extern	void			DtmfDelay		( uint16_t aMilliseconds );

// -----------------------------------------------------------------------
// Decoder
// The decoder assumes that there is or will be at least DTMF_MIN_SAMPLES
// in the DtmfBuffer. If there are not enough samples the result will
// always be 0 (No DTMF tone).
// The sample buffer will be cleared at the end of the routine to enable
// another sample run.
// The function returns the character representing the detected DTMF
// tone or 0 if no DTMF was detected.
// -----------------------------------------------------------------------
extern	uint8_t			DtmfDecode		( void );

// -----------------------------------------------------------------------
// Encoder
// The encoder itself does not produce any DTMF signals. It sets up
// the encoder environment in a way that when the DtmfEncodeSample is called
// it will return suitable values for A/D conversion.
// The Code parameter is the DTMF code to be presented. If the code is not
// a legal DTMF code the resulting values are all at offset (no output).
// The SampleRate parameter is the sample rate the D/A is going to be
// produced.
// The Offset is the value for zero output - the output will be swinging
// around this value.
// The level is the relative output amplitude. 100 means full 16 bit swing
// and 0 means no output at all.
// -----------------------------------------------------------------------
extern	void			DtmfEncode		( uint8_t aCode,
										  uint16_t aSampleRate,
										  uint16_t aOffset,
										  uint8_t aLevel );

// -----------------------------------------------------------------------
// Encoder Sample
// The function returns the next value for D/A conversion
// -----------------------------------------------------------------------
extern	uint16_t		DtmfEncodeSample	( void );

#endif
// -----------------------------------------------------------------------
// EOF: Dtmf.h
// -----------------------------------------------------------------------

I hope this "thing" when ready will be of some use for this community.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm surprised no one has mentioned to do a Google search on "goertzel dtmf"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dbc wrote:
I'm surprised no one has mentioned to do a Google search on "goertzel dtmf"

I am not.

ArnoldB wrote:
I didn't check the provided references if this was already mentioned somewhere http://en.wikipedia.org/wiki/Goe...

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well - here is the result of a tedious asm->C conversion.
Next step will be to make a board to test this with.

Attachment(s):