Merge pull request #16 from jjwbruijn/refactored-download-rawimages

Refactored download rawimages
This commit is contained in:
Jelmer
2023-02-17 14:53:09 +01:00
committed by GitHub
20 changed files with 59337 additions and 357 deletions

Binary file not shown.

BIN
fw_dumps/027C4B633B1A.bin Normal file

Binary file not shown.

58816
fw_dumps/027C4B633B1A.bin.html Normal file

File diff suppressed because it is too large Load Diff

BIN
fw_dumps/027C4D453B18.bin Normal file

Binary file not shown.

BIN
fw_dumps/02A901443416.bin Normal file

Binary file not shown.

BIN
fw_dumps/02BE4D273B12.bin Normal file

Binary file not shown.

View File

@@ -8,10 +8,11 @@
#include "eeprom.h"
#include "epd.h"
#include "printf.h"
#include "proto.h"
#include "screen.h"
#include "timer.h"
#include "userinterface.h" // for addIcons
#include "userinterface.h" // for addIcons
#define COMPRESSION_BITPACKED_3x5_to_7 0x62700357 // 3 pixels of 5 possible colors in 7 bits
#define COMPRESSION_BITPACKED_5x3_to_8 0x62700538 // 5 pixels of 3 possible colors in 8 bits
#define COMPRESSION_BITPACKED_3x6_to_8 0x62700368 // 3 pixels of 6 possible colors in 8 bits
@@ -335,31 +336,88 @@ void ByteDecode(uint8_t byte) {
}
void drawImageAtAddress(uint32_t addr, uint8_t lut) {
uint32_t __xdata clutAddr;
pr("sending to EPD - ");
clutAddr = drawPrvParseHeader(addr);
if (!clutAddr)
return;
drawPrvLoadAndMapClut(clutAddr);
struct EepromImageHeader* __xdata eih = (struct EepromImageHeader*)mClutMap;
eepromRead(addr, mClutMap, sizeof(struct EepromImageHeader));
epdSetup();
if(lut)selectLUT(lut);
mPassNo = 0;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();
mPassNo++;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_RED);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();
switch (eih->dataType) {
case DATATYPE_IMG_RAW_1BPP:
pr("Doing raw 1bpp\n");
epdSetup();
if (lut) selectLUT(lut);
beginFullscreenImage();
clearScreen();
beginWriteFramebuffer(EPD_COLOR_BLACK);
epdSelect();
for (uint16_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++) {
if (c % 256 == 0) {
epdDeselect();
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
epdSelect();
}
epdSend(mClutMap[c % 256]);
}
epdDeselect();
endWriteFramebuffer();
break;
case DATATYPE_IMG_RAW_2BPP:
pr("Doing raw 2bpp\n");
epdSetup();
if (lut) selectLUT(lut);
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
epdSelect();
for (uint16_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++) {
if (c % 256 == 0) {
epdDeselect();
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
epdSelect();
}
epdSend(mClutMap[c % 256]);
}
epdDeselect();
endWriteFramebuffer();
pr(" complete.\n");
beginWriteFramebuffer(EPD_COLOR_RED);
epdSelect();
for (uint16_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++) {
if (c % 256 == 0) {
epdDeselect();
eepromRead(addr + sizeof(struct EepromImageHeader) + (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)) + c, mClutMap, 256);
epdSelect();
}
epdSend(mClutMap[c % 256]);
}
epdDeselect();
endWriteFramebuffer();
break;
case DATATYPE_IMG_BMP:;
uint32_t __xdata clutAddr;
pr("sending to EPD - ");
clutAddr = drawPrvParseHeader(addr);
if (!clutAddr)
return;
drawPrvLoadAndMapClut(clutAddr);
epdSetup();
if (lut) selectLUT(lut);
mPassNo = 0;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();
mPassNo++;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_RED);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();
pr(" complete.\n");
break;
}
addOverlay();
drawWithSleep();
}
}

View File

@@ -32,17 +32,14 @@ void eepromReadStart(uint32_t addr) __reentrant;
//structures
#define EEPROM_IMG_INPROGRESS (0x7fffffffUL)
#define EEPROM_IMG_VALID (0x494d4722UL)
#define EEPROM_IMG_VALID (0x494d4721UL)
#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
uint8_t dataType;
uint32_t id;
//image data here

View File

