mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-23 18:08:50 +01:00
Merge pull request #16 from jjwbruijn/refactored-download-rawimages
Refactored download rawimages
This commit is contained in:
BIN
fw_dumps/0000026619db3438.bin
Normal file
BIN
fw_dumps/0000026619db3438.bin
Normal file
Binary file not shown.
BIN
fw_dumps/027C4B633B1A.bin
Normal file
BIN
fw_dumps/027C4B633B1A.bin
Normal file
Binary file not shown.
58816
fw_dumps/027C4B633B1A.bin.html
Normal file
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
BIN
fw_dumps/027C4D453B18.bin
Normal file
Binary file not shown.
BIN
fw_dumps/02A901443416.bin
Normal file
BIN
fw_dumps/02A901443416.bin
Normal file
Binary file not shown.
BIN
fw_dumps/02BE4D273B12.bin
Normal file
BIN
fw_dumps/02BE4D273B12.bin
Normal file
Binary file not shown.
108
tag_fw/drawing.c
108
tag_fw/drawing.c
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
27
tag_fw/epd.c
27
tag_fw/epd.c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
BIN
tag_fw/fw154.bin
BIN
tag_fw/fw154.bin
Binary file not shown.
BIN
tag_fw/fw29.bin
BIN
tag_fw/fw29.bin
Binary file not shown.
BIN
tag_fw/fw42.bin
BIN
tag_fw/fw42.bin
Binary file not shown.
@@ -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!
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user