#ifndef _HARDWARE_H
#define _HARDWARE_H

#include <avr/io.h>       // библиотека I/O
#include <util/delay.h>   // библиотеки пауз
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "structures.h"


#define SetBit(port,bit) port |=  _BV(bit)
#define ClrBit(port,bit) port &= ~_BV(bit)
#define Port4Out(port,bit) port |=  _BV(bit)
#define Port4Inp(port,bit) port &= ~_BV(bit)
#define GetState(port,bit) (port & (1<<bit))
#define Nop() __asm__ __volatile__ ("nop" ::)

#define HiBYTE(w) (uint8_t)((w >> 8) & 0x00ff)
#define LoBYTE(w) (uint8_t)((w >> 0) & 0x00ff)
//#define HiBYTE(w) (unsigned char)((w >> 8) & 0x00ff)
//#define LoBYTE(w) (uint8_t)((w >> 0) & 0x00ff)

#define RCVPCH1    38000    //частота 1-й ПЧ
#define RCVPCH2    10700    //частота 2-й ПЧ
#define POWER_DOWN 0x60     //бит для перевода процессора в сон

#define LC72131_Port_ini    DDRA  //настройка порта  LC72131
#define LC72131_Port        PORTA
#define LC72131_IN          PINA
#define CE                  PA5   //пин CE LC72131
#define DI                  PA4   //пин DI LC72131
#define CL                  PA3   //пин CL LC72131
#define DO                  PA2   //пин DO LC72131
#define I2C_Port_ini     DDRC     //настройка порта  I2C KSH148
#define I2C_Port         PORTC 
#define I2C_BitClc       PC0      //пин SCL KSH148
#define I2C_BitDat       PC1      //пин SDA KSH148
#define NFMWFM_Bit       PC3      //пин переключения NFM_WFM TA2008
#define NFMWFM_Port      PORTC    
#define NFMWFM_Port_ini  DDRC
#define FMMUTE_Bit       PC4      //пин включения FMMUTE
#define FMMUTE_Port      PORTC
#define FMMUTE_Port_ini  DDRC
#define POWER_Bit        PD7
#define POWER_Port_ini   DDRD
#define POWER_Bit        PD7
#define BUT_Port_ini     DDRC
#define BUT_Port         PORTC
#define BUT_M_Bit        PC6  //кнопка режим
#define BUT_S_Bit        PC7  //кнопка шаг
#define BUT_IN           PINC 
#define PWM_Port_ini     DDRD
#define APU_M_Bit        PD4  //управление шумодавом
#define AGC_S_Bit        PD5  //управление АРУ

unsigned char GetBit(unsigned char port_in, unsigned char bit)
{ 
   return  port_in&_BV(bit);
}

void port_init(void)
{
 /*PORTB = 0x00;
 DDRB  = 0x2F;
 PORTC = 0x00; //m103 output only
 DDRC  = 0x3F;
 PORTD = 0x00;
 DDRD  = 0xC0;*/
 
 DDRC  = 0x1F;
 PORTC = 0x18; //m103 output only
 PORTA = 0x00;
 DDRA  = 0x38;
 PORTB = 0x00;
 DDRB  = 0xBF;
 PORTD = 0x00;
 DDRD  = 0x00;
 
 Port4Out(PWM_Port_ini, APU_M_Bit);
 Port4Out(PWM_Port_ini, AGC_S_Bit);
 
 Port4Out(LC72131_Port_ini, CE);
 Port4Out(LC72131_Port_ini, DI);
 Port4Out(LC72131_Port_ini, CL);
 Port4Inp(LC72131_Port_ini, DO);
	
 Port4Out(I2C_Port_ini,I2C_BitClc); // I2C clc -> Out
 Port4Out(I2C_Port_ini,I2C_BitDat); // I2C dat -> Out

 SetBit(I2C_Port,I2C_BitClc);  // Init I2C
 SetBit(I2C_Port,I2C_BitDat);
 
 Port4Out(NFMWFM_Port_ini,NFMWFM_Bit);
 SetBit(NFMWFM_Port,NFMWFM_Bit);
 
 Port4Out(FMMUTE_Port_ini,FMMUTE_Bit);
 ClrBit(FMMUTE_Port,FMMUTE_Bit); 
 
 //кнопки Режим и Шаг
 Port4Inp(BUT_Port_ini, BUT_M_Bit);
 Port4Inp(BUT_Port_ini, BUT_S_Bit);
}

