Serial Frame

Address Length Type Values communications supports transmission of an arbitrary length packet of data to a specified address. Since the first byte is the address, a receiver immediately knows whether the packet can be ignored, the next byte indicates how many bytes can be ignored. If the packet is for the receiver, or a broadcast packet, the receiver captures the specified number of bytes and decoders it.

The following two functions will send or receive an ALTV packet. AltvRead() must be called repeatedly and will either return NULL when a complete packet has been received, or a pointer to a buffer containing the packet when a complete packet has been received.

It expects the upper two bits of the address byte to be one and zero. The buffer index remains at zero until it finds an address byte when searching for one. It will then read the next, length byte, and capture what it believes is the remainder of the packet. If it doesn't receive the next byte in packet within an acceptable amount of time, it resets the buffer index and starts searching for an address byte again. Eventually, it should synchronize and begin capturing a sequence of complete and valid packets. A checksum can always be added to the packet payload for verification if needed.

// read msg: <addr> <length> <type> <data ...>

//

// - <addr> is 10xx xxxx

// - <length> is in bytes

// - <type> can be type of data or a single byte command

// - poll is length one msg to specified node: <addr> <1> <POLL>

// - any response is similar, with address of master: 0x81

// - response has a time limit: 10 msec (how fast can PC respond)?

#include <Arduino.h>

#include "altv.h"

byte txEnPin = 2;

// -----------------------------------------------------------------------------

#define MAX_DATA_SIZE 20

void

altvSend (

byte addr,

byte type,

byte* data,

int nbyte )

{

byte buf [MAX_DATA_SIZE];

buf [IDX_ADDR] = Address(addr);

buf [IDX_LEN] = 1+nbyte;

buf [IDX_TYPE] = type;

if (nbyte)

memcpy (&buf [IDX_DATA], data, nbyte);

// transmit

digitalWrite (txEnPin, HIGH);

delay (1);

Serial.write (buf, 3 + nbyte);

// wait for transmission to complete

Serial.flush ();

digitalWrite (txEnPin, LOW);

}

// -----------------------------------------------------------------------------

#define RX_BUF_SIZE 20

byte rxBufIdx = 0;

byte rxBuf [RX_BUF_SIZE];

#define TIMEOUT 10 // msec

byte*

altvRead (void)

{

static long last = 0;

long time = millis ();

if (! Serial.available ()) {

// timeout, reset index, if not input after x msec if idx > 0

if ((0 < rxBufIdx) && (TIMEOUT < (time - last)) ) {

rxBufIdx = 0;

}

return NULL;

}

last = time;

digitalWrite (12, HIGH);

byte c = Serial.read ();

rxBuf [rxBufIdx] = c;

switch (rxBufIdx) {

case 0:

if (IsAddr(c)) // expected addr

rxBufIdx++;

break;

case 1:

rxBufIdx++;

if ((int)c > (int)RX_BUF_SIZE) { // unacceptable size

rxBufIdx = 0;

}

else if ((int)c == 0) { // zero length msg

rxBufIdx = 0;

return rxBuf;

}

break;

default:

if (rxBufIdx++ > rxBuf [IDX_LEN]) { // msg complete

rxBufIdx = 0;

return rxBuf;

}

break;

}

return NULL;

}