38 Commits

Author SHA1 Message Date
Nic Limper
a5d7282958 update tagtypes for M3 0027 firmware 2024-03-04 19:46:17 +01:00
jjwbruijn
f233d90b86 M3 Universal v0027 2024-03-04 19:04:15 +01:00
Nic Limper
739625f1c8 Squashed commit of the following:
commit d41ab4b27c
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:16:15 2024 +0100

    remove subghz in platformio.ini

commit dfa1a5cecd
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:15:14 2024 +0100

    Revert "Disable SubGhz support until C6 side is ready."

    This reverts commit 3bc96dc48e.

commit cdd26072fd
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:14:46 2024 +0100

    Revert "Merge remote-tracking branch 'mine/oepl_pr_1' into oepl_pr_1"

    This reverts commit 39b1938263, reversing
    changes made to 3bc96dc48e.

commit 39b1938263
Merge: 3bc96dc4 2b62dff5
Author: Skip Hansen <skip@gfrn.org>
Date:   Mon Mar 4 03:54:35 2024 -0800

    Merge remote-tracking branch 'mine/oepl_pr_1' into oepl_pr_1

commit 3bc96dc48e
Author: Skip Hansen <skip@gfrn.org>
Date:   Mon Mar 4 03:43:12 2024 -0800

    Disable SubGhz support until C6 side is ready.

commit 2b62dff5f5
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 11:44:06 2024 +0100

    fix gzip wwwfiles

    to prevent unchanged gzipped files showing up in the commit

commit 0864870540
Author: Skip Hansen <skip@gfrn.org>
Date:   Sun Mar 3 16:46:53 2024 -0800

    Added SubGhz channel support to AP Web GUI.
