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