/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 10.10.2010
Author  : 
Company : 
Comments: 


Chip type           : ATmega8
Program type        : Application
Clock frequency     : 16,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>
#include <delay.h>

#define delay_   30    // плавность включения
#define yes   1
#define no    0

int status = 0;  // текущее значение яркости

unsigned int tick = 0;          //счетчик тиков таймера
unsigned char b_cnt = 0;        //счетчик принятых бит
bit start_cond = 0;             //флаг стартового условия

unsigned char addr_1 = 0;       //прямой байт адреса
unsigned char addr_0 = 0;       //инверсный байт адреса
unsigned char cmd_1 = 0;        //прямой байт команды
unsigned char cmd_0 = 0;        //инверсный байт команды
unsigned char cmd = 0;          //байт команды

// Таблица задержек для 16-тибитного таймера
flash const unsigned int nagruzka[99] = {
20324,  // 1% нагрузки
19794,  // 2% нагрузки
19384,  // 3% нагрузки
19036,
18728,
18450,
18190,
17948,
17720,
17504,
17296,
17096,
16904,
16718,
16536,
16360,
16188,
16022,
15858,
15696,
15538,
15384,
15232,
15082,
14934,
14788,
14644,
14500,
14360,
14220,
14082,
13944,
13808,
13674,
13540,
13406,
13274,
13142,
13012,
12882,
12752,
12622,
12494,
12366,
12238,
12110,
11982,
11854,
11728,
11600,
11472,
11346,
11218,
11090,
10962,
10834,
10706,
10578,
10448,
10318,
10188,
10058,
9926,
9794,
9660,
9526,
9392,
9256,
9118,
8980,
8840,
8700,
8556,
8412,
8266,
8118,
7968,
7816,
7662,
7504,
7342,
7178,
7012,
6840,
6664,
6482,
6296,
6104,
5904,
5696,
5480,
5252,
5010,
4750,
4472,
4164,
3816, // 97% нагрузки
3406, // 98% нагрузки
2876, // 99% нагрузки
};

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
  {
  TCNT1 = 0; // сбросили таймер
  }
  
// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
        TCNT0=0xFA;                                                             // запускаем таймер на 96 мкс
        TCCR0=0x04;                                                             // частота таймера 62.500 кГц
        
        if (tick >= 92 && tick < 96)                                            //если прошло от 8,832 мс до 9,216 мс
                {
                start_cond = 1;                                                 //фиксируем стартовое условие
                addr_1 = addr_0 = cmd_1 = cmd_0 = 0;                            //обнуляем ранее полученную команду и адрес
                }
        if (tick >= 21 && tick < 25 && start_cond)                              //если прошло от 2,016 мс до 2,4 мс
                {
                b_cnt++;                                                        //приняли "1" и увеличили счетчик битов
                if (b_cnt < 9) addr_1 = (addr_1 << 1) + 1;                      //первый байт - прямой адрес
                if (b_cnt >= 9 && b_cnt < 17) addr_0 = (addr_0 << 1) + 1;       //второй байт - инверсный адрес
                if (b_cnt >= 16 && b_cnt < 25) cmd_1 = (cmd_1 << 1) + 1;        //третий байт - прямая команда
                if (b_cnt >= 24) cmd_0 = (cmd_0 << 1) + 1;                      //четвертый байт - инверсная команда
                }
        if (tick >= 10 && tick < 22 && start_cond)                              //если прошло от 0,96 мс до 2,112 мс
                {
                b_cnt++;                                                        //приняли "0" и увеличили счетчик битов
                if (b_cnt < 9) addr_1 = (addr_1 << 1);                          //далее - аналогично по байтам
                if (b_cnt >= 9 && b_cnt < 17) addr_0 = (addr_0 << 1);
                if (b_cnt >= 16 && b_cnt < 25) cmd_1 = (cmd_1 << 1);
                if (b_cnt >= 24) cmd_0 = (cmd_0 << 1);
                }
        tick = 0;                                                               //обнулили тики
        if (b_cnt == 32)  {                                                     //если приняли уже 4 байта
                 if ((cmd_1 + cmd_0) == 0xFF) {                                  //проверили правильность приема команды              
                  cmd = cmd_1;
                    if (cmd == 0b11111000) {      // кнопка "Display" - увеличение яркости
                     if (status < 98) {
                     TCCR1B=0x02;
                     status++;
                     OCR1A = nagruzka[status]; //97-последний индекс массива
                     }
                     else{
                      TCCR1B=0x00;
                      PORTC.5 = 1;//полностью включили                         
                     }
                    }
                    else if (cmd == 0b11000000)  {     // кнопка "Sleep" - уменьшение яркости
                     if (status >0) {
                     TCCR1B=0x02;
                     status--; 
                     OCR1A = nagruzka[status];
                                    }
                     else{
                      TCCR1B=0x00;
                      PORTC.5 = 0;  //полностью выключили   
                      }
                    }                  
                 }                       
                 else {
                  cmd = 0;        
                  b_cnt = 0;                                                    //обнулили счетчик битов
                  start_cond = 0;                                               //сбросили стартовое условие
                  //repeat_cond = 0;
                  TCCR0=0x00;                                                   //остановили таймер
                  TCNT0=0x00;
                 }
        }
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
        TCNT0=0xFA;                                                    //переинициировали таймер - отсчитывает 96 мкс
        tick++;                                                        //увеличили число тиков
        if (tick > 500) {                                              //если прошло более 48 мс
          TCCR0=0x00;                                                  //сбросили все к исходному состоянию
          TCNT0=0x00;
          tick = 0;                                                       
          start_cond = 0;
          //repeat_cond = 0;
          cmd = 0;
        }

}

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
  { 
  PORTC.5 = 1;    // открыли симистор
  delay_us(75);  // импульс 75 мкс
  PORTC.5 = 0;    // вернулись в режим ожидания
  }

