M2 FW 2.2 - Preload and buttons

This commit is contained in:
jjwbruijn
2023-09-28 01:03:29 +02:00
parent 0c591660bc
commit fa97daef3c
15 changed files with 580 additions and 261 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -58,6 +58,11 @@
#define CMD_DO_DEEPSLEEP 3
#define CMD_DO_LEDFLASH 4
#define CMD_ERASE_EEPROM_IMAGES 5
#define CMD_ENTER_SLIDESHOW_FAST 0x06
#define CMD_ENTER_SLIDESHOW_MEDIUM 0x07
#define CMD_ENTER_SLIDESHOW_SLOW 0x08
#define CMD_ENTER_SLIDESHOW_GLACIAL 0x09
#define CMD_ENTER_NORMAL_MODE 0x0F
#define WAKEUP_REASON_TIMED 0
#define WAKEUP_REASON_GPIO 2
@@ -87,4 +92,10 @@
#define CUSTOM_IMAGE_BUTTON2 0x11
// UNUSED: 0x12 to 0x1C
#define CUSTOM_IMAGE_GPIO 0x1D
#define CUSTOM_IMAGE_NFC_WAKE 0x1E
#define CUSTOM_IMAGE_NFC_WAKE 0x1E
#define TAG_CUSTOM_MODE_NONE 0x00
#define TAG_CUSTOM_SLIDESHOW_FAST 0x06
#define TAG_CUSTOM_SLIDESHOW_MEDIUM 0x07
#define TAG_CUSTOM_SLIDESHOW_SLOW 0x08
#define TAG_CUSTOM_SLIDESHOW_GLACIAL 0x09

View File

