/**************************************************************************************
Project : Control RGB LED for Cluster Car Dashboard
Version : 1.0.0
Date    : 29.10.2013
Author  : Fyodorov Evgenie
Company : fevcomp@bk.ru
Comments:

Chip type               : ATmega8
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
***************************************************************************************/

#include <mega8.h>
#include <delay.h>

//===========================Обявление переменных========================================

  volatile unsigned char R,G,B,C,BT_MODE,kbd_flags,scena=0,button;  
        // b00000001   
   eeprom unsigned char eeR,eeG,eeB;     


 enum{KEY_NULL,KEY_LEFT,KEY_RIGTH}; 

flash unsigned char RGB_mass[256]={
0x00, 0x00, 0x01, 0x02, 0x04, 0x06, 0x09, 0x0C,   // 0 .. 7
0x10, 0x14, 0x19, 0x1E, 0x24, 0x2A, 0x31, 0x38,   // 8 .. 15
0x40, 0x48, 0x51, 0x5A, 0x64, 0x6E, 0x79, 0x84,   // 16 .. 23
0x90, 0x9C, 0xA9, 0xB6, 0xC4, 0xD2, 0xE1, 0xFF,   // 24 .. 31
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 32 .. 39
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 40 .. 47
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 48 .. 55
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 56 .. 63
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 64 .. 71
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 72 .. 79
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 80 .. 87
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 88 .. 95
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 96 .. 103
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 104 .. 111
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 112 .. 119
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   // 120 .. 127
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 128 .. 135
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 136 .. 143
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 144 .. 151
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 152 .. 159
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 160 .. 167
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 168 .. 175
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 176 .. 183
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 184 .. 191
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 192 .. 199
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 200 .. 207
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 208 .. 215
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 216 .. 223
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 224 .. 231
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 232 .. 239
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // 240 .. 247
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};  // 248 .. 255






//============================Обявление функций========================================= 
 void min (void); 
 void max (void);
 void color (unsigned char cRi,unsigned char cGi,unsigned char cBi);
 void btn_color (unsigned char button);
 char bright_max (void);
 char bright_min (void);
 void on_rgb_led (void);
 void off_rgb_led (void);
 void on_red_led (void);
 void off_red_led (void); 

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void Prog_pwm(void)
 { static unsigned char enc_state,bt_state;
    unsigned char  temp; 
    static unsigned char pwm_counter;
//=====================Реализация программного ШИМ на 4 канала===========================
  pwm_counter++;
  
  temp= PORTB | 0x0f;
  
  if (pwm_counter>=RGB_mass[R])   temp &= ~(1 << PORTB0); //ШИМ канал для красного канала RGB LED
 
  if (pwm_counter>=RGB_mass[G])   temp &= ~(1 << PORTB1); //ШИМ канал для зеленого канала RGB LED
  
  if (pwm_counter>=RGB_mass[B])   temp &= ~(1 << PORTB2); //ШИМ канал для синего канала RGB LED
  
  if (pwm_counter>=C)   temp &= ~(1 << PORTB3); //ШИМ канал для красного монохромного LED 
       
  PORTB = temp;
  
     enc_state <<= 1;
     enc_state  |= PIND.0;
     enc_state <<= 1;
     enc_state  |= PIND.2;
   
     
   switch (enc_state) 
      {                
      case KEY_LEFT:  // b00000001
      case KEY_RIGTH: // b00000010 
      kbd_flags = enc_state; // LEFT RIGTH
      };  
     
     bt_state  <<= 1;
     
     bt_state   |= PIND.1;
    
     if(bt_state==254) BT_MODE = 1;
    
 }
//=====================Функция выбора политры цвета из спектра==========================
void min (void)
 {
  if (scena == 0) {if(G<31)  G++; else scena = 1;}
  if (scena == 1) {if(R)     R--; else scena = 2;}
  if (scena == 2) {if(B<31)  B++; else scena = 3;}
  if (scena == 3) {if(G)     G--; else scena = 4;}
  if (scena == 4) {if(R<31)  R++; else scena = 5;}
  if (scena == 5) {if(B)     B--; else scena = 0;}
  }

void max (void)
 {
  if (scena == 0) {if(G)     G--; else scena = 5;}
  if (scena == 1) {if(R<31)  R++; else scena = 0;}
  if (scena == 2) {if(B)     B--; else scena = 1;}
  if (scena == 3) {if(G<31)  G++; else scena = 2;}
  if (scena == 4) {if(R)     R--; else scena = 3;}
  if (scena == 5) {if(B<31)  B++; else scena = 4;}
 }
