#include "communication.h"

void setPORTC_LED(char LED_number)  //funkce slouzici pro debug
{   
    switch (LED_number)
    {
        case 0x00: PORTC = 0xFE; break;
        case 0x01: PORTC = 0xFC; break;
        case 0x02: PORTC = 0xF8; break;
        case 0x03: PORTC = 0xF0; break;
        case 0x04: PORTC = 0xE0; break;
        case 0x05: PORTC = 0xC0; break;    
        case 0x06: PORTC = 0x80; break;    
        case 0x07: PORTC = 0x00; break;    
        default: break;
    }
}   

char XBeeTransmitTestData (char * p_TestData, char count)  //posila data na USART1
{
    if(UCSR1A.6==1) //priznak vysilani dokonceno a v bufferu nejsou data k odeslani
    {
        UCSR1A.6=1; //nuluje se nastavanim do logicke 1
    };
       
    UDR1 = *(p_TestData + count);  //nacti do UDR znak 
    count++;
    if(count > 9)
    {
        count = 0;
    }
    while (UCSR1A.6==0)  //dokud neni vysilani dokonceno
    { 
    } 
    //priznak vysilani dokonceno zustava nastaven
    delay_ms(Wait_5ms);  //zpozdeni kvuli zpomaleni komunikace kvuli lepsimu debugu
    return count; 
}

char XBeeEnterCommandMode (void)  //vstup do Command modu
{
    delay_ms(Wait_2s);  //cekani GuardTime 1000 ms
    XBeeSendString (ENTER_COMMAND_MODE);  //vstup do command modu 
    SREG.7 = 1;  //globalni povoleni preruseni 
    delay_ms(Wait_1s);  //cekani GuardTime 1000 ms
    return 0x00;
}

void XBeeSetBaudRate (char * retezec, char baudRateXBee)
{
    char mem = baudRateXBee;
    switch (mem)
    {
        case 0x00: mem = '0'; break;
        case 0x01: mem = '1'; break;
        case 0x02: mem = '2'; break;
        case 0x03: mem = '3'; break;
        case 0x04: mem = '4'; break;
        case 0x05: mem = '5'; break;
        case 0x06: mem = '6'; break;
        case 0x07: mem = '7'; break;
        default: break;
    }
    *(retezec + 0) = 'A'; 
    *(retezec + 1) = 'T';
    *(retezec + 2) = 'B';
    *(retezec + 3) = 'D';
    *(retezec + 4) = ' ';
    *(retezec + 5) = mem;
    *(retezec + 6) = '\r';
    *(retezec + 7) = NULL;
}

void XBeeSetParity (char * retezec, char parityXBee)
{
    char mem = parityXBee;
    switch (mem)
    {
        case 0x00: mem = '0'; break; //zadna parita
        case 0x01: mem = '1'; break; //suda parita
        case 0x02: mem = '2'; break; //licha parita
        default: break;
    }
    *(retezec + 0) = 'A'; 
    *(retezec + 1) = 'T';
    *(retezec + 2) = 'N';
    *(retezec + 3) = 'B';
    *(retezec + 4) = ' ';
    *(retezec + 5) = mem;
    *(retezec + 6) = '\r';
    *(retezec + 7) = NULL;    
}

void XBeeSetUSARTParameters(char baudRateXBee, char parityXBee)
{
    
    SREG.7 = 0;  //zakaz preruseni globalne
    UCSR1B=0x00; // nastaveni hodnoty na 0b10011000 - preruseni od RXCIE, povolen vysilac a prijimac       
    
    switch(baudRateXBee)
    {
        case 0: UBRR1H = BAUDRATE1200H; UBRR1L = BAUDRATE1200L; break;
        case 1: UBRR1H = BAUDRATE2400H; UBRR1L = BAUDRATE2400L; break;
        case 2: UBRR1H = BAUDRATE4800H; UBRR1L = BAUDRATE4800L; break;
        case 3: UBRR1H = BAUDRATE9600H; UBRR1L = BAUDRATE9600L; break;
        case 4: UBRR1H = BAUDRATE19200H; UBRR1L = BAUDRATE19200L; break;
        case 5: UBRR1H = BAUDRATE38400H; UBRR1L = BAUDRATE38400L; break;
        case 6: UBRR1H = BAUDRATE57600H; UBRR1L = BAUDRATE57600L; break;
        case 7: UBRR1H = BAUDRATE115200H; UBRR1L = BAUDRATE115200L; break;
        default: break;
    }   
    
    /*//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NEFUNGUJE
    switch(parityXBee)
    {                                
        case 0: UCSR1C = (1<<URSEL1); break;  //zadna parita
        case 1: UCSR1C = (1<<URSEL1)|(1<<UPM11); break;  //suda parita
        case 2: UCSR1C = (1<<URSEL1)|(1<<UPM11)|(1<<UPM10); break;  //licha parita
        default: break;
    }                                                                                                            
    UCSR1C = UCSR1C & 0b01111111;  //vynulovani bitu URSEL    
    *///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NEFUNGUJE
                       
    UCSR1B=0x98; // nastaveni hodnoty na 0b10011000 - preruseni od RXCIE, povolen vysilac a prijimac
    delay_ms(10);   
    SREG.7 = 1;  //povoleni globalniho preruseni
              
}