/*========================================= ФУНКЦИЯ ПЛАВНОГО ВКЛЮЧЕНИЯ ===========================================*/

void soft_on () {  // функция регулирует мощность от 1% до 99% ( phaze от 0 до 98 )
 int on;                             // крайние положения надо выставлять вручную: PORTC.5 = 1 или PORTC.5 = 0
 for (on=0;on<=98;on++) {           
  status++;
  OCR1A = nagruzka[status];
  delay_ms(delay_);
 };
}

/*============================== ФУНКЦИЯ ПЛАВНОГО ВЫКЛЮЧЕНИЯ С ТЕКУЩЕЙ ЯРКОСТИ ===================================*/

void soft_off () {  
 int off;                             
 for (off=status;off>=0;off--) {           
  status--;
  OCR1A = nagruzka[status];
  delay_ms(delay_);
 };
}

void main(void)
{
// Declare your local variables here

// 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=0xFF;
DDRB=0xFF;

// Port C initialization
// Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTC=0x00;
DDRC=0x7F;

// 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=0x08;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 2000,000 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// 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: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: On
// INT1 Mode: Falling Edge
GICR|=0xC0;
MCUCR=0x0A;
GIFR=0xC0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x11;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
/*====================================== РЕАКЦИЯ НА НАЖАТИЕ КЛАВИШ ВЫКЛЮЧАТЕЛЯ ==================================*/

      /*if (PINB.0==0) {         // ждем нажатие клавиши выключателя
       delay_ms(50);           // антидребезг
       if (status==0) {
        TCCR1B=0x02;           // запуск таймера на 2000 кГц
        soft_on (98);          // плавно от 1% до 99% мощности
        TCCR1B=0x00;           // остановка таймера ( чтобы не молотил в пустую 200 мкс импульсы на PORTC.5 )
        PORTC.5 = 1;           // 100%
		status = 98;
        }
       else {
        TCCR1B=0x02;
        soft_off(status);      // плавно выключаем с текущей мощности
        TCCR1B=0x00;
        PORTC.5 = 0; // 0%
        status=0;
       };
       }*/
       
       /*if (PINB.5==0) {      // вкл/выкл основного света
       // реле вкл/выкл
       }*/
       

/*===================================== ВКЛЮЧЕНИЕ/ВЫКЛЮЧЕНИЕ С ПУЛЬТА ========================================*/

      if (cmd == 0b11011000) {          // кнопка "TV" - вкл/выкл диммера
       if ((status==0) || (status==1)) {
        TCCR1B=0x02;                    // запуск таймера на 2000 кГц
        soft_on ();                     // плавно включаем
        TCCR1B=0x00;                    // остановка таймера ( чтобы не молотил в пустую 200 мкс импульсы на PORTC.5 )
        PORTC.5 = 1;                    // 100%
		status = 98;
        }
       else {
        TCCR1B=0x02;
        soft_off();                     // плавно выключаем с текущей мощности
        TCCR1B=0x00;
        PORTC.5 = 0; // 0%
        status=0;
       };
      }
      
      if (cmd == 0b10000000) {          // кнопка "VIDEO" - вкл/выкл основного света
      // реле вкл/выкл
      }
      };
}
