#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#if defined(__AVR_AT90S2313__)
#  define OC1 PB3
#  define OCR OCR1
#  define DDROC DDRB
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
#  define OC1 PB1
#  define DDROC DDRB
#  define OCR OCR1
#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || \
      defined(__AVR_AT90S4434__) || defined(__AVR_AT90S8535__) || \
      defined(__AVR_ATmega163__)
#  define OC1 PD5
#  define DDROC DDRD
#  define OCR OCR1A
#elif defined(__AVR_ATmega8__)
#  define OC1 PB1
#  define DDROC DDRB
#  define OCR OCR1A
#  define PWM10 WGM10
#  define PWM11 WGM11
#elif defined(__AVR_ATmega32__)
#  define OC1 PD5
#  define DDROC DDRD
#  define OCR OCR1A
#  define PWM10 WGM10
#  define PWM11 WGM11
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
#  define OC1 PB5
#  define DDROC DDRB
#  define OCR OCR1A
#  define PWM10 WGM10
#  define PWM11 WGM11
#else
#  error "Dont know what kind of MCU you are compiling for"
#endif

//****************************************************************
#define SET_B(x) |= (1<<x)
#define CLR_B(x)  &=~(1<<x)
#define INV_B(x) ^=(1<<x)
//*******************************

//*******************************
#define F_CPU 3686400UL


void port_init(void);
void init_devices(void);
//void delaysa(unsigned int mks);
void nomovie(int servo);
void Pos(char servo,int angle);
//----------------------------------------------------------------
volatile char gservo;//Номер сервы
volatile int gangle;//Управляющий импульс
volatile const int period =1; //период в 20 миллисекунд
volatile static int cur_state;
//----------------------------------------------------------------
//****************ИНИЦИАЛИЗАЦИЯ ТАЙМЕРА***************************
void timer1_init()
{
TCCR1B = 0x00; //stop timer
//TCNT1 = gangle; //записать в регистр таймера число 3686400/1024/120(x)
//60056-среднее положение(+0.02)
TIMSK =0x04;//Разрешение прерывания по переполнению таймера 1
SREG SET_B(7);//Бит i в регистре SREG включен(разрешить глобальные прерывания)

TCCR1B =0x01; //Старт таймера при делителе = 1024
//Биты CS10 CS11 CS12
}
//**************ПРОЦЕДУРА ПЕРЕПОЛНЕНИЯ ТАЙМЕРА***********************
SIGNAL(SIG_OVERFLOW1)
{

  if(cur_state == 0) {
     //вывести '1'
     TCNT1=gangle; //настроить таймер на задежку t ms
	 PORTB SET_B(gservo);//Выставить 1 на ножку
     cur_state = 1;
	 
  } else 
  {
      //вывести '0'
       TCNT1 = period;  //настроить таймер на задежку (20) ms
	  PORTB CLR_B(gservo);//Выставить 1 на ножку
	  cur_state = 0;
  } 


}

//************ПРОЦЕДУРА ПОЗИЦИОНИРОВАНИЯ СЕРВЫ********************
void Pos(char servo,int angle)
{

//PORTB SET_B(servo);//Выставить 1 на ножку
gservo=servo;//Номер сервы
gangle=angle;//Управляющий импульс
//TCNT1=gangle;//Управляющий импульс


}

/*
//-***********МИКРОСЕКУНДНАЯ ЗАДЕРЖКА*****************************
void delaysa(unsigned int mks)
{
while(mks>0){
mks--;
}
}
*/
//************ИНИЦИАЛИЗАЦИЯ ПЕРИФЕРИЙНЫХ УСТРОЙСТВ****************
void init_devices(void)
{
//port_init();
PORTB = 0x00;
DDRB  = 255;
//PORTD = 12;// for buttons
//DDRD  = 0x00;
MCUCR = 0x00;
GIMSK = 0x00;
TIMSK = 0x00;
//SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//************ИНИЦИАЛИЗАЦИЯ USART*********************************
void USART_Init( unsigned int baud )
{

UBRRH = (unsigned int)(baud>>8);
UBRRL = (unsigned int)baud;

UCSRB = (1<<RXEN)|(1<<TXEN);

UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
//************ПРИЁМ USART*********************************
unsigned int USART_Receive( void )
{

while ( !(UCSRA & (1<<RXC)) )
;

return UDR;
}
//************ПЕРЕДАЧА USART*********************************
void USART_Transmit( unsigned int data )
{

while ( !( UCSRA & (1<<UDRE)) );

UDR = data;
}
//*****************УПРАВЛЕНИЕ СЕРВАМИ*************************
void Servo_Control()
{char s;
int angle;
 char szInput [4];
s=USART_Receive();

s=s-0x31;

szInput[0] = USART_Receive();
szInput[1] = USART_Receive();
szInput[2] = USART_Receive();
szInput[3] = USART_Receive();
szInput[4] = USART_Receive();
//szInput[5] = 0; // Строка должна заканчиваться 0

 angle = atoi (szInput);

Pos(s,angle);
}
//****************ФУНКЦИЯ ПЕРЕНАПРАВЛЕНИЯ**********************
void Command()
{char i;
i= USART_Receive();
if(i=='s')
{
Servo_Control();
}

}


//***************ГЛАВНАЯ ФУНКЦИЯ******************************
int main()
{gservo=20;
//gangle=60000;

 
USART_Init(23);
init_devices();
timer1_init();

while(1)
{
 
Command();
  
}
 return(0);
}