void SensorSetUSARTParameters(char baudRateSensor, char paritySensor)
{
    SREG.7 = 0;  //zakaz preruseni globalne
    UCSR0B=0x00; // nastaveni hodnoty na 0b10011000 - preruseni od RXCIE, povolen vysilac a prijimac       
    
    switch(baudRateSensor)
    {
        case 0: UBRR0H = BAUDRATE1200H; UBRR0L = BAUDRATE1200L; break;
        case 1: UBRR0H = BAUDRATE2400H; UBRR0L = BAUDRATE2400L; break;
        case 2: UBRR0H = BAUDRATE4800H; UBRR0L = BAUDRATE4800L; break;
        case 3: UBRR0H = BAUDRATE9600H; UBRR0L = BAUDRATE9600L; break;
        case 4: UBRR0H = BAUDRATE19200H; UBRR0L = BAUDRATE19200L; break;
        case 5: UBRR0H = BAUDRATE38400H; UBRR0L = BAUDRATE38400L; break;
        case 6: UBRR0H = BAUDRATE57600H; UBRR0L = BAUDRATE57600L; break;
        case 7: UBRR0H = BAUDRATE115200H; UBRR0L = BAUDRATE115200L; break;
        default: break;
    }   
    
    /*//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NEFUNGUJE
    switch(parityXBee)
    {                                
        case 0: UCSR0C = (1<<URSEL0); break;  //zadna parita
        case 1: UCSR0C = (1<<URSEL0)|(1<<UPM01); break;  //suda parita
        case 2: UCSR0C = (1<<URSEL0)|(1<<UPM01)|(1<<UPM00); break;  //licha parita
        default: break;
    }                                                                                                            
    UCSR0C = UCSR0C & 0b01111111;  //vynulovani bitu URSEL    
    *///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NEFUNGUJE
                       
    UCSR0B=0x98; // nastaveni hodnoty na 0b10011000 - preruseni od RXCIE, povolen vysilac a prijimac
    delay_ms(10);   
    SREG.7 = 1;  //povoleni globalniho preruseni
}


char XBeeSendString (char * string)  //funkce posilajici string na port XBee
{
    char count = 0;
    if(UCSR1A.6==1) //priznak vysilani dokonceno
    {
        UCSR1A.6=1; //nuluje se nastavanim do logicke 1
    };
    while (*(string + count) != NULL)  //dokud neni znak ve stringu roven NULL
    {
        UDR1 = *(string + count);  //nacti do UDR znak
        count++;
        while (UCSR1A.6==0)  //dokud neni vysilani dokonceno
        { 
        }
        if(*(string + count) != NULL)  //necha nastaven priznak vysilani dokonceno po ukonceni prenosu dat
        {
            UCSR1A.6=1;  //vynuluj priznak vysilani dokonceno       
        }
    };  
    return 0x00;
}

char XBeeUdrRecieve (void)  //cte hodnotu prijatych dat jednotkou USART1
{
    return UDR1;
}

char SensorUdrRecieve (void)  //cte hodnotu prijatych dat jednotkou USART1
{
    return UDR0;
}

