Serial communication protocol generic implementation

Dependents:   ClassFRDM ClassLPC

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DataComm.cpp Source File

DataComm.cpp

00001 #include "DataComm.h"
00002 
00003 //set pin for clock output, initialize it to zero
00004 void DataComm::setClockOut(PinName pin)
00005 {
00006     gpio_init_out_ex(&clock_out, pin, 0);        
00007 }
00008 
00009 //set pin for clock input
00010 void DataComm::setClockIn(PinName pin)
00011 {
00012     gpio_init_in(&clock_in, pin);    
00013 }
00014 
00015 //set pin for outgoing serial connection
00016 void DataComm::setSerialOut(PinName pin)
00017 {
00018     gpio_init_out_ex(&serial_out, pin, 0);        
00019 }
00020 
00021 //set pin for incoming serial connection
00022 void DataComm::setSerialIn(PinName pin)
00023 {
00024     gpio_init_in(&serial_in, pin);    
00025 } 
00026 
00027 //listen for incoming data, check for preamble, return from function if preamble found
00028 void DataComm::listen()
00029 {
00030     //variables
00031     int pre = 0, data_flag = 1;
00032     char temp = 0;
00033     
00034     //while preamble not found, load data into the buffer at every clock pulse
00035     while(!pre)
00036     {
00037         //read in data if clock is 1 and data flag is 1
00038         if(gpio_read(&clock_in) && data_flag)
00039         {
00040             //data is left shifted into our temporary variable.
00041             //each new data bit is moved into the least significant bit after the rest of the bits are shifted to the left
00042             //data must be sent from the other microcontroller shifted out from the most significant bit to the least significant bit.
00043             temp = (temp << 1) + gpio_read(&serial_in);
00044             data_flag = 0;
00045             //when preamble is found return from function
00046             if(temp == PREAMBLE)
00047             {
00048                 pre = 1;    
00049             }
00050         }
00051         //when clock returns to low - reset data flag to accept the next bit.
00052         if(!gpio_read(&clock_in) && !data_flag)
00053         {
00054             data_flag = 1;
00055         }
00056     }    
00057 }
00058 
00059 //set clock speed for sending data, automatically calculate skew time
00060 void DataComm::setClock(int clock)
00061 {
00062     clock_time = clock;
00063     //skew time 90% of the clock
00064     skew_time = (clock * 9)/10;   
00065 }
00066 
00067 //initiate a connection with a preamble
00068 void DataComm::initiate_connection()
00069 {
00070     //variables
00071     int j=128, done=0, skew_flag=0;
00072     
00073     //output preamble
00074     while(!done)
00075     {
00076         //start timer for clock
00077         t.start();
00078         //wait until the timer has reached the set time.
00079         while(t.read_ms() < clock_time)
00080         {
00081             //extract data just before clock goes high
00082             if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
00083             {
00084                 //extract data bit
00085                 gpio_write(&serial_out, ((PREAMBLE / j) % 2));
00086                 skew_flag = 0;
00087                 j /= 2; //decrement j to get to next bit location
00088             }
00089         }
00090         //stop and reset the timer
00091         t.stop();
00092         t.reset();
00093         //switch clock signal
00094         gpio_write(&clock_out, !gpio_read(&clock_out));
00095         //reset skew flag
00096         skew_flag = 1;
00097         //last preamble bit sent - return from function set clock to zero
00098         if(j==0)
00099         {
00100             gpio_write(&clock_out, 0);
00101             done = 1;  
00102         }
00103     }     
00104 }
00105 
00106 //send data from character array of a specific size
00107 void DataComm::send_data(char data[], int size)
00108 {
00109     //variables
00110     int i=0, j=128, done=0, skew_flag=0;
00111     
00112     //output data
00113     while(!done)
00114     {
00115         //start timer for clock
00116         t.start();
00117         //wait until the timer has reached the set time.
00118         while(t.read_ms() < clock_time)
00119         {
00120             //extract data just before clock goes high
00121             if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
00122             {
00123                 //extract data bit
00124                 gpio_write(&serial_out, ((data[i] / j) % 2));
00125                 skew_flag = 0;
00126                 j /= 2; //decrement j to get to next bit location
00127             }
00128         }
00129         //stop and reset the timer
00130         t.stop();
00131         t.reset();
00132         //switch clock signal
00133         gpio_write(&clock_out, !gpio_read(&clock_out));
00134         //reset skew flag
00135         skew_flag = 1;
00136         //last bit sent - move to next character or return from function
00137         if(j==0)
00138         {
00139             i++;
00140             if(i>size)
00141             {
00142                 //return from function, set clock to zero
00143                 done = 1;
00144                 gpio_write(&clock_out, 0);
00145             }
00146             j=128;  
00147         }
00148     }       
00149 }
00150 
00151 //receive data return pointer to character array that data is stored in
00152 char* DataComm::receive_data()
00153 {
00154     //variables
00155     int i=0, j=0, done = 0, data_flag = 1;
00156     char temp, data[MAX];
00157     
00158     //read characters until postamble is found
00159     while(!done)
00160     {
00161         //read in data if clock is 1 and data flag is 1
00162         if(gpio_read(&clock_in) && data_flag)
00163         {
00164             //data is left shifted into our temporary variable.
00165             //each new data bit is moved into the least significant bit after the rest of the bits are shifted to the left
00166             //data must be sent from the other microcontroller shifted out from the most significant bit to the least significant bit.
00167             temp = (temp << 1) + gpio_read(&serial_in);
00168             data_flag = 0;
00169             j++;
00170         }
00171         //when clock returns to low - reset data flag to accept the next bit.
00172         if(!gpio_read(&clock_in) && !data_flag)
00173         {
00174             data_flag = 1;
00175         }
00176         //after filling a new byte check for postamble.
00177         if(j>7)
00178         {
00179             //finished when postamble found, otherwise store the byte
00180             if(temp == POSTAMBLE)
00181                 done=1;
00182             else
00183                 data[i] = temp;
00184             //increment i, reset j
00185             i++;
00186             j=0;    
00187         }
00188     }
00189     return data;       
00190 }
00191 
00192 //close connection by sending postamble
00193 void DataComm::close_connection()
00194 {
00195     //variables
00196     int j=128, done=0, skew_flag=0;
00197     
00198     //output postamble
00199     while(!done)
00200     {
00201         //start timer for clock
00202         t.start();
00203         //wait until the timer has reached the set time.
00204         while(t.read_ms() < clock_time)
00205         {
00206             //extract data just before clock goes high
00207             if(!gpio_read(&clock_out) && skew_flag && t.read_ms() > skew_time)
00208             {
00209                 //extract data bit
00210                 gpio_write(&serial_out, ((POSTAMBLE / j) % 2));
00211                 skew_flag = 0;
00212                 j /= 2; //decrement j to get to next bit location
00213             }
00214         }
00215         //stop and reset the timer
00216         t.stop();
00217         t.reset();
00218         //switch clock signal
00219         gpio_write(&clock_out, !gpio_read(&clock_out));
00220         //reset skew flag
00221         skew_flag = 1;
00222         //last postamble bit sent - return from function and set clock to zero
00223         if(j==0)
00224         {
00225             gpio_write(&clock_out, 0);
00226             done = 1;  
00227         }
00228     }     
00229 }