packerParser.cpp
  1  // SPDX-FileCopyrightText: 2018 Limor Fried for Adafruit Industries
  2  //
  3  // SPDX-License-Identifier: MIT
  4  
  5  #include <string.h>
  6  #include <Arduino.h>
  7  #include <SPI.h>
  8  #if not defined (_VARIANT_ARDUINO_DUE_X_) && not defined (_VARIANT_ARDUINO_ZERO_)
  9    #include <SoftwareSerial.h>
 10  #endif
 11  
 12  #include "Adafruit_BLE.h"
 13  #include "Adafruit_BluefruitLE_SPI.h"
 14  #include "Adafruit_BluefruitLE_UART.h"
 15  
 16  
 17  #define PACKET_ACC_LEN                  (15)
 18  #define PACKET_GYRO_LEN                 (15)
 19  #define PACKET_MAG_LEN                  (15)
 20  #define PACKET_QUAT_LEN                 (19)
 21  #define PACKET_BUTTON_LEN               (5)
 22  #define PACKET_COLOR_LEN                (6)
 23  #define PACKET_LOCATION_LEN             (15)
 24  
 25  //    READ_BUFSIZE            Size of the read buffer for incoming packets
 26  #define READ_BUFSIZE                    (20)
 27  
 28  
 29  /* Buffer to hold incoming characters */
 30  uint8_t packetbuffer[READ_BUFSIZE+1];
 31  
 32  /**************************************************************************/
 33  /*!
 34      @brief  Casts the four bytes at the specified address to a float
 35  */
 36  /**************************************************************************/
 37  float parsefloat(uint8_t *buffer) 
 38  {
 39    float f = ((float *)buffer)[0];
 40    return f;
 41  }
 42  
 43  /**************************************************************************/
 44  /*! 
 45      @brief  Prints a hexadecimal value in plain characters
 46      @param  data      Pointer to the byte data
 47      @param  numBytes  Data length in bytes
 48  */
 49  /**************************************************************************/
 50  void printHex(const uint8_t * data, const uint32_t numBytes)
 51  {
 52    uint32_t szPos;
 53    for (szPos=0; szPos < numBytes; szPos++) 
 54    {
 55      Serial.print(F("0x"));
 56      // Append leading 0 for small values
 57      if (data[szPos] <= 0xF)
 58      {
 59        Serial.print(F("0"));
 60        Serial.print(data[szPos] & 0xf, HEX);
 61      }
 62      else
 63      {
 64        Serial.print(data[szPos] & 0xff, HEX);
 65      }
 66      // Add a trailing space if appropriate
 67      if ((numBytes > 1) && (szPos != numBytes - 1))
 68      {
 69        Serial.print(F(" "));
 70      }
 71    }
 72    Serial.println();
 73  }
 74  
 75  /**************************************************************************/
 76  /*!
 77      @brief  Waits for incoming data and parses it
 78  */
 79  /**************************************************************************/
 80  uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout) 
 81  {
 82    uint16_t origtimeout = timeout, replyidx = 0;
 83  
 84    memset(packetbuffer, 0, READ_BUFSIZE);
 85  
 86    while (timeout--) {
 87      if (replyidx >= 20) break;
 88      if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN))
 89        break;
 90      if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN))
 91        break;
 92      if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN))
 93        break;
 94      if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN))
 95        break;
 96      if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN))
 97        break;
 98      if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN))
 99        break;
100      if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN))
101        break;
102  
103      while (ble->available()) {
104        char c =  ble->read();
105        if (c == '!') {
106          replyidx = 0;
107        }
108        packetbuffer[replyidx] = c;
109        replyidx++;
110        timeout = origtimeout;
111      }
112      
113      if (timeout == 0) break;
114      delay(1);
115    }
116  
117    packetbuffer[replyidx] = 0;  // null term
118  
119    if (!replyidx)  // no data or timeout 
120      return 0;
121    if (packetbuffer[0] != '!')  // doesn't start with '!' packet beginning
122      return 0;
123    
124    // check checksum!
125    uint8_t xsum = 0;
126    uint8_t checksum = packetbuffer[replyidx-1];
127    
128    for (uint8_t i=0; i<replyidx-1; i++) {
129      xsum += packetbuffer[i];
130    }
131    xsum = ~xsum;
132  
133    // Throw an error message if the checksum's don't match
134    if (xsum != checksum)
135    {
136      Serial.print("Checksum mismatch in packet : ");
137      printHex(packetbuffer, replyidx+1);
138      return 0;
139    }
140    
141    // checksum passed!
142    return replyidx;
143  }