From 300f0fe018fe4b607ea92d5901c94b25533d50a0 Mon Sep 17 00:00:00 2001 From: Jelmer Date: Sun, 5 Feb 2023 00:07:25 +0100 Subject: [PATCH 1/4] improved AP stability onder load, cleanup --- ap_fw/Makefile | 2 +- ap_fw/board/boardZBS29common.c | 98 --------- ap_fw/board/zbs29v033/screen.c | 379 --------------------------------- ap_fw/board/zbs29v033/screen.h | 16 -- ap_fw/comms.c | 2 - ap_fw/eeprom.c | 322 ---------------------------- ap_fw/eeprom.h | 54 ----- ap_fw/main.c | 47 ++-- ap_fw/sleep.h | 10 - ap_fw/soc/zbs243/make.mk | 4 +- ap_fw/soc/zbs243/radio.c | 2 +- 11 files changed, 29 insertions(+), 907 deletions(-) delete mode 100644 ap_fw/board/zbs29v033/screen.c delete mode 100644 ap_fw/eeprom.c delete mode 100644 ap_fw/eeprom.h delete mode 100644 ap_fw/sleep.h diff --git a/ap_fw/Makefile b/ap_fw/Makefile index 4a251fc4..00cc639c 100644 --- a/ap_fw/Makefile +++ b/ap_fw/Makefile @@ -2,7 +2,7 @@ BUILD ?= zbs29v033 #file containing main() must be first! -SOURCES += main.c eeprom.c +SOURCES += main.c SOURCES += comms.c diff --git a/ap_fw/board/boardZBS29common.c b/ap_fw/board/boardZBS29common.c index bb90de2d..b3a7ab9c 100644 --- a/ap_fw/board/boardZBS29common.c +++ b/ap_fw/board/boardZBS29common.c @@ -64,102 +64,4 @@ void boardInitStage2(void) __bit boardGetOwnMac(uint8_t __xdata *mac) { return flashRead(FLASH_INFOPAGE_ADDR + 0x10, mac, 8); -} - -#pragma callee_saves prvUpdateApplierGet -static uint32_t prvUpdateApplierGet(void) __naked -{ - __asm__( - " mov DPTR, #00098$ \n" - " mov A, #00099$ \n" - " clr C \n" - " subb A, DPL \n" - " mov B, A \n" - " ret \n" - - ///actual updater code - "00098$: \n" - - - //copied to last page of flash for updating, called with ints off and eeprom ready to read update - //flashes 63 flash pages, uses xram for buffer. uses combined erase+flash flash op - - " mov _CLKSPEED, #0x21 \n" - " mov _CFGPAGE, #0x04 \n" - " mov R0, #0 \n" - - "00001$: \n" - - //read a page of update - " mov DPTR, #0xe000 \n" - " mov R1, #0x04 \n" - " mov R2, #0x00 \n" - "000010$: \n" - " mov _SPITX, #0x00 \n" - " mov _SPICFG, #0xa0 \n" - "000011$: \n" - " mov A, _SPICFG \n" - " jb A.5, 000011$ \n" - " mov A, _SPIRX \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz R2, 000010$ \n" - " djnz R1, 000010$ \n" - - //flash it - " clr A \n" - " orl _SETTINGS, #0x38 \n" - " mov _FWRTHREE, #0x03 \n" - " mov _FPGNO, R0 \n" - " mov _FWRDSTL, A \n" - " mov _FWRDSTH, A \n" - " mov _FWRLENL, #0xff \n" - " mov _FWRLENH, #0x03 \n" - " mov _FWRSRCL, A \n" - " mov _FWRSRCH, #0xe0 \n" - " orl _TRIGGER, #0x08 \n" - "00050$: \n" - " mov A, _TCON2 \n" - " jnb A.3, 00050$ \n" - " anl _TCON2, #~0x48 \n" - " anl _SETTINGS, #~0x10 \n" - - //go do next page - " inc R0 \n" - " cjne R0, #63, 00001$ \n" - - //done? reset - " mov _WDTCONF, #0x80 \n" - " mov _WDTENA, #0x01 \n" - " mov A, #0xff \n" - " mov _WDTRSTVALH, A \n" - " mov _WDTRSTVALM, A \n" - " mov _WDTRSTVALL, A \n" - "00090$: \n" - " sjmp 00090$ \n" - - "00099$: \n" - ); -} - -void selfUpdate(void) -{ - uint32_t updaterInfo = prvUpdateApplierGet(); - uint8_t __code *src = (uint8_t __code*)updaterInfo; - uint8_t i, len = updaterInfo >> 16; - uint8_t __xdata *dst = mScreenRow; - - for (i = len; i ; i--) - *dst++ = *src++; - - if (!flashWrite(0xfc00, mScreenRow, len, true)) - pr("failed to write updater\n"); - - IEN_EA = 0; //ints off - - __asm__( - " mov dptr, #0xfc00 \n" - " clr a \n" - " jmp @a+dptr \n" - ); } \ No newline at end of file diff --git a/ap_fw/board/zbs29v033/screen.c b/ap_fw/board/zbs29v033/screen.c deleted file mode 100644 index 5e3976dd..00000000 --- a/ap_fw/board/zbs29v033/screen.c +++ /dev/null @@ -1,379 +0,0 @@ -#include -#include "asmUtil.h" -#include "screen.h" -#include "printf.h" -#include "board.h" -#include "timer.h" -#include "sleep.h" -#include "adc.h" -#include "cpu.h" -#include "spi.h" - -uint8_t __xdata mScreenRow[320]; - -static __bit mInited = false, mPartial; -static uint8_t __xdata mPassNo; - -#define SCREEN_CMD_CLOCK_ON 0x80 -#define SCREEN_CMD_CLOCK_OFF 0x01 - -#define SCREEN_CMD_ANALOG_ON 0x40 -#define SCREEN_CMD_ANALOG_OFF 0x02 - -#define SCREEN_CMD_LATCH_TEMPERATURE_VAL 0x20 - -#define SCREEN_CMD_LOAD_LUT 0x10 -#define SCREEN_CMD_USE_MODE_2 0x08 // modified commands 0x10 and 0x04 - -#define SCREEN_CMD_REFRESH 0xC7 - -static const uint8_t __code mColorMap[][6] = - { - // colors are: B, DG, G, LG, W, R - // phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys) - { - 1, 1, 1, 1, 0, 0, // lo plane (B) - }, - { - 0, 0, 0, 0, 0, 1, // hi plane (R) - }}; - -#define einkPrvSelect() \ - do \ - { \ - P1_7 = 0; \ - } while (0) - -#define einkPrvDeselect() \ - do \ - { \ - P1_7 = 1; \ - } while (0) -// urx pin -#define einkPrvMarkCommand() \ - do \ - { \ - P2_2 = 0; \ - } while (0) - -#define einkPrvMarkData() \ - do \ - { \ - P2_2 = 1; \ - } while (0) - -#pragma callee_saves einkPrvCmd -static void einkPrvCmd(uint8_t cmd) // sets chip select -{ - einkPrvSelect(); - einkPrvMarkCommand(); - spiByte(cmd); -} - -#pragma callee_saves einkPrvData -static void einkPrvData(uint8_t byte) -{ - einkPrvMarkData(); - spiByte(byte); -} - -#pragma callee_saves einkPrvCmdWithOneByte -static void einkPrvCmdWithOneByte(uint16_t vals) // passing in one u16 is better than two params cause SDCC sucks -{ - einkPrvCmd(vals >> 8); - einkPrvData(vals); - einkPrvDeselect(); -} - -#pragma callee_saves einkPrvWaitWithTimeout -static void einkPrvWaitWithTimeout(uint32_t timeout) -{ - uint32_t __xdata start = timerGet(); - - while (timerGet() - start < timeout) - { - - if (!P2_1) - return; - } - pr("screen timeout %lu ticks\n", timerGet() - start); - //while (1) - ; -} - -#pragma callee_saves einkPrvWaitWithTimeout -static void einkPrvWaitWithTimeoutSleep(uint32_t timeout) -{ - uint8_t tmp_P2FUNC = P2FUNC; - uint8_t tmp_P2DIR = P2DIR; - uint8_t tmp_P2PULL = P2PULL; - uint8_t tmp_P2LVLSEL = P2LVLSEL; - P2FUNC &= 0xfd; - P2DIR |= 2; - P2PULL |= 2; - P2LVLSEL |= 2; - - P2CHSTA &= 0xfd; - P2INTEN |= 2; - P2CHSTA &= 0xfd; - sleepForMsec(timeout); - P2CHSTA &= 0xfd; - P2INTEN &= 0xfd; - - P2FUNC = tmp_P2FUNC; - P2DIR = tmp_P2DIR; - P2PULL = tmp_P2PULL; - P2LVLSEL = tmp_P2LVLSEL; - /*if (!P2_1) - return; - - pr("screen timeout\n"); - while(1);*/ -} - -#pragma callee_saves einkPrvReadByte -static uint8_t einkPrvReadByte(void) -{ - uint8_t val = 0, i; - - P0DIR = (P0DIR & ~(1 << 0)) | (1 << 1); - P0 &= ~(1 << 0); - P0FUNC &= ~((1 << 0) | (1 << 1)); - - P2_2 = 1; - - for (i = 0; i < 8; i++) - { - P0_0 = 1; - __asm__("nop\nnop\nnop\nnop\nnop\n"); - val <<= 1; - if (P0_1) - val++; - P0_0 = 0; - __asm__("nop\nnop\nnop\nnop\nnop\n"); - } - - // set up pins for spi (0.0,0.1,0.2) - P0FUNC |= (1 << 0) | (1 << 1); - - return val; -} - -#pragma callee_saves einkPrvReadStatus -static uint8_t einkPrvReadStatus(void) -{ - uint8_t sta; - einkPrvCmd(0x2f); - - sta = einkPrvReadByte(); - einkPrvDeselect(); - - return sta; -} - -#pragma callee_saves screenPrvStartSubPhase -static void screenPrvStartSubPhase(__bit redSubphase) -{ - einkPrvCmd(0x4e); - einkPrvData(0); - einkPrvDeselect(); - - einkPrvCmd(0x4f); - einkPrvData(0x00); - einkPrvData(0x00); - einkPrvDeselect(); - - einkPrvCmd(redSubphase ? 0x26 : 0x24); - - einkPrvDeselect(); -} - -#pragma callee_saves screenInitIfNeeded -static void screenInitIfNeeded(__bit forPartial) -{ - if (mInited) - return; - - mInited = true; - mPartial = forPartial; - - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 0; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 1; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - - einkPrvCmd(0x12); // software reset - einkPrvDeselect(); - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - - einkPrvCmdWithOneByte(0x7454); - - einkPrvCmdWithOneByte(0x7e3b); - - einkPrvCmd(0x2b); - einkPrvData(0x04); - einkPrvData(0x63); - einkPrvDeselect(); - - einkPrvCmd(0x0c); // they send 8f 8f 8f 3f - einkPrvData(0x8f); - einkPrvData(0x8f); - einkPrvData(0x8f); - einkPrvData(0x3f); - einkPrvDeselect(); - - einkPrvCmd(0x01); - einkPrvData((SCREEN_HEIGHT - 1) & 0xff); - einkPrvData((SCREEN_HEIGHT - 1) >> 8); - einkPrvData(0x00); - einkPrvDeselect(); - - einkPrvCmdWithOneByte(0x1103); - - einkPrvCmd(0x44); - einkPrvData(0x00); - einkPrvData(SCREEN_WIDTH / 8 - 1); - einkPrvDeselect(); - - einkPrvCmd(0x45); - einkPrvData(0x00); - einkPrvData(0x00); - einkPrvData((SCREEN_HEIGHT - 1) & 0xff); - einkPrvData((SCREEN_HEIGHT - 1) >> 8); - einkPrvDeselect(); - - einkPrvCmdWithOneByte(0x3cc0); // border will be HiZ - - einkPrvCmdWithOneByte(0x1880); // internal temp sensor - - einkPrvCmdWithOneByte(0x2108); - // turn on clock & analog - einkPrvCmdWithOneByte(0x22B1); - einkPrvCmd(0x20); // do action - einkPrvDeselect(); - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND); -} - -#pragma callee_saves screenPrvDraw -static void screenPrvDraw(void) -{ - einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_REFRESH); - einkPrvCmd(0x20); // do actions - if (1) - { - einkPrvWaitWithTimeoutSleep(1000 * 60UL); - screenSleep(); - } - else - { - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 60UL); - } -} - -__bit screenTxStart(__bit forPartial) -{ - screenInitIfNeeded(forPartial); - mPassNo = 0; - - screenPrvStartSubPhase(false); - - return true; -} - -void screenEndPass(void) -{ - switch (mPassNo) - { - case 0: - screenPrvStartSubPhase(true); - break; - default: - return; - } - mPassNo++; -} - -void screenTxEnd(void) -{ - screenPrvDraw(); - screenShutdown(); -} - -void screenShutdown(void) -{ - if (!mInited) - return; - - mInited = false; - einkPrvCmdWithOneByte(0x1003); // shut down -} - -void screenSleep(void) -{ - P2_0 = 0; - timerDelay(TIMER_TICKS_PER_SECOND / 250); - P2_0 = 1; - timerDelay(TIMER_TICKS_PER_SECOND / 250); - - einkPrvCmd(0x12); // software reset - einkPrvDeselect(); - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND); - - einkPrvCmdWithOneByte(0x1003); // shut down -} - -#pragma callee_saves screenByteTx -void screenByteTx(uint8_t byte) -{ - static uint8_t __xdata prev, step = 0; - - prev <<= 2; - prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f]; - if (++step == 4) - { - step = 0; - einkPrvSelect(); - einkPrvData(prev); - einkPrvDeselect(); - } -} - -// yes this is here... -uint16_t adcSampleBattery(void) -{ - __bit wasInited = mInited; - uint16_t voltage = 2600; - - if (!mInited) - screenInitIfNeeded(false); - - uint8_t val; - - einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON); - einkPrvCmd(0x20); // do action - einkPrvDeselect(); - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND); - - for (val = 3; val < 8; val++) - { - - einkPrvCmdWithOneByte(0x1500 + val); - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND); - if (einkPrvReadStatus() & 0x10) - { // set if voltage is less than threshold ( == 1.9 + val / 10) - voltage = 1850 + mathPrvMul8x8(val, 100); - break; - } - } - - einkPrvCmdWithOneByte(0x22B1); - einkPrvCmd(0x20); // do action - einkPrvDeselect(); - einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND); - - if (!wasInited) - screenShutdown(); - - return voltage; -} diff --git a/ap_fw/board/zbs29v033/screen.h b/ap_fw/board/zbs29v033/screen.h index 576238d5..89873766 100644 --- a/ap_fw/board/zbs29v033/screen.h +++ b/ap_fw/board/zbs29v033/screen.h @@ -27,22 +27,6 @@ extern int8_t __xdata mCurTemperature; #define SCREEN_DATA_PASSES 2 -void screenShutdown(void); - -void screenTest(void); - -__bit screenTxStart(__bit forPartial); - -void screenEndPass(void); //at end of each pass - -#pragma callee_saves screenByteTx -void screenByteTx(uint8_t byte); -void screenTxEnd(void); - -void screenSleep(void); - -extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight - #endif diff --git a/ap_fw/comms.c b/ap_fw/comms.c index a48885d0..36126866 100644 --- a/ap_fw/comms.c +++ b/ap_fw/comms.c @@ -42,8 +42,6 @@ bool commsTxUnencrypted(const void __xdata *packetP, uint8_t len) { mCommsBuf[0] = len + RADIO_PAD_LEN_BY; return radioTx(mCommsBuf);; - radioTx(mCommsBuf);; - } bool commsTxNoCpy(const void __xdata *packetp) { diff --git a/ap_fw/eeprom.c b/ap_fw/eeprom.c deleted file mode 100644 index 8d7e9d83..00000000 --- a/ap_fw/eeprom.c +++ /dev/null @@ -1,322 +0,0 @@ -#include "asmUtil.h" -#include "screen.h" -#include "eeprom.h" -#include "printf.h" -#include "board.h" -#include "cpu.h" - -static uint32_t __xdata mEepromSize; -static uint8_t __xdata mOpcodeErz4K = 0, mOpcodeErz32K = 0, mOpcodeErz64K = 0; -uint8_t mScreenRow[320]; - -uint32_t eepromGetSize(void) -{ - return mEepromSize; -} - -void eepromReadStart(uint32_t addr) __reentrant -{ - eepromPrvSelect(); - eepromByte(0x03); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); -} - -void eepromRead(uint32_t addr, void __xdata *dstP, uint16_t len) __reentrant -{ - uint8_t __xdata *dst = (uint8_t __xdata*)dstP; - - eepromPrvSelect(); - eepromByte(0x03); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); - - while (len--) - *dst++ = eepromByte(0); - eepromPrvDeselect(); -} - -static void eepromPrvSimpleCmd(uint8_t cmd) -{ - eepromPrvSelect(); - eepromByte(cmd); - eepromPrvDeselect(); -} - -static bool eepromPrvBusyWait(void) -{ - uint8_t val; - - eepromPrvSelect(); - eepromByte(0x05); - while ((val = eepromByte(0x00)) & 1); - eepromPrvDeselect(); - - return true; -} - -static bool eepromWriteLL(uint32_t addr, const void __xdata *srcP, uint16_t len) -{ - const uint8_t __xdata *src = (const uint8_t __xdata*)srcP; - - eepromPrvSimpleCmd(0x06); - - eepromPrvSelect(); - eepromByte(0x02); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); - - while (len--) - eepromByte(*src++); - eepromPrvDeselect(); - - return eepromPrvBusyWait(); -} - -void eepromDeepPowerDown(void) -{ - eepromPrvSimpleCmd(0xb9); -} - -static void eepromPrvWakeFromPowerdown(void) -{ - eepromPrvSimpleCmd(0xab); -} - -#pragma callee_saves eepromPrvSfdpRead -static void eepromPrvSfdpRead(uint16_t ofst, uint8_t __xdata *dst, uint8_t len) -{ - eepromPrvSelect(); - eepromByte(0x5a); //cmd - eepromByte(0); //addr - eepromByte(ofst >> 8); - eepromByte(ofst); - eepromByte(0x00); //dummy - while(len--) - *dst++ = eepromByte(0); - eepromPrvDeselect(); -} - -__bit eepromInit(void) -{ - uint8_t __xdata buf[8]; - uint8_t i, nParamHdrs; - - eepromPrvWakeFromPowerdown(); - - //process SFDP - - eepromPrvSfdpRead(0, buf, 8); - if (buf[0] != 0x53 || buf[1] != 0x46 || buf[2] != 0x44 || buf[3] != 0x50 || buf[7] != 0xff) { - pr("SFDP: header not found\n"); - - __bit valid = false; - - //try manual ID for chips we know of - eepromPrvSelect(); - eepromByte(0x90); - eepromByte(0x00); - eepromByte(0x00); - eepromByte(0x00); - if (eepromByte(0) == 0xc2) { //old macronix chips - valid = true; - mOpcodeErz4K = 0x20; - switch (eepromByte(0)) { - case 0x05: //MX25V512 - mEepromSize = 0x00010000ul; - break; - - case 0x12: //MX25V4005 - mEepromSize = 0x00080000ul; - break; - - default: - valid = false; - break; - } - } - eepromPrvDeselect(); - - return valid; - } - if (buf[5] != 0x01) { - pr("SFDP: version wrong: %u.%d\n", buf[5], buf[4]); - return false; - } - nParamHdrs = buf[6]; - if (nParamHdrs == 0xff) //that case is very unlikely and we just do not care - nParamHdrs--; - - //now we need to find the JEDEC parameter table header - for (i = 0; i <= nParamHdrs; i++) { - - eepromPrvSfdpRead(mathPrvMul8x8(i, 8) + 8, buf, 8); - if (buf[0] == 0x00 && buf[2] == 0x01 && buf[3] >= 9) { - - uint8_t j; - - eepromPrvSfdpRead(*(uint16_t __xdata*)(buf + 4), mScreenRow, 9 * 4); - if ((mScreenRow[0] & 3) != 1) { - pr("SFDP: no 4K ERZ\n"); - break; - } - if (!(mScreenRow[0] & 0x04)) { - pr("SFDP: no large write buf\n"); - break; - } - if ((mScreenRow[2] & 0x06)) { - pr("SFDP: addr.len != 3\n"); - break; - } - - if (!mScreenRow[1] || mScreenRow[1] == 0xff) { - pr("SFDP: 4K ERZ opcode invalid\n"); - break; - } - mOpcodeErz4K = mScreenRow[1]; - - if (mScreenRow[7] & 0x80) { - - pr("SFDP: device too big\n"); - break; - } - else { - - uint8_t t; - - if (t = mScreenRow[7]) - mEepromSize = 0x00200000UL; - else if (t = mScreenRow[6]) - mEepromSize = 0x00002000UL; - else if (t = mScreenRow[5]) - mEepromSize = 0x00000020UL; - else { - pr("SFDP: device so small?!\n"); - break; - } - - while (t) { - mEepromSize <<= 1; - t >>= 1; - } - } - - //get erase opcodes - for (j = 0x1c; j < 0x24; j += 2) { - uint8_t instr = mScreenRow[j + 1]; - - if (!instr || instr == 0xff) - continue; - - switch (mScreenRow[j]) { - case 0x0c: - if (mOpcodeErz4K != instr) { - pr("4K ERZ opcode disagreement\n"); - return false; - } - break; - - case 0x0f: //32K erase - mOpcodeErz32K = instr; - break; - - case 0x10: //64K erase - mOpcodeErz64K = instr; - break; - } - } - - /* - pr("EEPROM accepted\n"); - pr(" ERZ opcodes: \n"); - if (mOpcodeErz4K) - pr(" 4K: %02xh\n", mOpcodeErz4K); - if (mOpcodeErz32K) - pr(" 32K: %02xh\n", mOpcodeErz32K); - if (mOpcodeErz64K) - pr(" 64K: %02xh\n", mOpcodeErz64K); - pr(" Size: 0x%*08lx\n", (uint16_t)&mEepromSize); - */ - return true; - } - } - - pr("SFDP: no JEDEC table of expected version found\n"); - return false; -} - -bool eepromWrite(uint32_t addr, const void __xdata *srcP, uint16_t len) __reentrant -{ - const uint8_t __xdata *src = (const uint8_t __xdata*)srcP; - - while (len) { - - uint16_t lenNow = EEPROM_WRITE_PAGE_SZ - (addr & (EEPROM_WRITE_PAGE_SZ - 1)); - - if (lenNow > len) - lenNow = len; - - if (!eepromWriteLL(addr, src, lenNow)) - return false; - - addr += lenNow; - src += lenNow; - len -= lenNow; - } - return true; -} - -bool eepromErase(uint32_t addr, uint16_t nSec) __reentrant -{ - uint8_t now; - - if (((uint16_t)addr) & 0x0fff) - return false; - - for (;nSec; nSec -= now) { - - eepromPrvSimpleCmd(0x06); - eepromPrvSelect(); - - if (nSec >= 16 && !(uint16_t)addr && mOpcodeErz64K) { //erase 64K - - eepromByte(mOpcodeErz64K); - now = 16; - } - else if (nSec >= 8 && !(((uint16_t)addr) & 0x7fff) && mOpcodeErz32K) { //erase 32K - - eepromByte(mOpcodeErz32K); - now = 8; - } - else { //erase 4K - - eepromByte(mOpcodeErz4K); - now = 1; - } - - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr); - eepromPrvDeselect(); - - if (!eepromPrvBusyWait()) - return false; - - addr += mathPrvMul16x8(EEPROM_ERZ_SECTOR_SZ, now); - } - - return true; -} - -void eepromOtpModeEnter(void) -{ - eepromPrvSimpleCmd(0xb1); -} - -void eepromOtpModeExit(void) -{ - eepromPrvSimpleCmd(0xc1); -} \ No newline at end of file diff --git a/ap_fw/eeprom.h b/ap_fw/eeprom.h deleted file mode 100644 index 9d750274..00000000 --- a/ap_fw/eeprom.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _EEPROM_H_ -#define _EEPROM_H_ - -#include -#include - -#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 - -__bit eepromInit(void); -void eepromOtpModeEnter(void); -void eepromOtpModeExit(void); - -#pragma callee_saves eepromRead -void eepromRead(uint32_t addr, void __xdata *dst, uint16_t len) __reentrant; - -#pragma callee_saves eepromWrite -bool eepromWrite(uint32_t addr, const void __xdata *src, uint16_t len) __reentrant; - -#pragma callee_saves eepromErase -bool eepromErase(uint32_t addr, uint16_t numSectors) __reentrant; - -void eepromDeepPowerDown(void); - -#pragma callee_saves eepromGetSize -uint32_t eepromGetSize(void); - -//this is for firmware update use -void eepromReadStart(uint32_t addr) __reentrant; - -//structures -#define EEPROM_IMG_INPROGRESS (0x7fffffffUL) -#define EEPROM_IMG_VALID (0x494d4722UL) - -#include "board.h" - -#define EEPROM_PIECE_SZ (88) -struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them - uint64_t version; - uint32_t validMarker; - uint32_t size; - uint32_t rfu[8]; //zero-filled for now - uint8_t piecesMissing[EEPROM_PROGRESS_BYTES]; //each bit represents a EEPROM_PIECE_SZ-byte piece - uint32_t id; - - //image data here - //we pre-erase so progress can be calculated by finding the first non-0xff byte -}; - - - -#endif diff --git a/ap_fw/main.c b/ap_fw/main.c index cae4bd0e..0ec68756 100644 --- a/ap_fw/main.c +++ b/ap_fw/main.c @@ -9,7 +9,6 @@ #include "board.h" #include "comms.h" #include "cpu.h" -#include "eeprom.h" #include "printf.h" #include "proto.h" #include "radio.h" @@ -40,7 +39,8 @@ struct MacFrameBcast { uint16_t srcPan; uint8_t src[8]; } __packed; -#define PKT_AVAIL_DATA_REQ_SHORT 0xE4 + +#define PKT_AVAIL_DATA_SHORTREQ 0xE3 #define PKT_AVAIL_DATA_REQ 0xE5 #define PKT_AVAIL_DATA_INFO 0xE6 #define PKT_BLOCK_PARTIAL_REQUEST 0xE7 @@ -61,10 +61,9 @@ struct AvailDataReq { uint16_t batteryMv; uint8_t hwType; uint8_t wakeupReason; - uint8_t capabilities; // undefined, as of now + uint8_t capabilities; // undefined, as of now } __packed; - #define DATATYPE_NOUPDATE 0 #define DATATYPE_IMG 1 #define DATATYPE_IMGRAW 2 @@ -72,14 +71,13 @@ struct AvailDataReq { struct AvailDataInfo { uint8_t checksum; - uint64_t dataVer; // MD5 of potential traffic - uint32_t dataSize; - uint8_t dataType; // allows for 16 different datatypes + uint64_t dataVer; // MD5 of potential traffic + uint32_t dataSize; + uint8_t dataType; // allows for different datatypes uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image) - uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes + uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes } __packed; - struct blockPart { uint8_t checksum; uint8_t blockId; @@ -585,7 +583,7 @@ void sendPart(uint8_t partNo) { radioTx(radiotxbuffer); } void sendBlockData() { - if(getBlockDataLength()==0){ + if (getBlockDataLength() == 0) { pr("Invalid block request received, 0 parts..\n"); requestedData.requestedParts[0] |= 0x01; } @@ -632,20 +630,14 @@ void sendCancelXfer(uint8_t *dst) { void sendPong(void *__xdata buf) { struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf; struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1); - memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + 2); - radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG; radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING; memcpy(frameHeader->src, mSelfMac, 8); memcpy(frameHeader->dst, rxframe->src, 8); - - frameHeader->fcs.frameType = 1; - frameHeader->fcs.panIdCompressed = 1; - frameHeader->fcs.destAddrType = 3; - frameHeader->fcs.srcAddrType = 3; + radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits + radiotxbuffer[2] = 0xCC; // normal frame frameHeader->seq = seq++; frameHeader->pan = rxframe->srcPan; - radioTx(radiotxbuffer); } @@ -681,18 +673,16 @@ void main(void) { radioSetTxPower(10); radioRxEnable(true, true); - // uint8_t __xdata fromMac[8]; pr("RDY>\n"); housekeepingTimer = timerGet(); - // really... if I do the call below, it'll cost me 8 bytes IRAM. Not the kind of 'optimization' I ever dreamed of doing - // pr("MAC>%02X%02X%02X%02X%02X%02X%02X%02X\n", mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3], mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7]); 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]); + uint16_t __xdata loopCount = 1; pr("VER>%04X\n", version); while (1) { while ((timerGet() - housekeepingTimer) < ((TIMER_TICKS_PER_SECOND * HOUSEKEEPING_INTERVAL) - 100 * TIMER_TICKS_PER_MS)) { @@ -715,10 +705,17 @@ void main(void) { case PKT_PING: sendPong(radiorxbuffer); break; + case PKT_AVAIL_DATA_SHORTREQ: + // a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal battery use + // bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is sent + memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + 1, 0, sizeof(struct AvailDataReq)); + processAvailDataReq(radiorxbuffer); + break; default: pr("t=%02X\n", getPacketType(radiorxbuffer)); break; } + loopCount = 10000; } while (uartBytesAvail()) { processSerial(uartRx()); @@ -730,8 +727,14 @@ void main(void) { blockStartTimer = 0; } } + loopCount--; + if (loopCount == 0) { + loopCount = 10000; + // every once in a while, especially when handling a lot of traffic, the radio will hang. Calling this every once in while + // alleviates this problem. The radio is set back to 'receive' whenever loopCount overflows + RADIO_command = RADIO_CMD_RECEIVE; + } } - pr("housekeeping..."); for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) { if (pendingDataArr[c].attemptsLeft == 1) { diff --git a/ap_fw/sleep.h b/ap_fw/sleep.h deleted file mode 100644 index 02b06c46..00000000 --- a/ap_fw/sleep.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SLEEP_H_ -#define _SLEEP_H_ - -#include - - -void sleepForMsec(uint32_t msec); -void sleepTillInt(void); //assumes you left only one int enabled! - -#endif diff --git a/ap_fw/soc/zbs243/make.mk b/ap_fw/soc/zbs243/make.mk index c40d8ba9..f9432fbd 100644 --- a/ap_fw/soc/zbs243/make.mk +++ b/ap_fw/soc/zbs243/make.mk @@ -2,7 +2,7 @@ FLAGS += -Isoc/zbs243 FLAGS += -DSOC_ZBS243 --xram-loc 0xe000 --xram-size 0x2000 --model-large -SOURCES += soc/zbs243/soc.c soc/zbs243/wdt.c soc/zbs243/sleep.c soc/zbs243/spi.c soc/zbs243/uart.c soc/zbs243/timer.c soc/zbs243/radio.c +SOURCES += soc/zbs243/soc.c soc/zbs243/wdt.c soc/zbs243/spi.c soc/zbs243/uart.c soc/zbs243/timer.c soc/zbs243/radio.c SOURCES += soc/zbs243/flash.c soc/zbs243/temperature.c cpu/8051/random.c cpu/8051/printf.c -CPU = 8051 \ No newline at end of file +CPU = 8051 diff --git a/ap_fw/soc/zbs243/radio.c b/ap_fw/soc/zbs243/radio.c index 4fb70e9b..055527ce 100644 --- a/ap_fw/soc/zbs243/radio.c +++ b/ap_fw/soc/zbs243/radio.c @@ -7,7 +7,7 @@ #include "timer.h" #define RX_BUFFER_SIZE (RADIO_MAX_PACKET_LEN + 1 /* len byte */ + 2 /* RSSI & LQI */) -#define RX_BUFFER_NUM 3 +#define RX_BUFFER_NUM 7 static volatile uint8_t __xdata mRxBufs[RX_BUFFER_NUM][RX_BUFFER_SIZE]; static volatile uint8_t __xdata mLastRSSI, mLastTxedSeq, mRxOn, mRxBufNextR, mRxBufNextW, mRxBufNumFree; From efdc38115f3b66b91ac343fd51b89623d1b6492a Mon Sep 17 00:00:00 2001 From: Jelmer Date: Mon, 6 Feb 2023 14:06:31 +0100 Subject: [PATCH 2/4] fixed reception of short datareq for ap --- ap_fw/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ap_fw/main.c b/ap_fw/main.c index 0ec68756..a4c7ed4a 100644 --- a/ap_fw/main.c +++ b/ap_fw/main.c @@ -708,7 +708,7 @@ void main(void) { case PKT_AVAIL_DATA_SHORTREQ: // a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal battery use // bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is sent - memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + 1, 0, sizeof(struct AvailDataReq)); + memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq)+2); processAvailDataReq(radiorxbuffer); break; default: From 76d1600b291594f96148b8171d50e92381e2ce90 Mon Sep 17 00:00:00 2001 From: Jelmer Date: Mon, 6 Feb 2023 17:00:55 +0100 Subject: [PATCH 3/4] lots of improvements, improved battery life, scan --- tag_fw/board/boardCommon.h | 4 - tag_fw/board/boardZBS29common.c | 7 - tag_fw/drawing.c | 3 +- tag_fw/epd.c | 58 +++++-- tag_fw/epd.h | 1 + tag_fw/main.c | 259 +++++++++++++++++++++----------- tag_fw/powermgt.c | 143 +++++++++++++----- tag_fw/powermgt.h | 57 +++++-- tag_fw/proto.h | 2 +- tag_fw/settings.h | 11 +- tag_fw/syncedproto.c | 88 +++++++---- tag_fw/syncedproto.h | 12 +- tag_fw/userinterface.c | 78 ++++++++-- tag_fw/userinterface.h | 6 + 14 files changed, 520 insertions(+), 209 deletions(-) diff --git a/tag_fw/board/boardCommon.h b/tag_fw/board/boardCommon.h index f7b3efaa..323a92c0 100644 --- a/tag_fw/board/boardCommon.h +++ b/tag_fw/board/boardCommon.h @@ -9,10 +9,6 @@ void powerPortsDownForSleep(void); #pragma callee_saves boardInit void boardInit(void); -//early - before most things -#pragma callee_saves boardInitStage2 -void boardInitStage2(void); - //late, after eeprom #pragma callee_saves boardInit __bit boardGetOwnMac(uint8_t __xdata *mac); diff --git a/tag_fw/board/boardZBS29common.c b/tag_fw/board/boardZBS29common.c index 7a662eed..80667c6c 100644 --- a/tag_fw/board/boardZBS29common.c +++ b/tag_fw/board/boardZBS29common.c @@ -30,8 +30,6 @@ void powerPortsDownForSleep(void) void boardInit(void) { - wdtOff(); - //set up pins for spi(0.0,0.1,0.2), UART (0.6) P0FUNC |= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 6); P0DIR = (P0DIR &~ ((1 << 0) | (1 << 1) | (1 << 6))) | (1 << 2); @@ -54,14 +52,9 @@ void boardInit(void) //BS1 = low P1_2 = 0; - uartInit(); spiInit(); } -void boardInitStage2(void) -{ - //nothing yet -} __bit boardGetOwnMac(uint8_t __xdata *mac) { diff --git a/tag_fw/drawing.c b/tag_fw/drawing.c index e9cac41d..4ed967b9 100644 --- a/tag_fw/drawing.c +++ b/tag_fw/drawing.c @@ -359,6 +359,5 @@ void drawImageAtAddress(uint32_t addr) { pr(" complete.\n"); - draw(); - epdEnterSleep(); + drawWithSleep(); } diff --git a/tag_fw/epd.c b/tag_fw/epd.c index 1aa05b94..25d78422 100644 --- a/tag_fw/epd.c +++ b/tag_fw/epd.c @@ -198,7 +198,7 @@ void epdEnterSleep() { P2_0 = 1; timerDelay(50); shortCommand(CMD_SOFT_RESET2); - epdBusyWait(TIMER_TICKS_PER_MS * 10); + epdBusyWait(TIMER_TICKS_PER_MS * 15); shortCommand1(CMD_ENTER_SLEEP, 0x03); isInited = false; } @@ -239,12 +239,24 @@ static uint8_t epdGetStatus() { return sta; } uint16_t epdGetBattery(void) { +// epdEnterSleep(); // r +// return 2600; // r uint16_t voltage = 2600; - - if (!isInited) - epdReset(); uint8_t val; + //epdReset(); + + timerDelay(50); + P2_0 = 0; + timerDelay(50); + P2_0 = 1; + timerDelay(50); + + shortCommand(CMD_SOFT_RESET); // software reset + epdBusyWait(TIMER_TICKS_PER_MS * 30); + shortCommand(CMD_SOFT_RESET2); + epdBusyWait(TIMER_TICKS_PER_MS * 30); + shortCommand1(CMD_DISP_UPDATE_CTRL2, SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON); shortCommand(CMD_ACTIVATION); epdBusyWait(TIMER_TICKS_PER_MS * 100); @@ -258,12 +270,10 @@ uint16_t epdGetBattery(void) { } } - shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); - shortCommand(CMD_ACTIVATION); - epdBusyWait(TIMER_TICKS_PER_MS * 100); + shortCommand(CMD_SOFT_RESET2); + epdBusyWait(TIMER_TICKS_PER_MS * 15); + shortCommand1(CMD_ENTER_SLEEP, 0x03); - if (!isInited) - epdEnterSleep(); return voltage; } @@ -341,7 +351,7 @@ void selectLUT(uint8_t lut) { lutGroupDisable(LUTGROUP_NEGATIVE); lutGroupDisable(LUTGROUP_FASTBLINK); lutGroupDisable(LUTGROUP_SLOWBLINK); - //lutGroupSpeedup(LUTGROUP_SET, 2); + // lutGroupSpeedup(LUTGROUP_SET, 2); lutGroupDisable(LUTGROUP_IMPROVE_REDS); lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS); break; @@ -350,7 +360,7 @@ void selectLUT(uint8_t lut) { lutGroupDisable(LUTGROUP_FASTBLINK); lutGroupDisable(LUTGROUP_SLOWBLINK); lutGroupRepeat(LUTGROUP_SET, 0); - //lutGroupSpeedup(LUTGROUP_SET, 2); + // lutGroupSpeedup(LUTGROUP_SET, 2); lutGroupDisable(LUTGROUP_IMPROVE_REDS); lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS); break; @@ -421,6 +431,32 @@ void drawNoWait() { // shortCommand1(0x22, SCREEN_CMD_REFRESH); shortCommand(0x20); } +void drawWithSleep() { + shortCommand1(0x22, 0xCF); + // shortCommand1(0x22, SCREEN_CMD_REFRESH); + shortCommand(0x20); + uint8_t tmp_P2FUNC = P2FUNC; + uint8_t tmp_P2DIR = P2DIR; + uint8_t tmp_P2PULL = P2PULL; + uint8_t tmp_P2LVLSEL = P2LVLSEL; + P2FUNC &= 0xfd; + P2DIR |= 2; + P2PULL |= 2; + P2LVLSEL |= 2; + + P2CHSTA &= 0xfd; + P2INTEN |= 2; + P2CHSTA &= 0xfd; + sleepForMsec(TIMER_TICKS_PER_SECOND * 120); + P2CHSTA &= 0xfd; + P2INTEN &= 0xfd; + + P2FUNC = tmp_P2FUNC; + P2DIR = tmp_P2DIR; + P2PULL = tmp_P2PULL; + P2LVLSEL = tmp_P2LVLSEL; + eepromPrvDeselect(); +} void epdWaitRdy() { epdBusyWait(TIMER_TICKS_PER_SECOND * 120); } diff --git a/tag_fw/epd.h b/tag_fw/epd.h index a702d455..d7aa94b5 100644 --- a/tag_fw/epd.h +++ b/tag_fw/epd.h @@ -46,6 +46,7 @@ void clearWindow(bool color); void clearScreen(); void draw(); void drawNoWait(); +void drawWithSleep(); void epdWaitRdy(); void drawLineHorizontal(bool color, uint16_t x1, uint16_t x2, uint16_t y); void drawLineVertical(bool color, uint16_t x, uint16_t y1, uint16_t y2); diff --git a/tag_fw/main.c b/tag_fw/main.c index 21166f36..b94b4f1e 100644 --- a/tag_fw/main.c +++ b/tag_fw/main.c @@ -13,20 +13,21 @@ #include "printf.h" #include "proto.h" #include "radio.h" +#include "settings.h" #include "syncedproto.h" #include "timer.h" #include "userinterface.h" #include "wdt.h" -//#define DEBUG_MODE +// #define DEBUG_MODE +static bool __xdata attemptFirstContact = true; - - -uint8_t showChannelSelect() { +uint8_t showChannelSelect() { // returns 0 if no accesspoints were found uint8_t __xdata result[16]; memset(result, 0, sizeof(result)); showScanningWindow(); - for (uint8_t i = 0; i < 8; i++) { + powerUp(INIT_RADIO); + for (uint8_t i = 0; i < 5; i++) { for (uint8_t c = 11; c < 27; c++) { if (detectAP(c)) { if (mLastLqi > result[c - 11]) result[c - 11] = mLastLqi; @@ -47,96 +48,184 @@ uint8_t showChannelSelect() { highestLqi = result[c]; } } + powerDown(INIT_RADIO); epdWaitRdy(); mLastLqi = highestLqi; return highestSlot; } +uint8_t channelSelect() { // returns 0 if no accesspoints were found + uint8_t __xdata result[16]; + memset(result, 0, sizeof(result)); + for (uint8_t i = 0; i < 2; i++) { + for (uint8_t c = 11; c < 27; c++) { + if (detectAP(c)) { + if (mLastLqi > result[c - 11]) result[c - 11] = mLastLqi; + } + } + } + uint8_t __xdata highestLqi = 0; + uint8_t __xdata highestSlot = 0; + for (uint8_t c = 0; c < sizeof(result); c++) { + if (result[c] > highestLqi) { + highestSlot = c + 11; + highestLqi = result[c]; + } + } + + mLastLqi = highestLqi; + return highestSlot; +} + void mainProtocolLoop(void) { - clockingAndIntsInit(); - timerInit(); - boardInit(); + powerUp(INIT_BASE | INIT_UART | INIT_GPIO); + wdt10s(); + boardGetOwnMac(mSelfMac); - if (!boardGetOwnMac(mSelfMac)) { - pr("failed to get MAC. Aborting\n"); - while (1) - ; - } else { - 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]); - } - - irqsOn(); - boardInitStage2(); - - pr("BOOTED> (UI 0.03-1)\n\n"); - - if (!eepromInit()) { - pr("failed to init eeprom\n"); - while (1) - ; - } else { - initializeProto(); - } - eepromDeepPowerDown(); - // initialize Powers-saving-attempt-array with the default value; - initPowerSaving(); -#ifndef DEBUG_MODE - // show the splashscreen - getExtraData(); - - showSplashScreen(); - - eepromDeepPowerDown(); - initRadio(); - - currentChannel = showChannelSelect(); - if (currentChannel == 0) { - // couldn't find an AP :() - showNoAP(); - } else { - radioSetChannel(currentChannel); - // Found an AP. - showAPFound(); - } -#endif -#ifdef DEBUG_MODE - initRadio(); - currentChannel = 11; -#endif - epdEnterSleep(); - - P1CHSTA &= ~(1 << 0); - - while (1) { - radioRxEnable(true, true); - - struct AvailDataInfo *__xdata avail = getAvailDataInfo(); - 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 (doDataDownload(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. + { + bool __xdata macSet = false; + for (uint8_t __xdata c = 0; c < 8; c++) { + if (mSelfMac[c] != 0xFF) { + macSet = true; + break; } } - // if the AP told us to sleep for a specific period, do so. - if (nextCheckInFromAP) { - doSleep(nextCheckInFromAP * 60000UL); + if (!macSet) { + pr("Mac can't be all FF's.\n"); + powerUp(INIT_EPD); + showNoMAC(); + powerDown(INIT_EPD | INIT_GPIO | INIT_EEPROM); + doSleep(-1); + wdtDeviceReset(); + } + } + + pr("BOOTED> %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); + + 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_EPD_VOLTREADING | INIT_TEMPREADING | INIT_EEPROM); + + // get the highest slot number, number of slots + initializeProto(); + powerDown(INIT_EEPROM); + + // show the splashscreen + powerUp(INIT_EPD); + showSplashScreen(); + + wdt30s(); + powerUp(INIT_EPD); + currentChannel = showChannelSelect(); + + powerUp(INIT_GPIO | INIT_EPD); + if (currentChannel) { + showAPFound(); + initPowerSaving(INTERVAL_BASE); + powerDown(INIT_EPD | INIT_GPIO); + doSleep(5000UL); + } else { + showNoAP(); + initPowerSaving(INTERVAL_AT_MAX_ATTEMPTS); + powerDown(INIT_EPD | INIT_GPIO); + doSleep(120000UL); + } + + while (1) { + if (currentChannel) { + // associated + + struct AvailDataInfo *__xdata avail; + if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || attemptFirstContact || wakeUpReason != WAKEUP_REASON_TIMED) { + if (attemptFirstContact) + wakeUpReason = WAKEUP_REASON_BOOTUP; + + + if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) { + powerUp(INIT_BASE | INIT_TEMPREADING | INIT_EPD_VOLTREADING | INIT_RADIO); + voltageCheckCounter = 0; + } else { + powerUp(INIT_BASE | INIT_TEMPREADING | INIT_RADIO); + } + voltageCheckCounter++; + + avail = getAvailDataInfo(); + if (avail != NULL) { + longDataReqCounter = 0; + attemptFirstContact = false; + } + } else { + powerUp(INIT_BASE | INIT_RADIO); //| INIT_GPIO | INIT_UART + 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 + wdt10s(); + powerUp(INIT_GPIO | INIT_UART); + if (doDataDownload(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; + } + powerUp(INIT_GPIO); + powerDown(INIT_EEPROM | INIT_RADIO); + } else { + // no data transfer, just sleep. + } + } + + powerDown(INIT_GPIO); + + 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 { - doSleep(getNextSleep() * 1000UL); + // not associated + powerUp(INIT_BASE | INIT_RADIO); // || INIT_GPIO | INIT_UART + + // try to find a working channel + powerUp(INIT_RADIO); + wdt30s(); + currentChannel = channelSelect(); + powerDown(INIT_RADIO | INIT_GPIO); + + // did we find a working channel? + if (currentChannel) { + // now associated! + scanAttempts = 0; + attemptFirstContact = true; + initPowerSaving(INTERVAL_BASE); + doSleep(getNextSleep() * 1000UL); + + } else { + // still not associated + doSleep(getNextScanSleep(true) * 1000UL); + } } } } diff --git a/tag_fw/powermgt.c b/tag_fw/powermgt.c index d9c1e212..ab588160 100644 --- a/tag_fw/powermgt.c +++ b/tag_fw/powermgt.c @@ -21,6 +21,7 @@ #include "sleep.h" #include "syncedproto.h" #include "timer.h" +#include "uart.h" // for initUart #include "userinterface.h" #include "wdt.h" @@ -29,41 +30,105 @@ uint8_t __xdata dataReqAttemptArrayIndex = 0; uint8_t __xdata dataReqLastAttempt = 0; uint16_t __xdata nextCheckInFromAP = 0; uint8_t __xdata wakeUpReason = 0; - -extern int8_t adcSampleTemperature(void); //in degrees C - -void initPowerSaving() { - for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { - dataReqAttemptArr[c] = INTERVAL_BASE; - } -} +uint8_t __xdata scanAttempts = 0; int8_t __xdata temperature = 0; uint16_t __xdata batteryVoltage = 0; +uint16_t __xdata longDataReqCounter = 0; +uint16_t __xdata voltageCheckCounter = 0; -void getExtraData(){ - batteryVoltage = epdGetBattery(); - temperature = adcSampleTemperature(); - pr("temp = %d volt = %d\n", temperature, batteryVoltage); +extern int8_t adcSampleTemperature(void); // in degrees C + +void initPowerSaving(uint16_t initialValue) { + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { + dataReqAttemptArr[c] = initialValue; + } } +void powerUp(uint8_t parts) { + if (parts & INIT_BASE) { + clockingAndIntsInit(); + timerInit(); + irqsOn(); + wdtOn(); + wdt10s(); + } + if (parts & INIT_GPIO) + boardInit(); -// init/sleep -void initAfterWake() { - clockingAndIntsInit(); - timerInit(); - // partialInit(); - boardInit(); - epdEnterSleep(); - irqsOn(); - boardInitStage2(); - getExtraData(); - initRadio(); + if (parts & INIT_EPD) + epdSetup(); + + if ((parts & INIT_BASE) && !(parts & INIT_EPD_VOLTREADING) && !(parts & INIT_EPD)) { + if (!(parts & INIT_GPIO)) + boardInit(); + epdEnterSleep(); // this required fixing! halp halp fix me + } + + if (parts & INIT_EPD_VOLTREADING) { + if (!(parts & INIT_GPIO)) + boardInit(); + batteryVoltage = epdGetBattery(); + } + + if (parts & INIT_UART) { + uartInit(); + } + + if (parts & INIT_EEPROM) { + if (!eepromInit()) { + powerDown(INIT_RADIO); + powerUp(INIT_EPD); + showNoEEPROM(); + powerDown(INIT_EEPROM | INIT_EPD | INIT_GPIO); + doSleep(-1); + wdtDeviceReset(); + } + } + + if (parts & INIT_TEMPREADING) { + temperature = adcSampleTemperature(); + } + + if (parts & INIT_RADIO) { + radioInit(); + radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID); + radioSetTxPower(10); + if (currentChannel >= 11 && currentChannel <= 25) { + radioSetChannel(currentChannel); + } else { + radioSetChannel(RADIO_FIRST_CHANNEL); + } + } } + +void powerDown(uint8_t parts) { + if (parts & INIT_RADIO) { + radioRxEnable(false, true); + RADIO_IRQ4_pending = 0; + UNK_C1 &= ~0x81; + TCON &= ~0x20; + uint8_t __xdata cfgPg = CFGPAGE; + CFGPAGE = 4; + RADIO_command = 0xCA; + RADIO_command = 0xC5; + CFGPAGE = cfgPg; + } + if (parts & INIT_EEPROM) { + eepromDeepPowerDown(); + eepromPrvDeselect(); + } + if (parts & INIT_EPD) + epdEnterSleep(); + + if (parts & INIT_GPIO) + powerPortsDownForSleep(); +} + void doSleep(uint32_t __xdata t) { - if (t > 1000) pr("s=%lu\n ", t / 1000); - powerPortsDownForSleep(); + // if (t > 1000) pr("s=%lu\n ", t / 1000); + // powerPortsDownForSleep(); #ifdef HAS_BUTTON // Button setup on TEST pin 1.0 (input pullup) @@ -78,7 +143,6 @@ void doSleep(uint32_t __xdata t) { // sleepy sleepForMsec(t); wakeUpReason = WAKEUP_REASON_TIMED; - #ifdef HAS_BUTTON P1INTEN = 0; if (P1CHSTA && (1 << 0)) { @@ -87,26 +151,37 @@ void doSleep(uint32_t __xdata t) { P1CHSTA &= ~(1 << 0); } #endif - - initAfterWake(); } -uint16_t getNextSleep() { + +uint32_t getNextScanSleep(bool increment) { + if (increment) { + if (scanAttempts < 255) + scanAttempts++; + } + + if (scanAttempts < INTERVAL_1_ATTEMPTS) { + return INTERVAL_1_TIME; + } else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)) { + return INTERVAL_2_TIME; + } else { + return INTERVAL_3_TIME; + } +} + +void addAverageValue() { uint16_t __xdata curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE; curval *= dataReqLastAttempt; curval /= DATA_REQ_MAX_ATTEMPTS; curval += INTERVAL_BASE; dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval; dataReqAttemptArrayIndex++; +} +uint16_t getNextSleep() { uint16_t avg = 0; - bool noNetwork = true; for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { avg += dataReqAttemptArr[c]; - if (dataReqAttemptArr[c] != INTERVAL_AT_MAX_ATTEMPTS) { - noNetwork = false; - } } - if (noNetwork == true) return INTERVAL_NO_SIGNAL; avg /= POWER_SAVING_SMOOTHING; return avg; } \ No newline at end of file diff --git a/tag_fw/powermgt.h b/tag_fw/powermgt.h index 9e7757ef..9814ed35 100644 --- a/tag_fw/powermgt.h +++ b/tag_fw/powermgt.h @@ -2,41 +2,76 @@ #define _POWERMGT_H_ #include +#define WAKEUP_REASON_TIMED 0 +#define WAKEUP_REASON_BOOTUP 1 +#define WAKEUP_REASON_GPIO 2 +#define WAKEUP_REASON_NFC 3 -#define WAKEUP_REASON_TIMED 0 -#define WAKEUP_REASON_BOOTUP 1 -#define WAKEUP_REASON_GPIO 2 -#define WAKEUP_REASON_NFC 3 +#define INIT_EPD_VOLTREADING 0x80 +#define INIT_RADIO 0x40 +#define INIT_GPIO 0x20 +#define INIT_UART 0x10 +#define INIT_EPD 0x08 +#define INIT_EEPROM 0x04 +#define INIT_TEMPREADING 0x02 +#define INIT_BASE 0x01 +#define wdt10s() \ + do { \ + wdtSetResetVal(0xFFF68A1F); \ + } while (0) + +#define wdt30s() \ + do { \ + wdtSetResetVal(0xFFE39E5F); \ + } while (0) + +#define wdt60s() \ + do { \ + wdtSetResetVal(0xFFC73CBF); \ + } while (0) // power saving algorithm #define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA) #define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current -#define INTERVAL_NO_SIGNAL 1800 // interval (in seconds) when no answer for POWER_SAVING_SMOOTHING attempts, - // (INTERVAL_AT_MAX_ATTEMPTS * POWER_SAVING_SMOOTHING) seconds #define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request. // If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address #define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP #define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval #define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life! - #define MAXIMUM_PING_ATTEMPTS 20 // How many attempts to discover an AP the tag should do #define PING_REPLY_WINDOW 2UL +#define LONG_DATAREQ_INTERVAL 300 // How often (in seconds, approximately) the tag should do a long datareq (including temperature) +#define VOLTAGE_CHECK_INTERVAL 288 // How often the tag should do a battery voltage check (multiplied by LONG_DATAREQ_INTERVAL) + +// power saving when no AP's were found (scanning every X) +#define INTERVAL_1_TIME 1800UL // Try every half hour +#define INTERVAL_1_ATTEMPTS 48 // for 48 attempts (an entire day) +#define INTERVAL_2_TIME 3600UL // Try every hour +#define INTERVAL_2_ATTEMPTS 24 // for 24 attempts (an additional day) +#define INTERVAL_3_TIME 86400UL // Try every day + +extern void powerUp(uint8_t parts); +extern void powerDown(uint8_t parts); extern void initAfterWake(); extern void doSleep(uint32_t __xdata t); + +extern void addAverageValue(); extern uint16_t getNextSleep(); -extern void initPowerSaving(); -extern void getExtraData(); + +extern uint32_t getNextScanSleep(bool increment); +extern void initPowerSaving(uint16_t initialValue); extern uint8_t __xdata wakeUpReason; - extern uint16_t __xdata nextCheckInFromAP; extern uint8_t __xdata dataReqLastAttempt; extern int8_t __xdata temperature; extern uint16_t __xdata batteryVoltage; - +extern uint8_t __xdata scanAttempts; +extern uint16_t __xdata longDataReqCounter; +extern uint16_t __xdata voltageCheckCounter; #endif \ No newline at end of file diff --git a/tag_fw/proto.h b/tag_fw/proto.h index 1297a671..85e2bedc 100644 --- a/tag_fw/proto.h +++ b/tag_fw/proto.h @@ -90,7 +90,7 @@ struct MacFrameBcast { uint8_t src[8]; } __packed; -#define PKT_AVAIL_DATA_REQ_SHORT 0xE4 +#define PKT_AVAIL_DATA_SHORTREQ 0xE3 #define PKT_AVAIL_DATA_REQ 0xE5 #define PKT_AVAIL_DATA_INFO 0xE6 #define PKT_BLOCK_PARTIAL_REQUEST 0xE7 diff --git a/tag_fw/settings.h b/tag_fw/settings.h index 763a26ef..04be2750 100644 --- a/tag_fw/settings.h +++ b/tag_fw/settings.h @@ -1,12 +1,11 @@ -#ifndef SYNCED_H -#define SYNCED_H +#ifndef SETTINGS_H +#define SETTINGS_H #include -#define FW_VERSION 012 // version number (max 2.5.5 :) ) -#define FW_VERSION_SUFFIX "-rf15" // suffix, like -RC1 or whatever. +#define FW_VERSION 013 // version number (max 2.5.5 :) ) +#define FW_VERSION_SUFFIX "-rf99" // suffix, like -RC1 or whatever. #define HAS_BUTTON // uncomment to enable reading a push button (connect between 'TEST' en 'GND' on the tag, along with a 100nF capacitor in parallel). -// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers - +#define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers #endif \ No newline at end of file diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index 99539e90..a1a989d5 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -1,4 +1,5 @@ #define __packed + #include "syncedproto.h" #include @@ -120,27 +121,6 @@ void addCRC(void *p, uint8_t len) { } // radio stuff -void initRadio() { - radioInit(); - radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID); - if (currentChannel >= 11 && currentChannel <= 25) { - radioSetChannel(currentChannel); - } else { - radioSetChannel(RADIO_FIRST_CHANNEL); - } - radioSetTxPower(10); -} -void killRadio() { - radioRxEnable(false, true); - RADIO_IRQ4_pending = 0; - UNK_C1 &= ~0x81; - TCON &= ~0x20; - uint8_t __xdata cfgPg = CFGPAGE; - CFGPAGE = 4; - RADIO_command = 0xCA; - RADIO_command = 0xC5; - CFGPAGE = cfgPg; -} void sendPing() { struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + 2 + 4); @@ -160,8 +140,8 @@ void sendPing() { uint8_t detectAP(uint8_t channel) { uint32_t __xdata t; radioRxEnable(false, true); - radioRxFlush(); radioSetChannel(channel); + radioRxFlush(); radioRxEnable(true, true); for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++) { sendPing(); @@ -184,6 +164,19 @@ uint8_t detectAP(uint8_t channel) { } // data xfer stuff +void sendShortAvailDataReq() { + struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1); + outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2; + outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_SHORTREQ; + memcpy(txframe->src, mSelfMac, 8); + outBuffer[1] = 0x21; + outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet + txframe->seq = seq++; + txframe->dstPan = 0xFFFF; + txframe->dstAddr = 0xFFFF; + txframe->srcPan = PROTO_PAN_ID; + commsTxNoCpy(outBuffer); +} void sendAvailDataReq() { struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4); @@ -202,7 +195,7 @@ void sendAvailDataReq() { // TODO: send some (more) meaningful data availreq->hwType = HW_TYPE; availreq->wakeupReason = wakeUpReason; - availreq->lastPacketRSSI = (uint8_t)(-1*mLastRSSI); + availreq->lastPacketRSSI = mLastRSSI; availreq->lastPacketLQI = mLastLqi; availreq->temperature = temperature; availreq->batteryMv = batteryVoltage; @@ -210,6 +203,7 @@ void sendAvailDataReq() { commsTxNoCpy(outBuffer); } struct AvailDataInfo *__xdata getAvailDataInfo() { + radioRxEnable(true, true); uint32_t __xdata t; for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { sendAvailDataReq(); @@ -232,6 +226,31 @@ struct AvailDataInfo *__xdata getAvailDataInfo() { dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; return NULL; } +struct AvailDataInfo *__xdata getShortAvailDataInfo() { + radioRxEnable(true, true); + uint32_t __xdata t; + for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { + sendShortAvailDataReq(); + // sendAvailDataReq(); + t = timerGet() + (TIMER_TICKS_PER_MS * DATA_REQ_RX_WINDOW_SIZE); + while (timerGet() < t) { + int8_t __xdata ret = commsRxUnencrypted(inBuffer); + if (ret > 1) { + if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) { + if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) { + struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)inBuffer; + memcpy(APmac, f->src, 8); + APsrcPan = f->pan; + dataReqLastAttempt = c; + return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); + } + } + } + } + } + dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; + return NULL; +} bool processBlockPart(struct blockPart *bp) { uint16_t __xdata start = bp->blockPart * BLOCK_PART_DATA_SIZE; uint16_t __xdata size = BLOCK_PART_DATA_SIZE; @@ -439,7 +458,6 @@ void drawImageFromEeprom() { wdtOn(); drawImageAtAddress(getAddressForSlot(curImgSlot)); // adcSampleBattery(); - initRadio(); } uint32_t getHighSlotId() { uint32_t temp = 0; @@ -483,15 +501,18 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { if (curXferComplete && 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("old ver, already downloaded!\n"); + powerUp(INIT_RADIO); sendXferComplete(); + powerDown(INIT_RADIO); return true; } else { // check if we've seen this version before curImgSlot = findSlot(&(avail->dataVer)); if (curImgSlot != 0xFF) { // found a (complete)valid image slot for this version + powerDown(INIT_RADIO); sendXferComplete(); - killRadio(); + powerDown(INIT_RADIO); pr("already seen, drawing from eeprom slot %d\n", curImgSlot); @@ -551,6 +572,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { while (!curXferComplete) { // this while loop loops until the transfer has been completed, or we get tired for other reasons startdownload:; + wdt10s(); #ifndef DEBUGBLOCKS pr("REQ %d ", curBlock.blockId); #endif @@ -571,6 +593,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { // timerDelay(TIMER_TICKS_PER_MS*100); // DO BLOCK REQUEST - request a block, get an ack with timing info (hopefully) + powerUp(INIT_RADIO); struct blockRequestAck *__xdata ack = performBlockRequest(); if (ack == NULL) { pr("Cancelled request\n"); @@ -583,7 +606,9 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { if (ack->pleaseWaitMs < 35) { timerDelay(ack->pleaseWaitMs * TIMER_TICKS_PER_MS); } else { + powerDown(INIT_GPIO); doSleep(ack->pleaseWaitMs - 10); + powerUp(INIT_BASE | INIT_GPIO | INIT_UART | INIT_RADIO); radioRxEnable(true, true); } } else { @@ -594,6 +619,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { // didn't receive packets blockRequestAttempt++; if (blockRequestAttempt > 5) { + powerDown(INIT_RADIO); pr("bailing on download, 0 blockparts rx'd\n"); return false; } @@ -601,7 +627,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { // successfull block RX loop blockRequestAttempt = 0; } - + powerDown(INIT_RADIO); #ifdef DEBUGBLOCKS pr("RX %d[", curBlock.blockId); for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) { @@ -695,19 +721,23 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) { eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader)); // pr("transfer complete!"); curXferComplete = true; + powerUp(INIT_RADIO); sendXferComplete(); - killRadio(); + powerDown(INIT_RADIO); + wdt60s(); drawImageFromEeprom(); curDataInfo.dataVer = 0xAA; break; case DATATYPE_UPDATE: pr("firmware download complete, doing update.\n"); + powerUp(INIT_EPD); showApplyUpdate(); curXferComplete = true; + powerUp(INIT_RADIO); sendXferComplete(); - killRadio(); + powerDown(INIT_RADIO); + wdt60s(); eepromReadStart(EEPROM_UPDATA_AREA_START); - // wdtDeviceReset(); selfUpdate(); break; } diff --git a/tag_fw/syncedproto.h b/tag_fw/syncedproto.h index a78a2b94..6224fe42 100644 --- a/tag_fw/syncedproto.h +++ b/tag_fw/syncedproto.h @@ -2,20 +2,20 @@ #define SYNCED_H #include +//#include "settings.h" - -extern uint8_t __xdata mSelfMac[8]; +extern uint8_t __xdata mSelfMac[]; extern uint8_t __xdata currentChannel; extern uint8_t __xdata APmac[]; -extern void initRadio(); -extern void killRadio(); +extern void setupRadio(void); +extern void killRadio(void); extern struct AvailDataInfo *__xdata getAvailDataInfo(); +extern struct AvailDataInfo *__xdata getShortAvailDataInfo(); extern bool doDataDownload(struct AvailDataInfo *__xdata avail); extern void initializeProto(); -extern struct AvailDataInfo *__xdata getAvailDataInfo(); -uint8_t detectAP(uint8_t channel); +extern uint8_t detectAP(uint8_t channel); #endif \ No newline at end of file diff --git a/tag_fw/userinterface.c b/tag_fw/userinterface.c index b005d802..69e9f149 100644 --- a/tag_fw/userinterface.c +++ b/tag_fw/userinterface.c @@ -25,12 +25,10 @@ extern uint8_t __xdata mSelfMac[8]; extern uint8_t __xdata currentChannel; extern uint8_t __xdata APmac[]; -static const uint8_t __code fwVersion = FW_VERSION; -static const char __code fwVersionSuffix[] = FW_VERSION_SUFFIX; +const uint8_t __code fwVersion = FW_VERSION; +const char __code fwVersionSuffix[] = FW_VERSION_SUFFIX; void showSplashScreen() { - epdSetup(); - #if (SCREEN_WIDTH == 152) // 1.54" clearScreen(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); @@ -52,7 +50,7 @@ void showSplashScreen() { epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix); epdPrintEnd(); - draw(); + #endif #if (SCREEN_WIDTH == 128) // 2.9" @@ -88,7 +86,6 @@ void showSplashScreen() { // drawLineVertical(EPD_COLOR_RED, 64, 10, 286); // drawLineVertical(EPD_COLOR_BLACK, 65, 10, 286); - draw(); // timerDelay(TIMER_TICKS_PER_SECOND * 4); #endif #if (SCREEN_WIDTH == 400) // 2.9" @@ -120,14 +117,12 @@ void showSplashScreen() { loadRawBitmap(solum, 253, 72, EPD_COLOR_BLACK); loadRawBitmap(hacked, 261, 82, EPD_COLOR_RED); - draw(); #endif + drawWithSleep(); } void showApplyUpdate() { - epdSetup(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); - selectLUT(1); clearScreen(); setColorMode(EPD_MODE_IGNORE, EPD_MODE_NORMAL); @@ -140,7 +135,6 @@ void showApplyUpdate() { uint8_t __xdata resultcounter = 0; void showScanningWindow() { - epdSetup(); setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); selectLUT(EPD_LUT_FAST_NO_REDS); clearScreen(); @@ -180,8 +174,9 @@ void addScanResult(uint8_t channel, uint8_t lqi) { } void showAPFound() { - selectLUT(EPD_LUT_FAST_NO_REDS); clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); + selectLUT(1); #if (SCREEN_WIDTH == 128) epdPrintBegin(0, 285, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); epdpr("Waiting for data..."); @@ -247,7 +242,7 @@ void showAPFound() { epdpr("%02X%02X", mSelfMac[1], mSelfMac[0]); epdPrintEnd(); #endif - draw(); + drawWithSleep(); } void showNoAP() { @@ -281,5 +276,62 @@ void showNoAP() { epdpr("a little while"); epdPrintEnd(); #endif - draw(); + drawWithSleep(); } + +void showNoEEPROM() { + selectLUT(EPD_LUT_NO_REPEATS); + clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); +#if (SCREEN_WIDTH == 128) // 2.9" + epdPrintBegin(0, 285, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("EEPROM FAILED :("); + epdPrintEnd(); + epdPrintBegin(64, 285, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); + loadRawBitmap(failed, 42, 26, EPD_COLOR_RED); +#endif +#if (SCREEN_WIDTH == 152) // 1.54" + epdPrintBegin(26, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("EEPROM "); + epdPrintEnd(); + epdPrintBegin(8, 32, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("FAILED :("); + epdPrintEnd(); + loadRawBitmap(failed, 60, 72, EPD_COLOR_RED); + + epdPrintBegin(3, 136, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); +#endif + drawWithSleep(); +} + +void showNoMAC() { + selectLUT(EPD_LUT_NO_REPEATS); + clearScreen(); + setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); +#if (SCREEN_WIDTH == 128) // 2.9" + epdPrintBegin(0, 285, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("NO MAC SET :("); + epdPrintEnd(); + epdPrintBegin(64, 285, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); + loadRawBitmap(failed, 42, 26, EPD_COLOR_RED); +#endif +#if (SCREEN_WIDTH == 152) // 1.54" + epdPrintBegin(20, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("NO MAC"); + epdPrintEnd(); + epdPrintBegin(30, 32, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK); + epdpr("SET :("); + epdPrintEnd(); + loadRawBitmap(failed, 60, 72, EPD_COLOR_RED); + epdPrintBegin(3, 136, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK); + epdpr("Sleeping forever :'("); + epdPrintEnd(); +#endif + drawWithSleep(); +} \ No newline at end of file diff --git a/tag_fw/userinterface.h b/tag_fw/userinterface.h index 7b697e72..fa674cc2 100644 --- a/tag_fw/userinterface.h +++ b/tag_fw/userinterface.h @@ -8,4 +8,10 @@ void showScanningWindow(); void addScanResult(uint8_t channel, uint8_t lqi); void showAPFound(); void showNoAP(); +void showNoEEPROM(); +void showNoMAC(); + + +extern const uint8_t __code fwVersion; +extern const char __code fwVersionSuffix[]; #endif \ No newline at end of file From d85043a18caee833ebcfe7ea475c1efb2d7eacdd Mon Sep 17 00:00:00 2001 From: Jelmer Date: Mon, 6 Feb 2023 21:23:23 +0100 Subject: [PATCH 4/4] further power consumption tuning --- tag_fw/powermgt.h | 10 +++++----- tag_fw/syncedproto.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tag_fw/powermgt.h b/tag_fw/powermgt.h index 9814ed35..475247f6 100644 --- a/tag_fw/powermgt.h +++ b/tag_fw/powermgt.h @@ -46,11 +46,11 @@ #define VOLTAGE_CHECK_INTERVAL 288 // How often the tag should do a battery voltage check (multiplied by LONG_DATAREQ_INTERVAL) // power saving when no AP's were found (scanning every X) -#define INTERVAL_1_TIME 1800UL // Try every half hour -#define INTERVAL_1_ATTEMPTS 48 // for 48 attempts (an entire day) -#define INTERVAL_2_TIME 3600UL // Try every hour -#define INTERVAL_2_ATTEMPTS 24 // for 24 attempts (an additional day) -#define INTERVAL_3_TIME 86400UL // Try every day +#define INTERVAL_1_TIME 3600UL // Try every hour +#define INTERVAL_1_ATTEMPTS 24 // for 24 attempts (an entire day) +#define INTERVAL_2_TIME 7200UL // Try every 2 hours +#define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day) +#define INTERVAL_3_TIME 86400UL // Finally, try every day extern void powerUp(uint8_t parts); extern void powerDown(uint8_t parts); diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index a1a989d5..b023e372 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -457,7 +457,7 @@ void drawImageFromEeprom() { wdtSetResetVal(0xFFFFFFFF - 0x38C340); wdtOn(); drawImageAtAddress(getAddressForSlot(curImgSlot)); - // adcSampleBattery(); + powerDown(INIT_EPD); } uint32_t getHighSlotId() { uint32_t temp = 0;