#include #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); } }