diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..f20992b6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "${workspaceFolder}/esp32_fw/.pio/libdeps/lolin32_lite/ESP Async WebServer" +} \ No newline at end of file diff --git a/ap_fw/main.c b/ap_fw/main.c index aed84837..43c52926 100644 --- a/ap_fw/main.c +++ b/ap_fw/main.c @@ -148,7 +148,7 @@ struct espAvailDataReq { } __packed; #define TIMER_TICKS_PER_MS 1333UL -uint16_t __xdata version = 0x0007; +uint16_t __xdata version = 0x000A; #define RAW_PKT_PADDING 2 static uint8_t __xdata mRxBuf[COMMS_MAX_PACKET_SZ]; @@ -307,7 +307,7 @@ void processSerial(uint8_t lastchar) { cmdbuffer[c] = cmdbuffer[c + 1]; } cmdbuffer[3] = lastchar; - if (strncmp(cmdbuffer, "SDA>", 4) == 0) { + if ((strncmp(cmdbuffer, "SDA>", 4) == 0) && (eventMode == false)) { RXState = ZBS_RX_WAIT_SDA; bytesRemain = sizeof(struct pendingData); serialbufferp = serialbuffer; @@ -793,6 +793,10 @@ void main(void) { sendPong(radiorxbuffer); break; case PKT_AVAIL_DATA_SHORTREQ: + if (eventMode == true) { + sendPong(radiorxbuffer); + break; + } // a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal battery use // bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is sent if (ret == 18) { diff --git a/ap_fw/soc/zbs243/radio.h b/ap_fw/soc/zbs243/radio.h index d5922781..2930b1aa 100644 --- a/ap_fw/soc/zbs243/radio.h +++ b/ap_fw/soc/zbs243/radio.h @@ -8,7 +8,10 @@ void RF_IRQ1(void) __interrupt (4); void RF_IRQ2(void) __interrupt (5); #define RADIO_PAD_LEN_BY 2 - + +extern bool radioChannelClear(); + + #include "../radioCommon.h" diff --git a/esp32_fw/data/www/event.html b/esp32_fw/data/www/event.html new file mode 100644 index 00000000..2f8edc45 --- /dev/null +++ b/esp32_fw/data/www/event.html @@ -0,0 +1,82 @@ + + + + + + +Event Mesh - messages + + + +
+ +
+ +
+ +
+ + +
+ + + + +
+
+ +
+
+ +
+
+
+ + +
+
+ ID:
+ Now:- +
+
+
+ Next:- +
+
+
+ +
+
+ +
+
+ +
+
+ ID:
+
+
+
+
+
+
+ +
+
+ + +
+
    +
