/******************************************************************************
 * Title    : main
 * File     : main.c
 * Software : AVR-GCC
 * Hardware : AVR ATtiny2313
 *****************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include "gpio.h"
#include "hal.h"

/***************** pov things ****************/
            //  LLLLLLLL
            //  EEEEEEEE
            //  DDDDDDDD
            //  87654321
#define POV__ 0b00000000, \
              0b00000000, \
              0b00000000, \
              0b00000000, \
              0b00000000, \
              0b00000000, \
              0b00000000, \
              0b00000000

#define POV_A 0b01010100, \
              0b00101010, \
              0b00000001, \
              0b00001000, \
              0b00000001, \
              0b00001000, \
              0b00000001, \
              0b00001000, \
              0b01010100, \
              0b00101010

#define POV_B 0b00010100, \
              0b00100010, \
              0b01000001, \
              0b00001000, \
              0b01000001, \
              0b00001000, \
              0b01000001, \
              0b00001000, \
              0b01010101, \
              0b00101010

#define POV_C 0b00000000, \
              0b00100010, \
              0b01000001, \
              0b00000000, \
              0b01000001, \
              0b00000000, \
              0b01000001, \
              0b00000000, \
              0b00010100, \
              0b00101010

#define POV_D 0b00001000, \
              0b00010100, \
              0b00000000, \
              0b00100010, \
              0b01000001, \
              0b00000000, \
              0b01000001, \
              0b00000000, \
              0b01010101, \
              0b00101010

#define POV_E 0b01000001, \
              0b00000000, \
              0b01000001, \
              0b00001000, \
              0b01000001, \
              0b00001000, \
              0b01010101, \
              0b00101010

uint16_t loopCnt = 0;
uint16_t maxCntVal = 0;
uint8_t message[] = { POV__,
                      POV_A,
                      POV__,
                      POV_B,
                      POV__,
                      POV_C,
                      POV__,
                      POV_D,
                      POV__,
                      POV_E
                    };
uint16_t sectors = 64;
uint16_t textColumns = sizeof(message)/sizeof(uint8_t);
uint16_t offset = 0;

/****************** timer 1 ******************/
// at 8MHz -> clock periode 125ns
// timer interval should be 100us
//      100us / 0,125us = 800
//      65536 - 800 = 64736
uint16_t startTimer1 = 64736;

void initTimer0(void)
{
    TCNT1 = startTimer1;

    // compare output mode - normal port operation
    // waveform generation mode - normal
    TCCR1A = 0;
    // input capture noise canceler - off
    // input capture edge select - falling
    // clock select - clk_io / 1 (no prescaler)
    TCCR1B = 1;
    // nothing
    TCCR1C = 0;

    // enable timer1 overflow interrupt
    TIMSK = (1<<TOIE1);
}

// iotn2313.h -> for interrupt vector definitions
ISR(TIMER1_OVF_vect)
{
    static uint16_t actSector = 0;

    TCNT1 = startTimer1;

    // calculate actual sector
    actSector = (((loopCnt % maxCntVal) * sectors) / maxCntVal) + offset;
    if (actSector < textColumns)
    {
	    LED_PORT = message[actSector];
    }
    else if (actSector < (textColumns+sectors))
    {
        LED_PORT = 0;
    }
    else
    {
        LED_PORT = 0;
        offset = 0;
    }

    // increment counter value
	loopCnt++;
}

/******************* int0 ********************/
void initExtInt0(void)
{
    // external interrupt 0 at rising edge
    MCUCR |= (1<<ISC00) | (1<<ISC01);
    // enable external interrupt 0
    GIMSK |= (1<<INT0);
}

ISR(INT0_vect)
{
    maxCntVal = loopCnt;
    loopCnt = 0;

    offset++;
}

/******************* main ********************/
int main (void)
{
	// initialize leds
	DDRB |= 0xff;
	PORTB &= 0;

	// activate light barrier pull up
	PORTD |= (1<<2);

    // initialize all others
    initTimer0();
    initExtInt0();

    // activate global interrupt
    ActivateGINT();

	for(;;)
	{
	}

	return 0;
}

