Reworking the communcation

This commit is contained in:
2025-12-23 23:36:51 +00:00
parent ce15563aee
commit dc23bbaf5b
10 changed files with 409 additions and 140 deletions
+16
View File
@@ -0,0 +1,16 @@
#include "commands.h"
char* CommandToStr(Command id) {
switch(id) {
case CmdRequestID:
return (char*)"CmdRequestID";
case CmdAckID:
return (char*)"CmdAckID";
case CmdCreateWindow:
return (char*)"CmdCreateWindow";
case CmdDestroyWindow:
return (char*)"CmdDestroyWindow";
}
return (char*)"CmdInvalid";
}
+6 -4
View File
@@ -4,11 +4,13 @@
#include <stdint.h>
typedef enum : uint8_t {
CmdRequestID = 0,
CmdAckID,
CmdCreateScreen,
CmdCreateWindow
CmdUnknown = 0,
CmdRequestID = 1,
CmdAckID = 2,
CmdCreateWindow = 3,
CmdDestroyWindow = 4
} Command;
char* CommandToStr(Command id);
#endif
+9
View File
@@ -1 +1,10 @@
#include "communication.h"
uint8_t CRC8(const uint8_t *data, size_t len) {
uint8_t crc = 0x00;
while (len--) {
crc = pgm_read_byte(&crc8_table[crc ^ *data++]);
}
return crc;
}
+43 -1
View File
@@ -1,6 +1,48 @@
#ifndef __COMMUNICATION__
#define __COMMUNICATION__
int router();
#include "pgmspace.h"
#include <Arduino.h>
#include <cstdint>
const byte STX = 0x02;
const byte ETX = 0x03;
const byte ACK = 0x06;
static const uint8_t crc8_table[256] PROGMEM = {
0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,
0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
0x70,0x77,0x7E,0x79,0x6C,0x6B,0x62,0x65,
0x48,0x4F,0x46,0x41,0x54,0x53,0x5A,0x5D,
0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,
0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,
0x90,0x97,0x9E,0x99,0x8C,0x8B,0x82,0x85,
0xA8,0xAF,0xA6,0xA1,0xB4,0xB3,0xBA,0xBD,
0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,0xD5,0xD2,
0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,
0x8F,0x88,0x81,0x86,0x93,0x94,0x9D,0x9A,
0x27,0x20,0x29,0x2E,0x3B,0x3C,0x35,0x32,
0x1F,0x18,0x11,0x16,0x03,0x04,0x0D,0x0A,
0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,
0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,
0x89,0x8E,0x87,0x80,0x95,0x92,0x9B,0x9C,
0xB1,0xB6,0xBF,0xB8,0xAD,0xAA,0xA3,0xA4,
0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,0xEB,0xEC,
0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,
0x51,0x56,0x5F,0x58,0x4D,0x4A,0x43,0x44,
0x19,0x1E,0x17,0x10,0x05,0x02,0x0B,0x0C,
0x21,0x26,0x2F,0x28,0x3D,0x3A,0x33,0x34,
0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,
0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,
0x3E,0x39,0x30,0x37,0x22,0x25,0x2C,0x2B,
0x06,0x01,0x08,0x0F,0x1A,0x1D,0x14,0x13,
0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,0xBC,0xBB,
0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,
0xE6,0xE1,0xE8,0xEF,0xFA,0xFD,0xF4,0xF3
};
uint8_t CRC8(const uint8_t *data, size_t len);
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef __IDENTIFICATION_PACKET__
#define __IDENTIFICATION_PACKET__
#include "packets.h"
#include <cstdint>
#include <stdint.h>
// eventually try this out with __attrubute__((packed))
struct __attribute__((packed)) IdentificationPacket {
char StartMarker;
uint8_t DeviceID;
PacketType PktType;
char deviceName[32];
char EndMarker;
};
void initIdentificationPacket(IdentificationPacket* packet, const char* name,
uint8_t id);
void sendIdentificationPacket(IdentificationPacket* packet);
#endif
@@ -1,4 +1,4 @@
#include "identificationPacket.h"
#include "packets.h"
#include <Arduino.h>
#include <cstdint>
#include <cstring>
@@ -16,8 +16,3 @@ void initIdentificationPacket(IdentificationPacket* packet, const char* name,
strncpy(packet->deviceName, name, strlen(name));
packet->deviceName[strlen(name)] = '\0';
}
void sendIdentificationPacket(IdentificationPacket* packet) {
Serial.write((uint8_t*)packet, sizeof(*packet));
Serial.flush();
}
+21
View File
@@ -6,4 +6,25 @@
typedef uint8_t PacketType;
const uint8_t identificationPacket = 0;
struct __attribute__((packed)) IdentificationPacket {
char StartMarker;
uint8_t DeviceID;
PacketType PktType;
char deviceName[32];
char EndMarker;
};
void initIdentificationPacket(IdentificationPacket* packet, const char* name,
uint8_t id);
struct __attribute__((packed)) NewWindowBody {
char StartMarker;
uint16_t x0;
uint16_t y0;
uint16_t width;
uint16_t height;
char title[32];
char EndMarker;
};
#endif
+104
View File
@@ -0,0 +1,104 @@
#include "walkieTalkie.h"
#include "HardwareSerial.h"
#include "communication/commands.h"
#include "communication/communication.h"
#include <cstdint>
#include <stdint.h>
#include <Arduino.h>
namespace WalkieTalkie {
// ahem - maybe refactor this inferno!
size_t RecvData(Command *command, uint8_t *payload, uint16_t payloadMax) {
int16_t len = 0;
uint8_t crc = 0;
int16_t result = 0;
while (Serial.available() > 0) {
uint8_t byte = Serial.read();
switch(state) {
case WaitingSTX:
if (byte == STX) {
Serial2.println(F("First byte is STX"));
state = RecvCMD;
resetBuffer();
} else {
Serial2.print(F("First byte is not STX: "));
Serial2.println(byte);
}
break;
case RecvCMD:
Serial2.println(F("Reading the command byte"));
*command = Command(byte);
Serial2.print(" Command: ");
Serial2.println(byte);
state = RecvLen;
resetBuffer();
break;
case RecvLen:
Serial2.println(F("Reading the len"));
buffer[bufferIndex++] = byte;
// we are currently using a int16_t for the len so: 2 bytes
if (bufferIndex > 1) {
len = buffer[0] | (buffer[1] << 8);
Serial2.print("Len: ");
Serial2.println(len);
state = RecvPayload;
resetBuffer();
}
break;
case RecvPayload:
Serial2.print("Reading payload: ");
Serial2.print(bufferIndex);
Serial2.print(" - ");
Serial2.println(byte);
buffer[bufferIndex++] = byte;
if (bufferIndex == len) {
// put the buffer data somewhere
memcpy(payload, buffer, len);
state = RecvCRC;
resetBuffer();
}
break;
case RecvCRC:
crc = byte;
Serial2.print("Reading CRC:");
Serial2.println(crc);
if (crc != CRC8(payload, len)) {
Serial2.print("CRC don't match. Expected: ");
Serial2.print(crc);
Serial2.print(", Got: ");
Serial2.println(CRC8(payload, len));
return -1;
break;
}
state = RecvETX;
resetBuffer();
break;
case RecvETX:
Serial2.println("Reading ETX");
if (byte != ETX) {
Serial2.print("Failure, last byte was: ");
Serial2.println(byte);
state = WaitingSTX;
return -1;
} else {
state = WaitingSTX;
return len;
}
break;
}
}
return 0;
}
};
+43
View File
@@ -0,0 +1,43 @@
#ifndef __WALKIE_TALKIE__
#define __WALKIE_TALKIE__
#include "communication/communication.h"
#include "communication/commands.h"
#include <cstdint>
#include <Arduino.h>
#include <cstring>
namespace WalkieTalkie {
typedef enum {
WaitingSTX = 0,
RecvCMD = 1,
RecvLen = 2,
RecvPayload = 3,
RecvCRC = 4,
RecvETX = 5,
} RecvState;
inline uint8_t buffer[4096];
inline int16_t bufferIndex = 0;
inline RecvState state = WaitingSTX;
inline static void resetBuffer() {
bufferIndex = 0;
}
struct ACKPacket {
uint8_t StartMarker;
uint8_t ACK;
uint8_t EndMarker;
};
template<typename PacketType>
void SendData(PacketType *packet) {
Serial.write((uint8_t*)packet, sizeof(*packet));
Serial.flush();
}
size_t RecvData(Command *command, uint8_t *payload, uint16_t payloadMax);
};
#endif
+162 -104
View File
@@ -7,18 +7,17 @@ TODO:
to have more ways to run analytics
*/
#include "UIComponent.h"
#include "values.h"
#include "windowPool.h"
#include "UIScreen.h"
#include "UIDecorations.h"
#include "UIDimensions.h"
#include "communication/commands.h"
#include "communication/packets.h"
#include "communication/identificationPacket.h"
#include "Arduino_GFX.h"
#include "HardwareSerial.h"
#include "UIComponent.h"
#include "UIDecorations.h"
#include "UIDimensions.h"
#include "UIScreen.h"
#include "communication/commands.h"
#include "communication/packets.h"
#include "communication/walkieTalkie.h"
#include "values.h"
#include "windowPool.h"
// #include "UIDrawing.h"
#include "UIString.h"
// #include "UITable.h"
@@ -56,15 +55,13 @@ Arduino_ESP32RGBPanel *panel = new Arduino_ESP32RGBPanel(
Arduino_GFX *gfx = new Arduino_RGB_Display(TFT_HOR_RES, TFT_VER_RES, panel, 16);
// HardwareSerial debugSerial(1);
Curses::Screen mainScreen(
gfx,
UIDimensions(0, 0, TFT_HOR_RES, TFT_VER_RES),
UIDecorations()
);
Curses::Screen mainScreen(gfx, UIDimensions(0, 0, TFT_HOR_RES, TFT_VER_RES),
UIDecorations());
// UIelements
// UIDecorations *gearTextDecor = new UIDecorations();
// UIString gearText(gfx, UIDimensions(0, 0, 0, 0), gearTextDecor, (char *)"Gear");
// UIString gearText(gfx, UIDimensions(0, 0, 0, 0), gearTextDecor, (char
// *)"Gear");
//
// UIElement mainWindow(
// gfx,
@@ -93,58 +90,61 @@ void setup() {
UIElement *mainWindow = mainScreen.mainWindowHandle;
mainWindow->drawBox();
int16_t childID = mainWindow->AddChild(STRING);
if (childID < 0) {
Serial2.println("Failed to add new window!");
} else {
Serial2.print("Successfully added a new window: ");
Serial2.println(childID);
UIElement* childComponent = mainWindow->GetChild(childID);
childComponent->SetTitle((char*)"%s [%2d]", (const char*)"Child Window", childID);
childComponent->SetUIDecorations(UIDecorations());
childComponent->SetUIDimensions(UIDimensions(20, 20, 300, 300));
childComponent->SetDisplay(mainScreen.display);
childComponent->drawBox();
}
childID = mainWindow->AddChild(STRING);
if (childID < 0) {
Serial2.println("Failed to add new window!");
} else {
Serial2.print("Successfully added a new window: ");
Serial2.println(childID);
UIElement* childComponent = mainWindow->GetChild(childID);
childComponent->SetTitle((char*)"%s [%2d]", (const char*)"Second Child", childID);
childComponent->SetUIDecorations(UIDecorations());
childComponent->SetUIDimensions(UIDimensions(330, 20, 300, 300));
childComponent->SetDisplay(mainScreen.display);
childComponent->drawBox();
}
mainWindow->RemoveChild(1);
childID = mainWindow->AddChild(STRING);
if (childID < 0) {
Serial2.println("Failed to add new window!");
} else {
Serial2.print("Successfully added a new window: ");
Serial2.println(childID);
UIElement* childComponent = mainWindow->GetChild(childID);
childComponent->SetTitle((char*)"%s [%2d]", (const char*)"Third Child", childID);
childComponent->SetUIDecorations(UIDecorations());
childComponent->SetUIDimensions(UIDimensions(20, 20, 300, 300));
childComponent->SetDisplay(mainScreen.display);
childComponent->drawBox();
}
// int16_t childID = mainWindow->AddChild(STRING);
// if (childID < 0) {
// Serial2.println("Failed to add new window!");
// } else {
// Serial2.print("Successfully added a new window: ");
// Serial2.println(childID);
//
// UIElement *childComponent = mainWindow->GetChild(childID);
//
// childComponent->SetTitle((char *)"%s [%2d]", (const char *)"Child Window",
// childID);
// childComponent->SetUIDecorations(UIDecorations());
// childComponent->SetUIDimensions(UIDimensions(20, 20, 300, 300));
// childComponent->SetDisplay(mainScreen.display);
//
// childComponent->drawBox();
// }
//
// childID = mainWindow->AddChild(STRING);
// if (childID < 0) {
// Serial2.println("Failed to add new window!");
// } else {
// Serial2.print("Successfully added a new window: ");
// Serial2.println(childID);
//
// UIElement *childComponent = mainWindow->GetChild(childID);
//
// childComponent->SetTitle((char *)"%s [%2d]", (const char *)"Second Child",
// childID);
// childComponent->SetUIDecorations(UIDecorations());
// childComponent->SetUIDimensions(UIDimensions(330, 20, 300, 300));
// childComponent->SetDisplay(mainScreen.display);
//
// childComponent->drawBox();
// }
//
// mainWindow->RemoveChild(1);
//
// childID = mainWindow->AddChild(STRING);
// if (childID < 0) {
// Serial2.println("Failed to add new window!");
// } else {
// Serial2.print("Successfully added a new window: ");
// Serial2.println(childID);
//
// UIElement *childComponent = mainWindow->GetChild(childID);
//
// childComponent->SetTitle((char *)"%s [%2d]", (const char *)"Third Child",
// childID);
// childComponent->SetUIDecorations(UIDecorations());
// childComponent->SetUIDimensions(UIDimensions(20, 20, 300, 300));
// childComponent->SetDisplay(mainScreen.display);
//
// childComponent->drawBox();
// }
WindowPool::PrintInUse();
@@ -156,56 +156,114 @@ uint64_t lastDataRead = 0;
bool gotAck = false;
struct header {
uint8_t StartMarker;
Command Cmd;
uint8_t EndMarker;
};
void PrintHeader(header *h) {
Serial2.println("HEADER:");
Serial2.print(" StartMarker: ");
Serial2.println(h->StartMarker);
Serial2.print(" Command : ");
Serial2.println(CommandToStr(h->Cmd));
Serial2.print(" EndMarker : ");
Serial2.println(h->EndMarker);
Serial2.println();
}
struct UIWindowPacket {
uint8_t StartMarker;
uint16_t x0;
uint16_t y0;
uint16_t width;
uint16_t height;
uint8_t EndMarker;
};
uint64_t lastSent = 0;
void loop(void) {
uint64_t cur = millis();
// if (!gotAck && (cur - lastSent) >= 1000) {
// // Send the packet again
// sendHello();
// lastSent = cur;
// }
if (Serial.available() >= 1) {
uint8_t cmd = Serial.read();
// with this new way of reading data, we are just gonna read a payload
// and get a command
Command cmd = CmdUnknown;
uint8_t payload[256] = {0};
if (Serial.available() > 0) {
size_t resp = WalkieTalkie::RecvData(&cmd, payload, 256);
if (resp < 0) {
Serial2.println(F("Failed to receive data from serial"));
return;
} else if (resp == 0) {
Serial2.println(F("No data to receive"));
return;
}
Serial2.print("Command: ");
Serial2.println(CommandToStr(cmd));
Serial2.print("Response: ");
Serial2.println(resp);
switch(cmd) {
case CmdRequestID:
Serial2.println("Got identification request!");
// gearText.Update("Connecting");
IdentificationPacket papers;
initIdentificationPacket(&papers, ESLABS_DEVICE_NAME, ESLABS_DEVICE_ID);
sendIdentificationPacket(&papers);
break;
case CmdAckID:
Serial2.println("Got ack!");
// gearText.Update("Connected");
gotAck = true;;
break;
case NewWindow:
Serial2.println("Received request to create window");
break;
case DestroyWindow:
Serial2.println("Received request to destroy window");
WalkieTalkie::SendData(&papers);
break;
default:
Serial2.print(F("Command `"));
Serial2.print(CommandToStr(cmd));
Serial2.print(F("` has not been implemented yet."));
}
}
// // Request data here
// SendDataRequest();
//
// // Receive data
// DataPacket telemetryPacket;
// int res = RecvDataPacket(&telemetryPacket);
//
// if (res == 0) {
// ui->Update(&telemetryPacket);
//
// lastDataRead = millis();
// // Try to use a state machine for this instead? Would it be better or just more
// // verbose and difficult to read?
// if (Serial.available() >= 1) {
// // Receive the header
// header h = {0};
// int res = WalkieTalkie::RecvData(&h);
// if (res > 0) {
// PrintHeader(&h);
// } else {
// Serial2.println(F("Failed to read header"));
// return;
// }
//
// // If no data is received for 5 seconds, reset the display
// if (millis() - lastDataRead >= 5000) {
// Serial2.print("Resetting the display");
// // Now we receive the body
// switch(h.Cmd) {
// case CmdRequestID:
// // We have no body to receive, we just return data
// break;
// case CmdCreateWindow:
// Serial2.println("Awaiting body...");
// // We have to receive a body, should have plenty of data
// //
// UIWindowPacket windowData;
// size_t bytes = WalkieTalkie::RecvData(&windowData);
// if (bytes <= 0) {
// Serial2.println("Malformed data");
// }
//
// Serial2.print("StartMarker: ");
// Serial2.println(windowData.StartMarker);
// Serial2.print("x0: ");
// Serial2.println(windowData.x0);
// Serial2.print("y0: ");
// Serial2.println(windowData.y0);
// Serial2.print("width: ");
// Serial2.println(windowData.width);
// Serial2.print("height: ");
// Serial2.println(windowData.height);
// // Serial2.print("title: ");
// // Serial2.println(windowData.title);
// Serial2.print("EndMarker: ");
// Serial2.println(windowData.EndMarker);
//
// Serial2.println("Received body... Continuing");
// break;
// }
// }
}