// SPDX-FileCopyrightText: 2021 Phillip Burgess for Adafruit Industries // // SPDX-License-Identifier: MIT #include // packetbuffer holds inbound data #define READ_BUFSIZE 20 uint8_t packetbuffer[READ_BUFSIZE + 1]; // +1 is for NUL string terminator /**************************************************************************/ /*! @brief Casts the four bytes at the specified address to a float. @param ptr Pointer into packet buffer. @returns Floating-point value. */ /**************************************************************************/ float parsefloat(uint8_t *ptr) { float f; // Make a suitably-aligned float variable, memcpy(&f, ptr, 4); // because in-buffer instance might be misaligned! return f; // (You can't always safely parse in-place) } /**************************************************************************/ /*! @brief Prints a series of bytes in 0xNN hexadecimal notation. @param buf Pointer to array of byte data. @param len Data length in bytes. */ /**************************************************************************/ void printHex(const uint8_t *buf, const uint32_t len) { for (uint32_t i=0; i < len; i++) { Serial.print(F("0x")); if (buf[i] <= 0xF) Serial.write('0'); // Zero-pad small values Serial.print(buf[i], HEX); if (i < (len - 1)) Serial.write(' '); // Space between bytes } Serial.println(); } static const struct { // Special payloads from Bluefruit Connect app... char id; // Packet type identifier uint8_t len; // Size of complete, well-formed packet of this type } _app_packet[] = { {'A', 15}, // Accelerometer {'G', 15}, // Gyro {'M', 15}, // Magnetometer {'Q', 19}, // Quaterion {'B', 5}, // Button {'C', 6}, // Color {'L', 15}, // Location }; #define NUM_PACKET_TYPES (sizeof _app_packet / sizeof _app_packet[0]) #define SHORTEST_PACKET_LEN 5 // Button, for now /**************************************************************************/ /*! @brief Given packet data, identify if it's one of the known Bluefruit Connect app packet types. @param buf Pointer to packet data. @param len Size of packet in bytes. @returns Packet type index (0 to NUM_PACKET_TYPES-1) if recognized, -1 if unrecognized. */ /**************************************************************************/ int8_t packetType(uint8_t *buf, uint8_t len) { if ((len >= SHORTEST_PACKET_LEN) && (buf[0] == '!')) { for (int8_t type=0; typeavailable()) { char c = ble->read(); if (c == '!') { // '!' resets buffer to start len = 0; xsum = 255; } packetbuffer[len++] = c; // Stop when buffer's full or packet type recognized if ((len >= READ_BUFSIZE) || ((type = packetType(packetbuffer, len)) >= 0)) break; start_time = now; // Reset timeout on char received xsum -= c; // Not last char, do checksum math type = -1; // Reset packet type finder } } while((now - start_time) < timeout); // If packet type recognized, verify checksum (else freeform string) if ((type >= 0) && (xsum != packetbuffer[len-1])) { // Last byte = checksum Serial.print("Packet checksum mismatch: "); printHex(packetbuffer, len); return 0; } packetbuffer[len] = 0; // Terminate packet string return len; // Checksum is valid for packet, or it's a freeform string }