CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Goertzel troubles

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
iw2nzm



Joined: 23 Feb 2007
Posts: 55

View user's profile Send private message

Goertzel troubles
PostPosted: Sat Apr 21, 2007 9:29 am     Reply with quote

Hello,

I wrote a simple code to detect DTMF tone using the modified Goertzel algorithm. Here is the code:

Code:

#include <12F683.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES MCLR                     //Master Clear pin enabled
#FUSES PUT                      //Power Up Timer
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled

#use delay(clock=20000000)
#use fast_io(A)

#define OUT      PIN_A0
#define IN      PIN_A1
#define RING   PIN_A2

#define   TIMEOUT      100      // 30 sec
#define   MAX_SAMPLES   200
#define   MAX_DETECT   3
#define   THRS         50

int1  ready = FALSE;
int8  index, i, detect;
int16 tick = 0;
int16 s, s_prev, s_prev2;
int16 pwr[8];
int16 coeff[8] = {1717, 1652, 1582, 1506, 1151, 840, 618};

char analyze();

#int_EXT
void EXT_isr(void) {
   i = index = detect = s = s_prev = s_prev2 = 0;
   ready = FALSE;
   output_drive(RING);
   output_low(RING);
   delay_ms(10);
   output_high(OUT);
   tick = 0;
   disable_interrupts(INT_EXT);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_TIMER1);
}

#int_TIMER1
void  TIMER1_isr(void) {   // 100 ms
   set_timer1(0x0BDB);
   if (++tick >= TIMEOUT) {
      tick = 0;
      output_float(RING);
      output_low(OUT);
      ready = FALSE;
      disable_interrupts(INT_TIMER1);
      enable_interrupts(INT_EXT);
   }
}

#int_TIMER2
void  TIMER2_isr(void) {   // 125 us
   if (++i < MAX_SAMPLES) {
      s = input(IN) + ((coeff[index] * s_prev) >> 10) - s_prev2;
      s_prev2 = s_prev;
      s_prev = s;
   } else {
      disable_interrupts(INT_TIMER2);
      if (index == 7) {
         ready = TRUE;
      } else {
         pwr[index] = s_prev2 * s_prev2 + s_prev * s_prev - (coeff[index] * s_prev2 * s_prev) >> 10;
         index++;
         i = s = s_prev = s_prev2 = 0;
         enable_interrupts(INT_TIMER2);
      }
   }
}

void main() {
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);   
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DIV_BY_1,124,5);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);
   disable_interrupts(INT_TIMER1);
   disable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   ext_int_edge(L_TO_H);
   setup_oscillator(False);
   output_float(RING);
   output_float(IN);
   output_drive(OUT);
   output_low(OUT);
   
   i = index = detect = s = s_prev = s_prev2 = 0;
   ready = FALSE;
   output_drive(RING);
   output_low(RING);
   delay_ms(10);
   output_high(OUT);
   tick = 0;
   disable_interrupts(INT_EXT);
   enable_interrupts(INT_TIMER2);
//   enable_interrupts(INT_TIMER1);
   
   
   for (;;) {
      if (ready) {
         ready = FALSE;
         if(analyze() == '#') {
            if (++detect > MAX_DETECT) {                  
               output_float(RING);
               output_low(OUT);
               disable_interrupts(INT_TIMER1);
               enable_interrupts(INT_EXT);
            }
            else {
               index = s = s_prev = s_prev2 = 0;
               enable_interrupts(INT_TIMER2);
            }
         }
         else {
            detect = 0;
            index = s = s_prev = s_prev2 = 0;
            enable_interrupts(INT_TIMER2);
         }
      }
   }
}

char analyze() {
   int8 j;
   signed int8 first, second;
   
   first = second = -1;
   for (j = 0; j < 4; j++)
      if (pwr[j] > first && pwr[j] > THRS) first = 0x01 << j;
   for (j = 4; j < 8; j++);
      if (pwr[j] > second && pwr[j] > THRS) second = 0x01 << j;
      
   if (first == -1 || second == -1) return 0;
   
   first += second;
   switch (first) {
      case 17:
         return '1';
      case 33:
         return '2';
      case 65:
         return '3';
      case 18:
         return '4';
      case 34:
         return '5';
      case 66:
         return '6';
      case 20:
         return '7';
      case 36:
         return '8';
      case 68:
         return '9';
      case 40:
         return '0';
      case 24:
         return '*';
      case 72:
         return '#';
      case 129:
         return 'A';
      case 130:
         return 'B';
      case 132:
         return 'C';
      case 136:
         return 'D';
   }
}


It doesn't work... It doesn't detect the '#' even if it sometimes detect any incoming dtmf tone.

Well, I don't hope you can find the error... but I ask you how to debug! I don't know how I can fix errors in this code...

Any suggestion is welcome!

Marco / iw2nzm
Richard Arroyo



