/*****************************************************
Chip type           : ATtiny2313
Clock frequency     : 8,000000 MHz
Data Stack size     : 64
*****************************************************/

#include <tiny2313.h>
#include <stdio.h> // Для UART
#include <delay.h>
#include <string.h>                              
 
//Временные пределы
#define Tmin 40 //длинный промежуток
#define Tmax 68
#define TminK 22 //короткий промежуток
#define TmaxK 34

//Коды пульта
#define TV 12
#define MUTE 13
#define SLEEP 38
#define VOL_UP 16
#define VOL_DOWN 17
#define CHANNEL_UP 32
#define CHANNEL_DOWN 33

//Режим
#define MODE_LOFF     0
#define MODE_LAMP     1
#define MODE_LEDS     2
#define MODE_CH_R     3
#define MODE_CH_G     4
#define MODE_CH_B     5
#define MODE_ANIM     6

unsigned char sct_bit = 0;      //Счетчик битов RC5
unsigned char RC5_buffer [14];  //Буффер RC5
bit centre =  0;                //Флаг центра 
bit not_korr = 0;               //Флаг попадания в промежутки
unsigned char Timer = 0;        //число в счетчике таймера
unsigned char trigger = 0;      //переменная тригера
unsigned char device = 0;        //переменная адреса ПДУ
unsigned char command = 0;      //переменная для команды
unsigned char mode = MODE_CH_R; //MODE_LAMP;
eeprom unsigned char LED_R = 255, 
                     LED_G = 255, 
                     LED_B = 255;

