LED chaser as a guitar/synth tuning reference

Hi all.

I’m wondering if anyone’s come across a tuner like this thing → LED chaser as a frequency reference (guitars and synths) - YouTube

It works by scanning the LEDs one at a time at 1760Hz (high A) and writing the output of the internal analogue comparator to that LED depending on the state - if the input is positive, the LED turns on, and off if it’s negative.

Here’s the code for an ATMega168P:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <stdint.h>
#include <stddef.h>


uint8_t led = 0;

void initialize ()
{
        DDRD = 0x7F;
        DDRB = 1;
        TCCR1B = _BV(WGM12) | _BV(CS10);
        TIMSK1 = _BV(OCIE1A);
        OCR1A = F_CPU/(440*4);
        DIDR1 = _BV(AIN1D);
}

int main ()
{
        initialize ();
        sei ();
        
        while(1);
}

ISR (TIMER1_COMPA_vect)
{
        if (led == 7)
        {
                if (ACSR & _BV(ACO))
                {
                        PORTB &= ~1;
                }
                else
                {
                        PORTB |= 1;
                }
        }
        else
        {
                if (ACSR & _BV(ACO))
                {
                        PORTD &= ~(1<<led);
                }
                else
                {
                        PORTD |= 1<<led;
                }
        }
        led = (led + 1) & 7;
}

The LEDs wire to PORTD 0 through 6, except for the 8th LED which wires to PB0. The signal is applied to through a 100k ohm resistor to AIN1 (PD7 or pin 13). I did the LEDs this way because I managed to break pin 15 off my last ATMega (bah!).

The code above will work for ‘A’ across several octaves. Of course, if a switch is added you can select different frequencies to load into OCR1A, say if you want to try it on a guitar.

Cheers.

1 Like

And here’s the same thing with an LED matrix → LED matrix for synth/guitar tuning - YouTube

With code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <stdint.h>
#include <stddef.h>


volatile uint8_t led = 0;
volatile uint8_t led_sh = 0;
volatile uint8_t led_reg[2][8];

const uint16_t freqs[] = {
        F_CPU/2093, F_CPU/2349, F_CPU/2637, F_CPU/2794, F_CPU/3135,
        F_CPU/3520, F_CPU/3951, F_CPU/4186 };
                        
void LED_send (uint8_t addr, uint8_t data) {
        cli ();
        PORTD &= ~1;

	SPDR = addr;
	while(!(SPSR & _BV(SPIF)));
        
	SPDR = data;
	while(!(SPSR & _BV(SPIF)));
	
        PORTD |= 1;
        sei ();
}

void initialize ()
{
        DDRD = 1;
        DDRB = 0xFF;
        PORTD = 1;        
        
        SPCR = _BV(SPE) | _BV(MSTR);
        
        TCCR1B = _BV(WGM12) | _BV(CS10);
        TIMSK1 = _BV(OCIE1A);
        OCR1A = freqs[5];
        DIDR1 = _BV(AIN1D);
        
        LED_send (11, 7);       // Scan all LEDs
        LED_send (12, 1);       // Enable display driver

}

int main ()
{
        initialize ();
        sei ();
        
        while(1)
        {
                uint8_t i;
                for (i = 0; i < 8; i++)
                {
                        LED_send (i + 1, (led_reg[0][i] & led_reg[1][i]));
                }
        }
}

ISR (TIMER1_COMPA_vect)
{
        led_reg[0][led] = (led_reg[0][led] << 1) | (ACSR & _BV(ACO) ? 1 : 0);
        led_sh = (led_sh + 1) & 7;
        if (led_sh == 0)
        {
                led = (led + 1) & 7;
                led_reg[1][led] = led_reg[0][led];
        }
        
}
2 Likes

Ok, now I want 12 of them!

2 Likes