Joined: 04 Apr 2006
Posts: 22
Location: Sebastopol, CA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sun Apr 22, 2007 2:25 am     Reply with quote

Hello,

I am too tired to go through all of your errors
but hopefully this will help you for now.


First, it appears you have forgotten one of the eight coefficients.


Your array only lists 7: (int16 coeff[8] = {1717, 1652, 1582, 1506, 1151, 840, 618};)

I belive CCS C defaults to unsigned integers. You did not specify the type therefor
you are using unsigned integers which is disastrous.



How did you calculate your coefficients?
1024? * (2 * Cos(2 * pi * (F / FS)))?

This algorithm is quite sensitive to truncation.
Scaling down will lead to truncation errors and
no scaling will cause overflow depending on the data type and n samples
so you must compromise between the two.
I think your program suffers from truncation errors resulting
in incorrect filter response.



Using a 1bit waveform as the input signal will
work but result in poor SNR and harmonic excitation.
With 1 bit the SINAD is only 7.78.

Do you have filtering and biasing present on
pin PIN_A1?

Keep in mind when using signed 16 bit integers
the product of two numbers greater than the sqrt(32767)
will cause an overflow. Also, 16 bit multiplies will take 48us @5mips
on this chip due to no hardware multiplier. It appears you're still
ok time wise.

I'm nodding off ... time to sleep.

-Richard
_________________
RAA
iw2nzm



Joined: 23 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Sun Apr 22, 2007 2:40 am     Reply with quote

Richard Arroyo wrote:
Hello,

I am too tired to go through all of your errors
but hopefully this will help you for now.


I guess I was too tired too when I wrote that! Confused

Thank you for your detailed answer. Now I go to fix those errors.

The coefficients was calculated in this way:

k = N * fi/fs

k, nearest integer
N, filter lenght
fs, sampling frequency
fi, input frequency

coeff = 2 * cos(2pik/N)

Then I use 1024 times coeff in order to manage integers instead floats.

I know the 1-bit AD is very poor, but I read it's possible to achieve quite good result even with small PICs.

Ok, I go to test again.

Thank you
Marco / iw2nzm
iw2nzm



Joined: 23 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Sun Apr 22, 2007 2:44 am     Reply with quote

Addendum

I used this schematic:
http://www.geocities.com/constantinescuradu/content/dtmfrem/dtmf_trafo_300bw.png


Marco / iw2nzm
subi



Joined: 29 Aug 2010
Posts: 24

View user's profile Send private message

Goertzel algorythm
PostPosted: Mon Jan 02, 2012 8:41 am     Reply with quote

Dear programmers,

I would like to learn the goertzel algorythm in CCS with ADC to tone detect (697 - 1633Hz). But I have not found any good program and circuit about it. So if you can help me please do it.

Thank you for your help.

Sorry for my English.
Best regards,
Subi
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jan 02, 2012 9:24 am     Reply with quote

you might try Google 'dtmf decoder PIC' ther are 1,000s of hits. First one is a complete project, quite detailed, and up to you to convert to CCS C or just use as inline asm....

Honestly easier to use dtmf chip and use a few I/O pins unless your PIC has big memory space.
subi



Joined: 29 Aug 2010
Posts: 24

View user's profile Send private message

PostPosted: Mon Jan 02, 2012 10:26 am     Reply with quote

temtronic wrote:
you might try Google 'dtmf decoder PIC' ther are 1,000s of hits. First one is a complete project, quite detailed, and up to you to convert to CCS C or just use as inline asm....

Honestly easier to use dtmf chip and use a few I/O pins unless your PIC has big memory space.


Dear temptronic,
Thank you for your answer and your advise. But I would like to say that I have looked for Goertzel in the net to use Google for about one mounth. But as I wrote I would like to learn more about Goertzel and I am a hobbist and a beginner. So I tried to write over the other code to CCS C. It was unsuccessful. Therefore I thought to ask help from more humbler programmers. But I have not been a tax anybody.

Sorry for my trouble.
Best regards,
Subi from Hungary
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Jan 02, 2012 10:38 am     Reply with quote

Is this a STUDENT project?

Hobby effort?

Meant to be part of commercial product?

The Goertzel method is a cool demonstration -
but is SO processor intensive - there is not much else the pic can do Except perform a pretty low quality job of detection.

If you are creating a product - you should be aware that there are FAR better ways to do this with an external chip OPTIMIZED for the DTMF detection task. And I already know from experience that a shared 3.57954 mhz xtal can do a fine job at 9600 baud too.



Very Happy Very Happy Arrow
subi



Joined: 29 Aug 2010
Posts: 24

View user's profile Send private message

PostPosted: Mon Jan 02, 2012 12:25 pm     Reply with quote

Hi asmboy,

It is a hobby project for me. I do not want to use external IC only softver. I have some good pics for example 18F45K20 or 18F46K80 and I would like to use them. So I have enough memory. If you can halp me I will able to be glad.

Subi
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group