//=====================Функция предворительно настроенных цветов========================== 
 void color (unsigned char cRi,unsigned char cGi,unsigned char cBi)
  {
   R=cRi; G=cGi; B=cBi;
  }
//=============Функция выбора преднастроенного цвета по нажатию на кнопку=================
 void btn_color (unsigned char button)
  {
    switch (button)
      {
       case 1: color (31,0,0);break;
       case 2: color (0,31,0);break;
       case 3: color (0,0,31);break;
       case 0: color (31,31,31);break;
      }
  }  
//===================Функция увеличенияc  c           яркости===========================================
char bright_max (void)
{
if((RGB_mass[R]<255)||(RGB_mass[G]<255)||(RGB_mass[B]<255))
{
R++;                                                                  
G++;
B++;
}else return 0;
 return 1;
}
//==================Функция уменьшения яркости============================================
char bright_min (void)
{
if((RGB_mass[R])||(RGB_mass[G])||(RGB_mass[B]))
{
R--; 
G--;
B--;
}else return 0;
 return 1;
}
//=======================Функция плавного включение RGB LED===========================================
void on_rgb_led (void)
{
while(bright_max())delay_ms(10);
}
//=======================Функция плавного выключения RGB LED===========================================
void off_rgb_led (void)
{
 while(bright_min())delay_ms(10);
}
//=======================Функция плавного включение RED LED===========================================
void on_red_led (void)
{
 {
 for (C=0;C<31;C++)
  delay_ms(5);
 }
}
//=======================Функция плавного выключение RED LED===========================================
void off_red_led (void)
{
 {
     for (C=31;C>0;C--)
  delay_ms(5);
 }
}      
void main(void)
{ unsigned char kbd, tR,tG,tB;
// Инициализация портов. 
// Инициализация выходов
DDRB |= (1 << PORTB5)|(1 << PORTB4)|(1 << PORTB3)|(1 << PORTB2)|(1 << PORTB1)|(1 << PORTB0);
PORTB = 0x00;
// Инициализация входов
DDRD |= (0 << PORTD2)|(0 << PORTD1)|(0 << PORTD0)|(0<<PORTD7);
// Подключаем подтягивающие резисторы
PORTD |= (1 << PORTD2)|(1 << PORTD1)|(1 << PORTD0)|(1<<PORTD7);


// подтяжка к Vcc
PORTD |= (1<<7);
DDRD=0x00;
// Разрешение прерывания по таймеру0
TIMSK |= (1 << TOIE0);
TCCR0 |= (1 << CS00);


 
#asm("sei")
//===================Плавное включение RED LED при вкл. питания===========================
  on_red_led(); 
//===================Плавное включение RGB LED при вкл. питания===========================
  delay_ms(5);  
 on_rgb_led(); 
 
 tR = eeR;
 tG = eeG;
 tB = eeB; 
 
 while((RGB_mass[R] != RGB_mass[tR]) || ( RGB_mass[G] != RGB_mass[tG]) || ( RGB_mass[B] != RGB_mass[tB]))
 {
 if (RGB_mass[R] > RGB_mass[tR]) R--;
 if (RGB_mass[G] > RGB_mass[tG]) G--;
 if (RGB_mass[B] > RGB_mass[tB]) B--; 
 
 if (RGB_mass[R] < RGB_mass[tR]) R++;
 if (RGB_mass[G] < RGB_mass[tG]) G++;
 if (RGB_mass[B] < RGB_mass[tB]) B++; 
 
 delay_ms(15);
 }
  
while (1)
  {


//=======================Обработка события нажатия кнопки энкодера=========================
         
           if (BT_MODE)
           { 
           BT_MODE = 0;
           if(button++ > 5)     button = 0;
//==================Выбор преднастроенных цветов политры по нажатию кнопки=================
            btn_color (button);
             
           }   
         
         kbd = kbd_flags;  
         kbd_flags=KEY_NULL;    
         
          
         if (button==4) //Регулировка каналов по спектру
         {
         if (kbd == KEY_LEFT)  max (); 
         if (kbd == KEY_RIGTH) min (); 
         }
        else      //Регулировка яркости LED RGB
         {
         if (kbd == KEY_LEFT)  bright_max (); 
         if (kbd == KEY_RIGTH) bright_min ();  
         }
         
          if (tR != R) eeR = tR = R;
          if (tG != G) eeG = tG = G;
          if (tB != B) eeB = tB = B;  
          
              
         
          
  }
//====================Плавное выключение RGB LED при выкл. питания======================== 
  off_rgb_led();
  delay_ms(5);
//====================Плавное выключение RED LED при выкл. питания======================== 
  off_red_led();  
 }