void XBeeUsartRecieve(char * p_programMemory, char * p_switchMemory, char * p_baudRateXBee, char * p_parityXBee, char * p_baudRateSensor, char * p_paritySensor, char * p_memory, char * p_stackForSensor, char * p_countStackForSensor)
{
    char symbol;
    symbol = XBeeUdrRecieve();      
    
    if(*(p_programMemory) < 6)
    {
        XBeeUsartRecieveConfirm(p_programMemory, p_switchMemory, p_memory, symbol);    
    }                                  
    else
    {
        XBeeUsartRecieveData(p_programMemory, p_switchMemory, p_baudRateXBee, p_parityXBee, p_baudRateSensor, p_paritySensor, p_stackForSensor, p_countStackForSensor, symbol);
    }
}

void XBeeUsartRecieveConfirm(char * p_programMemory, char * p_switchMemory, char * p_memory, char symbol) 
{
    if(*(p_programMemory)<6)  //probiha nastaveni parametru komunikace XBee
    {
        switch (symbol)
        {
            case 'O': (*(p_memory))++; break;  //XBee modul odpovi "O"
            case 'K': (*(p_memory))++; break;  //XBee modul odpovi "K"
            case 'E': (*(p_memory))++; break;  //XBee modul odpovi "E"
            case 'R': (*(p_memory))++; break;  //XBee modul odpovi "R"
            case 0x0D:                  //XBee modul odpovi "\r"   
            {   
                if(*(p_memory) == 2)  //je v poradku odpovezeno OK\r, program pokracuje dale
                {
                    (*(p_programMemory))++;
                    (*(p_switchMemory)) = (*(p_programMemory));
                    *(p_memory) = 0; 
                }   
                else  //prisla odpoved ERROR\r, program XBee bude restartovan
                {         
                    PORTC = 0xFF;                
                    delay_ms(Wait_5s);     
                    PORTC = 0x00;
                    delay_ms(Wait_5s);   
                    PORTC = 0xFF;
                    *(p_programMemory) = 0x01;
                    *(p_switchMemory) = 0x01;
                }                   
                break;
            }
            default: break;
        } 
        if(*(p_programMemory) == 1)
        {
            
        }  
        else if(*(p_programMemory) == 2)
        {
            setPORTC_LED(0x01);
        }  
        else if(*(p_programMemory) == 3)
        {   
            setPORTC_LED(0x02);
        }  
        else if(*(p_programMemory) == 4)
        {      
            setPORTC_LED(0x03);
        }  
        else if(*(p_programMemory) == 5)
        {                          
            setPORTC_LED(0x04);
        }  
        else if(*(p_programMemory) == 6)
        {                                                   
            setPORTC_LED(0x05);
            *(p_switchMemory) = 0x00;  //nicdelajici cykus
        }        
    }
}
 