+ +
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/esp32_fw/include/commstructs.h b/esp32_fw/include/commstructs.h index a52e6c4b..67789077 100644 --- a/esp32_fw/include/commstructs.h +++ b/esp32_fw/include/commstructs.h @@ -18,6 +18,14 @@ struct blockData { uint8_t data[]; } __packed; +#define EVENT_PKT_SIZE 100 +struct eventData { + uint8_t checksum; + uint8_t eventDataID; + uint8_t data[100]; +} __packed; + + #define SOLUM_154_033 0 #define SOLUM_29_033 1 #define SOLUM_42_033 2 diff --git a/esp32_fw/include/serial.h b/esp32_fw/include/serial.h index 76ed03a1..8855243f 100644 --- a/esp32_fw/include/serial.h +++ b/esp32_fw/include/serial.h @@ -3,6 +3,9 @@ void zbsTx(uint8_t* packetdata, uint8_t len); void zbsRxTask(void* parameter); +void setEventMode(bool on); +bool sendEventData(struct eventData* ed); + void sendCancelPending(struct pendingData* pending); void sendDataAvail(struct pendingData* pending); void Ping(); \ No newline at end of file diff --git a/esp32_fw/src/serial.cpp b/esp32_fw/src/serial.cpp index 9698faf3..da48c4ba 100644 --- a/esp32_fw/src/serial.cpp +++ b/esp32_fw/src/serial.cpp @@ -21,6 +21,8 @@ #define ZBS_RX_WAIT_JOINNETWORK 10 #define ZBS_RX_WAIT_XFERTIMEOUT 11 +static SemaphoreHandle_t serialWait; + uint8_t restartBlockRequest = 0; uint16_t sendBlock(const void* data, const uint16_t len) { @@ -89,7 +91,7 @@ uint8_t pktlen = 0; uint8_t pktindex = 0; char lastchar = 0; uint8_t charindex = 0; -uint64_t waitingForVersion = 0; +uint64_t waitingForVersion = 0; uint16_t version; void ShortRXWaitLoop() { @@ -103,16 +105,75 @@ void ShortRXWaitLoop() { cmdbuffer[3] = lastchar; } } - +int8_t serialWaitReply() { + uint32_t start = millis(); + int8_t ret = -1; + while ((millis() - start) < 100) { + ShortRXWaitLoop(); + if ((strncmp(cmdbuffer, "ACK>", 4) == 0)) { + memset(cmdbuffer, 0x00, 4); + return 1; + } + if ((strncmp(cmdbuffer, "NOK>", 4) == 0)) { + memset(cmdbuffer, 0x00, 4); + return 0; + } + if ((strncmp(cmdbuffer, "NOQ>", 4) == 0)) { + memset(cmdbuffer, 0x00, 4); + return 2; + } + } + Serial.println(cmdbuffer); + return -1; +} +bool sendEventData(struct eventData* ed) { + addCRC(ed, sizeof(struct eventData)); + uint8_t attempts = 5; + xSemaphoreTake(serialWait, portMAX_DELAY); + while (attempts--) { + uint8_t len = sizeof(struct eventData)+5; + uint8_t* sendp = (uint8_t*)ed; + Serial1.print("UED>"); + while(len--){ + Serial1.write(*(sendp++)); + delayMicroseconds(200); + } + if (serialWaitReply() == 1) { + Serial.println("Event Data Sent"); + xSemaphoreGive(serialWait); + return true; + } + vTaskDelay(3 / portTICK_PERIOD_MS); + } + xSemaphoreGive(serialWait); + Serial.println("Failed to send event data"); + return false; +} void Ping() { Serial1.print("VER?"); waitingForVersion = esp_timer_get_time(); } - +void setEventMode(bool on) { + uint8_t attempts = 5; + xSemaphoreTake(serialWait, portMAX_DELAY); + while (attempts--) { + if (on) { + Serial1.print("EEM>"); + } else { + Serial1.print("SEM>"); + } + if (serialWaitReply() == 1) { + xSemaphoreGive(serialWait); + return; + } + } + xSemaphoreGive(serialWait); + Serial.println("Failed to set mode..."); +} void SerialRXLoop() { if (Serial1.available()) { lastchar = Serial1.read(); - //Serial.write(lastchar); + // Serial.write(lastchar); switch (RXState) { case ZBS_RX_WAIT_HEADER: Serial.write(lastchar); @@ -227,7 +288,6 @@ void SerialRXLoop() { } extern uint8_t* getDataForFile(File* file); - void zbsRxTask(void* parameter) { Serial1.begin(230400, SERIAL_8N1, RXD1, TXD1); @@ -236,7 +296,9 @@ void zbsRxTask(void* parameter) { Serial1.print("VER?"); waitingForVersion = esp_timer_get_time(); + serialWait = xSemaphoreCreateMutex(); while (1) { + xSemaphoreTake(serialWait, portMAX_DELAY); SerialRXLoop(); if (Serial.available()) { @@ -245,9 +307,9 @@ void zbsRxTask(void* parameter) { vTaskDelay(1 / portTICK_PERIOD_MS); if (waitingForVersion) { - if (esp_timer_get_time() - waitingForVersion > 10000*1000ULL) { + if (esp_timer_get_time() - waitingForVersion > 10000 * 1000ULL) { waitingForVersion = 0; - //performDeviceFlash(); + // performDeviceFlash(); Serial.println("I wasn't able to connect to a ZBS tag, trying to reboot the tag."); Serial.println("If this problem persists, please check wiring and definitions in the settings.h file, and presence of the right firmware"); simplePowerOn(); @@ -255,7 +317,7 @@ void zbsRxTask(void* parameter) { refreshAllPending(); } } - + if (version && firstrun) { Serial.printf("ZBS/Zigbee FW version: %04X\n", version); uint16_t fsversion; @@ -270,5 +332,6 @@ void zbsRxTask(void* parameter) { } firstrun = false; } + xSemaphoreGive(serialWait); } } diff --git a/esp32_fw/src/web.cpp b/esp32_fw/src/web.cpp index 4da1b13f..d0e4b49e 100644 --- a/esp32_fw/src/web.cpp +++ b/esp32_fw/src/web.cpp @@ -2,7 +2,6 @@ #include #include - #include #include #include @@ -14,6 +13,7 @@ #include "commstructs.h" #include "newproto.h" +#include "serial.h" #include "settings.h" #include "tag_db.h" @@ -157,16 +157,32 @@ void wsSendSysteminfo() { } void wsSendTaginfo(uint8_t mac[6]) { - String json = ""; json = tagDBtoJson(mac); xSemaphoreTake(wsMutex, portMAX_DELAY); ws.textAll(json); xSemaphoreGive(wsMutex); - } +struct eventNowNext { + uint8_t type; + uint8_t nowStartHour; + uint8_t nowStartMinutes; + uint8_t nowEndHour; + uint8_t nowEndMinutes; + uint8_t nextStartHour; + uint8_t nextStartMinutes; + uint8_t nextEndHour; + uint8_t nextEndMinutes; + uint8_t data[]; +}; + +struct eventGeneric { + uint8_t type; + uint8_t data[]; +}; + void init_web() { LittleFS.begin(true); @@ -206,7 +222,7 @@ void init_web() { server.serveStatic("/current", LittleFS, "/current/"); server.serveStatic("/", LittleFS, "/www/").setDefaultFile("index.html"); - + server.on( "/imgupload", HTTP_POST, [](AsyncWebServerRequest *request) { request->send(200); @@ -218,15 +234,15 @@ void init_web() { if (request->hasParam("mac")) { String dst = request->getParam("mac")->value(); uint8_t mac[6]; - if (sscanf(dst.c_str(), "%02X%02X%02X%02X%02X%02X", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5])==6) { + if (sscanf(dst.c_str(), "%02X%02X%02X%02X%02X%02X", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6) { json = tagDBtoJson(mac); } } else { - uint8_t startPos=0; + uint8_t startPos = 0; if (request->hasParam("pos")) { startPos = atoi(request->getParam("pos")->value().c_str()); } - json = tagDBtoJson(nullptr,startPos); + json = tagDBtoJson(nullptr, startPos); } request->send(200, "application/json", json); }); @@ -243,8 +259,8 @@ void init_web() { taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value(); taginfo->contentMode = atoi(request->getParam("contentmode", true)->value().c_str()); taginfo->nextupdate = 0; - //memset(taginfo->md5, 0, 16 * sizeof(uint8_t)); - //memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t)); + // memset(taginfo->md5, 0, 16 * sizeof(uint8_t)); + // memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t)); wsSendTaginfo(mac); saveDB("/current/tagDB.json"); request->send(200, "text/plain", "Ok, saved"); @@ -272,6 +288,72 @@ void init_web() { } }); + server.on("/event_start", HTTP_POST, [](AsyncWebServerRequest *request) { + setEventMode(true); + request->send(200, "text/plain", "Mode set"); + }); + + server.on("/event_stop", HTTP_POST, [](AsyncWebServerRequest *request) { + setEventMode(false); + request->send(200, "text/plain", "Mode set"); + }); + + server.on("/event_dataNowNext", HTTP_POST, [](AsyncWebServerRequest *request) { + struct eventData ed; + struct eventNowNext *nownext = (struct eventNowNext *)ed.data; + + sscanf(request->getParam("id", true)->value().c_str(), "%d", &ed.eventDataID); + + sscanf(request->getParam("nowStart", true)->value().c_str(), "%d:%d", &nownext->nowStartHour, &nownext->nowStartMinutes); + sscanf(request->getParam("nowEnd", true)->value().c_str(), "%d:%d", &nownext->nowEndHour, &nownext->nowEndMinutes); + sscanf(request->getParam("nextStart", true)->value().c_str(), "%d:%d", &nownext->nextStartHour, &nownext->nextStartMinutes); + sscanf(request->getParam("nextEnd", true)->value().c_str(), "%d:%d", &nownext->nextEndHour, &nownext->nextEndMinutes); + String data = request->getParam("Row1", true)->value(); + data += "\n"; + data += request->getParam("Row2", true)->value(); + data += "\n"; + data += request->getParam("Row3", true)->value(); + data += "\n"; + data += request->getParam("Row4", true)->value(); + data += "\0"; + nownext->type = 0xB1; + strncpy((char *)nownext->data, data.c_str(), 100 - sizeof(struct eventNowNext)); + bool ret = sendEventData(&ed); + if (ret) { + request->send(200, "text/plain", "event data sent"); + } else { + request->send(200, "text/plain", "Failed sending event data, please try again"); + } + }); + + server.on("/event_dataGeneric", HTTP_POST, [](AsyncWebServerRequest *request) { + struct eventData ed; + struct eventGeneric *generic = (struct eventGeneric *)ed.data; + + sscanf(request->getParam("id", true)->value().c_str(), "%d", &ed.eventDataID); + + String data = request->getParam("Row1", true)->value(); + data += "\n"; + data += request->getParam("Row2", true)->value(); + data += "\n"; + data += request->getParam("Row3", true)->value(); + data += "\n"; + data += request->getParam("Row4", true)->value(); + data += "\n"; + data += request->getParam("Row5", true)->value(); + data += "\n"; + data += request->getParam("Row6", true)->value(); + data += "\0"; + generic->type = 0xB2; + strncpy((char *)generic->data, data.c_str(), 100 - sizeof(struct eventGeneric)); + bool ret = sendEventData(&ed); + if (ret) { + request->send(200, "text/plain", "Event data sent"); + } else { + request->send(200, "text/plain", "Failed sending event data, please try again"); + } + }); + server.onNotFound([](AsyncWebServerRequest *request) { if (request->url() == "/" || request->url() == "index.htm") { request->send(200, "text/html", "-"); diff --git a/tag_fw/bitmaps.h b/tag_fw/bitmaps.h index 56caed91..e78522a5 100644 --- a/tag_fw/bitmaps.h +++ b/tag_fw/bitmaps.h @@ -3,8 +3,36 @@ // images generated by https://lvgl.io/tools/imageconverter, prepended with width, height. "CF_INDEXED_1_BIT"-mode, little-endian #include - #include "screen.h" + +static const uint8_t __code atc1441[] = { +112,9, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x04, 0x7c, 0xe2, 0x30, 0xc4, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x0a, 0x11, 0x16, 0x51, 0x4c, + 0x20, 0xb1, 0xcb, 0x1e, 0x72, 0xce, 0x34, 0x16, 0x44, 0x0a, 0x11, 0x02, 0x51, 0x44, + 0x1c, 0xca, 0x2c, 0xa0, 0x8b, 0x11, 0x4c, 0x19, 0x44, 0x11, 0x11, 0x02, 0x92, 0x44, + 0x02, 0x8a, 0x28, 0x9c, 0x8a, 0x1f, 0x44, 0x11, 0x44, 0x1f, 0x11, 0x02, 0xfb, 0xe4, + 0x22, 0x8a, 0x28, 0x82, 0x8a, 0x10, 0x44, 0x11, 0x28, 0x11, 0x11, 0x12, 0x10, 0x44, + 0x1c, 0xf1, 0xc8, 0xbc, 0x72, 0x0e, 0x3c, 0x1e, 0x10, 0x11, 0x10, 0xe2, 0x10, 0x44, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + + +static const uint8_t __code openepaperlink[] = { +136,9, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x1c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x22, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, + 0x44, 0xe4, 0x4e, 0x59, 0xc6, 0x8b, 0x22, 0x22, 0xb1, 0xcb, 0x20, 0xb1, 0xcb, 0x1c, 0xb4, 0x15, 0x92, + 0x79, 0x15, 0x51, 0x62, 0x29, 0x8c, 0xa2, 0x22, 0xca, 0x2c, 0xbc, 0xc8, 0x2c, 0xa2, 0xc4, 0x16, 0x54, + 0x41, 0x15, 0x5f, 0x43, 0xe8, 0x88, 0xa2, 0x22, 0x8b, 0xe8, 0xa0, 0x89, 0xe8, 0xbe, 0x84, 0x14, 0x58, + 0x41, 0x12, 0x90, 0x42, 0x08, 0x88, 0x94, 0x22, 0x8a, 0x08, 0xa0, 0x8a, 0x28, 0xa0, 0x84, 0x14, 0x54, + 0x40, 0xe2, 0x8e, 0x41, 0xc7, 0x8f, 0x08, 0x1c, 0xf1, 0xc8, 0xbe, 0xf1, 0xef, 0x1c, 0x87, 0xd4, 0x52, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, +}; + + static const uint8_t __code hadberlin[] = { 152,21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -187,7 +215,80 @@ static const uint8_t __code hackaday[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; - +static const uint8_t __code hackadaysmall[] = { +80, 71, + 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, + 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, + 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, + 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, + 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, + 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, + 0x80, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x04, + 0xc0, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x0c, + 0xe0, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1c, + 0xf0, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x7c, + 0xfd, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xfc, + 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf8, + 0x3f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf0, + 0x1f, 0xff, 0xff, 0xc0, 0x7f, 0xf0, 0x0f, 0xff, 0xff, 0xe0, + 0x0f, 0xff, 0xff, 0xe1, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xc0, + 0x03, 0xff, 0xff, 0xe7, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x00, + 0x00, 0x03, 0xff, 0x8f, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x9f, 0xff, 0xff, 0xe7, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x3f, 0xff, 0xff, 0xf3, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7f, 0xff, 0xff, 0xf9, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0xfc, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x09, 0xff, 0xff, 0xff, 0xfe, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xf8, 0x7f, 0xf8, 0x7f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x1f, 0xe0, 0x1f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x0f, 0xc0, 0x1f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xe0, 0x0f, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x80, 0x3f, 0xf0, 0x0f, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0xff, 0xfc, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xc3, 0xff, 0xff, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe7, 0xff, 0xff, 0x9f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xf7, 0xff, 0xff, 0xbf, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xff, 0xfc, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xf8, 0x7f, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1b, 0xff, 0xf8, 0x7f, 0xff, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x39, 0xff, 0xfb, 0x7f, 0xfe, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x79, 0xff, 0xfb, 0x7f, 0xfe, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, + 0x00, 0x01, 0xfe, 0x7f, 0xff, 0xff, 0xf9, 0xfe, 0x00, 0x00, + 0x00, 0x03, 0xfe, 0x3f, 0xff, 0xff, 0xf1, 0xff, 0x00, 0x00, + 0x03, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xe3, 0xff, 0xff, 0x00, + 0x0f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xc0, + 0x1f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, + 0x3f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xf0, + 0x7f, 0xff, 0xff, 0x0f, 0xef, 0xdf, 0xc3, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xfe, 0x0f, 0xef, 0xdf, 0xc1, 0xff, 0xff, 0xf8, + 0xfd, 0xff, 0xfc, 0x07, 0xcf, 0xcf, 0x80, 0xff, 0xfe, 0xf8, + 0xf8, 0xff, 0xf0, 0x03, 0x83, 0x07, 0x00, 0x3f, 0xfc, 0x7c, + 0xf0, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x3c, + 0xc0, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x0c, + 0x80, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x04, + 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, + 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, + 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, + 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, + 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, + 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, + 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, +}; static const uint8_t __code oepli[] = { 128, 26, diff --git a/tag_fw/board/ssd1619.c b/tag_fw/board/ssd1619.c index 89530ec6..5976d0af 100644 --- a/tag_fw/board/ssd1619.c +++ b/tag_fw/board/ssd1619.c @@ -701,7 +701,7 @@ void writeCharEPD(uint8_t c) { if (font[c][i]) empty = false; } if (empty) { - for (uint8_t i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 5; i++) { if (directionY) { pushYFontBytesToEPD(0x00, 0x00); } else { diff --git a/tag_fw/fw154.bin b/tag_fw/fw154.bin deleted file mode 100644 index c378db66..00000000 Binary files a/tag_fw/fw154.bin and /dev/null differ diff --git a/tag_fw/fw29-uc8151.bin b/tag_fw/fw29-uc8151.bin deleted file mode 100644 index abf073b8..00000000 Binary files a/tag_fw/fw29-uc8151.bin and /dev/null differ diff --git a/tag_fw/fw29.bin b/tag_fw/fw29.bin deleted file mode 100644 index 1f5ba229..00000000 Binary files a/tag_fw/fw29.bin and /dev/null differ diff --git a/tag_fw/fw42.bin b/tag_fw/fw42.bin deleted file mode 100644 index 2197c5e4..00000000 Binary files a/tag_fw/fw42.bin and /dev/null differ diff --git a/tag_fw/main.c b/tag_fw/main.c index cf5ea6f4..34ed9ed3 100644 --- a/tag_fw/main.c +++ b/tag_fw/main.c @@ -374,15 +374,15 @@ void main() { } } -#define EVENT_POLL_INTERVAL 5000 +#define EVENT_POLL_INTERVAL 3000 uint8_t __xdata eventDataID = 0; - +uint16_t __xdata failedCount = 0; void eventMode() { powerUp(INIT_EPD); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(EPD_LUT_FAST_NO_REDS); clearScreen(); - epdPrintBegin(0, 60, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdPrintBegin(2, 60, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); epdpr("EventMode"); epdPrintEnd(); drawWithSleep(); @@ -390,24 +390,28 @@ void eventMode() { doSleep(1000); - uint16_t __xdata failedCount = 0; + powerUp(INIT_EPD); + eventStartScreen(); + powerDown(INIT_EPD); - // display welcome! + doSleep(5000); + + while (failedCount < 28800) { // 24 hours at 3 second intervals - while (failedCount < 17280) { // 24 hours at 5 second intervals wdt10s(); - powerUp(INIT_RADIO | INIT_UART); + powerUp(INIT_RADIO); + powerUp(INIT_UART); struct eventData* __xdata ed = getEventData(); powerDown(INIT_RADIO); if (ed == NULL) { failedCount++; } else { - // eventdata is copied to blockXferBuffer, gets picked up from + // eventdata is copied to blockXferBuffer, gets picked up from there failedCount = 0; // check if should display this data, and make it available to other tags - if ((ed->eventDataID > eventDataID) || (ed->eventDataID - eventDataID > 128)) { + if ((ed->eventDataID > eventDataID) || (eventDataID - ed->eventDataID > 128)) { eventDataID = ed->eventDataID; // display event logo while we run the AP (we could just skip straight to showing the data, but where's the fun in that) @@ -436,10 +440,19 @@ void eventMode() { doSleep(EVENT_POLL_INTERVAL); } + wdt60s(); // display thank you blah + powerUp(INIT_EPD); + eventEndScreen(); + powerDown(INIT_EPD); + // sleep, wake every 10 minutes to see if an event has started; while (1) { - // sleep forever - doSleep(-1); + doSleep(600000); + wdt10s(); + powerUp(INIT_RADIO); + struct eventData* __xdata ed = getEventData(); + powerDown(INIT_RADIO); + if(ed!=NULL)wdtDeviceReset(); } } \ No newline at end of file diff --git a/tag_fw/soc/zbs243/radio.c b/tag_fw/soc/zbs243/radio.c index 802f2561..e6a5a877 100644 --- a/tag_fw/soc/zbs243/radio.c +++ b/tag_fw/soc/zbs243/radio.c @@ -111,19 +111,14 @@ bool radioTx(const void __xdata *packetP) // waits for tx end uint16_t bkp, wait; __bit irqs; - // this is how to do CCA. we do not bother because fuck it - // this is how WE do CCA. 'Fuck it' still somewhat applies if we don't get a clear channel in a reasonable amount of time - // okay fuck it. - /* + // this is how to do CCA. for (uint8_t i = 0; i < 0x80; i++) { if (!(RADIO_curRfState & 1)) { - //pr("radio CCA fail\n"); - timerDelay(TIMER_TICKS_PER_SECOND / 2000); - //return; + pr("-"); + return false; } } - */ - + mAckTimePassed = false; mGotAck = false; mLastTxedSeq = packet[3]; diff --git a/tag_fw/soc/zbs243/radio.h b/tag_fw/soc/zbs243/radio.h index d5922781..7d118e5f 100644 --- a/tag_fw/soc/zbs243/radio.h +++ b/tag_fw/soc/zbs243/radio.h @@ -12,9 +12,6 @@ void RF_IRQ2(void) __interrupt (5); #include "../radioCommon.h" - - - #endif diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index c10760d5..8b0f1cbd 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -247,6 +247,9 @@ struct AvailDataInfo *__xdata getShortAvailDataInfo() { return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); } } + if (getPacketType(inBuffer) == PKT_EVENT_PONG) { + wdtDeviceReset(); + } } } } @@ -814,7 +817,7 @@ void initializeProto() { #define EVENT_AP_TIME 10 #define RAW_PKT_PADDING 2 #define EVENT_PKT_SIZE 100 -#define EVENT_DATA_REQ_RX_WINDOW_SIZE 10 +#define EVENT_DATA_REQ_RX_WINDOW_SIZE 7 static void sendEventPong(const void *__xdata buf) { struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf; @@ -857,21 +860,19 @@ void eventAPMode() { // received a packet, lets see what it is switch (getPacketType(inBuffer)) { case PKT_PING: - pr("pong rx\n"); sendEventPong(inBuffer); break; case PKT_EVENT_DATA_REQ: - pr("event data reply\n"); sendEventDataReply(inBuffer); break; } } } } -static void sendEventDataReq() { +bool sendEventDataReq() { struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4); - outBuffer[0] = sizeof(struct MacFrameBcast) + 2 + 2; + outBuffer[0] = sizeof(struct MacFrameBcast) + 2 + 2 + 10; // added some random extra bytes, seems to reduce crashes. Probably some timing issue outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_EVENT_DATA_REQ; memcpy(txframe->src, mSelfMac, 8); txframe->fcs.frameType = 1; @@ -882,16 +883,22 @@ static void sendEventDataReq() { txframe->dstPan = PROTO_PAN_ID; txframe->dstAddr = 0xFFFF; txframe->srcPan = PROTO_PAN_ID; - commsTxNoCpy(outBuffer); + return commsTxNoCpy(outBuffer); } struct eventData *__xdata getEventData() { radioRxEnable(true, true); uint32_t __xdata t; - for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { - sendEventDataReq(); + bool timeExtended = false; + timerDelay(100); + for (uint8_t c = 0; c < 2; c++) { + + if(!sendEventDataReq()) return NULL; + t = timerGet() + (TIMER_TICKS_PER_MS * EVENT_DATA_REQ_RX_WINDOW_SIZE); + while (timerGet() < t) { int8_t __xdata ret = commsRxUnencrypted(inBuffer); + if (ret > 1) { if (getPacketType(inBuffer) == PKT_EVENT_DATA) { if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct eventData) + EVENT_PKT_SIZE)) { diff --git a/tag_fw/userinterface.c b/tag_fw/userinterface.c index bb072f09..dee9a153 100644 --- a/tag_fw/userinterface.c +++ b/tag_fw/userinterface.c @@ -63,6 +63,122 @@ void addOverlay() { } } +extern uint8_t __xdata blockXferBuffer[]; +struct eventNowNext { + uint8_t type; + uint8_t nowStartHour; + uint8_t nowStartMinutes; + uint8_t nowEndHour; + uint8_t nowEndMinutes; + uint8_t nextStartHour; + uint8_t nextStartMinutes; + uint8_t nextEndHour; + uint8_t nextEndMinutes; + uint8_t data[]; +}; + +static void eventNowNext() { + struct eventNowNext* enn = (struct eventNowNext*)(blockXferBuffer + sizeof(struct eventData)); + + selectLUT(EPD_LUT_NO_REPEATS); + clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); + loadRawBitmap(hadberlin, 0, 0, EPD_COLOR_BLACK); + if (blockXferBuffer[1] & 0x01) { + loadRawBitmap(atc1441, 20, 143, EPD_COLOR_BLACK); + } else { + loadRawBitmap(openepaperlink, 8, 143, EPD_COLOR_BLACK); + } + + epdPrintBegin(2, 22, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_RED); + epdpr("Now:"); + epdPrintEnd(); + epdPrintBegin(2, 86, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); + epdpr("Next:"); + epdPrintEnd(); + epdPrintBegin(73, 33, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("%02d:%02d-%02d:%02d", enn->nowStartHour, enn->nowStartMinutes, enn->nowEndHour, enn->nowEndMinutes); + epdPrintEnd(); + + epdPrintBegin(73, 86, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("%02d:%02d-%02d:%02d", enn->nextStartHour, enn->nextStartMinutes, enn->nextEndHour, enn->nextEndMinutes); + epdPrintEnd(); + + char* readp = enn->data; + uint8_t row = 0; + uint8_t currow = 0; + epdPrintBegin(2, 54, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + while (*readp) { + if (*readp == '\n') row++; + if (row != currow) { + readp++; + currow = row; + epdPrintEnd(); + switch (row) { + case 1: + epdPrintBegin(2, 70, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 2: + epdPrintBegin(2, 102, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 3: + epdPrintBegin(2, 118, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + } + } else { + writeCharEPD(*(readp++)); + } + } + epdPrintEnd(); + drawWithSleep(); +} + +static void eventGeneric() { + selectLUT(EPD_LUT_NO_REPEATS); + clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); + loadRawBitmap(hadberlin, 0, 0, EPD_COLOR_BLACK); + if (blockXferBuffer[1] & 0x01) { + loadRawBitmap(atc1441, 20, 143, EPD_COLOR_BLACK); + } else { + loadRawBitmap(openepaperlink, 8, 143, EPD_COLOR_BLACK); + } + + char* readp = &blockXferBuffer[3]; + uint8_t row = 0; + uint8_t currow = 0; + epdPrintBegin(2, 38, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + while (*readp) { + if (*readp == '\n') row++; + if (row != currow) { + readp++; + currow = row; + epdPrintEnd(); + switch (row) { + case 1: + epdPrintBegin(2, 54, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 2: + epdPrintBegin(2, 70, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 3: + epdPrintBegin(2, 86, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 4: + epdPrintBegin(2, 102, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + case 5: + epdPrintBegin(2, 118, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + break; + } + } else { + writeCharEPD(*(readp++)); + } + } + epdPrintEnd(); + drawWithSleep(); +} + void eventUpdateScreen() { selectLUT(EPD_LUT_FAST_NO_REDS); clearScreen(); @@ -71,20 +187,52 @@ void eventUpdateScreen() { drawNoWait(); } -extern uint8_t __xdata blockXferBuffer[]; - -void eventScreen() { +void eventStartScreen() { selectLUT(EPD_LUT_NO_REPEATS); clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); - loadRawBitmap(hadberlin, 0, 0, EPD_COLOR_BLACK); + loadRawBitmap(hackadaysmall, 40, 37, EPD_COLOR_BLACK); + epdPrintBegin(20, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_RED); + epdpr("Welcome"); + epdPrintEnd(); - epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); - epdpr("ID=%d",blockXferBuffer[1]); + epdPrintBegin(10, 117, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("to Hackaday Berlin"); + epdPrintEnd(); + epdPrintBegin(66, 133, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("2023"); + epdPrintEnd(); + drawWithSleep(); +} +void eventEndScreen() { + selectLUT(EPD_LUT_DEFAULT); + clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); + loadRawBitmap(hadberlin, 0, 131, EPD_COLOR_BLACK); + loadRawBitmap(hackadaysmall, 40, 37, EPD_COLOR_BLACK); + epdPrintBegin(4, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_RED); + epdpr("Thank you"); + epdPrintEnd(); + + epdPrintBegin(36, 117, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("for visiting"); epdPrintEnd(); drawWithSleep(); } +void eventScreen() { + switch (blockXferBuffer[2]) { + case 0xB1: + eventNowNext(); + break; + case 0xB2: + eventGeneric(); + break; + default: + pr("type=%d\n", blockXferBuffer[2]); + break; + } +} void showSplashScreen() { selectLUT(EPD_LUT_NO_REPEATS); @@ -107,7 +255,8 @@ void showSplashScreen() { epdPrintEnd(); epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); - epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); + epdpr("Hackaday Berlin 2023"); + //epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); epdPrintEnd(); #endif @@ -173,7 +322,6 @@ void showSplashScreen() { #endif drawWithSleep(); } - void showApplyUpdate() { setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(1); @@ -195,9 +343,7 @@ void showApplyUpdate() { epdPrintEnd(); drawNoWait(); } - uint8_t __xdata resultcounter = 0; - void showScanningWindow() { setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(EPD_LUT_FAST_NO_REDS); @@ -232,7 +378,6 @@ void showScanningWindow() { selectLUT(EPD_LUT_FAST); resultcounter = 0; } - void addScanResult(uint8_t channel, uint8_t lqi) { if (channel == 11) resultcounter = 0; #if (SCREEN_WIDTH == 128) // 2.9" @@ -248,7 +393,6 @@ void addScanResult(uint8_t channel, uint8_t lqi) { epdPrintEnd(); resultcounter++; } - void showAPFound() { clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -354,7 +498,6 @@ void showAPFound() { addOverlay(); drawWithSleep(); } - void showNoAP() { selectLUT(EPD_LUT_NO_REPEATS); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -400,7 +543,6 @@ void showNoAP() { addOverlay(); drawWithSleep(); } - void showLongTermSleep() { selectLUT(EPD_LUT_NO_REPEATS); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -454,7 +596,6 @@ void showNoEEPROM() { #endif drawWithSleep(); } - void showNoMAC() { selectLUT(EPD_LUT_NO_REPEATS); clearScreen(); diff --git a/tag_fw/userinterface.h b/tag_fw/userinterface.h index 11d41a86..d9ac25fb 100644 --- a/tag_fw/userinterface.h +++ b/tag_fw/userinterface.h @@ -14,8 +14,10 @@ void showLongTermSleep(); void showNoEEPROM(); void showNoMAC(); +void eventStartScreen(); void eventUpdateScreen(); void eventScreen(); +void eventEndScreen();