/*****************************************************
Chip type               : ATmega88P
AVR Core Clock frequency: 13,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/



#define DDR_SS DDRB
#define DDR_SCK DDRB
#define DDR_MOSI DDRB
#define PORT_SS PORTB
#define PORT_SCK PORTB
#define PORT_MOSI PORTB
#define PIN_MISO PINB
#define PIN_IRQ PIND
#define SS 2
#define SCK 5
#define MOSI 3
#define MISO 4
#define IRQ 2

#include <mega88p.h>
#include <stdlib.h>
#include <delay.h>


#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE0 32
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0<256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow0;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer0[rx_wr_index0]=data;
   if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
   if (++rx_counter0 == RX_BUFFER_SIZE0)
      {
      rx_counter0=0;
      rx_buffer_overflow0=1;
      };
   };
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0];
if (++rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

// Standard Input/Output functions
#include <stdio.h>

#define ADC_VREF_TYPE 0x60

// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}

// rf модуль

unsigned char data_rf,rfxx_flag=1;
unsigned int status_rf;
unsigned int RFXX_WRT_CMD(unsigned int aCmd) //Отправить команду
{
unsigned char i;
unsigned int temp=0;
PORT_SCK&=~(1<<SCK);
PORT_SS&=~(1<<SS);
for(i=0;i<16;i++)
   {
   if(aCmd&0x8000) PORT_MOSI|=(1<<MOSI);
   else PORT_MOSI&=~(1<<MOSI);
   PORT_SCK|=(1<<SCK);
   temp<<=1;
   if(PIN_MISO&(1<<MISO)) temp|=0x0001;
   PORT_SCK&=~(1<<SCK);
   aCmd<<=1;
   }
PORT_SS|=(1<<SS);
return(temp);
}

void RF12_SEND(unsigned char aByte)
{
while(!(RFXX_WRT_CMD(0x0000)&0x8000));
RFXX_WRT_CMD(0xB800+aByte);
}

void RF12_INIT(void) //Инициализация
{
DDR_SS|=(1<<SS);
DDR_SCK|=(1<<SCK);
DDR_MOSI|=(1<<MOSI);
PORT_SS|=(1<<SS);
while (!PIND.2) RFXX_WRT_CMD(0x0000);

RFXX_WRT_CMD(0x80E7);//EL,EF,868band,12pF
RFXX_WRT_CMD(0x8219);//!er,!ebb,!ET,ES,EX,!eb,!ew,DC
RFXX_WRT_CMD(0xA640);//=868MHz
RFXX_WRT_CMD(0xC647);//06->57.6kbps 47->4.8kbps
RFXX_WRT_CMD(0x94C0);//VDI,FAST,67kHz,0dBm,-103dBm
RFXX_WRT_CMD(0xC2AC);//AL,!ml,DIG,DQD4
RFXX_WRT_CMD(0xCAB0);//FIFO11,SYNC,!ff,DR
RFXX_WRT_CMD(0xC4F3);//@PWR,NO RSTRIC,!st,!fi,OE,EN
RFXX_WRT_CMD(0x9820);//!mp,45kHz,MAX OUT
RFXX_WRT_CMD(0xCC07);
RFXX_WRT_CMD(0xE000);//NOT USE
RFXX_WRT_CMD(0xC800);//NOT USE
RFXX_WRT_CMD(0xC000);//1MHz,2.2V
}


// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
status_rf=RFXX_WRT_CMD(0x0000);
data_rf=(char)((RFXX_WRT_CMD(0xB000))&0x00FF);
rfxx_flag=0;
}

void fifo_reset(void)
  {
  RFXX_WRT_CMD(0xCAB0);
  RFXX_WRT_CMD(0xCAB2);
  } 
  
void RF12_tx_on(void)
  {
   RFXX_WRT_CMD(0x80E7);
   RFXX_WRT_CMD(0x8239);
  }
  
void RF12_rx_on(void)
  {
   RFXX_WRT_CMD(0x80E7);
   RFXX_WRT_CMD(0x8299);
   fifo_reset();
  }
  
unsigned char i,w0,w1,speed=0x10,sost=0x80,direct=0x10;
unsigned char inbuff[7],crc_in;

void rtx_pack (unsigned char ack)
  {
   unsigned char crc,ar1,ar2,ar3,ar4;
   ar1=read_adc(6);
   ar2=read_adc(0);
   ar3=read_adc(7);
   ar4=(PORTC&0b00111100)>>2;   
   
   crc=sost%0x31;
   crc=(crc+ar1)%0x31;
   crc=(crc+ar2)%0x31;
   crc=(crc+ar3)%0x31;
   crc=(crc+ar4)%0x31;
   crc=(crc+ack)%0x31;
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0x2D);//SYNC HI BYTE
  RF12_SEND(0xD4);//SYNC LOW BYTE
  RF12_SEND(0x6A);
  RF12_SEND(0x20);
  RF12_SEND(sost);
  RF12_SEND(ar1);
  RF12_SEND(ar2);
  RF12_SEND(ar3);
  RF12_SEND(ar4);
  RF12_SEND(ack);
  RF12_SEND(crc);
  RF12_SEND(0xAA);//DUMMY BYTE
  RF12_SEND(0xAA);//DUMMY BYTE
  };


void main(void)
{
// Declare your local variables here
 unsigned char temp;
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
PORTB=0x00;DDRB=0x2F;
PORTC=0x40;DDRC=0x3E;
PORTD=0x0D;DDRD=0xF2;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9,766 kHz
// Mode: Fast PWM top=FFh
// OC0A output: Non-Inverted PWM
// OC0B output: Non-Inverted PWM
TCCR0A=0xA3;TCCR0B=0x05;TCNT0=0x00;
OCR0A=0xA0;OCR0B=0x60;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 10000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Toggle
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x40;TCCR1B=0x09;TCNT1H=0x00;TCNT1L=0x00;
ICR1H=0x00;ICR1L=0x00;
OCR1AH=0x27;OCR1AL=0x10;
OCR1BH=0x00;OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Falling Edge
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x02;
EIMSK=0x01;
EIFR=0x01;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 57600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x06;  //115200--0x06,9600--0x54

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization
// ADC Clock frequency: 156,250 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: Free Running
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA6;
ADCSRB&=0xF8;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/256k
// Watchdog Timer interrupt: Off
#pragma optsize-
#asm("wdr")
WDTCSR=0x39;
WDTCSR=0x29;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Global enable interrupts
#asm("sei")
PORTC.5=1;delay_ms(200);PORTC.5=0;
//Инициализация FRM12
RF12_INIT();
          RF12_tx_on(); 
          delay_ms(5);
          rtx_pack (0x20);
          RF12_rx_on();

while (1)
      {    
          w0=0;w1=0;crc_in=0;
lb1:       while (!(data_rf==0x2D)) {rfxx_flag=1;};
           while (!(data_rf==0xD4)) {rfxx_flag=1;};
           while (!(data_rf==0x20)) {rfxx_flag=1;};
           while (!(data_rf==0x6A)) {rfxx_flag=1;};      // начало пакета
          
          while (rfxx_flag) {};
          inbuff[0]=data_rf,rfxx_flag=1,crc_in=inbuff[0]%0x31; 
          while (rfxx_flag) {};          
          inbuff[1]=data_rf,rfxx_flag=1,crc_in=(crc_in+inbuff[1])%0x31; 
          while (rfxx_flag) {}; 
          inbuff[2]=data_rf,rfxx_flag=1,crc_in=(crc_in+inbuff[2])%0x31;
          while (rfxx_flag) {};  
          inbuff[3]=data_rf,rfxx_flag=1,crc_in=(crc_in+inbuff[3])%0x31;
          while (rfxx_flag) {};  
          inbuff[4]=data_rf,rfxx_flag=1,crc_in=(crc_in+inbuff[4])%0x31;
          while (rfxx_flag) {};  
          inbuff[5]=data_rf,rfxx_flag=1,crc_in=(crc_in+inbuff[5])%0x31;
          while (rfxx_flag) {};                        
          inbuff[6]=data_rf,rfxx_flag=1; 
                                       
          if (!(inbuff[6]==crc_in)) goto lb1;  //конец пакета
          #asm("wdr") 
          
          // обработка пакета
          
          direct=inbuff[1];
          speed=inbuff[2];
          if (direct>=0x10) PORTD.7=0,PORTB.0=1;
          else PORTB.0=0,PORTD.7=1;
          PORTC&=~0x3C;
          PORTC|=(inbuff[3])<<2;
          if (speed>=0x10) PORTC.1=0,PORTD.4=1;
          else PORTD.4=0,PORTC.1=1; 
          OCR0A=((abs(0x10-direct))<<4)+1;OCR0B=((abs(0x10-speed))<<4)+1;
          sost=inbuff[0]+1; 
          
          // отправляем обратно телеметрию
          RF12_tx_on(); 
          delay_ms(5);
          rtx_pack (0x20);
          RF12_rx_on();
                    
     };
}
