Skip to content

Commit b5808d1

Browse files
Starting to parse packet types
1 parent 77ec4e8 commit b5808d1

3 files changed

Lines changed: 240 additions & 0 deletions

File tree

EyeLights_Bluetooth/.nrf52840.test.only

Whitespace-only changes.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-FileCopyrightText: 2021 Phil Burgess for Adafruit Industries
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
/*
6+
BLUETOOTH THING for Adafruit EyeLights (LED Glasses + Driver).
7+
*/
8+
9+
#include <Adafruit_IS31FL3741.h> // For LED driver
10+
#include <bluefruit.h>
11+
#include "EyeLightsCanvasFont.h"
12+
13+
// function prototypes over in packetParser.cpp
14+
uint8_t readPacket(BLEUart *ble, uint16_t timeout);
15+
float parsefloat(uint8_t *buffer);
16+
void printHex(const uint8_t * data, const uint32_t numBytes);
17+
int8_t packetType(uint8_t *buf, uint8_t len);
18+
19+
// GLOBAL VARIABLES -------
20+
21+
// Packet buffer
22+
extern uint8_t packetbuffer[];
23+
24+
// BLE Service
25+
BLEDis bledis;
26+
BLEUart bleuart;
27+
28+
Adafruit_EyeLights_buffered glasses; // LED matrix is buffered for smooth animation
29+
30+
// Crude error handler, prints message to Serial console, flashes LED
31+
void err(char *str, uint8_t hz) {
32+
Serial.println(str);
33+
pinMode(LED_BUILTIN, OUTPUT);
34+
for (;;) digitalWrite(LED_BUILTIN, (millis() * hz / 500) & 1);
35+
}
36+
37+
void setup() { // Runs once at program start...
38+
39+
Serial.begin(115200);
40+
//while(!Serial);
41+
42+
Bluefruit.begin();
43+
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
44+
45+
// Configure and start the BLE Uart service
46+
bleuart.begin();
47+
48+
// Set up and start advertising
49+
startAdv();
50+
51+
if (! glasses.begin()) err("IS3741 not found", 2);
52+
53+
// Configure glasses for max brightness, enable output
54+
glasses.setLEDscaling(0xFF);
55+
glasses.setGlobalCurrent(0xFF);
56+
glasses.enable(true);
57+
}
58+
59+
void startAdv(void)
60+
{
61+
// Advertising packet
62+
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
63+
Bluefruit.Advertising.addTxPower();
64+
65+
// Include the BLE UART (AKA 'NUS') 128-bit UUID
66+
Bluefruit.Advertising.addService(bleuart);
67+
68+
// Secondary Scan Response packet (optional)
69+
// Since there is no room for 'Name' in Advertising packet
70+
Bluefruit.ScanResponse.addName();
71+
72+
/* Start Advertising
73+
* - Enable auto advertising if disconnected
74+
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
75+
* - Timeout for fast mode is 30 seconds
76+
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
77+
*
78+
* For recommended advertising interval
79+
* https://developer.apple.com/library/content/qa/qa1931/_index.html
80+
*/
81+
Bluefruit.Advertising.restartOnDisconnect(true);
82+
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
83+
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
84+
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
85+
}
86+
87+
void loop() { // Repeat forever...
88+
89+
uint8_t len = readPacket(&bleuart, 500);
90+
if (len == 0) return;
91+
92+
switch(packetType(packetbuffer, len)) {
93+
case 0: // Accelerometer
94+
Serial.println("Accel");
95+
break;
96+
case 1: // Gyro:
97+
Serial.println("Gyro");
98+
break;
99+
case 2: // Magnetometer
100+
Serial.println("Mag");
101+
break;
102+
case 3: // Quaternion
103+
Serial.println("Quat");
104+
break;
105+
case 4: // Button
106+
Serial.println("Button");
107+
break;
108+
case 5: // Color
109+
Serial.println("Color");
110+
printHex(&packetbuffer[2], 3);
111+
break;
112+
case 6: // Location
113+
Serial.println("Location");
114+
break;
115+
default:
116+
Serial.println((char *)packetbuffer);
117+
}
118+
119+
glasses.fill(0);
120+
121+
glasses.show(); // Buffered mode MUST use show() to refresh matrix
122+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include <bluefruit.h>
2+
3+
// Holds inbound data
4+
#define READ_BUFSIZE 20
5+
uint8_t packetbuffer[READ_BUFSIZE + 1]; // +1 for NUL string terminator
6+
7+
/**************************************************************************/
8+
/*!
9+
@brief Casts the four bytes at the specified address to a float.
10+
@param ptr Pointer into packet buffer.
11+
@returns Floating-point value.
12+
*/
13+
/**************************************************************************/
14+
float parsefloat(uint8_t *ptr) {
15+
float f;
16+
memcpy(&f, ptr, 4); // Suitably-aligned, can't always parse in-place.
17+
return f;
18+
}
19+
20+
/**************************************************************************/
21+
/*!
22+
@brief Prints a series of bytes in 0xNN hexadecimal notation.
23+
@param buf Pointer to array of byte data.
24+
@param len Data length in bytes.
25+
*/
26+
/**************************************************************************/
27+
void printHex(const uint8_t *buf, const uint32_t len) {
28+
for (uint32_t i=0; i < len; i++) {
29+
Serial.print(F("0x"));
30+
if (buf[i] <= 0xF) Serial.write('0'); // Zero-pad small values
31+
Serial.print(buf[i], HEX);
32+
if (i < (len - 1)) Serial.write(' '); // Space between bytes
33+
}
34+
Serial.println();
35+
}
36+
37+
static const struct { // A set of special data packet types from app...
38+
char id; // Packet type identifier
39+
uint8_t len; // Size of complete, well-formed packet of this type
40+
} _app_packet[] = {
41+
{'A', 15}, // Accelerometer
42+
{'G', 15}, // Gyro
43+
{'M', 15}, // Magnetometer
44+
{'Q', 19}, // Quaterion
45+
{'B', 5}, // Button
46+
{'C', 6}, // Color
47+
{'L', 15}, // Location
48+
};
49+
#define NUM_PACKET_TYPES (sizeof _app_packet / sizeof _app_packet[0])
50+
#define SHORTEST_PACKET_LEN 5 // Button, for now
51+
52+
/**************************************************************************/
53+
/*!
54+
@brief Given packet data, identify as one of the known packet types.
55+
@param buf Pointer to packet data.
56+
@param len Size of packet in bytes.
57+
@returns Packet type index (0 to NUM_PACKET_TYPES-1) if recognized,
58+
-1 if unrecognized.
59+
*/
60+
/**************************************************************************/
61+
int8_t packetType(uint8_t *buf, uint8_t len) {
62+
if ((len >= SHORTEST_PACKET_LEN) && (buf[0] == '!')) {
63+
for (int8_t type=0; type<NUM_PACKET_TYPES; type++) {
64+
if ((buf[1] == _app_packet[type].id) &&
65+
(len == _app_packet[type].len)) {
66+
return type;
67+
}
68+
}
69+
}
70+
return -1; // Length too short for a packet, or not a recognized type
71+
}
72+
73+
/**************************************************************************/
74+
/*!
75+
@brief Wait for incoming data and determine if it's one of the
76+
special packet types.
77+
@param ble Pointer to BLE UART object.
78+
timeout Character read timeout in milliseconds.
79+
@returns Length of data, or 0 if checksum is invalid for the type of
80+
packet detected.
81+
@note Packet buffer is not cleared. Calling function is expected
82+
to check return value before deciding whether to act on the
83+
data.
84+
*/
85+
/**************************************************************************/
86+
uint8_t readPacket(BLEUart *ble, uint16_t timeout) {
87+
int8_t type = -1; // App packet type, -1 if unknown or freeform string
88+
uint8_t len = 0, xsum = 255; // Packet length and ~checksum so far
89+
uint32_t now, start_time = millis();
90+
do {
91+
now = millis();
92+
if (ble->available()) {
93+
char c = ble->read();
94+
if (c == '!') { // '!' resets buffer to start
95+
len = 0;
96+
xsum = 255;
97+
}
98+
packetbuffer[len++] = c;
99+
// Stop when buffer's full or packet type recognized
100+
if ((len >= READ_BUFSIZE) ||
101+
((type = packetType(packetbuffer, len)) >= 0)) break;
102+
start_time = now; // Reset timeout on char received
103+
xsum -= c; // Not last char, do checksum math
104+
type = -1; // Reset packet type finder
105+
}
106+
} while((now - start_time) < timeout);
107+
108+
// If packet type recognized, verify checksum (else freeform string)
109+
if ((type >= 0) && (xsum != packetbuffer[len-1])) { // Last byte = checksum
110+
Serial.print("Packet checksum mismatch: ");
111+
printHex(packetbuffer, len);
112+
return 0;
113+
}
114+
115+
packetbuffer[len] = 0; // Terminate packet string
116+
117+
return len; // Checksum is valid for packet, or it's a freeform string
118+
}

0 commit comments

Comments
 (0)