From fa97daef3c15456a44c57f4683a171d4347b33eb Mon Sep 17 00:00:00 2001 From: jjwbruijn Date: Thu, 28 Sep 2023 01:03:29 +0200 Subject: [PATCH] M2 FW 2.2 - Preload and buttons --- .../Tag/SOLUM_154_SSD1619-tag-00-0022.bin | Bin 0 -> 61576 bytes binaries/Tag/SOLUM_29_SSD1619-tag-01-0022.bin | Bin 0 -> 61786 bytes binaries/Tag/SOLUM_29_UC8151-tag-11-0022.bin | Bin 0 -> 59733 bytes binaries/Tag/SOLUM_42_SSD1619-tag-02-0022.bin | Bin 0 -> 61777 bytes oepl-definitions.h | 13 +- zbs243_Tag_FW/main.c | 261 +++++++++++---- zbs243_Tag_FW/powermgt.c | 38 ++- zbs243_Tag_FW/powermgt.h | 7 + zbs243_Tag_FW/settings.h | 6 +- zbs243_Tag_FW/syncedproto.c | 306 ++++++++++++------ zbs243_Tag_FW/syncedproto.h | 11 +- zbs243_Tag_FW/userinterface.c | 141 ++++---- zbs243_Tag_FW/userinterface.h | 9 +- zbs243_shared/eeprom.c | 0 zbs243_shared/eeprom.h | 49 ++- 15 files changed, 580 insertions(+), 261 deletions(-) create mode 100644 binaries/Tag/SOLUM_154_SSD1619-tag-00-0022.bin create mode 100644 binaries/Tag/SOLUM_29_SSD1619-tag-01-0022.bin create mode 100644 binaries/Tag/SOLUM_29_UC8151-tag-11-0022.bin create mode 100644 binaries/Tag/SOLUM_42_SSD1619-tag-02-0022.bin mode change 100644 => 100755 zbs243_shared/eeprom.c mode change 100644 => 100755 zbs243_shared/eeprom.h diff --git a/binaries/Tag/SOLUM_154_SSD1619-tag-00-0022.bin b/binaries/Tag/SOLUM_154_SSD1619-tag-00-0022.bin new file mode 100644 index 0000000000000000000000000000000000000000..aaf0edd5f81158b05dd8079a6dba69040456dbf4 GIT binary patch literal 61576 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 WPe@PvXx9hg|ICZ7zxa2;zyAjGduRdx literal 0 HcmV?d00001 diff --git a/binaries/Tag/SOLUM_29_SSD1619-tag-01-0022.bin b/binaries/Tag/SOLUM_29_SSD1619-tag-01-0022.bin new file mode 100644 index 0000000000000000000000000000000000000000..9dea4e92a12af2cad54625a45fd5222a978a4506 GIT binary patch literal 61786 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

