diff --git a/binaries/AP_force_flash.bin b/binaries/AP_force_flash.bin new file mode 100755 index 00000000..34d1d0a9 Binary files /dev/null and b/binaries/AP_force_flash.bin differ diff --git a/binaries/Tag_FW_1.54.bin b/binaries/Tag_FW_1.54.bin index 69de9c17..2696f754 100644 Binary files a/binaries/Tag_FW_1.54.bin and b/binaries/Tag_FW_1.54.bin differ diff --git a/binaries/Tag_FW_2.9-uc8151.bin b/binaries/Tag_FW_2.9-uc8151.bin index 59269da9..a65c106c 100644 Binary files a/binaries/Tag_FW_2.9-uc8151.bin and b/binaries/Tag_FW_2.9-uc8151.bin differ diff --git a/binaries/Tag_FW_2.9.bin b/binaries/Tag_FW_2.9.bin index eba10bf4..5e3396c3 100644 Binary files a/binaries/Tag_FW_2.9.bin and b/binaries/Tag_FW_2.9.bin differ diff --git a/binaries/Tag_FW_4.2.bin b/binaries/Tag_FW_4.2.bin index d5198482..cfe88d81 100644 Binary files a/binaries/Tag_FW_4.2.bin and b/binaries/Tag_FW_4.2.bin differ diff --git a/binaries/Tag_FW_Pack.bin b/binaries/Tag_FW_Pack.bin index 2ecc0496..8a03bff4 100644 Binary files a/binaries/Tag_FW_Pack.bin and b/binaries/Tag_FW_Pack.bin differ diff --git a/tag_types.h b/tag_types.h index ec7fc74b..2f6981f5 100755 --- a/tag_types.h +++ b/tag_types.h @@ -20,7 +20,14 @@ #define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2" #define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2" #define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD -#define DATATYPE_UK_SEGMENTED 0x51 // Segmented data for the UK Segmented display type +#define DATATYPE_UK_SEGMENTED 0x51 // Segmented data for the UK Segmented display type (contained in availableData Reply) +#define DATATYPE_EU_SEGMENTED 0x52 // Segmented data for the EU/DE Segmented display type (contained in availableData Reply) #define DATATYPE_NFC_RAW_CONTENT 0xA0 // raw memory content for the NT3H1101 #define DATATYPE_NFC_URL_DIRECT 0xA1 // URL format for NT3H1101 +#define DATATYPE_TAG_CONFIG_DATA 0xA8 // Config data for tag +#define DATATYPE_COMMAND_DATA 0xAF // Command for the tag to execute (contained in availableData Reply) #define DATATYPE_CUSTOM_LUT_OTA 0xB0 // Custom OTA updated LUT + +#define CMD_DO_REBOOT 0 +#define CMD_DO_SCAN 1 +#define CMD_DO_RESET_SETTINGS 2 \ No newline at end of file diff --git a/zbs243_Tag_FW/Makefile b/zbs243_Tag_FW/Makefile index 5fe685aa..39fa1d6c 100644 --- a/zbs243_Tag_FW/Makefile +++ b/zbs243_Tag_FW/Makefile @@ -5,7 +5,7 @@ BUILD ?= zbs29_ssd1619 SOURCES += main.c eeprom.c drawing.c SOURCES += comms.c SOURCES += syncedproto.c userinterface.c -SOURCES += powermgt.c barcode.c i2cdevices.c +SOURCES += powermgt.c barcode.c i2cdevices.c settings.c all: #make sure it is the first target diff --git a/zbs243_Tag_FW/i2cdevices.c b/zbs243_Tag_FW/i2cdevices.c index 741fc776..5cc02abc 100755 --- a/zbs243_Tag_FW/i2cdevices.c +++ b/zbs243_Tag_FW/i2cdevices.c @@ -34,7 +34,7 @@ bool supportsNFCWake() { } if (pcount < 10000) { // P1_3 (Field Detect) dropped to 'low' pretty fast, this means the load on this pin is high - pr("This tag currently does not support NFC wake, load on the FD pin (P1.3) is pretty high.\nOn some boards, a pull-up resistor backpowers the NFC IC. Consider removing it!\n"); + pr("NFC: This tag currently does not support NFC wake, load on the FD pin (P1.3) is pretty high.\nOn some boards, a pull-up resistor backpowers the NFC IC. Consider removing it!\n"); return false; } else { // No reason to believe this pin is currently loaded down severely @@ -121,7 +121,7 @@ bool i2cCheckDevice(uint8_t address) { iictest.deviceAddr = address << 1; uint8_t res = i2cTransact(&iictest, 1); if (res == 0) { - pr("Found i2c device at 0x%02X\n", address); + pr("I2C: Device found at 0x%02X\n", address); return true; } return false; diff --git a/zbs243_Tag_FW/main.c b/zbs243_Tag_FW/main.c index d790a0a7..388b9014 100755 --- a/zbs243_Tag_FW/main.c +++ b/zbs243_Tag_FW/main.c @@ -23,6 +23,12 @@ // #define DEBUG_MODE +static const uint64_t __code __at(0x008b) mVersionRom = 0x1000011300000000ull; + +#define TAG_MODE_CHANSEARCH 0 +#define TAG_MODE_ASSOCIATED 1 +uint8_t currentTagMode = TAG_MODE_CHANSEARCH; + void displayLoop() { powerUp(INIT_BASE | INIT_UART); @@ -118,6 +124,7 @@ uint8_t showChannelSelect() { // returns 0 if no accesspoints were found return highestSlot; } uint8_t channelSelect() { // returns 0 if no accesspoints were found + powerUp(INIT_RADIO); uint8_t __xdata result[16]; memset(result, 0, sizeof(result)); @@ -128,7 +135,7 @@ uint8_t channelSelect() { // returns 0 if no accesspoints were found } } } - + powerDown(INIT_RADIO); uint8_t __xdata highestLqi = 0; uint8_t __xdata highestSlot = 0; for (uint8_t c = 0; c < sizeof(result); c++) { @@ -142,79 +149,54 @@ uint8_t channelSelect() { // returns 0 if no accesspoints were found return highestSlot; } -void main() { - // displayLoop(); // remove me - setupPortsInitial(); - powerUp(INIT_BASE | INIT_UART); - +void validateMacAddress() { + // check if the mac contains at least some non-0xFF values + for (uint8_t __xdata c = 0; c < 8; c++) { + if (mSelfMac[c] != 0xFF) goto macIsValid; + } + // invalid mac address. Display warning screen and sleep forever + pr("Mac can't be all FF's.\n"); + powerUp(INIT_EPD); + showNoMAC(); + powerDown(INIT_EPD | INIT_UART | INIT_EEPROM); + doSleep(-1); + wdtDeviceReset(); +macIsValid: + return; +} +uint8_t getFirstWakeUpReason() { if (RESET & 0x01) { - wakeUpReason = WAKEUP_REASON_WDT_RESET; pr("WDT reset!\n"); - } else { - wakeUpReason = WAKEUP_REASON_FIRSTBOOT; + return WAKEUP_REASON_WDT_RESET; } - - wdt10s(); - - boardGetOwnMac(mSelfMac); - - { - bool __xdata macSet = false; - for (uint8_t __xdata c = 0; c < 8; c++) { - if (mSelfMac[c] != 0xFF) { - macSet = true; - break; - } - } - - if (!macSet) { - pr("Mac can't be all FF's.\n"); - powerUp(INIT_EPD); - showNoMAC(); - powerDown(INIT_EPD | INIT_UART | INIT_EEPROM); - doSleep(-1); - wdtDeviceReset(); - } - } - - pr("BOOTED> %d.%d.%d%s\n", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); - + return WAKEUP_REASON_FIRSTBOOT; +} +void checkI2C() { powerUp(INIT_I2C); - - //i2cBusScan(); - +// i2cBusScan(); if (i2cCheckDevice(0x55)) { powerDown(INIT_I2C); + // found something! capabilities |= CAPABILITY_HAS_NFC; if (supportsNFCWake()) { - pr("This board supports NFC wake!\n"); + pr("NFC: NFC Wake Supported\n"); capabilities |= CAPABILITY_NFC_WAKE; } } else { + pr("I2C: No devices found"); + // didn't find a NFC chip on the expected ID powerDown(INIT_I2C); } +} - pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]); - pr("%02X%02X", mSelfMac[2], mSelfMac[3]); - pr("%02X%02X", mSelfMac[4], mSelfMac[5]); - pr("%02X%02X\n", mSelfMac[6], mSelfMac[7]); - - powerUp(INIT_RADIO); // load down the battery using the radio to get a good voltage reading - powerUp(INIT_EPD_VOLTREADING | INIT_TEMPREADING); - powerDown(INIT_RADIO); - - powerUp(INIT_EEPROM); - // get the highest slot number, number of slots - initializeProto(); - powerDown(INIT_EEPROM); - +void detectButtonOrJig() { switch (checkButtonOrJig()) { case DETECT_P1_0_BUTTON: capabilities |= CAPABILITY_HAS_WAKE_BUTTON; break; case DETECT_P1_0_JIG: wdt120s(); - // show the screensaver (minimal text to prevent image burn-in) + // show the screensaver, full LUT (minimal text to prevent image burn-in) powerUp(INIT_EPD); afterFlashScreenSaver(); while (1) @@ -225,161 +207,258 @@ void main() { default: break; } +} - // show the splashscreen - powerUp(INIT_EPD); - showSplashScreen(); +void TagAssociated() { + // associated + 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) { + // check if we should do a voltage measurement (those are pretty expensive) + if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) { + doVoltageReading(); + voltageCheckCounter = 0; + } else { + powerUp(INIT_TEMPREADING); + } + voltageCheckCounter++; + + // check if the battery level is below minimum, and force a redraw of the screen + + if ((lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) || (noAPShown && tagSettings.enableNoRFSymbol)) { + // Check if we were already displaying an image + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM | INIT_EPD); + wdt60s(); + drawImageFromEeprom(curImgSlot); + powerDown(INIT_EEPROM | INIT_EPD); + } else { + powerUp(INIT_EPD); + showAPFound(); + powerDown(INIT_EPD); + } + } + + powerUp(INIT_RADIO); + avail = getAvailDataInfo(); + powerDown(INIT_RADIO); + + if (avail != NULL) { + // we got some data! + longDataReqCounter = 0; + // since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status + wakeUpReason = WAKEUP_REASON_TIMED; + } + if (tagSettings.enableTagRoaming) { + uint8_t roamChannel = channelSelect(); + if (roamChannel) currentChannel = roamChannel; + } + } else { + powerUp(INIT_RADIO); + avail = getShortAvailDataInfo(); + powerDown(INIT_RADIO); + } + + addAverageValue(); + + if (avail == NULL) { + // no data :( this means no reply from AP + nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period + } else { + nextCheckInFromAP = avail->nextCheckIn; + // got some data from the AP! + if (avail->dataType != DATATYPE_NOUPDATE) { + // data transfer + if (processAvailDataInfo(avail)) { + // succesful transfer, next wake time is determined by the NextCheckin; + } else { + // failed transfer, let the algorithm determine next sleep interval (not the AP) + nextCheckInFromAP = 0; + } + } else { + // no data transfer, just sleep. + } + } + + uint16_t nextCheckin = getNextSleep(); + longDataReqCounter += nextCheckin; + + if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS) { + // We've averaged up to the maximum interval, this means the tag hasn't been in contact with an AP for some time. + if (tagSettings.enableScanForAPAfterTimeout) { + currentTagMode = TAG_MODE_CHANSEARCH; + return; + } + } + + // if the AP told us to sleep for a specific period, do so. + if (nextCheckInFromAP) { + doSleep(nextCheckInFromAP * 60000UL); + } else { + doSleep(getNextSleep() * 1000UL); + } +} + +void TagChanSearch() { + // not associated + if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) { + doVoltageReading(); + } + + // try to find a working channel + currentChannel = channelSelect(); + + // Check if we should redraw the screen with icons, info screen or screensaver + if ((!currentChannel && !noAPShown && tagSettings.enableNoRFSymbol) || + (lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) || + (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { + powerUp(INIT_EPD); + wdt60s(); + if (curImgSlot != 0xFF) { + powerUp(INIT_EEPROM); + drawImageFromEeprom(curImgSlot); + powerDown(INIT_EEPROM); + } else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { + showLongTermSleep(); + } else { + showNoAP(); + } + powerDown(INIT_EPD); + } + + // did we find a working channel? + if (currentChannel) { + // now associated! set up and bail out of this loop. + scanAttempts = 0; + wakeUpReason = WAKEUP_REASON_NETWORK_SCAN; + initPowerSaving(INTERVAL_BASE); + doSleep(getNextSleep() * 1000UL); + currentTagMode = TAG_MODE_ASSOCIATED; + return; + } else { + // still not associated + doSleep(getNextScanSleep(true) * 1000UL); + } +} + +void executeCommand(uint8_t cmd) { + switch (cmd) { + case CMD_DO_REBOOT: + wdtDeviceReset(); + break; + case CMD_DO_RESET_SETTINGS: + loadDefaultSettings(); + writeSettings(); + break; + case CMD_DO_SCAN: + currentChannel = channelSelect(); + break; + } +} + +void main() { + // displayLoop(); // remove me + setupPortsInitial(); + powerUp(INIT_BASE | INIT_UART); + pr("BOOTED> %d.%d.%d%s\n", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); + + // Find the reason why we're booting; is this a WDT? + wakeUpReason = getFirstWakeUpReason(); + + // get our own mac address. this is stored in Infopage at offset 0x10-onwards + boardGetOwnMac(mSelfMac); + pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]); + pr("%02X%02X", mSelfMac[2], mSelfMac[3]); + pr("%02X%02X", mSelfMac[4], mSelfMac[5]); + pr("%02X%02X\n", mSelfMac[6], mSelfMac[7]); + + // load settings from infopage + loadSettings(); + + // get the highest slot number, number of slots + initializeProto(); + + if (tagSettings.enableFastBoot) { + // Fastboot + pr("Doing fast boot\n"); + capabilities = tagSettings.fastBootCapabilities; + if (tagSettings.fixedChannel) { + currentChannel = tagSettings.fixedChannel; + } else { + currentChannel = channelSelect(); + } + } else { + // Normal boot/startup + + // validate the mac address; this will display a warning on the screen if the mac address is invalid + validateMacAddress(); + +#if (NFC_TYPE == 1) + // initialize I2C + checkI2C(); +#endif + + // Get a voltage reading on the tag, loading down the battery with the radio + doVoltageReading(); + + // detect button or jig + detectButtonOrJig(); + + // show the splashscreen + pr("EPD: First powerup\n"); + powerUp(INIT_EPD); + showSplashScreen(); // we've now displayed something on the screen; for the SSD1619, we are now aware of the lut-size #ifdef EPD_SSD1619 - capabilities |= CAPABILITY_SUPPORTS_CUSTOM_LUTS; - if (dispLutSize != 7) { - capabilities |= CAPABILITY_ALT_LUT_SIZE; - } + capabilities |= CAPABILITY_SUPPORTS_CUSTOM_LUTS; + if (dispLutSize != 7) { + capabilities |= CAPABILITY_ALT_LUT_SIZE; + } #endif + tagSettings.fastBootCapabilities = capabilities; - powerUp(INIT_EPD); - wdt30s(); - currentChannel = showChannelSelect(); + // now that we've collected all possible capabilities, save it to settings + writeSettings(); + // scan for channels + powerUp(INIT_EPD); + wdt30s(); + if (tagSettings.fixedChannel) { + currentChannel = tagSettings.fixedChannel; + } else { + currentChannel = showChannelSelect(); + } + } + + // 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); } + // this is the loop we'll stay in forever, basically. while (1) { powerUp(INIT_UART); wdt10s(); - if (currentChannel) { - // associated - - 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) { - // check if we should do a voltage measurement (those are pretty expensive) - if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) { - powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading - powerUp(INIT_TEMPREADING | INIT_EPD_VOLTREADING); - powerDown(INIT_RADIO); - voltageCheckCounter = 0; - } else { - powerUp(INIT_TEMPREADING); - } - voltageCheckCounter++; - - // check if the battery level is below minimum, and force a redraw of the screen - if ((lowBattery && !lowBatteryShown) || (noAPShown)) { - // Check if we were already displaying an image - if (curImgSlot != 0xFF) { - powerUp(INIT_EEPROM | INIT_EPD); - wdt60s(); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EEPROM | INIT_EPD); - } else { - powerUp(INIT_EPD); - showAPFound(); - powerDown(INIT_EPD); - } - } - powerUp(INIT_RADIO); - avail = getAvailDataInfo(); - powerDown(INIT_RADIO); - - if (avail != NULL) { - // we got some data! - longDataReqCounter = 0; - // since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status - wakeUpReason = WAKEUP_REASON_TIMED; - } - } else { - powerUp(INIT_RADIO); - avail = getShortAvailDataInfo(); - powerDown(INIT_RADIO); - } - - addAverageValue(); - - if (avail == NULL) { - // no data :( - nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period - } else { - nextCheckInFromAP = avail->nextCheckIn; - // got some data from the AP! - if (avail->dataType != DATATYPE_NOUPDATE) { - // data transfer - if (processAvailDataInfo(avail)) { - // succesful transfer, next wake time is determined by the NextCheckin; - } else { - // failed transfer, let the algorithm determine next sleep interval (not the AP) - nextCheckInFromAP = 0; - } - } else { - // no data transfer, just sleep. - } - } - - uint16_t nextCheckin = getNextSleep(); - longDataReqCounter += nextCheckin; - if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS) { - // disconnected, obviously... - currentChannel = 0; - } - - // if the AP told us to sleep for a specific period, do so. - if (nextCheckInFromAP) { - doSleep(nextCheckInFromAP * 60000UL); - } else { - doSleep(getNextSleep() * 1000UL); - } - - } else { - // not associated - if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) { - powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading - powerUp(INIT_EPD_VOLTREADING); - powerDown(INIT_RADIO); - } - // try to find a working channel - powerUp(INIT_RADIO); - currentChannel = channelSelect(); - powerDown(INIT_RADIO); - - if ((!currentChannel && !noAPShown) || (lowBattery && !lowBatteryShown) || (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { - powerUp(INIT_EPD); - wdt60s(); - if (curImgSlot != 0xFF) { - powerUp(INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EEPROM); - } else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { - showLongTermSleep(); - } else { - showNoAP(); - } - powerDown(INIT_EPD); - } - - // did we find a working channel? - if (currentChannel) { - // now associated! - scanAttempts = 0; - wakeUpReason = WAKEUP_REASON_NETWORK_SCAN; - initPowerSaving(INTERVAL_BASE); - doSleep(getNextSleep() * 1000UL); - - } else { - // still not associated - doSleep(getNextScanSleep(true) * 1000UL); - } + switch (currentTagMode) { + case TAG_MODE_ASSOCIATED: + TagAssociated(); + break; + case TAG_MODE_CHANSEARCH: + TagChanSearch(); + break; } } -} +} \ No newline at end of file diff --git a/zbs243_Tag_FW/main.lk b/zbs243_Tag_FW/main.lk new file mode 100644 index 00000000..c3616a4d --- /dev/null +++ b/zbs243_Tag_FW/main.lk @@ -0,0 +1,45 @@ +-muwx +-i main.ihx +-M +-X 0x2000 +-C 0xfc00 +-b HOME = 0x0000 +-b XSEG = 0xe000 +-b PSEG = 0xe000 +-b ISEG = 0x0000 +-b BSEG = 0x0000 +-k /usr/local/bin/../share/sdcc/lib/large +-k /usr/local/share/sdcc/lib/large +-l mcs51 +-l libsdcc +-l libint +-l liblong +-l libfloat +main.rel +eeprom.rel +drawing.rel +comms.rel +syncedproto.rel +userinterface.rel +powermgt.rel +barcode.rel +i2cdevices.rel +settings.rel +soc/zbs243/soc.rel +soc/zbs243/wdt.rel +soc/zbs243/sleep.rel +soc/zbs243/spi.rel +soc/zbs243/uart.rel +soc/zbs243/timer.rel +soc/zbs243/radio.rel +soc/zbs243/flash.rel +soc/zbs243/temperature.rel +cpu/8051/random.rel +cpu/8051/printf.rel +soc/zbs243/i2c.rel +cpu/8051/asmUtil.rel +cpu/8051/cpu.rel +board/zbs29_uc8151/board.rel +board/zbs29_uc8151/screen.rel + +-e diff --git a/zbs243_Tag_FW/powermgt.c b/zbs243_Tag_FW/powermgt.c index 7e1094e2..d8d5022e 100755 --- a/zbs243_Tag_FW/powermgt.c +++ b/zbs243_Tag_FW/powermgt.c @@ -34,7 +34,7 @@ uint8_t __xdata wakeUpReason = 0; uint8_t __xdata scanAttempts = 0; int8_t __xdata temperature = 0; -uint16_t __xdata batteryVoltage = 0; +uint16_t __xdata batteryVoltage = 2600; bool __xdata lowBattery = false; uint16_t __xdata longDataReqCounter = 0; uint16_t __xdata voltageCheckCounter = 0; @@ -153,10 +153,11 @@ static void configI2C(const bool setup) { if (setup) { P1DIR &= ~(1 << 6); P1_6 = 1; + timerDelay(13330); P1FUNC |= (1 << 4) | (1 << 5); P1PULL |= (1 << 4) | (1 << 5); i2cInit(); - i2cCheckDevice(0x50); // first transaction after init fails, this makes sure everything is ready for the first transaction + // i2cCheckDevice(0x50); // first transaction after init fails, this makes sure everything is ready for the first transaction } else { P1DIR |= (1 << 6); P1_6 = 0; @@ -174,6 +175,7 @@ void powerUp(const uint8_t parts) { timerInit(); irqsOn(); wdtOn(); + wdt10s(); } if (parts & INIT_EPD) { @@ -186,7 +188,7 @@ void powerUp(const uint8_t parts) { epdConfigGPIO(true); configSPI(true); batteryVoltage = epdGetBattery(); - if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) { + if (batteryVoltage < tagSettings.batLowVoltage) { lowBattery = true; } else { lowBattery = false; @@ -302,7 +304,12 @@ void doSleep(const uint32_t __xdata t) { P1CHSTA &= ~(1 << 3); } - // sleepy + if (tagSettings.enableRFWake) { + // enabled RF wake, adds a little extra energy draw! + RADIO_RadioPowerCtl &= 0xFB; + } + + // sleepy time sleepForMsec(t); P1INTEN = 0; if ((P1CHSTA & (1 << 0)) && (capabilities & CAPABILITY_HAS_WAKE_BUTTON)) { @@ -316,6 +323,12 @@ void doSleep(const uint32_t __xdata t) { } } +void doVoltageReading() { + powerUp(INIT_RADIO); // load down the battery using the radio to get a good voltage reading + powerUp(INIT_EPD_VOLTREADING | INIT_TEMPREADING); + powerDown(INIT_RADIO); +} + uint32_t getNextScanSleep(const bool increment) { if (increment) { if (scanAttempts < 255) @@ -346,5 +359,8 @@ uint16_t getNextSleep() { avg += dataReqAttemptArr[c]; } avg /= POWER_SAVING_SMOOTHING; + + // check if we should sleep longer due to an override in the config + if (avg < tagSettings.minimumCheckInTime) return tagSettings.minimumCheckInTime; return avg; } \ No newline at end of file diff --git a/zbs243_Tag_FW/powermgt.h b/zbs243_Tag_FW/powermgt.h index d45374c9..04ab8a47 100755 --- a/zbs243_Tag_FW/powermgt.h +++ b/zbs243_Tag_FW/powermgt.h @@ -55,6 +55,8 @@ extern void powerDown(const uint8_t parts); extern void initAfterWake(); extern void doSleep(const uint32_t __xdata t); +void doVoltageReading(); + extern void addAverageValue(); extern uint16_t getNextSleep(); diff --git a/zbs243_Tag_FW/settings.c b/zbs243_Tag_FW/settings.c new file mode 100755 index 00000000..4e0dd0aa --- /dev/null +++ b/zbs243_Tag_FW/settings.c @@ -0,0 +1,95 @@ +#include "settings.h" + +#include +#include +#include +#include +#include +#include + +#include "asmUtil.h" +#include "powermgt.h" +#include "printf.h" +#include "syncedproto.h" + +struct tagsettings __xdata tagSettings = {0}; +extern uint8_t __xdata blockXferBuffer[]; +uint8_t* __xdata infopageTempBuffer = 1024 + blockXferBuffer; + +#define INFOPAGE_SETTINGS_OFFSET 0x50 + +void loadDefaultSettings() { + tagSettings.settingsVer = SETTINGS_STRUCT_VERSION; + tagSettings.enableFastBoot = DEFAULT_SETTING_FASTBOOT; + tagSettings.enableRFWake = DEFAULT_SETTING_RFWAKE; + tagSettings.enableTagRoaming = DEFAULT_SETTING_TAGROAMING; + tagSettings.enableScanForAPAfterTimeout = DEFAULT_SETTING_SCANFORAP; + tagSettings.enableLowBatSymbol = DEFAULT_SETTING_LOWBATSYMBOL; + tagSettings.enableNoRFSymbol = DEFAULT_SETTING_NORFSYMBOL; + tagSettings.customMode = 0; + tagSettings.fastBootCapabilities = 0; + tagSettings.minimumCheckInTime = INTERVAL_BASE; + tagSettings.fixedChannel = 0; + tagSettings.batLowVoltage = BATTERY_VOLTAGE_MINIMUM; +} + +void loadSettingsFromBuffer(uint8_t* p) { + pr("SETTINGS: received settings from AP\n"); + switch (*p) { + case SETTINGS_STRUCT_VERSION: // the current tag struct + pr("SETTINGS: received matching version\n"); + memcpy((void*)tagSettings, (void*)p, sizeof(struct tagsettings)); + break; + default: + pr("SETTINGS: received something we couldn't really process, version %d\n"); + break; + } + tagSettings.fastBootCapabilities = capabilities; + writeSettings(); +} + +static bool compareSettings() { + // check if the settings match the settings in the infopage + flashRead(FLASH_INFOPAGE_ADDR + INFOPAGE_SETTINGS_OFFSET, (void*)infopageTempBuffer, sizeof(struct tagsettings)); + if (memcmp((void*)infopageTempBuffer, (void*)tagSettings, sizeof(struct tagsettings)) == 0) { + // same + return true; + } + // different + return false; +} + +static void upgradeSettings() { + // add an upgrade strategy whenever you update the struct version +} + +void loadSettings() { + flashRead((FLASH_INFOPAGE_ADDR + INFOPAGE_SETTINGS_OFFSET), (void*)infopageTempBuffer, sizeof(struct tagsettings)); + xMemCopy((void*)tagSettings, (void*)infopageTempBuffer, sizeof(struct tagsettings)); + if (tagSettings.settingsVer == 0xFF) { + // settings not set. load the defaults + loadDefaultSettings(); + pr("SETTINGS: Loaded default settings\n"); + } else { + if (tagSettings.settingsVer < SETTINGS_STRUCT_VERSION) { + // upgrade + upgradeSettings(); + pr("SETTINGS: Upgraded from previous version\n"); + } else { + // settings are valid + pr("SETTINGS: Loaded from infopage\n"); + } + } +} + +void writeSettings() { + if (compareSettings()) { + pr("SETTINGS: Settings matched current settings\n"); + return; + } + flashRead(FLASH_INFOPAGE_ADDR, (void*)infopageTempBuffer, 1024); + xMemCopy((void*)(infopageTempBuffer + INFOPAGE_SETTINGS_OFFSET), (void*)tagSettings, sizeof(tagSettings)); + flashErase(FLASH_INFOPAGE_ADDR + 1); + flashWrite(FLASH_INFOPAGE_ADDR, (void*)infopageTempBuffer, 1024, false); + pr("SETTINGS: Updated settings in infopage\n"); +} \ No newline at end of file diff --git a/zbs243_Tag_FW/settings.h b/zbs243_Tag_FW/settings.h index 38b69be8..f765bd4d 100755 --- a/zbs243_Tag_FW/settings.h +++ b/zbs243_Tag_FW/settings.h @@ -3,8 +3,39 @@ #include -#define FW_VERSION 017 // version number (max 2.5.5 :) ) -#define FW_VERSION_SUFFIX "-CLUT" // suffix, like -RC1 or whatever. +#define FW_VERSION 18 // version number (max 2.5.5 :) ) +#define FW_VERSION_SUFFIX "-RW" // 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 SETTINGS_STRUCT_VERSION 0x01 + +#define DEFAULT_SETTING_FASTBOOT 0 +#define DEFAULT_SETTING_RFWAKE 0 +#define DEFAULT_SETTING_TAGROAMING 0 +#define DEFAULT_SETTING_SCANFORAP 1 +#define DEFAULT_SETTING_LOWBATSYMBOL 1 +#define DEFAULT_SETTING_NORFSYMBOL 1 + +struct tagsettings { + uint8_t settingsVer; // the version of the struct as written to the infopage + uint8_t enableFastBoot; // default 0; if set, it will skip splashscreen + uint8_t enableRFWake; // default 0; if set, it will enable RF wake. This will add about ~0.9µA idle power consumption + uint8_t enableTagRoaming; // default 0; if set, the tag will scan for an accesspoint every few check-ins. This will increase power consumption quite a bit + uint8_t enableScanForAPAfterTimeout; // default 1; if a the tag failed to check in, after a few attempts it will try to find a an AP on other channels + uint8_t enableLowBatSymbol; // default 1; tag will show 'low battery' icon on screen if the battery is depleted + uint8_t enableNoRFSymbol; // default 1; tag will show 'no signal' icon on screen if it failed to check in for a longer period of time + uint8_t fastBootCapabilities; // holds the byte with 'capabilities' as detected during a normal tag boot; allows the tag to skip detecting buttons and NFC chip + uint8_t customMode; // default 0; if anything else, tag will bootup in a different 'mode' + uint16_t batLowVoltage; // Low battery threshold voltage (2450 for 2.45v). defaults to BATTERY_VOLTAGE_MINIMUM from powermgt.h + uint16_t minimumCheckInTime; // defaults to BASE_INTERVAL from powermgt.h + uint8_t fixedChannel; // default 0; if set to a valid channel number, the tag will stick to that channel +} __packed; + +extern struct tagsettings tagSettings; + +void loadDefaultSettings(); +void writeSettings(); +void loadSettings(); +void loadSettingsFromBuffer(uint8_t* p); #endif \ No newline at end of file diff --git a/zbs243_Tag_FW/syncedproto.c b/zbs243_Tag_FW/syncedproto.c index 14d4adf6..b6b7f146 100755 --- a/zbs243_Tag_FW/syncedproto.c +++ b/zbs243_Tag_FW/syncedproto.c @@ -50,6 +50,8 @@ uint8_t __xdata currentChannel = 0; static uint8_t __xdata inBuffer[128] = {0}; static uint8_t __xdata outBuffer[128] = {0}; +extern void executeCommand(uint8_t cmd); // this is defined in main.c + // tools static uint8_t __xdata getPacketType(const void *__xdata buffer) { const struct MacFcs *__xdata fcs = buffer; @@ -471,6 +473,7 @@ static uint32_t getHighSlotId() { return temp; } +// data transfer stuff static uint8_t __xdata partsThisBlock = 0; static uint8_t __xdata blockAttempts = 0; // these CAN be local to the function, but for some reason, they won't survive sleep? // they get overwritten with 7F 32 44 20 00 00 00 00 11, I don't know why. @@ -570,6 +573,7 @@ static bool getDataBlock(const uint16_t blockSize) { pr("failed getting block\n"); return false; } + 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 @@ -847,6 +851,37 @@ 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)) { + pr("this was the same as the last transfer, disregard\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + } + curBlock.blockId = 0; + xMemCopy8(&(curBlock.ver), &(avail->dataVer)); + curBlock.type = avail->dataType; + xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); + wdt10s(); + if (getDataBlock(avail->dataSize)) { + curDataInfo.dataSize = 0; // mark as transfer not pending + loadSettingsFromBuffer(sizeof(struct blockData) + blockXferBuffer); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + return true; + } + return false; + break; + case DATATYPE_COMMAND_DATA: + pr("CMD received\n"); + powerUp(INIT_RADIO); + sendXferComplete(); + powerDown(INIT_RADIO); + executeCommand(avail->dataTypeArgument); + return true; + break; case DATATYPE_CUSTOM_LUT_OTA: // Handle data for the NFC IC (if we have it) @@ -874,7 +909,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { wdt10s(); if (getDataBlock(avail->dataSize)) { curDataInfo.dataSize = 0; // mark as transfer not pending - memcpy(customLUT, sizeof(struct blockData) + blockXferBuffer, dispLutSize * 10); + memcpy(customLUT, sizeof(struct blockData) + blockXferBuffer, 6 + (dispLutSize * 10)); powerUp(INIT_RADIO); sendXferComplete(); powerDown(INIT_RADIO); @@ -888,6 +923,8 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) { } void initializeProto() { + powerUp(INIT_EEPROM); getNumSlots(); curHighSlotId = getHighSlotId(); + powerDown(INIT_EEPROM); } \ No newline at end of file diff --git a/zbs243_Tag_FW/syncedproto.h b/zbs243_Tag_FW/syncedproto.h old mode 100644 new mode 100755 index fe39ec87..e3be548d --- a/zbs243_Tag_FW/syncedproto.h +++ b/zbs243_Tag_FW/syncedproto.h @@ -13,7 +13,7 @@ extern uint8_t __xdata curImgSlot; extern void setupRadio(void); extern void killRadio(void); - +void dump(const uint8_t *__xdata a, const uint16_t __xdata l); extern struct AvailDataInfo *__xdata getAvailDataInfo(); extern struct AvailDataInfo *__xdata getShortAvailDataInfo(); extern void drawImageFromEeprom(const uint8_t imgSlot); diff --git a/zbs243_Tag_FW/userinterface.c b/zbs243_Tag_FW/userinterface.c index a777ad8c..94affe74 100755 --- a/zbs243_Tag_FW/userinterface.c +++ b/zbs243_Tag_FW/userinterface.c @@ -51,7 +51,7 @@ void addCapabilities() { } void addOverlay() { - if (currentChannel == 0) { + 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); @@ -67,7 +67,7 @@ void addOverlay() { noAPShown = false; } - if (batteryVoltage != 2600) { + if ((batteryVoltage < tagSettings.batLowVoltage) && (tagSettings.enableLowBatSymbol)) { #if (SCREEN_WIDTH == 152) loadRawBitmap(battery, SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, EPD_COLOR_BLACK); #elif (SCREEN_WIDTH == 400) @@ -81,7 +81,6 @@ void addOverlay() { } } - void afterFlashScreenSaver() { selectLUT(EPD_LUT_DEFAULT); clearScreen(); @@ -106,7 +105,6 @@ void afterFlashScreenSaver() { drawWithSleep(); } - void showSplashScreen() { selectLUT(EPD_LUT_NO_REPEATS); clearScreen(); diff --git a/zbs243_shared/board/ssd1619.c b/zbs243_shared/board/ssd1619.c index 0dcd58b6..95c5ebc5 100755 --- a/zbs243_shared/board/ssd1619.c +++ b/zbs243_shared/board/ssd1619.c @@ -42,6 +42,11 @@ #define CMD_YSTART_POS 0x4F #define CMD_ANALOG_BLK_CTRL 0x74 #define CMD_DIGITAL_BLK_CTRL 0x7E +// added for OTA LUT-support +#define CMD_GATE_LEVEL 0x03 +#define CMD_SOURCE_LEVEL 0x04 +#define CMD_DUMMY_PERIOD 0x3A +#define CMD_GATE_LINE_WIDTH 0x3B #define SCREEN_CMD_CLOCK_ON 0x80 #define SCREEN_CMD_CLOCK_OFF 0x01 @@ -83,7 +88,7 @@ bool __xdata epdGPIOActive = false; #define LUT_BUFFER_SIZE 128 static uint8_t waveformbuffer[LUT_BUFFER_SIZE]; -uint8_t __xdata customLUT[LUT_BUFFER_SIZE] = {0}; +uint8_t __xdata customLUT[LUT_BUFFER_SIZE] = {0}; struct waveform10* __xdata waveform10 = (struct waveform10*)waveformbuffer; // holds the LUT/waveform struct waveform* __xdata waveform7 = (struct waveform*)waveformbuffer; // holds the LUT/waveform @@ -378,14 +383,6 @@ void selectLUT(uint8_t lut) { return; } - // Handling if we received an OTA LUT - if (lut == EPD_LUT_OTA) { - memcpy(waveformbuffer, customLUT, dispLutSize * 10); - writeLut(); - currentLut = lut; - return; - } - if (currentLut != EPD_LUT_DEFAULT) { // load the 'default' LUT for the current temperature in the EPD lut register shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1? @@ -447,6 +444,22 @@ void selectLUT(uint8_t lut) { break; } + // Handling if we received an OTA LUT + if (lut == EPD_LUT_OTA) { + memcpy(waveformbuffer, customLUT, dispLutSize * 10); + writeLut(); + shortCommand1(CMD_GATE_LEVEL, customLUT[70]); + commandBegin(CMD_SOURCE_LEVEL); + epdSend(customLUT[71]); + epdSend(customLUT[72]); + epdSend(customLUT[73]); + commandEnd(); + shortCommand1(CMD_DUMMY_PERIOD, customLUT[74]); + shortCommand1(CMD_GATE_LINE_WIDTH, customLUT[75]); + currentLut = lut; + return; + } + if (dispLutSize == 10) { lutGroupDisable(LUTGROUP_UNUSED); lutGroupDisable(LUTGROUP_UNKNOWN); diff --git a/zbs243_shared/board/zbs154_ssd1619/board.h b/zbs243_shared/board/zbs154_ssd1619/board.h index 6e8c683e..46d255ab 100755 --- a/zbs243_shared/board/zbs154_ssd1619/board.h +++ b/zbs243_shared/board/zbs154_ssd1619/board.h @@ -22,6 +22,7 @@ #define HAS_EEPROM 1 #define HAS_SCREEN 1 +#define NFC_TYPE 1 #define AP_EMULATE_TAG 1 //hw types diff --git a/zbs243_shared/board/zbs29_ssd1619/board.h b/zbs243_shared/board/zbs29_ssd1619/board.h index 6c78a256..9f1c06d7 100755 --- a/zbs243_shared/board/zbs29_ssd1619/board.h +++ b/zbs243_shared/board/zbs29_ssd1619/board.h @@ -21,6 +21,7 @@ #define HAS_EEPROM 1 #define HAS_SCREEN 1 +#define NFC_TYPE 1 #define AP_EMULATE_TAG 1 //hw types diff --git a/zbs243_shared/board/zbs29_uc8151/board.h b/zbs243_shared/board/zbs29_uc8151/board.h index 82a58130..7ec406f0 100755 --- a/zbs243_shared/board/zbs29_uc8151/board.h +++ b/zbs243_shared/board/zbs29_uc8151/board.h @@ -21,6 +21,7 @@ #define HAS_EEPROM 1 #define HAS_SCREEN 1 +#define NFC_TYPE 1 #define AP_EMULATE_TAG 1 //hw types diff --git a/zbs243_shared/board/zbs42_ssd1619/board.h b/zbs243_shared/board/zbs42_ssd1619/board.h index 7b8ece16..e1d5519b 100755 --- a/zbs243_shared/board/zbs42_ssd1619/board.h +++ b/zbs243_shared/board/zbs42_ssd1619/board.h @@ -22,6 +22,7 @@ #define HAS_EEPROM 1 #define HAS_SCREEN 1 +#define NFC_TYPE 2 #define AP_EMULATE_TAG 1 //hw types