?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

/*! \file stxetx.c \brief STX/ETX Packet Protocol Implementation Library. */
//*****************************************************************************
//
// File Name    : 'stxetx.c'
// Title                : STX/ETX Packet Protocol Implementation Library
// Author               : Pascal Stang - Copyright (C) 2002
// Created              : 10/9/2002
// Revised              : 6/30/2003
// Version              : 0.1
// Target MCU   : any
// Editor Tabs  : 4
//
// Description  : This library provides a set of functions needed to send and
//              receive STX/ETX packets.  STX/ETX is a simple packet protocol that can
//              be wrapped around user data for one or more of the following reasons:
//
//                      1. packetization is needed
//                              - Using packets can be helpful if your data naturally forms 
//                              little "bunches" or if different types of data must be sent
//                              over the same channel (a serial cable, for example).  If your
//                              data forms "bunches", you can send user data inside STX/ETX
//                              packets with a predetermined structure, like an array of A/D
//                              conversion results.  If you need a way to tell the receiver
//                              what kind of data you're sending, you can use the TYPE field
//                              in the STX/ETX packet.
//                      2. error checking is needed
//                              - STX/ETX packets will add a checksum to your data.  This
//                              allows the receiver to verify that data was received correctly
//                              and is error-free.  Packets which are corrupted in transmission
//                              and fail the the checksum test are automatically discarded.
//                              Error checking is especially useful when the data transmission
//                              channel is unreliable or noisy (examples: radio, infrared, long
//                              cables, etc)
//      
//              STX/ETX packets have the following structure:
//
//              [STX][status][type][length][user data...][checksum][ETX]
//
//              All fields are 1 byte except for user data which may be 0-255 bytes.
//              Uppercase fields are constant (STX=0x02, ETX=0x03), lowercase fields
//              vary.  The length field is the number of bytes in the user data area.
//              The checksum is the 8-bit sum of all bytes between but not including
//              STX/ETX.
//
// This code is distributed under the GNU Public License
//              which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#include "global.h"
#include "stxetx.h"
//#include "rprintf.h"

// function pointer to data output routine
static void (*stxetxDataOut)(unsigned char data);

// received packet data buffer
unsigned char stxetxRxPacket[STXETX_MAXRXPACKETSIZE];

// functions


// Initialize STX/ETX packet protocol library
void stxetxInit(void (*dataout_func)(unsigned char data))
{
        stxetxDataOut = dataout_func;
}

// Send/Create STX/ETX packet
void stxetxSend(unsigned char status, unsigned char type, unsigned char datalength, unsigned char* dataptr)
{
        unsigned char checksum = 0;
        unsigned short i;
        
        // write packet header
        stxetxDataOut(STX);
        stxetxDataOut(status);
        stxetxDataOut(type);
        stxetxDataOut(datalength);
        // update checksum
        checksum += status + type + datalength;
        // copy data into packet
        for(i = 0; i < datalength; i++)
        {
                stxetxDataOut(*dataptr);
                checksum += *dataptr;
                dataptr++;
        }
        // write packet trailer
        stxetxDataOut(checksum);
        stxetxDataOut(ETX);
}

