mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 05:06:39 +01:00
version as in use on hackaday Berlin 2023
This commit is contained in:
@@ -753,7 +753,7 @@ void main(void) {
|
||||
rndSeed(mSelfMac[0] ^ (uint8_t)timerGetLowBits(), mSelfMac[1]);
|
||||
// wdtSetResetVal(0xFD0DCF);
|
||||
// wdtOn();
|
||||
radioSetChannel(RADIO_FIRST_CHANNEL);
|
||||
radioSetChannel(26);
|
||||
radioSetTxPower(10);
|
||||
radioRxEnable(true, true);
|
||||
|
||||
|
||||
@@ -217,8 +217,8 @@ void radioSetChannel(uint8_t ch) {
|
||||
static const uint8_t perChannelSetting1[] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33, 0x33};
|
||||
static const uint8_t perChannelSetting2[] = {4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2};
|
||||
|
||||
if (ch < RADIO_FIRST_CHANNEL || ch >= RADIO_FIRST_CHANNEL + RADIO_NUM_CHANNELS)
|
||||
return;
|
||||
//if (ch < RADIO_FIRST_CHANNEL || ch >= RADIO_FIRST_CHANNEL + RADIO_NUM_CHANNELS)
|
||||
// return;
|
||||
|
||||
RADIO_channel = ch; // configmed to be at least RX channel
|
||||
RADIO_command = RADIO_CMD_RECEIVE;
|
||||
|
||||
@@ -63,6 +63,39 @@
|
||||
<input type="submit" value="Send EventData Update">
|
||||
</form>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div class="actionbox">
|
||||
Show screen:
|
||||
<form action="event_showScreen" method="POST" target="empty">
|
||||
ID:<input name="id" size=3 maxlength=3 placeholder="1"/><br/>
|
||||
<select name="screen">
|
||||
<option value="0">Event Begin</option>
|
||||
<option value="1">Event End</option>
|
||||
<option value="2">Update Screen</option>
|
||||
</select><br/>
|
||||
<input type="checkbox" name="mesh" value="Rebroadcast">Rebroadcast<br/>
|
||||
<input type="submit" value="Send EventData Update">
|
||||
</form>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="actionbox">
|
||||
Do command:
|
||||
<form action="event_doCmd" method="POST" target="empty">
|
||||
ID:<input name="id" size=3 maxlength=3 placeholder="1"/><br/>
|
||||
<select name="cmd">
|
||||
<option value="0">Reset</option>
|
||||
<option value="1">Go To EventEnd</option>
|
||||
<option value="2">Cmd 2</option>
|
||||
<option value="3">Cmd 1</option>
|
||||
<option value="4">Cmd 2</option>
|
||||
</select><br/>
|
||||
<input type="checkbox" name="mesh" value="Rebroadcast">Rebroadcast<br/>
|
||||
<input type="submit" value="Send EventData Update">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="messages">
|
||||
|
||||
@@ -131,10 +131,21 @@ bool sendEventData(struct eventData* ed) {
|
||||
uint8_t attempts = 5;
|
||||
xSemaphoreTake(serialWait, portMAX_DELAY);
|
||||
while (attempts--) {
|
||||
uint8_t len = sizeof(struct eventData)+5;
|
||||
uint8_t len = sizeof(struct eventData) + 5;
|
||||
uint8_t* sendp = (uint8_t*)ed;
|
||||
Serial1.print("UED>");
|
||||
while(len--){
|
||||
Serial1.print("U");
|
||||
delayMicroseconds(200);
|
||||
|
||||
Serial1.print("E");
|
||||
delayMicroseconds(200);
|
||||
|
||||
Serial1.print("D");
|
||||
delayMicroseconds(200);
|
||||
|
||||
Serial1.print(">");
|
||||
delayMicroseconds(200);
|
||||
|
||||
while (len--) {
|
||||
Serial1.write(*(sendp++));
|
||||
delayMicroseconds(200);
|
||||
}
|
||||
|
||||
@@ -354,6 +354,58 @@ void init_web() {
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/event_showScreen", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
struct eventData ed;
|
||||
struct eventGeneric *generic = (struct eventGeneric *)ed.data;
|
||||
|
||||
|
||||
uint8_t id[4];
|
||||
sscanf(request->getParam("id", true)->value().c_str(), "%d", &id[0]);
|
||||
|
||||
uint8_t screenShow[4];
|
||||
sscanf(request->getParam("screen", true)->value().c_str(), "%d", &screenShow[0]);
|
||||
|
||||
ed.eventDataID = id[0];
|
||||
generic->type = 0x20;
|
||||
generic->type |= (screenShow[0] & 0x0F);
|
||||
|
||||
if (request->hasParam("mesh", true)) {
|
||||
generic->type |= 0x80;
|
||||
}
|
||||
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_doCmd", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
struct eventData ed;
|
||||
struct eventGeneric *generic = (struct eventGeneric *)ed.data;
|
||||
|
||||
|
||||
uint8_t id[4];
|
||||
sscanf(request->getParam("id", true)->value().c_str(), "%d", &id[0]);
|
||||
|
||||
uint8_t cmd[4];
|
||||
sscanf(request->getParam("cmd", true)->value().c_str(), "%d", &cmd[0]);
|
||||
|
||||
ed.eventDataID = id[0];
|
||||
generic->type = 0x10;
|
||||
generic->type |= (cmd[0] & 0x0F);
|
||||
|
||||
if (request->hasParam("mesh", true)) {
|
||||
generic->type |= 0x80;
|
||||
}
|
||||
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", "-");
|
||||
|
||||
102
tag_fw/main.c
102
tag_fw/main.c
@@ -374,6 +374,29 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
extern void dump(uint8_t* __xdata a, uint16_t __xdata l); // remove me when done
|
||||
|
||||
void doMeshIfNeeded(uint8_t cmddata) {
|
||||
wdt30s();
|
||||
if (!(cmddata & 0x40)) {
|
||||
powerUp(INIT_EPD);
|
||||
eventUpdateScreen();
|
||||
}
|
||||
if (cmddata & 0x80) {
|
||||
wdt30s();
|
||||
// enter AP mode
|
||||
pr("AP enabled\n");
|
||||
powerUp(INIT_RADIO);
|
||||
eventAPMode();
|
||||
powerDown(INIT_RADIO);
|
||||
pr("AP disabled\n");
|
||||
epdWaitRdy();
|
||||
}
|
||||
if (!(cmddata & 0x40)) {
|
||||
powerDown(INIT_EPD);
|
||||
}
|
||||
}
|
||||
|
||||
#define EVENT_POLL_INTERVAL 3000
|
||||
uint8_t __xdata eventDataID = 0;
|
||||
uint16_t __xdata failedCount = 0;
|
||||
@@ -407,34 +430,57 @@ void eventMode() {
|
||||
if (ed == NULL) {
|
||||
failedCount++;
|
||||
} else {
|
||||
// eventdata is copied to blockXferBuffer, gets picked up from there
|
||||
failedCount = 0;
|
||||
uint8_t cmddata = ed->data[0];
|
||||
uint8_t newEventDataID = ed->eventDataID;
|
||||
|
||||
// check if should display this data, and make it available to other tags
|
||||
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)
|
||||
powerUp(INIT_EPD);
|
||||
eventUpdateScreen();
|
||||
|
||||
wdt30s();
|
||||
// enter AP mode
|
||||
pr("AP enabled\n");
|
||||
powerUp(INIT_RADIO);
|
||||
eventAPMode();
|
||||
powerDown(INIT_RADIO);
|
||||
pr("AP disabled\n");
|
||||
|
||||
// for good measure, check if the EPD was ready with the picture
|
||||
epdWaitRdy();
|
||||
|
||||
wdt10s();
|
||||
// display new data
|
||||
eventScreen();
|
||||
powerDown(INIT_EPD);
|
||||
} else {
|
||||
// ignore
|
||||
switch ((cmddata >> 4) & 0x03) {
|
||||
case EVENT_CMD_EVENTSCREEN:
|
||||
if (!((newEventDataID > eventDataID) || (eventDataID - newEventDataID > 128))) break; // ignore this message, its probably a mesh echo/reflection
|
||||
doMeshIfNeeded(cmddata);
|
||||
eventDataID = newEventDataID;
|
||||
wdt10s();
|
||||
powerUp(INIT_EPD);
|
||||
eventScreen();
|
||||
powerDown(INIT_EPD);
|
||||
break;
|
||||
case EVENT_CMD_DRAWSCREEN:
|
||||
if (!((newEventDataID > eventDataID) || (eventDataID - newEventDataID > 128))) break; // ignore this message, its probably a mesh echo/reflection
|
||||
doMeshIfNeeded(cmddata);
|
||||
eventDataID = newEventDataID;
|
||||
wdt30s();
|
||||
powerUp(INIT_EPD);
|
||||
switch (cmddata & 0x0F) {
|
||||
case 0:
|
||||
eventStartScreen();
|
||||
break;
|
||||
case 1:
|
||||
wdt60s();
|
||||
eventEndScreen();
|
||||
break;
|
||||
case 2:
|
||||
eventUpdateScreen();
|
||||
epdWaitRdy();
|
||||
break;
|
||||
}
|
||||
powerDown(INIT_EPD);
|
||||
break;
|
||||
case EVENT_CMD_CMD:
|
||||
if (!((newEventDataID > eventDataID) || (eventDataID - newEventDataID > 128))) break; // ignore this message, its probably a mesh echo/reflection
|
||||
switch (cmddata & 0x0F) {
|
||||
case 0: // reset
|
||||
if (eventDataID != 0) {
|
||||
doMeshIfNeeded(cmddata);
|
||||
wdtDeviceReset();
|
||||
}
|
||||
break;
|
||||
case 1: // go to event end
|
||||
doMeshIfNeeded(cmddata);
|
||||
failedCount = -1;
|
||||
break;
|
||||
}
|
||||
eventDataID = newEventDataID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
doSleep(EVENT_POLL_INTERVAL);
|
||||
@@ -446,13 +492,13 @@ void eventMode() {
|
||||
eventEndScreen();
|
||||
powerDown(INIT_EPD);
|
||||
|
||||
// sleep, wake every 10 minutes to see if an event has started;
|
||||
// sleep, wake every 10 minutes to see if an event has started;
|
||||
while (1) {
|
||||
doSleep(600000);
|
||||
wdt10s();
|
||||
powerUp(INIT_RADIO);
|
||||
struct eventData* __xdata ed = getEventData();
|
||||
powerDown(INIT_RADIO);
|
||||
if(ed!=NULL)wdtDeviceReset();
|
||||
if (ed != NULL) wdtDeviceReset();
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,22 @@ struct MacFrameBcast {
|
||||
uint8_t src[8];
|
||||
} __packed;
|
||||
|
||||
#define EVENT_CMD_EVENTSCREEN 3
|
||||
#define EVENT_CMD_DRAWSCREEN 2
|
||||
#define EVENT_CMD_CMD 1
|
||||
#define EVENT_CMD_GETIMGBLOCKDATA 0
|
||||
|
||||
struct eventCmd{
|
||||
uint8_t mesh : 1;
|
||||
uint8_t noMeshScreen : 1;
|
||||
uint8_t cmd : 2;
|
||||
uint8_t cmdArg: 4;
|
||||
} __packed;
|
||||
|
||||
#define EVENT_CMD_RESET 0
|
||||
#define EVENT_CMD_NO_MESH_SCREEN 0x40
|
||||
|
||||
|
||||
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
|
||||
#define PKT_AVAIL_DATA_REQ 0xE5
|
||||
#define PKT_AVAIL_DATA_INFO 0xE6
|
||||
|
||||
@@ -817,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 7
|
||||
#define EVENT_DATA_REQ_RX_WINDOW_SIZE 8
|
||||
|
||||
static void sendEventPong(const void *__xdata buf) {
|
||||
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf;
|
||||
@@ -860,9 +860,11 @@ void eventAPMode() {
|
||||
// received a packet, lets see what it is
|
||||
switch (getPacketType(inBuffer)) {
|
||||
case PKT_PING:
|
||||
timerDelay(13 * (100 - mLastLqi));
|
||||
sendEventPong(inBuffer);
|
||||
break;
|
||||
case PKT_EVENT_DATA_REQ:
|
||||
timerDelay(13 * (100 - mLastLqi));
|
||||
sendEventDataReply(inBuffer);
|
||||
break;
|
||||
}
|
||||
@@ -891,8 +893,7 @@ struct eventData *__xdata getEventData() {
|
||||
bool timeExtended = false;
|
||||
timerDelay(100);
|
||||
for (uint8_t c = 0; c < 2; c++) {
|
||||
|
||||
if(!sendEventDataReq()) return NULL;
|
||||
if (!sendEventDataReq()) return NULL;
|
||||
|
||||
t = timerGet() + (TIMER_TICKS_PER_MS * EVENT_DATA_REQ_RX_WINDOW_SIZE);
|
||||
|
||||
@@ -900,7 +901,7 @@ struct eventData *__xdata getEventData() {
|
||||
int8_t __xdata ret = commsRxUnencrypted(inBuffer);
|
||||
|
||||
if (ret > 1) {
|
||||
if (getPacketType(inBuffer) == PKT_EVENT_DATA) {
|
||||
if ((getPacketType(inBuffer) == PKT_EVENT_DATA) && (pktIsUnicast(inBuffer))) {
|
||||
if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct eventData) + EVENT_PKT_SIZE)) {
|
||||
struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)inBuffer;
|
||||
memcpy(blockXferBuffer, inBuffer + sizeof(struct MacFrameNormal) + 1, 128);
|
||||
|
||||
@@ -255,7 +255,7 @@ void showSplashScreen() {
|
||||
epdPrintEnd();
|
||||
|
||||
epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
epdpr("Hackaday Berlin 2023");
|
||||
epdpr("Hackaday Berlin 2023-");
|
||||
//epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
|
||||
epdPrintEnd();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user