/*
** ===================================================================
** Název souboru   : Mbile_unit.c
** Mikrokontroler  : ATmega16,...
** Popis           : Program pro ovladani Mobilni jednotky
**                 :  
** Autor           : Jan Kristel (kristel_ml@volny,cz)
**                 : xx.04.2014
** ===================================================================
*/

#define AVR_ATmega16A
#define F_CPU 8000000UL

#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h> 
#include <stdio.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include "Mobile_unit.h"	
#include "jk_xtea.h"

     
#define LED 5
//#define LED_2 5
#define PWR 3
#define kl 1 // jen na test
//----PORTD---
#define SL 2  // MCP2030
#define CS 7
#define RSII 7 //PORTA7 
#define LFDATA 0 //PORT0 

//-----------------

#define AFE_WRITE_COMMAND   7


//---------------promene------------
volatile unsigned char buffer_0[15]; // na seriak
volatile unsigned char buffer_USART_tx[6];

unsigned char temp = 0;
volatile uint8_t i;
volatile int flag0 = 0;

//*************** ID tohoto Tagu ***************
unsigned char ID_mobile_tag [4] = {'8', '8', '5', '8' };  // |verze|ID| 
//**********************************************

unsigned char rx_base_data [8];
unsigned char rx_base_data_k [3]  = {'w', 'a', 'k'}; // inicializacni hodnota

//-----------------------------

volatile unsigned long  key_enc[4] = {1234,7766,1234,2233};
volatile unsigned char  buffer_enc [6];

//============== Funkce pro konfihuraci MCP2030 ===============

void AFE_WriteByte(uint8_t byte) {
    
	// Temp varaiables
    uint8_t Position = 0;
    uint8_t ByteValue = byte;
	volatile uint8_t AFE_DATA_LAT = 0;
    // Write byte to AFE
    for (Position = 0; Position < 8; Position++) {
         AFE_DATA_LAT = ((ByteValue >> (uint8_t) (7 - Position)) & 0x01);
        
		if (AFE_DATA_LAT == 1)  // nastavuje bit po bitu podle slova
        {
	   PORTD |= (1 << LFDATA);
        }
		else
		{
	   PORTD &= ~ (1 << LFDATA);
		}			
			
	   _delay_ms(10); //asm("nop");
       PORTD  |= (1 << SL); //AFE_CLOCK_LAT = 1;  
        _delay_ms(10);
       PORTD  &= ~ (1 << SL);  //AFE_CLOCK_LAT = 0;
    }
}

void AFE_WriteCommand(uint8_t command) {
    // Select AFE chip for SPI communication
    DDRD  |= (1 << CS); // AFE CS TRIS vystup
	DDRD  |= (1 << SL); //AFE_CLOCK_TRIS = 0; // AVR vystupni log1
    PORTD &= ~ (1 << SL);//AFE_CLOCK_LAT = 0;  
    PORTD &= ~ (1 << CS);// AFE_CS_LAT = 0;  
    DDRD  |= (1 << LFDATA);// AFE_DATA_TRIS = 0
 
    // Send Command Byte
    AFE_WriteByte((uint8_t) ((command & 0x07) << 5));
    //Write dummy byte required by specs
    AFE_WriteByte(0x00);
    // Deselect AFE chip
     
    PORTD &= ~ (1 << SL); //AFE_CLOCK_LAT = 0;
    DDRD  |= (1 << SL); //AFE_CLOCK_TRIS = 0;
	PORTD  |= (1 << CS); //AFE_CS_LAT = 1;
	DDRD  &= ~ (1 << LFDATA);/// AFE_DATA_TRIS = 1;
	DDRD  &= ~ (1 << SL);//AFE_CLOCK_TRIS = 1; // avr vstup naopak
   
}