/*
	Коды кнопок пульта
	
    DEVICE_ID=0; 0x00;
    
    TV=12; 0x0C;
    MUTE=13; 0x0D;
    SLEEP=38; 0x26;
    VOL_UP=16; 0x10;
    VOL_DOWN=17; 0x11;
    CHANNEL_UP=32; 0x20;
    CHANNEL_DOWN=33; 0x21;
*/
//------------------------------------------------------------------------------------------------
void init_pwm (void)
{
	TCCR0A=( 1 << COM0A1 ) | ( 0 << COM0A0 ) | ( 1 << WGM10 ); 
	TCCR1A=( 1 << COM1A1 ) | ( 0 << COM1A0 ) | ( 1 << COM1B1 ) | ( 0 << COM1B0 ) | ( 1 << WGM10 ); 

	TCCR0B=(1<<CS10); 
	TCCR1B=(1<<CS10); 
}
//------------------------------------------------------------------------------------------------
void rc5_cl_buf(void){            //очищаем буффер
  char i = 0;      
  for (i=0; i<14; i++){ RC5_buffer [i] = 0;  }
}   
//------------------------------------------------------------------------------------------------
void rc5_ti_stop(void){           //остановка таймера
   GIMSK|=0x00;
   TCCR0B = 0x00;
   TCNT0 = 0;
   sct_bit = 0; 
} 
//------------------------------------------------------------------------------------------------
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
Timer = TCNT0; //запоминаем значение счетчика   
TCNT0 = 0;     //обнуляем счетчик
not_korr = 1;                         
if(sct_bit==0){
                  TCCR0B = 0x04; //запускаем таймер  (31.250 KHz)
                  RC5_buffer [sct_bit] = !PIND.2;//записываем в эл.массива
                  sct_bit++;            //+1 к счётчику принятых битов
                  centre = 1;           
        }else{
                  if ((Timer>TminK)&&(Timer<TmaxK)){   // проверка короткого промежутка
                                                  if (centre) {
                                                              centre = 0;
                                                              not_korr = 0; 
                                                  }else{
                                                              centre = 1;
                                                              RC5_buffer [sct_bit] = !PIND.2;
                                                              sct_bit++;
                                                              not_korr=0;
                                                  };
                  }; 
                  if ((Timer>Tmin)&&(Timer<Tmax)){ // проверка длинного промежутка
                                                  RC5_buffer [sct_bit] = !PIND.2;
                                                  sct_bit++;
                                                  not_korr = 0;
                  };                               
                  if (not_korr == 1) {             // если не попали ни в один из промежутков то  
                                       rc5_ti_stop();   //останавливаем таймер
                                       rc5_cl_buf();    //очищаем буффер
                  };
                  if (sct_bit == 14){        // если бит последний то 
                    rc5_ti_stop();   //останавливаем таймер
                     
                    trigger = RC5_buffer [2];  //формируем переменную тригера 
                   
                    device = (RC5_buffer [3] << 4)|(RC5_buffer [4] << 3)|(RC5_buffer [5] << 2)|(RC5_buffer [6] << 1)|RC5_buffer [7];                                    //формируем адрес ПДУ                
                    command = (RC5_buffer [8] << 5)|(RC5_buffer [9] << 4)|(RC5_buffer [10] << 3 )|(RC5_buffer [11] << 2)|(RC5_buffer [12] << 1)|RC5_buffer [13];        //формируем команду
           
            
                    switch(mode) // Проверяем в каком мы режиме
                    {
                        case MODE_CH_R: // Режим смены яркости красных светодиодов
                        {   
                            switch(command)
                            {
                                case CHANNEL_UP:
                                { 
                                    if(OCR0A<=254)
                                    OCR0A++;
                                }break;
                                
                                case CHANNEL_DOWN:
                                {
                                    if(OCR0A>=1)
                                    OCR0A--;        
                                }break;
                                
                                case SLEEP:
                                {      
                                    mode = MODE_CH_G; 
                                    LED_R = OCR0A;
                                }break;
                            }    
                        }break;  
                        
                        case MODE_CH_G:
                        {             
                            switch(command)
                            {
                                case CHANNEL_UP:
                                { 
                                    if(OCR1A<=254)
                                    OCR1A++;
                                }break;
                                
                                case CHANNEL_DOWN:
                                {
                                    if(OCR1A>=1)
                                    OCR1A--;        
                                }break;
                                
                                case SLEEP:
                                {      
                                    mode = MODE_CH_B; 
                                    LED_G = OCR1A;
                                }break;
                            }   
                        }break;  
                        
                        case MODE_CH_B:
                        {      
                            switch(command)
                            {
                                case CHANNEL_UP:
                                { 
                                    if(OCR1B<=254)
                                    OCR1B++;
                                }break;
                                
                                case CHANNEL_DOWN:
                                {
                                    if(OCR1B>=1)
                                    OCR1B--;        
                                }break;
                                
                                case SLEEP:
                                {      
                                    mode = MODE_CH_R; 
                                    LED_B = OCR1B;
                                }break;
                            }   
                        }break;
                    }
                             
                    
                    EIFR=0x40;   // сбрасываем флаг прерывания по входу INT0          
                    
                    };                                                                         
        };  
}
//------------------------------------------------------------------------------------------------
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{   
rc5_ti_stop();        //останавливаем таймер
rc5_cl_buf();        //очищаем буффер
GIMSK|=0x40; //разрешаем прерывания по входу
EIFR=0x40;  //сбрасываем флаг прерывания (если произошло)
}
//------------------------------------------------------------------------------------------------
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Port A initialization
PORTA=0x00;
DDRA=0x00;
// Port B initialization
PORTB=0x00;
DDRB=0x1C;
// Port D initialization
PORTD=0x04;
DDRD=0x20;

// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x40;
MCUCR=0x01;
EIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x82;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
// UCSRA=0x00;
// UCSRB=0x98;   //0x18;
// UCSRC=0x06;
// UBRRH=0x00;
// UBRRL=0x33;

OCR0A=10;//LED_R; 
OCR1A=10;//LED_G; 
OCR1B=10;//LED_B; 

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// После этой инициализации ШИМ - тинька не реагирует на пульт - в то время как светодиоды активно светятся
init_pwm();

// Global enable interrupts
#asm("sei")

while (1)
      {  
        //printf("Command = 0x%d\r\n", command);     
        //putsf("Hello, world!\r\n"); 
        //delay_ms(1000);
      };
}