void XBeeUsartRecieveData(char * p_programMemory, char * p_switchMemory, char * p_baudRateXBee, char * p_parityXBee, char * p_baudRateSensor, char * p_paritySensor, char * p_stackForSensor, char * p_countStackForSensor, char symbol)
{
    switch(*(p_programMemory))
    {
        case 0x06: //resime zda-li prisla hlavicka, nahrada za znak hlavicky nebo data  
        {                              
            if(symbol == 0xBB)  //prisla nahrada 0xAA nebo 0xBB
            {                         
                *(p_switchMemory) = 0x00;  //nicdelajici cyklus
                *(p_programMemory) = 0x10;  //hodnota vyhodnocujici dalsi krok
            } 
            else if(symbol == 0xAA)  //prisla hlavicka
            { 
                *(p_switchMemory) = 0x00;  //nicdelajici cyklus
                *(p_programMemory) = 0x11;  //hodnota vyhodnocujici dalsi krok 
            }    
            else 
            {
                //odesli na vystup nynejsi znak symbol
                SaveToStackForSensor(symbol, p_stackForSensor, p_countStackForSensor);
            }
            break;     
        }  
    
 
        case 0x10:  //resime jestli prisla nahrada za 0xAA nebo za 0xBB
        {
            if(symbol == 0x55)  //byla to nahrada 0xBB znaky 0xBB55
            {
                //na vystup odesli 0xBB  
                SaveToStackForSensor(0xBB, p_stackForSensor, p_countStackForSensor);
            }      
            else  //byla to nahrada za 0xAA znakem 0xBB
            {
                //byla to nahrada 0xAA, na vystup odesli 0xAA a nynejsi znak symbol 
                SaveToStackForSensor(0xAA, p_stackForSensor, p_countStackForSensor);
                SaveToStackForSensor(symbol, p_stackForSensor, p_countStackForSensor);
            } 
            *(p_programMemory) = 0x06;  //dalsi krok zavisi na hodnote symbol 
            break;
        }  
     
        case 0x11:  //prisla hlavicka a resime co dal 
        {
            if(symbol == 0x01)  //nastaveni USART0
            {
                *(p_programMemory) = 0x20;  
                //XBeeSendString("Prenastavuji USART pripojeny k senzoru.");
            }                                    
            else if(symbol == 0x02) //nastaveni USART1
            {
                *(p_programMemory) = 0x30;  
                //XBeeSendString("Prenastavuji USART pripojeny k XBee.");
            }  
            else if(symbol == 0x03)  //zapnuti/vypnuti LED diod
            {
                *(p_programMemory) = 0x40;
                //XBeeSendString("Menim nastaveni LED diod.");
            }  
            else if(symbol == 0x04)  //posilej/neposilej testovaci data
            {
                *(p_programMemory) = 0x50;
            }
            else if(symbol == 0x05)  //posilej/neposilej data ze senzoru prijatych v USART
            {
                *(p_programMemory) = 0x60;
            }                 
            else if (symbol == 0x06)
            {
                *(p_programMemory) = 0x70;  //posilej/neposilej data ze senzoru prijatych v SPI
            }                  
            else
            {
            }
            break;     
        }             
    
        case 0x20:  //prenastaveni USART0 pripojene k senzoru  
        {
            if(symbol <= 0x07) //nastaveni baudRate USART0 jednotky pripojene k senzoru, rozmezi hodnot je 0-7
            {                  
                *(p_baudRateSensor) = symbol;   
                *(p_programMemory) = 0x21;   
            }
            else
            {
               XBeeSendString("ERROR");
            } 
            break;
        } 
        case 0x21:  //prenastaveni USART0, parity  
        {
            if(symbol <= 0x02) //nastaveni parityXBee, rozmezi hodnot je 0-2
            {                  
                *(p_paritySensor) = symbol;
                SensorSetUSARTParameters(*(p_baudRateSensor), *(p_paritySensor));        
                XBeeSendString("OK");  //nastaveni probehlo v poradku
                *(p_programMemory) = 0x06;
            }
            else
            {
               XBeeSendString("ERROR");
            } 
            break;
        }  
        case 0x30:  //prenastaveni USART1 pripojene k XBee  
        {
            if(symbol <= 0x07) //nastaveni baudRate XBee, rozmezi hodnot je 0-7
            {                  
                *(p_baudRateXBee) = symbol;   
                *(p_programMemory) = 0x31; 
            }
            else
            {
               XBeeSendString("ERROR");
            } 
            break;
        } 
        case 0x31:  //prenastaveni USART1, parity  
        {
            if(symbol <= 0x02) //nastaveni parity XBee, rozmezi hodnot je 0-2
            {                  
                *(p_parityXBee) = symbol;
                PORTC = 0xFF;  //zhasnuti LED diod, roznou se po uspesnem nastaveni komunikace s XBee modulem   
                *(p_programMemory) = 0x01;
                *(p_switchMemory) = 0x01;     
            }
            else
            {
               XBeeSendString("ERROR");
            } 
            break;
        }
        case 0x40:  //rozinani/zhasinani LED diod
        {
            if(symbol == 0x00)
            {
                PORTC = 0x00;  //roznuti LED diod
                XBeeSendString("OK");
                *(p_programMemory) = 0x06;
            }   
            else
            {
                PORTC = 0xFF;  //zhasnuti LED diod
                XBeeSendString("OK");
                *(p_programMemory) = 0x06;
            } 
            break;
        }     
        case 0x50:
        {         
            if(symbol == 0x00)  //start posilani testovacich dat
            {
                XBeeSendString("OK");
                *(p_programMemory) = 0x06;
                *(p_switchMemory) = 0x06;
            }   
            else
            {   
                XBeeSendString("OK");  //konec posilani testovacich dat
                *(p_programMemory) = 0x06;
                *(p_switchMemory) = 0x00;
            } 
            break;
        }
        case 0x60:  //preposilani dat ze sensoru do PC pripojenemu k USART jednotce
        {      
            if(symbol == 0x00)  //posilej data ze senzoru prijatych v USART 
            {
                SREG.7 = 0;
                UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);   
                delay_ms(Wait_10ms);
                SREG.7 = 1;
                XBeeSendString("OK");
                *(p_programMemory) = 0x06;
            }              
            else  //neposilej data ze senzoru prijatych v USART 
            {
                SREG.7 = 0;
                UCSR0B = (0<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);   
                delay_ms(Wait_10ms);
                SREG.7 = 1;
                XBeeSendString("OK");
                *(p_programMemory) = 0x06;
            }
            break;
        }    
        case 0x70:  //preposilani dat ze senzoru do PC pripojenemu k SPI jednotce  
        {         
            if(symbol == 0x00)  //posilej data ze senzoru prijatych v SPI
            {                      
                SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR);  //povoleni preruseni a zapnuti SPI periferie 
                
            }
            else  //neposilej data ze senzoru prijatych v SPI
            {
                SPCR = (0<<SPIE)|(1<<SPE)|(1<<MSTR);  //zakaz preruseni a zapnuti SPI periferie  
            }      
            *(p_programMemory) = 0x71;
            break;
        } 
        case 0x71:
        {
            if(symbol == 0x00)  //posilej data v rezimu LSB
            {  
                SPCR = SPCR | (1<<DORD);
            }
            else  //posilej data v rezimu MSB
            {   
                //bit DORD = 0
            }   
            *(p_programMemory) = 0x72;
            break;
        }         
        case 0x72:
        {         
            if(symbol == 0x00)  //CPHA a CPOL = 0
            { 
            }
            else if(symbol == 0x01)  //CPHA = 0 a CPOL = 1
            {
                SPCR = SPCR | (1<<CPOL);
            }                      
            else if(symbol == 0x02)  //CPHA = 1 a CPOL = 0
            {         
                SPCR = SPCR | (1<<CPHA);           
            }
            else  //CPHA = 1 a CPOL = 1
            {    
                SPCR = SPCR | (1<<CPHA) | (1<<CPOL);
            }     
            *(p_programMemory) = 0x73;
            break;
        } 
        case 0x73:   
        {   
            if(symbol == 0x00)  //rychlost SPI je frekvence krystalu / 4
            {     
            }
            else if(symbol == 0x01)  //rychlost SPI je frekvence krystalu / 16
            {
                SPCR = SPCR | (1<<SPR0);  
            }                      
            else if(symbol == 0x02)  //rychlost SPI je frekvence krystalu / 64
            {         
                SPCR = SPCR | (1<<SPR1);           
            }
            else  //rychlost SPI je frekvence krystalu / 128
            {    
                SPCR = SPCR | (1<<SPR1) | (1<<SPR0);
            }      
            delay_ms(10); 
            XBeeSendString("OK");
            *(p_programMemory) = 0x06;
            break;
        } 
        default: break;
    }   
    
}

