/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 04.02.2015
Author  : NeVaDa
Company :
Comments:


Chip type               : ATmega328
Program type            : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <mega328.h>
#include <delay.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#define F_CPU  16000000
#define IR_PORT PORTB
 #define IR_PIN PINB
 #define IR_DDR DDRB
 #define IR_BV   1  //_BV(1)
#define IR_OCR OCR1A
#define IR_TCCRnA TCCR1A
#define IR_TCCRnB TCCR1B
#define IR_TCNTn TCNT1
#define IR_TIFRn TIFR1
#define IR_TIMSKn TIMSK1
#define IR_TOIEn TOIE1
#define IR_ICRn ICR1
#define IR_OCRn OCR1A
#define IR_COMn0 COM1A0
#define IR_COMn1 COM1A1
#define PRONTO_IR_SOURCE 0 // Pronto code byte 0
#define PRONTO_FREQ_CODE 1 // Pronto code byte 1
#define PRONTO_SEQUENCE1_LENGTH 2 // Pronto code byte 2
#define PRONTO_SEQUENCE2_LENGTH 3 // Pronto code byte 3
#define PRONTO_CODE_START 4 // Pronto code byte 4
static const uint16_t *ir_code = NULL;
static uint16_t ir_cycle_count = 0;
static uint32_t ir_total_cycle_count = 0;
static uint8_t ir_seq_index = 0;
static uint8_t ir_led_state = 0;
const uint16_t inputLength = 511;

uint16_t input[]={
 0x00, 0x6C, 0x22, 0x2, 0x15B, 0xAD, 0x16, 0x16,
 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x41,
 0x16, 0x41, 0x16, 0x41, 0x16, 0x41, 0x16, 0x41,
 0x16, 0x41, 0x16, 0x16, 0x16, 0x41, 0x16, 0x16,
 0x16, 0x41, 0x16, 0x41, 0x16, 0x16, 0x16, 0x16,
 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x41,
 0x16, 0x16, 0x16, 0x16, 0x16, 0x41, 0x16, 0x41,
 0x16, 0x41, 0x16, 0x41, 0x16, 0x41, 0x16, 0x622,
 0x15B, 0x57, 0x16, 0xE6C
 };

#define TX_DEL  delay_ms(100)  //задержка ответа
#define ERROR PORTC.0
#define OK    PORTC.1
flash unsigned char numm[58]={   //преобразование ANSI в числа
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9} ;

unsigned char t_rx=0;

#define ADRESSIR1  'S'   // "S"  адрес устройства
#define ADRESSIR2  'I'   // "I"
#define ADRESSIR3  'R'   // "R"

#define ADRESTMP1  'T'   // "T"  адрес устройства
#define ADRESTMP2  'M'   // "M"
#define ADRESTMP3  'P'   // "P"

#define ADRESHUD1  'H'   // "H"  адрес устройства
#define ADRESHUD2  'U'   // "U"
#define ADRESHUD3  'D'   // "D"

//usart

volatile unsigned char usart_ready=0;  //флаг непрочитаных данных
volatile unsigned int trx = 0;
volatile bit usart_read=0;
volatile unsigned char etap=0,com=0; //  приём, этап проверки, команда

#define SIZE_BIT 512
#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE0 512
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow0;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
    if ( data != '.' && data != '\r' && data != '\n' && rx_wr_index0 < inputLength-1)
   {
   rx_buffer0[rx_wr_index0++]=data;
   }
   else
   {
       rx_buffer0[rx_wr_index0]='\0';
      trx=0;
      t_rx=0; //останавливаем таймер
      rx_counter0=SIZE_BIT;      //уравниваем ко-во бит
        rx_wr_index0=0; //обнулили индекс входного буфера
        rx_counter0=0;    //обнулили счётчик после считывания
        usart_ready =1;
         etap=0;
         com=0;
   }
#if RX_BUFFER_SIZE0 == 256
   // special case for receiver buffer size=256
   if (++rx_counter0 == 0)
      {
#else
   if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
   if (++rx_counter0 == RX_BUFFER_SIZE0)
      {
      rx_counter0=0;
#endif
      rx_buffer_overflow0=1;
      }
      t_rx=1;
   }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

void ir_on()
 {
 IR_TCCRnA |= (1<<IR_COMn1) + (1<<IR_COMn0);
 ir_led_state = 1;
 }

 void ir_off()
 {
 IR_TCCRnA &= ((~(1<<IR_COMn1)) & (~(1<<IR_COMn0)) );
 ir_led_state = 0;
 }

void ir_toggle()
 {
  if (ir_led_state)
  { ir_off();  }
   else
  { ir_on(); }
 }

void ir_start(uint16_t *code)
{
 uint16_t top=0;
 ir_code = code;
  IR_PORT &= ~IR_BV; // Turn output off (atmega328 only)
 //digitalWrite(9,LOW); // Turn output off
  IR_DDR |= IR_BV; // Set it as output (atmega328 only)
 // pinMode(9,OUTPUT); // Set it as output
 IR_TCCRnA = 0x00; // Reset the pwm
 IR_TCCRnB = 0x00;
 //printf_P(PSTR("FREQ CODE: %hd\r\n"), code[PRONTO_FREQ_CODE]);
   top = ( (F_CPU/1000000.0) * code[PRONTO_FREQ_CODE] * 0.241246 ) - 1;
 //printf_P(PSTR("top: %hu\n\r"), top);
 //IR_ICRn = top;
 ICR1H  = top>>8;ICR1L=top&0xff;
 //IR_OCRn = top >> 1;
  OCR1AH = (top>>1)>>8;OCR1AL = (top>>1)&0xff;
 IR_TCCRnA = (1<<WGM11);
 IR_TCCRnB = (1<<WGM13) | (1<<WGM12);
 // IR_TCNTn = 0x0000;
 TCNT1L=0x00;TCNT1H=0x00;
 IR_TIFRn = 0x00;
 IR_TIMSKn = 1 << IR_TOIEn;
 ir_seq_index = PRONTO_CODE_START;
 ir_cycle_count = 0;
 ir_on();
 IR_TCCRnB |= (1<<CS10);
}