//SPI initialize
// clock rate: 5000000hz
void spi_init(void)
{
 //SPCR = 0xD0; //setup SPI
 SPCR = 0x50; //(1<<SPE)|(1<<MSTR)|(1<<SPR0);//0x50;
 SPSR = 0x00; //setup SPI
}

//////////////////
void UapuB_Out(unsigned char Uapu)
{
   OCR1B = Uapu;
}

//////////////////
void UapyA_Out(unsigned char Uapy)
{
   OCR1A = Uapy;
}

//АЦП тим = 104мкс
void adc_init(unsigned char channel)
{
 ADCSRA  = 0x00;         //disable adc
 ADMUX   = 0xC0;         //внутренний 2.56В
 ADMUX  |= channel;      // select adc input 6 
 _delay_us(10);
 //ADCSRA  = 0xED;
 ADCSRA = (1<<ADEN)|(0<<ADSC)|(0<<ADATE)|(0<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);  
}

//АЦП тим = 104мкс
void adc_init_irq(unsigned char channel)
{
 ADCSRA  = 0x00;         //disable adc
 ADMUX   = 0xC0;         //внутренний 2.56В
 //ADMUX  |= channel;      // select adc input 6 
 ACSR  = 0x80; 
 ADCSRA  = 0xED; 
}


int adc_read(void)
{
   int adc;
   
   ADCSRA |= (1 << ADSC); //Начинаем преобразование
   while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования 
   ADCSRA |= 0x10;  
   adc     = ADCL;            //Read 8 low bits first (important)
   adc    |= (int)ADCH << 8; //read 2 high bits and shift into top byte  
   return adc;
}

//TIMER0 опрос 100Гц
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x64; //set count
 OCR0  = 0x9C; //set compare
 TCCR0 = 0x05; //start timer
}

void timer0_stop(void)
{
  TCCR0 = 0x00;
}


//TIMER2 initialize - prescale:1024
// WGM: Normal
// desired value: 5000Hz
// actual value: 5208,333Hz (4,0%)
void timer2_init(void)
{
 TCCR2 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT2 = 0xFD; //setup
 OCR2  = 0x03;
 TCCR2 = 0x07; //start
}


void timer2_stop(void)
{
  TCCR2 = 0x00; //stop
}


//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 cli();          //disable all interrupts
 port_init();
 spi_init(); 
 //adc_init(6);
 //adc_init_irq(0);
 timer0_init();
 timer2_init();
 
 TCCR1A = 0B10100001; // Timer1 is duble 8-bit PWM
 TCCR1B = 0B00000001; // Timer1 running on MCU clock / 1  
 
 OCR1A = 255;         // set PWM1 value
 OCR1B = 255;          // set PWM2 value
 
 MCUCR = 0x03;
 GICR  = 0x00;
 TIMSK = 0x41;  //timer interrupt sources
 sei();         //re-enable interrupts
 //all peripherals are now initialized
}

void disable_encoderIRQ(void)
{
   GICR  &= ~0x40;
}

void enable_encoderIRQ(void)
{
   GICR  |= 0x40;
}

void Go_To_Sleep(void)
{
   timer0_stop();
   timer2_stop();
   enable_encoderIRQ();
   MCUCR |= POWER_DOWN;
   //asm("sleep");
   //asm("nop");
}

void Go_To_WakeUp(void)
{
   timer0_init();
   timer2_init();
}

//-----------------------------I2C----------------------------//

void I2CStart(void)
{
     SetBit(I2C_Port,I2C_BitClc);
     SetBit(I2C_Port,I2C_BitDat);

    _delay_us(10);
     ClrBit(I2C_Port,I2C_BitDat);

    _delay_us(10);
     ClrBit(I2C_Port,I2C_BitClc);
}

//////////////////
void I2CStop(void)
{
     ClrBit(I2C_Port,I2C_BitDat);
     SetBit(I2C_Port,I2C_BitClc);

    _delay_us(10);
     SetBit(I2C_Port,I2C_BitDat);
}

//////////////////
void I2CSync(void)
{
    _delay_us(10);
     SetBit(I2C_Port,I2C_BitClc);

    _delay_us(10);
     ClrBit(I2C_Port,I2C_BitClc);
}

//////////////////////////
void I2COutByte(uint8_t c)
{
  uint8_t i;

    for(i=0; i < 8; i++)
    {

      if(c & 0x80)
	       SetBit(I2C_Port,I2C_BitDat);
      else
	       ClrBit(I2C_Port,I2C_BitDat);
 
	    I2CSync();

	    c <<= 1;
    }
    I2CSync(); // ASK
    return;
}


#endif