void SaveToStackForSensor(char symbol, char * p_stackForSensor, char * p_countStackForSensor)
{
    *(p_stackForSensor + *(p_countStackForSensor)) = symbol; 
    (*(p_countStackForSensor))++;
    if(*(p_countStackForSensor) == 32)  //ochrana proti preteceni zasobniku
    {
        *(p_countStackForSensor) = 31;
    }
}

void SensorUsartRecieve(char * p_stackForPC, char * p_countStackForPC)
{
    char symbol = SensorUdrRecieve();     
    *(p_stackForPC + *(p_countStackForPC)) = symbol; 
    (*(p_countStackForPC))++;  
    
    if(*(p_countStackForPC) == 32)  //ochrana proti preteceni zasobniku
    {
        *(p_countStackForPC) = 31;
    } 
}

char SPIRecieve (void)
{
    return SPDR;
}

void SensorSPIRecieve(char * p_stackForPC, char * p_countStackForPC)
{
    char symbol = SPIRecieve();
    if(symbol == 'g')
    {
        setPORTC_LED(0x01); //////////////////////////////////////////////////////////////////
    }     
    *(p_stackForPC + *(p_countStackForPC)) = symbol; 
    (*(p_countStackForPC))++;                   
    
    if(*(p_countStackForPC) == 32)  //ochrana proti preteceni zasobniku
    {
        *(p_countStackForPC) = 31;
    } 
}


