#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>

//port a bit pro LED:
volatile uint8_t &portLED = PORTB;
const uint8_t bitLED = 5;
//port a bity pro enkoder:
volatile uint8_t &pinENK = PIND;
const uint8_t bitCK = 5;
const uint8_t bitDT = 4;
const uint8_t bitBT = 3;
//perioda a stred:
const uint8_t max = 6;
const uint8_t stred = 3;

inline void setbit(volatile uint8_t &reg, uint8_t bit)
{
  reg = reg | (1 << bit);
}

inline void clearbit(volatile uint8_t &reg, uint8_t bit)
{
  reg = reg & ~(1 << bit);
}

uint8_t getbit(volatile uint8_t reg, uint8_t bit)
{
  return (reg & (1 << bit)) >> bit;
}

void inicializace()
{
  setbit(DDRB, bitLED);  //PB5 vystup
  setbit(PCICR, PCIE2);  //PD povolen
  setbit(PCMSK2, bitCK); //PD5 (PCINT21) povolen
  setbit(PCMSK2, bitBT); //PD3 (PCINT19) povolen
}

//sirka impulzu pro LED:
volatile uint8_t sirka = stred;

int main(void)
{
  //generuje casovou osu:
  uint8_t pocitadlo = 0;

  inicializace();
  sei();  //přerušení povoleno

  while (1)
  {
    //na zacatku periody:
    if((pocitadlo == 0) && (sirka > 0))
      setbit(portLED, bitLED);    //zapne LED
    //na konci impulzu:
    if(pocitadlo == sirka)
      clearbit(portLED, bitLED);  //vypne LED
    
    //pocitadlo se meni 0 az max-1:
    pocitadlo++;
    if(pocitadlo == max)
      pocitadlo = 0;

    //casovani periody na 7 ms:
    _delay_ms(1);
  }
}

//obsluha preruseni enkoderu:
ISR(PCINT2_vect)
{
  uint8_t stav = ~pinENK;

  if(getbit(stav, bitCK))  //detekce otaceni
  {
    if(getbit(stav, bitDT))  //detekce smeru
    {
      if(sirka < max)  //po smeru hod. rucek
        sirka++;
    }
    else
    {
      if(sirka > 0)    //proti smeru hod. rucek
        sirka--;
    }
  }

  if(getbit(stav, bitBT))  //stredove tlacitko
  {
    sirka = stred;
  }
}