Serial communication protocol generic implementation

Dependents:   ClassFRDM ClassLPC

DataComm.cpp

Committer:
askksa12543
Date:
2015-03-19
Revision:
2:ba93026839a9
Parent:
1:9cfb17f74dcd

File content as of revision 2:ba93026839a9:

#include "DataComm.h"

//set pin for clock output, initialize it to zero
void DataComm::setClockOut(PinName pin)
{
    gpio_init_out_ex(&clock_out, pin, 0);        
}

//set pin for clock input
void DataComm::setClockIn(PinName pin)
{
    gpio_init_in(&clock_in, pin);    
}

//set pin for outgoing serial connection
void DataComm::setSerialOut(PinName pin)
{
    gpio_init_out_ex(&serial_out, pin, 0);        
}

//set pin for incoming serial connection
void DataComm::setSerialIn(PinName pin)
{
    gpio_init_in(&serial_in, pin);    
} 

//listen for incoming data, check for preamble, return from function if preamble found
void DataComm::listen()
{
    //variables
    int pre = 0, data_flag = 1;
    char temp = 0;
    
    //while preamble not found, load data into the buffer at every clock pulse
    while(!pre)
    {
        //read in data if clock is 1 and data flag is 1
        if(gpio_read(&clock_in) && data_flag)
        {
            //data is left shifted into our temporary variable.
            //each new data bit is moved into the least significant bit after the rest of the bits are shifted to the left
            //data must be sent from the other microcontroller shifted out from the most significant bit to the least significant bit.
            temp = (temp << 1) + gpio_read(&serial_in);
            data_flag = 0;
            //when preamble is found return from function
            if(temp == PREAMBLE)
            {
                pre = 1;    
            }
        }
        //when clock returns to low - reset data flag to accept the next bit.
        if(!gpio_read(&clock_in) && !data_flag)
        {
            data_flag = 1;
        }
    }    
}

//set clock speed for sending data, automatically calculate skew time
void DataComm::setClock(int clock)
{
    clock_time = clock;
    //skew time 90% of the clock
    skew_time = (clock * 9)/10;   
}

//initiate a connection with a preamble
void DataComm::initiate_connection()
{
    //variables
    int j=128, done=0, skew_flag=0;
    
    //output preamble
    while(!done)
    {
        //start timer for clock
        t.start();
        //wait until the timer has reached the set time.
        while(t.read_ms() < clock_time)
        {
            //extract data just before clock goes high
            if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
            {
                //extract data bit
                gpio_write(&serial_out, ((PREAMBLE / j) % 2));
                skew_flag = 0;
                j /= 2; //decrement j to get to next bit location
            }
        }
        //stop and reset the timer
        t.stop();
        t.reset();
        //switch clock signal
        gpio_write(&clock_out, !gpio_read(&clock_out));
        //reset skew flag
        skew_flag = 1;
        //last preamble bit sent - return from function set clock to zero
        if(j==0)
        {
            gpio_write(&clock_out, 0);
            done = 1;  
        }
    }     
}

//send data from character array of a specific size
void DataComm::send_data(char data[], int size)
{
    //variables
    int i=0, j=128, done=0, skew_flag=0;
    
    //output data
    while(!done)
    {
        //start timer for clock
        t.start();
        //wait until the timer has reached the set time.
        while(t.read_ms() < clock_time)
        {
            //extract data just before clock goes high
            if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
            {
                //extract data bit
                gpio_write(&serial_out, ((data[i] / j) % 2));
                skew_flag = 0;
                j /= 2; //decrement j to get to next bit location
            }
        }
        //stop and reset the timer
        t.stop();
        t.reset();
        //switch clock signal
        gpio_write(&clock_out, !gpio_read(&clock_out));
        //reset skew flag
        skew_flag = 1;
        //last bit sent - move to next character or return from function
        if(j==0)
        {
            i++;
            if(i>size)
            {
                //return from function, set clock to zero
                done = 1;
                gpio_write(&clock_out, 0);
            }
            j=128;  
        }
    }       
}

//receive data return pointer to character array that data is stored in
char* DataComm::receive_data()
{
    //variables
    int i=0, j=0, done = 0, data_flag = 1;
    char temp, data[MAX];
    
    //read characters until postamble is found
    while(!done)
    {
        //read in data if clock is 1 and data flag is 1
        if(gpio_read(&clock_in) && data_flag)
        {
            //data is left shifted into our temporary variable.
            //each new data bit is moved into the least significant bit after the rest of the bits are shifted to the left
            //data must be sent from the other microcontroller shifted out from the most significant bit to the least significant bit.
            temp = (temp << 1) + gpio_read(&serial_in);
            data_flag = 0;
            j++;
        }
        //when clock returns to low - reset data flag to accept the next bit.
        if(!gpio_read(&clock_in) && !data_flag)
        {
            data_flag = 1;
        }
        //after filling a new byte check for postamble.
        if(j>7)
        {
            //finished when postamble found, otherwise store the byte
            if(temp == POSTAMBLE)
                done=1;
            else
                data[i] = temp;
            //increment i, reset j
            i++;
            j=0;    
        }
    }
    return data;       
}

//close connection by sending postamble
void DataComm::close_connection()
{
    //variables
    int j=128, done=0, skew_flag=0;
    
    //output postamble
    while(!done)
    {
        //start timer for clock
        t.start();
        //wait until the timer has reached the set time.
        while(t.read_ms() < clock_time)
        {
            //extract data just before clock goes high
            if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
            {
                //extract data bit
                gpio_write(&serial_out, ((POSTAMBLE / j) % 2));
                skew_flag = 0;
                j /= 2; //decrement j to get to next bit location
            }
        }
        //stop and reset the timer
        t.stop();
        t.reset();
        //switch clock signal
        gpio_write(&clock_out, !gpio_read(&clock_out));
        //reset skew flag
        skew_flag = 1;
        //last postamble bit sent - return from function and set clock to zero
        if(j==0)
        {
            gpio_write(&clock_out, 0);
            done = 1;  
        }
    }     
}