// process buffer containing STX/ETX packets
unsigned char stxetxProcess(cBuffer* rxBuffer)
{
        unsigned char foundpacket = FALSE;
        unsigned short i;
        unsigned char length, checksum;
        //unsigned char type;

        // process the buffer
        // go through buffer looking for packets
        // the STX must be located at least STXETX_HEADERLENGTH+STXETX_TRAILERLENGTH from end
        // otherwise we must not have a complete packet
        while( rxBuffer->datalength >= ((u16)STXETX_HEADERLENGTH+(u16)STXETX_TRAILERLENGTH) )
        {
                // look for a potential start of packet
                if(bufferGetAtIndex(rxBuffer, 0) == STX)
                {
                        // if this is a start, then get the length
                        length = bufferGetAtIndex(rxBuffer, STXETX_LENGTHOFFSET);

                        // now we must have at least STXETX_HEADERLENGTH+length+STXETX_TRAILERLENGTH in buffer to continue
                        if(rxBuffer->datalength >= ((u16)STXETX_HEADERLENGTH+length+(u16)STXETX_TRAILERLENGTH))
                        {
                                // check to see if ETX is in the right position
                                if(bufferGetAtIndex(rxBuffer, STXETX_HEADERLENGTH+length+STXETX_TRAILERLENGTH-1) == ETX)
                                {
                                        // found potential packet
                                        // test checksum
                                        checksum = 0;
                                        // sum data between STX and ETX, not including checksum itself
                                        // (u16) casting needed to avoid unsigned/signed mismatch
                                        for(i = 0; i<((u16)STXETX_HEADERLENGTH+length+(u16)STXETX_TRAILERLENGTH-(u16)STXETX_NOETXSTXCHECKSUM); i++)
                                        {
                                                checksum += bufferGetAtIndex(rxBuffer, i+STXETX_STATUSOFFSET);
                                        }
                                        // compare checksums
                                        if(checksum == bufferGetAtIndex(rxBuffer, STXETX_CHECKSUMOFFSET+length))
                                        {
                                                //we have a packet!
                                                foundpacket = TRUE;
                                        
                                                // copy data to buffer
                                                // (don't copy STX, ETX, or CHECKSUM)
                                                for(i = 0; i < ((u16)STXETX_HEADERLENGTH+length-1); i++)
                                                {
                                                        stxetxRxPacket[i] = bufferGetAtIndex(rxBuffer, i+1);
                                                }

                                                // debug
                                                //rprintf("STXETX Received packet type: 0x%x\n", bufferGetAtIndex(rxBuffer, STXETX_TYPEOFFSET));

                                                // dump this packet from the
                                                bufferDumpFromFront(rxBuffer, STXETX_HEADERLENGTH+length+STXETX_TRAILERLENGTH);

                                                // done with this processing session
                                                break;
                                        }
                                        else
                                        {
                                                // checksum bad
                                                //rprintf("STXETX Received packet with bad checksum\r\n");
                                                // for now, we dump these
                                                // dump this STX
                                                bufferGetFromFront(rxBuffer);
                                        }
                                }
                                else
                                {
                                        // no ETX or ETX in wrong position
                                        // dump this STX
                                        bufferGetFromFront(rxBuffer);
                                }
                        }
                        else
                        {
                                // not enough data in buffer to decode pending packet
                                // wait until next time
                                break;
                        }
                }
                else
                {
                        // this is not a start, dump it
                        bufferGetFromFront(rxBuffer);
                }
        }

        // check if receive buffer is full with no packets decoding
        // (ie. deadlocked on garbage data or packet that exceeds buffer size)
        if(!bufferIsNotFull(rxBuffer))
        {
                // dump receive buffer contents to relieve deadlock
                bufferFlush(rxBuffer);
        }
        
        return foundpacket;
}

unsigned char stxetxGetRxPacketStatus(void)
{
        // return the packet's status
        // (subtract 1 from the offset because the STX has already been discarded)
        return stxetxRxPacket[STXETX_STATUSOFFSET-1];
}

unsigned char stxetxGetRxPacketType(void)
{
        // return the packet's type
        // (subtract 1 from the offset because the STX has already been discarded)
        return stxetxRxPacket[STXETX_TYPEOFFSET-1];
}

unsigned char stxetxGetRxPacketDatalength(void)
{
        // return the packet's datalength
        // (subtract 1 from the offset because the STX has already been discarded)
        return stxetxRxPacket[STXETX_LENGTHOFFSET-1];
}

unsigned char* stxetxGetRxPacketData(void)
{
        // return a pointer to the packet's data payload
        // (subtract 1 from the offset because the STX has already been discarded)
        return stxetxRxPacket+STXETX_DATAOFFSET-1;
}
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3