2024-03-04 13:21:58 +01:00
Jan-Henrik Bruhn
b527d3e57d Fix openepaperlink.eu proxy on https proxies (#251) 2024-03-04 12:03:55 +01:00
Cougar
ba82ab8628 Add Estonian language (#254) 2024-03-04 11:51:49 +01:00
Jelmer
085a642ed2 New M3 types by VstudioLAB 2024-03-04 11:39:45 +01:00
jjwbruijn
e2870825cf 88MZ100 v0028 - bugfix and commands 2024-03-03 21:56:00 +01:00
jjwbruijn
a4bdb4acab FW Pack for autoflasher 2024-03-02 12:13:05 +01:00
Jelmer
058016d208 Update tagotaversions.json 2024-03-02 02:58:30 +01:00
Jelmer
b14cd3909c Update tagotaversions.json - test 2024-03-02 02:40:14 +01:00
jjwbruijn
cd09a53e02 v0027 M2 ZBS Binaries 2024-03-02 02:09:27 +01:00
jjwbruijn
6bdf99a8e7 v0027 M2 ZBS243, fixes inadvertent redraw 2024-03-01 14:02:37 +01:00
Jelmer
1b256c3fba Create README.md 2024-03-01 01:41:27 +01:00
Jelmer
ec217a94d0 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-03-01 01:29:34 +01:00
Jelmer
2b99ce7139 MiniAP V3 Case 2024-03-01 01:29:26 +01:00
Nic Limper
f6a8fa3d4d added Dansk (thanks Cokeman), added Nebular 213 templates, removed flasher icon in S2 based AP's 2024-02-29 17:37:35 +01:00
Jelmer
294ed5bd28 Create README.md 2024-02-29 17:08:54 +01:00
Jelmer
92c5d60cf8 Nano C6 case 2024-02-29 16:59:54 +01:00
leXorNet
7ca5461c33 Increased language count cap from 8 to 9 to support the latest language (#250) 2024-02-29 00:19:49 +01:00
Jelmer
aebbb22cde Update oepl-definitions.h 2024-02-28 20:03:10 +01:00
Nic Limper
14e96c72f7 bugfix miniAP doesn't display channel 27 2024-02-28 08:16:47 +01:00
Nic Limper
ebd1adc0d5 gzipped www files 2024-02-28 01:20:37 +01:00
Nic Limper
f4cb642142 add Denmark to dayahead electricity prices; enable it also for 2.9" UC8151 2024-02-28 01:11:01 +01:00
Nic Limper
9b2d76a6b6 bugfix: idlereq should not be queued, and only sent when queue is empty 2024-02-28 01:09:00 +01:00
leXorNet
ac979a3c52 Added Swedish content language (#245) 2024-02-27 12:11:13 +01:00
Jan-Henrik Bruhn
a606c4c1aa Use relative paths for fetch calls and websocket (#243)
This allows the OEPL Frontend to be put behind a reverse proxy like Home
Assistant Ingress to proxy it behind a relative path.
2024-02-27 01:47:36 +01:00
Jelmer
c22fe0d91b Merge pull request #241 from TheRealMrSteel/patch-1
Update content_cards.json
2024-02-27 00:37:42 +01:00
Jelmer
b29907a725 Merge pull request #242 from VstudioLAB/M3_58-26-29FREEZER
M3 58 26 29 freezer
2024-02-27 00:36:03 +01:00
Jelmer
8da475901d Support for rotating generated images based on tagtype profile 2024-02-27 00:32:09 +01:00
Vstudio LAB
e4ed0b13db Delete ARM_Tag_FW/Newton_M3_nRF52811/$PROJECT_DIR directory 2024-02-26 22:55:48 +01:00
VstudioLAB
0ffd0fbf0e Update .gitignore 2024-02-26 22:49:03 +01:00
Steel
1cba70b9cc Update content_cards.json
typo in id19
2024-02-26 22:47:50 +01:00
VstudioLAB
6b67f6df2b updates 2024-02-26 22:24:48 +01:00
VstudioLAB
f83667bcce Added support for the 2.6 BWR 2024-02-15 13:25:58 +01:00
VstudioLAB
bee51a23b6 5.85" Initial support and general preparation for BW only compatibility. 2024-02-15 00:09:25 +01:00
VstudioLAB
a787ac6ddf M3 5.85" cleanning 2024-02-14 22:09:50 +01:00
VstudioLAB
5561f82bf6 Original commit (5.85" BWR only)
First commit of that branch.
At the moment, only the M3 5.85" is added, but not finished.
2024-02-14 21:39:36 +01:00
VstudioLAB
b07eeb31ce initial commit 2024-02-14 00:56:38 +01:00
100 changed files with 1264 additions and 8048 deletions

1
.gitignore vendored
View File

@@ -26,3 +26,4 @@
sdcc/sdcc
ESP32_AP-Flasher/.vscode/extensions.json
ARM_Tag_FW\Newton_M3_nRF52811\$PROJECT_DIR

View File

@@ -53,6 +53,7 @@ uint64_t __attribute__((section(".fwmagic"))) magic = FW_MAGIC;
#define TAG_MODE_CHANSEARCH 0
#define TAG_MODE_ASSOCIATED 1
#define TAG_MODE_DEEPSLEEP 0x10
__attribute__((section(".aon"))) uint8_t currentTagMode = TAG_MODE_CHANSEARCH;
__attribute__((section(".aon"))) volatile struct zigbeeCalibDataStruct zigbeeCalibData;
@@ -444,6 +445,11 @@ void TagChanSearch() {
}
}
void tagDeepSleep() {
printf("MAIN: long sleepy\n");
sleep_with_with_wakeup(1800 * 1000UL);
}
int main(void) {
(*(volatile unsigned int *)0x20124000) = 0x100004; // On WARM RESET: Goto this address. -> entry
(*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000
@@ -538,6 +544,9 @@ int main(void) {
case TAG_MODE_CHANSEARCH:
TagChanSearch();
break;
case TAG_MODE_DEEPSLEEP:
tagDeepSleep();
break;
}
}
return 0;
@@ -592,3 +601,34 @@ void applyUpdate(uint32_t size) {
while (1)
;
}
void executeCommand(uint8_t cmd) {
printf("executing command %d \n", cmd);
delay(20);
switch (cmd) {
case CMD_DO_REBOOT:
NVIC_SystemReset();
break;
case CMD_DO_RESET_SETTINGS:
break;
case CMD_DO_SCAN:
currentChannel = showChannelSelect();
break;
case CMD_ERASE_EEPROM_IMAGES:
eraseImageBlocks();
break;
case CMD_GET_BATTERY_VOLTAGE:
doVoltageReading();
// ensure
longDataReqCounter = LONG_DATAREQ_INTERVAL + 1;
sleep_with_with_wakeup(2 * 1000UL);
break;
case CMD_DO_DEEPSLEEP:
showLongTermSleep();
currentTagMode = TAG_MODE_DEEPSLEEP;
break;
default:
printf("Unimplemented command 0x%02X\n", cmd);
break;
}
}

View File

@@ -31,3 +31,4 @@
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
void applyUpdate(uint32_t len);
void executeCommand(uint8_t cmd);

View File

@@ -68,3 +68,6 @@ uint32_t timerMs(){
return (uint32_t)(diff/TIMER_TICKS_PER_MSEC);
}
uint32_t millis(){
return (uint32_t)(timerGet() / TIMER_TICKS_PER_MSEC);
}

View File

@@ -11,6 +11,8 @@ uint64_t timerGet(void);
void timerStop(void);
uint32_t timerMs(void);
uint32_t millis();
void timerDelay(uint64_t cycles);

View File

@@ -31,17 +31,12 @@ extern "C" {
#define FW88MZ100
#define HAL_PacketRX commsRxUnenc
#define millis() timerGet()
#define HAL_TIMER_TICK (TIMER_TICKS_PER_MSEC)
void inline HAL_msDelay(uint32_t t) {
timerDelay(t * TIMER_TICKS_PER_MSEC);
}
void executeCommand(uint8_t c) {
}
void loadSettingsFromBuffer(uint8_t *buffer) {
}

View File

@@ -18,6 +18,7 @@ extern "C" {
#include "screen.h"
#include "mz100/util.h"
#include "zigbee.h"
#include "mz100/timer.h"
}
__attribute__((section(".aonshadow"))) uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
@@ -120,9 +121,7 @@ void powerDown(const uint8_t parts) {
}
void doSleep(const uint32_t t) {
printf("Sleeping for: %d ms\r\n", t);
// sleepForMs(t);
delay(t);
timerDelay(t*TIMER_TICKS_PER_MSEC);
}
uint32_t getNextScanSleep(const bool increment) {

View File

@@ -27,13 +27,13 @@
// power saving algorithm
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
#define INTERVAL_AT_MAX_ATTEMPTS 300 // interval (in seconds) (at max attempts) for target average current
#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request.
#define DATA_REQ_RX_WINDOW_SIZE 4UL // How many milliseconds we should wait for a packet during the data_request.
// If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address
#define DATA_REQ_MAX_ATTEMPTS 3 // How many attempts (at most) we should do to get something back from the AP
#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval
#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life!
#define MAXIMUM_PING_ATTEMPTS 3 // How many attempts to discover an AP the tag should do
#define PING_REPLY_WINDOW 5UL
#define PING_REPLY_WINDOW 10UL
#define LONG_DATAREQ_INTERVAL 300 // How often (in seconds, approximately) the tag should do a long datareq (including temperature)
#define VOLTAGE_CHECK_INTERVAL 288 // How often the tag should do a battery voltage check (multiplied by LONG_DATAREQ_INTERVAL)

View File

@@ -3,8 +3,8 @@
#include <stdint.h>
#define FW_VERSION 0x0027 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-zlib" // suffix, like -RC1 or whatever.
#define FW_VERSION 0x0028 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-cmds" // 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

View File

@@ -83,15 +83,12 @@ void showSplashScreen() {
fr.epdPrintf(10, 350, 0, rotation::ROTATE_0, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(80, 160, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.setFont((char *)"font/FreeSans9pt7b");
fr.epdPrintf(622, 290, 0, rotation::ROTATE_270, "v%04X%s", FW_VERSION, FW_VERSION_SUFFIX);
fr.epdPrintf(622, 280, 0, rotation::ROTATE_270, "v%04X%s", FW_VERSION, FW_VERSION_SUFFIX);
selectLUT(1);
draw();
epdEnterSleep();
}
#define FW_VERSION 0x0027 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-zlib" // suffix, like -RC1 or whatever.
void showApplyUpdate() {
epdSetup();
fs->init();
@@ -120,7 +117,7 @@ void showAPFound() {
fr.epdPrintf(10, 315, 0, rotation::ROTATE_0, "Battery: %d.%dV", batteryVoltage / 1000, batteryVoltage % 1000);
fr.epdPrintf(10, 350, 0, rotation::ROTATE_0, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.setFont((char *)"font/FreeSans9pt7b");
fr.epdPrintf(622, 290, 0, rotation::ROTATE_270, "v%04X%s", FW_VERSION, FW_VERSION_SUFFIX);
fr.epdPrintf(622, 280, 0, rotation::ROTATE_270, "v%04X%s", FW_VERSION, FW_VERSION_SUFFIX);
addOverlay();
if (lowBatteryShown) {
@@ -154,16 +151,12 @@ void showNoAP() {
}
void showLongTermSleep() {
// selectLUT(EPD_LUT_NO_REPEATS);
// clearScreen();
// epdPrintBegin(2, SCREEN_HEIGHT - 16, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
// epdpr("zZ");
// epdPrintEnd();
addOverlay();
// drawWithSleep();
epdSetup();
selectLUT(0);
draw();
epdEnterSleep();
}
void showNoEEPROM() {
// selectLUT(EPD_LUT_NO_REPEATS);
// clearScreen();

View File

@@ -134,7 +134,7 @@ void getTemperature() {
temperature = (uint8_t)(temp / 100);
printf("temp = %lu.%lu\n", temp / 100, temp % 100);
//printf("temp = %lu.%lu\n", temp / 100, temp % 100);
}
void boardGetOwnMac(uint8_t *mac) {

View File

@@ -105,6 +105,7 @@ struct tagSpecs {
uint8_t buttonCount = 0;
bool hasNFC = false;
bool hasLED = false;
bool hasThirdColor = false;
uint16_t macSuffix = 0x0000;
uint8_t OEPLtype = 0;
uint8_t solumType = 0;

View File

@@ -36,6 +36,13 @@ void identifyTagInfo() {
CA FE BA DE 15 0B 12 04 00 10 01 E0 01 20 03 39 00 03 81 9D 00 00 4C FF FF FF FF FF FF FF FF FF 7.4 UC8179
F3 22 BC 05 15 0A 0D 04 00 19 01 A0 02 C0 03 38 07 07 01 80 00 00 64 FF FF FF FF FF FF FF FF FF 9.7 SSD
AD BA FE CA 15 0A 1B 04 00 19 01 A0 02 C0 03 38 07 07 01 80 00 00 64 FF FF FF FF FF FF FF FF FF 9.7 type 2
92 C3 80 05 15 08 19 04 00 12 01 18 03 10 01 04 07 07 01 80 00 00 63 FF FF FF FF FF FF FF FF FF 5.85 BWR
22 F0 BF 05 15 0A 14 04 00 12 00 18 03 10 01 04 07 07 01 80 00 00 24 FF FF FF FF FF FF FF FF FF 5.85 BW
99 78 B1 05 15 0A 06 04 00 0D 01 68 01 B8 00 38 07 07 01 80 00 00 43 FF FF FF FF FF FF FF FF FF 2.6"
72 92 1E 7E 15 0B 09 04 00 15 00 80 01 A8 00 38 00 01 01 9C 00 00 22 FF FF FF FF FF FF FF FF FF 2.9" FREEZER
31 50 53 06 16 02 19 04 00 12 01 C8 00 C8 00 04 00 07 01 9C 00 00 40 FF FF FF FF FF FF FF FF FF
MAC | calib | |?????|Xres |Yres | ??? |capab| |type|
@@ -49,7 +56,7 @@ void identifyTagInfo() {
0x12 - SSD (var1.6)
0x15 - SSD (2.9 lite)
0x19 - SSD (9.7)
0x0A - Have third color?
0x12 - 0x01 | (0x80 if it has a button)
0x13 - 0x80 | (0x10 if it has a LED) | (0x0C ?? ) | (0x01 if it has a button)
*/
@@ -65,12 +72,20 @@ void identifyTagInfo() {
capabilities[1] = getUICRByte(0x13);
tag.solumType = getUICRByte(0x16);
if (getUICRByte(0x0A) == 0x01) {
tag.hasThirdColor = true;
}
switch (controllerType) {
case 0x0F:
case 0x12:
case 0x15:
case 0x19:
epd = new unissd;
if (epdXRes == 792 && epdYRes == 272) {
epd = new dualssd;
} else {
epd = new unissd;
}
break;
case 0x0D:
epd = new epdvar29;
@@ -106,6 +121,28 @@ void identifyTagInfo() {
if (capabilities[1] & 0x10) tag.hasLED = true;
if (capabilities[0] & 0x01) tag.hasNFC = true;
#ifdef DEBUG_SHOW_TAGINFO
printf("TagType report:\n");
printf("Resolution: %d*%d Px\n", epd->Xres, epd->Yres);
printf("Nb of buttons: %d\n", tag.buttonCount);
if (tag.hasLED) {
printf("This tag have a led: Yes\n");
} else {
printf("This tag have a led: No\n");
}
if (tag.hasNFC) {
printf("This tag have NFC: Yes\n");
} else {
printf("This tag have NFC: No\n");
}
if (tag.hasThirdColor) {
printf("This tag is Black and white only: No\n");
} else {
printf("This tag is Black and white only: Yes\n");
}
#endif
// we'll calculate image slot size here
uint32_t imageSize = epd->Xres * epd->Yres / 4;
tag.imageSize = ((imageSize + EEPROM_ERZ_SECTOR_SZ - 1) / EEPROM_ERZ_SECTOR_SZ) * EEPROM_ERZ_SECTOR_SZ;
@@ -115,6 +152,8 @@ void identifyTagInfo() {
tag.macSuffix = 0xB0D0;
epd->epdMirrorV = true;
tag.OEPLtype = SOLUM_M3_BWR_16;
epd->effectiveXRes = epdXRes;
epd->effectiveYRes = epdYRes - 1; // Yeah... I wonder why too....
break;
case STYPE_SIZE_022:
tag.macSuffix = 0xB190;
@@ -122,6 +161,12 @@ void identifyTagInfo() {
tag.OEPLtype = SOLUM_M3_BWR_22;
epd->XOffset = 8;
break;
case STYPE_SIZE_026:
tag.macSuffix = 0xB3D0;
epd->drawDirectionRight = true;
tag.OEPLtype = SOLUM_M3_BWR_26;
epd->XOffset = 8;
break;
case STYPE_SIZE_029:
tag.OEPLtype = SOLUM_M3_BWR_29;
if (tag.buttonCount == 2) {
@@ -134,6 +179,12 @@ void identifyTagInfo() {
epd->drawDirectionRight = true;
epd->XOffset = 8;
break;
case STYPE_SIZE_029_FREEZER:
tag.OEPLtype = SOLUM_M3_BW_29;
tag.macSuffix = 0x82D0;
epd->drawDirectionRight = true;
epd->XOffset = 8;
break;
case STYPE_SIZE_042:
tag.macSuffix = 0xB6D0;
tag.OEPLtype = SOLUM_M3_BWR_42;
@@ -145,6 +196,14 @@ void identifyTagInfo() {
// epd->mirrorH = true;
tag.OEPLtype = SOLUM_M3_BWR_43;
break;
case STYPE_SIZE_058:
tag.macSuffix = 0xE3D0;
tag.OEPLtype = SOLUM_M3_BWR_58;
break;
case STYPE_SIZE_058_FREEZER:
tag.macSuffix = 0x84D0;
tag.OEPLtype = SOLUM_M3_BW_58;
break;
case STYPE_SIZE_060:
tag.macSuffix = 0xB890;
tag.OEPLtype = SOLUM_M3_BWR_60;

View File

@@ -49,6 +49,8 @@
#define BATTERY_VOLTAGE_MINIMUM 2450 // 2600 or below is the best we can do on the EPD
#define WAKE_SECOND_CHECKIN_DELAY 10000UL
// power saving when no AP's were found (scanning every X)
#define VOLTAGEREADING_DURING_SCAN_INTERVAL 2 // how often we should read voltages; this is done every scan attempt in interval bracket 3
#define INTERVAL_1_TIME 3600UL // Try every hour

View File

@@ -5,12 +5,26 @@
#define FW_VERSION 0x0027 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "ZLIB" // suffix, like RC1 or whatever.
#define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
#endif
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
// #define DEBUG_SHOW_TAGINFO
// #define DEBUG_DRAWING
// #define DEBUG_EPD
// #define DEBUG_FS
// #define DEBUG_COMPRESSION
// #define DEBUG_PROTO
// #define DEBUG_SETTINGS
// #define DEBUG_MAIN
// #define DEBUG_FAST_CHECK_IN
// #define DEBUG_DONTVALIDATEPROTO
#if defined(DEBUG_SETTINGS) || defined(DEBUG_EPD) || defined(DEBUGBLOCKS) || defined(DEBUG_PROTO) || defined(DEBUG_COMPRESSION) || defined(DEBUG_FS) || defined(DEBUG_MAIN) || defined(DEBUG_FAST_CHECK_IN) || defined(DEBUG_SHOW_TAGINFO) || defined(DEBUG_DONTVALIDATEPROTO) || defined(DEBUG_DRAWING)
#define DEBUG_BUILD
#define DEBUG_DRAWING
#endif
#define SETTINGS_STRUCT_VERSION 0x01

View File

@@ -1,5 +1,5 @@
[platformio]
core_dir = $PROJECT_DIR/core
core_dir = D:/Documents/GitHub/OpenEPaperLink/ARM_Tag_FW/Newton_M3_nRF52811/core
[env]
platform = nordicnrf52@9.6.0

View File

@@ -0,0 +1,212 @@
#include <Arduino.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lut.h"
#include "settings.h"
#include "hal.h"
#include "wdt.h"
#include "drawing.h"
#include "dualssd.h"
#define CMD_DRV_OUTPUT_CTRL 0x01
#define CMD_SOFT_START_CTRL 0x0C
#define CMD_ENTER_SLEEP 0x10
#define CMD_DATA_ENTRY_MODE 0x11
#define CMD_SOFT_RESET 0x12
#define CMD_SOFT_RESET2 0x13
#define CMD_SETUP_VOLT_DETECT 0x15
#define CMD_TEMP_SENSOR_CONTROL 0x18
#define CMD_ACTIVATION 0x20
#define CMD_DISP_UPDATE_CTRL 0x21
#define CMD_DISP_UPDATE_CTRL2 0x22
#define CMD_WRITE_FB_BW 0x24
#define CMD_WRITE_FB_RED 0x26
#define CMD_VCOM_GLITCH_CTRL 0x2B
#define CMD_LOAD_OTP_LUT 0x31
#define CMD_WRITE_LUT 0x32
#define CMD_BORDER_WAVEFORM_CTRL 0x3C
#define CMD_WINDOW_X_SIZE 0x44
#define CMD_WINDOW_Y_SIZE 0x45
#define CMD_WRITE_PATTERN_RED 0x46
#define CMD_WRITE_PATTERN_BW 0x47
#define CMD_XSTART_POS 0x4E
#define CMD_YSTART_POS 0x4F
#define CMD_ANALOG_BLK_CTRL 0x74
#define CMD_DIGITAL_BLK_CTRL 0x7E
#define SCREEN_CMD_CLOCK_ON 0x80
#define SCREEN_CMD_CLOCK_OFF 0x01
#define SCREEN_CMD_ANALOG_ON 0x40
#define SCREEN_CMD_ANALOG_OFF 0x02
#define SCREEN_CMD_LATCH_TEMPERATURE_VAL 0x20
#define SCREEN_CMD_LOAD_LUT 0x10
#define SCREEN_CMD_USE_MODE_2 0x08 // modified commands 0x10 and 0x04
#define SCREEN_CMD_REFRESH 0xC7
#define CONTROLLER_ONE 0x00
#define CONTROLLER_TWO 0x80
void dualssd::selectLUT(uint8_t lut) {
// implement alternative LUTs here. Currently just reset the watchdog to two minutes,
// to ensure it doesn't reset during the much longer bootup procedure
lut += 1; // make the compiler a happy camper
wdt120s();
return;
}
void dualssd::epdEnterSleep() {
epdWrite(CMD_ENTER_SLEEP, 1, 0x01);
}
void dualssd::epdSetup() {
printf("init epd...\n");
epdReset();
epdWrite(CMD_SOFT_RESET, 0);
delay(10);
switch (this->controllerType) {
case 0x0F:
case 0x12:
case 0x15:
/* 5.85 INIT SEQUENCE
0x11, 0x00
0x91, 0x01
0x44, 0x31, 0x00
0x45, 0x0F, 0x01, 0x00, 0x00
0x4E, 0x31
0x4F, 0x0F, 0x01
0xC4, 0x00, 0x31
0xC5, 0x0F, 0x01, 0x00, 0x00
0xCE, 0x00
0xCF, 0x0F, 0x01
0x3C, 0x01
*/
/* 5.85 BW INIT SEQUENCE
0x11, 0x00
0x91, 0x01
0x44, 0x31, 0x00
0x45, 0x0F, 0x01, 0x00, 0x00
0x4E, 0x31
0x4F, 0x0F, 0x01
0xC4, 0x00, 0x31
0xC5, 0x0F, 0x01, 0x00, 0x00
0xCE, 0x00
0xCF, 0x0F, 0x01
0x3C, 0x01
*/
epdWrite(CMD_DATA_ENTRY_MODE + CONTROLLER_ONE, 1, 0x02);
epdWrite(CMD_DATA_ENTRY_MODE + CONTROLLER_TWO, 1, 0x03);
if (tag.hasThirdColor) {
epdWrite(CMD_DISP_UPDATE_CTRL, 2, 0x08, 0x10);
} else {
epdWrite(CMD_DISP_UPDATE_CTRL, 2, 0x48, 0x10);
}
epdWrite(CMD_WINDOW_X_SIZE + CONTROLLER_ONE, 2, 0x31, 0x00);
epdWrite(CMD_WINDOW_Y_SIZE + CONTROLLER_ONE, 4, 0x00, 0x00, 0x0F, 0x01);
epdWrite(CMD_XSTART_POS + CONTROLLER_ONE, 1, 0x31);
epdWrite(CMD_YSTART_POS + CONTROLLER_ONE, 2, 0x00, 0x00);
epdWrite(CMD_WINDOW_X_SIZE + CONTROLLER_TWO, 2, 0x00, 0x31);
epdWrite(CMD_WINDOW_Y_SIZE + CONTROLLER_TWO, 4, 0x00, 0x00, 0x0F, 0x01);
epdWrite(CMD_XSTART_POS + CONTROLLER_TWO, 1, 0x00);
epdWrite(CMD_YSTART_POS + CONTROLLER_TWO, 2, 0x0F, 0x01);
epdWrite(CMD_BORDER_WAVEFORM_CTRL, 1, 0x01);
break;
}
}
void dualssd::epdWriteDisplayData() {
uint8_t *buf[2] = {0, 0}; // this will hold pointers to odd/even data lines
// Those dual SSD controller (SSD1683??) behave as 2 400pxx wide screens, that needs independent data transfers.
uint8_t c_increment = 1;
if (!tag.hasThirdColor) {
c_increment = 2;
}
for (uint8_t c = 0; c < 4; c = c + c_increment) {
delay(10);
if (c == 0) epd_cmd(CMD_WRITE_FB_BW + CONTROLLER_ONE); // BW
if (c == 1) epd_cmd(CMD_WRITE_FB_RED + CONTROLLER_ONE); // RED
if (c == 2) epd_cmd(CMD_WRITE_FB_BW + CONTROLLER_TWO); // BW
if (c == 3) epd_cmd(CMD_WRITE_FB_RED + CONTROLLER_TWO); // RED
delay(10);
markData();
epdSelect();
for (uint16_t curY = 0; curY < epd->effectiveYRes; curY += 2) {
// Get 'even' screen line
buf[0] = (uint8_t *)calloc(epd->effectiveXRes / 8, 1);
drawItem::renderDrawLine(buf[0], curY, c % 2);
if (epd->epdMirrorH) drawItem::reverseBytes(buf[0], epd->effectiveXRes / 8);
// on the first pass, the second (buf[1]) buffer is unused, so we don't have to wait for it to flush to the display / free it
if (buf[1]) {
// wait for 'odd' display line to finish writing to the screen
epdSPIWait();
free(buf[1]);
}
// start transfer of even data line to the screen
if (c < 2) {
epdSPIAsyncWrite(buf[0] + (epd->effectiveXRes / 16), (epd->effectiveXRes / 16) + 1);
} else {
epdSPIAsyncWrite(buf[0], (epd->effectiveXRes / 16) + 1);
}
// Get 'odd' screen display line
buf[1] = (uint8_t *)calloc(epd->effectiveXRes / 8, 1);
drawItem::renderDrawLine(buf[1], curY + 1, c % 2);
if (epd->epdMirrorH) drawItem::reverseBytes(buf[1], epd->effectiveXRes / 8);
// wait until the 'even' data has finished writing
epdSPIWait();
free(buf[0]);
// start transfer of the 'odd' data line
if (c < 2) {
epdSPIAsyncWrite(buf[1] + (epd->effectiveXRes / 16), (epd->effectiveXRes / 16) + 1);
} else {
epdSPIAsyncWrite(buf[1], (epd->effectiveXRes / 16) + 1);
}
}
// check if this was the first pass. If it was, we'll need to wait until the last display line finished writing
if (c == 0 || c == 2) {
epdSPIWait();
epdDeselect();
free(buf[1]);
buf[1] = nullptr;
}
}
// flush the draw list, make sure items don't appear on subsequent screens
drawItem::flushDrawItems();
// wait until the last line of display has finished writing and clean our stuff up
epdSPIWait();
epdDeselect();
if (buf[1]) free(buf[1]);
}
void dualssd::draw() {
drawNoWait();
getVoltage();
epdBusyWaitFalling(120000);
}
void dualssd::drawNoWait() {
epdWriteDisplayData();
// epdWrite(CMD_DISP_UPDATE_CTRL2, 1, 0xF7);
epdWrite(CMD_ACTIVATION, 0);
}
void dualssd::epdWaitRdy() {
epdBusyWaitFalling(120000);
}

View File

@@ -0,0 +1,23 @@
#ifndef _EPD_DUALSSD_H_
#define _EPD_DUALSSD_H_
class dualssd : public epdInterface {
public:
void epdSetup();
void epdEnterSleep();
void draw();
void drawNoWait();
void epdWaitRdy();
void epdWriteDisplayData();
void selectLUT(uint8_t lut);
protected:
void commandReadBegin(uint8_t cmd);
void commandReadEnd();
uint8_t epdReadByte();
void setWindowX(uint16_t start, uint16_t end);
void setWindowY(uint16_t start, uint16_t end);
void setPosXY(uint16_t x, uint16_t y);
};
#endif

View File

@@ -21,6 +21,7 @@ void selectLUT(uint8_t lut);
#include "uc_variant_043.h"
#include "unissd.h"
#include "dualssd.h"
#include "uc_variant_029.h"
#include "uc8159.h"
#include "uc8179.h"

View File

@@ -75,14 +75,23 @@ void unissd::epdSetup() {
case 0x15:
// stock init 1.6"
epdWrite(CMD_DRV_OUTPUT_CTRL, 3, this->effectiveYRes & 0xFF, this->effectiveYRes >> 8, 0x00);
epdWrite(CMD_DATA_ENTRY_MODE, 1, 0x01);
if (epd->epdMirrorV) {
epdWrite(CMD_DATA_ENTRY_MODE, 1, 0x03);
epdWrite(CMD_WINDOW_Y_SIZE, 4, this->YOffset & 0xFF, this->YOffset >> 8, (this->YOffset + this->effectiveYRes) & 0xFF, (this->YOffset + this->effectiveYRes) >> 8);
} else {
epdWrite(CMD_DATA_ENTRY_MODE, 1, 0x01);
epdWrite(CMD_WINDOW_Y_SIZE, 4, (this->YOffset + this->effectiveYRes) & 0xFF, (this->YOffset + this->effectiveYRes) >> 8, this->YOffset & 0xFF, this->YOffset >> 8);
}
epdWrite(CMD_WINDOW_X_SIZE, 2, this->XOffset / 8, ((this->XOffset + this->effectiveXRes) / 8) - 1);
epdWrite(CMD_WINDOW_Y_SIZE, 4, (this->YOffset + this->effectiveYRes) & 0xFF, (this->YOffset + this->effectiveYRes) >> 8, this->YOffset & 0xFF, this->YOffset >> 8);
epdWrite(CMD_BORDER_WAVEFORM_CTRL, 1, 0x05);
epdWrite(CMD_TEMP_SENSOR_CONTROL, 1, 0x80);
// end stock init
// added
epdWrite(CMD_DISP_UPDATE_CTRL, 2, 0x08, 0x00); // fix reversed image with stock setup
if (tag.hasThirdColor) {
epdWrite(CMD_DISP_UPDATE_CTRL, 2, 0x08, 0x00); // fix reversed image with stock setup
} else {
epdWrite(CMD_DISP_UPDATE_CTRL, 2, 0x48, 0x00); // fix reversed image with stock setup
}
break;
case 0x19:
// stock init 9.7"
@@ -108,13 +117,21 @@ void unissd::epdSetup() {
void unissd::epdWriteDisplayData() {
// this display expects two entire framebuffers worth of data to be written, one for b/w and one for red
uint8_t *buf[2] = {0, 0}; // this will hold pointers to odd/even data lines
for (uint8_t c = 0; c < 2; c++) {
uint8_t c_end = 2; // The loop must be executed 2 times if BWR, 1 time if BW
if (!tag.hasThirdColor) {
c_end = 1;
}
for (uint8_t c = 0; c < c_end; c++) {
switch (this->controllerType) {
case 0x0F:
case 0x12:
case 0x15:
epdWrite(CMD_XSTART_POS, 1, (this->XOffset / 8));
epdWrite(CMD_YSTART_POS, 2, (this->YOffset + this->effectiveYRes) & 0xFF, (this->YOffset + this->effectiveYRes) >> 8);
if (epd->epdMirrorV) {
epdWrite(CMD_YSTART_POS, 2, this->YOffset & 0xFF, (this->YOffset) >> 8);
} else {
epdWrite(CMD_YSTART_POS, 2, (this->YOffset + this->effectiveYRes) & 0xFF, (this->YOffset + this->effectiveYRes) >> 8);
}
break;
case 0x19:
epdWrite(CMD_XSTART_POS, 2, 0xBF, 0x03);
@@ -130,11 +147,8 @@ void unissd::epdWriteDisplayData() {
// Get 'even' screen line
buf[0] = (uint8_t *)calloc(epd->effectiveXRes / 8, 1);
if (epd->epdMirrorV) {
drawItem::renderDrawLine(buf[0], (epd->effectiveYRes - 1) - curY, c);
} else {
drawItem::renderDrawLine(buf[0], curY, c);
}
drawItem::renderDrawLine(buf[0], curY, c);
if (epd->epdMirrorH) drawItem::reverseBytes(buf[0], epd->effectiveXRes / 8);
// on the first pass, the second (buf[1]) buffer is unused, so we don't have to wait for it to flush to the display / free it
if (buf[1]) {
@@ -148,11 +162,9 @@ void unissd::epdWriteDisplayData() {
// Get 'odd' screen display line
buf[1] = (uint8_t *)calloc(epd->effectiveXRes / 8, 1);
if (epd->epdMirrorV) {
drawItem::renderDrawLine(buf[1], (epd->effectiveYRes - 1) - (curY + 1), c);
} else {
drawItem::renderDrawLine(buf[1], curY + 1, c);
}
drawItem::renderDrawLine(buf[1], curY + 1, c);
if (epd->epdMirrorH) drawItem::reverseBytes(buf[1], epd->effectiveXRes / 8);
// wait until the 'even' data has finished writing

View File

@@ -84,25 +84,10 @@ bool displayCustomImage(uint8_t imagetype) {
return false;
}
void externalWakeHandler(uint8_t type) {
if (displayCustomImage(type)) {
doSleep(2000);
// if something else was previously on the display, draw that
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
uint8_t lut = getEepromImageDataArgument(curImgSlot);
lut &= 0x03;
powerUp(INIT_EPD);
drawImageFromEeprom(curImgSlot, lut);
powerDown(INIT_EPD | INIT_EEPROM);
}
}
}
void TagAssociated() {
// associated
bool fastNextCheckin = false;
uint32_t fastNextCheckinDelay = WAKE_SECOND_CHECKIN_DELAY;
struct AvailDataInfo *avail;
static bool buttonCheckOut = false; // send another full request if the previous was a trigger reason (buttons, nfc)
// Is there any reason why we should do a long (full) get data request (including reason, status)?
@@ -139,23 +124,23 @@ void TagAssociated() {
switch (wakeUpReason) {
case WAKEUP_REASON_BUTTON1:
externalWakeHandler(CUSTOM_IMAGE_BUTTON1);
if (displayCustomImage(CUSTOM_IMAGE_BUTTON1)) fastNextCheckinDelay = 0;
fastNextCheckin = true;
break;
case WAKEUP_REASON_BUTTON2:
externalWakeHandler(CUSTOM_IMAGE_BUTTON2);
if (displayCustomImage(CUSTOM_IMAGE_BUTTON2)) fastNextCheckinDelay = 0;
fastNextCheckin = true;
break;
case WAKEUP_REASON_GPIO:
externalWakeHandler(CUSTOM_IMAGE_GPIO);
if (displayCustomImage(CUSTOM_IMAGE_GPIO)) fastNextCheckinDelay = 0;
fastNextCheckin = true;
break;
case WAKEUP_REASON_RF:
externalWakeHandler(CUSTOM_IMAGE_RF_WAKE);
if (displayCustomImage(CUSTOM_IMAGE_RF_WAKE)) fastNextCheckinDelay = 0;
fastNextCheckin = true;
break;
case WAKEUP_REASON_NFC:
externalWakeHandler(CUSTOM_IMAGE_NFC_WAKE);
if (displayCustomImage(CUSTOM_IMAGE_NFC_WAKE)) fastNextCheckinDelay = 0;
fastNextCheckin = true;
break;
}
@@ -168,7 +153,7 @@ void TagAssociated() {
}
// since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status
if ((wakeUpReason == WAKEUP_REASON_BUTTON1) | (wakeUpReason == WAKEUP_REASON_BUTTON2) | (wakeUpReason == WAKEUP_REASON_NFC) | (wakeUpReason == CUSTOM_IMAGE_RF_WAKE)) {
if ((wakeUpReason == WAKEUP_REASON_GPIO) | (wakeUpReason == WAKEUP_REASON_BUTTON1) | (wakeUpReason == WAKEUP_REASON_BUTTON2) | (wakeUpReason == WAKEUP_REASON_NFC) | (wakeUpReason == CUSTOM_IMAGE_RF_WAKE)) {
buttonCheckOut = true;
}
wakeUpReason = WAKEUP_REASON_TIMED;
@@ -225,9 +210,13 @@ void TagAssociated() {
if (fastNextCheckin) {
// do a fast check-in next
fastNextCheckin = false;
doSleep(100UL);
if (fastNextCheckinDelay) {
doSleep(fastNextCheckinDelay);
} else {
doSleep(100UL);
}
} else {
if (nextCheckInFromAP) {
if (nextCheckInFromAP & 0x7FFF) {
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP & 0x8000) {
doSleep((nextCheckInFromAP & 0x7FFF) * 1000UL);

View File

@@ -25,20 +25,21 @@ struct fwmetadata {
#define EEPROM_SETTINGS_SIZE 4096
#define BLOCKSIZE_MS 240 // was 270
#define BLOCKSIZE_MS 280 // was 270
#define FWNRF
#define LEDSENABLED
#define PERSISTENTVAR
#define HAL_TIMER_TICK 1
#define PERSISTENTVAR
#define EEPROM_IMG_START 0
;
#define HAL_PacketRX commsRxUnencrypted
#define HAL_msDelay delay
void dump(const uint8_t *a, const uint16_t l);
extern void executeCommand(uint8_t cmd); // this is defined in main.c
static void saveUpdateMetadata(uint32_t size) {
struct fwmetadata metadata;
metadata.magic1 = MAGIC1;
@@ -71,8 +72,12 @@ static bool validateEepromMD5(uint64_t ver, uint32_t eepromstart, uint32_t flen)
printf("This is what we got:\n");
dump(hash, 16);
}
#ifdef DEBUG_DONTVALIDATEPROTO
return true;
#else
return isValid;
#endif
}
#include "../../common/oepl-protocol.cpp"

View File

@@ -26,12 +26,19 @@ bool lowBatteryShown = false;
bool noAPShown = false;
void addOverlay() {
if (currentChannel == 0) {
drawMask(epd->Xres - 27, 5, 22, 22, COLOR_BLACK);
drawMask(epd->Xres - 27, 5, 22, 22, COLOR_RED);
drawRoundedRectangle(epd->Xres - 28, 4, 24, 24, COLOR_RED);
addBufferedImage(epd->Xres - 24, 8, COLOR_BLACK, rotation::ROTATE_0, ant, DRAW_NORMAL);
addBufferedImage(epd->Xres - 16, 15, COLOR_RED, rotation::ROTATE_0, cross, DRAW_NORMAL);
drawMask(epd->Xres - 28, 4, 24, 24, COLOR_BLACK);
if(tag.hasThirdColor){
drawMask(epd->Xres - 28, 4, 24, 24, COLOR_RED);
drawRoundedRectangle(epd->Xres - 28, 4, 24, 24, COLOR_RED);
addBufferedImage(epd->Xres - 24, 8, COLOR_BLACK, rotation::ROTATE_0, ant, DRAW_NORMAL);
addBufferedImage(epd->Xres - 16, 15, COLOR_RED, rotation::ROTATE_0, cross, DRAW_NORMAL);
}else{
drawRoundedRectangle(epd->Xres - 28, 4, 24, 24, COLOR_BLACK);
addBufferedImage(epd->Xres - 24, 8, COLOR_BLACK, rotation::ROTATE_0, ant, DRAW_NORMAL);
addBufferedImage(epd->Xres - 16, 15, COLOR_BLACK, rotation::ROTATE_0, cross, DRAW_NORMAL);
}
noAPShown = true;
} else {
noAPShown = false;
@@ -39,8 +46,13 @@ void addOverlay() {
if (lowBattery) {
drawMask(epd->Xres - 27, epd->Yres - 26, 22, 22, COLOR_BLACK);
drawMask(epd->Xres - 27, epd->Yres - 26, 22, 22, COLOR_RED);
drawRoundedRectangle(epd->Xres - 28, epd->Yres - 26, 24, 24, COLOR_RED);
if(tag.hasThirdColor){
drawMask(epd->Xres - 27, epd->Yres - 26, 22, 22, COLOR_RED);
drawRoundedRectangle(epd->Xres - 28, epd->Yres - 26, 24, 24, COLOR_RED);
}else{
drawMask(epd->Xres - 27, epd->Yres - 26, 22, 22, COLOR_BLACK);
drawRoundedRectangle(epd->Xres - 28, epd->Yres - 26, 24, 24, COLOR_BLACK);
}
addBufferedImage(epd->Xres - 24, epd->Yres - 19, COLOR_BLACK, rotation::ROTATE_0, battery, DRAW_NORMAL);
lowBatteryShown = true;
} else {
@@ -48,10 +60,16 @@ void addOverlay() {
}
#ifdef DEBUG_BUILD
fontrender fr(&FreeSansBold18pt7b);
drawMask(15, epd->Yres - 53, 129, 33, COLOR_BLACK);
drawMask(15, epd->Yres - 53, 129, 33, COLOR_RED);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_RED);
fr.epdPrintf(17, epd->Yres - 50, COLOR_RED, rotation::ROTATE_0, "DEBUG");
drawMask(15, epd->Yres - 53, 130, 33, COLOR_BLACK);
if(tag.hasThirdColor){
drawMask(15, epd->Yres - 53, 130, 33, COLOR_RED);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_RED);
fr.epdPrintf(17, epd->Yres - 50, COLOR_RED, rotation::ROTATE_0, "DEBUG");
}else{
drawMask(15, epd->Yres - 53, 130, 33, COLOR_BLACK);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_BLACK);
fr.epdPrintf(17, epd->Yres - 50, COLOR_BLACK, rotation::ROTATE_0, "DEBUG");
}
#endif
}
@@ -67,9 +85,9 @@ void showSplashScreen() {
case STYPE_SIZE_016:
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
fr.epdPrintf(10, 38, COLOR_RED, rotation::ROTATE_0, "Newton M3 2.2\"");
fr.epdPrintf(10, 38, COLOR_RED, rotation::ROTATE_0, "Newton M3 1.6\"");
fr.epdPrintf(5, epd->Yres - 40, 0, rotation::ROTATE_0, "FW: %04X-%s", fwVersion, fwVersionSuffix);
fr.epdPrintf(2, epd->Yres - 20, 0, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(2, epd->Yres - 20, 0, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_022:
fr.setFont(&FreeSansBold18pt7b);
@@ -81,6 +99,16 @@ void showSplashScreen() {
fr.epdPrintf(5, epd->Yres - 20, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_026:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 38, COLOR_RED, rotation::ROTATE_0, "Newton M3 2.6\"");
// fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(5, epd->Yres - 40, 0, rotation::ROTATE_0, "FW: %04X-%s", fwVersion, fwVersionSuffix);
fr.epdPrintf(5, epd->Yres - 20, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_029:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
@@ -91,6 +119,16 @@ void showSplashScreen() {
fr.epdPrintf(5, epd->Yres - 20, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_029_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 38, COLOR_BLACK, rotation::ROTATE_0, "Newton M3 2.9\" Freezer");
// fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(epd->Xres - 17, 0, COLOR_BLACK, rotation::ROTATE_270, "FW: %04X-%s", fwVersion, fwVersionSuffix);
fr.epdPrintf(5, epd->Yres - 20, COLOR_BLACK, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_042:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
@@ -111,6 +149,26 @@ void showSplashScreen() {
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 32, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_058:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 38, COLOR_RED, rotation::ROTATE_0, "Newton M3 5.85\"");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(epd->Xres - 17, 0, 0, rotation::ROTATE_270, "FW: %04X-%s", fwVersion, fwVersionSuffix);
fr.epdPrintf(5, epd->Yres - 20, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_058_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 38, COLOR_BLACK, rotation::ROTATE_0, "Newton M3 5.85\" Freezer");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(epd->Xres - 17, 0, COLOR_BLACK, rotation::ROTATE_270, "FW: %04X-%s", fwVersion, fwVersionSuffix);
fr.epdPrintf(5, epd->Yres - 20, COLOR_BLACK, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_060:
fr.setFont(&FreeSansBold24pt7b);
fr.epdPrintf(10, 10, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink");
@@ -145,12 +203,19 @@ void showSplashScreen() {
addQR(260, 160, 3, 7, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
}
#ifdef DEBUGBLOCKS
#ifdef DEBUG_BUILD
drawMask(15, epd->Yres - 53, 129, 33, COLOR_BLACK);
drawMask(15, epd->Yres - 53, 129, 33, COLOR_RED);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_RED);
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(17, epd->Yres - 50, COLOR_RED, rotation::ROTATE_0, "DEBUG");
if(tag.hasThirdColor){
drawMask(15, epd->Yres - 53, 129, 33, COLOR_RED);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_RED);
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(17, epd->Yres - 50, COLOR_RED, rotation::ROTATE_0, "DEBUG");
}else{
drawMask(15, epd->Yres - 53, 129, 33, COLOR_BLACK);
drawRoundedRectangle(15, epd->Yres - 53, 129, 33, COLOR_BLACK);
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(17, epd->Yres - 50, COLOR_BLACK, rotation::ROTATE_0, "DEBUG");
}
#endif
draw();
}
@@ -198,6 +263,18 @@ void showAPFound() {
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_026:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 53, COLOR_RED, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]);
fr.epdPrintf(10, 71, COLOR_RED, rotation::ROTATE_0, "RSSI: %ddBm LQI: %d", mLastRSSI, mLastLqi);
fr.epdPrintf(10, 89, COLOR_RED, rotation::ROTATE_0, "Ch %d", currentChannel);
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, epd->Yres - 43, 0, rotation::ROTATE_0, "Battery: %d.%dV Temp: %d'C", batteryVoltage / 1000, batteryVoltage % 1000, temperature);
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_029:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
@@ -210,6 +287,18 @@ void showAPFound() {
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_029_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 53, COLOR_BLACK, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]);
fr.epdPrintf(10, 71, COLOR_BLACK, rotation::ROTATE_0, "RSSI: %ddBm LQI: %d", mLastRSSI, mLastLqi);
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "Ch %d", currentChannel);
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, epd->Yres - 43, 0, rotation::ROTATE_0, "Battery: %d.%dV Temp: %d'C", batteryVoltage / 1000, batteryVoltage % 1000, temperature);
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_042:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
@@ -235,6 +324,30 @@ void showAPFound() {
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_058:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 53, COLOR_RED, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]);
fr.epdPrintf(10, 71, COLOR_RED, rotation::ROTATE_0, "RSSI: %ddBm LQI: %d", mLastRSSI, mLastLqi);
fr.epdPrintf(10, 89, COLOR_RED, rotation::ROTATE_0, "Ch %d", currentChannel);
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, epd->Yres - 43, 0, rotation::ROTATE_0, "Battery: %d.%dV Temp: %d'C", batteryVoltage / 1000, batteryVoltage % 1000, temperature);
fr.epdPrintf(10, epd->Yres - 25, 0, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_058_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found");
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, 53, COLOR_BLACK, rotation::ROTATE_0, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]);
fr.epdPrintf(10, 71, COLOR_BLACK, rotation::ROTATE_0, "RSSI: %ddBm LQI: %d", mLastRSSI, mLastLqi);
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "Ch %d", currentChannel);
fr.setFont(&FreeSans9pt7b);
fr.epdPrintf(10, epd->Yres - 43, COLOR_BLACK, rotation::ROTATE_0, "Battery: %d.%dV Temp: %d'C", batteryVoltage / 1000, batteryVoltage % 1000, temperature);
fr.epdPrintf(10, epd->Yres - 25, COLOR_BLACK, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
break;
case STYPE_SIZE_060:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found - Waiting for data");
@@ -296,6 +409,16 @@ void showNoAP() {
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(10, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by pressing a button");
break;
case STYPE_SIZE_026:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
fr.setFont(&FreeSans9pt7b);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(10, 69, COLOR_BLACK, rotation::ROTATE_0, "Couldn't find an AP :(");
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(10, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning");
fr.epdPrintf(10, 129, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone");
break;
case STYPE_SIZE_029:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
@@ -305,6 +428,15 @@ void showNoAP() {
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(10, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by pressing a button");
break;
case STYPE_SIZE_029_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
fr.setFont(&FreeSans9pt7b);
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(10, 69, COLOR_BLACK, rotation::ROTATE_0, "Couldn't find an AP :(");
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(10, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by pressing a button");
break;
case STYPE_SIZE_042:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
@@ -328,6 +460,26 @@ void showNoAP() {
fr.epdPrintf(152, 89, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning");
fr.epdPrintf(152, 109, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone");
break;
case STYPE_SIZE_058:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
fr.setFont(&FreeSans9pt7b);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(10, 69, COLOR_BLACK, rotation::ROTATE_0, "Couldn't find an AP :(");
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(152, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning");
fr.epdPrintf(152, 129, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone");
break;
case STYPE_SIZE_058_FREEZER:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found");
fr.setFont(&FreeSans9pt7b);
addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(10, 69, COLOR_BLACK, rotation::ROTATE_0, "Couldn't find an AP :(");
fr.epdPrintf(10, 89, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(152, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning");
fr.epdPrintf(152, 129, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone");
break;
case STYPE_SIZE_060:
fr.setFont(&FreeSansBold18pt7b);
fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found U_U");
@@ -357,7 +509,8 @@ void showNoAP() {
addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
fr.epdPrintf(10, 39, COLOR_BLACK, rotation::ROTATE_0, "Couldn't find an AP :(");
fr.epdPrintf(10, 58, COLOR_BLACK, rotation::ROTATE_0, "I'll try again in a little while, but you");
fr.epdPrintf(10, 77, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by pressing a button");
fr.epdPrintf(10, 77, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning");
fr.epdPrintf(10, 98, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone");
addFlashImage(200, 128, COLOR_BLACK, rotation::ROTATE_0, pandablack);
addFlashImage(312, 274, COLOR_RED, rotation::ROTATE_0, pandared);
break;

View File

@@ -63,7 +63,7 @@ void addBufferedImage(uint16_t x, uint16_t y, bool color, enum rotation ro, cons
di->type = drawItem::drawType::DRAW_MASK;
else
di->type = drawItem::drawType::DRAW_BUFFERED_1BPP;
di->checkBounds();
di->addToList();
}
@@ -85,6 +85,7 @@ void addFlashImage(uint16_t x, uint16_t y, bool color, enum rotation ro, const u
di->color = color;
di->cleanUp = false;
di->type = drawItem::drawType::DRAW_BUFFERED_1BPP;
di->checkBounds();
di->addToList();
}
#ifdef ENABLE_OEPLFS
@@ -119,6 +120,7 @@ void addFSImage(uint16_t x, uint16_t y, uint8_t color, enum rotation ro, char *n
} else {
di->type = drawItem::drawType::DRAW_OEPLFS_1BPP;
}
di->checkBounds();
di->addToList();
}
@@ -153,6 +155,7 @@ void addCompressedFSImage(uint16_t x, uint16_t y, enum rotation ro, char *name)
di->color = imgheader.bpp;
if (di->color == 1) di->color = 0;
di->cleanUp = true;
di->checkBounds();
di->addToList();
}
#endif
@@ -207,6 +210,8 @@ void addQR(uint16_t x, uint16_t y, uint8_t version, uint8_t scale, const char *c
di->ypos = y;
di->color = 0;
di->type = drawItem::drawType::DRAW_BUFFERED_1BPP;
di->checkBounds();
di->addToList();
}
@@ -227,8 +232,12 @@ void drawImageAtAddressWrap(uint32_t addr, uint8_t lut) {
di->addItem((uint8_t *)addr, epd->effectiveXRes, epd->effectiveYRes);
di->type = drawItem::drawType::DRAW_EEPROM_1BPP;
di->direction = false;
if (di->mirrorH) di->mirrorV = !di->mirrorV;
if (di->mirrorH) {
di->mirrorH = 0;
di->mirrorV = !di->mirrorV;
}
di->cleanUp = false;
di->checkBounds();
di->addToList();
} break;
case DATATYPE_IMG_RAW_2BPP: {
@@ -240,8 +249,12 @@ void drawImageAtAddressWrap(uint32_t addr, uint8_t lut) {
di->addItem((uint8_t *)addr, epd->effectiveXRes, epd->effectiveYRes);
di->type = drawItem::drawType::DRAW_EEPROM_2BPP;
di->direction = false;
if (di->mirrorH) di->mirrorV = !di->mirrorV;
if (di->mirrorH) {
di->mirrorH = 0;
di->mirrorV = !di->mirrorV;
}
di->cleanUp = false;
di->checkBounds();
di->addToList();
} break;
case DATATYPE_IMG_ZLIB: {
@@ -271,10 +284,14 @@ void drawImageAtAddressWrap(uint32_t addr, uint8_t lut) {
di->xpos = 0;
di->ypos = 0;
di->direction = false;
if (di->mirrorH) di->mirrorV = !di->mirrorV;
if (di->mirrorH) {
di->mirrorH = 0;
di->mirrorV = !di->mirrorV;
}
if (imgheader.bpp == 1) di->color = 0;
if (imgheader.bpp == 2) di->color = 2;
di->cleanUp = true;
di->checkBounds();
di->addToList();
} break;
}
@@ -291,17 +308,19 @@ void drawImageAtAddress(uint32_t addr, uint8_t lut) {
void drawRoundedRectangle(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, bool color) {
uint16_t widthBytes = width / 8;
if (width % 8) widthBytes++;
uint32_t framebufferSize = (widthBytes + 1) * height;
uint32_t framebufferSize = widthBytes * height;
uint8_t *framebuffer = (uint8_t *)calloc(framebufferSize + 4, 1);
if (framebuffer == NULL) {
return;
}
((uint16_t *)framebuffer)[0] = width + 1;
uint8_t frameBufferZerosize = width;
if ((width % 8) != 0) {
frameBufferZerosize++;
}
((uint16_t *)framebuffer)[0] = frameBufferZerosize;
((uint16_t *)framebuffer)[1] = height;
framebuffer += 4;
uint16_t w = width - 1;
uint16_t x = 1;
while (w--) {
@@ -453,9 +472,9 @@ void drawItem::getXLine(uint8_t *line, uint16_t y, uint8_t c) {
}
}
if (mirrorH) {
copyWithByteShift(line, &buffer[((height - (y - ypos)) * widthBytes)], widthBytes, xpos / 8);
copyWithByteShift(line, &buffer[((height - (y - ypos)) * widthBytes)], drawnWidthBytes, xpos / 8);
} else {
copyWithByteShift(line, &buffer[((y - ypos) * widthBytes)], widthBytes, xpos / 8);
copyWithByteShift(line, &buffer[((y - ypos) * widthBytes)], drawnWidthBytes, xpos / 8);
}
}
break;
@@ -476,7 +495,7 @@ void drawItem::getXLine(uint8_t *line, uint16_t y, uint8_t c) {
if (mirrorV) {
reverseBytes(dbuffer, widthBytes);
}
copyWithByteShift(line, dbuffer, widthBytes, xpos / 8);
copyWithByteShift(line, dbuffer, drawnWidthBytes, xpos / 8);
free(dbuffer);
}
break;
@@ -496,20 +515,36 @@ void drawItem::getXLine(uint8_t *line, uint16_t y, uint8_t c) {
if (mirrorV) {
reverseBytes(dbuffer, widthBytes);
}
copyWithByteShift(line, dbuffer, widthBytes, xpos / 8);
copyWithByteShift(line, dbuffer, drawnWidthBytes, xpos / 8);
free(dbuffer);
}
break;
case DRAW_EEPROM_1BPP:
if (c != color) return;
if (epd->drawDirectionRight)
if (mirrorH)
y = epd->effectiveYRes - 1 - y;
HAL_flashRead((uint32_t)buffer + sizeof(struct EepromImageHeader) + (y * (epd->effectiveXRes / 8)), line, (epd->effectiveXRes / 8));
if (mirrorV) {
uint8_t *dbuffer = (uint8_t *)malloc(widthBytes);
HAL_flashRead((uint32_t)buffer + sizeof(struct EepromImageHeader) + (y * (epd->effectiveXRes / 8)), dbuffer, (epd->effectiveXRes / 8));
reverseBytes(dbuffer, widthBytes);
memcpy(line, dbuffer, widthBytes);
free(dbuffer);
} else {
HAL_flashRead((uint32_t)buffer + sizeof(struct EepromImageHeader) + (y * (epd->effectiveXRes / 8)), line, (epd->effectiveXRes / 8));
}
break;
case DRAW_EEPROM_2BPP:
if (epd->drawDirectionRight)
if (mirrorH)
y = epd->effectiveYRes - 1 - y;
HAL_flashRead((uint32_t)(buffer + sizeof(struct EepromImageHeader) + ((y + (c * epd->effectiveYRes)) * (epd->effectiveXRes / 8))), line, (epd->effectiveXRes / 8));
if (mirrorV) {
uint8_t *dbuffer = (uint8_t *)malloc(widthBytes);
HAL_flashRead((uint32_t)(buffer + sizeof(struct EepromImageHeader) + ((y + (c * epd->effectiveYRes)) * (epd->effectiveXRes / 8))), dbuffer, (epd->effectiveXRes / 8));
reverseBytes(dbuffer, widthBytes);
memcpy(line, dbuffer, widthBytes);
free(dbuffer);
} else {
HAL_flashRead((uint32_t)(buffer + sizeof(struct EepromImageHeader) + ((y + (c * epd->effectiveYRes)) * (epd->effectiveXRes / 8))), line, (epd->effectiveXRes / 8));
}
break;
default:
printf("DRAW: Not supported mode!\n");
@@ -639,6 +674,16 @@ bool drawItem::addToList() {
return false;
}
void drawItem::checkBounds() {
drawnWidthBytes = widthBytes;
// if(!direction){ // draw X lines
uint8_t availBytesWidth = epd->effectiveXRes / 8;
availBytesWidth -= (xpos / 8);
if (widthBytes < availBytesWidth) availBytesWidth = widthBytes;
drawnWidthBytes = availBytesWidth;
}
drawItem::~drawItem() {
if (cleanUp) {
switch (this->type) {
@@ -933,5 +978,6 @@ void fontrender::epdPrintf(uint16_t x, uint16_t y, bool color, enum rotation ro,
di->xpos = x;
di->color = color;
di->type = drawItem::drawType::DRAW_FONT;
di->checkBounds();
di->addToList();
}

View File

@@ -72,6 +72,8 @@ class drawItem {
static void renderDrawLine(uint8_t *line, uint16_t number, uint8_t c);
static void flushDrawItems();
void checkBounds();
// these are also used for rotated screens
static void reverseBytes(uint8_t *src, uint8_t src_len);
static uint8_t bitReverse(uint8_t byte);
@@ -113,6 +115,7 @@ class drawItem {
void getXLine(uint8_t *line, uint16_t yPos, uint8_t color);
void getYLine(uint8_t *line, uint16_t xPos, uint8_t color);
uint8_t widthBytes = 0;
uint8_t drawnWidthBytes = 0;
uint8_t *buffer = nullptr;
};

View File

@@ -23,8 +23,6 @@ volatile uint8_t PERSISTENTVAR currentChannel = 0;
static uint8_t inBuffer[128] = {0};
static uint8_t outBuffer[128] = {0};
extern void executeCommand(uint8_t cmd); // this is defined in main.c
// tools
static uint8_t getPacketType(const void *buffer) {
const struct MacFcs *fcs = (MacFcs *)buffer;
@@ -112,7 +110,7 @@ uint8_t detectAP(const uint8_t channel) {
radioRxEnable(true);
for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++) {
sendPing();
t = millis() + (HAL_TIMER_TICK * (PING_REPLY_WINDOW));
t = millis() + PING_REPLY_WINDOW;
while (millis() < t) {
int8_t ret = HAL_PacketRX(inBuffer);
if (ret > 1) {
@@ -126,7 +124,7 @@ uint8_t detectAP(const uint8_t channel) {
}
}
}
HAL_msDelay(1);
HAL_msDelay(10);
}
}
return 0;
@@ -179,7 +177,7 @@ struct AvailDataInfo *getAvailDataInfo() {
uint32_t t;
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) {
sendAvailDataReq();
t = millis() + (HAL_TIMER_TICK * (DATA_REQ_RX_WINDOW_SIZE));
t = millis() + DATA_REQ_RX_WINDOW_SIZE;
while (millis() < t) {
int8_t ret = HAL_PacketRX(inBuffer);
if (ret > 1) {
@@ -203,8 +201,7 @@ struct AvailDataInfo *getShortAvailDataInfo() {
uint32_t t;
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) {
sendShortAvailDataReq();
// sendAvailDataReq();
t = millis() + (HAL_TIMER_TICK * (DATA_REQ_RX_WINDOW_SIZE));
t = millis() + DATA_REQ_RX_WINDOW_SIZE;
while (millis() < t) {
int8_t ret = HAL_PacketRX(inBuffer);
if (ret > 1) {
@@ -251,7 +248,7 @@ static bool blockRxLoop(const uint32_t timeout, uint8_t *blockbuffer) {
uint32_t t;
bool success = false;
radioRxEnable(true);
t = millis() + (HAL_TIMER_TICK * (timeout + 20));
t = millis() + (timeout + 20);
bool blockComplete = false;
@@ -316,16 +313,17 @@ static struct blockRequestAck *performBlockRequest() {
uint32_t t;
radioRxEnable(true);
radioRxFlush();
for (uint8_t c = 0; c < 30; c++) {
for (uint8_t c = 0; c < 10; c++) {
sendBlockRequest();
t = millis() + (HAL_TIMER_TICK * ((7UL + c / 10)));
t = millis() + 6UL;
do {
int8_t ret = HAL_PacketRX(inBuffer);
if (ret > 1) {
switch (getPacketType(inBuffer)) {
case PKT_BLOCK_REQUEST_ACK:
if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck)))
if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck))) {
return (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
}
break;
case PKT_BLOCK_PART:
return continueToRX();
@@ -370,7 +368,7 @@ static void sendXferComplete() {
for (uint8_t c = 0; c < 16; c++) {
sendXferCompletePacket();
uint32_t start = millis();
while ((millis() - start) < (HAL_TIMER_TICK * (6UL))) {
while ((millis() - start) < (6UL)) {
int8_t ret = HAL_PacketRX(inBuffer);
if (ret > 1) {
if (getPacketType(inBuffer) == PKT_XFER_COMPLETE_ACK) {
@@ -591,7 +589,7 @@ static uint8_t *getDataBlock(const uint16_t blockSize) {
}
#ifdef FWNRF
doSleep(ack->pleaseWaitMs + 40);
doSleep(ack->pleaseWaitMs);
powerUp(INIT_UART | INIT_RADIO);
radioRxEnable(true);
#endif
@@ -656,8 +654,8 @@ static uint8_t *getDataBlock(const uint16_t blockSize) {
}
static uint32_t downloadFWUpdate(const struct AvailDataInfo *avail) {
uint16_t dataRequestSize = 0;
uint32_t curXferSize = 0;
static uint32_t PERSISTENTVAR curXferSize = 0;
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&xferDataInfo.dataVer, 8) && xferDataInfo.dataSize) {
// looks like we did. We'll carry on where we left off.
@@ -672,6 +670,7 @@ static uint32_t downloadFWUpdate(const struct AvailDataInfo *avail) {
}
while (xferDataInfo.dataSize) {
uint16_t dataRequestSize = 0;
wdt10s();
if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining
@@ -709,8 +708,8 @@ static uint32_t downloadFWUpdate(const struct AvailDataInfo *avail) {
}
static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) {
uint16_t dataRequestSize = 0;
uint32_t curXferSize = 0;
static uint32_t PERSISTENTVAR curXferSize = 0;
powerUp(INIT_EEPROM);
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&xferDataInfo.dataVer, 8) && xferDataInfo.dataSize) {
@@ -772,6 +771,7 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) {
}
while (xferDataInfo.dataSize) {
uint16_t dataRequestSize = 0;
wdt10s();
if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) {
// more than one block remaining

View File

@@ -61,5 +61,26 @@
"days": [ "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" ],
"months": [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Decembre" ],
"date_format": [ "%d-%m-%Y", "%d-%m" ]
},
"9": {
"language": "sv",
"daysShort": [ "SÖ", "MÅ", "TI", "ON", "TO", "FR", "LÖ" ],
"days": [ "Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag" ],
"months": [ "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" ],
"date_format": [ "%d-%m-%Y", "%d-%m" ]
},
"10": {
"language": "dk",
"daysShort": [ "SØ", "MA", "TI", "ON", "TO", "FR", "LØ" ],
"days": [ "Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag" ],
"months": [ "Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December" ],
"date_format": [ "%d-%m-%Y", "%d-%m" ]
},
"11": {
"language": "et",
"daysShort": [ "P", "E", "T", "K", "N", "R", "L" ],
"days": [ "Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev" ],
"months": [ "Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember" ],
"date_format": [ "%d-%m-%Y", "%d-%m" ]
}
}

View File

@@ -13,6 +13,6 @@
},
"shortlut": 0,
"options": ["button"],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27],
"usetemplate": 1
}

View File

@@ -0,0 +1,18 @@
{
"name": "M2 2.7\"",
"width": 264,
"height": 176,
"rotatebuffer": 1,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
},
"shortlut": 0,
"options": ["button"],
"contentids": [ 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20],
"usetemplate": 1
}

View File

@@ -1,20 +1,21 @@
{
"name": "M3 9.7\"",
"width": 960,
"height": 672,
"rotatebuffer": 0,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
},
"shortlut": 0,
"options": ["button"],
"contentids": [ 22, 23, 1, 5, 8, 9, 7, 19, 10, 11 ],
"usetemplate": 1,
"name": "M3 9.7\"",
"width": 960,
"height": 672,
"rotatebuffer": 2,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"options": [ "button" ],
"contentids": [ 22, 23, 1, 5, 8, 9, 7, 19, 10, 11 ],
"usetemplate": 1,
"template": {
"1": {
"weekday": [ 480, -5, "Signika-SB.ttf", 160 ],
@@ -37,5 +38,5 @@
"days": 7,
"gridparam": [ 7, 19, 30, "calibrib16.vlw", "REFSAN12.vlw", 16 ]
}
}
}
}

View File

@@ -2,19 +2,20 @@
"name": "M3 4.3\"",
"width": 522,
"height": 152,
"rotatebuffer": 1,
"rotatebuffer": 3,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["button"],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 11, 17, 18, 19, 20, 27],
"usetemplate": 1,
"zlib_compression": "27",
"options": [ "button" ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 11, 17, 18, 19, 20, 27 ],
"usetemplate": 1,
"template": {
"1": {
"weekday": [ 160, 5, "Signika-SB.ttf", 60 ],

View File

@@ -6,13 +6,14 @@
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["button"],
"contentids": [ 22, 23, 1, 2, 3, 4, 8, 7, 19, 10, 21 ],
"usetemplate": 0
"zlib_compression": "27",
"options": [ "button" ],
"contentids": [ 22, 23, 1, 2, 3, 4, 8, 7, 19, 10, 21 ],
"usetemplate": 0
}

View File

@@ -2,22 +2,23 @@
"name": "M3 2.2\"",
"width": 296,
"height": 160,
"rotatebuffer": 1,
"rotatebuffer": 3,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["button", "led"],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26],
"zlib_compression": "27",
"options": [ "button", "led" ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26 ],
"template": {
"1": {
"weekday": [148, 5, "Signika-SB.ttf", 60],
"date": [148, 75, "Signika-SB.ttf", 50]
"weekday": [ 148, 5, "Signika-SB.ttf", 60 ],
"date": [ 148, 75, "Signika-SB.ttf", 50 ]
},
"2": {
"fonts": [ "Signika-SB.ttf", 150, 150, 110, 80, 60, 50 ],
@@ -30,20 +31,20 @@
"bars": [ 5, 141, 10 ]
},
"4": {
"location": [5, 5, "fonts/bahnschrift30"],
"wind": [280, 5, "fonts/bahnschrift30"],
"temp": [5, 65, "fonts/bahnschrift70"],
"icon": [285, 20, 70, 2],
"dir": [245, -12, 40],
"umbrella": [190, -50, 25]
"location": [ 5, 5, "fonts/bahnschrift30" ],
"wind": [ 280, 5, "fonts/bahnschrift30" ],
"temp": [ 5, 65, "fonts/bahnschrift70" ],
"icon": [ 285, 20, 70, 2 ],
"dir": [ 245, -12, 40 ],
"umbrella": [ 190, -50, 25 ]
},
"8": {
"location": [5, 12, "t0_14b_tf"],
"column": [5, 59],
"day": [30, 18, "fonts/twcondensed20", 41, 108],
"icon": [30, 55, 30],
"wind": [18, 26],
"line": [20, 128]
"location": [ 5, 12, "t0_14b_tf" ],
"column": [ 5, 59 ],
"day": [ 30, 18, "fonts/twcondensed20", 41, 108 ],
"icon": [ 30, 55, 30 ],
"wind": [ 18, 26 ],
"line": [ 20, 128 ]
},
"9": {
"title": [ 5, 4, "bahnschrift20.vlw", 25 ],
@@ -52,8 +53,8 @@
"desc": [ 0, 5, "", 1 ]
},
"10": {
"title": [149, 5, "fonts/bahnschrift20"],
"pos": [149, 30]
"title": [ 149, 5, "fonts/bahnschrift20" ],
"pos": [ 149, 30 ]
},
"11": {
"mode": 0,

View File

@@ -0,0 +1,18 @@
{
"name": "M3 2.6\"",
"width": 360,
"height": 184,
"rotatebuffer": 3,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26 ],
"usetemplate": 1
}

View File

@@ -2,18 +2,19 @@
"name": "M3 2.9\"",
"width": 384,
"height": 168,
"rotatebuffer": 1,
"rotatebuffer": 3,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["button", "led"],
"contentids": [22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26, 27],
"zlib_compression": "27",
"options": [ "button", "led" ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26, 27 ],
"usetemplate": 1,
"template": {
"1": {
@@ -31,12 +32,12 @@
"bars": [ 5, 141, 14 ]
},
"8": {
"location": [5, 12, "t0_14b_tf"],
"column": [5, 76],
"day": [39, 23, "bahnschrift20.vlw", 48, 140],
"icon": [39, 65, 45],
"wind": [23, 26],
"line": [20, 168]
"location": [ 5, 12, "t0_14b_tf" ],
"column": [ 5, 76 ],
"day": [ 39, 23, "bahnschrift20.vlw", 48, 140 ],
"icon": [ 39, 65, 45 ],
"wind": [ 23, 26 ],
"line": [ 20, 168 ]
},
"9": {
"title": [ 5, 4, "bahnschrift20.vlw", 25 ],
@@ -56,12 +57,12 @@
"items": 10,
"red": [ 0, 21, 384, 16 ],
"line": [ 5, 23, 18, "calibrib16.vlw", 55 ]
},
},
"27": {
"bars": [ 12, 360, 110, 20 ],
"time": [ "calibrib16.vlw" ],
"yaxis": [ "BellCent10.vlw", 1, 6 ],
"head": [ "calibrib30.vlw" ]
}
}
}
}

View File

@@ -6,13 +6,14 @@
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["led"],
"zlib_compression": "27",
"options": [ "led" ],
"contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ],
"usetemplate": 2
}

View File

@@ -12,6 +12,7 @@
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"options": [ "led" ],
"contentids": [ 22, 23, 1, 4, 5, 8, 9, 7, 19, 10, 11 ],
"usetemplate": 1,

View File

@@ -6,13 +6,14 @@
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": ["button", "led"],
"contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20],
"usetemplate": 1
"zlib_compression": "27",
"options": [ "button", "led" ],
"contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ],
"usetemplate": 46
}

View File

@@ -0,0 +1,18 @@
{
"name": "M3 2.9\" FREEZER",
"width": 384,
"height": 168,
"rotatebuffer": 3,
"bpp": 1,
"colors": 2,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"options": [ "button", "led" ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26, 27 ],
"usetemplate": 51
}

View File

@@ -0,0 +1,19 @@
{
"name": "M3 5.85\"",
"width": 792,
"height": 272,
"rotatebuffer": 0,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"options": [ ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26, 27 ],
"usetemplate": 51
}

View File

@@ -0,0 +1,18 @@
{
"name": "M3 5.85\" FREEZER",
"width": 792,
"height": 272,
"rotatebuffer": 0,
"bpp": 1,
"colors": 2,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"zlib_compression": "27",
"options": [ ],
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 26, 27 ],
"usetemplate": 51
}

View File

@@ -0,0 +1,84 @@
{
"name": "HS BWR 2.13\"",
"width": 256,
"height": 128,
"rotatebuffer": 1,
"bpp": 2,
"colors": 3,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"shortlut": 0,
"options": [ "led" ],
"contentids": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 27 ],
"template": {
"1": {
"weekday": [ 128, 3, "Signika-SB.ttf", 50 ],
"date": [ 128, 62, "Signika-SB.ttf", 40 ]
},
"2": {
"fonts": [ "Signika-SB.ttf", 150, 150, 150, 115, 90, 70 ],
"xy": [ 128, 53 ]
},
"16": {
"location": [ 7, 15, "t0_14b_tf" ],
"title": [ 210, 11, "glasstown_nbp_tf" ],
"cols": [ 4, 121, 10, "glasstown_nbp_tf" ],
"bars": [ 10, 110, 8 ]
},
"4": {
"location": [ 5, 3, "fonts/bahnschrift30" ],
"wind": [ 245, 3, "fonts/bahnschrift30" ],
"temp": [ 10, 60, "fonts/bahnschrift70" ],
"icon": [ 240, 20, 70, 2 ],
"dir": [ 210, -12, 40 ],
"umbrella": [ 175, -50, 25 ]
},
"8": {
"location": [ 5, 12, "t0_14b_tf" ],
"column": [ 5, 51 ],
"day": [ 28, 18, "fonts/twcondensed20", 41, 108 ],
"icon": [ 28, 55, 30 ],
"wind": [ 18, 26 ],
"line": [ 20, 128 ]
},
"9": {
"title": [ 8, 2, "bahnschrift20.vlw", 25 ],
"items": 5,
"line": [ 8, 25, "REFSAN12.vlw" ],
"desc": [ 0, 5, "", 1 ]
},
"10": {
"title": [ 128, 2, "calibrib16.vlw" ],
"pos": [ 128, 16 ]
},
"11": {
"mode": 0,
"days": 1,
"title": [ 10, 2, "fonts/bahnschrift20" ],
"date": [ 245, 2 ],
"items": 7,
"red": [ 0, 21, 256, 14 ],
"line": [ 10, 32, 15, "t0_14b_tf", 50 ]
},
"21": [
{ "text": [ 10, 5, "OpenEpaperLink AP", "bahnschrift20", 1, 0, 0 ] },
{ "text": [ 10, 50, "IP address:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 110, 50, "{ap_ip}", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 10, 70, "Channel:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 110, 70, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 10, 90, "Tag count:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 110, 90, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] }
],
"27": {
"bars": [ 26, 216, 80, 20 ],
"time": [ "BellCent10.vlw" ],
"yaxis": [ "BellCent10.vlw", 6, 6 ],
"head": [ "bahnschrift20.vlw" ]
}
}
}

View File

@@ -6,76 +6,11 @@
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 27 ],
"template": {
"1": {
"weekday": [ 148, -3, "Signika-SB.ttf", 60 ],
"date": [ 148, 65, "Signika-SB.ttf", 48 ]
},
"2": {
"fonts": [ "Signika-SB.ttf", 150, 150, 150, 120, 100, 80 ],
"xy": [ 148, 53 ]
},
"16": {
"location": [ 5, 5, "fonts/bahnschrift30" ],
"title": [ 247, 11, "glasstown_nbp_tf" ],
"cols": [ 1, 125, 12, "glasstown_nbp_tf" ],
"bars": [ 5, 111, 10 ]
},
"4": {
"location": [5, 5, "fonts/bahnschrift30"],
"wind": [280, 5, "fonts/bahnschrift30"],
"temp": [5, 65, "fonts/bahnschrift70"],
"icon": [285, 20, 70, 2],
"dir": [235, -12, 40],
"umbrella": [190, -50, 25]
},
"8": {
"location": [5, 12, "t0_14b_tf"],
"column": [5, 59],
"day": [30, 18, "fonts/twcondensed20", 41, 108],
"icon": [30, 55, 30],
"wind": [18, 26],
"line": [20, 128]
},
"9": {
"title": [ 2, 0, "bahnschrift20.vlw", 25 ],
"items": 8,
"line": [ 1, 25, "REFSAN12.vlw" ],
"desc": [ 0, 5, "", 1 ]
},
"10": {
"title": [149, 5, "fonts/bahnschrift20"],
"pos": [149, 27]
},
"11": {
"mode": 0,
"days": 1,
"title": [5, 2, "fonts/bahnschrift20"],
"date": [290, 2],
"items": 7,
"red": [0, 21, 296, 14],
"line": [5, 32, 15, "t0_14b_tf", 50]
},
"21": [
{ "text": [ 5, 5, "OpenEpaperLink AP", "bahnschrift20", 1, 0, 0 ] },
{ "text": [ 5, 50, "IP address:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 120, 50, "{ap_ip}", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 5, 70, "Channel:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 120, 70, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 5, 90, "Tag count:", "t0_14b_tf", 1, 0, 0 ] },
{ "text": [ 120, 90, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] }
],
"27": {
"bars": [ 9, 288, 90, 10 ],
"time": [ "BellCent10.vlw" ],
"yaxis": [ "BellCent10.vlw", 0, 6 ],
"head": [ "calibrib30.vlw" ]
}
}
"usetemplate": 1
}

View File

@@ -6,50 +6,11 @@
"bpp": 2,
"colors": 3,
"colortable": {
"white": [255, 255, 255],
"black": [0, 0, 0],
"red": [255, 0, 0],
"gray": [150, 150, 150]
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ],
"gray": [ 150, 150, 150 ]
},
"contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20],
"template": {
"1": {
"weekday": [ 200, 0, "Signika-SB.ttf", 70 ],
"month": [ 200, 210, "Signika-SB.ttf", 70 ],
"day": [ 200, 45, "Signika-SB.ttf", 170 ]
},
"4": {
"location": [ 20, 20, "fonts/calibrib30" ],
"wind": [ 90, 83, "fonts/calibrib50" ],
"temp": [ 20, 170, "fonts/calibrib100" ],
"icon": [ 385, 0, 100, 2 ],
"dir": [ 40, 50, 80 ],
"umbrella": [ 325, 155, 78 ]
},
"8": {
"location": [ 10, 10, "fonts/calibrib30" ],
"column": [ 6, 66 ],
"day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ],
"rain": [ 34, 260 ],
"icon": [ 32, 145, 30 ],
"wind": [ 17, 90 ],
"line": [ 50, 300 ]
},
"9": {
"title": [ 6, 0, "Signika-SB.ttf", 25 ],
"items": 4,
"line": [ 9, 40, "calibrib16.vlw" ],
"desc": [ 2, 8, "REFSAN12.vlw", 1.2 ]
},
"10": {
"title": [ 200, 10, "fonts/bahnschrift20" ],
"pos": [ 200, 35 ]
},
"11": {
"rotate": 0,
"mode": 1,
"days": 4,
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "BellCent10.vlw", 14 ]
}
}
"contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ],
"usetemplate": 2
}

Binary file not shown.

Binary file not shown.

View File

@@ -54,6 +54,7 @@ class tagRecord {
struct Config {
uint8_t channel;
uint8_t subghzchannel;
char alias[32];
uint8_t led;
uint8_t tft;

View File

@@ -82,7 +82,6 @@ void contentRunner() {
if (minutesUntilNextUpdate > 1 && (wsClientCount() == 0 || config.stopsleep == 0)) {
taginfo->pendingIdle = minutesUntilNextUpdate * 60;
if (taginfo->isExternal == false) {
Serial.printf("sleeping for %d more minutes\n", minutesUntilNextUpdate);
prepareIdleReq(taginfo->mac, minutesUntilNextUpdate);
}
}
@@ -1186,7 +1185,7 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa
int temp = imageParams.height;
imageParams.height = imageParams.width;
imageParams.width = temp;
imageParams.rotatebuffer = 1 - imageParams.rotatebuffer;
imageParams.rotatebuffer = 1 - (imageParams.rotatebuffer%2);
initSprite(spr, imageParams.width, imageParams.height, imageParams);
} else {
initSprite(spr, imageParams.width, imageParams.height, imageParams);
@@ -2085,7 +2084,7 @@ void rotateBuffer(uint8_t rotation, uint8_t &currentOrientation, TFT_eSprite &sp
initSprite(spr, sprCpy.width(), sprCpy.height(), imageParams);
sprCpy.pushToSprite(&spr, 0, 0);
sprCpy.deleteSprite();
imageParams.rotatebuffer = 1 - imageParams.rotatebuffer;
imageParams.rotatebuffer = 1 - (imageParams.rotatebuffer%2);
}
currentOrientation = rotation;
}

View File

@@ -17,7 +17,7 @@ int currentLanguage = 0;
void updateLanguageFromConfig() {
int tempLang = config.language;
if (tempLang < 0 || tempLang > 8) {
if (tempLang < 0 || tempLang > 11) {
Serial.println("Language not supported");
return;
}

View File

@@ -88,10 +88,16 @@ uint32_t colorDistance(Color &c1, Color &c2, Error &e1) {
void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer_size, bool is_red) {
uint8_t rotate = imageParams.rotate;
long bufw = spr.width(), bufh = spr.height();
if (imageParams.rotatebuffer) {
if (imageParams.rotatebuffer % 2) {
//turn the image 90 or 270
rotate = (rotate + 3) % 4;
rotate = (rotate + (imageParams.rotatebuffer - 1)) % 4;
bufw = spr.height();
bufh = spr.width();
} else {
// rotate 180
rotate = (rotate + (imageParams.rotatebuffer)) % 4;
}
memset(buffer, 0, buffer_size);
@@ -234,8 +240,8 @@ size_t prepareHeader(uint8_t headerbuf[], uint16_t bufw, uint16_t bufh, imgParam
uint8_t headersize = 6;
headerbuf[0] = headersize;
memcpy(headerbuf + (imageParams.rotatebuffer == 1 ? 3 : 1), &bufw, sizeof(uint16_t));
memcpy(headerbuf + (imageParams.rotatebuffer == 1 ? 1 : 3), &bufh, sizeof(uint16_t));
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 3 : 1), &bufw, sizeof(uint16_t));
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 1 : 3), &bufh, sizeof(uint16_t));
if (imageParams.hasRed && imageParams.bpp > 1) {
totalbytes = buffer_size * 2 + headersize;
@@ -258,7 +264,7 @@ size_t compressAndWrite(Miniz::tdefl_compressor *comp, const void *inbuf, size_t
uint32_t t = millis();
Miniz::tdefl_compressOEPL(comp, inbuf, &inbytes_compressed, zlibbuf, &outbytes_compressed, flush);
Serial.printf("zlib: compressed %d into %d bytes in %d ms\n", inbytes_compressed, outbytes_compressed, millis()-t);
Serial.printf("zlib: compressed %d into %d bytes in %d ms\n", inbytes_compressed, outbytes_compressed, millis() - t);
f_out.write((const uint8_t *)zlibbuf, outbytes_compressed);
return outbytes_compressed;
@@ -266,7 +272,7 @@ size_t compressAndWrite(Miniz::tdefl_compressor *comp, const void *inbuf, size_t
void rewriteHeader(File &f_out) {
// https://www.rfc-editor.org/rfc/rfc1950
const uint8_t cmf = 0x48; // 4096
const uint8_t cmf = 0x48; // 4096
// const uint8_t cmf = 0x58; // 8192
uint8_t flg, flevel = 3;
uint16_t header = cmf << 8 | (flevel << 6);
@@ -277,7 +283,6 @@ void rewriteHeader(File &f_out) {
f_out.write(flg);
}
void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
long t = millis();

View File

@@ -74,15 +74,15 @@ void prepareCancelPending(const uint8_t dst[8]) {
}
void prepareIdleReq(const uint8_t* dst, uint16_t nextCheckin) {
if (nextCheckin > 0) {
if (nextCheckin > 0 && countQueueItem(dst) == 0) {
struct pendingData pending = {0};
memcpy(pending.targetMac, dst, 8);
pending.availdatainfo.dataType = DATATYPE_NOUPDATE;
pending.availdatainfo.nextCheckIn = nextCheckin;
pending.attemptsLeft = 10 + config.maxsleep;
Serial.printf(">SDA %02X%02X%02X%02X%02X%02X%02X%02X NOP\n", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
queueDataAvail(&pending, true);
Serial.printf(">SDA %02X%02X%02X%02X%02X%02X%02X%02X sleeping %d minutes\n", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0], nextCheckin);
sendDataAvail(&pending);
}
}
@@ -209,6 +209,15 @@ bool prepareDataAvail(String& filename, uint8_t dataType, uint8_t dataTypeArgume
file.close();
uint16_t attempts = 60 * 24;
if (memcmp(md5bytes, taginfo->md5, 16) == 0) {
wsLog("new image is the same as current image. not updating tag.");
wsSendTaginfo(dst, SYNC_TAGSTATUS);
if (contentFS->exists(filename) && resend == false) {
contentFS->remove(filename);
}
return true;
}
if (dataType != DATATYPE_FW_UPDATE) {
char dst_path[64];
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X%02X%02X_%lu.pending", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0], millis() % 1000000);
@@ -440,7 +449,7 @@ void processXferComplete(struct espXferComplete* xfc, bool local) {
if (config.preview && (queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_ZLIB)) {
contentFS->rename(queueItem->filename, String(dst_path));
} else {
contentFS->remove(queueItem->filename);
if (queueItem->pendingdata.availdatainfo.dataType != DATATYPE_FW_UPDATE) contentFS->remove(queueItem->filename);
}
}
memcpy(md5bytes, &queueItem->pendingdata.availdatainfo.dataVer, sizeof(uint64_t));
@@ -508,10 +517,16 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
}
char buffer[64];
char hexmac[17];
mac2hex(eadr->src, hexmac);
tagRecord* taginfo = tagRecord::findByMAC(eadr->src);
if (taginfo == nullptr) {
if (config.lock == 1 || (config.lock == 2 && eadr->adr.wakeupReason != WAKEUP_REASON_FIRSTBOOT)) return;
if (eadr->adr.currentChannel > 0 && eadr->adr.currentChannel != apInfo.channel) return;
if (eadr->adr.currentChannel > 0 && eadr->adr.currentChannel != apInfo.channel) {
Serial.printf("Tag %s reports illegal channel %d\n", hexmac, eadr->adr.currentChannel);
return;
}
taginfo = new tagRecord;
memcpy(taginfo->mac, eadr->src, sizeof(taginfo->mac));
taginfo->pendingCount = 0;
@@ -520,9 +535,6 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
time_t now;
time(&now);
char hexmac[17];
mac2hex(eadr->src, hexmac);
if (!local) {
if (taginfo->isExternal == false) {
wsLog("moved AP from local to external " + String(hexmac));
@@ -637,8 +649,11 @@ void setAPchannel() {
udpsync.getAPList();
} else {
if (curChannel.channel != config.channel) {
curChannel.channel = config.channel;
sendChannelPower(&curChannel);
curChannel.channel = config.channel;
#ifdef HAS_SUBGHZ
curChannel.subghzchannel = config.subghzchannel;
#endif
sendChannelPower(&curChannel);
}
}
}

View File

@@ -57,7 +57,10 @@ void logLine(const String& text) {
contentFS->remove("/logold.txt");
contentFS->rename("/log.txt", "/logold.txt");
logFile = contentFS->open("/log.txt", "a");
if (!logFile) return;
if (!logFile) {
xSemaphoreGive(fsMutex);
return;
}
}
logFile.print(timeStr);

View File

@@ -315,6 +315,7 @@ void initAPconfig() {
configFile.close();
}
config.channel = APconfig.containsKey("channel") ? APconfig["channel"] : 0;
config.subghzchannel = APconfig.containsKey("subghzchannel") ? APconfig["subghzchannel"] : 0;
if (APconfig["alias"]) strlcpy(config.alias, APconfig["alias"], sizeof(config.alias));
config.led = APconfig.containsKey("led") ? APconfig["led"] : 255;
config.tft = APconfig.containsKey("tft") ? APconfig["tft"] : 255;
@@ -343,6 +344,7 @@ void saveAPconfig() {
fs::File configFile = contentFS->open("/current/apconfig.json", "w");
DynamicJsonDocument APconfig(500);
APconfig["channel"] = config.channel;
APconfig["subghzchannel"] = config.subghzchannel;
APconfig["alias"] = config.alias;
APconfig["led"] = config.led;
APconfig["tft"] = config.tft;

View File

@@ -509,6 +509,13 @@ void init_web() {
#else
response->print("\"hasBLE\": \"0\", ");
#endif
#ifdef HAS_SUBGHZ
response->print("\"hasSubGhz\": \"1\", ");
#else
response->print("\"hasSubGhz\": \"0\", ");
#endif
response->print("\"apstate\": \"" + String(apInfo.state) + "\"");
File configFile = contentFS->open("/current/apconfig.json", "r");
@@ -542,6 +549,9 @@ void init_web() {
if (request->hasParam("channel", true)) {
config.channel = static_cast<uint8_t>(request->getParam("channel", true)->value().toInt());
}
if (request->hasParam("subghzchannel", true)) {
config.subghzchannel = static_cast<uint8_t>(request->getParam("subghzchannel", true)->value().toInt());
}
if (request->hasParam("led", true)) {
config.led = static_cast<uint8_t>(request->getParam("led", true)->value().toInt());
updateBrightnessFromConfig();

View File

@@ -350,6 +350,8 @@
"AT": "Austria",
"BE": "Belgium",
"CZ": "Czech Republic",
"DK1": "Denmark DK1",
"DK2": "Denmark DK2",
"EE": "Estonia",
"FI": "Finland",
"FR": "France",
@@ -409,7 +411,7 @@
{
"key": "interval",
"name": "Interval",
"desc": "In case of an url, wow often (in minutes) the template is being fetched. Minimum is 3 minutes.",
"desc": "In case of an url, how often (in minutes) the template is being fetched. Minimum is 3 minutes.",
"type": "int"
}
]

View File

@@ -435,7 +435,8 @@
}
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
if (tagTypes[hwtype].rotatebuffer) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer%2) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer>=2) canvas.style.transform='rotate(180deg)';
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
if (data.length == 0) canvas.style.display = 'none';

View File

@@ -127,7 +127,7 @@ const fetchAndPost = async (url, name, path) => {
formData.append('path', path);
formData.append('file', fileContent, name);
const uploadResponse = await fetch('/littlefs_put', {
const uploadResponse = await fetch('littlefs_put', {
method: 'POST',
body: formData
});
@@ -146,7 +146,7 @@ const fetchAndPost = async (url, name, path) => {
async function checkTagFW() {
const fwfile = "/Tag_FW_Pack.bin";
const url = "/check_file?path=" + encodeURIComponent(fwfile);
const url = "check_file?path=" + encodeURIComponent(fwfile);
const response = await fetch(url);
if (response.ok) {
const data = await response.json();

View File

@@ -289,6 +289,24 @@ options:
<option value="27">27</option>
</select>
</p>
<p title="Enable SubGhz support and select channel. This requires an AP that has an optional CC1101 SubGhz radio module attached.">
<label for="apcfgsubgigchid">SubGhz channel</label>
<select id="apcfgsubgigchid">
<option value="0" selected>disabled</option>
<option value="100">100 - 864.000 Mhz (Europe, etc)</option>
<option value="101">101 - 865.006 Mhz (Europe, etc)</option>
<option value="102">102 - 866.014 Mhz (Europe, etc)</option>
<option value="103">103 - 867.020 Mhz (Europe, etc)</option>
<option value="104">104 - 868.027 Mhz (Europe, etc)</option>
<option value="105">105 - 869.034 Mhz (Europe, etc)</option>
<option value="200">200 - 903.000 Mhz (US, etc)</option>
<option value="201">201 - 907.027 Mhz (US, etc)</option>
<option value="202">202 - 911.054 Mhz (US, etc)</option>
<option value="203">203 - 915.083 Mhz (US, etc)</option>
<option value="204">204 - 919.110 Mhz (US, etc)</option>
<option value="205">205 - 923.138 Mhz (US, etc)</option>
</select>
</p>
<p title="Enable Bluetooth (BLE) support. Only enable this if you have BLE capable tags. Changing this value requires a reboot to take effect.">
<label for="apcfgble">Bluetooth</label>
<select id="apcfgble">
@@ -330,6 +348,9 @@ options:
<option value="6">SK Slovenčina</option>
<option value="7">PL Polski</option>
<option value="8">ES Español</option>
<option value="9">SV Svenska</option>
<option value="10">DK Dansk</option>
<option value="11">ET Eesti</option>
</select>
</p>
<p title="Depending on the content, a tag can sleep for

View File

@@ -44,7 +44,7 @@ let getTagtypeBusy = false;
const loadConfig = new Event("loadConfig");
window.addEventListener("loadConfig", function () {
fetch("/get_ap_config")
fetch("get_ap_config")
.then(response => response.json())
.then(data => {
apConfig = data;
@@ -53,17 +53,20 @@ window.addEventListener("loadConfig", function () {
$(".logo").innerHTML = data.alias;
this.document.title = data.alias;
}
if (data.C6) {
if (data.C6 == 1) {
var optionToRemove = $("#apcfgchid").querySelector('option[value="27"]');
if (optionToRemove) $("#apcfgchid").removeChild(optionToRemove);
$('#c6Option').style.display = 'block';
}
if (data.hasFlasher) {
if (data.hasFlasher == 1) {
$('[data-target="flashtab"]').style.display = 'block';
}
if (data.hasBLE == 0) {
$("#apcfgble").parentNode.style.display = 'none';
}
if (data.hasSubGhz == 0) {
$("#apcfgsubgigchid").parentNode.style.display = 'none';
}
if (data.savespace) {
}
if (data.apstate) {
@@ -77,7 +80,7 @@ window.addEventListener("loadConfig", function () {
window.addEventListener("load", function () {
window.dispatchEvent(loadConfig);
initTabs();
fetch('/content_cards.json')
fetch('content_cards.json')
.then(response => response.json())
.then(data => {
cardconfig = data;
@@ -133,7 +136,7 @@ function initTabs() {
};
function loadTags(pos) {
return fetch("/get_db?pos=" + pos)
return fetch("get_db?pos=" + pos)
.then(response => response.json())
.then(data => {
processTags(data.tags);
@@ -169,7 +172,7 @@ function formatUptime(seconds) {
function connect() {
protocol = location.protocol == "https:" ? "wss://" : "ws://";
socket = new WebSocket(protocol + location.host + "/ws");
socket = new WebSocket(protocol + location.host + location.pathname + "ws");
socket.addEventListener("open", (event) => {
showMessage("websocket connected");
@@ -309,7 +312,7 @@ function processTags(tagArray) {
if (element.isexternal && element.contentMode == 12) {
loadImage(tagmac, 'http://' + tagDB[tagmac].apip + '/current/' + tagmac + '.raw?' + cachetag);
} else {
loadImage(tagmac, '/current/' + tagmac + '.raw?' + cachetag);
loadImage(tagmac, 'current/' + tagmac + '.raw?' + cachetag);
}
} else {
$('#tag' + tagmac + ' .tagimg').style.display = 'none'
@@ -497,7 +500,7 @@ $('#taglist').addEventListener("click", (event) => {
function loadContentCard(mac) {
$('#cfgmac').innerHTML = mac;
$('#cfgmac').dataset.mac = mac;
fetch("/get_db?mac=" + mac)
fetch("get_db?mac=" + mac)
.then(response => response.json())
.then(data => {
const tagdata = data.tags[0];
@@ -570,7 +573,7 @@ $('#cfgsave').onclick = function () {
formData.append("lut", $('#cfglut').value);
formData.append("invert", $('#cfginvert').value);
fetch("/save_cfg", {
fetch("save_cfg", {
method: "POST",
body: formData
})
@@ -587,7 +590,7 @@ function sendCmd(mac, cmd) {
let formData = new FormData();
formData.append("mac", mac);
formData.append("cmd", cmd);
fetch("/tag_cmd", {
fetch("tag_cmd", {
method: "POST",
body: formData
})
@@ -655,7 +658,7 @@ $('#cfgautoupdate').onclick = async function () {
var fullFilename = name + "_" + version + ".bin";
var filepath = "/" + fullFilename;
var binurl = "https://raw.githubusercontent.com/" + repo + "/master/binaries/Tag/" + fullFilename;
var url = "/check_file?path=" + encodeURIComponent(filepath);
var url = "check_file?path=" + encodeURIComponent(filepath);
var response = await fetch(url);
if (response.ok) {
var data = await response.json();
@@ -666,7 +669,7 @@ $('#cfgautoupdate').onclick = async function () {
var formData2 = new FormData();
formData2.append('path', filepath);
formData2.append('file', fileContent, fullFilename);
var uploadResponse = await fetch('/littlefs_put', {
var uploadResponse = await fetch('littlefs_put', {
method: 'POST',
body: formData2
});
@@ -690,7 +693,7 @@ $('#cfgautoupdate').onclick = async function () {
else showMessage('Error: auto update failed', true);
formData.append("contentmode", 5);
formData.append("modecfgjson", JSON.stringify(obj));
fetch("/save_cfg", {
fetch("save_cfg", {
method: "POST",
body: formData
})
@@ -705,7 +708,7 @@ $('#rebootbutton').onclick = function (event) {
event.preventDefault();
if (!confirm('Reboot AP now?')) return;
socket.close();
fetch("/reboot", {
fetch("reboot", {
method: "POST"
});
alert('Rebooted. Webpage will reload.');
@@ -723,13 +726,14 @@ document.addEventListener("loadTab", function (event) {
switch (event.detail) {
case 'configtab':
case 'aptab':
fetch("/get_ap_config")
fetch("get_ap_config")
.then(response => response.json())
.then(data => {
if (data && 'alias' in data) {
apConfig = data;
$('#apcfgalias').value = data.alias;
$('#apcfgchid').value = data.channel;
$('#apcfgsubgigchid').value = data.subghzchannel;
$('#apcfgble').value = data.ble;
$("#apcfgledbrightness").value = data.led;
$("#apcfgtftbrightness").value = data.tft;
@@ -765,6 +769,7 @@ $('#apcfgsave').onclick = function () {
let formData = new FormData();
formData.append("alias", $('#apcfgalias').value);
formData.append("channel", $('#apcfgchid').value);
formData.append("subghzchannel", $('#apcfgsubgigchid').value);
formData.append('ble', $('#apcfgble').value);
formData.append('led', $('#apcfgledbrightness').value);
formData.append('tft', $('#apcfgtftbrightness').value);
@@ -778,7 +783,7 @@ $('#apcfgsave').onclick = function () {
formData.append('sleeptime1', $('#apcnight1').value);
formData.append('sleeptime2', $('#apcnight2').value);
fetch("/save_apcfg", {
fetch("save_apcfg", {
method: "POST",
body: formData
})
@@ -796,7 +801,7 @@ $('#uploadButton').onclick = function () {
if (file) {
const formData = new FormData();
formData.append('file', file);
fetch('/restore_db', {
fetch('restore_db', {
method: 'POST',
body: formData
})
@@ -834,7 +839,7 @@ $('#restoreFromLocal').onclick = function () {
const formData = new FormData();
formData.append('file', blob, 'tagResult.json');
fetch('/restore_db', {
fetch('restore_db', {
method: 'POST',
body: formData
})
@@ -938,7 +943,7 @@ function contentselected() {
case 'binfile':
case 'jsonfile':
input = document.createElement("select");
fetch('/edit?list=%2F&recursive=1')
fetch('edit?list=%2F&recursive=1')
.then(response => response.json())
.then(data => {
let files = data.filter(item => item.type === "file" && item.name.endsWith(".jpg"));
@@ -1133,7 +1138,8 @@ function processQueue() {
}
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
if (tagTypes[hwtype].rotatebuffer) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer%2) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer>=2) canvas.style.transform='rotate(180deg)';
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
if (data.length == 0) {
@@ -1356,7 +1362,7 @@ async function getTagtype(hwtype) {
try {
getTagtypeBusy = true;
tagTypes[hwtype] = { busy: true };
const response = await fetch('/tagtypes/' + hwtype.toString(16).padStart(2, '0').toUpperCase() + '.json');
const response = await fetch('tagtypes/' + hwtype.toString(16).padStart(2, '0').toUpperCase() + '.json');
if (!response.ok) {
let data = { name: 'unknown id ' + hwtype.toString(16), width: 0, height: 0, bpp: 0, rotatebuffer: 0, colortable: [], busy: false };
tagTypes[hwtype] = data;
@@ -1447,7 +1453,7 @@ function dropUpload() {
formData.append('file', blob, 'image.jpg');
try {
const response = await fetch('/imgupload', {
const response = await fetch('imgupload', {
method: 'POST',
body: formData,
});
@@ -1477,7 +1483,7 @@ function dropUpload() {
const formData = new FormData();
formData.append('mac', mac);
formData.append('json', jsonContent);
fetch('/jsonupload', {
fetch('jsonupload', {
method: 'POST',
body: formData,
})
@@ -1609,7 +1615,7 @@ function populateAPCard(msg) {
function populateAPInfo(apip) {
let apid = apip.replace(/\./g, "-");
fetch('http://' + apip + '/sysinfo')
fetch('sysinfo')
.then(response => {
if (response.status != 200) {
$('#ap' + apid + ' .apswversion').innerHTML = "Error fetching sysinfo: " + response.status;

View File

@@ -10,7 +10,7 @@ let buttonState = false;
export async function initUpdate() {
const response = await fetch("/version.txt");
const response = await fetch("version.txt");
let filesystemversion = await response.text();
if (!filesystemversion) filesystemversion = "unknown";
$('#repo').value = repo;
@@ -30,7 +30,7 @@ export async function initUpdate() {
$('#selectRepo').style.display = 'inline-block';
$('#repoWarning').style.display = 'none';
const sysinfoPromise = fetch("/sysinfo")
const sysinfoPromise = fetch("sysinfo")
.then(response => {
if (response.status != 200) {
print("Error fetching sysinfo: " + response.status, "red");
@@ -167,7 +167,7 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
print("Updating littleFS partition...");
fetch("http://openepaperlink.eu/getupdate/?url=" + fileUrl)
fetch("//openepaperlink.eu/getupdate/?url=" + fileUrl)
.then(response => response.json())
.then(data => {
checkfiles(data);
@@ -181,7 +181,7 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
if (updateactions) {
await fetchAndPost(updateactions.url, updateactions.name, updateactions.path);
try {
const response = await fetch("/update_actions", {
const response = await fetch("update_actions", {
method: "POST",
body: ''
});
@@ -200,7 +200,7 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
for (const file of files) {
try {
if (file.name != "update_actions.json") {
const url = "/check_file?path=" + encodeURIComponent(file.path);
const url = "check_file?path=" + encodeURIComponent(file.path);
const response = await fetch(url);
if (response.ok) {
const data = await response.json();
@@ -271,7 +271,7 @@ export async function updateESP(fileUrl, showConfirm) {
while (retryCount < maxRetries) {
try {
const response = await fetch("http://openepaperlink.eu/getupdate/?url=" + fileUrl + "&env=" + env);
const response = await fetch("//openepaperlink.eu/getupdate/?url=" + fileUrl + "&env=" + env);
const responseBody = await response.text();
if (!response.ok) {
throw new Error("Network response was not OK: " + responseBody);
@@ -290,7 +290,7 @@ export async function updateESP(fileUrl, showConfirm) {
console.log(`URL for "${file.name}": ${binurl}`);
try {
const response = await fetch('/update_ota', {
const response = await fetch('update_ota', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
@@ -342,7 +342,7 @@ $('#rollbackBtn').onclick = function () {
print("Rolling back...");
fetch("/rollback", {
fetch("rollback", {
method: "POST",
body: ''
})
@@ -365,7 +365,7 @@ $('#updateC6Btn').onclick = function () {
const formData = new FormData();
formData.append('download', isChecked ? '1' : '0'); // Convert to '1' or '0'
fetch("/update_c6", {
fetch("update_c6", {
method: "POST",
body: formData
})
@@ -389,7 +389,7 @@ $('#selectRepo').onclick = function (event) {
const filesJsonAsset = assets.find(asset => asset.name === 'filesystem.json');
const binariesJsonAsset = assets.find(asset => asset.name === 'binaries.json');
if (filesJsonAsset && binariesJsonAsset) {
const updateUrl = "http://openepaperlink.eu/getupdate/?url=" + binariesJsonAsset.browser_download_url + "&env=" + $('#repo').value;
const updateUrl = "//openepaperlink.eu/getupdate/?url=" + binariesJsonAsset.browser_download_url + "&env=" + $('#repo').value;
return fetch(updateUrl);
} else {
throw new Error("Json file binaries.json and/or filesystem.json not found in the release assets");
@@ -443,7 +443,7 @@ $('#confirmSelectRepo').onclick = function (event) {
let formData = new FormData();
formData.append("repo", repo);
formData.append("env", $('#environment').value);
fetch("/save_apcfg", {
fetch("save_apcfg", {
method: "POST",
body: formData
})
@@ -478,7 +478,7 @@ export function print(line, color = "white") {
export function reboot() {
print("Rebooting now... Reloading webpage in 5 seconds...", "yellow");
fetch("/reboot", { method: "POST" });
fetch("reboot", { method: "POST" });
setTimeout(() => {
location.reload();
}, 5000);
@@ -520,7 +520,7 @@ const fetchAndPost = async (url, name, path) => {
formData.append('path', path);
formData.append('file', fileContent, name);
const uploadResponse = await fetch('/littlefs_put', {
const uploadResponse = await fetch('littlefs_put', {
method: 'POST',
body: formData
});
@@ -544,7 +544,7 @@ const writeVersion = async (content, name, path) => {
const blob = new Blob([content]);
formData.append('file', blob, name);
const uploadResponse = await fetch('/littlefs_put', {
const uploadResponse = await fetch('littlefs_put', {
method: 'POST',
body: formData
});

View File

@@ -1,7 +1,7 @@
const $ = document.querySelector.bind(document);
window.addEventListener("load", function () {
fetch("/get_wifi_config")
fetch("get_wifi_config")
.then(response => response.json())
.then(data => {
$('#ssid').value = data.ssid || "";
@@ -25,7 +25,7 @@ $('#listssid').addEventListener('click', () => {
});
function getSsidList() {
fetch("/get_ssid_list")
fetch("get_ssid_list")
.then(response => response.json())
.then(data => {
if (data.scanstatus < 0) {
@@ -64,7 +64,7 @@ $('#connect').addEventListener('click', () => {
dns: $('#dns').value
};
fetch('/save_wifi_config', {
fetch('save_wifi_config', {
method: 'POST',
headers: {
'Content-Type': 'application/json'

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
## Alternative case for the MiniAP v3 ##
Slim-fit case for the MiniAP v3. This one allows for a cooler S3/C6!
![IMG_6257](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/5443ca75-7f7c-4582-83ec-d35199a1dbc8)
![IMG_6256](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/c0cd6741-8911-4a82-ac5b-7a1065d81f7d)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,10 @@
## S3 C6 NanoAP Case ##
This is a tiny case for the Nano AP, meant for C6 modules with an IPEX connector instead of the PCB antenna. You'll need a small external PCB antenna, which goes into a slot on the side.
The S3 and C6 are cooled by 20x20mm heatsinks that are stuck on with double-sided heat-conducting tape.
![image](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/85fe3454-ae33-4af1-a1bf-c4eb3e6e617c)
![image](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/f12d3570-1be3-406d-81ae-755aac38ffc1)
![image](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/09642d97-5a2f-4ada-bb7c-83785d8f5657)
![image](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/102185ea-1c38-4400-b8b9-ed6710ac8e1e)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,74 +1,94 @@
[
{
"00" : {
"type": "SOL_M2_154_SSD",
"version": "26",
"md5": "b6948f6eb87fbb6f21f1254adbaa07ac"
},
"01" : {
"type": "SOL_M2_29_SSD",
"version": "26",
"md5": "7309496eb0f3da3b450fd7fc121a4982"
},
"02" : {
"type": "SOL_M2_42_SSD",
"version": "26",
"md5": "add97e450fa020ee994defe15f0c77ae"
},
"05" : {
"type": "SOL_M2_75_ota",
"version": "04",
"md5": "26c058db1f14c7ee2f301283bcbe7c9d"
},
"11" : {
"type": "SOL_M2_29_UC",
"version": "25",
"md5": "0c692cfca683948efeb3501a00c8f8bd"
},
"21" : {
"type": "SOL_M2_29_LT",
"version": "25",
"md5": "8ebc88f2a8de187a81d2f7c4c39b0d8e"
},
"2E" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"2F" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"30" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"31" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"33" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"34" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"35" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
},
"36" : {
"type": "SOL_M3_Uni_ota",
"version": "26",
"md5": "d234e395a8441779caa2df75ca9a508d"
}
"00": {
"type": "SOL_M2_154_SSD",
"version": "0027",
"md5": "0cf7b60327ff2b0318185be2e8ba82a0"
},
"01": {
"type": "SOL_M2_29_SSD",
"version": "0027",
"md5": "a051ee5d5517b3e8d3d09ae1e076eabc"
},
"02": {
"type": "SOL_M2_42_SSD",
"version": "0027",
"md5": "94aa727296a4c480a6702ea612288b4c"
},
"05": {
"type": "SOL_M2_75_ota",
"version": "04",
"md5": "26c058db1f14c7ee2f301283bcbe7c9d"
},
"11": {
"type": "SOL_M2_29_UC",
"version": "0027",
"md5": "aba3e35ef2bb63066d47e924bccd64f0"
},
"21": {
"type": "SOL_M2_29_LT",
"version": "0027",
"md5": "130203d9ab7905b14166af1cc7260285"
},
"2E": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"2F": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"30": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"31": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"32": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"33": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"34": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"35": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"36": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"40": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"41": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
},
"42": {
"type": "SOL_M3_Uni_ota",
"version": "0027",
"md5": "03311a065fe4e1d20f373df7bc5f8dbe"
}
}
]

View File

@@ -38,8 +38,11 @@
#define SOLUM_M3_BWY_26 0x3A
#define SOLUM_M3_BWR_29 0x33 // the 'standard' SSD1619 version
#define SOLUM_M3_BWY_29 0x3B
#define SOLUM_M3_BW_29 0x40
#define SOLUM_M3_BWR_42 0x34
#define SOLUM_M3_BWY_42 0x3C
#define SOLUM_M3_BWR_58 0x41
#define SOLUM_M3_BW_58 0x42
#define SOLUM_M3_BWR_60 0x35
#define SOLUM_M3_BWY_60 0x3D
#define SOLUM_M3_BWR_75 0x36
@@ -47,6 +50,7 @@
#define SOLUM_M3_BWR_116 0x37
#define SOLUM_M3_BWY_116 0x3F
// M3 Tags overflow
#define SOLUM_M3_BW_29 0x40
#define SOLUM_M3_BWR_58 0x41
@@ -75,9 +79,13 @@
// Solum types - customer data byte 16 in M3 (nRF) UICR
#define STYPE_SIZE_016 0x40
#define STYPE_SIZE_022 0x41
#define STYPE_SIZE_026 0x43
#define STYPE_SIZE_029 0x42
#define STYPE_SIZE_029_FREEZER 0x22
#define STYPE_SIZE_042 0x46
#define STYPE_SIZE_043 0x47
#define STYPE_SIZE_058 0x63
#define STYPE_SIZE_058_FREEZER 0x24
#define STYPE_SIZE_060 0x48
#define STYPE_SIZE_075 0x4C
#define STYPE_SIZE_097 0x64
@@ -123,6 +131,7 @@
#define CMD_ENTER_SLIDESHOW_GLACIAL 0x09
#define CMD_ENTER_NORMAL_MODE 0x0F
#define CMD_ENTER_WAIT_RFWAKE 0x20
#define CMD_GET_BATTERY_VOLTAGE 0x21
#define WAKEUP_REASON_TIMED 0
#define WAKEUP_REASON_GPIO 2

View File

@@ -18,6 +18,9 @@ struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
#ifdef HAS_SUBGHZ
uint8_t subghzchannel;
#endif
} __packed;
struct espAvailDataReq {

View File

@@ -9,26 +9,26 @@ BINDIR="../binaries/Tag"
echo -e "\nBuilding 1.54 version..."
make BUILD=zbs154_ssd1619 CPU=8051 SOC=zbs243 > /dev/null
mv main.bin ${BINDIR}/SOLUM_154_SSD1619-00-${VER}.bin -v
mv main.bin ${BINDIR}/SOL_M2_154_SSD_${VER}.bin -v
make clean > /dev/null
echo -e "\n\nBuilding 2.9 (SSD1619) version..."
make BUILD=zbs29_ssd1619 CPU=8051 SOC=zbs243 > /dev/null
mv main.bin ${BINDIR}/SOLUM_29_SSD1619-01-${VER}.bin -v
mv main.bin ${BINDIR}/SOL_M2_29_SSD_${VER}.bin -v
make clean > /dev/null
echo -e "\n\nBuilding 4.2 version..."
make BUILD=zbs42_ssd1619 CPU=8051 SOC=zbs243 > /dev/null
mv main.bin ${BINDIR}/SOLUM_42_SSD1619-02-${VER}.bin -v
mv main.bin ${BINDIR}/SOL_M2_42_SSD_${VER}.bin -v
make clean > /dev/null
echo -e "\n\nBuilding 2.9 (UC8151) version..."
make BUILD=zbs29_uc8151 CPU=8051 SOC=zbs243 > /dev/null
mv main.bin ${BINDIR}/SOLUM_29_UC8151-11-${VER}.bin -v
mv main.bin ${BINDIR}/SOL_M2_29_UC_${VER}.bin -v
make clean > /dev/null
echo -e "\n\nBuilding 2.9 BW (SSD1619 - freezer) version..."
make BUILD=zbs29_BW_ssd1619 CPU=8051 SOC=zbs243 > /dev/null
mv main.bin ${BINDIR}/SOLUM_29_BW_LOWTEMP-21-${VER}.bin -v
mv main.bin ${BINDIR}/SOL_M2_29_LT_${VER}.bin -v
make clean > /dev/null

View File

@@ -558,6 +558,10 @@ void executeCommand(uint8_t cmd) {
eraseImageBlocks();
powerDown(INIT_EEPROM);
break;
case CMD_GET_BATTERY_VOLTAGE:
longDataReqCounter = LONG_DATAREQ_INTERVAL + 1;
voltageCheckCounter = VOLTAGE_CHECK_INTERVAL;
break;
#ifndef LEAN_VERSION
case CMD_ENTER_SLIDESHOW_FAST:
powerUp(INIT_EEPROM);
@@ -757,7 +761,7 @@ void main() {
#ifdef DEBUGMAIN
pr("MAIN: Ap Found!\n");
#endif
//showNoAP();
// showNoAP();
showAPFound();
// write the settings to the eeprom
@@ -772,7 +776,7 @@ void main() {
#ifdef DEBUGMAIN
pr("MAIN: No AP found...\n");
#endif
//showAPFound();
// showAPFound();
showNoAP();
// write the settings to the eeprom
powerUp(INIT_EEPROM);

View File

@@ -3,17 +3,17 @@
#include <stdint.h>
#define FW_VERSION 0x0026 // version number
#define FW_VERSION_SUFFIX "-MD5" // suffix, like -RC1 or whatever.
#define FW_VERSION 0x0027 // version number
#define FW_VERSION_SUFFIX "-RDRW" // suffix, like -RC1 or whatever.
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
#define DEBUGPROTO // debug protocol
//#define DEBUGPROTO // debug protocol
// #define DEBUGOTA // debug OTA FW updates
#define DEBUGDRAWING // debug the drawing part
#define DEBUGEPD // debug the EPD driver
#define DEBUGMAIN // parts in the main loop
#define DEBUGNFC // debug NFC functions
//#define DEBUGDRAWING // debug the drawing part
//#define DEBUGEPD // debug the EPD driver
//#define DEBUGMAIN // parts in the main loop
//#define DEBUGNFC // debug NFC functions
// #define DEBUGGUI // debug GUI drawing (enabled)
#define DEBUGSETTINGS // debug settings module (preferences/eeprom)
//#define DEBUGSETTINGS // debug settings module (preferences/eeprom)
// #define DEBUGEEPROM // eeprom-related debug messages
#define VALIDATE_IMAGE_MD5 // The firmware can validate the image MD5 before displaying it. This costs about 8mAS (milliamp-second) for a 1.54, 16
// #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket
@@ -59,4 +59,4 @@ void writeSettings();
void loadSettings();
void loadSettingsFromBuffer(uint8_t* p);
void invalidateSettingsEEPROM();
#endif
#endif

View File

@@ -217,9 +217,9 @@ static void sendAvailDataReq() {
commsTxNoCpy(outBuffer);
}
struct AvailDataInfo *__xdata getAvailDataInfo() {
#ifdef DEBUGPROTO
#ifdef DEBUGPROTO
pr("PROTO: Full AvailData\n");
#endif
#endif
radioRxEnable(true, true);
uint32_t __xdata t;
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) {
@@ -244,9 +244,9 @@ struct AvailDataInfo *__xdata getAvailDataInfo() {
return NULL;
}
struct AvailDataInfo *__xdata getShortAvailDataInfo() {
#ifdef DEBUGPROTO
#ifdef DEBUGPROTO
pr("PROTO: Short AvailData\n");
#endif
#endif
radioRxEnable(true, true);
uint32_t __xdata t;
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) {
@@ -683,9 +683,9 @@ static bool getDataBlock(const uint16_t blockSize) {
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
requestPartialBlock = false;
#ifdef DEBUGPROTO
#ifdef DEBUGPROTO
pr("PROTO: blk failed validation!\n");
#endif
#endif
}
} else {
#ifndef DEBUGBLOCKS
@@ -695,9 +695,9 @@ static bool getDataBlock(const uint16_t blockSize) {
requestPartialBlock = true;
}
}
#ifdef DEBUGPROTO
#ifdef DEBUGPROTO
pr("PROTO: failed getting block\n");
#endif
#endif
return false;
}
@@ -948,7 +948,9 @@ inline bool processImageDataAvail(struct AvailDataInfo *__xdata avail) {
} else {
// currently not displayed
#ifdef DEBUGPROTO
pr("PROTO: currently not shown image\n");
#endif
// try to find the data in the SPI EEPROM
powerUp(INIT_EEPROM);
uint8_t findImgSlot = findSlotVer(&(avail->dataVer));
@@ -956,6 +958,9 @@ inline bool processImageDataAvail(struct AvailDataInfo *__xdata avail) {
// Is this image already in a slot somewhere
if (findImgSlot != 0xFF) {
#ifdef DEBUGPROTO
pr("PROTO: Found image in EEPROM\n");
#endif
// found a (complete)valid image slot for this version
powerUp(INIT_RADIO);
sendXferComplete();
@@ -994,9 +999,8 @@ inline bool processImageDataAvail(struct AvailDataInfo *__xdata avail) {
return false;
}
}
// keep track on what is currently displayed
xMemCopy8(curDispDataVer, xferDataInfo.dataVer);
// keep track on what is currently displayed
xMemCopy8(curDispDataVer, &xferDataInfo.dataVer);
return true;
}
}
@@ -1228,4 +1232,4 @@ bool validateFWMagic() {
void initializeProto() {
getNumSlots();
curHighSlotId = getHighSlotId();
}
}