/*********************************************
* Chip type           : ATmega8
* Clock frequency     : 8,000000 MHz
*********************************************/

#define F_CPU 9600000UL 		 //Definovanie názvu F_CPU ako hodnotu 1000000HZ 
#include <util/delay.h>          //knižnica pre oneskorenia

#include <avr/io.h>
#include <avr/interrupt.h>


#define setb(port,pin) port |= 1<<pin 		//nastav bit
#define clrb(port,pin) port &= ~(1<<pin) 	//nuluj bit
#define negb(port,pin) port ^= 1<<pin 		//neguj bit

//SERVOTESTER V 1.0
// 1 PB5 (PCINT5/RESET/ADC0/dW) 
// 2 PB3 (PCINT3/CLKI/ADC3)            button_sweep  - sweep on trigger
// 3 PB4 (PCINT4/ADC2)                 button_middle - pulse width 1.5mS
// 4 gnd
// 5 PB0 (MOSI/AIN0/OC0A/PCINT0)       pulse_out
// 6 PB1 (MISO/AIN1/OC0B/INT0/PCINT1)
// 7 PB2 (SCK/ADC1/T0/PCINT2)          r_var (2k2, gnd, vcc) - pulse width or sweep frequency
// 8 vcc
// fuse default (0x6a)
#define MIDDLE 4
#define SWEEP 3
#define RESET 5

#define WIDTH_MODE   0
#define SWEEP_MODE   2

#define DEB_LIMIT 5


ISR (TIM0_OVF_vect)

{ 
static unsigned char int_count=0, button_debounce=0, sweep_state=WIDTH_MODE;
static char sweep_direct=0;
static int sweep_count;




static unsigned char impulse = 255-155,menu=1,tmp; 
// 1mS =180, 1.5mS=143, 2mS=105

  if(int_count++ >=25)
  {
    OCR0A = impulse;
    int_count = 0;
    if(sweep_state == WIDTH_MODE)   impulse=ADCH;//only high 8 bits (left justify mode)

    if(!(PINB & (1<<SWEEP)))
    {
      if(button_debounce == DEB_LIMIT)
      {

//	  sweep_state = SWEEP_MODE; sweep_count = 0;

	  	menu++;

		if (menu==1){sweep_state = WIDTH_MODE;setb(PORTB,1);setb(PORTB,2);}
		if (menu==2){sweep_state = MIDDLE;clrb(PORTB,2);clrb(PORTB,1);}
		if (menu==3){sweep_state = SWEEP_MODE; sweep_count = 0;setb(PORTB,1);clrb(PORTB,2);menu=0;}
		/*
		switch (menu)

		{
		case 1:{sweep_state = SWEEP_MODE; sweep_count = 0;}	
		case 2:{sweep_state = WIDTH_MODE;menu=0;}	
		break;

		}
*/


        
        button_debounce = 0;
      }
    }
    else 
	if(button_debounce < DEB_LIMIT)
      button_debounce++;
        

    if(sweep_state == MIDDLE)
      impulse = 139;//255-155/2-155/4; //1.5mS
    else
    {
      if(sweep_state == WIDTH_MODE)
      {
        impulse >>=1;
        tmp = impulse>>1;
        impulse -= tmp;
        tmp >>=2;
        impulse += tmp;
        impulse += 100-1;
      }
      else
      {
        if(sweep_direct == 0)
        {
          sweep_count += ((int)impulse)<<3;
          if(sweep_count > 0x3fff)
          {
            sweep_count = 0x3fff;
            sweep_direct = 1;
          }
        }
        else
       {
          sweep_count -= ((int)impulse)<<3;
          if(sweep_count < 0)
          {
            sweep_count = 0;
            sweep_direct = 0;
          }
        }
        impulse = sweep_count>>6;
        impulse >>=1;
        tmp = impulse>>1;
        impulse -= tmp;
        tmp >>=2;
        impulse += tmp;
        impulse += 100-1;
      }
    }
    
  }
  else
  {
    OCR0A = 255; //low level all period (inverse compare out)
    ADCSRA |= 1<<ADSC;//ADC single conversion start
  }
}

int main()
{

	OSCCAL=0x70; // calibration for internal 9,6 MHz //factory 0x69
 // internal_clk = 9.6 MHz
// pulse period 20mS, lenght 1 - 1.5(middle) - 2mS 
  // default divider = 8 (9.6/8=1.2)
  // 9.6 /2 master clock prescaler=4.8 /64 timer counter prescaler /150 timer value = 500Hz (2mS)
  CLKPR = 1<<CLKPCE;// divider change enable
  CLKPR = 1;// 0=divider - 1, 1=divider 2 (page 26 manual PDF)

  
  TCCR0A = 1<<COM0A1 | 1<<COM0A0 | 1<<WGM01 | 1<<WGM00;//WGM2:0 = 3 -> Fast PWM 0xFF TOP MAX  
  OCR0A = 100;
 // OCR0B = 105;//for test purpose only
  
// TIMSK0 = 1<<OCIE0A;
  TIMSK0 = 1<<TOIE0;//TOIE0 counter overflow interrupt
  TCCR0B = 3;//3=timer prescaler 64, 1=1
    
  ADMUX = 1<<ADLAR | 1<<MUX1;//ADC init REF_VCC(ADMUX=0), left_just(ADLAR=1), chan ADC1=PB2(MUX1..0=01)
  ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1;//ADC on (ADEN=1), 4.8/64(prescaler)=75kHz(ADPS2:0=110)
  DIDR0 = 1<<ADC2D;//ADC digital input on PB2 disable
  ADCSRA |= 1<<ADSC;//start single conversion
  //ADC only ADCH read 

  DDRB |=  1<<PB0 | 1<<PB1 | 1<<PB2;//timers out ON  
  PORTB |=   1<<SWEEP | 1<<RESET;//pullup enable on button and reset

  setb(PORTB,1);
  setb(PORTB,2);
  sei();              // Assembler macro for global int. enable

 // SREG |=  1<<7; //interrupt enable


while(1);



}
