// Direct LCD drive test by Joonas Pihlajamaa, joonas.pihlajamaa@iki.fi
// Released to public domain.

#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 12000000UL // 12 MHz

#define SEG_PINS 7 // PB0-PB2

int main(void) {
    DDRD = (1<<PD6); // PD6 to common cathode
    DDRB = SEG_PINS; // Port B segment pins as outputs
	
	TCCR1B |= (1 << WGM12); // configure timer 1 for CTC mode
	TIMSK |= (1 << OCIE1A); // enable CTC interrupt for timer 1
    
	OCR1A = 625 * (F_CPU/1000000L); // 200 Hz with prescaler 8

	sei(); //  enable global interrupts

	TCCR1B |= (1 << CS11); // start timer 1 at clk/8

	while(1) {} // loop forever

	return 1;
}

ISR(TIMER1_COMPA_vect) { // 200 Hz timer to generate 100 Hz square wave
    static uint8_t cathode = 0, segments = 0, counter = 0;
    
    PORTD ^= (1<<PD6); // toggle cathode voltage
    cathode = !cathode; // toggle cathode indicator
    
    if(cathode == 0) { // cathode at 0V - high bits visible
        // segment bit LO/HI -> pin LO/HI
        PORTB = (segments & SEG_PINS) | (PORTB & ~SEG_PINS);
    } else {
        // segment bit LO/HI -> pin HI/LO
        PORTB = (~segments & SEG_PINS) | (PORTB & ~SEG_PINS);
    }
    
    counter++;
    
    if(counter >= 200) {
        counter = 0;
        segments++;
    }
}