@@ -79,6 +79,8 @@ static uint8_t __xdata dispLutSize = 0;
static bool __xdata isInited = false;
bool __xdata epdGPIOActive = false;
#define LUT_BUFFER_SIZE 128
uint8_t waveformbuffer[LUT_BUFFER_SIZE];
struct waveform10* __xdata waveform10 = (struct waveform10*)waveformbuffer; // holds the LUT/waveform
@@ -193,6 +195,31 @@ static void epdReset() {
shortCommand(CMD_SOFT_RESET2);
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
}
void epdConfigGPIO(bool setup) {
// data / _command: 2.2
// busy 2.1
// reset 2.0
// _select 1.7
// bs1 1.2
// GENERIC SPI BUS PINS
// spi.clk 0.0
// spi.mosi 0.1
if(epdGPIOActive==setup)return;
if (setup) {
P2DIR |= (1 << 1); // busy as input
P2DIR &= ~((1 << 2) | (1 << 0)); // D/C and Reset as output
P1DIR &= ~((1 << 7) | (1 << 2)); // select and bs1 as output
P1_2 = 0; // select 4-wire SPI / BS1 = low
P1_7 = 1; // deselect EPD
} else {
P2DIR |= ((1 << 2) | (1 << 0)); // DC and Reset as input
P2 &= ~((1 << 2) | (1 << 0));
P1DIR |= ((1 << 7) | (1 << 2)); // Select and BS1 as input
P2 &= ~((1 << 7));
}
epdGPIOActive = setup;
}
void epdEnterSleep() {
P2_0 = 0;
timerDelay(10);

View File

@@ -36,6 +36,9 @@
void epdSetup();
void epdEnterSleep();
uint16_t epdGetBattery();
void epdConfigGPIO(bool setup);
extern bool __xdata epdGPIOActive;
void setWindowX(uint16_t start, uint16_t end);
void setWindowY(uint16_t start, uint16_t end);

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -143,7 +143,8 @@ uint8_t channelSelect() { // returns 0 if no accesspoints were found
void mainProtocolLoop(void) {
// displayLoop(); // remove me
powerUp(INIT_BASE | INIT_UART | INIT_GPIO);
setupPortsInitial();
powerUp(INIT_BASE | INIT_UART);
if (RESET & 0x01) {
wakeUpReason = WAKEUP_REASON_WDT_RESET;
@@ -169,7 +170,7 @@ void mainProtocolLoop(void) {
pr("Mac can't be all FF's.\n");
powerUp(INIT_EPD);
showNoMAC();
powerDown(INIT_EPD | INIT_GPIO | INIT_EEPROM);
powerDown(INIT_EPD | INIT_UART | INIT_EEPROM);
doSleep(-1);
wdtDeviceReset();
}
@@ -196,23 +197,22 @@ void mainProtocolLoop(void) {
wdt30s();
currentChannel = showChannelSelect();
powerUp(INIT_GPIO | INIT_EPD);
wdt10s();
if (currentChannel) {
showAPFound();
initPowerSaving(INTERVAL_BASE);
powerDown(INIT_EPD | INIT_GPIO);
powerDown(INIT_EPD | INIT_UART);
doSleep(5000UL);
} else {
showNoAP();
initPowerSaving(INTERVAL_AT_MAX_ATTEMPTS);
powerDown(INIT_EPD | INIT_GPIO);
powerDown(INIT_EPD | INIT_UART);
doSleep(120000UL);
}
while (1) {
powerUp(INIT_UART);
wdt10s();
if (currentChannel) {
// associated
@@ -222,28 +222,30 @@ void mainProtocolLoop(void) {
if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) {
// check if we should do a voltage measurement (those are pretty expensive)
if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) {
powerUp(INIT_BASE | INIT_TEMPREADING | INIT_EPD_VOLTREADING | INIT_RADIO);
powerUp(INIT_TEMPREADING | INIT_EPD_VOLTREADING);
voltageCheckCounter = 0;
} else {
powerUp(INIT_BASE | INIT_TEMPREADING | INIT_RADIO);
powerUp(INIT_TEMPREADING);
}
voltageCheckCounter++;
// check if the battery level is below minimum, and force a redraw of the screen
if ((lowBattery && !lowBatteryShown) || (noAPShown)) {
powerUp(INIT_EPD);
// Check if we were already displaying an image
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
drawImageFromEeprom();
powerDown(INIT_EEPROM);
powerUp(INIT_EEPROM | INIT_EPD);
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EEPROM | INIT_EPD);
} else {
powerUp(INIT_EPD);
showAPFound();
powerDown(INIT_EPD);
}
}
powerUp(INIT_RADIO);
avail = getAvailDataInfo();
powerDown(INIT_RADIO);
if (avail != NULL) {
// we got some data!
longDataReqCounter = 0;
@@ -251,10 +253,10 @@ void mainProtocolLoop(void) {
wakeUpReason = WAKEUP_REASON_TIMED;
}
} else {
powerUp(INIT_BASE | INIT_RADIO); //| INIT_GPIO | INIT_UART
powerUp(INIT_RADIO);
avail = getShortAvailDataInfo();
powerDown(INIT_RADIO);
}
powerDown(INIT_RADIO);
addAverageValue();
@@ -266,22 +268,17 @@ void mainProtocolLoop(void) {
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE) {
// data transfer
powerUp(INIT_GPIO | INIT_UART);
if (doDataDownload(avail)) {
if (processAvailDataInfo(avail)) {
// succesful transfer, next wake time is determined by the NextCheckin;
} else {
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
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) {
@@ -299,31 +296,27 @@ void mainProtocolLoop(void) {
} else {
// not associated
if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) {
powerUp(INIT_BASE | INIT_EPD_VOLTREADING | INIT_RADIO);
} else {
powerUp(INIT_BASE | INIT_RADIO); // || INIT_GPIO | INIT_UART
powerUp(INIT_EPD_VOLTREADING);
}
// try to find a working channel
powerUp(INIT_RADIO);
currentChannel = channelSelect();
powerDown(INIT_RADIO);
if ((!currentChannel && !noAPShown) || (lowBattery && !lowBatteryShown) || (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) {
powerUp(INIT_EPD);
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
drawImageFromEeprom();
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EEPROM);
} else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) {
showLongTermSleep();
powerDown(INIT_EPD);
} else {
showNoAP();
powerDown(INIT_EPD);
}
powerDown(INIT_EPD);
}
powerDown(INIT_GPIO);
// did we find a working channel?
if (currentChannel) {
// now associated!

View File

@@ -38,54 +38,75 @@ bool __xdata lowBattery = false;
uint16_t __xdata longDataReqCounter = 0;
uint16_t __xdata voltageCheckCounter = 0;
bool __xdata spiActive = false;
bool __xdata uartActive = false;
bool __xdata eepromActive = false;
extern int8_t adcSampleTemperature(void); // in degrees C
void initPowerSaving(uint16_t initialValue) {
void setupPortsInitial() {
P0INTEN = 0;
P1INTEN = 0;
P2INTEN = 0;
P0FUNC = 0;
P1FUNC = 0;
P2FUNC = 0;
P0DIR = 0xFF;
P1DIR = 0xFF;
P2DIR = 0xFF;
P0PULL = 0x00;
P1PULL = 0x00;
P2PULL = 0x00;
}
void initPowerSaving(const 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();
}
if (parts & INIT_GPIO){
boardInit();
static void configSPI(const bool setup) {
if (setup == spiActive) return;
if (setup) {
P0FUNC |= (1 << 0) | (1 << 1) | (1 << 2);
P0DIR |= (1 << 2); // MISO as input
P0DIR &= ~((1 << 0) | (1 << 1)); // CLK and MOSI as output
P0PULL |= (1 << 2);
spiInit();
wdtOn();
} else {
P0FUNC &= ~((1 << 0) | (1 << 1) | (1 << 2));
P0DIR |= (1 << 0) | (1 << 1) | (1 << 2);
P0PULL &= ~(1 << 2);
uint8_t bcp;
CLKEN &= ~(0x08);
bcp = CFGPAGE;
CFGPAGE = 4;
SPIENA &= ~(0x81);
CFGPAGE = bcp;
}
spiActive = setup;
}
if (parts & INIT_EPD)
epdSetup();
if ((parts & INIT_BASE) && !(parts & INIT_EPD_VOLTREADING) && !(parts & INIT_EPD)) {
if (!(parts & INIT_GPIO)){
boardInit();
wdtOn();
}
epdEnterSleep(); // this required fixing! halp halp fix me
}
if (parts & INIT_EPD_VOLTREADING) {
if (!(parts & INIT_GPIO)){
boardInit();
wdtOn();
}
batteryVoltage = epdGetBattery();
if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) {
lowBattery = true;
} else {
lowBattery = false;
}
}
if (parts & INIT_UART) {
static void configUART(const bool setup) {
if (uartActive == setup) return;
if (setup) {
P0FUNC |= (1 << 6);
P0DIR &= ~(1 << 6);
uartInit();
} else {
P0DIR |= (1 << 6);
P0FUNC &= ~(1 << 6);
CLKEN &= ~(0x20);
}
uartActive = setup;
}
if (parts & INIT_EEPROM) {
static void configEEPROM(const bool setup) {
if (setup == eepromActive) return;
if (setup) {
P1FUNC &= ~(1 << 1);
P1DIR &= ~(1 << 1);
if (!eepromInit()) {
powerDown(INIT_RADIO);
powerUp(INIT_EPD);
@@ -94,6 +115,46 @@ void powerUp(uint8_t parts) {
doSleep(-1);
wdtDeviceReset();
}
} else {
P1DIR |= (1 << 1);
}
setup == eepromActive;
}
void powerUp(const uint8_t parts) {
if (parts & INIT_BASE) {
clockingAndIntsInit();
timerInit();
irqsOn();
wdtOn();
}
if (parts & INIT_EPD) {
configSPI(true);
epdConfigGPIO(true);
epdSetup();
}
if (parts & INIT_EPD_VOLTREADING) {
epdConfigGPIO(true);
configSPI(true);
batteryVoltage = epdGetBattery();
if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) {
lowBattery = true;
} else {
lowBattery = false;
}
configSPI(false);
epdConfigGPIO(false);
}
if (parts & INIT_UART) {
configUART(true);
}
if (parts & INIT_EEPROM) {
configSPI(true);
configEEPROM(true);
}
if (parts & INIT_TEMPREADING) {
@@ -112,7 +173,10 @@ void powerUp(uint8_t parts) {
}
}
void powerDown(uint8_t parts) {
void powerDown(const uint8_t parts) {
if (parts & INIT_UART) {
configUART(false);
}
if (parts & INIT_RADIO) {
radioRxEnable(false, true);
RADIO_IRQ4_pending = 0;
@@ -127,18 +191,45 @@ void powerDown(uint8_t parts) {
if (parts & INIT_EEPROM) {
eepromDeepPowerDown();
eepromPrvDeselect();
configEEPROM(false);
}
if (parts & INIT_EPD)
if (parts & INIT_EPD) {
epdConfigGPIO(true);
epdEnterSleep();
if (parts & INIT_GPIO)
powerPortsDownForSleep();
epdConfigGPIO(false);
}
if (!eepromActive && !epdGPIOActive) {
configSPI(false);
}
}
void doSleep(uint32_t __xdata t) {
void doSleep(const uint32_t __xdata t) {
// if (t > 1000) pr("s=%lu\n ", t / 1000);
// powerPortsDownForSleep();
// set up pins for spi(0.0,0.1,0.2), UART (0.6)
// setup 1.1(eeprom_nCS), 1.2(eink_BS1), 1.7(eink_nCS)
// setup 2.0(eink_nRST), 2.1(eink_BUSY), 2.2(eink_D/nC)
P0FUNC = 0;
P1FUNC = 0;
P2FUNC = 0;
P0DIR = 1;
P0 = 0;
P0PULL = 1;
P1DIR = 0x86;
P1PULL = 0x86;
P2DIR = 7;
P2 = 0;
P2PULL = 5;
spiActive = false;
uartActive = false;
eepromActive = false;
#ifdef HAS_BUTTON
// Button setup on TEST pin 1.0 (input pullup)
P1FUNC &= ~(1 << 0);
@@ -148,20 +239,18 @@ void doSleep(uint32_t __xdata t) {
P1INTEN = (1 << 0);
P1CHSTA &= ~(1 << 0);
#endif
// sleepy
sleepForMsec(t);
#ifdef HAS_BUTTON
P1INTEN = 0;
if (P1CHSTA && (1 << 0)) {
wakeUpReason = WAKEUP_REASON_GPIO;
pr("button pressed\n");
P1CHSTA &= ~(1 << 0);
}
#endif
}
uint32_t getNextScanSleep(bool increment) {
uint32_t getNextScanSleep(const bool increment) {
if (increment) {
if (scanAttempts < 255)
scanAttempts++;

View File

@@ -59,17 +59,19 @@
#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);
extern void setupPortsInitial();
extern void powerUp(const uint8_t parts);
extern void powerDown(const uint8_t parts);
extern void initAfterWake();
extern void doSleep(uint32_t __xdata t);
extern void doSleep(const uint32_t __xdata t);
extern void addAverageValue();
extern uint16_t getNextSleep();
extern uint32_t getNextScanSleep(bool increment);
extern void initPowerSaving(uint16_t initialValue);
extern uint32_t getNextScanSleep(const bool increment);
extern void initPowerSaving(const uint16_t initialValue);
extern uint8_t __xdata wakeUpReason;

View File

@@ -116,9 +116,12 @@ struct AvailDataReq {
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG 1
#define DATATYPE_IMGRAW 2
#define DATATYPE_UPDATE 3
#define DATATYPE_IMG_BMP 2
#define DATATYPE_FW_UPDATE 3
#define DATATYPE_IMG_DIFF 0x10 // always 1BPP
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD
struct AvailDataInfo {
uint8_t checksum;

View File

@@ -4,7 +4,7 @@
#include <stdint.h>
#define FW_VERSION 014 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-lutje" // suffix, like -RC1 or whatever.
#define FW_VERSION_SUFFIX "-RE" // 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 PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket

View File

@@ -25,41 +25,33 @@
#include "wdt.h"
// download-stuff
bool __xdata dataPending = true;
uint8_t __xdata blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
struct blockRequest __xdata curBlock = {0};
struct AvailDataInfo __xdata curDataInfo = {0};
uint16_t __xdata dataRemaining = 0; // since the targeted solum tags don't have more than 64k progmem, this is fine.
bool __xdata curXferComplete = false;
bool __xdata requestPartialBlock = false;
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
#define BLOCK_TRANSFER_ATTEMPTS 5
uint8_t __xdata prevImgSlot = 0xFF;
uint8_t __xdata curImgSlot = 0xFF;
uint32_t __xdata curHighSlotId = 0;
uint8_t __xdata nextImgSlot = 0;
uint8_t __xdata imgSlots = 0;
static uint32_t __xdata curHighSlotId = 0;
static uint8_t __xdata nextImgSlot = 0;
static uint8_t __xdata imgSlots = 0;
uint8_t __xdata drawWithLut = 0;
// doDownload persistent variables
bool __xdata lastBlock = false;
uint8_t __xdata partsThisBlock = 0;
uint8_t __xdata blockRequestAttempt = 0;
uint8_t __xdata blockValidateAttempt = 0;
// stuff we need to keep track of related to the network/AP
uint8_t __xdata APmac[8] = {0};
uint16_t __xdata APsrcPan = 0;
uint8_t __xdata mSelfMac[8] = {0};
uint8_t __xdata seq = 0;
static uint8_t __xdata seq = 0;
uint8_t __xdata currentChannel = 0;
// buffer we use to prepare/read packets
// static uint8_t __xdata mRxBuf[130];
static uint8_t __xdata inBuffer[128] = {0};
static uint8_t __xdata outBuffer[128] = {0};
// tools
uint8_t __xdata getPacketType(void *__xdata buffer) {
struct MacFcs *__xdata fcs = buffer;
static uint8_t __xdata getPacketType(const void *__xdata buffer) {
const struct MacFcs *__xdata fcs = buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
// broadcast frame
uint8_t __xdata type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)];
@@ -71,8 +63,8 @@ uint8_t __xdata getPacketType(void *__xdata buffer) {
}
return 0;
}
bool pktIsUnicast(void *__xdata buffer) {
struct MacFcs *__xdata fcs = buffer;
static bool pktIsUnicast(const void *__xdata buffer) {
const struct MacFcs *__xdata fcs = buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
return false;
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
@@ -82,7 +74,7 @@ bool pktIsUnicast(void *__xdata buffer) {
// unknown type...
return false;
}
void dump(uint8_t *__xdata a, uint16_t __xdata l) {
void dump(const uint8_t *__xdata a, const uint16_t __xdata l) {
pr("\n ");
#define ROWS 16
for (uint8_t c = 0; c < ROWS; c++) {
@@ -104,7 +96,7 @@ void dump(uint8_t *__xdata a, uint16_t __xdata l) {
}
pr("\n");
}
bool checkCRC(void *p, uint8_t len) {
static bool checkCRC(const void *p, const uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
@@ -112,7 +104,7 @@ bool checkCRC(void *p, uint8_t len) {
// pr("CRC: rx %d, calc %d\n", ((uint8_t *)p)[0], total);
return ((uint8_t *)p)[0] == total;
}
void addCRC(void *p, uint8_t len) {
static void addCRC(void *p, const uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
@@ -121,7 +113,7 @@ void addCRC(void *p, uint8_t len) {
}
// radio stuff
void sendPing() {
static void sendPing() {
struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1);
memset(outBuffer, 0, sizeof(struct MacFrameBcast) + 2 + 4);
outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2;
@@ -132,12 +124,12 @@ void sendPing() {
txframe->fcs.destAddrType = 2;
txframe->fcs.srcAddrType = 3;
txframe->seq = seq++;
txframe->dstPan = 0xFFFF;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
commsTxNoCpy(outBuffer);
}
uint8_t detectAP(uint8_t channel) {
uint8_t detectAP(const uint8_t channel) {
uint32_t __xdata t;
radioRxEnable(false, true);
radioSetChannel(channel);
@@ -164,7 +156,7 @@ uint8_t detectAP(uint8_t channel) {
}
// data xfer stuff
void sendShortAvailDataReq() {
static 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;
@@ -172,12 +164,12 @@ void sendShortAvailDataReq() {
outBuffer[1] = 0x21;
outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet
txframe->seq = seq++;
txframe->dstPan = 0xFFFF;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
commsTxNoCpy(outBuffer);
}
void sendAvailDataReq() {
static void sendAvailDataReq() {
struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1);
memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4);
struct AvailDataReq *__xdata availreq = (struct AvailDataReq *)(outBuffer + 2 + sizeof(struct MacFrameBcast));
@@ -189,7 +181,7 @@ void sendAvailDataReq() {
txframe->fcs.destAddrType = 2;
txframe->fcs.srcAddrType = 3;
txframe->seq = seq++;
txframe->dstPan = 0xFFFF;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
// TODO: send some (more) meaningful data
@@ -251,7 +243,7 @@ struct AvailDataInfo *__xdata getShortAvailDataInfo() {
dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS;
return NULL;
}
bool processBlockPart(struct blockPart *bp) {
static bool processBlockPart(const struct blockPart *bp) {
uint16_t __xdata start = bp->blockPart * BLOCK_PART_DATA_SIZE;
uint16_t __xdata size = BLOCK_PART_DATA_SIZE;
// validate if it's okay to copy data
@@ -274,7 +266,7 @@ bool processBlockPart(struct blockPart *bp) {
return false;
}
}
bool blockRxLoop(uint32_t timeout) {
static bool blockRxLoop(const uint32_t timeout) {
uint32_t __xdata t;
bool success = false;
radioRxEnable(true, true);
@@ -292,12 +284,12 @@ bool blockRxLoop(uint32_t timeout) {
radioRxFlush();
return success;
}
struct blockRequestAck *__xdata continueToRX() {
static struct blockRequestAck *__xdata continueToRX() {
struct blockRequestAck *ack = (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
ack->pleaseWaitMs = 0;
return ack;
}
void sendBlockRequest() {
static void sendBlockRequest() {
memset(outBuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2);
struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)(outBuffer + 1);
struct blockRequest *__xdata blockreq = (struct blockRequest *)(outBuffer + 2 + sizeof(struct MacFrameNormal));
@@ -325,7 +317,7 @@ void sendBlockRequest() {
addCRC(blockreq, sizeof(struct blockRequest));
commsTxNoCpy(outBuffer);
}
struct blockRequestAck *__xdata performBlockRequest() {
static struct blockRequestAck *__xdata performBlockRequest() {
uint32_t __xdata t;
radioRxEnable(true, true);
radioRxFlush();
@@ -359,7 +351,7 @@ struct blockRequestAck *__xdata performBlockRequest() {
return continueToRX();
// return NULL;
}
void sendXferCompletePacket() {
static void sendXferCompletePacket() {
memset(outBuffer, 0, sizeof(struct MacFrameNormal) + 2 + 4);
struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)(outBuffer + 1);
outBuffer[0] = sizeof(struct MacFrameNormal) + 2 + 2;
@@ -378,7 +370,7 @@ void sendXferCompletePacket() {
f->seq = seq++;
commsTxNoCpy(outBuffer);
}
void sendXferComplete() {
static void sendXferComplete() {
radioRxEnable(true, true);
for (uint8_t c = 0; c < 8; c++) {
@@ -397,7 +389,7 @@ void sendXferComplete() {
pr("XFC NACK!\n");
return;
}
bool validateBlockData() {
static bool validateBlockData() {
struct blockData *bd = (struct blockData *)blockXferBuffer;
// pr("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum);
uint16_t t = 0;
@@ -408,10 +400,10 @@ bool validateBlockData() {
}
// EEprom related stuff
uint32_t getAddressForSlot(uint8_t s) {
static uint32_t getAddressForSlot(const uint8_t s) {
return EEPROM_IMG_START + (EEPROM_IMG_EACH * s);
}
void getNumSlots() {
static void getNumSlots() {
uint32_t eeSize = eepromGetSize();
uint16_t nSlots = mathPrvDiv32x16(eeSize - EEPROM_IMG_START, EEPROM_IMG_EACH >> 8) >> 8;
if (eeSize < EEPROM_IMG_START || !nSlots) {
@@ -424,7 +416,7 @@ void getNumSlots() {
} else
imgSlots = nSlots;
}
uint8_t findSlot(uint8_t *__xdata ver) {
static uint8_t findSlot(const uint8_t *__xdata 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++) {
@@ -438,26 +430,28 @@ uint8_t findSlot(uint8_t *__xdata ver) {
}
return 0xFF;
}
void eraseUpdateBlock() {
static void eraseUpdateBlock() {
eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN / EEPROM_ERZ_SECTOR_SZ);
}
void saveUpdateBlockData(uint8_t blockId) {
static void eraseImageBlock(const uint8_t c) {
eepromErase(getAddressForSlot(c), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ);
}
static void saveUpdateBlockData(uint8_t blockId) {
if (!eepromWrite(EEPROM_UPDATA_AREA_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE))
pr("EEPROM write failed\n");
}
void saveImgBlockData(uint8_t blockId) {
static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) {
uint16_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE));
if (length > 4096) length = 4096;
if (!eepromWrite(getAddressForSlot(curImgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length))
if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length))
pr("EEPROM write failed\n");
}
void drawImageFromEeprom() {
drawImageAtAddress(getAddressForSlot(curImgSlot), drawWithLut);
void drawImageFromEeprom(const uint8_t imgSlot) {
drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut);
drawWithLut = 0; // default back to the regular ol' stock/OTP LUT
powerDown(INIT_EPD);
}
uint32_t getHighSlotId() {
static uint32_t getHighSlotId() {
uint32_t temp = 0;
uint32_t __xdata markerValid = EEPROM_IMG_VALID;
for (uint8_t __xdata c = 0; c < imgSlots; c++) {
@@ -474,110 +468,31 @@ uint32_t getHighSlotId() {
return temp;
}
// Main download function
bool doDataDownload(struct AvailDataInfo *__xdata avail) {
// this is the main function for the download process
static uint8_t __xdata partsThisBlock = 0;
static uint8_t __xdata blockAttempts = 0; // these CAN be local to the function, but for some reason, they won't survive sleep?
// they get overwritten with 7F 32 44 20 00 00 00 00 11, I don't know why.
if (!eepromInit()) { // we'll need the eeprom here, init it.
pr("failed to init eeprom\n");
return false;
}
// GET AVAIL DATA INFO - enable the radio and get data
if (avail == NULL) { // didn't receive a reply to get info about the data, we'll resync and try again later
#ifdef DEBUGBLOCKS
pr("didn't receive getavaildatainfo");
#endif
return false;
}
// did receive available data info (avail struct)
switch (avail->dataType) {
case DATATYPE_IMG:
case DATATYPE_IMGRAW:
// check if this download is currently displayed or active
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();
powerDown(INIT_RADIO);
pr("already seen, drawing from eeprom slot %d\n", curImgSlot);
// mark as completed and draw from EEPROM
curXferComplete = true;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
drawWithLut = avail->dataTypeArgument;
wdt60s();
drawImageFromEeprom();
return true;
} else {
// not found in cache, prepare to download
// go to the next image slot
nextImgSlot++;
if (nextImgSlot >= imgSlots) nextImgSlot = 0;
curImgSlot = nextImgSlot;
drawWithLut = avail->dataTypeArgument;
eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ);
pr("new download, writing to slot %d\n", curImgSlot);
// continue!
}
}
break;
case DATATYPE_UPDATE:
pr("received firmware!\n");
eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN / EEPROM_ERZ_SECTOR_SZ);
break;
}
// prepare for download
curXferComplete = false;
curBlock.blockId = 0;
xMemCopy8(&(curBlock.ver), &(avail->dataVer));
curBlock.type = avail->dataType;
xMemCopyShort(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
dataRemaining = curDataInfo.dataSize; // this was + 2, and I can't remember why. It works fine without it, so I don't know....
// set requested parts - check if the transfer is contained in this block
if (dataRemaining > BLOCK_DATA_SIZE) {
// full block, not last
lastBlock = false;
static bool getDataBlock(const uint16_t blockSize) {
blockAttempts = BLOCK_TRANSFER_ATTEMPTS;
if (blockSize == BLOCK_DATA_SIZE) {
partsThisBlock = BLOCK_MAX_PARTS;
memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES);
} else {
// final block, probably partial
lastBlock = true;
partsThisBlock = dataRemaining / BLOCK_PART_DATA_SIZE;
if (dataRemaining % BLOCK_PART_DATA_SIZE) partsThisBlock++;
partsThisBlock = blockSize / BLOCK_PART_DATA_SIZE;
if (blockSize % BLOCK_PART_DATA_SIZE) partsThisBlock++;
memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES);
for (uint8_t c = 0; c < partsThisBlock; c++) {
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
}
// do transfer!
blockRequestAttempt = 0;
blockValidateAttempt = 0;
while (!curXferComplete) {
// this while loop loops until the transfer has been completed, or we get tired for other reasons
startdownload:;
wdt10s();
requestPartialBlock = false; // this forces the AP to request the block data from the host
while (blockAttempts--) {
#ifndef DEBUGBLOCKS
pr("REQ %d ", curBlock.blockId);
#endif
#ifdef DEBUGBLOCKS
#else
pr("REQ %d[", curBlock.blockId);
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
if ((c != 0) && (c % 8 == 0)) pr("][");
if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) {
@@ -588,45 +503,27 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
}
pr("]\n");
#endif
// 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");
return false;
} else {
// got an ack!
}
// SLEEP - until the AP is ready with the data
if (ack->pleaseWaitMs) {
if (ack->pleaseWaitMs) { // SLEEP - until the AP is ready with the data
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);
powerUp(INIT_UART | INIT_RADIO);
radioRxEnable(true, true);
}
} else {
// immediately start with the reception of the block data
}
// BLOCK RX LOOP - receive a block, until the timeout has passed
if (!blockRxLoop(270)) { // was 300
// didn't receive packets
blockRequestAttempt++;
if (blockRequestAttempt > 5) {
powerDown(INIT_RADIO);
pr("bailing on download, 0 blockparts rx'd\n");
return false;
}
} else {
// successfull block RX loop
blockRequestAttempt = 0;
}
blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed
powerDown(INIT_RADIO);
#ifdef DEBUGBLOCKS
pr("RX %d[", curBlock.blockId);
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
@@ -639,7 +536,6 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
}
pr("]\n");
#endif
// check if we got all the parts we needed, e.g: has the block been completed?
bool blockComplete = true;
for (uint8_t c = 0; c < partsThisBlock; c++) {
@@ -651,31 +547,14 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
pr("- COMPLETE\n");
#endif
if (validateBlockData()) {
// checked and found okay
requestPartialBlock = false; // next block is going to be requested from the ESP32 by the AP
blockValidateAttempt = 0;
switch (curBlock.type) {
case DATATYPE_IMG:
case DATATYPE_IMGRAW:
saveImgBlockData(curBlock.blockId);
break;
case DATATYPE_UPDATE:
saveUpdateBlockData(curBlock.blockId);
break;
}
// block download complete, validated
return true;
} else {
// block checked, but failed validation. Mark all parts for this block as 'request'
blockValidateAttempt++;
if (blockValidateAttempt > 5) {
pr("bailing on download, 0 blockparts rx'd\n");
return false;
}
for (uint8_t c = 0; c < partsThisBlock; c++) {
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
blockComplete = false;
requestPartialBlock = false;
pr("block failed validation!\n");
pr("blk failed validation!\n");
}
} else {
#ifndef DEBUGBLOCKS
@@ -684,67 +563,180 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
// block incomplete, re-request a partial block
requestPartialBlock = true;
}
}
pr("failed getting block\n");
return false;
}
if (blockComplete) {
if (!lastBlock) {
// Not the last block! check what the next block is going to be
curBlock.blockId++;
dataRemaining -= BLOCK_DATA_SIZE;
if (dataRemaining > BLOCK_DATA_SIZE) {
// full block-size
partsThisBlock = BLOCK_MAX_PARTS;
memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES);
lastBlock = false;
} else {
// final block, probably partial
partsThisBlock = dataRemaining / BLOCK_PART_DATA_SIZE;
if (dataRemaining % BLOCK_PART_DATA_SIZE) partsThisBlock++;
memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES);
for (uint8_t c = 0; c < partsThisBlock; c++) {
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
lastBlock = true;
}
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) {
// 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));
eraseUpdateBlock();
}
} else {
// this was the last block. What should we do next?
switch (curBlock.type) {
case DATATYPE_IMG:
case DATATYPE_IMGRAW:;
// transfer complete. Save data info and mark data in image slot as 'valid'
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
xMemCopy8(&eih->version, &curDataInfo.dataVer);
eih->size = curDataInfo.dataSize;
eih->validMarker = EEPROM_IMG_VALID;
eih->id = ++curHighSlotId;
eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader));
// pr("transfer complete!");
curXferComplete = true;
powerUp(INIT_RADIO);
sendXferComplete();
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();
powerDown(INIT_RADIO);
wdt60s();
eepromReadStart(EEPROM_UPDATA_AREA_START);
selfUpdate();
break;
}
}
while (curDataInfo.dataSize) {
wdt10s();
static uint16_t __xdata dataRequestSize;
if (curDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
} else {
// incomplete block, wrap around and get the rest of the block...
// only one block remains
dataRequestSize = curDataInfo.dataSize;
}
} // end download while loop
if (getDataBlock(dataRequestSize)) {
// succesfully downloaded datablock, save to eeprom
powerUp(INIT_EEPROM);
saveUpdateBlockData(curBlock.blockId);
powerDown(INIT_EEPROM);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
} else {
// failed to get the block we wanted, we'll stop for now, maybe resume later
return false;
}
}
// no more data, download complete
return true;
}
static bool downloadImageDataToEEPROM(const struct AvailDataInfo *__xdata avail) {
static uint16_t __xdata imageSize = 0;
// 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) {
// looks like we did. We'll carry on where we left off.
pr("restarting image download");
} else {
// go to the next image slot
nextImgSlot++;
if (nextImgSlot >= imgSlots) nextImgSlot = 0;
curImgSlot = nextImgSlot;
drawWithLut = avail->dataTypeArgument;
eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ);
pr("new download, writing to slot %d\n", curImgSlot);
// 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;
}
while (curDataInfo.dataSize) {
wdt10s();
static uint16_t __xdata dataRequestSize;
if (curDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
} else {
// only one block remains
dataRequestSize = curDataInfo.dataSize;
}
if (getDataBlock(dataRequestSize)) {
// succesfully downloaded datablock, save to eeprom
powerUp(INIT_EEPROM);
saveImgBlockData(curImgSlot, curBlock.blockId);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
} else {
// failed to get the block we wanted, we'll stop for now, probably resume later
return false;
}
}
// borrow the blockXferBuffer temporarily
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
xMemCopy8(&eih->version, &curDataInfo.dataVer);
eih->validMarker = EEPROM_IMG_VALID;
eih->id = ++curHighSlotId;
eih->size = imageSize;
eih->dataType = curDataInfo.dataType;
eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader));
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
// no more data, download complete
return true;
}
bool processAvailDataInfo(const 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:
// 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
powerUp(INIT_EEPROM);
curImgSlot = findSlot(&(avail->dataVer));
powerDown(INIT_EEPROM);
if (curImgSlot != 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
drawWithLut = avail->dataTypeArgument;
wdt60s();
powerUp(INIT_EPD | INIT_EEPROM);
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EPD | INIT_EEPROM);
return true;
} else {
// not found in cache, prepare to download
drawWithLut = avail->dataTypeArgument;
powerUp(INIT_EEPROM);
downloadImageDataToEEPROM(avail);
wdt60s();
powerUp(INIT_EPD);
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EPD | INIT_EEPROM);
return true;
}
break;
case DATATYPE_FW_UPDATE:
powerUp(INIT_EEPROM);
if (downloadFWUpdate(avail)) {
pr("firmware download complete, doing update.\n");
powerUp(INIT_EPD);
showApplyUpdate();
powerUp(INIT_RADIO);
sendXferComplete();
powerDown(INIT_RADIO);
wdt60s();
eepromReadStart(EEPROM_UPDATA_AREA_START);
selfUpdate();
} else {
return false;
}
break;
}
return true;
}

View File

@@ -16,9 +16,9 @@ extern void killRadio(void);
extern struct AvailDataInfo *__xdata getAvailDataInfo();
extern struct AvailDataInfo *__xdata getShortAvailDataInfo();
extern void drawImageFromEeprom();
extern bool doDataDownload(struct AvailDataInfo *__xdata avail);
extern void drawImageFromEeprom(const uint8_t imgSlot);
extern bool processAvailDataInfo(const struct AvailDataInfo *__xdata avail);
extern void initializeProto();
extern uint8_t detectAP(uint8_t channel);
extern uint8_t detectAP(const uint8_t channel);
#endif