void AFE_WriteRegister(uint8_t address, uint8_t data) {
 /** Setup AFE into LFDATA mode by custom setup
   * @param byte(0-6) - AFE Register 0 - 6 setup */

	// Temp variables
    uint8_t position = 0,
            parity = 0,
            temp = 0,
            afeData1 = 0,
            afeData0 = 0;
    // prepare parity bit
    parity = 1;
    // Calculate the parity bit
    for (position = 0; position < 8; position++) {
        temp = (uint8_t) (data >> position);
        parity ^= temp;
    }
    // prepare data
    afeData1 = (uint8_t) ((AFE_WRITE_COMMAND << 5) | (address << 1) | temp);
    afeData0 = (uint8_t) (data << 1 | (parity & 0x01));
    // Select AFE chip for SPI communication
    DDRD  |= (1 << CS); // vystup
	DDRD  |= (1 << SL); //AFE_CLOCK_TRIS = 0; // AVR vystupni log1
    PORTD &= ~ (1 << SL);//AFE_CLOCK_LAT = 0;  
    PORTD &= ~ (1 << CS);// AFE_CS_LAT = 0;  
    DDRD  |= (1 << LFDATA);// AFE_DATA_TRIS = 0
      
   // AFE_CLOCK_TRIS = 0;
   // AFE_CLOCK_LAT = 0;
   // AFE_CS_LAT = 0;
   // AFE_DATA_TRIS = 0;
    
	// Write Address and Data
    AFE_WriteByte(afeData1);
    AFE_WriteByte(afeData0);
    // Deselect AFE chip
  
    PORTD &= ~ (1 << SL); //AFE_CLOCK_LAT = 0;
    DDRD  |= (1 << SL); //AFE_CLOCK_TRIS = 0;
	PORTD  |= (1 << CS); //AFE_CS_LAT = 1;
	DDRD  &= ~ (1 << LFDATA);/// AFE_DATA_TRIS = 1;
	DDRD  &= ~ (1 << SL);//AFE_CLOCK_TRIS = 1; // avr vstup naopak
	
	//AFE_CLOCK_LAT = 0;
    //AFE_CLOCK_TRIS = 0;
   // AFE_CS_LAT = 1;
   // AFE_DATA_TRIS = 1;
   // AFE_CLOCK_TRIS = 1;
}


//**********INIT****************

void init()
{
_delay_ms(1000);


//- pzn. musi se nastavit driv nez USART	
//*************init MCP2030********
//                 reg,  bity,
//AFE_WriteCommand (0b011);//	soft reset

AFE_WriteRegister(0x00, 0b11110000); //TOEH = 4ms  TOEL = 4ms
//AFE_WriteRegister(0x01, 0b00000000);
AFE_WriteRegister(0x05, 0b00010000);	// 8% hloubka modulace
//AFE_WriteCommand (0b101);	
//*********************************

//******inicializace USART*********
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 1200
UCSRA=0x00;
UCSRB |= (1<<RXEN);//|(1<<RXCIE);//|(1<<TXEN);
//--UCSRC=0x86;
UBRRH=0x01;
UBRRL=0xA0;
//**************************** /
    	 
//TCCR0  |= (1<<CS02); //nastavi preddelicku na 256
//TIMSK  |= (1<<TOIE0); // povoli preruseni pri preteceni 

DDRA =  0b00100000; //LED PA5 OUT
DDRC =  0b00001000; //PWR - IO  PC3 OUT
DDRD =  0b00000010; //
PORTD = 0b00000000; 

//----init----
MCUCR |= (1<<ISC10); // any LOG
GICR  |= (1<<INT2); // enable INT1
GIFR = 0x00;

// -- mozna kvuli prog
PORTC |= (1<<PWR);  // vypni napajeni mod. IO -  LOG "1"
PORTD  &= ~(1<<kl); // TXD do LOG "0"

sei();

for (uint8_t i=0; i<5; i++)  // indikace zapnuti
{
 PORTA |= (1<<LED);
 _delay_ms(50);
 PORTA &= ~(1<<LED);
 _delay_ms(50);
}
}

//********* USART - RX *************
unsigned char USART_receive(void){
  	while(1)
	{
	  if(bit_is_set(UCSRA,RXC))   
	    {
	     return(UDR);
	    }
		return(0);
	}
}

