rgbmatrixscreen/teensy/comms.cpp
2021-04-29 21:46:54 -04:00

165 lines
4.1 KiB
C++

#include <Arduino.h>
#include "log.h"
#include "comms.h"
#include "lua.hpp"
#define HWS Serial2
#define PACK_OVERHEAD 5
#define BUFF_SIZE 128
uint8_t buff[BUFF_SIZE + 1]; // makes it easier to handle a trailing null
int maybe_packet(uint8_t *p) {
uint8_t type = p[0];
if (type < 32)
return 1;
return 0;
}
uint16_t packet_length(uint8_t *p) {
if (!maybe_packet(p)) {
return -1;
}
uint16_t l = p[1] << 8 + p[2];
return l;
}
uint16_t crc16(uint8_t *p, int l) {
return 1; // TODO actually make this generate crcs
}
// takes in a max size, how many bytes are received and how many should be
int read_pack(uint8_t *p, uint16_t max, uint16_t recv_len, uint16_t pack_len) {
if (pack_len == 0) // quick shortcut
return 0;
if (recv_len < pack_len) { // if we haven't received everything, we should try
if (pack_len > max) { // packet is too large to fit in buffer, return -1
return -1; // say we can't handle this with the buffer provided
} else {
uint16_t i = pack_len - recv_len; // off by one?
uint16_t q = 0;
while(i > 0) {
if (HWS.available()) {
*p++ = HWS.read();
i--;
q++;
} else {
delayMicroseconds(1); // short delay
}
}
return q; // we read some data
}
}
return 0; // nothing to read
}
int parse_packet(uint8_t *p, uint16_t recv_len) {
if (maybe_packet(p)) {
uint16_t pack_len = packet_length(p);
// TODO CRC check on smaller packets
switch(p[0]) {
case 1:
// otherwise we'll need to load it ourselves into the program buffer
if (recv_len == pack_len) {
p[PACK_OVERHEAD + pack_len + 1] = 0;
lua_start(p + PACK_OVERHEAD); // load it directly from our buffer
} else {
int t = read_pack(l_prog_buff, MAX_PRGMSIZE - 1, 0, pack_len);
if (t < 0) { // program too big.
// all programs should have no values that are valid packet starts, so we'll just let the rest of the code skip them. might be a bug later TODO
HWS.write(0x03);
HWS.write(0x00);
HWS.write(38);
HWS.write(0);
HWS.write(0);
HWS.print("Program too big, reduce the total size");
} else {
l_prog_buff[t+1] = 0; // null byte
lua_start(l_prog_buff);
}
}
break;
case 5: // send the output log
HWS.write(0x06); // send packet header
HWS.write(LOG_RINGSIZE >> 8);
HWS.write(LOG_RINGSIZE & 0xFF);
HWS.write(0);
HWS.write(0);
char *rb_p = log_curpos+1;
if (rb_p - log_ringbuffer >= LOG_RINGSIZE)
rb_p = log_ringbuffer;
while(rb_p != log_curpos) {
if (*rb_p)
HWS.write(*rb_p);
rb_p++;
if (rb_p - log_ringbuffer >= LOG_RINGSIZE)
rb_p = log_ringbuffer;
}
break;
case 8:
// TODO recv bitmap
break;
case 10: // KV data for lua
// TODO call lua func for this
break;
case 11: // set brightness. Do not honor currently.
// TODO
break;
case 9: // req KV data
case 7: // we should never get this, we send request for bitmap
case 6: // we should never get this, we send output log
case 4: // we should never get this, we send PRGMACK
case 3: // we should never get this, we send error
case 2: // we should never get this, we send it
case 0: // null packet, do nothing
default:
return 0;
}
return 1;
} else {
return 0;
}
}
void setup_comms() {
HWS.begin(115200);
}
void loop_comms() {
if (HWS.available() >= 5) {
uint c = 5;
buff[0] = HWS.read();
if (!maybe_packet(buff))
return; // skip this byte, we'll check on the next loop
uint16_t pack_len = packet_length(buff);
int len = read_pack(buff + PACK_OVERHEAD, BUFF_SIZE - PACK_OVERHEAD, 0, pack_len);
// we read the rest of the packet, tell parser
if (len > 0) {
c+ = len;
}
parse_packet(buff, c);
}
}