/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.8 Evaluation
Automatic Program Generator
© Copyright 1998-2012 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : Mouse test
Version : 1.0
Date    : 16.07.2012
Author  : Gleb
Company : Gleb
Comments: 


Chip type               : ATmega32A
Program type            : Application
AVR Core Clock frequency: 14,745000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <mega32a.h>

#include <delay.h>

// Standard Input/Output functions
#include <stdio.h>

// Alphanumeric LCD functions
#include <alcd.h>


// Declare your global variables here

#define BUFFER_SIZE 8

char buffer[BUFFER_SIZE];
char buf_counter=0;
char buf_index=0;
char buf_end=0;

char getByte(void)
{
    char b;
    while (buf_counter==0);
    b=buffer[buf_index];
    if(++buf_index == BUFFER_SIZE) buf_index=0;
    #asm("cli")
    if(--buf_counter==0)
    {
        buf_index=0;
        buf_end=0;
    }
    return b;
    #asm("sei")
}

void putByte(char b)
{
    if(buf_counter==0) // empty
    {
        buf_index=0;
        buf_end=0;
    }
    else
    {
        if(buf_counter == BUFFER_SIZE) // overflow
        {
           printf("Buf. ovf\r\n");
           while(buf_counter!=0)
            printf("%d\r\n",getByte());
        }
        else
        {
            if(++buf_end==BUFFER_SIZE) buf_end=0;
        }
    }
    buffer[buf_end]=b;
    #asm("cli")
    buf_counter++;
    #asm("sei")
}

#define STATE_WAIT 0
#define STATE_STARTED 1
#define STATE_PARITY 2
#define STATE_STOP 3
#define STATE_ACK 4

#define MODE_RECEIVE 0
#define MODE_TRANSMIT 1

#define MOUSE_RESET 0xFF;
#define MOUSE_STREAM_MODE 0xEA;
#define MOUSE_ENABLE_DATA_REPORTING 0xF4


 
char bitcounter=0;
char state=0;
char parity=0;
char data=0;
char mode=MODE_RECEIVE;

void timer_enable()
{
    TCCR0=0x05;
    TCNT0=0x00;
    OCR0=0x2B;
    //TIMSK=0x02;
}

void timer_disable()
{
    TCCR0=0x00;
    TCNT0=0x00;
    OCR0=0x2B;
    //TIMSK=0x00;
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    switch(mode)
    {
        case MODE_RECEIVE:
            switch(state)
            {
                case STATE_WAIT:
                    if(PIND.4==0)
                    {
                        data=0;
                        bitcounter=0;
                        parity=0;
                        state++;
                        timer_enable();
                    }
                    else
                        printf("Start error!\r\n");
                break;
                case STATE_STARTED:
                    data=data<<1;
                    if(PIND.4==1) data|=1;
                    if(++bitcounter==8) state++;
                    break;
                case STATE_PARITY:
                    parity=PIND.4;
                    state++;
                break;
                case STATE_STOP:
                    if(PIND.4==1)
                    {
                        putByte(data);
                        timer_disable();
                        bitcounter=0;
                        data=0;
                        state=STATE_WAIT;
                        parity=0;
                    }
                    else
                        printf("STOP error!\r\n");
                break;
                default:
                    printf("Unknown error!\r\n");
                break; 
            }       
            break;
        case MODE_TRANSMIT:
            switch(state)
            {
                case STATE_STARTED:
                    putchar('1');
                    PORTD.4=(data && (1<<8-bitcounter-1))?1:0;
                    if(++bitcounter==8) state++;
                    break;
                case STATE_PARITY:
                    putchar('2');
                    PORTD.4=parity;
                    state++;
                    break;
                case STATE_STOP:
                    putchar('3');
                    PORTD.4=1;
                    PORTD=0x18;
                    DDRD=0x00;
                    MCUCR=0x08; // falling edge
                    state++;
                    break;
                case STATE_ACK:
                    putchar('4');
                    if(PIND.4==0)
                    {
                       printf("OK\r\n"); 
                    }
                    else
                    {
                        printf("Error\r\n");
                    }
                    state=0;
                    mode=MODE_RECEIVE;
                    break;
                default:
                    printf("Error\r\n");
                    break;      
            }
            break;
    }
}
void sendByte(char b)
{
    printf("Sending...\r\n");
    #asm("cli")
    PORTD=0x18; // pin 3, 4 out + pull up
    DDRD=0x18;
    PORTD.3=0;
    delay_us(120);
    PORTD.3=1;
    PORTD=0x08; // pin 3 - clock in, pin 4 - data out 0
    DDRD=0x10;
    PORTD.4=0;
    data=b;
    state=STATE_STARTED;
    bitcounter=0;
    parity=(data % 2)?0:1;
    mode=MODE_TRANSMIT;
    MCUCR=0x0C; // rising edge
    #asm("sei")
}
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
// Place your code here
   timer_disable();
   printf("Timeout error!\r\n");
   //print_data();
}

void init()
{
    // Port D initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=0 State4=T State3=T State2=T State1=T State0=T 
    PORTD=0x18;
    DDRD=0x00;
    // Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 14,399 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
    TCCR0=0x00;
    TCNT0=0x00;
    OCR0=0x2B;
    // External Interrupt(s) initialization
// INT0: Off
// INT1: On
// INT1 Mode: Falling Edge
// INT2: Off   
    GICR|=0x80;
    MCUCR=0x08;
    MCUCSR=0x00;
    GIFR=0x80;

// Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x02;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 57600
    UCSRA=0x00;
    UCSRB=0x08;
    UCSRC=0x06;
    UBRRH=0x00;
    UBRRL=0x0F;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    lcd_init(16);

// Global enable interrupts
    #asm("sei")    
}

void main(void)
{
init();
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("Waiting...");
delay_ms(1000);
printf("Flush\r\n");
while(buf_counter!=0)
{
    printf("0x%X\r\n",getByte());        
}
sendByte(MOUSE_ENABLE_DATA_REPORTING);
while (1);
}