unsigned char USART_receive_char(void){
	//cte 4 znaky
uint8_t y = 1;
	
  	for (uint8_t x = 0 ; x<4; x++)
	{
	 y = 1;
	 	
	 while( y == 1 )
	 {
	  if(bit_is_set(UCSRA,RXC)) //je li RXC plny zkopiruj data do temp   
	    {
	  rx_base_data [x] = UDR;   //
	   y = 0 ; 
	    }
	 }	  	
	}
}

void USART_send( unsigned char data){
	 
 while(!(UCSRA & (1<<UDRE)));
	 UDR = data;
}

void USART_putstring(volatile char* StringPtr){
		  
	 while(*StringPtr != 0x00){
	 USART_send(*StringPtr);
	 StringPtr++;}
}


//*******************TX_SEND************

void TX_send()
{
	
	 PORTC  &= ~(1<<PWR); // napajeni ostatnich IO	 
	 UCSRB |= (1<<TXEN);  // povoli TX UART
	 _delay_ms(50);	//
     sprintf ( buffer_0 , "xxx"); //
     USART_putstring(buffer_0);
   
    // zasifruj ID
     encode(buffer_enc, ID_mobile_tag, key_enc, EE_SHIFT_0);
    
    // posli @ start|encr. ID 6bytu|kocnovy znak|  
    sprintf ( buffer_0 , "@" ); //
    USART_putstring(buffer_0);
	
    sprintf ( buffer_0 , buffer_enc );
	USART_putstring(buffer_0);
	
    sprintf ( buffer_0 , "x+++" );
	USART_putstring(buffer_0);
	
     UCSRB &= ~ (1<<TXEN);  // TX UART // kvuli radeji kvuli proudum
	PORTC |= (1<<PWR); // vypni log "1"	
}

void RX_Data()
{
//------------RX Data-----------

 unsigned int temp = 0;  // puvodne char!!
 
 uint8_t flag = 0;
 
 for (i = 0 ; i < 200 ; i++ )  //smycka ceka 5 sec na prichozi znak kdyz ne - vdal jed problem
 {
 
  temp = USART_receive();  // testuje prichozi znak
   
  if (temp == '*')// ceka na synch znak
   {
   USART_receive_char(); // prijmi cely string
   i = 220 ; 
      
   }
   else 
   {
    _delay_ms(10);  //kvuli obvodum	   
   }

   
 }	


//---------porovnani prichozich dat--------
   
   for (uint8_t i = 0 ; i<2; i++)
  { 		  
  
	 if ( rx_base_data [i] == rx_base_data_k [i]) 
	 {
	  flag = 1; 
    
	 } 
    else
	 {
	  flag = 0; // nevyhovel 
	 }
  }

 //-------------odpoved - kdyz vzhovy------
   if(flag == 1)  // vyhovuji data proved
  {
	    
	TX_send();
	
	
  // po odeslani zrusi pole	rx_base_data
  	   rx_base_data[1] = "x"; // zneplatni 	
//-------------pro ladeni------
		 
     PORTA |= (1<<LED);  // blikne
  	 _delay_ms(100);
     PORTA  &= ~(1<<LED);
  //  _delay_ms(50);
   //  PORTA |= (1<<LED);
	_delay_ms(1000);
    // PORTA  &= ~(1<<LED);

    } 
	
// --- po odeslani povoli preruseni a zhodi priznak	

}

void sleep_now()
{
     //fce uspani MCU  
	 MCUCR|=(1<<SM1);// Power down     
     MCUCR|=(1<<SE);// Sleep enable
     asm volatile ("sleep"::); 
}

ISR(INT2_vect) 
{
//PORTA |= (1<<LED);  // ladeni
// disable sleep - wake up!
GICR  &= ~(1<<INT2); // disable INT2  
MCUCR &= ~(1<<SE);// Sleep disable 
GIFR=0x00;

RX_Data(); // prijme data

GICR  |= (1<<INT2);  // enable
GIFR=0x00;
//PORTA  &= ~(1<<LED);
}

int main(void)
{
  init();
	
	while(1)
    {
     sleep_now(); // hlavni program pouze uspava	
    }
}