@@ -24,15 +24,23 @@
#include "../oepl-definitions.h"
#include "../oepl-proto.h"
// #define DEBUG_MODE
static const uint64_t __code __at(0x008b) mVersionRom = 0x1000011300000000ull;
#define TAG_MODE_CHANSEARCH 0
#define TAG_MODE_ASSOCIATED 1
#define DELAY_SLIDESHOW_FAST 30
#define DELAY_SLIDESHOW_MEDIUM 60
#define DELAY_SLIDESHOW_SLOW 300
#define DELAY_SLIDESHOW_GLACIAL 1800
uint8_t currentTagMode = TAG_MODE_CHANSEARCH;
uint8_t __xdata slideShowCurrentImg = 0;
uint8_t __xdata slideShowRefreshCount = 1;
void displayLoop() {
powerUp(INIT_BASE | INIT_UART);
@@ -46,22 +54,6 @@ void displayLoop() {
showApplyUpdate();
timerDelay(TIMER_TICKS_PER_SECOND * 4);
wdt60s();
pr("Scanning screen - ");
powerUp(INIT_EPD);
showScanningWindow();
timerDelay(TIMER_TICKS_PER_SECOND * 8);
for (uint8_t i = 0; i < 5; i++) {
for (uint8_t c = 0; c < 16; c++) {
addScanResult(11 + c, 2 * i + 60 + c);
}
pr("redraw... ");
draw();
}
pr("\n");
timerDelay(TIMER_TICKS_PER_SECOND * 4);
wdt30s();
pr("AP Found\n");
@@ -99,43 +91,16 @@ void displayLoop() {
wdtDeviceReset();
}
uint8_t showChannelSelect() { // returns 0 if no accesspoints were found
uint8_t __xdata result[sizeof(channelList)];
memset(result, 0, sizeof(result));
showScanningWindow();
drawNoWait();
powerUp(INIT_RADIO);
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (detectAP(channelList[c])) {
if (mLastLqi > result[c]) result[c] = mLastLqi;
pr("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI);
}
}
}
uint8_t __xdata highestLqi = 0;
uint8_t __xdata highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++) {
if (result[c] > highestLqi) {
highestSlot = channelList[c];
highestLqi = result[c];
}
}
powerDown(INIT_RADIO);
epdWaitRdy();
mLastLqi = highestLqi;
return highestSlot;
}
uint8_t channelSelect() { // returns 0 if no accesspoints were found
uint8_t channelSelect(uint8_t rounds) { // returns 0 if no accesspoints were found
powerUp(INIT_RADIO);
uint8_t __xdata result[16];
memset(result, 0, sizeof(result));
for (uint8_t i = 0; i < 2; i++) {
for (uint8_t i = 0; i < rounds; i++) {
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (detectAP(channelList[c])) {
if (mLastLqi > result[c]) result[c] = mLastLqi;
if (rounds > 2) pr("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI);
}
}
}
@@ -215,6 +180,7 @@ void detectButtonOrJig() {
void TagAssociated() {
// associated
bool fastNextCheckin = false;
struct AvailDataInfo *__xdata avail;
// Is there any reason why we should do a long (full) get data request (including reason, status)?
if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) {
@@ -234,7 +200,8 @@ void TagAssociated() {
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM | INIT_EPD);
wdt60s();
drawImageFromEeprom(curImgSlot);
uint8_t lut = getEepromImageDataArgument(curImgSlot) & 0x03;
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EEPROM | INIT_EPD);
} else {
powerUp(INIT_EPD);
@@ -247,6 +214,23 @@ void TagAssociated() {
avail = getAvailDataInfo();
powerDown(INIT_RADIO);
switch (wakeUpReason) {
case WAKEUP_REASON_BUTTON1:
gpioButton1();
fastNextCheckin = true;
break;
case WAKEUP_REASON_BUTTON2:
gpioButton2();
fastNextCheckin = true;
break;
#ifdef ENABLE_GPIO_WAKE
case WAKEUP_REASON_GPIO:
gpioButtonOther();
fastNextCheckin = true;
break;
#endif
}
if (avail != NULL) {
// we got some data!
longDataReqCounter = 0;
@@ -254,14 +238,12 @@ void TagAssociated() {
wakeUpReason = WAKEUP_REASON_TIMED;
}
if (tagSettings.enableTagRoaming) {
uint8_t roamChannel = channelSelect();
uint8_t roamChannel = channelSelect(1);
if (roamChannel) currentChannel = roamChannel;
}
} else {
powerUp(INIT_RADIO);
#ifdef ENABLE_RETURN_DATA
// example code to send data back to the AP. Up to 90 bytes can be sent in one packet
uint8_t __xdata blaat[2] = {0xAB, 0xBA};
@@ -304,11 +286,22 @@ void TagAssociated() {
}
}
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP) {
doSleep(nextCheckInFromAP * 60000UL);
if (fastNextCheckin) {
// do a fast check-in next
fastNextCheckin = false;
doSleep(100UL);
} else {
doSleep(getNextSleep() * 1000UL);
if (nextCheckInFromAP) {
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP & 0x8000) {
doSleep((nextCheckInFromAP & 0x7FFF) * 1000UL);
} else {
doSleep(nextCheckInFromAP * 60000UL);
}
} else {
// sleep determined by algorithm
doSleep(getNextSleep() * 1000UL);
}
}
}
@@ -319,7 +312,7 @@ void TagChanSearch() {
}
// try to find a working channel
currentChannel = channelSelect();
currentChannel = channelSelect(2);
// Check if we should redraw the screen with icons, info screen or screensaver
if ((!currentChannel && !noAPShown && tagSettings.enableNoRFSymbol) ||
@@ -328,9 +321,12 @@ void TagChanSearch() {
powerUp(INIT_EPD);
wdt60s();
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EEPROM);
if (!displayCustomImage(CUSTOM_IMAGE_LOST_CONNECTION)) {
powerUp(INIT_EEPROM);
uint8_t lut = getEepromImageDataArgument(curImgSlot) & 0x03;
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EEPROM);
}
} else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) {
showLongTermSleep();
} else {
@@ -354,6 +350,72 @@ void TagChanSearch() {
}
}
void TagSlideShow() {
currentChannel = 11; // suppress the no-rf image thing
displayCustomImage(CUSTOM_IMAGE_SPLASHSCREEN);
// do a short channel search
currentChannel = channelSelect(2);
pr("Slideshow mode ch: %d\n", currentChannel);
// if we did find an AP, check in once
if (currentChannel) {
doVoltageReading();
struct AvailDataInfo *__xdata avail;
powerUp(INIT_RADIO);
avail = getAvailDataInfo();
if (avail != NULL) {
processAvailDataInfo(avail);
}
}
powerDown(INIT_RADIO);
// suppress the no-rf image
currentChannel = 11;
while (1) {
powerUp(INIT_UART);
wdt60s();
powerUp(INIT_EEPROM);
uint8_t img = findNextSlideshowImage(slideShowCurrentImg);
if (img != slideShowCurrentImg) {
slideShowCurrentImg = img;
uint8_t lut = getEepromImageDataArgument(img) & 0x03;
powerUp(INIT_EPD);
if (SLIDESHOW_FORCE_FULL_REFRESH_EVERY) {
slideShowRefreshCount++;
}
if ((slideShowRefreshCount == SLIDESHOW_FORCE_FULL_REFRESH_EVERY) || (lut == 0)) {
slideShowRefreshCount = 1;
lut = 0;
}
drawImageFromEeprom(img, lut);
powerDown(INIT_EPD | INIT_EEPROM);
} else {
// same image, so don't update the screen; this only happens when there's exactly one slideshow image
powerDown(INIT_EEPROM);
}
switch (tagSettings.customMode) {
case TAG_CUSTOM_SLIDESHOW_FAST:
doSleep(1000UL * SLIDESHOW_INTERVAL_FAST);
break;
case TAG_CUSTOM_SLIDESHOW_MEDIUM:
doSleep(1000UL * SLIDESHOW_INTERVAL_MEDIUM);
break;
case TAG_CUSTOM_SLIDESHOW_SLOW:
doSleep(1000UL * SLIDESHOW_INTERVAL_SLOW);
break;
case TAG_CUSTOM_SLIDESHOW_GLACIAL:
doSleep(1000UL * SLIDESHOW_INTERVAL_GLACIAL);
break;
}
pr("wake...\n");
}
}
void executeCommand(uint8_t cmd) {
switch (cmd) {
case CMD_DO_REBOOT:
@@ -364,7 +426,7 @@ void executeCommand(uint8_t cmd) {
writeSettings();
break;
case CMD_DO_SCAN:
currentChannel = channelSelect();
currentChannel = channelSelect(4);
break;
case CMD_DO_DEEPSLEEP:
powerUp(INIT_EPD);
@@ -374,6 +436,61 @@ void executeCommand(uint8_t cmd) {
doSleep(-1);
}
break;
case CMD_ERASE_EEPROM_IMAGES:
powerUp(INIT_EEPROM);
eraseImageBlocks();
powerDown(INIT_EEPROM);
break;
case CMD_ENTER_SLIDESHOW_FAST:
powerUp(INIT_EEPROM);
if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) {
powerDown(INIT_EEPROM);
return;
}
powerDown(INIT_EEPROM);
tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_FAST;
writeSettings();
wdtDeviceReset();
break;
case CMD_ENTER_SLIDESHOW_MEDIUM:
powerUp(INIT_EEPROM);
if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) {
powerDown(INIT_EEPROM);
return;
}
powerDown(INIT_EEPROM);
tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_MEDIUM;
writeSettings();
wdtDeviceReset();
break;
case CMD_ENTER_SLIDESHOW_SLOW:
powerUp(INIT_EEPROM);
if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) {
powerDown(INIT_EEPROM);
return;
}
powerDown(INIT_EEPROM);
tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_SLOW;
writeSettings();
wdtDeviceReset();
break;
case CMD_ENTER_SLIDESHOW_GLACIAL:
powerUp(INIT_EEPROM);
if (findSlotDataTypeArg(CUSTOM_IMAGE_SLIDESHOW << 3) == 0xFF) {
powerDown(INIT_EEPROM);
return;
}
powerDown(INIT_EEPROM);
tagSettings.customMode = TAG_CUSTOM_SLIDESHOW_GLACIAL;
writeSettings();
wdtDeviceReset();
break;
case CMD_ENTER_NORMAL_MODE:
tagSettings.customMode = TAG_CUSTOM_MODE_NONE;
writeSettings();
wdtDeviceReset();
break;
}
}
@@ -399,6 +516,17 @@ void main() {
// get the highest slot number, number of slots
initializeProto();
switch (tagSettings.customMode) {
case TAG_CUSTOM_SLIDESHOW_FAST:
case TAG_CUSTOM_SLIDESHOW_MEDIUM:
case TAG_CUSTOM_SLIDESHOW_SLOW:
case TAG_CUSTOM_SLIDESHOW_GLACIAL:
TagSlideShow();
break;
default:
break;
}
if (tagSettings.enableFastBoot) {
// Fastboot
pr("Doing fast boot\n");
@@ -406,7 +534,7 @@ void main() {
if (tagSettings.fixedChannel) {
currentChannel = tagSettings.fixedChannel;
} else {
currentChannel = channelSelect();
currentChannel = channelSelect(2);
}
} else {
// Normal boot/startup
@@ -426,9 +554,9 @@ void main() {
detectButtonOrJig();
// show the splashscreen
pr("EPD: First powerup\n");
powerUp(INIT_EPD);
currentChannel = 11;
showSplashScreen();
currentChannel = 0;
// we've now displayed something on the screen; for the SSD1619, we are now aware of the lut-size
#ifdef EPD_SSD1619
@@ -443,28 +571,25 @@ void main() {
writeSettings();
// scan for channels
powerUp(INIT_EPD);
wdt30s();
if (tagSettings.fixedChannel) {
currentChannel = tagSettings.fixedChannel;
} else {
currentChannel = showChannelSelect();
currentChannel = channelSelect(4);
}
}
// end of the fastboot option split
wdt10s();
powerUp(INIT_EPD);
if (currentChannel) {
showAPFound();
initPowerSaving(INTERVAL_BASE);
powerDown(INIT_EPD | INIT_UART);
currentTagMode = TAG_MODE_ASSOCIATED;
doSleep(5000UL);
} else {
showNoAP();
initPowerSaving(INTERVAL_AT_MAX_ATTEMPTS);
powerDown(INIT_EPD | INIT_UART);
currentTagMode = TAG_MODE_CHANSEARCH;
doSleep(120000UL);
}

View File

@@ -292,16 +292,34 @@ void doSleep(const uint32_t __xdata t) {
P1DIR |= (1 << 0);
P1PULL |= (1 << 0);
P1LVLSEL |= (1 << 0);
P1INTEN = (1 << 0);
P1INTEN |= (1 << 0);
P1CHSTA &= ~(1 << 0);
// Button setup on RXD pin 0.7 (input pullup)
P0FUNC &= ~(1 << 7);
P0DIR |= (1 << 7);
P0PULL |= (1 << 7);
P0LVLSEL |= (1 << 7);
P0INTEN |= (1 << 7);
P0CHSTA &= ~(1 << 7);
}
#ifdef ENABLE_GPIO_WAKE
// enable wake on pin 0.2 (MISO)
P0FUNC &= ~(1 << 3);
P0DIR |= (1 << 3);
P0PULL |= (1 << 3);
P0LVLSEL |= (1 << 3);
P0INTEN |= (1 << 3);
P0CHSTA &= ~(1 << 3);
#endif
if (capabilities & CAPABILITY_NFC_WAKE) {
P1FUNC &= ~(1 << 3);
P1DIR |= (1 << 3);
P1PULL |= (1 << 3);
P1LVLSEL |= (1 << 3);
P1INTEN = (1 << 3);
P1INTEN |= (1 << 3);
P1CHSTA &= ~(1 << 3);
}
@@ -313,15 +331,29 @@ void doSleep(const uint32_t __xdata t) {
// sleepy time
sleepForMsec(t);
P1INTEN = 0;
P0INTEN = 0;
if ((P1CHSTA & (1 << 0)) && (capabilities & CAPABILITY_HAS_WAKE_BUTTON)) {
wakeUpReason = WAKEUP_REASON_GPIO;
wakeUpReason = WAKEUP_REASON_BUTTON1;
P1CHSTA &= ~(1 << 0);
}
if ((P0CHSTA & (1 << 7)) && (capabilities & CAPABILITY_HAS_WAKE_BUTTON)) {
wakeUpReason = WAKEUP_REASON_BUTTON2;
P0CHSTA &= ~(1 << 7);
}
if ((P1CHSTA & (1 << 3)) && (capabilities & CAPABILITY_NFC_WAKE)) {
wakeUpReason = WAKEUP_REASON_NFC;
P1CHSTA &= ~(1 << 3);
}
#ifdef ENABLE_GPIO_WAKE
if (P0CHSTA & (1 << 3)) {
wakeUpReason = WAKEUP_REASON_GPIO;
P0CHSTA &= ~(1 << 3);
}
#endif
}
void doVoltageReading() {

View File

@@ -40,6 +40,13 @@
#define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day)
#define INTERVAL_3_TIME 86400UL // Finally, try every day
// slideshow power settings
#define SLIDESHOW_FORCE_FULL_REFRESH_EVERY 16 // force a full refresh every X screen draws
#define SLIDESHOW_INTERVAL_FAST 15 // interval for 'fast'
#define SLIDESHOW_INTERVAL_MEDIUM 60
#define SLIDESHOW_INTERVAL_SLOW 300
#define SLIDESHOW_INTERVAL_GLACIAL 1800
extern uint8_t checkButtonOrJig();
extern void setupPortsInitial();

View File

@@ -3,11 +3,11 @@
#include <stdint.h>
#define FW_VERSION 21 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-RET" // suffix, like -RC1 or whatever.
#define FW_VERSION 22 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-BUT" // suffix, like -RC1 or whatever.
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
// #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket
#define ENABLE_GPIO_WAKE // uncomment to enable GPIO wake
// #define ENABLE_RETURN_DATA // enables the tag to send blocks of data back. Enabling this costs about 4 IRAM bytes
#define SETTINGS_STRUCT_VERSION 0x01

View File

@@ -28,17 +28,17 @@
// download-stuff
uint8_t __xdata blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
static struct blockRequest __xdata curBlock = {0}; // used by the block-requester, contains the next request that we'll send
static struct AvailDataInfo __xdata curDataInfo = {0}; // last 'AvailDataInfo' we received from the AP
static bool __xdata requestPartialBlock = false; // if we should ask the AP to get this block from the host or not
static struct blockRequest __xdata curBlock = {0}; // used by the block-requester, contains the next request that we'll send
static uint8_t __xdata curDispDataVer[8] = {0};
static struct AvailDataInfo __xdata xferDataInfo = {0}; // holds the AvailDataInfo during the transfer
static bool __xdata requestPartialBlock = false; // if we should ask the AP to get this block from the host or not
#define BLOCK_TRANSFER_ATTEMPTS 5
uint8_t __xdata prevImgSlot = 0xFF;
uint8_t __xdata curImgSlot = 0xFF;
static uint32_t __xdata curHighSlotId = 0;
static uint8_t __xdata nextImgSlot = 0;
static uint8_t xferImgSlot = 0xFF; // holds current transfer slot in progress
uint8_t __xdata curImgSlot = 0xFF; // currently shown image
static uint32_t __xdata curHighSlotId = 0; // current highest ID, will be incremented before getting written to a new slot
static uint8_t __xdata nextImgSlot = 0; // next slot in sequence for writing
static uint8_t __xdata imgSlots = 0;
uint8_t __xdata drawWithLut = 0;
// stuff we need to keep track of related to the network/AP
uint8_t __xdata APmac[8] = {0};
@@ -51,6 +51,9 @@ uint8_t __xdata currentChannel = 0;
static uint8_t __xdata inBuffer[128] = {0};
static uint8_t __xdata outBuffer[128] = {0};
// other stuff we shouldn't have to put here...
static uint32_t __xdata markerValid = EEPROM_IMG_VALID;
extern void executeCommand(uint8_t cmd); // this is defined in main.c
// tools
@@ -469,10 +472,9 @@ static void getNumSlots() {
} else
imgSlots = nSlots;
}
static uint8_t findSlot(const uint8_t *__xdata ver) {
static uint8_t findSlotVer(const uint8_t *ver) {
// return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere
uint32_t __xdata markerValid = EEPROM_IMG_VALID;
for (uint8_t __xdata c = 0; c < imgSlots; c++) {
for (uint8_t c = 0; c < imgSlots; c++) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (xMemEqual4(&eih->validMarker, &markerValid)) {
@@ -483,6 +485,42 @@ static uint8_t findSlot(const uint8_t *__xdata ver) {
}
return 0xFF;
}
// making this reentrant saves one byte of idata...
uint8_t __xdata findSlotDataTypeArg(uint8_t arg) __reentrant {
arg &= (0xF8); // unmatch with the 'preload' bit and LUT bits
for (uint8_t c = 0; c < imgSlots; c++) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (xMemEqual4(&eih->validMarker, &markerValid)) {
if ((eih->argument & 0xF8) == arg) {
return c;
}
}
}
return 0xFF;
}
uint8_t getEepromImageDataArgument(const uint8_t slot) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(slot), eih, sizeof(struct EepromImageHeader));
return eih->argument;
}
uint8_t __xdata findNextSlideshowImage(uint8_t start) __reentrant {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
uint8_t c = start;
while (1) {
c++;
if (c > imgSlots) c = 0;
if (c == start) return c;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (xMemEqual4(&eih->validMarker, &markerValid)) {
if ((eih->argument & 0xF8) == (CUSTOM_IMAGE_SLIDESHOW << 3)) {
return c;
}
}
}
}
static void eraseUpdateBlock() {
eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN / EEPROM_ERZ_SECTOR_SZ);
}
@@ -500,13 +538,16 @@ static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) {
if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length))
pr("EEPROM write failed\n");
}
void drawImageFromEeprom(const uint8_t imgSlot) {
drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut);
drawWithLut = 0; // default back to the regular ol' stock/OTP LUT
void eraseImageBlocks() {
for (uint8_t c = 0; c < imgSlots; c++) {
eraseImageBlock(c);
}
}
void drawImageFromEeprom(const uint8_t imgSlot, uint8_t lut) {
drawImageAtAddress(getAddressForSlot(imgSlot), lut);
}
static uint32_t getHighSlotId() {
uint32_t temp = 0;
uint32_t __xdata markerValid = EEPROM_IMG_VALID;
for (uint8_t __xdata c = 0; c < imgSlots; c++) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
@@ -625,25 +666,25 @@ static bool getDataBlock(const uint16_t blockSize) {
uint16_t __xdata dataRequestSize = 0;
static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) {
// check if we already started the transfer of this information & haven't completed it
if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8) && curDataInfo.dataSize) {
if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8) && xferDataInfo.dataSize) {
// looks like we did. We'll carry on where we left off.
} else {
// start, or restart the transfer from 0. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer
curBlock.blockId = 0;
xMemCopy8(&(curBlock.ver), &(avail->dataVer));
curBlock.type = avail->dataType;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
eraseUpdateBlock();
}
while (curDataInfo.dataSize) {
while (xferDataInfo.dataSize) {
wdt10s();
if (curDataInfo.dataSize > BLOCK_DATA_SIZE) {
if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
} else {
// only one block remains
dataRequestSize = curDataInfo.dataSize;
dataRequestSize = xferDataInfo.dataSize;
}
if (getDataBlock(dataRequestSize)) {
// succesfully downloaded datablock, save to eeprom
@@ -651,7 +692,7 @@ static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) {
saveUpdateBlockData(curBlock.blockId);
powerDown(INIT_EEPROM);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
xferDataInfo.dataSize -= dataRequestSize;
} else {
// failed to get the block we wanted, we'll stop for now, maybe resume later
return false;
@@ -664,21 +705,42 @@ static bool downloadFWUpdate(const struct AvailDataInfo *__xdata avail) {
uint16_t __xdata imageSize = 0;
static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail) {
// check if we already started the transfer of this information & haven't completed it
if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8) && curDataInfo.dataSize) {
if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8) &&
(xferDataInfo.dataTypeArgument == avail->dataTypeArgument) &&
xferDataInfo.dataSize) {
// looks like we did. We'll carry on where we left off.
pr("restarting image download");
curImgSlot = nextImgSlot;
} else {
// go to the next image slot
nextImgSlot++;
if (nextImgSlot >= imgSlots) nextImgSlot = 0;
curImgSlot = nextImgSlot;
pr("Saving to image slot %d\n", curImgSlot);
drawWithLut = avail->dataTypeArgument;
// new transfer
powerUp(INIT_EEPROM);
// go to the next image slot
uint8_t startingSlot = nextImgSlot;
while (1) {
nextImgSlot++;
if (nextImgSlot >= imgSlots) nextImgSlot = 0;
if (nextImgSlot == startingSlot) {
powerDown(INIT_EEPROM);
pr("No slots available. Too many images in the slideshow?\n");
return true;
}
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(nextImgSlot), eih, sizeof(struct EepromImageHeader));
// check if the marker is indeed valid
if (xMemEqual4(&eih->validMarker, &markerValid)) {
struct imageDataTypeArgStruct *eepromDataArgument = (struct imageDataTypeArgStruct *)&(eih->argument);
// normal type, we can overwrite this
if (eepromDataArgument->specialType == 0x00) break;
} else {
// bullshit marker, so safe to overwrite
break;
}
}
xferImgSlot = nextImgSlot;
uint8_t __xdata attempt = 5;
while (attempt--) {
if (eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ)) goto eraseSuccess;
if (eepromErase(getAddressForSlot(xferImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ)) goto eraseSuccess;
}
eepromFail:
powerDown(INIT_RADIO);
@@ -688,35 +750,36 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail)
doSleep(-1);
wdtDeviceReset();
eraseSuccess:
pr("new download, writing to slot %d\n", curImgSlot);
powerDown(INIT_EEPROM);
pr("new download, writing to slot %d\n", xferImgSlot);
// start, or restart the transfer. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer
curBlock.blockId = 0;
xMemCopy8(&(curBlock.ver), &(avail->dataVer));
curBlock.type = avail->dataType;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
imageSize = curDataInfo.dataSize;
xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
imageSize = xferDataInfo.dataSize;
}
while (curDataInfo.dataSize) {
while (xferDataInfo.dataSize) {
wdt10s();
if (curDataInfo.dataSize > BLOCK_DATA_SIZE) {
if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
} else {
// only one block remains
dataRequestSize = curDataInfo.dataSize;
dataRequestSize = xferDataInfo.dataSize;
}
if (getDataBlock(dataRequestSize)) {
// succesfully downloaded datablock, save to eeprom
powerUp(INIT_EEPROM);
#ifdef DEBUGBLOCKS
pr("Saving block %d to slot %d\n", curBlock.blockId, curImgSlot);
pr("Saving block %d to slot %d\n", curBlock.blockId, xferImgSlot);
#endif
saveImgBlockData(curImgSlot, curBlock.blockId);
saveImgBlockData(xferImgSlot, curBlock.blockId);
powerDown(INIT_EEPROM);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
xferDataInfo.dataSize -= dataRequestSize;
} else {
// failed to get the block we wanted, we'll stop for now, probably resume later
return false;
@@ -726,111 +789,138 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail)
// borrow the blockXferBuffer temporarily
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
xMemCopy8(&eih->version, &curDataInfo.dataVer);
xMemCopy8(&eih->version, &xferDataInfo.dataVer);
eih->validMarker = EEPROM_IMG_VALID;
eih->id = ++curHighSlotId;
eih->size = imageSize;
eih->dataType = curDataInfo.dataType;
eih->dataType = xferDataInfo.dataType;
eih->argument = xferDataInfo.dataTypeArgument;
#ifdef DEBUGBLOCKS
pr("Now writing datatype 0x%02X to slot %d\n", curDataInfo.dataType, curImgSlot);
pr("Now writing datatype 0x%02X to slot %d\n", xferDataInfo.dataType, xferImgSlot);
#endif
powerUp(INIT_EEPROM);
eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader));
eepromWrite(getAddressForSlot(xferImgSlot), eih, sizeof(struct EepromImageHeader));
powerDown(INIT_EEPROM);
return true;
}
bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
switch (avail->dataType) {
#if (SCREEN_WIDTH == 152)
// the 1.54" screen is pretty small, we can write an entire 1bpp image from the block transfer buffer directly to the EPD buffer
case DATATYPE_IMG_RAW_1BPP_DIRECT:
pr("Direct draw image received\n");
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
// we've downloaded this already, we're guessing it's already displayed
pr("currently shown image, send xfc\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
}
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
if (avail->dataSize > 4096) avail->dataSize = 4096;
inline bool processImageDataAvail(struct AvailDataInfo *__xdata avail) {
struct imageDataTypeArgStruct arg;
*((uint8_t *)arg) = avail->dataTypeArgument;
if (getDataBlock(avail->dataSize)) {
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
if (arg.preloadImage) {
pr("Preloading image with type 0x%02X from arg 0x%02X\n", arg.specialType, avail->dataTypeArgument);
powerUp(INIT_EEPROM);
switch (arg.specialType) {
// check if a slot with this argument is already set; if so, erase. Only one of each arg type should exist
default: {
uint8_t slot = findSlotDataTypeArg(avail->dataTypeArgument);
if (slot != 0xFF) {
eepromErase(getAddressForSlot(slot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ);
}
} break;
// regular image preload, there can be multiple of this type in the EEPROM
case CUSTOM_IMAGE_NOCUSTOM: {
// check if a version of this already exists
uint8_t slot = findSlotVer(&(avail->dataVer));
if (slot != 0xFF) {
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
}
} break;
case CUSTOM_IMAGE_SLIDESHOW:
break;
}
powerDown(INIT_EEPROM);
curDataInfo.dataSize = 0; // mark as transfer not pending
powerUp(INIT_EPD);
drawImageFromBuffer(blockXferBuffer, drawWithLut);
powerDown(INIT_EPD);
drawWithLut = 0; // default back to the regular ol' stock/OTP LUT
return true;
}
pr("downloading preload image...\n");
if (downloadImageDataToEEPROM(avail)) {
// sets xferImgSlot to the right slot
pr("preload complete!\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
} else {
return false;
break;
#endif
case DATATYPE_IMG_BMP:
case DATATYPE_IMG_DIFF:
case DATATYPE_IMG_RAW_1BPP:
case DATATYPE_IMG_RAW_2BPP:
// check if this download is currently displayed or active
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
// we've downloaded this already, we're guessing it's already displayed
pr("currently shown image, send xfc\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
}
}
// check if we've seen this version before
} else {
// check if we're currently displaying this data payload
if (xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata)curDispDataVer, 8)) {
// currently displayed, not doing anything except for sending an XFC
pr("currently shown image, send xfc\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
return true;
} else {
// currently not displayed
// try to find the data in the SPI EEPROM
powerUp(INIT_EEPROM);
curImgSlot = findSlot(&(avail->dataVer));
uint8_t findImgSlot = findSlotVer(&(avail->dataVer));
powerDown(INIT_EEPROM);
if (curImgSlot != 0xFF) {
// Is this image already in a slot somewhere
if (findImgSlot != 0xFF) {
// found a (complete)valid image slot for this version
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
pr("already seen, drawing from eeprom slot %d\n", curImgSlot);
// mark as completed and draw from EEPROM
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
curDataInfo.dataSize = 0; // mark as transfer not pending
xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
xferDataInfo.dataSize = 0; // mark as transfer not pending
drawWithLut = avail->dataTypeArgument;
wdt60s();
curImgSlot = findImgSlot;
powerUp(INIT_EPD | INIT_EEPROM);
drawImageFromEeprom(curImgSlot);
drawImageFromEeprom(findImgSlot, arg.lut);
powerDown(INIT_EPD | INIT_EEPROM);
return true;
} else {
// not found in cache, prepare to download
pr("downloading to imgslot\n");
drawWithLut = avail->dataTypeArgument;
powerUp(INIT_EEPROM);
pr("downloading image...\n");
if (downloadImageDataToEEPROM(avail)) {
// sets xferImgSlot to the right slot
pr("download complete!\n");
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
// not preload, draw now
wdt60s();
curImgSlot = xferImgSlot;
powerUp(INIT_EPD | INIT_EEPROM);
drawImageFromEeprom(curImgSlot);
drawImageFromEeprom(xferImgSlot, arg.lut);
powerDown(INIT_EPD | INIT_EEPROM);
return true;
} else {
powerDown(INIT_EEPROM);
return false;
}
}
// keep track on what is currently displayed
xMemCopy8(curDispDataVer, xferDataInfo.dataVer);
return true;
}
}
}
bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
switch (avail->dataType) {
case DATATYPE_IMG_BMP:
case DATATYPE_IMG_DIFF:
case DATATYPE_IMG_RAW_1BPP:
case DATATYPE_IMG_RAW_2BPP:
return processImageDataAvail(avail);
break;
case DATATYPE_FW_UPDATE:
powerUp(INIT_EEPROM);
@@ -866,6 +956,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
}
pr("NFC URL received\n");
/*
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
// we've already downloaded this NFC data, disregard and send XFC
pr("this was the same as the last transfer, disregard\n");
@@ -899,8 +990,9 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
}
return false;
break;
*/
case DATATYPE_TAG_CONFIG_DATA:
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
if (xferDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8)) {
pr("this was the same as the last transfer, disregard\n");
powerUp(INIT_RADIO);
sendXferComplete();
@@ -910,10 +1002,10 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
curBlock.blockId = 0;
xMemCopy8(&(curBlock.ver), &(avail->dataVer));
curBlock.type = avail->dataType;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
wdt10s();
if (getDataBlock(avail->dataSize)) {
curDataInfo.dataSize = 0; // mark as transfer not pending
xferDataInfo.dataSize = 0; // mark as transfer not pending
loadSettingsFromBuffer(sizeof(struct blockData) + blockXferBuffer);
powerUp(INIT_RADIO);
sendXferComplete();
@@ -943,7 +1035,7 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
}
#ifdef EPD_SSD1619
pr("OTA LUT received\n");
if (curDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & curDataInfo.dataVer, 8)) {
if (xferDataInfo.dataSize == 0 && xMemEqual((const void *__xdata) & avail->dataVer, (const void *__xdata) & xferDataInfo.dataVer, 8)) {
pr("this was the same as the last transfer, disregard\n");
powerUp(INIT_RADIO);
sendXferComplete();
@@ -953,10 +1045,10 @@ bool processAvailDataInfo(struct AvailDataInfo *__xdata avail) {
curBlock.blockId = 0;
xMemCopy8(&(curBlock.ver), &(avail->dataVer));
curBlock.type = avail->dataType;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
xMemCopyShort(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
wdt10s();
if (getDataBlock(avail->dataSize)) {
curDataInfo.dataSize = 0; // mark as transfer not pending
xferDataInfo.dataSize = 0; // mark as transfer not pending
memcpy(customLUT, sizeof(struct blockData) + blockXferBuffer, 6 + (dispLutSize * 10));
powerUp(INIT_RADIO);
sendXferComplete();

View File

@@ -10,8 +10,8 @@ extern uint8_t __xdata APmac[];
extern uint8_t __xdata curImgSlot;
extern void setupRadio(void);
extern void killRadio(void);
//extern void setupRadio(void);
//extern void killRadio(void);
#ifdef ENABLE_RETURN_DATA
@@ -19,9 +19,14 @@ extern bool sendTagReturnData(uint8_t __xdata *data, uint8_t len, uint8_t type);
#endif
void dump(const uint8_t *__xdata a, const uint16_t __xdata l);
extern uint8_t __xdata findSlotDataTypeArg(uint8_t arg) __reentrant;
uint8_t __xdata findNextSlideshowImage(uint8_t start) __reentrant;
uint8_t getEepromImageDataArgument(const uint8_t slot);
extern struct AvailDataInfo *__xdata getAvailDataInfo();
extern struct AvailDataInfo *__xdata getShortAvailDataInfo();
extern void drawImageFromEeprom(const uint8_t imgSlot);
extern void drawImageFromEeprom(const uint8_t imgSlot, uint8_t lut);
void eraseImageBlocks();
extern bool processAvailDataInfo(struct AvailDataInfo *__xdata avail);
extern void initializeProto();
extern uint8_t detectAP(const uint8_t channel);

View File

@@ -52,7 +52,7 @@ void addCapabilities() {
}
void addOverlay() {
if ((currentChannel == 0)&&(tagSettings.enableNoRFSymbol)) {
if ((currentChannel == 0) && (tagSettings.enableNoRFSymbol)) {
#if (SCREEN_WIDTH == 152)
loadRawBitmap(ant, SCREEN_WIDTH - 16, 0, EPD_COLOR_BLACK);
loadRawBitmap(cross, SCREEN_WIDTH - 8, 7, EPD_COLOR_RED);
@@ -83,6 +83,7 @@ void addOverlay() {
}
void afterFlashScreenSaver() {
if (displayCustomImage(CUSTOM_IMAGE_LONGTERMSLEEP)) return;
selectLUT(EPD_LUT_DEFAULT);
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
@@ -92,7 +93,6 @@ void afterFlashScreenSaver() {
epdpr("OpenEPaperLink");
epdPrintEnd();
epdPrintBegin(100, 32, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("v%d.%d.%d", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10));
epdPrintEnd();
@@ -172,7 +172,7 @@ void afterFlashScreenSaver() {
epdpr("v%d.%d.%d", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10));
epdPrintEnd();
epdPrintBegin(10, 48, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdPrintBegin(10, 48, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("I'm fast asleep... UwU To wake me:");
epdPrintEnd();
@@ -201,6 +201,8 @@ void afterFlashScreenSaver() {
}
void showSplashScreen() {
if (displayCustomImage(CUSTOM_IMAGE_SPLASHSCREEN)) return;
powerUp(INIT_EPD);
selectLUT(EPD_LUT_NO_REPEATS);
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
@@ -298,6 +300,7 @@ void showSplashScreen() {
#endif
drawWithSleep();
powerUp(INIT_EPD);
}
void showApplyUpdate() {
@@ -322,60 +325,10 @@ void showApplyUpdate() {
drawNoWait();
}
uint8_t __xdata resultcounter = 0;
void showScanningWindow() {
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
selectLUT(EPD_LUT_FAST_NO_REDS);
clearScreen();
#if (SCREEN_WIDTH == 128) // 2.9"
epdPrintBegin(2, 275, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Scanning for APs");
epdPrintEnd();
// epdPrintBegin(40, 262, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_RED);
// epdpr("Channel - Quality");
// epdPrintEnd();
loadRawBitmap(receive, 36, 24, EPD_COLOR_BLACK);
#endif
#if (SCREEN_WIDTH == 152) // 1.54"
loadRawBitmap(receive, 96, 28, EPD_COLOR_BLACK);
epdPrintBegin(3, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Scanning...");
epdPrintEnd();
#endif
#if (SCREEN_WIDTH == 400) // 4.2"
epdPrintBegin(2, 2, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Scanning for APs");
epdPrintEnd();
// epdPrintBegin(2, 40, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
// epdpr("Channel - Quality");
// epdPrintEnd();
loadRawBitmap(receive, 320, 125, EPD_COLOR_BLACK);
#endif
draw();
selectLUT(EPD_LUT_FAST);
resultcounter = 0;
}
void addScanResult(uint8_t channel, uint8_t lqi) {
if (channel == 11) resultcounter = 0;
#if (SCREEN_WIDTH == 128) // 2.9"
epdPrintBegin(56 + ((resultcounter % 4) * 16), 282 - (47 * (resultcounter / 4)), EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
#endif
#if (SCREEN_WIDTH == 152) // 1.54"
epdPrintBegin(4 + (47 * (resultcounter / 8)), 31 + (15 * (resultcounter % 8)), EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
#endif
#if (SCREEN_WIDTH == 400) // 4.2"
epdPrintBegin(4 + (47 * (resultcounter / 8)), 58 + (15 * (resultcounter % 8)), EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
#endif
epdpr("%d-%d", channel, lqi);
epdPrintEnd();
resultcounter++;
}
void showAPFound() {
if (displayCustomImage(CUSTOM_IMAGE_APFOUND)) return;
powerUp(INIT_EPD | INIT_EEPROM);
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
selectLUT(1);
@@ -479,9 +432,14 @@ void showAPFound() {
#endif
addOverlay();
drawWithSleep();
powerDown(INIT_EPD | INIT_EEPROM);
}
void showNoAP() {
if (displayCustomImage(CUSTOM_IMAGE_NOAPFOUND)) return;
powerUp(INIT_EPD | INIT_EEPROM);
selectLUT(EPD_LUT_NO_REPEATS);
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
clearScreen();
@@ -525,9 +483,11 @@ void showNoAP() {
#endif
addOverlay();
drawWithSleep();
powerDown(INIT_EPD | INIT_EEPROM);
}
void showLongTermSleep() {
if (displayCustomImage(CUSTOM_IMAGE_LONGTERMSLEEP)) return;
selectLUT(EPD_LUT_NO_REPEATS);
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
clearScreen();
@@ -616,4 +576,71 @@ void showNoMAC() {
epdPrintEnd();
#endif
drawWithSleep();
}
}
bool displayCustomImage(uint8_t imagetype) {
powerUp(INIT_EEPROM);
uint8_t slot = findSlotDataTypeArg(imagetype << 3);
if (slot != 0xFF) {
// found a slot for gpio button 1
uint8_t lut = getEepromImageDataArgument(slot);
lut &= 0x03;
powerUp(INIT_EPD);
drawImageFromEeprom(slot, lut);
powerDown(INIT_EPD | INIT_EEPROM);
return true;
} else {
powerDown(INIT_EEPROM);
}
return false;
}
void gpioButton1() {
if (displayCustomImage(CUSTOM_IMAGE_BUTTON1)) {
sleepForMsec(2000);
// if something else was previously on the display, draw that
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
uint8_t lut = getEepromImageDataArgument(curImgSlot);
lut &= 0x03;
powerUp(INIT_EPD);
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EPD | INIT_EEPROM);
}
}
}
void gpioButton2() {
if (displayCustomImage(CUSTOM_IMAGE_BUTTON1)) {
sleepForMsec(2000);
// if something else was previously on the display, draw that
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
uint8_t lut = getEepromImageDataArgument(curImgSlot);
lut &= 0x03;
powerUp(INIT_EPD);
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EPD | INIT_EEPROM);
}
}
}
#ifdef ENABLE_GPIO_WAKE
void gpioButtonOther() {
if (displayCustomImage(CUSTOM_IMAGE_GPIO)) {
sleepForMsec(2000);
// if something else was previously on the display, draw that
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
uint8_t lut = getEepromImageDataArgument(curImgSlot);
lut &= 0x03;
powerUp(INIT_EPD);
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EPD | INIT_EEPROM);
}
}
}
#endif

View File

@@ -4,17 +4,22 @@
void addOverlay();
bool displayCustomImage(uint8_t imagetype);
void afterFlashScreenSaver();
void showSplashScreen();
void showApplyUpdate();
void showScanningWindow();
void addScanResult(uint8_t channel, uint8_t lqi);
void showAPFound();
void showNoAP();
void showLongTermSleep();
void showNoEEPROM();
void showNoMAC();
void gpioButton1();
void gpioButton2();
void gpioButtonOther();
extern const uint16_t __code fwVersion;
extern const char __code fwVersionSuffix[];
extern bool __xdata lowBatteryShown;

0
zbs243_shared/eeprom.c Normal file → Executable file
View File

49
zbs243_shared/eeprom.h Normal file → Executable file
View File

@@ -4,10 +4,10 @@
#include <stdbool.h>
#include <stdint.h>
#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment
#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment
#define EEPROM_WRITE_PAGE_SZ 256 // max write size & alignment
#define EEPROM_ERZ_SECTOR_SZ 4096 // erase size and alignment
//device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that
// device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that
__bit eepromInit(void);
void eepromOtpModeEnter(void);
@@ -27,25 +27,40 @@ void eepromDeepPowerDown(void);
#pragma callee_saves eepromGetSize
uint32_t eepromGetSize(void);
//this is for firmware update use
void eepromReadStart(uint32_t addr) __reentrant;
// this is for firmware update use
void eepromReadStart(uint32_t addr) __reentrant;
// structures
#define EEPROM_IMG_INPROGRESS (0x7fffffffUL)
//#define EEPROM_IMG_VALID (0x494d4721UL)
#define EEPROM_IMG_VALID (0x474d4721UL)
//structures
#define EEPROM_IMG_INPROGRESS (0x7fffffffUL)
#define EEPROM_IMG_VALID (0x494d4721UL)
#include "board.h"
struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint8_t dataType;
uint32_t id;
//image data here
//we pre-erase so progress can be calculated by finding the first non-0xff byte
struct EepromImageHeader { // each image space is 0x17000 bytes, we have space for ten of them
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint8_t dataType;
uint32_t id;
uint8_t argument;
// image data here
// we pre-erase so progress can be calculated by finding the first non-0xff byte
};
#define CUSTOM_IMAGE_NOCUSTOM 0x00 // regular image type
#define CUSTOM_IMAGE_SPLASHSCREEN 0x01 // will show at first boot/powerup
#define CUSTOM_IMAGE_LOST_CONNECTION 0x02 // this image will be shown (if it exists on the tag) if the tag looses its connection
#define CUSTOM_IMAGE_APFOUND 0x03 // this image will be shown during bootup if an AP was found
#define CUSTOM_IMAGE_NOAPFOUND 0x04 // shown if during bootup no AP was found
// UNUSED: 0x05-0x0F
#define CUSTOM_IMAGE_SLIDESHOW 0x0F // image is part of a slideshow
#define CUSTOM_IMAGE_BUTTON1 0x10
#define CUSTOM_IMAGE_BUTTON2 0x11
// UNUSED: 0x12 to 0x1C
#define CUSTOM_IMAGE_GPIO 0x1D
#define CUSTOM_IMAGE_NFC_WAKE 0x1E
#endif