#include <inttypes.h>            
#include <avr/io.h> 
#include <avr/interrupt.h>  
#include <util/delay.h> 

#define XTAL        1000000L    
#define TIMER_CLOCK       2 
#define blue OCR0A                                       //nazw rejestru OCR0A zastp nazw "blue" (wyjcie PB2))    
#define red OCR0B                                       //nazw rejestru OCR0B zastp nazw "red" (wyjcie PD5) 
#define green OCR1A                                       //nazw rejestru OCR1A zastp nazw "green" (wyjcie PB3) 

static volatile uint8_t i=1;                              //deklaracja zmiennej globalnej "i" 
volatile uint8_t b;                                       //deklaracja zmiennej globalnej "b" 
  
/*******************KONFIGURACJA REJESTRW I WE/WY********************/ 
init_setup()                                          //podporogram ktry jest uruchamiany                                         
{                                                      //w programie gownym, konfiguruje rejestry i porty    
   DDRB|=(1<<PB2)|(1<<PB3);                              //PB2 i PB3 jako wyjcia                                           
   DDRD|=(1<<PD5)|(0<<PD0);                              //PD5 jako wyjcie, PD0 jako wejcie                                
   PORTD|=(1<<PD0);                                    //PD0 podcignite do VCC 
                                                                      
   //opisane na samym dole programu 
    
   TCCR0A|=(1<<WGM00)|(0<<WGM01)|(0<<WGM02)|(1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0);    
   TCCR0B|=(1<<CS00); 
    
   TCCR1A|=(1<<WGM10)|(0<<WGM11)|(0<<WGM12)|(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0); 
   TCCR1B|=(1<<CS10)|(1<<CS11)|(1<<WGM12);     
                            
    OCR1A = 3600;                                       //wpisanie do rejestru OCR1A staej wartoci                                        
                                                   //od niej zaley jak czsto wystpuje przerwanie 
    TIMSK|=(1<<OCIE1B);                                 //ustawienie OCIE1B w rejestrze TIMSk odblokowuje przerwanie                      

    sei();                                             //globalne zezwolenie na przerwania                                            
}                                                    
/*********************************************************************/ 

/*******************OBSUGA PRZERWANIA********************************/ 
ISR(TIMER1_COMPB_vect)                                    //przerwanie od timera_1 wykonywane jest                                              
{                                                                     //gdy warto timera_1 zrwna si z wartoci OCR1A 
    if(bit_is_clear(PIND,0))                              //jeeli PD0 wcinity 
        { 
        _delay_ms(80);                                    //opnienie 80ms 
        incr_i();                                       //id do podprogramu "incr_i" 
        }    
} 
/*********************************************************************/ 

/*******************PODPOGRAM ZWIKSZAJCY ZMIENN "i"****************/ 
void incr_i()                                          //podprogram obsugujcy zmienna "i" 
{ 
   _delay_ms(80);                                       //opnienie 80ms 
   while(bit_is_clear(PIND,0)){}                           //nic nie rb gdy wcinity PD0 
   _delay_ms(80);                                       //opnienie 80ms 
   i=i+1;                                             //zwiksz warto zminnej "i" o 1 
   _delay_ms(100);                                       //opnienie 100ms 
   if(i==5) i=1;                                       //jeeli i=5 to i=1 
} 
/*********************************************************************/ 

/*******************PODPROGRAMY DLA TRYBW OWIETLENIA****************/ 
void red_mode()                                          //podprogram ktry na stae wpisuje 
{                                                   //wartoci do rejestrw OCR0A, OCR0B, OCR1A 
   red=0; 
   blue=255; 
   green=255; 
} 

void blue_mode()                                                          
{                                                    
   blue=0; 
   red=255; 
   green=255; 
}    
    
void green_mode()                                        
{                                                    
   green=0; 
   blue=255; 
   red=255; 
} 

void pwm_mode()                                          //podprogram pynnie zmieniajcy wiecenie diod 
{ 
      for(b=0;b<255;b++) 
         { 
            red=b;                                    //do rejestru OCR0B wpisywana jest warto zmiennej "b" 
            _delay_ms(10); 
         } 
      for(b=255;b>0;b--) 
         { 
            red=b; 
            _delay_ms(10); 
         } 
         for(b=0;b<255;b++) 
         { 
            blue=b; 
            _delay_ms(10); 
         } 
      for(b=255;b>0;b--) 
         { 
            blue=b; 
            _delay_ms(10); 
         } 
         for(b=0;b<255;b++) 
         { 
            green=b; 
            _delay_ms(10); 
         } 
      for(b=255;b>0;b--) 
         { 
            green=b; 
            _delay_ms(10); 
         } 
} 

int main(void)                                          //program gwny 
{ 
init_setup();                                          //wywoanie podprogramu "init_setup"                    
while(1)                                             //nieskoczona ptla 
{ 

if(i==1) pwm_mode();                                    //jeeli i=1 wywoaj podprogram "pmw_mode" 
if(i==2) red_mode(); 
if(i==3) blue_mode(); 
if(i==4) green_mode(); 

}                
} 

//(1<<WGM00)|(0<<WGM01)|(0<<WGM02) - PWM phase correct, tryb pracy PWM 
//(1<<COM0A1)|(1<<COM0A0) - Set OC0A on Compare Match when up-counting. Clear OC0A on Compare Match when down-counting. 
//(1<<COM0B1)|(1<<COM0B0) - Set OCR0B on Compare Match when up-counting. Clear OCR0B on Compare Match when down-counting. 
//(1<<CS00) - No prescaler 

//(1<<WGM10)|(0<<WGM11)|(0<<WGM12) - PWM, Phase Correct, 8-bit 
//(1<<COM1A1)|(1<<COM1A0) - Set OC1A/OC1B on Compare Match, clearSet OC1A/OC1B on Compare Match when up- 
counting. Clear OC1A/OC1B on Compare Match 
when downcounting. OC1A/OC1B at TOP 
//(1<<COM1B1)|(1<<COM1B0) - Set OC1A/OC1B on Compare Match when up- 
counting. Clear OC1A/OC1B on Compare Match 
when downcounting. 
//(1<<WGM12) - CTC 
//(1<<CS10)|(1<<CS11) - clkI/O/64 (From prescaler) 

