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

volatile uint8_t line_counter ;
volatile uint8_t segment_counter ;

#define WRITE_DISPLAY(c) while(!(UCSR0A & _BV(UDRE0)));\
                         UDR0 = c;
unsigned char image_bits[] = {
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x80, 0x07, 0x80, 0x07, 0x80, 0x01, 0x40, 0x08, 0x40, 0x08, 0x80,
   0x01, 0x40, 0x10, 0x20, 0x08, 0x80, 0x01, 0x60, 0x20, 0x10, 0x18, 0x80,
   0x01, 0x20, 0x20, 0x10, 0x10, 0x80, 0x01, 0x20, 0x40, 0x08, 0x10, 0x80,
   0x01, 0x20, 0x40, 0x08, 0x10, 0x80, 0x01, 0x20, 0x40, 0x08, 0x10, 0x80,
   0x01, 0x20, 0x40, 0x08, 0x10, 0x80, 0x01, 0x20, 0x40, 0x08, 0x10, 0x80,
   0x01, 0x20, 0x40, 0x08, 0x10, 0x80, 0x01, 0x20, 0xc0, 0x0c, 0x10, 0x80,
   0x01, 0x20, 0x80, 0x04, 0x10, 0x80, 0x01, 0x60, 0x80, 0x04, 0x18, 0x80,
   0x01, 0x40, 0x80, 0x04, 0x08, 0x80, 0x01, 0x40, 0x80, 0x04, 0x08, 0x80,
   0x01, 0x40, 0x80, 0x04, 0x08, 0x80, 0x01, 0x80, 0x80, 0x04, 0x04, 0x80,
   0x01, 0x80, 0x80, 0x07, 0x04, 0x80, 0x01, 0x80, 0x00, 0x00, 0x04, 0x80,
   0x01, 0x00, 0x01, 0x00, 0x02, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x0c, 0x80,
   0x01, 0x20, 0x00, 0x00, 0x10, 0x80, 0x01, 0x10, 0x00, 0x00, 0x20, 0x80,
   0x01, 0x08, 0x00, 0x00, 0x40, 0x80, 0x01, 0x0c, 0x00, 0x00, 0xc0, 0x80,
   0x01, 0x04, 0x00, 0x00, 0x80, 0x80, 0x01, 0x02, 0x00, 0x00, 0x00, 0x81,
   0x01, 0x02, 0x00, 0x00, 0x00, 0x81, 0x01, 0x02, 0x00, 0x00, 0x00, 0x81,
   0x01, 0x01, 0x00, 0x00, 0x00, 0x82, 0x01, 0x01, 0x00, 0x00, 0x00, 0x82,
   0x01, 0x01, 0x00, 0x00, 0x00, 0x82, 0x01, 0x01, 0x00, 0x00, 0x00, 0x82,
   0x01, 0x01, 0x03, 0x00, 0x03, 0x82, 0x01, 0x02, 0x03, 0x00, 0x03, 0x81,
   0x01, 0x02, 0x00, 0x00, 0x00, 0x81, 0x01, 0x02, 0x00, 0x00, 0x00, 0x81,
   0x01, 0x04, 0x00, 0x00, 0x80, 0x80, 0x01, 0x04, 0x00, 0x00, 0x80, 0x80,
   0x01, 0x08, 0x80, 0x04, 0x40, 0x80, 0x01, 0x10, 0x00, 0x03, 0x20, 0x80,
   0x01, 0x60, 0x80, 0x04, 0x18, 0x80, 0x01, 0x80, 0x01, 0x00, 0x06, 0x80,
   0x01, 0x00, 0x06, 0x80, 0x01, 0x80, 0x01, 0x00, 0xf8, 0x7f, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80 };


int main(void)
{
	// configure UART for SPI. 
	UCSR0C = _BV(UMSEL01) | _BV(UMSEL00);
	// set baudrate to Fosc/4
	UBRR0H = 0;
	UBRR0L = 1;
	// only enable tx, no rx.
	UCSR0B = _BV(TXEN0);
	// Use timer for selecting lines
	TCCR0A = _BV(WGM01);
	// run timer on Fosc/256 => 62.5us/count
	TCCR0B = _BV(CS02);
	// about 4ms/line, 60ms for entire display
	OCR0A = 15;		
	TIMSK0 = _BV(OCIE0A);	

	uint8_t i,j;
	uint8_t line_counter_prev;

	for(i=16; i<34; i++) {
		WRITE_DISPLAY(0x02);
		WRITE_DISPLAY(i);
		WRITE_DISPLAY(0x00);
		for (j=0; j<6; j++){	
			// 7 time 0xff is on, 6 times 0xef is on?
			// 6 time 0xff is off, 7 or 6 teime 0xfe is off
			WRITE_DISPLAY(0xef);
		}
	};
	line_counter = 0;
	sei();

	// this code unlocks the shift registers
	WRITE_DISPLAY(0x00);
	WRITE_DISPLAY(0x02);
	WRITE_DISPLAY(0x0f);
	WRITE_DISPLAY(0x00);
	
	sei();
	while (1) {
		// put something usefull in de vmem
		WRITE_DISPLAY(0x00);
	}
	return 666;
}

ISR(TIMER0_COMPA_vect) {
	// write out 1/4 of the a line, and turn the line on once every four ints
	uint8_t *vp = (uint8_t*) image_bits;
	WRITE_DISPLAY(0x00);
	vp += (6*line_counter);
	WRITE_DISPLAY(0x00);
	vp += (6*16*segment_counter);
	WRITE_DISPLAY(0x00);
	uint8_t i,j;
	WRITE_DISPLAY(0x00);
	for (i =0; i<6;i++) {
		//WRITE_DISPLAY(0x00);
		uint8_t b = vp[i];
		for (j = 0; j< 8; j++) {
			WRITE_DISPLAY(0x03);
			WRITE_DISPLAY(b & 0x01);
			//WRITE_DISPLAY(0x01);
			b >>= 1;
		}
		//WRITE_DISPLAY(0x00);
	}
	WRITE_DISPLAY(0x00);

	if (segment_counter == 4) {
		WRITE_DISPLAY(0x00);
		WRITE_DISPLAY(0x02);
		WRITE_DISPLAY(0xa0 | line_counter);
		WRITE_DISPLAY(0x80);
		segment_counter = 0;
		if (line_counter == 0x0f) {
			//WRITE_DISPLAY(0x00);
			line_counter = 0;
		} else {
			line_counter += 1;
			//WRITE_DISPLAY(0x00);
		}
	} else {
		segment_counter++;
		//WRITE_DISPLAY(0x00);
	}
	return;
}

