Very simple bytestuffed protocol

The version here is crafted so it can be tested on an Arduino

Should be easy portable

Jens


byteStuff on Ard no 1

open raw

// JDN oct 2024
// simple byte stuffing protocol
// WARNING: no check on timeout in rx as well as tx
//
// NB tx and RX buf size is 64 on ardino uno and mega
//
// bytestuff is inserted and removed on the fly so ...
// SPECIAL:
// In the example we use TX and RX on Serial "1" port - the same port
// So for test you have to connect TX and RX pins
// On an UNO its pin 0 and 1
// WHEN UPLOADING REMOVE THE CONNECTION OTHERWISE UPLOAD FAIL
//
//vrs 0.13


// start of frame delimiter - is inserted automaticly
#define SOT '['

// end of frame delimiter - is inserted automaticly
#define EOT ']'

// Byte stuffing value
#define STUFFBYTE 'S'

// nr of restart in rxPkg if a SOT occurs after forst SOT and before the wanted EOT
#define NRRESTART 1

// define rx and tx ports
#define TXPORT Serial
#define RXPORT Serial

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

// tx pgk lgt do not include SOF and EOF
void txPkg(const char *src, int lgt) {
  char b;

  //1. txSOF
  TXPORT.write(SOT);

  //2: tx message
  while (0 < lgt) {
    b = *src;
    switch (b) {
      case SOT:  // bytesstuffing now ?
      case EOT:  // just add more chars if needed
      case STUFFBYTE:
        b = ~b;
        TXPORT.write(STUFFBYTE);
        TXPORT.write(b);
        break;
      default:
        TXPORT.write(b);
    }
    lgt--;
    if (0 < lgt)
      src++;
  }

  //3. tx EOT
  TXPORT.write(EOT);
}

//----

void emptyRxBuf() {
  delay(100);  // why ?? dont know ! :-)
  while (RXPORT.available())
    RXPORT.read();
}

uint8_t getNextByte() {
  char b;
  while (RXPORT.available() < 1)
    ;
  b = RXPORT.read();
  return (b);
}

int rxPkg(uint8_t *dest, int maxLgt) {
  int bytesRcv = 0;
  uint8_t b, noRestart;
  uint8_t *p;

  noRestart = NRRESTART;
  p = dest;
  //1. read SOT - start of Frame
  while (1) {
    b = getNextByte();
    if (b == SOT)
      break;
  }

  //2. assumption EOF is not in tlg - only as EOF
  // read message and EOT
  // NB if your buffer fills up before EOT is received length returned is negative
  while (1) {

    b = getNextByte();
    //hm lost EOT so start on next pkg
    if (SOT == b) {  // start again
      noRestart--;
      if (noRestart < 0) {
        bytesRcv = -9999;
        goto outhere;
      }
      p = dest;
      bytesRcv = 0;
      break;
    }

    if (EOT == b) {
      goto outhere;
    } else {
      if (b == STUFFBYTE) {
        b = getNextByte();  // drop stuff Symbol and get next char
        b = ~b;             //destuff// --------------------
      }
      *p = b;
      p++;
      bytesRcv++;
      // rx user buffer full ?
      if (maxLgt <= bytesRcv) {
        bytesRcv = -bytesRcv;  // negativ value indicates for caller buffer full
        goto outhere;          // before we did get EOT !!
      }
    }
  }

  // 3. return nr of bytes rcv not including SOF and EOF
outhere:
  return bytesRcv;
}

uint8_t rcvBuf[100];
char bf[] = "1234S45[]0";
int nrRcv = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("\n----");
  Serial.println(__FILE__);
  Serial.println(__DATE__);
  Serial.println(sizeof(bf));
  Serial.println("--<>--");

  delay(100);

  // empty buf
  emptyRxBuf();

  delay(500);

  //test
  txPkg(bf, sizeof(bf));
  delay(500);
  nrRcv = rxPkg(rcvBuf, 100);
  delay(100);

  // results of test
  Serial.println("\n---after test");
  Serial.print("tx: ");
  Serial.println(sizeof(bf));
  Serial.print("rx: ");
  Serial.println(nrRcv);
  if (nrRcv == sizeof(bf))
    Serial.println("same number of chr received as transmitted");
  else
    Serial.println("did not receive same number as transmitted");
  Serial.println((char *)rcvBuf);
  Serial.println("--eof");
}


void loop() {}