mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
Initial Arduino IDE based on Processing.
This commit is contained in:
218
build/shared/lib/avrlib/stxetx.c
Executable file
218
build/shared/lib/avrlib/stxetx.c
Executable file
@ -0,0 +1,218 @@
|
||||
/*! \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;
|
||||
}
|
Reference in New Issue
Block a user