/* Jesper Hansen 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.0 2001-02-12 jesper PIN assignements on the 2323 PB0 High LED PB1 Input pin PB2 Low Led */ #include #include #define F_CPU 11059200 // CPU clock frequency #define PRESCALER 64 // CPU prescaler value #define BASE_FREQUENCY (F_CPU/PRESCALER) // counter frequency #define TUNING_FORK_A 440.0 // "base" A #define NOTE_DIFF 1.05946309436 // the 12'th root of 2 #define E_STRING 164.81 // top string (1) #define A_STRING 220.00 #define D_STRING 293.66 #define G_STRING 391.99 #define B_STRING 493.88 #define EH_STRING 659.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= Center_Count[i]) // if count >= this string count cbi(PORTB,2); // light "Too Low" LED } } }