Change protocol to protobuf + SLIP

This commit is contained in:
Patrick Moessler 2019-10-16 23:03:18 +02:00
parent 8da1adcb9b
commit 8c6a205efd
2 changed files with 526 additions and 307 deletions

View file

@ -1,4 +0,0 @@
#include <pb.h>
#include <pb_decode.h>
#include <fx.pb.h>

View file

@ -1,9 +1,13 @@
#include <Arduino.h>
#include <WS2812FX.h>
#include <bluefruit.h>
#include "uartproto.h"
#include <cstdint>
#include <fx.pb.h>
#include <pb.h>
#include <pb_decode.h>
#include <slip/Stream.h>
#define NEOPIXEL_VERSION_STRING "Neopixel v2.0"
#define NEOPIXEL_VERSION_STRING "BLEtail 1.0"
#define PIN 30 /* Pin used to drive the NeoPixels */
#define MAXCOMPONENTS 4
@ -22,22 +26,16 @@ BLEDfu bledfu;
BLEDis bledis;
BLEUart bleuart;
// framing
packetio::SLIPStream bleslip(bleuart);
void startAdv(void);
void connect_callback(uint16_t conn_handle);
void swapBuffers();
void commandVersion();
void commandSetup();
void commandSetBrightness();
void commandSetSpeed();
void commandSetMode();
void commandClearColor();
void commandSetPixel();
void commandImage();
void commandHalt();
void sendResponse(char const *);
void dispatch(fx_Root &fx);
void setup()
{
void setup() {
Serial.begin(115200);
while (!Serial)
delay(10); // for nrf52840 with native usb
@ -46,28 +44,14 @@ void setup()
Serial.println("--------------------------------");
Serial.println();
Serial.println("Please connect using the Bluefruit Connect LE application");
Serial.println("Please connect using the BLEtail application");
// Config Neopixels
ws2812fx.init();
ws2812fx.setLength(40);
ws2812fx.setBrightness(50);
ws2812fx.setSpeed(200);
// ws2812fx.setMode(FX_MODE_RAINBOW);
// ws2812fx.setNumSegments(5);
// ws2812fx.setSegment(0, 0*(40/5), 1*(40/5)-1, FX_MODE_RAINBOW_CYCLE, RED, 200, false);
// ws2812fx.setSegment(1, 1*(40/5), 2*(40/5)-1, FX_MODE_STATIC, BLACK, 200, false);
// ws2812fx.setSegment(2, 2*(40/5), 3*(40/5)-1, FX_MODE_RAINBOW_CYCLE, RED, 200, REVERSE);
// ws2812fx.setSegment(4, 3*(40/5), 4*(40/5)-1, FX_MODE_STATIC, BLACK, 200, false);
// ws2812fx.setSegment(5, 4*(40/5), 5*(40/5)-1, FX_MODE_RAINBOW_CYCLE, GREEN, 200, false);
// ws2812fx.setSegment(0, 0 * (40 / 5), 1 * (40 / 5) - 1, FX_MODE_COLOR_WIPE, YELLOW, 400, false);
// ws2812fx.setSegment(1, 1 * (40 / 5), 2 * (40 / 5) - 1, FX_MODE_COLOR_WIPE, YELLOW, 400, false);
// ws2812fx.setSegment(2, 2 * (40 / 5), 3 * (40 / 5) - 1, FX_MODE_STATIC, BLACK, 200, REVERSE);
// ws2812fx.setSegment(4, 3 * (40 / 5), 4 * (40 / 5) - 1, FX_MODE_FADE, YELLOW, 800, false);
// ws2812fx.setSegment(5, 4 * (40 / 5), 5 * (40 / 5) - 1, FX_MODE_FADE, YELLOW, 800, false);
ws2812fx.setBrightness(10);
ws2812fx.setSpeed(0x1000);
ws2812fx.setMode(FX_MODE_RAINBOW);
ws2812fx.start();
@ -92,8 +76,7 @@ void setup()
startAdv();
}
void startAdv(void)
{
void startAdv(void) {
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
@ -110,18 +93,17 @@ void startAdv(void)
* - 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
* 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
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
void connect_callback(uint16_t conn_handle)
{
void connect_callback(uint16_t conn_handle) {
// Get the reference to current connection
BLEConnection *connection = Bluefruit.Connection(conn_handle);
@ -130,327 +112,569 @@ void connect_callback(uint16_t conn_handle)
Serial.print("Connected to ");
Serial.println(central_name);
Serial.println("Please select the 'Neopixels' tab, click 'Connect' and have fun");
}
void loop()
{
// Echo received data
if (Bluefruit.connected() && bleuart.notifyEnabled())
{
int command = bleuart.read();
uint8_t parseOptions(const fx_Options &opts) {
uint8_t o = 0;
if (opts.reverse) {
o |= REVERSE;
}
if (opts.gammaCorrect) {
o |= GAMMA;
}
o |= (opts.fadeRate << 4);
o |= (opts.size << 1);
return o;
}
switch (command)
{
case 'V':
{ // Get Version
commandVersion();
break;
}
uint32_t colorFromRGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return ((uint32_t)w) << 24 | ((uint32_t)r) << 16 | ((uint32_t)g) << 8 |
((uint32_t)b);
}
case 'S':
{ // Setup dimensions, components, stride...
commandSetup();
break;
static bool pb_stream_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) {
Stream *s = reinterpret_cast<Stream *>(stream->state);
int c = s->read();
if (c >= 0) {
*buf = c;
// Serial.print("rx:");
// Serial.println(c);
} else if (c == packetio::PacketStream::EOP) {
stream->bytes_left = 0;
// Serial.println("eop");
reinterpret_cast<packetio::SLIPStream *>(stream->state)->next();
return false;
} else if (c == packetio::PacketStream::EOF) {
if(stream->bytes_left == 0){
stream->bytes_left = SIZE_MAX;
}
// ignore. will be called again
} else {
Serial.print("err:");
Serial.println(c);
}
return true;
};
case 'C':
{ // Clear with color
commandClearColor();
break;
}
pb_istream_s as_pb_istream(Stream &s) {
return {pb_stream_read, &s, SIZE_MAX};
};
case 'B':
{ // Set Brightness
commandSetBrightness();
break;
}
case 'M':
{ // Set Mode
commandSetMode();
break;
}
case 's':
{ // Set Speed
commandSetSpeed();
break;
}
pb_istream_s pb_in = as_pb_istream(bleslip);
case 'P':
{ // Set Pixel
commandSetPixel();
break;
}
case 'I':
{ // Receive new image
commandImage();
break;
}
case 'H':
{ // Receive new image
commandHalt();
break;
}
void loop() {
if (Bluefruit.connected() && bleuart.notifyEnabled()) {
fx_Root fx = fx_Root_init_zero;
if (pb_decode(&pb_in, fx_Root_fields, &fx)) {
Serial.print("pb decode:");
Serial.println(fx.which_msg);
dispatch(fx);
pb_in = as_pb_istream(bleslip); // reset stream for next packet
}
}
ws2812fx.service();
}
void swapBuffers()
{
uint8_t *base_addr = pixelBuffer;
int pixelIndex = 0;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
if (components == 3)
{
ws2812fx.setPixelColor(pixelIndex, ws2812fx.Color(*base_addr, *(base_addr + 1), *(base_addr + 2)));
}
else
{
ws2812fx.setPixelColor(pixelIndex, ws2812fx.Color(*base_addr, *(base_addr + 1), *(base_addr + 2), *(base_addr + 3)));
}
base_addr += components;
pixelIndex++;
}
pixelIndex += stride - width; // Move pixelIndex to the next row (take into account the stride)
}
ws2812fx.show();
void dispatch(fx_Root &fx) {
// switch (fx.which_msg) {
// case fx_Root_start_tag: {
// ws2812fx.start();
// break;
// }
// case fx_Root_stop_tag: {
// ws2812fx.stop();
// break;
// }
// case fx_Root_pause_tag: {
// ws2812fx.pause();
// break;
// }
// case fx_Root_resume_tag: {
// ws2812fx.resume();
// break;
// }
// case fx_Root_strip_off_tag: {
// ws2812fx.strip_off();
// break;
// }
// case fx_Root_fade_out_tag: {
// if (fx.msg.fade_out.has_fadeTime) {
// ws2812fx.fade_out(fx.msg.fade_out.fadeTime);
// } else {
// ws2812fx.fade_out();
// }
// break;
// }
// case fx_Root_setMode_tag: {
// if (fx.msg.setMode.has_segment) {
// ws2812fx.setMode(static_cast<uint8_t>(fx.msg.setMode.mode));
// } else {
// ws2812fx.setMode(static_cast<uint8_t>(fx.msg.setMode.segment),
// static_cast<uint8_t>(fx.msg.setMode.mode));
// }
// break;
// }
// case fx_Root_setOptions_tag: {
// ws2812fx.setOptions(fx.msg.setOptions.segment,
// parseOptions(fx.msg.setOptions.options));
// break;
// }
// case fx_Root_setSpeed_tag: {
// if (fx.msg.setSpeed.has_segment) {
// ws2812fx.setSpeed(static_cast<uint8_t>(fx.msg.setSpeed.speed));
// } else {
// ws2812fx.setSpeed(static_cast<uint8_t>(fx.msg.setSpeed.segment),
// static_cast<uint8_t>(fx.msg.setSpeed.speed));
// }
// break;
// }
// case fx_Root_increaseSpeed_tag: {
// ws2812fx.increaseSpeed(fx.msg.increaseSpeed.step);
// break;
// }
// case fx_Root_decreaseSpeed_tag: {
// ws2812fx.decreaseSpeed(fx.msg.decreaseSpeed.step);
// break;
// }
// case fx_Root_setColor_tag: {
// switch (fx.msg.setColor.color.which_colorTypes) {
// case fx_ColorType_rgb_tag: {
// ws2812fx.setColor(fx.msg.setColor.color.colorTypes.rgb.r,
// fx.msg.setColor.color.colorTypes.rgb.b,
// fx.msg.setColor.color.colorTypes.rgb.g);
// break;
// }
// case fx_ColorType_rgbw_tag: {
// ws2812fx.setColor(fx.msg.setColor.color.colorTypes.rgbw.r,
// fx.msg.setColor.color.colorTypes.rgbw.b,
// fx.msg.setColor.color.colorTypes.rgbw.g,
// fx.msg.setColor.color.colorTypes.rgbw.w);
// break;
// }
// case fx_ColorType_color_tag: {
// if (fx.msg.setColor.has_segment) {
// ws2812fx.setColor(fx.msg.setColor.segment,
// fx.msg.setColor.color.colorTypes.color);
// } else {
// ws2812fx.setColor(fx.msg.setColor.color.colorTypes.color);
// }
// break;
// }
// case fx_ColorType_multiColor_tag: {
// uint32_t colors[NUM_COLORS] = {
// fx.msg.setColor.color.colorTypes.multiColor.col1,
// fx.msg.setColor.color.colorTypes.multiColor.col2,
// fx.msg.setColor.color.colorTypes.multiColor.col3};
// if (fx.msg.setColor.has_segment) {
// ws2812fx.setColors(fx.msg.setColor.segment, colors);
// } else {
// ws2812fx.setColors(0, colors);
// }
// break;
// }
// }
// break;
// }
// case fx_Root_setBrightness_tag: {
// ws2812fx.setBrightness(fx.msg.setBrightness.brightness);
// break;
// }
// case fx_Root_increaseBrightness_tag: {
// ws2812fx.increaseBrightness(fx.msg.increaseBrightness.step);
// break;
// }
// case fx_Root_decreaseBrightness_tag: {
// ws2812fx.decreaseBrightness(fx.msg.decreaseBrightness.step);
// break;
// }
// case fx_Root_setLength_tag: {
// ws2812fx.setLength(fx.msg.setLength.numPixels);
// break;
// }
// case fx_Root_increaseLength_tag: {
// ws2812fx.increaseLength(fx.msg.increaseLength.step);
// break;
// }
// case fx_Root_decreaseLength_tag: {
// ws2812fx.decreaseLength(fx.msg.decreaseLength.step);
// break;
// }
// case fx_Root_trigger_tag: {
// ws2812fx.trigger();
// break;
// }
// case fx_Root_setNumSegments_tag: {
// ws2812fx.setNumSegments(fx.msg.setNumSegments.numSegments);
// break;
// }
// case fx_Root_setSegment_tag: {
// switch (fx.msg.setSegment.color.which_colorTypes) {
// case fx_ColorType_rgb_tag: {
// ws2812fx.setSegment(
// fx.msg.setSegment.segment, fx.msg.setSegment.start,
// fx.msg.setSegment.end, fx.msg.setSegment.mode,
// colorFromRGBW(fx.msg.setSegment.color.colorTypes.rgb.r,
// fx.msg.setSegment.color.colorTypes.rgb.g,
// fx.msg.setSegment.color.colorTypes.rgb.b, 0),
// fx.msg.setSegment.speed,
// parseOptions(fx.msg.setSegment.options));
// break;
// }
// case fx_ColorType_rgbw_tag: {
// ws2812fx.setSegment(
// fx.msg.setSegment.segment, fx.msg.setSegment.start,
// fx.msg.setSegment.end, fx.msg.setSegment.mode,
// colorFromRGBW(fx.msg.setSegment.color.colorTypes.rgbw.r,
// fx.msg.setSegment.color.colorTypes.rgbw.g,
// fx.msg.setSegment.color.colorTypes.rgbw.b,
// fx.msg.setSegment.color.colorTypes.rgbw.w),
// fx.msg.setSegment.speed,
// parseOptions(fx.msg.setSegment.options));
// break;
// }
// case fx_ColorType_color_tag: {
// ws2812fx.setSegment(
// fx.msg.setSegment.segment, fx.msg.setSegment.start,
// fx.msg.setSegment.end, fx.msg.setSegment.mode,
// fx.msg.setSegment.color.colorTypes.color,
// fx.msg.setSegment.speed,
// parseOptions(fx.msg.setSegment.options));
// break;
// }
// case fx_ColorType_multiColor_tag: {
// uint32_t colors[NUM_COLORS] = {
// fx.msg.setSegment.color.colorTypes.multiColor.col1,
// fx.msg.setSegment.color.colorTypes.multiColor.col2,
// fx.msg.setSegment.color.colorTypes.multiColor.col3};
// ws2812fx.setSegment(
// fx.msg.setSegment.segment, fx.msg.setSegment.start,
// fx.msg.setSegment.end, fx.msg.setSegment.mode, colors,
// fx.msg.setSegment.speed,
// parseOptions(fx.msg.setSegment.options));
// break;
// }
// }
// break;
// }
// case fx_Root_resetSegments_tag: {
// ws2812fx.resetSegments();
// break;
// }
// case fx_Root_resetSegmentRuntimes_tag: {
// ws2812fx.resetSegmentRuntimes();
// break;
// }
// case fx_Root_resetSegmentRuntime_tag: {
// ws2812fx.resetSegmentRuntime(fx.msg.resetSegmentRuntime.segment);
// break;
// }
// case fx_Root_setPixelColor_tag: {
// switch (fx.msg.setPixelColor.color.which_colorTypes) {
// case fx_ColorType_rgb_tag: {
// ws2812fx.setPixelColor(fx.msg.setPixelColor.offset,
// fx.msg.setPixelColor.color.colorTypes.rgb.r,
// fx.msg.setPixelColor.color.colorTypes.rgb.b,
// fx.msg.setPixelColor.color.colorTypes.rgb.g);
// break;
// }
// case fx_ColorType_rgbw_tag: {
// ws2812fx.setPixelColor(fx.msg.setPixelColor.offset,
// fx.msg.setPixelColor.color.colorTypes.rgbw.r,
// fx.msg.setPixelColor.color.colorTypes.rgbw.b,
// fx.msg.setPixelColor.color.colorTypes.rgbw.g,
// fx.msg.setPixelColor.color.colorTypes.rgbw.w);
// break;
// }
// case fx_ColorType_color_tag: {
// ws2812fx.setPixelColor(fx.msg.setPixelColor.offset,
// fx.msg.setPixelColor.color.colorTypes.color);
// break;
// }
// }
// break;
// }
// case fx_Root_copyPixels_tag: {
// ws2812fx.copyPixels(fx.msg.copyPixels.destination,
// fx.msg.copyPixels.source,
// fx.msg.copyPixels.count);
// break;
// }
// case fx_Root_display_tag: {
// break;
// }
// case fx_Root_show_tag: {
// ws2812fx.show();
// break;
// }
// case fx_Root_halt_tag: {
// commandHalt();
// break;
// }
// }
}
void commandVersion()
{
Serial.println(F("Command: Version check"));
sendResponse(NEOPIXEL_VERSION_STRING);
}
// void swapBuffers()
// {
// uint8_t *base_addr = pixelBuffer;
// int pixelIndex = 0;
// for (int j = 0; j < height; j++)
// {
// for (int i = 0; i < width; i++)
// {
// if (components == 3)
// {
// ws2812fx.setPixelColor(pixelIndex, ws2812fx.Color(*base_addr,
// *(base_addr + 1), *(base_addr + 2)));
// }
// else
// {
// ws2812fx.setPixelColor(pixelIndex, ws2812fx.Color(*base_addr,
// *(base_addr + 1), *(base_addr + 2), *(base_addr + 3)));
// }
// base_addr += components;
// pixelIndex++;
// }
// pixelIndex += stride - width; // Move pixelIndex to the next row (take
// into account the stride)
// }
// ws2812fx.show();
// }
void commandSetup()
{
Serial.println(F("Command: Setup"));
// void commandVersion()
// {
// Serial.println(F("Command: Version check"));
// sendResponse(NEOPIXEL_VERSION_STRING);
// }
ws2812fx.stop();
// void commandSetup()
// {
// Serial.println(F("Command: Setup"));
width = bleuart.read();
height = bleuart.read();
stride = bleuart.read();
componentsValue = bleuart.read();
is400Hz = bleuart.read();
// ws2812fx.stop();
neoPixelType pixelType;
pixelType = componentsValue + (is400Hz ? NEO_KHZ400 : NEO_KHZ800);
// width = bleuart.read();
// height = bleuart.read();
// stride = bleuart.read();
// componentsValue = bleuart.read();
// is400Hz = bleuart.read();
components = (componentsValue == NEO_RGB || componentsValue == NEO_RBG || componentsValue == NEO_GRB || componentsValue == NEO_GBR || componentsValue == NEO_BRG || componentsValue == NEO_BGR) ? 3 : 4;
// neoPixelType pixelType;
// pixelType = componentsValue + (is400Hz ? NEO_KHZ400 : NEO_KHZ800);
Serial.printf("\tsize: %dx%d\n", width, height);
Serial.printf("\tstride: %d\n", stride);
Serial.printf("\tpixelType %d\n", pixelType);
Serial.printf("\tcomponents: %d\n", components);
// components = (componentsValue == NEO_RGB || componentsValue == NEO_RBG ||
// componentsValue == NEO_GRB || componentsValue == NEO_GBR || componentsValue
// == NEO_BRG || componentsValue == NEO_BGR) ? 3 : 4;
if (pixelBuffer != NULL)
{
delete[] pixelBuffer;
}
// Serial.printf("\tsize: %dx%d\n", width, height);
// Serial.printf("\tstride: %d\n", stride);
// Serial.printf("\tpixelType %d\n", pixelType);
// Serial.printf("\tcomponents: %d\n", components);
uint32_t size = width * height;
pixelBuffer = new uint8_t[size * components];
ws2812fx.updateLength(size);
ws2812fx.updateType(pixelType);
ws2812fx.setPin(PIN);
// if (pixelBuffer != NULL)
// {
// delete[] pixelBuffer;
// }
ws2812fx.start();
// uint32_t size = width * height;
// pixelBuffer = new uint8_t[size * components];
// ws2812fx.updateLength(size);
// ws2812fx.updateType(pixelType);
// ws2812fx.setPin(PIN);
// Done
sendResponse("OK");
}
// ws2812fx.start();
void commandSetBrightness()
{
Serial.println(F("Command: SetBrightness"));
// // Done
// sendResponse("OK");
// }
// Read value
uint8_t brightness = bleuart.read();
// void commandSetBrightness()
// {
// Serial.println(F("Command: SetBrightness"));
// Set brightness
ws2812fx.setBrightness(brightness);
// // Read value
// uint8_t brightness = bleuart.read();
// Refresh pixels
// swapBuffers();
// // Set brightness
// ws2812fx.setBrightness(brightness);
// Done
sendResponse("OK");
}
// // Refresh pixels
// // swapBuffers();
void commandSetMode()
{
Serial.println(F("Command: SetMode"));
// // Done
// sendResponse("OK");
// }
// Read value
uint8_t mode = bleuart.read();
// void commandSetMode()
// {
// Serial.println(F("Command: SetMode"));
// Set mode
ws2812fx.setMode(mode);
ws2812fx.resume();
// // Read value
// uint8_t mode = bleuart.read();
// Done
sendResponse("OK");
}
// // Set mode
// ws2812fx.setMode(mode);
// ws2812fx.resume();
void commandSetSpeed()
{
Serial.println(F("Command: SetSpeed"));
// // Done
// sendResponse("OK");
// }
// Read value
uint16_t speed = (bleuart.read() << 8) | bleuart.read();
// void commandSetSpeed()
// {
// Serial.println(F("Command: SetSpeed"));
// Set speed
ws2812fx.setSpeed(speed);
ws2812fx.resume();
// // Read value
// uint16_t speed = (bleuart.read() << 8) | bleuart.read();
// Done
sendResponse("OK");
}
// // Set speed
// ws2812fx.setSpeed(speed);
// ws2812fx.resume();
void commandClearColor()
{
Serial.println(F("Command: ClearColor"));
// // Done
// sendResponse("OK");
// }
// Read color
uint8_t color[MAXCOMPONENTS];
for (int j = 0; j < components;)
{
if (bleuart.available())
{
color[j] = bleuart.read();
j++;
}
}
// void commandClearColor()
// {
// Serial.println(F("Command: ClearColor"));
ws2812fx.setMode(FX_MODE_STATIC);
ws2812fx.setColor(*(reinterpret_cast<uint32_t *>(color)));
// // Read color
// uint8_t color[MAXCOMPONENTS];
// for (int j = 0; j < components;)
// {
// if (bleuart.available())
// {
// color[j] = bleuart.read();
// j++;
// }
// }
// Set all leds to color
// int size = width * height;
// uint8_t *base_addr = pixelBuffer;
// for (int i = 0; i < size; i++)
// {
// // ws2812fx.setPixelColor(i, *(reinterpret_cast<uint32_t*>(color)));
// for (int j = 0; j < components; j++)
// {
// *base_addr = color[j];
// base_addr++;
// }
// }
// ws2812fx.setMode(FX_MODE_STATIC);
// ws2812fx.setColor(*(reinterpret_cast<uint32_t *>(color)));
// Swap buffers
Serial.println(F("ClearColor completed"));
// swapBuffers();
// // Set all leds to color
// // int size = width * height;
// // uint8_t *base_addr = pixelBuffer;
// // for (int i = 0; i < size; i++)
// // {
// // // ws2812fx.setPixelColor(i, *(reinterpret_cast<uint32_t*>(color)));
// // for (int j = 0; j < components; j++)
// // {
// // *base_addr = color[j];
// // base_addr++;
// // }
// // }
if (components == 3)
{
Serial.printf("\tclear (%d, %d, %d)\n", color[0], color[1], color[2]);
}
else
{
Serial.printf("\tclear (%d, %d, %d, %d)\n", color[0], color[1], color[2], color[3]);
}
// // Swap buffers
// Serial.println(F("ClearColor completed"));
// // swapBuffers();
// Done
sendResponse("OK");
}
// if (components == 3)
// {
// Serial.printf("\tclear (%d, %d, %d)\n", color[0], color[1], color[2]);
// }
// else
// {
// Serial.printf("\tclear (%d, %d, %d, %d)\n", color[0], color[1], color[2],
// color[3]);
// }
void commandSetPixel()
{
Serial.println(F("Command: SetPixel"));
// // Done
// sendResponse("OK");
// }
// Read position
uint8_t x = bleuart.read();
uint8_t y = bleuart.read();
// void commandSetPixel()
// {
// Serial.println(F("Command: SetPixel"));
// Read colors
uint32_t pixelOffset = y * width + x;
uint32_t pixelDataOffset = pixelOffset * components;
uint8_t *base_addr = pixelBuffer + pixelDataOffset;
for (int j = 0; j < components;)
{
if (bleuart.available())
{
*base_addr = bleuart.read();
base_addr++;
j++;
}
}
// // Read position
// uint8_t x = bleuart.read();
// uint8_t y = bleuart.read();
// Set colors
uint32_t ws2812fxIndex = y * stride + x;
uint8_t *pixelBufferPointer = pixelBuffer + pixelDataOffset;
uint32_t color;
if (components == 3)
{
color = ws2812fx.Color(*pixelBufferPointer, *(pixelBufferPointer + 1), *(pixelBufferPointer + 2));
Serial.printf("\tcolor (%d, %d, %d)\n", *pixelBufferPointer, *(pixelBufferPointer + 1), *(pixelBufferPointer + 2));
}
else
{
color = ws2812fx.Color(*pixelBufferPointer, *(pixelBufferPointer + 1), *(pixelBufferPointer + 2), *(pixelBufferPointer + 3));
Serial.printf("\tcolor (%d, %d, %d, %d)\n", *pixelBufferPointer, *(pixelBufferPointer + 1), *(pixelBufferPointer + 2), *(pixelBufferPointer + 3));
}
ws2812fx.pause();
ws2812fx.setPixelColor(ws2812fxIndex, color);
ws2812fx.show();
// // Read colors
// uint32_t pixelOffset = y * width + x;
// uint32_t pixelDataOffset = pixelOffset * components;
// uint8_t *base_addr = pixelBuffer + pixelDataOffset;
// for (int j = 0; j < components;)
// {
// if (bleuart.available())
// {
// *base_addr = bleuart.read();
// base_addr++;
// j++;
// }
// }
// Done
sendResponse("OK");
}
// // Set colors
// uint32_t ws2812fxIndex = y * stride + x;
// uint8_t *pixelBufferPointer = pixelBuffer + pixelDataOffset;
// uint32_t color;
// if (components == 3)
// {
// color = ws2812fx.Color(*pixelBufferPointer, *(pixelBufferPointer + 1),
// *(pixelBufferPointer + 2)); Serial.printf("\tcolor (%d, %d, %d)\n",
// *pixelBufferPointer, *(pixelBufferPointer + 1), *(pixelBufferPointer +
// 2));
// }
// else
// {
// color = ws2812fx.Color(*pixelBufferPointer, *(pixelBufferPointer + 1),
// *(pixelBufferPointer + 2), *(pixelBufferPointer + 3));
// Serial.printf("\tcolor (%d, %d, %d, %d)\n", *pixelBufferPointer,
// *(pixelBufferPointer + 1), *(pixelBufferPointer + 2),
// *(pixelBufferPointer + 3));
// }
// ws2812fx.pause();
// ws2812fx.setPixelColor(ws2812fxIndex, color);
// ws2812fx.show();
void commandImage()
{
Serial.printf("Command: Image %dx%d, %d, %d\n", width, height, components, stride);
// // Done
// sendResponse("OK");
// }
ws2812fx.pause();
// void commandImage()
// {
// Serial.printf("Command: Image %dx%d, %d, %d\n", width, height, components,
// stride);
// Receive new pixel buffer
int size = width * height;
uint8_t *base_addr = pixelBuffer;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < components;)
{
if (bleuart.available())
{
*base_addr = bleuart.read();
base_addr++;
j++;
}
}
// ws2812fx.pause();
/*
if (components == 3) {
uint32_t index = i*components;
Serial.printf("\tp%d (%d, %d, %d)\n", i, pixelBuffer[index], pixelBuffer[index+1], pixelBuffer[index+2] );
}
*/
}
// // Receive new pixel buffer
// int size = width * height;
// uint8_t *base_addr = pixelBuffer;
// for (int i = 0; i < size; i++)
// {
// for (int j = 0; j < components;)
// {
// if (bleuart.available())
// {
// *base_addr = bleuart.read();
// base_addr++;
// j++;
// }
// }
// Swap buffers
Serial.println(F("Image received"));
swapBuffers();
// /*
// if (components == 3) {
// uint32_t index = i*components;
// Serial.printf("\tp%d (%d, %d, %d)\n", i, pixelBuffer[index],
// pixelBuffer[index+1], pixelBuffer[index+2] );
// }
// */
// }
// Done
sendResponse("OK");
}
// // Swap buffers
// Serial.println(F("Image received"));
// swapBuffers();
void commandHalt()
{
// // Done
// sendResponse("OK");
// }
void commandHalt() {
sendResponse("power off");
ws2812fx.stop();
if (Bluefruit.connected())
{
if (Bluefruit.connected()) {
Bluefruit.disconnect(Bluefruit.connHandle());
}
@ -460,8 +684,7 @@ void commandHalt()
sd_power_system_off();
}
void sendResponse(char const *response)
{
void sendResponse(char const *response) {
Serial.printf("Send Response: %s\n", response);
bleuart.write(response, strlen(response) * sizeof(char));
// bleuart.write(response, strlen(response) * sizeof(char));
}