/****************************************************************** Includes */
#include <stdio.h>          // Standard Input/Output
#include <avr/io.h>         // AVR device-specific IO definitions
#include <compat/deprecated.h>  // Use sbi(), cbi() function
#include <avr/interrupt.h>	// Interrupt Service routine

#define F_CPU 16000000UL     // CPU clock frequency (in Hertz)    
#include <util/delay.h>     // util_delay

#define RX_BUFSIZE 80       // Buffer RX

/******************************************************* Prototype functions */
static int uart_putchar(char c, FILE *stream);
static int uart_getchar(FILE *stream);
static FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
void Init_Serial(unsigned int baudrate);

void W1(void);
void W2(void);
unsigned int ADCx[8];
unsigned int ADCxo[8];
unsigned int ADCxo1[8];
unsigned int ADCxo2[8];
unsigned int ADCxo3[8];


unsigned int chick=0;
/************************************************************* USART putchar */
static int uart_putchar(char c, FILE *stream)
{   
    loop_until_bit_is_set(UCSRA, UDRE);
    UDR = c;

    return 0;
}

/************************************************************* USART getchar */
static int uart_getchar(FILE *stream) {
  
    uint8_t c;
	        
        loop_until_bit_is_set(UCSRA, RXC);
	        
        if (UCSRA & _BV(FE))    return _FDEV_EOF;
//        if (UCSRA & _BV(DOR))   return _FDEV_ERR;

        c = UDR;



    return c;
}

/*********************************************************** Initialize UART */
static void USART_Init(unsigned int baud)
{
	// Set baud rate
	UBRRH = (unsigned char) (baud>>8);
	UBRRL = (unsigned char) baud;
    
	UCSRA = (1<<U2X);
	// Enable receiver and tramsmitter
	UCSRB = (1<<RXEN) | (1<<TXEN);

	// Set frame format: 8data, NoneParity, 1stop bit
	UCSRC = (1<<URSEL)|(3<<UCSZ0);

    // Set address uart_str to stdout/stdin
    stdout = stdin = &uart_str;
}

/************************************************************ Main Functions */
/***************************************************************** delay_ms */

void delay_ms(uint16_t i)
{
    for (;i > 0; i--)
        _delay_ms(1);
}

/************************************************************* USART PWM */
void init_PWM1(void)
{
	// PORT PA0,PA1 PA2 Output
    DDRC = (1<<DDC5)|(1<<DDC4)|(1<<DDC3); 
	// PORT PD5(OC1A),PD4(OC1B) Output PWM
    DDRB = (1<<DDB1)|(1<<DDB2);             

	// Clear up-counting Set downcounting
    TCCR1A = (1<<COM1A1)|(0<<COM1A0);   
	TCCR1A |= (1<<COM1B1)|(0<<COM1B0);

	// Mode 8: PWM,Phase and Frequency Corect (TOP = ICR1A)
    TCCR1B  = (1<<WGM13)|(0<<WGM12);    
    TCCR1A |= (0<<WGM11)|(0<<WGM10);  
	
	// clk_IO/1 (From prescaler)	    
    TCCR1B |= (0<<CS12)|(1<<CS11)|(0<<CS10); 

	ICR1 = 20000;		// Freq = 1000 Hz(TOP = ICR1) //1000=100%
    
    // Duty Cycle 50%
    OCR1A = 1500;      	// Output Compare Register 1 A //500 = 50%
    OCR1B = 1500;       	// Output Compare Register 1 B //500 = 50%

    TCNT1 = 0;          	// Clear Timer
  
  	// T/C1 Output Compare A/B Match and Timer Overflow interrupt Enable
 //   TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);    

 //   sei();                  // Set I-bit global interrupt enable
	
}

int ADC_init(void)
{
	DDRC = 0x00;

	// AVCC with external capacitor at AREF pin
	ADMUX = (0<<REFS1)|(1<<REFS0);

	// ADC Enable & Auto Trigger Disable
	ADCSRA = (1<<ADEN);
	ADCSRA |= (1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);	// XTAL/8

	ADCSRA |= (1<<ADSC);				// ADC Start Conversion
	while (!(ADCSRA &(1<<ADIF)));    // Wait Coversion completes

	return ADCW;
}

void ADC_read(void)
{

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x00;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[0] = ADCW;                     // Read ADC

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x01;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[1] = ADCW;                     // Read ADC

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x02;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[2] = ADCW;                     // Read ADC

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x03;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[3] = ADCW;                     // Read ADC

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x04;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[4] = ADCW;                     // Read ADC

		ADMUX = (0<<REFS1)|(1<<REFS0)|0x05;
		ADCSRA |= (1<<ADSC);				// ADC Start Conversion
		while (!(ADCSRA &(1<<ADIF)))    // Wait Coversion completes
         			 ;
		ADCx[5] = ADCW;                     // Read ADC
}


void timer_init(void){
	TCCR0 = (0<<CS02)|(1<<CS01)|(0<<CS00);   // clk_IO/8 (From prescaler)
	TIMSK = (1<<TOIE0);// T/C0 Overflow interrupt Enable
	SREG  = 0x80;                           // Set I-bit Global interrupt   
}

int main(void)
{   
//	int i;
    USART_Init(16);     // baudrate to 115,200 bps using a 16MHz crystal

	init_PWM1();

	 timer_init();

	//port PD6,PD7 Input
	DDRD |= (0<<DDD6)|(0<<DDD7);

	ADC_init();         

    printf("\fHello KID!!! \r\n");

	while (1) {
/*
		for(i=0;i<6;i++){
			ADCxo[i]=	ADCx[i];
		}

		ADC_read();

		for(i=0;i<6;i++){
			ADCx[i]=	(ADCx[i]+ADCxo[i]*5)/6;
		}

		for(i=0;i<6;i++){
			printf("%4d = %4d",i,ADCx[i]);
		}
		printf("\r\n");

		delay_ms(1);
*/ 
    }

}



/*********************************************** External Interrupt Request 0 */

void W1(void)
{
	OCR1A = 1300;      	// Output Compare Register 1 A //500 = 50%
    OCR1B = 1700;       	// Output Compare Register 1 B //500 = 50%
	delay_ms(1000);

	OCR1A = 1700;      	// Output Compare Register 1 A //500 = 50%
    OCR1B = 1300;       	// Output Compare Register 1 B //500 = 50%
	delay_ms(1000);
}

void W2(void)
{
	OCR1A = 1400;      	// Output Compare Register 1 A //500 = 50%
    OCR1B = 1600;      	// Output Compare Register 1 B //500 = 50%
	delay_ms(300);

	OCR1A = 1600;      	// Output Compare Register 1 A //500 = 50%
    OCR1B = 1400;       	// Output Compare Register 1 B //500 = 50%
	delay_ms(300);
}
/**************************************************** T/C1 Overflow Interrupt */

ISR (TIMER0_OVF_vect)
{   
		int i;

		chick ++;
		for(i=0;i<6;i++){
			ADCxo3[i]=	ADCxo2[i];
			ADCxo2[i]=	ADCxo1[i];
			ADCxo1[i]=	ADCx[i];
			ADCxo[i]=	ADCx[i];
		}

		ADC_read();

		for(i=0;i<6;i++){
			ADCx[i]=	(ADCx[i]+ADCxo[i]*4+ADCxo1[i]+ADCxo2[i]+ADCxo3[i]);
			ADCx[i] = ADCx[i] /8;
		}

//------------------------------------------------------------------------------
		if(chick >=50){
			TIMSK = (0<<TOIE0);// T/C0 Overflow interrupt Disable

			chick = 0;
			for(i=0;i<6;i++){
				printf("%4d = %4d",i,ADCx[i]);
			}
			printf("\r\n");
//-------------------------------------------------------------------------------
			TIMSK = (1<<TOIE0);// T/C0 Overflow interrupt Enable
			SREG  = 0x80;           // Set I-bit Global interrupt   
		}

	TCNT0 = 256-40;
}

