commit
3da3457fb2
2 changed files with 259 additions and 0 deletions
@ -0,0 +1,125 @@ |
|||||||
|
/*********************************************************************
|
||||||
|
This is an example for our nRF52 based Bluefruit LE modules |
||||||
|
|
||||||
|
Pick one up today in the adafruit shop! |
||||||
|
|
||||||
|
Adafruit invests time and resources providing this open source code, |
||||||
|
please support Adafruit and open-source hardware by purchasing |
||||||
|
products from Adafruit! |
||||||
|
|
||||||
|
MIT license, check LICENSE for more information |
||||||
|
All text above, and the splash screen below must be included in |
||||||
|
any redistribution |
||||||
|
*********************************************************************/ |
||||||
|
|
||||||
|
#include <bluefruit.h> |
||||||
|
#include "Adafruit_NeoPixel.h" |
||||||
|
|
||||||
|
#define PIXEL_COUNT 4 * 60 // The number of NeoPixels connected to the board.
|
||||||
|
|
||||||
|
#define PIXEL_PIN 4 // The pin connected to the input of the NeoPixels.
|
||||||
|
|
||||||
|
// Create NeoPixel strip from above parameters.
|
||||||
|
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); |
||||||
|
|
||||||
|
BLEUart bleuart; |
||||||
|
|
||||||
|
// Function prototypes for packetparser.cpp
|
||||||
|
uint8_t readPacket (BLEUart *ble_uart, uint16_t timeout); |
||||||
|
float parsefloat (uint8_t *buffer); |
||||||
|
void printHex (const uint8_t * data, const uint32_t numBytes); |
||||||
|
|
||||||
|
// Packet buffer
|
||||||
|
extern uint8_t packetbuffer[]; |
||||||
|
|
||||||
|
void setup(void) |
||||||
|
{ |
||||||
|
Serial.begin(115200); |
||||||
|
Serial.println(F("Adafruit Bluefruit52 Controller App Example")); |
||||||
|
Serial.println(F("-------------------------------------------")); |
||||||
|
|
||||||
|
// Initialize NeoPixels.
|
||||||
|
strip.begin(); |
||||||
|
for (int i = 0; i < strip.numPixels(); i++) { |
||||||
|
strip.setPixelColor(i, 50, 50, 50); |
||||||
|
} |
||||||
|
strip.show(); |
||||||
|
|
||||||
|
Bluefruit.begin(); |
||||||
|
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
|
||||||
|
Bluefruit.setTxPower(4); |
||||||
|
Bluefruit.setName("Lightstrip"); |
||||||
|
|
||||||
|
// Configure and start the BLE Uart service
|
||||||
|
bleuart.begin(); |
||||||
|
|
||||||
|
// Set up and start advertising
|
||||||
|
startAdv(); |
||||||
|
|
||||||
|
Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode")); |
||||||
|
Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!")); |
||||||
|
Serial.println();
|
||||||
|
} |
||||||
|
|
||||||
|
void startAdv(void) |
||||||
|
{ |
||||||
|
// Advertising packet
|
||||||
|
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); |
||||||
|
Bluefruit.Advertising.addTxPower(); |
||||||
|
|
||||||
|
// Include the BLE UART (AKA 'NUS') 128-bit UUID
|
||||||
|
Bluefruit.Advertising.addService(bleuart); |
||||||
|
|
||||||
|
// Secondary Scan Response packet (optional)
|
||||||
|
// Since there is no room for 'Name' in Advertising packet
|
||||||
|
Bluefruit.ScanResponse.addName(); |
||||||
|
|
||||||
|
/* Start Advertising
|
||||||
|
* - Enable auto advertising if disconnected |
||||||
|
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms |
||||||
|
* - Timeout for fast mode is 30 seconds |
||||||
|
* - Start(timeout) with timeout = 0 will advertise forever (until connected) |
||||||
|
*
|
||||||
|
* For recommended advertising interval |
||||||
|
* https://developer.apple.com/library/content/qa/qa1931/_index.html
|
||||||
|
*/ |
||||||
|
Bluefruit.Advertising.restartOnDisconnect(true); |
||||||
|
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
||||||
|
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||||
|
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
||||||
|
} |
||||||
|
|
||||||
|
/**************************************************************************/ |
||||||
|
/*!
|
||||||
|
@brief Constantly poll for new command or response data |
||||||
|
*/ |
||||||
|
/**************************************************************************/ |
||||||
|
void loop(void) |
||||||
|
{ |
||||||
|
// Wait for new data to arrive
|
||||||
|
uint8_t len = readPacket(&bleuart, 500); |
||||||
|
if (len == 0) return; |
||||||
|
|
||||||
|
// Got a packet!
|
||||||
|
// printHex(packetbuffer, len);
|
||||||
|
|
||||||
|
// Color
|
||||||
|
if (packetbuffer[1] == 'C') { |
||||||
|
uint8_t red = packetbuffer[2]; |
||||||
|
uint8_t green = packetbuffer[3]; |
||||||
|
uint8_t blue = packetbuffer[4]; |
||||||
|
Serial.print ("RGB #"); |
||||||
|
if (red < 0x10) Serial.print("0"); |
||||||
|
Serial.print(red, HEX); |
||||||
|
if (green < 0x10) Serial.print("0"); |
||||||
|
Serial.print(green, HEX); |
||||||
|
if (blue < 0x10) Serial.print("0"); |
||||||
|
Serial.println(blue, HEX); |
||||||
|
|
||||||
|
for (int i = 0; i < strip.numPixels(); i++) { |
||||||
|
strip.setPixelColor(i, red, green, blue); |
||||||
|
} |
||||||
|
strip.show(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,134 @@ |
|||||||
|
#include <string.h> |
||||||
|
#include <Arduino.h> |
||||||
|
#include <bluefruit.h> |
||||||
|
|
||||||
|
|
||||||
|
#define PACKET_ACC_LEN (15) |
||||||
|
#define PACKET_GYRO_LEN (15) |
||||||
|
#define PACKET_MAG_LEN (15) |
||||||
|
#define PACKET_QUAT_LEN (19) |
||||||
|
#define PACKET_BUTTON_LEN (5) |
||||||
|
#define PACKET_COLOR_LEN (6) |
||||||
|
#define PACKET_LOCATION_LEN (15) |
||||||
|
|
||||||
|
// READ_BUFSIZE Size of the read buffer for incoming packets
|
||||||
|
#define READ_BUFSIZE (20) |
||||||
|
|
||||||
|
|
||||||
|
/* Buffer to hold incoming characters */ |
||||||
|
uint8_t packetbuffer[READ_BUFSIZE+1]; |
||||||
|
|
||||||
|
/**************************************************************************/ |
||||||
|
/*!
|
||||||
|
@brief Casts the four bytes at the specified address to a float |
||||||
|
*/ |
||||||
|
/**************************************************************************/ |
||||||
|
float parsefloat(uint8_t *buffer)
|
||||||
|
{ |
||||||
|
float f; |
||||||
|
memcpy(&f, buffer, 4); |
||||||
|
return f; |
||||||
|
} |
||||||
|
|
||||||
|
/**************************************************************************/ |
||||||
|
/*!
|
||||||
|
@brief Prints a hexadecimal value in plain characters |
||||||
|
@param data Pointer to the byte data |
||||||
|
@param numBytes Data length in bytes |
||||||
|
*/ |
||||||
|
/**************************************************************************/ |
||||||
|
void printHex(const uint8_t * data, const uint32_t numBytes) |
||||||
|
{ |
||||||
|
uint32_t szPos; |
||||||
|
for (szPos=0; szPos < numBytes; szPos++)
|
||||||
|
{ |
||||||
|
Serial.print(F("0x")); |
||||||
|
// Append leading 0 for small values
|
||||||
|
if (data[szPos] <= 0xF) |
||||||
|
{ |
||||||
|
Serial.print(F("0")); |
||||||
|
Serial.print(data[szPos] & 0xf, HEX); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Serial.print(data[szPos] & 0xff, HEX); |
||||||
|
} |
||||||
|
// Add a trailing space if appropriate
|
||||||
|
if ((numBytes > 1) && (szPos != numBytes - 1)) |
||||||
|
{ |
||||||
|
Serial.print(F(" ")); |
||||||
|
} |
||||||
|
} |
||||||
|
Serial.println(); |
||||||
|
} |
||||||
|
|
||||||
|
/**************************************************************************/ |
||||||
|
/*!
|
||||||
|
@brief Waits for incoming data and parses it |
||||||
|
*/ |
||||||
|
/**************************************************************************/ |
||||||
|
uint8_t readPacket(BLEUart *ble_uart, uint16_t timeout)
|
||||||
|
{ |
||||||
|
uint16_t origtimeout = timeout, replyidx = 0; |
||||||
|
|
||||||
|
memset(packetbuffer, 0, READ_BUFSIZE); |
||||||
|
|
||||||
|
while (timeout--) { |
||||||
|
if (replyidx >= 20) break; |
||||||
|
if ((packetbuffer[1] == 'A') && (replyidx == PACKET_ACC_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'G') && (replyidx == PACKET_GYRO_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'M') && (replyidx == PACKET_MAG_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'Q') && (replyidx == PACKET_QUAT_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'B') && (replyidx == PACKET_BUTTON_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'C') && (replyidx == PACKET_COLOR_LEN)) |
||||||
|
break; |
||||||
|
if ((packetbuffer[1] == 'L') && (replyidx == PACKET_LOCATION_LEN)) |
||||||
|
break; |
||||||
|
|
||||||
|
while (ble_uart->available()) { |
||||||
|
char c = ble_uart->read(); |
||||||
|
if (c == '!') { |
||||||
|
replyidx = 0; |
||||||
|
} |
||||||
|
packetbuffer[replyidx] = c; |
||||||
|
replyidx++; |
||||||
|
timeout = origtimeout; |
||||||
|
} |
||||||
|
|
||||||
|
if (timeout == 0) break; |
||||||
|
delay(1); |
||||||
|
} |
||||||
|
|
||||||
|
packetbuffer[replyidx] = 0; // null term
|
||||||
|
|
||||||
|
if (!replyidx) // no data or timeout
|
||||||
|
return 0; |
||||||
|
if (packetbuffer[0] != '!') // doesn't start with '!' packet beginning
|
||||||
|
return 0; |
||||||
|
|
||||||
|
// check checksum!
|
||||||
|
uint8_t xsum = 0; |
||||||
|
uint8_t checksum = packetbuffer[replyidx-1]; |
||||||
|
|
||||||
|
for (uint8_t i=0; i<replyidx-1; i++) { |
||||||
|
xsum += packetbuffer[i]; |
||||||
|
} |
||||||
|
xsum = ~xsum; |
||||||
|
|
||||||
|
// Throw an error message if the checksum's don't match
|
||||||
|
if (xsum != checksum) |
||||||
|
{ |
||||||
|
Serial.print("Checksum mismatch in packet : "); |
||||||
|
printHex(packetbuffer, replyidx+1); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// checksum passed!
|
||||||
|
return replyidx; |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue