/**************************************************************************************
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 C,BT_MODE,kbd_flags,scena=0,button;  
        // b00000001   
        
 typedef union {
unsigned char ch;
struct{
      char level:5;
      char max:2;
      char min:1;
};
}RGB;

RGB R,G,B;

 enum{KEY_NULL,KEY_LEFT,KEY_RIGTH}; 
//============================Обявление функций========================================= 
 void min (void); 
 void max (void);
 void color (unsigned int cRi,unsigned int cGi,unsigned int cBi);
 void btn_color (unsigned int button);
 void bright_max (void);
 void 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 канала===========================
  if (pwm_counter++>30) pwm_counter=0;
  temp= PORTB | 0x0f;
  
  if (((R.min)||((pwm_counter>=R.level)&&(!R.max))))   temp &= ~(1 << PORTB0); //ШИМ канал для красного канала RGB LED
 
  if (((G.min)||((pwm_counter>=G.level)&&(!G.max))))   temp &= ~(1 << PORTB1); //ШИМ канал для зеленого канала RGB LED
  
  if (((B.min)||((pwm_counter>=B.level)&&(!B.max))))   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.level<31) G.level++; else scena = 1;}
  if (scena == 1) {if(R.level)     R.level--; else scena = 2;}
  if (scena == 2) {if(B.level<31) B.level++; else scena = 3;}
  if (scena == 3) {if(G.level)     G.level--; else scena = 4;}
  if (scena == 4) {if(R.level<31) R.level++; else scena = 5;}
  if (scena == 5) {if(B.level)     B.level--; else scena = 0;}
  }

void max (void)
 {
  if (scena == 0) {if(G.level)     G.level--; else scena = 5;}
  if (scena == 1) {if(R.level<31) R.level++; else scena = 0;}
  if (scena == 2) {if(B.level)     B.level--; else scena = 1;}
  if (scena == 3) {if(G.level<31) G.level++; else scena = 2;}
  if (scena == 4) {if(R.level)     R.level--; else scena = 3;}
  if (scena == 5) {if(B.level<31) B.level++; else scena = 4;}
 }
//=====================Функция предворительно настроенных цветов========================== 
 void color (unsigned int cRi,unsigned int cGi,unsigned int cBi)
  {
   R.level=cRi; G.level=cGi; B.level=cBi;
  }
//=============Функция выбора преднастроенного цвета по нажатию на кнопку=================
 void btn_color (unsigned int 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;
      }
  }  
//===================Функция увеличения яркости===========================================
 void bright_max (void)
{
R.ch++; 
G.ch++;
B.ch++;


}
//==================Функция уменьшения яркости============================================
void bright_min (void)
{
R.ch--; 
G.ch--;
B.ch--;
}
//=======================Функция плавного включение RGB LED===========================================
void on_rgb_led (void)
{unsigned char temp=0;
   
   while(temp++<31){
    R.level=G.level=B.level=temp;
    delay_ms(10);
   };
   
}
//=======================Функция плавного выключения RGB LED===========================================
void off_rgb_led (void)
{
unsigned char temp=31;
   while(temp--)
    {
     R.level=G.level=B.level=temp;
    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;
// Инициализация портов. 
// Инициализация выходов
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);

 DDRC=0x03;
// подтяжка к 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();
;
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 ();  
          
         }
          
  }
//====================Плавное выключение RGB LED при выкл. питания======================== 
  off_rgb_led();
  delay_ms(5);
//====================Плавное выключение RED LED при выкл. питания======================== 
  off_red_led();  
 }

