frequency counter by using microcontroller
hi pjyc...i already check code from Jesper digital guitar tuner...it is for avr...i don't know avr...i want to implement his code algorithm for 8051??
could me out with the code plz..idea behind it...especially of timer count and count_hi??
here's the code
/*
Jesper Hansen <jesperh@telia.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Simple Digital Guitar Tuner
---------------------------
version 1.02001-02-12jesper
PIN assignements on the 2323
PB0High LED
PB1Input pin
PB2Low Led
*/
#include <io.h>
#include <signal.h>
#define F_CPU11059200// CPU clock frequency
#define PRESCALER64// CPU prescaler value
#define BASE_FREQUENCY(F_CPU/PRESCALER)// counter frequency
#define TUNING_FORK_A440.0// "base" A
#define NOTE_DIFF1.05946309436// the 12'th root of 2
#define E_STRING164.81// top string (1)
#define A_STRING220.00
#define D_STRING293.66
#define G_STRING391.99
#define B_STRING493.88
#define EH_STRING659.26// bottom string (6)
// The guitar note span
// # # # # # # # # # #
//EF G A BC D EF G A BC D E
//1 2 3 4 * 5 6
//
unsigned int Center_Count[] =
{
BASE_FREQUENCY/EH_STRING,// High E
BASE_FREQUENCY/B_STRING,// B
BASE_FREQUENCY/G_STRING,// G
BASE_FREQUENCY/D_STRING,// D
BASE_FREQUENCY/A_STRING,// A
BASE_FREQUENCY/E_STRING,// Low E
};
unsigned int Transition_Count[] =
{
BASE_FREQUENCY/(B_STRING+(EH_STRING-B_STRING)/2),// E to B
BASE_FREQUENCY/(G_STRING+(B_STRING-G_STRING)/2),// B to G
BASE_FREQUENCY/(D_STRING+(G_STRING-D_STRING)/2),// G to D
BASE_FREQUENCY/(A_STRING+(D_STRING-A_STRING)/2),// D to A
BASE_FREQUENCY/(E_STRING+(A_STRING-E_STRING)/2),// A to E
};
volatile unsigned char count_hi;// overflow accumulator
//
//timer 0 overflow interrupt
//
SIGNAL(SIG_OVERFLOW0)
{
count_hi++;// increment overflow count
}
//----------------------------------------------------------------------------
// Main Lupe
//----------------------------------------------------------------------------
int main(void)
{
unsigned int i;
unsigned int count;
//------------------------------
// Initialize
//------------------------------
cbi(DDRB, 1);// PB1 is input
cbi(PORTB, 1);// no pullups active
sbi(DDRB, 0);// PB0 is ouput, High LED
sbi(DDRB, 2);// PB2 is ouput, Low LED
outp(0x03,TCCR0);// set prescaler to f/64 (172.8 kHz @ 11.0592 MHz)
sbi(TIMSK,TOIE0);// enable interrupt on timer overflow
asm volatile ("sei");// global interrupt enable
//----------------------------------------------------------------------------
// Let things loose
//----------------------------------------------------------------------------
while (1)// loop forever
{
count = 0;// clear sample count
loop_until_bit_is_set(PINB,1);// wait for something to happen
// got a high edge
// start sampling
outp(0,TCNT0);// clear counter
count_hi = 0;// clear hi count
// sample loop
for (i=0;i<32;i++)
{
while (bit_is_set(PINB,1))// ignore hi->lo edge transitions
if (count_hi > 80)// skip if no edge is seen within
break;// a reasonable time
while (bit_is_clear(PINB,1))// wait for lo->hi edge
if (count_hi > 80)// skip if no edge is seen within
break;// a reasonable time
count += (count_hi << 8) + inp(TCNT0); // get counter value
outp(0,TCNT0);// clear counter
if (count_hi > 80)// skip if counter has accumulated a
break;// too high value
count_hi = 0;// clear hi count
}
// initially turn off both leds
sbi(PORTB,0);
sbi(PORTB,2);
if (count_hi <= 80)// if count is reasonable
{
count = count >> 5;// average accumulated count by dividing with 32
// now we have to find the correct string
// go through transition frequencies
for (i=0;i<sizeof(Transition_Count)/sizeof(Transition_Count[0]);i++)
{
if (count < Transition_Count)// stop if lower than this transition count
break;
}
// i now holds the string index
// check the count for a match, allowing
// 1 extra count "hysteresis" to avoid too
// much LED flickering
if (count-1 <= Center_Count)// if count <= this string count
cbi(PORTB,0);// light "Too High" LED
if (count+1 >= Center_Count)// if count >= this string count
cbi(PORTB,2);// light "Too Low" LED
}
}
}