#define TOTAL_CYCLES 80000 // Turns off after this number of
// cycles. About 2 seconds
// FIXME: Turn off after having sent
// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
 uint16_t sequenceIndexEnd;
 uint16_t repeatSequenceIndexStart;
 ir_total_cycle_count++;
 ir_cycle_count++;
 if (ir_cycle_count== ir_code[ir_seq_index])
 {
   ir_toggle();
  ir_cycle_count = 0;
  ir_seq_index++;
  sequenceIndexEnd = PRONTO_CODE_START+(ir_code[PRONTO_SEQUENCE1_LENGTH]<<1)+(ir_code[PRONTO_SEQUENCE2_LENGTH]<<1);
  repeatSequenceIndexStart = PRONTO_CODE_START +(ir_code[PRONTO_SEQUENCE1_LENGTH]<<1);
  if (ir_seq_index >= sequenceIndexEnd )
  {
    ir_seq_index = repeatSequenceIndexStart;
    if(ir_total_cycle_count>TOTAL_CYCLES)
    {
     ir_off();
     TCCR1B &= ~(1<<CS10);
     }

   }

 }

}

void ir_stop()
 {
  IR_TCCRnA = 0x00; // Reset the pwm
  IR_TCCRnB = 0x00;
 }

 void go_ir()
 {
     uint16_t array[80];
     uint16_t j = 0;
     uint8_t i = 0;
        if ( !strncmp(rx_buffer0, "AVR_SIR", 7) )
          {
            char *p = rx_buffer0+4; //указываем начало
             while ( (p = strchr(p,' ')) != NULL ) //ждём пока недойдем до пробела и записываем номер строки
             //теперь нужно склеить  от начла до конца и  записать в массив

              array[j++] = atol(p);
             // array[j++] = strtol(p, &p, 16);
             //array[j++] = atol(p);

             ir_start(array);  //посылаем склееные части
          /*
             putsf("SENT ");
            for ( i = 0; i < j; i++ )
            {
             putsf("0x");
             printf ("%c",array[i]);
             putsf(" ");
             }
            */


    }
     ir_stop();
 }

 void usart_rx_tx() //функция приёма-передачи данных
 {

    if(t_rx==1)
   {
   delay_ms(1);
   trx++;
   }
   else
   {
    trx=0;
   }
     if(trx>=200&&rx_counter0<SIZE_BIT&&usart_ready==0) //если после поступления первого символа прошло
     {  //более 200 мс
      trx=0;
      t_rx=0; //останавливаем таймер
      rx_counter0=SIZE_BIT;      //уравниваем ко-во бит
     }

     if(usart_ready==0)  //если данные небыли приняты или прочитаны
     {
         if(rx_counter0>=SIZE_BIT)  //данные пришли и буфер заполнен более или равно чем SIZE_BIT
       {
        rx_wr_index0=0; //обнулили индекс входного буфера
        rx_counter0=0;    //обнулили счётчик после считывания
        usart_ready =1;
         etap=0;
         com=0;
       }
     }
     if(usart_ready==1) //если данные приняты, но непроверены
     {
       if(etap==0)
        {
         if(rx_buffer0[4]==ADRESSIR1&&rx_buffer0[5]==ADRESSIR2&&rx_buffer0[6]==ADRESSIR3){com=1;etap=1;OK=1;ERROR=0;}
         if(rx_buffer0[4]==ADRESTMP1&&rx_buffer0[5]==ADRESTMP2&&rx_buffer0[6]==ADRESTMP3){com=2;etap=1;OK=1;ERROR=0;}
         if(rx_buffer0[4]==ADRESHUD1&&rx_buffer0[5]==ADRESHUD2&&rx_buffer0[6]==ADRESHUD3){com=3;etap=1;OK=1;ERROR=0;}
         if(com==0){etap=3;OK=0;ERROR=1; }
        }

       if(etap==1)
       {
         if(com==1)
         {
           go_ir();
           etap=3;
         }
         if(com==2)
         {

         }
         if(com==3)
         {

         }

       }

       if(etap==3) //очистка буферов и переменных
       {
        unsigned int rx=0;
        for(rx=0;rx<=RX_BUFFER_SIZE0;rx++)
        {
        rx_buffer0[rx]=0;     //обнуляем приёмный буфер
        }
        usart_ready=0; //обнулили переменные
        t_rx=0; //остановили таймер
        trx=0;
       }

     }

 }

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out
// State6=T State5=T State4=T State3=T State2=T State1=0 State0=0
PORTC=0x00;
DDRC=0x03;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x01;

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x67;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Global enable interrupts
#asm("sei")
       PORTD.7=1;
while (1)
      {
        usart_rx_tx();
            if(PIND.7==0)
         {

           while(!PIND.7){;};
           ir_start(input);
            delay_ms(50);
           ir_stop();
         }
      }


}