CeI=KU z%%`DG60s?)?J6WnVYcH3(kQ8l3Xw{c64*Kn23<_f&OZA1@l!|J&VR%&sNfBRQ*ngE z*vz&_7pnF7^UP=(3bZW}O9R0Pz(Q=z{K}}!M_9eIjCo0!>P9(TJGZKk6r-4mrdVm?<%Zw{-Ezl^SA#x}TpiLsr8= zx2b0Qfo?f8ZlV2*7j%c{uKYXp{n@*#mk^ACx#p!i4_vl6h$=#$hYq2^QyuK3!#Y-X z_8Rc?F3Nm1_?VUXZ1`XiW7Nko@iuek2%Doz#ci%x9DNZ1B!9^Vx9RL$8140DEV)z%rkWj=;)%Hkr>xz<-hX zY%-q>&Y_vlhJ85f6*A}X%x43CS?04r)JAVMhwt86fALn+ddHgXI^xLzaaelH<@x9rT_o{ literal 0 HcmV?d00001 diff --git a/binaries/Tag/SOLUM_29_UC8151-tag-11-0022.bin b/binaries/Tag/SOLUM_29_UC8151-tag-11-0022.bin new file mode 100644 index 0000000000000000000000000000000000000000..e8aee8e164e1d3837d460eac6b846ae705918b7a GIT binary patch literal 59733 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 result[c]) result[c] = mLastLqi; - pr("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI); - } - } - } - - uint8_t __xdata highestLqi = 0; - uint8_t __xdata highestSlot = 0; - for (uint8_t c = 0; c < sizeof(result); c++) { - if (result[c] > highestLqi) { - highestSlot = channelList[c]; - highestLqi = result[c]; - } - } - powerDown(INIT_RADIO); - epdWaitRdy(); - mLastLqi = highestLqi; - return highestSlot; -} -uint8_t channelSelect() { // returns 0 if no accesspoints were found +uint8_t channelSelect(uint8_t rounds) { // returns 0 if no accesspoints were found powerUp(INIT_RADIO); uint8_t __xdata result[16]; memset(result, 0, sizeof(result)); - for (uint8_t i = 0; i < 2; i++) { + for (uint8_t i = 0; i < rounds; i++) { for (uint8_t c = 0; c < sizeof(channelList); c++) { if (detectAP(channelList[c])) { if (mLastLqi > result[c]) result[c] = mLastLqi; + if (rounds > 2) pr("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI); } } } @@ -215,6 +180,7 @@ void detectButtonOrJig() { void TagAssociated() { // associated + bool fastNextCheckin = false; struct AvailDataInfo *__xdata avail; // Is there any reason why we should do a long (full) get data request (including reason, status)? if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) { @@ -234,7 +200,8 @@ void TagAssociated() { if (curImgSlot != 0xFF) { powerUp(INIT_EEPROM | INIT_EPD); wdt60s(); - drawImageFromEeprom(curImgSlot); + uint8_t lut = getEepromImageDataArgument(curImgSlot) & 0x03; + drawImageFromEeprom(curImgSlot, lut); powerDown(INIT_EEPROM | INIT_EPD); } else { powerUp(INIT_EPD); @@ -247,6 +214,23 @@ void TagAssociated() { avail = getAvailDataInfo(); powerDown(INIT_RADIO); + switch (wakeUpReason) { + case WAKEUP_REASON_BUTTON1: + gpioButton1(); + fastNextCheckin = true; + break; + case WAKEUP_REASON_BUTTON2: + gpioButton2(); + fastNextCheckin = true; + break; +#ifdef ENABLE_GPIO_WAKE + case WAKEUP_REASON_GPIO: + gpioButtonOther(); + fastNextCheckin = true; + break; +#endif + } + if (avail != NULL) { // we got some data! longDataReqCounter = 0; @@ -254,14 +238,12 @@ void TagAssociated() { wakeUpReason = WAKEUP_REASON_TIMED; } if (tagSettings.enableTagRoaming) { - uint8_t roamChannel = channelSelect(); + uint8_t roamChannel = channelSelect(1); if (roamChannel) currentChannel = roamChannel; } } else { powerUp(INIT_RADIO); - - #ifdef ENABLE_RETURN_DATA // example code to send data back to the AP. Up to 90 bytes can be sent in one packet uint8_t __xdata blaat[2] = {0xAB, 0xBA}; @@ -304,11 +286,22 @@ void TagAssociated() { } } - // if the AP told us to sleep for a specific period, do so. - if (nextCheckInFromAP) { - doSleep(nextCheckInFromAP * 60000UL); + if (fastNextCheckin) { + // do a fast check-in next + fastNextCheckin = false; + doSleep(100UL); } else { - doSleep(getNextSleep() * 1000UL); + if (nextCheckInFromAP) { + // if the AP told us to sleep for a specific period, do so. + if (nextCheckInFromAP & 0x8000) { + doSleep((nextCheckInFromAP & 0x7FFF) * 1000UL); + } else { + doSleep(nextCheckInFromAP * 60000UL); + } + } else { + // sleep determined by algorithm + doSleep(getNextSleep() * 1000UL); + } } } @@ -319,7 +312,7 @@ void TagChanSearch() { } // try to find a working channel - currentChannel = channelSelect(); + currentChannel = channelSelect(2); // Check if we should redraw the screen with icons, info screen or screensaver if ((!currentChannel && !noAPShown && tagSettings.enableNoRFSymbol) || @@ -328,9 +321,12 @@ void TagChanSearch() { powerUp(INIT_EPD); wdt60s(); if (curImgSlot != 0xFF) { - powerUp(INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EEPROM); + if (!displayCustomImage(CUSTOM_IMAGE_LOST_CONNECTION)) { + powerUp(INIT_EEPROM); + uint8_t lut = getEepromImageDataArgument(curImgSlot) & 0x03; + drawImageFromEeprom(curImgSlot, lut); + powerDown(INIT_EEPROM); + } } else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { showLongTermSleep(); } else { @@ -354,6 +350,72 @@ void TagChanSearch() { } } +void TagSlideShow() { + currentChannel = 11; // suppress the no-rf image thing + displayCustomImage(CUSTOM_IMAGE_SPLASHSCREEN); + + // do a short channel search + currentChannel = channelSelect(2); + + pr("Slideshow mode ch: %d\n", currentChannel); + + // if we did find an AP, check in once + if (currentChannel) { + doVoltageReading(); + struct AvailDataInfo *__xdata avail; + powerUp(INIT_RADIO); + avail = getAvailDataInfo(); + + if (avail != NULL) { + processAvailDataInfo(avail); + } + } + powerDown(INIT_RADIO); + + // suppress the no-rf image + currentChannel = 11; + + while (1) { + powerUp(INIT_UART); + wdt60s(); + powerUp(INIT_EEPROM); + uint8_t img = findNextSlideshowImage(slideShowCurrentImg); + if (img != slideShowCurrentImg) { + slideShowCurrentImg = img; + uint8_t lut = getEepromImageDataArgument(img) & 0x03; + powerUp(INIT_EPD); + if (SLIDESHOW_FORCE_FULL_REFRESH_EVERY) { + slideShowRefreshCount++; + } + if ((slideShowRefreshCount == SLIDESHOW_FORCE_FULL_REFRESH_EVERY) || (lut == 0)) { + slideShowRefreshCount = 1; + lut = 0; + } + drawImageFromEeprom(img, lut); + powerDown(INIT_EPD | INIT_EEPROM); + } else { + // same image, so don't update the screen; this only happens when there's exactly one slideshow image + powerDown(INIT_EEPROM); + } + + switch (tagSettings.customMode) { + case TAG_CUSTOM_SLIDESHOW_FAST: + doSleep(1000UL * SLIDESHOW_INTERVAL_FAST); + break; + case TAG_CUSTOM_SLIDESHOW_MEDIUM: + doSleep(1000UL * SLIDESHOW_INTERVAL_MEDIUM); + break; + case TAG_CUSTOM_SLIDESHOW_SLOW: + doSleep(1000UL * SLIDESHOW_INTERVAL_SLOW); + break; + case TAG_CUSTOM_SLIDESHOW_GLACIAL: + doSleep(1000UL * SLIDESHOW_INTERVAL_GLACIAL); + break; + } + pr("wake...\n"); + } +} + void executeCommand(uint8_t cmd) { switch (cmd) { case CMD_DO_REBOOT: @@ -364,7 +426,7 @@ void executeCommand(uint8_t cmd) { writeSettings(); break; case CMD_DO_SCAN: - currentChannel = channelSelect(); + currentChannel = channelSelect(4); break; case CMD_DO_DEEPSLEEP: powerUp(INIT_EPD); @@ -374,6 +436,61 @@ void executeCommand(uint8_t cmd) { doSleep(-1); } break; + case CMD_ERASE_EEPROM_IMAGES: + powerUp(INIT_EEPROM); + eraseImageBlocks(); + powerDown(INIT_EEPROM); + break; + case CMD_ENTER_SLIDESHOW_FAST: + powerUp(INIT_EEPROM); + if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) { + powerDown(INIT_EEPROM); + return; + } + powerDown(INIT_EEPROM); + tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_FAST; + writeSettings(); + wdtDeviceReset(); + break; + case CMD_ENTER_SLIDESHOW_MEDIUM: + powerUp(INIT_EEPROM); + if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) { + powerDown(INIT_EEPROM); + return; + } + powerDown(INIT_EEPROM); + tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_MEDIUM; + writeSettings(); + wdtDeviceReset(); + break; + case CMD_ENTER_SLIDESHOW_SLOW: + powerUp(INIT_EEPROM); + if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) { + powerDown(INIT_EEPROM); + return; + } + powerDown(INIT_EEPROM); + + tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_SLOW; + writeSettings(); + wdtDeviceReset(); + break; + case CMD_ENTER_SLIDESHOW_GLACIAL: + powerUp(INIT_EEPROM); + if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) { + powerDown(INIT_EEPROM); + return; + } + powerDown(INIT_EEPROM); + tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_GLACIAL; + writeSettings(); + wdtDeviceReset(); + break; + case CMD_ENTER_NORMAL_MODE: + tagSettings.customMode = TAG_CUSTOM_MODE_NONE; + writeSettings(); + wdtDeviceReset(); + break; } } @@ -399,6 +516,17 @@ void main() { // get the highest slot number, number of slots initializeProto(); + switch (tagSettings.customMode) { + case TAG_CUSTOM_SLIDESHOW_FAST: + case TAG_CUSTOM_SLIDESHOW_MEDIUM: + case TAG_CUSTOM_SLIDESHOW_SLOW: + case TAG_CUSTOM_SLIDESHOW_GLACIAL: + TagSlideShow(); + break; + default: + break; + } + if (tagSettings.enableFastBoot) { // Fastboot pr("Doing fast boot\n"); @@ -406,7 +534,7 @@ void main() { if (tagSettings.fixedChannel) { currentChannel = tagSettings.fixedChannel; } else { - currentChannel = channelSelect(); + currentChannel = channelSelect(2); } } else { // Normal boot/startup @@ -426,9 +554,9 @@ void main() { detectButtonOrJig(); // show the splashscreen - pr("EPD: First powerup\n"); - powerUp(INIT_EPD); + currentChannel = 11; showSplashScreen(); + currentChannel = 0; // we've now displayed something on the screen; for the SSD1619, we are now aware of the lut-size #ifdef EPD_SSD1619 @@ -443,28 +571,25 @@ void main() { writeSettings(); // scan for channels - powerUp(INIT_EPD); wdt30s(); if (tagSettings.fixedChannel) { currentChannel = tagSettings.fixedChannel; } else { - currentChannel = showChannelSelect(); + currentChannel = channelSelect(4); } } - // end of the fastboot option split + wdt10s(); powerUp(INIT_EPD); if (currentChannel) { showAPFound(); initPowerSaving(INTERVAL_BASE); - powerDown(INIT_EPD | INIT_UART); currentTagMode = TAG_MODE_ASSOCIATED; doSleep(5000UL); } else { showNoAP(); initPowerSaving(INTERVAL_AT_MAX_ATTEMPTS); - powerDown(INIT_EPD | INIT_UART); currentTagMode = TAG_MODE_CHANSEARCH; doSleep(120000UL); } diff --git a/zbs243_Tag_FW/powermgt.c b/zbs243_Tag_FW/powermgt.c index d403eac9..077b16b7 100755 --- a/zbs243_Tag_FW/powermgt.c +++ b/zbs243_Tag_FW/powermgt.c @@ -292,16 +292,34 @@ void doSleep(const uint32_t __xdata t) { P1DIR |= (1 << 0); P1PULL |= (1 << 0); P1LVLSEL |= (1 << 0); - P1INTEN = (1 << 0); + P1INTEN |= (1 << 0); P1CHSTA &= ~(1 << 0); + + // Button setup on RXD pin 0.7 (input pullup) + P0FUNC &= ~(1 << 7); + P0DIR |= (1 << 7); + P0PULL |= (1 << 7); + P0LVLSEL |= (1 << 7); + P0INTEN |= (1 << 7); + P0CHSTA &= ~(1 << 7); } +#ifdef ENABLE_GPIO_WAKE + // enable wake on pin 0.2 (MISO) + P0FUNC &= ~(1 << 3); + P0DIR |= (1 << 3); + P0PULL |= (1 << 3); + P0LVLSEL |= (1 << 3); + P0INTEN |= (1 << 3); + P0CHSTA &= ~(1 << 3); +#endif + if (capabilities & CAPABILITY_NFC_WAKE) { P1FUNC &= ~(1 << 3); P1DIR |= (1 << 3); P1PULL |= (1 << 3); P1LVLSEL |= (1 << 3); - P1INTEN = (1 << 3); + P1INTEN |= (1 << 3); P1CHSTA &= ~(1 << 3); } @@ -313,15 +331,29 @@ void doSleep(const uint32_t __xdata t) { // sleepy time sleepForMsec(t); P1INTEN = 0; + P0INTEN = 0; if ((P1CHSTA & (1 << 0)) && (capabilities & CAPABILITY_HAS_WAKE_BUTTON)) { - wakeUpReason = WAKEUP_REASON_GPIO; + wakeUpReason = WAKEUP_REASON_BUTTON1; P1CHSTA &= ~(1 << 0); } + if ((P0CHSTA & (1 << 7)) && (capabilities & CAPABILITY_HAS_WAKE_BUTTON)) { + wakeUpReason = WAKEUP_REASON_BUTTON2; + P0CHSTA &= ~(1 << 7); + } + if ((P1CHSTA & (1 << 3)) && (capabilities & CAPABILITY_NFC_WAKE)) { wakeUpReason = WAKEUP_REASON_NFC; P1CHSTA &= ~(1 << 3); } + +#ifdef ENABLE_GPIO_WAKE + if (P0CHSTA & (1 << 3)) { + wakeUpReason = WAKEUP_REASON_GPIO; + P0CHSTA &= ~(1 << 3); + } +#endif + } void doVoltageReading() { diff --git a/zbs243_Tag_FW/powermgt.h b/zbs243_Tag_FW/powermgt.h index f93bc3a1..8ee8bc1b 100755 --- a/zbs243_Tag_FW/powermgt.h +++ b/zbs243_Tag_FW/powermgt.h @@ -40,6 +40,13 @@ #define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day) #define INTERVAL_3_TIME 86400UL // Finally, try every day +// slideshow power settings +#define SLIDESHOW_FORCE_FULL_REFRESH_EVERY 16 // force a full refresh every X screen draws +#define SLIDESHOW_INTERVAL_FAST 15 // interval for 'fast' +#define SLIDESHOW_INTERVAL_MEDIUM 60 +#define SLIDESHOW_INTERVAL_SLOW 300 +#define SLIDESHOW_INTERVAL_GLACIAL 1800 + extern uint8_t checkButtonOrJig(); extern void setupPortsInitial(); diff --git a/zbs243_Tag_FW/settings.h b/zbs243_Tag_FW/settings.h index 3bd820fd..b058c8cb 100755 --- a/zbs243_Tag_FW/settings.h +++ b/zbs243_Tag_FW/settings.h @@ -3,11 +3,11 @@ #include -#define FW_VERSION 21 // version number (max 2.5.5 :) ) -#define FW_VERSION_SUFFIX "-RET" // suffix, like -RC1 or whatever. +#define FW_VERSION 22 // version number (max 2.5.5 :) ) +#define FW_VERSION_SUFFIX "-BUT" // suffix, like -RC1 or whatever. // #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers // #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket - +#define ENABLE_GPIO_WAKE // uncomment to enable GPIO wake // #define ENABLE_RETURN_DATA // enables the tag to send blocks of data back. Enabling this costs about 4 IRAM bytes #define SETTINGS_STRUCT_VERSION 0x01 diff --git a/zbs243_Tag_FW/syncedproto.c b/zbs243_Tag_FW/syncedproto.c index 4efbb641..938c9c4c 100755 --- a/zbs243_Tag_FW/syncedproto.c +++ b/zbs243_Tag_FW/syncedproto.c @@ -28,17 +28,17 @@ // download-stuff uint8_t __xdata blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0}; -static struct blockRequest __xdata curBlock = {0}; // used by the block-requester, contains the next request that we'll send -static struct AvailDataInfo __xdata curDataInfo = {0}; // last 'AvailDataInfo' we received from the AP -static bool __xdata requestPartialBlock = false; // if we should ask the AP to get this block from the host or not +static struct blockRequest __xdata curBlock = {0}; // used by the block-requester, contains the next request that we'll send +static uint8_t __xdata curDispDataVer[8] = {0}; +static struct AvailDataInfo __xdata xferDataInfo = {0}; // holds the AvailDataInfo during the transfer +static bool __xdata requestPartialBlock = false; // if we should ask the AP to get this block from the host or not #define BLOCK_TRANSFER_ATTEMPTS 5 -uint8_t __xdata prevImgSlot = 0xFF; -uint8_t __xdata curImgSlot = 0xFF; -static uint32_t __xdata curHighSlotId = 0; -static uint8_t __xdata nextImgSlot = 0; +static uint8_t xferImgSlot = 0xFF; // holds current transfer slot in progress +uint8_t __xdata curImgSlot = 0xFF; // currently shown image +static uint32_t __xdata curHighSlotId = 0; // current highest ID, will be incremented before getting written to a new slot +static uint8_t __xdata nextImgSlot = 0; // next slot in sequence for writing static uint8_t __xdata imgSlots = 0; -uint8_t __xdata drawWithLut = 0; // stuff we need to keep track of related to the network/AP uint8_t __xdata APmac[8] = {0}; @@ -51,6 +51,9 @@ uint8_t __xdata currentChannel = 0; static uint8_t __xdata inBuffer[128] = {0}; static uint8_t __xdata outBuffer[128] = {0}; +// other stuff we shouldn't have to put here... +static uint32_t __xdata markerValid = EEPROM_IMG_VALID; + extern void executeCommand(uint8_t cmd); // this is defined in main.c // tools @@ -469,10 +472,9 @@ static void getNumSlots() { } else imgSlots = nSlots; } -static uint8_t findSlot(const uint8_t *__xdata ver) { +static uint8_t findSlotVer(const uint8_t *ver) { // return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere - uint32_t __xdata markerValid = EEPROM_IMG_VALID; - for (uint8_t __xdata c = 0; c < imgSlots; c++) { + for (uint8_t c = 0; c < imgSlots; c++) { struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); if (xMemEqual4(&eih->validMarker, &markerValid)) { @@ -483,6 +485,42 @@ static uint8_t findSlot(const uint8_t *__xdata ver) { } return 0xFF; } + +// making this reentrant saves one byte of idata... +uint8_t __xdata findSlotDataTypeArg(uint8_t arg) __reentrant { + arg &= (0xF8); // unmatch with the 'preload' bit and LUT bits + for (uint8_t c = 0; c < imgSlots; c++) { + struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; + eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); + if (xMemEqual4(&eih->validMarker, &markerValid)) { + if ((eih->argument & 0xF8) == arg) { + return c; + } + } + } + return 0xFF; +} +uint8_t getEepromImageDataArgument(const uint8_t slot) { + struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; + eepromRead(getAddressForSlot(slot), eih, sizeof(struct EepromImageHeader)); + return eih->argument; +} +uint8_t __xdata findNextSlideshowImage(uint8_t start) __reentrant { + struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; + uint8_t c = start; + while (1) { + c++; + if (c > imgSlots) c = 0; + if (c == start) return c; + eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); + if (xMemEqual4(&eih->validMarker, &markerValid)) { + if ((eih->argument & 0xF8) == (CUSTOM_IMAGE_SLIDESHOW << 3)) { + return c; + } + } + } +} + static void eraseUpdateBlock() { eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN / EEPROM_ERZ_SECTOR_SZ); } @@ -500,13 +538,16 @@ static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) { if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length)) pr("EEPROM write failed\n"); } -void drawImageFromEeprom(const uint8_t imgSlot) { - drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut); - drawWithLut = 0; // default back to the regular ol' stock/OTP LUT +void eraseImageBlocks() { + for (uint8_t c = 0; c < imgSlots; c++) { + eraseImageBlock(c); + } +} +void drawImageFromEeprom(const uint8_t imgSlot, uint8_t lut) { + drawImageAtAddress(getAddressForSlot(imgSlot), lut); } static uint32_t getHighSlotId() { uint32_t temp = 0; - uint32_t __xdata markerValid = EEPROM_IMG_VALID; for (uint8_t __xdata c = 0; c < imgSlots; c++) { struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); @@ -625,25 +666,25 @@ static bool getDataBlock(const uint16_t blockSize) { uint16_t __xdata dataRequestSize = 0; static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) { // check if we already started the transfer of this information & haven't completed it - if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8) && curDataInfo.dataSize) { + if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8) && xferDataInfo.dataSize) { // looks like we did. We'll carry on where we left off. } else { // start, or restart the transfer from 0. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer curBlock.blockId = 0; xMemCopy8(&(curBlock.ver), &(avail->dataVer)); curBlock.type = avail->dataType; - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); eraseUpdateBlock(); } - while (curDataInfo.dataSize) { + while (xferDataInfo.dataSize) { wdt10s(); - if (curDataInfo.dataSize > BLOCK_DATA_SIZE) { + if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) { // more than one block remaining dataRequestSize = BLOCK_DATA_SIZE; } else { // only one block remains - dataRequestSize = curDataInfo.dataSize; + dataRequestSize = xferDataInfo.dataSize; } if (getDataBlock(dataRequestSize)) { // succesfully downloaded datablock, save to eeprom @@ -651,7 +692,7 @@ static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) { saveUpdateBlockData(curBlock.blockId); powerDown(INIT_EEPROM); curBlock.blockId++; - curDataInfo.dataSize -= dataRequestSize; + xferDataInfo.dataSize -= dataRequestSize; } else { // failed to get the block we wanted, we'll stop for now, maybe resume later return false; @@ -664,21 +705,42 @@ static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) { uint16_t __xdata imageSize = 0; static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail) { // check if we already started the transfer of this information & haven't completed it - if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8) && curDataInfo.dataSize) { + if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8) && + (xferDataInfo.dataTypeArgument == avail->dataTypeArgument) && + xferDataInfo.dataSize) { // looks like we did. We'll carry on where we left off. pr("restarting image download"); - curImgSlot = nextImgSlot; } else { - // go to the next image slot - nextImgSlot++; - if (nextImgSlot >= imgSlots) nextImgSlot = 0; - curImgSlot = nextImgSlot; - pr("Saving to image slot %d\n", curImgSlot); - drawWithLut = avail->dataTypeArgument; + // new transfer powerUp(INIT_EEPROM); + // go to the next image slot + uint8_t startingSlot = nextImgSlot; + while (1) { + nextImgSlot++; + if (nextImgSlot >= imgSlots) nextImgSlot = 0; + if (nextImgSlot == startingSlot) { + powerDown(INIT_EEPROM); + pr("No slots available. Too many images in the slideshow?\n"); + return true; + } + struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; + eepromRead(getAddressForSlot(nextImgSlot), eih, sizeof(struct EepromImageHeader)); + // check if the marker is indeed valid + if (xMemEqual4(&eih->validMarker, &markerValid)) { + struct imageDataTypeArgStruct *eepromDataArgument = (struct imageDataTypeArgStruct *)&(eih->argument); + // normal type, we can overwrite this + if (eepromDataArgument->specialType == 0x00) break; + } else { + // bullshit marker, so safe to overwrite + break; + } + } + + xferImgSlot = nextImgSlot; + uint8_t __xdata attempt = 5; while (attempt--) { - if (eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ)) goto eraseSuccess; + if (eepromErase(getAddressForSlot(xferImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ)) goto eraseSuccess; } eepromFail: powerDown(INIT_RADIO); @@ -688,35 +750,36 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail) doSleep(-1); wdtDeviceReset(); eraseSuccess: - pr("new download, writing to slot %d\n", curImgSlot); + powerDown(INIT_EEPROM); + pr("new download, writing to slot %d\n", xferImgSlot); // start, or restart the transfer. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer curBlock.blockId = 0; xMemCopy8(&(curBlock.ver), &(avail->dataVer)); curBlock.type = avail->dataType; - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - imageSize = curDataInfo.dataSize; + xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + imageSize = xferDataInfo.dataSize; } - while (curDataInfo.dataSize) { + while (xferDataInfo.dataSize) { wdt10s(); - if (curDataInfo.dataSize > BLOCK_DATA_SIZE) { + if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) { // more than one block remaining dataRequestSize = BLOCK_DATA_SIZE; } else { // only one block remains - dataRequestSize = curDataInfo.dataSize; + dataRequestSize = xferDataInfo.dataSize; } if (getDataBlock(dataRequestSize)) { // succesfully downloaded datablock, save to eeprom powerUp(INIT_EEPROM); #ifdef DEBUGBLOCKS - pr("Saving block %d to slot %d\n", curBlock.blockId, curImgSlot); + pr("Saving block %d to slot %d\n", curBlock.blockId, xferImgSlot); #endif - saveImgBlockData(curImgSlot, curBlock.blockId); + saveImgBlockData(xferImgSlot, curBlock.blockId); powerDown(INIT_EEPROM); curBlock.blockId++; - curDataInfo.dataSize -= dataRequestSize; + xferDataInfo.dataSize -= dataRequestSize; } else { // failed to get the block we wanted, we'll stop for now, probably resume later return false; @@ -726,111 +789,138 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail) // borrow the blockXferBuffer temporarily struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer; - xMemCopy8(&eih->version, &curDataInfo.dataVer); + xMemCopy8(&eih->version, &xferDataInfo.dataVer); eih->validMarker = EEPROM_IMG_VALID; eih->id = ++curHighSlotId; eih->size = imageSize; - eih->dataType = curDataInfo.dataType; + eih->dataType = xferDataInfo.dataType; + eih->argument = xferDataInfo.dataTypeArgument; #ifdef DEBUGBLOCKS - pr("Now writing datatype 0x%02X to slot %d\n", curDataInfo.dataType, curImgSlot); + pr("Now writing datatype 0x%02X to slot %d\n", xferDataInfo.dataType, xferImgSlot); #endif powerUp(INIT_EEPROM); - eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader)); + eepromWrite(getAddressForSlot(xferImgSlot), eih, sizeof(struct EepromImageHeader)); powerDown(INIT_EEPROM); return true; } -bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { - switch (avail->dataType) { -#if (SCREEN_WIDTH == 152) - // the 1.54" screen is pretty small, we can write an entire 1bpp image from the block transfer buffer directly to the EPD buffer - case DATATYPE_IMG_RAW_1BPP_DIRECT: - pr("Direct draw image received\n"); - if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) { - // we've downloaded this already, we're guessing it's already displayed - pr("currently shown image, send xfc\n"); - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - return true; - } - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - if (avail->dataSize > 4096) avail->dataSize = 4096; +inline bool processImageDataAvail(struct AvailDataInfo *__xdata avail) { + struct imageDataTypeArgStruct arg; + *((uint8_t *)arg) = avail->dataTypeArgument; - if (getDataBlock(avail->dataSize)) { - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); + if (arg.preloadImage) { + pr("Preloading image with type 0x%02X from arg 0x%02X\n", arg.specialType, avail->dataTypeArgument); + powerUp(INIT_EEPROM); + switch (arg.specialType) { + // check if a slot with this argument is already set; if so, erase. Only one of each arg type should exist + default: { + uint8_t slot = findSlotDataTypeArg(avail->dataTypeArgument); + if (slot != 0xFF) { + eepromErase(getAddressForSlot(slot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ); + } + } break; + // regular image preload, there can be multiple of this type in the EEPROM + case CUSTOM_IMAGE_NOCUSTOM: { + // check if a version of this already exists + uint8_t slot = findSlotVer(&(avail->dataVer)); + if (slot != 0xFF) { + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + } + } break; + case CUSTOM_IMAGE_SLIDESHOW: + break; + } + powerDown(INIT_EEPROM); - curDataInfo.dataSize = 0; // mark as transfer not pending - powerUp(INIT_EPD); - drawImageFromBuffer(blockXferBuffer, drawWithLut); - powerDown(INIT_EPD); - drawWithLut = 0; // default back to the regular ol' stock/OTP LUT - return true; - } + pr("downloading preload image...\n"); + if (downloadImageDataToEEPROM(avail)) { + // sets xferImgSlot to the right slot + pr("preload complete!\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + } else { return false; - break; -#endif - case DATATYPE_IMG_BMP: - case DATATYPE_IMG_DIFF: - case DATATYPE_IMG_RAW_1BPP: - case DATATYPE_IMG_RAW_2BPP: - // check if this download is currently displayed or active - if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) { - // we've downloaded this already, we're guessing it's already displayed - pr("currently shown image, send xfc\n"); - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - return true; - } + } - // check if we've seen this version before + } else { + // check if we're currently displaying this data payload + if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata)curDispDataVer, 8)) { + // currently displayed, not doing anything except for sending an XFC + + pr("currently shown image, send xfc\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + + } else { + // currently not displayed + + // try to find the data in the SPI EEPROM powerUp(INIT_EEPROM); - curImgSlot = findSlot(&(avail->dataVer)); + uint8_t findImgSlot = findSlotVer(&(avail->dataVer)); powerDown(INIT_EEPROM); - if (curImgSlot != 0xFF) { + + // Is this image already in a slot somewhere + if (findImgSlot != 0xFF) { // found a (complete)valid image slot for this version powerUp(INIT_RADIO); sendXferComplete(); powerDown(INIT_RADIO); - pr("already seen, drawing from eeprom slot %d\n", curImgSlot); - // mark as completed and draw from EEPROM - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - curDataInfo.dataSize = 0; // mark as transfer not pending + xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + xferDataInfo.dataSize = 0; // mark as transfer not pending - drawWithLut = avail->dataTypeArgument; wdt60s(); + curImgSlot = findImgSlot; powerUp(INIT_EPD | INIT_EEPROM); - drawImageFromEeprom(curImgSlot); + drawImageFromEeprom(findImgSlot, arg.lut); powerDown(INIT_EPD | INIT_EEPROM); - return true; + } else { // not found in cache, prepare to download - pr("downloading to imgslot\n"); - drawWithLut = avail->dataTypeArgument; - powerUp(INIT_EEPROM); + pr("downloading image...\n"); if (downloadImageDataToEEPROM(avail)) { + // sets xferImgSlot to the right slot pr("download complete!\n"); powerUp(INIT_RADIO); sendXferComplete(); powerDown(INIT_RADIO); + // not preload, draw now wdt60s(); + curImgSlot = xferImgSlot; powerUp(INIT_EPD | INIT_EEPROM); - drawImageFromEeprom(curImgSlot); + drawImageFromEeprom(xferImgSlot, arg.lut); powerDown(INIT_EPD | INIT_EEPROM); - return true; + } else { - powerDown(INIT_EEPROM); return false; } } + + // keep track on what is currently displayed + xMemCopy8(curDispDataVer, xferDataInfo.dataVer); + return true; + } + } +} + +bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { + switch (avail->dataType) { + case DATATYPE_IMG_BMP: + case DATATYPE_IMG_DIFF: + case DATATYPE_IMG_RAW_1BPP: + case DATATYPE_IMG_RAW_2BPP: + return processImageDataAvail(avail); break; case DATATYPE_FW_UPDATE: powerUp(INIT_EEPROM); @@ -866,6 +956,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { } pr("NFC URL received\n"); + /* if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) { // we've already downloaded this NFC data, disregard and send XFC pr("this was the same as the last transfer, disregard\n"); @@ -899,8 +990,9 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { } return false; break; + */ case DATATYPE_TAG_CONFIG_DATA: - if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) { + if (xferDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8)) { pr("this was the same as the last transfer, disregard\n"); powerUp(INIT_RADIO); sendXferComplete(); @@ -910,10 +1002,10 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { curBlock.blockId = 0; xMemCopy8(&(curBlock.ver), &(avail->dataVer)); curBlock.type = avail->dataType; - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); wdt10s(); if (getDataBlock(avail->dataSize)) { - curDataInfo.dataSize = 0; // mark as transfer not pending + xferDataInfo.dataSize = 0; // mark as transfer not pending loadSettingsFromBuffer(sizeof(struct blockData) + blockXferBuffer); powerUp(INIT_RADIO); sendXferComplete(); @@ -943,7 +1035,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { } #ifdef EPD_SSD1619 pr("OTA LUT received\n"); - if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) { + if (xferDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8)) { pr("this was the same as the last transfer, disregard\n"); powerUp(INIT_RADIO); sendXferComplete(); @@ -953,10 +1045,10 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { curBlock.blockId = 0; xMemCopy8(&(curBlock.ver), &(avail->dataVer)); curBlock.type = avail->dataType; - xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); wdt10s(); if (getDataBlock(avail->dataSize)) { - curDataInfo.dataSize = 0; // mark as transfer not pending + xferDataInfo.dataSize = 0; // mark as transfer not pending memcpy(customLUT, sizeof(struct blockData) + blockXferBuffer, 6 + (dispLutSize * 10)); powerUp(INIT_RADIO); sendXferComplete(); diff --git a/zbs243_Tag_FW/syncedproto.h b/zbs243_Tag_FW/syncedproto.h index 5f6287b7..3a01a5b8 100755 --- a/zbs243_Tag_FW/syncedproto.h +++ b/zbs243_Tag_FW/syncedproto.h @@ -10,8 +10,8 @@ extern uint8_t __xdata APmac[]; extern uint8_t __xdata curImgSlot; -extern void setupRadio(void); -extern void killRadio(void); +//extern void setupRadio(void); +//extern void killRadio(void); #ifdef ENABLE_RETURN_DATA @@ -19,9 +19,14 @@ extern bool sendTagReturnData(uint8_t __xdata *data, uint8_t len, uint8_t type); #endif void dump(const uint8_t *__xdata a, const uint16_t __xdata l); + +extern uint8_t __xdata findSlotDataTypeArg(uint8_t arg) __reentrant; +uint8_t __xdata findNextSlideshowImage(uint8_t start) __reentrant; +uint8_t getEepromImageDataArgument(const uint8_t slot); extern struct AvailDataInfo *__xdata getAvailDataInfo(); extern struct AvailDataInfo *__xdata getShortAvailDataInfo(); -extern void drawImageFromEeprom(const uint8_t imgSlot); +extern void drawImageFromEeprom(const uint8_t imgSlot, uint8_t lut); +void eraseImageBlocks(); extern bool processAvailDataInfo(struct AvailDataInfo *__xdata avail); extern void initializeProto(); extern uint8_t detectAP(const uint8_t channel); diff --git a/zbs243_Tag_FW/userinterface.c b/zbs243_Tag_FW/userinterface.c index 912ff923..47cdb2cc 100755 --- a/zbs243_Tag_FW/userinterface.c +++ b/zbs243_Tag_FW/userinterface.c @@ -52,7 +52,7 @@ void addCapabilities() { } void addOverlay() { - if ((currentChannel == 0)&&(tagSettings.enableNoRFSymbol)) { + if ((currentChannel == 0) && (tagSettings.enableNoRFSymbol)) { #if (SCREEN_WIDTH == 152) loadRawBitmap(ant, SCREEN_WIDTH - 16, 0, EPD_COLOR_BLACK); loadRawBitmap(cross, SCREEN_WIDTH - 8, 7, EPD_COLOR_RED); @@ -83,6 +83,7 @@ void addOverlay() { } void afterFlashScreenSaver() { + if (displayCustomImage(CUSTOM_IMAGE_LONGTERMSLEEP)) return; selectLUT(EPD_LUT_DEFAULT); clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -92,7 +93,6 @@ void afterFlashScreenSaver() { epdpr("OpenEPaperLink"); epdPrintEnd(); - epdPrintBegin(100, 32, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); epdpr("v%d.%d.%d", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10)); epdPrintEnd(); @@ -172,7 +172,7 @@ void afterFlashScreenSaver() { epdpr("v%d.%d.%d", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10)); epdPrintEnd(); - epdPrintBegin(10, 48, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdPrintBegin(10, 48, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); epdpr("I'm fast asleep... UwU To wake me:"); epdPrintEnd(); @@ -201,6 +201,8 @@ void afterFlashScreenSaver() { } void showSplashScreen() { + if (displayCustomImage(CUSTOM_IMAGE_SPLASHSCREEN)) return; + powerUp(INIT_EPD); selectLUT(EPD_LUT_NO_REPEATS); clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -298,6 +300,7 @@ void showSplashScreen() { #endif drawWithSleep(); + powerUp(INIT_EPD); } void showApplyUpdate() { @@ -322,60 +325,10 @@ void showApplyUpdate() { drawNoWait(); } -uint8_t __xdata resultcounter = 0; - -void showScanningWindow() { - setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); - selectLUT(EPD_LUT_FAST_NO_REDS); - clearScreen(); -#if (SCREEN_WIDTH == 128) // 2.9" - epdPrintBegin(2, 275, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - epdpr("Scanning for APs"); - epdPrintEnd(); - // epdPrintBegin(40, 262, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_RED); - // epdpr("Channel - Quality"); - // epdPrintEnd(); - loadRawBitmap(receive, 36, 24, EPD_COLOR_BLACK); -#endif -#if (SCREEN_WIDTH == 152) // 1.54" - loadRawBitmap(receive, 96, 28, EPD_COLOR_BLACK); - epdPrintBegin(3, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - epdpr("Scanning..."); - epdPrintEnd(); -#endif -#if (SCREEN_WIDTH == 400) // 4.2" - epdPrintBegin(2, 2, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); - epdpr("Scanning for APs"); - epdPrintEnd(); - - // epdPrintBegin(2, 40, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED); - // epdpr("Channel - Quality"); - // epdPrintEnd(); - loadRawBitmap(receive, 320, 125, EPD_COLOR_BLACK); -#endif - - draw(); - 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" - epdPrintBegin(56 + ((resultcounter % 4) * 16), 282 - (47 * (resultcounter / 4)), EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); -#endif -#if (SCREEN_WIDTH == 152) // 1.54" - epdPrintBegin(4 + (47 * (resultcounter / 8)), 31 + (15 * (resultcounter % 8)), EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); -#endif -#if (SCREEN_WIDTH == 400) // 4.2" - epdPrintBegin(4 + (47 * (resultcounter / 8)), 58 + (15 * (resultcounter % 8)), EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); -#endif - epdpr("%d-%d", channel, lqi); - epdPrintEnd(); - resultcounter++; -} - void showAPFound() { + if (displayCustomImage(CUSTOM_IMAGE_APFOUND)) return; + powerUp(INIT_EPD | INIT_EEPROM); + clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(1); @@ -479,9 +432,14 @@ void showAPFound() { #endif addOverlay(); drawWithSleep(); + powerDown(INIT_EPD | INIT_EEPROM); + } void showNoAP() { + if (displayCustomImage(CUSTOM_IMAGE_NOAPFOUND)) return; + powerUp(INIT_EPD | INIT_EEPROM); + selectLUT(EPD_LUT_NO_REPEATS); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); clearScreen(); @@ -525,9 +483,11 @@ void showNoAP() { #endif addOverlay(); drawWithSleep(); + powerDown(INIT_EPD | INIT_EEPROM); } void showLongTermSleep() { + if (displayCustomImage(CUSTOM_IMAGE_LONGTERMSLEEP)) return; selectLUT(EPD_LUT_NO_REPEATS); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); clearScreen(); @@ -616,4 +576,71 @@ void showNoMAC() { epdPrintEnd(); #endif drawWithSleep(); -} \ No newline at end of file +} + +bool displayCustomImage(uint8_t imagetype) { + powerUp(INIT_EEPROM); + uint8_t slot = findSlotDataTypeArg(imagetype << 3); + if (slot != 0xFF) { + // found a slot for gpio button 1 + + uint8_t lut = getEepromImageDataArgument(slot); + lut &= 0x03; + powerUp(INIT_EPD); + drawImageFromEeprom(slot, lut); + powerDown(INIT_EPD | INIT_EEPROM); + return true; + } else { + powerDown(INIT_EEPROM); + } + return false; +} + +void gpioButton1() { + if (displayCustomImage(CUSTOM_IMAGE_BUTTON1)) { + sleepForMsec(2000); + + // if something else was previously on the display, draw that + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM); + uint8_t lut = getEepromImageDataArgument(curImgSlot); + lut &= 0x03; + powerUp(INIT_EPD); + drawImageFromEeprom(curImgSlot, lut); + powerDown(INIT_EPD | INIT_EEPROM); + } + } +} + +void gpioButton2() { + if (displayCustomImage(CUSTOM_IMAGE_BUTTON1)) { + sleepForMsec(2000); + + // if something else was previously on the display, draw that + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM); + uint8_t lut = getEepromImageDataArgument(curImgSlot); + lut &= 0x03; + powerUp(INIT_EPD); + drawImageFromEeprom(curImgSlot, lut); + powerDown(INIT_EPD | INIT_EEPROM); + } + } +} + +#ifdef ENABLE_GPIO_WAKE +void gpioButtonOther() { + if (displayCustomImage(CUSTOM_IMAGE_GPIO)) { + sleepForMsec(2000); + // if something else was previously on the display, draw that + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM); + uint8_t lut = getEepromImageDataArgument(curImgSlot); + lut &= 0x03; + powerUp(INIT_EPD); + drawImageFromEeprom(curImgSlot, lut); + powerDown(INIT_EPD | INIT_EEPROM); + } + } +} +#endif diff --git a/zbs243_Tag_FW/userinterface.h b/zbs243_Tag_FW/userinterface.h index e3bc33b6..f923b0b5 100755 --- a/zbs243_Tag_FW/userinterface.h +++ b/zbs243_Tag_FW/userinterface.h @@ -4,17 +4,22 @@ void addOverlay(); +bool displayCustomImage(uint8_t imagetype); + void afterFlashScreenSaver(); void showSplashScreen(); void showApplyUpdate(); -void showScanningWindow(); -void addScanResult(uint8_t channel, uint8_t lqi); void showAPFound(); void showNoAP(); void showLongTermSleep(); void showNoEEPROM(); void showNoMAC(); + +void gpioButton1(); +void gpioButton2(); +void gpioButtonOther(); + extern const uint16_t __code fwVersion; extern const char __code fwVersionSuffix[]; extern bool __xdata lowBatteryShown; diff --git a/zbs243_shared/eeprom.c b/zbs243_shared/eeprom.c old mode 100644 new mode 100755 diff --git a/zbs243_shared/eeprom.h b/zbs243_shared/eeprom.h old mode 100644 new mode 100755 index 59f36984..476f5b5e --- a/zbs243_shared/eeprom.h +++ b/zbs243_shared/eeprom.h @@ -4,10 +4,10 @@ #include #include -#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment -#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment +#define EEPROM_WRITE_PAGE_SZ 256 // max write size & alignment +#define EEPROM_ERZ_SECTOR_SZ 4096 // erase size and alignment -//device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that +// device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that __bit eepromInit(void); void eepromOtpModeEnter(void); @@ -27,25 +27,40 @@ void eepromDeepPowerDown(void); #pragma callee_saves eepromGetSize uint32_t eepromGetSize(void); -//this is for firmware update use -void eepromReadStart(uint32_t addr) __reentrant; +// this is for firmware update use +void eepromReadStart(uint32_t addr) __reentrant; + +// structures +#define EEPROM_IMG_INPROGRESS (0x7fffffffUL) +//#define EEPROM_IMG_VALID (0x494d4721UL) +#define EEPROM_IMG_VALID (0x474d4721UL) -//structures -#define EEPROM_IMG_INPROGRESS (0x7fffffffUL) -#define EEPROM_IMG_VALID (0x494d4721UL) #include "board.h" -struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them - uint64_t version; - uint32_t validMarker; - uint32_t size; - uint8_t dataType; - uint32_t id; - - //image data here - //we pre-erase so progress can be calculated by finding the first non-0xff byte +struct EepromImageHeader { // each image space is 0x17000 bytes, we have space for ten of them + uint64_t version; + uint32_t validMarker; + uint32_t size; + uint8_t dataType; + uint32_t id; + uint8_t argument; + // image data here + // we pre-erase so progress can be calculated by finding the first non-0xff byte }; +#define CUSTOM_IMAGE_NOCUSTOM 0x00 // regular image type +#define CUSTOM_IMAGE_SPLASHSCREEN 0x01 // will show at first boot/powerup +#define CUSTOM_IMAGE_LOST_CONNECTION 0x02 // this image will be shown (if it exists on the tag) if the tag looses its connection +#define CUSTOM_IMAGE_APFOUND 0x03 // this image will be shown during bootup if an AP was found +#define CUSTOM_IMAGE_NOAPFOUND 0x04 // shown if during bootup no AP was found +// UNUSED: 0x05-0x0F +#define CUSTOM_IMAGE_SLIDESHOW 0x0F // image is part of a slideshow +#define CUSTOM_IMAGE_BUTTON1 0x10 +#define CUSTOM_IMAGE_BUTTON2 0x11 +// UNUSED: 0x12 to 0x1C +#define CUSTOM_IMAGE_GPIO 0x1D +#define CUSTOM_IMAGE_NFC_WAKE 0x1E + #endif