#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>

/* RFM12B INTERFACE */
#define SCK 5 // SPI clock
#define SDO 4 // SPI Data output (RFM12B side)
#define SDI 3 // SPI Data input (RFM12B side)
#define CS 2 // SPI SS (chip select)
#define NIRQ 2 // (PORTD)
/* IO CONTROL */
#define HI(x) PORTB |= (1<<(x))
#define LO(x) PORTB &= ~(1<<(x))
#define WAIT_NIRQ_LOW() while(PIND&(1<<NIRQ))
/* LED */
#define LED 6
#define LED_OFF() PORTD &= ~(1<<LED)
#define LED_ON() PORTD |= (1<<LED)

void delay_ms(uint16_t ms) 
{
        while ( ms ) 
        {
                _delay_ms(1);
                ms--;
        }
}

void portInit() {
	HI(CS);
	HI(SDI);
	LO(SCK);
	DDRB = (1<<CS) | (1<<SDI) | (1<<SCK);
	DDRD = (1<<LED);
	DDRB &= ~(1<<PB0);// | (1<<PB1)); // This sets PB0/1  to an input
	PORTB |= (1<<PB0);// | (1<<PB1); // This enables the pullup on port B pin 0/1
}

unsigned int writeCmd(unsigned int cmd) {
	unsigned char i;
	unsigned int recv;
	recv = 0;
	LO(SCK);
	LO(CS);
	for(i=0; i<16; i++) {
		if(cmd&0x8000) HI(SDI); else LO(SDI);
		HI(SCK);
		recv<<=1;
		if( PINB&(1<<SDO) ) {
			recv|=0x0001;
		}
		LO(SCK);
		cmd<<=1;
	}
	HI(CS);
	return recv;
}

void rfInit() {
	writeCmd(0x80D7); //EL,EF,433band,12.0pF
	writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
	writeCmd(0xA640); //frequency select
	writeCmd(0xC647); //4.8kbps
	writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
	writeCmd(0xC2AC); //AL,!ml,DIG,DQD4
	writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR
	writeCmd(0xCED4); //SYNC=2DD4 , AG
	writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
	writeCmd(0x9850); //!mp,90kHz,MAX OUT
	writeCmd(0xCC17); //OB1 , ACOB0, LPX,Iddy,CDDIT,CBW0
	writeCmd(0xE000); //NOT USED
	writeCmd(0xC800); //NOT USED
	writeCmd(0xC040); //1.66MHz,2.2V
}

void rfSend(unsigned char data)
{
	WAIT_NIRQ_LOW();
	writeCmd(0xB800 + data);
}

uint16_t man_encode(int unenc) {
    uint8_t odd_byte,even_byte,temp;

    odd_byte=unenc&0xAA;
    temp=(~unenc&0xAA)>>1;
    odd_byte=odd_byte|temp;

    even_byte=unenc&0x55;
    temp=(~unenc&0x55)<<1;
    even_byte=even_byte|temp;
    return((uint16_t)odd_byte<<8)|even_byte;
}

int main() {
	volatile unsigned int button_state;
	unsigned int adc_value; // Variable to hold ADC result
	
	ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
    // ADEN: Set to turn on ADC , by default it is turned off 
    //ADPS2 and ADPS0 set to make division factor 32 
    ADMUX=0x45; // ADC input channel set to PC5
   
	uint8_t encoded=0xFF;
	uint8_t mot_pot=0x00;
	
	int i,j,k;
	k=0;
	button_state = 0;
	asm("cli");
	for(i=0;i<1000;i++)for(j=0;j<123;j++);
	portInit();
	rfInit();

	while(1){
		mot_pot = 0x00;
		
		/*---------read motor speed input-------*/
		ADMUX=0x45; // ADC input channel set to PC5
		ADCSRA |= (1<<ADSC); // Start conversion
        while (ADCSRA & (1<<ADSC)); // wait for conversion to complete
        //adc_value = ADCW; //Store ADC value
		mot_pot |= ADCW / 34; //1023/34 = 30 max mot speed nem lehet nagyobb mint 31 (5 bit)
		/*-------------------------------------*/

		/*---------read direction input-------*/
		ADMUX=0x44; // ADC input channel set to PC4
		ADCSRA |= (1<<ADSC); // Start conversion
        while (ADCSRA & (1<<ADSC)); // wait for conversion to complete
        if(ADCW < 300) //left
		{
			mot_pot |= 0b00100000;
		}
		else
		{
			if(ADCW > 700)//right
			{
				mot_pot |= 0b01000000;
			}
		}
		/*-------------------------------------*/
		
		/*----------read button state----------*/
		if (!(PINB & (1<<PB0))){ //pressed (PB0 set to hight, if btn pressed it is low)
			mot_pot |= 0b10000000;
		}
		/*-------------------------------------*/
		
		
		writeCmd(0x0000);
		rfSend(0xAA); // PREAMBLE
		rfSend(0xAA);
		rfSend(0xAA);
		rfSend(0x2D); // SYNC
		rfSend(0xD4);

		//encoded=man_encode(mot_pot)>>8;
		//rfSend(encoded);
		//encoded=man_encode(mot_pot);
		//rfSend(encoded);
		rfSend(mot_pot);
		
		k++;
		if(k==100){
			LED_ON();
		}
		if(k==200){
			LED_OFF();
			k=0;
		}

	}
}
