#include <avr/io.h>
#include <stdint.h>
#include <avr/eeprom.h>
#include <stdio.h>
#include <avr/interrupt.h>

//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;

//predvolba se bude ukladat do E2PROM:
uint8_t predvolba EEMEM;

//nacte predvolbu z E2PROM:
void nactipredvolbu()
{
  uint8_t nacteno;
  
  nacteno = eeprom_read_byte((const uint8_t*) &predvolba);
  if(nacteno > max)  //oprava rozsahu
    nacteno = max;
    
  OCR4B = nacteno;  //nastaveni do casovace
}

//ulozi predvolbu do E2PROM:
void ulozpredvolbu()
{
  uint8_t zapsano;
  
  zapsano = OCR4B;
  cli();
  eeprom_write_byte(&predvolba, zapsano);
  eeprom_busy_wait();
  sei();
}

void inicializace()
{
  DDRD = (1 << 2);  //PD2 vystup
  PORTD = (1 << 2); //OC4B povolen

  PCICR =(1 << PCIE2);  //Pin Change PD povolen
  //PD5 (PCINT21), PD3 (PCINT19) povoleny:
  PCMSK2 =(1 << bitCK) | (1 << bitBT);

  //neinv. rezim OC4B, PWM (f+k+ICR4), D = 1024:
  TCCR4A = (1 << COM4B1);
  TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40);
  ICR4 = max;
  OCR4B = stred;
}

int main(void)
{
  inicializace();
  nactipredvolbu();
  sei();  //preruseni povoleno

  while (1)
  {
  }
}

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

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

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

  if(getbit(stav, bitBT))  //stredove tlacitko
  {
    ulozpredvolbu();
  }
}