From f2dc16953dbc873089bbce30dcbcf93ddbc7f512 Mon Sep 17 00:00:00 2001 From: jjwbruijn Date: Thu, 15 Feb 2024 18:51:10 +0100 Subject: [PATCH] beta v0027 M2-7.5" FW --- .../88MZ100_OpenEpaperLink_7.4/Makefile | 23 +- .../compression.cpp | 1 + .../88MZ100_OpenEpaperLink_7.4/drawing.cpp | 798 +---------------- .../88MZ100_OpenEpaperLink_7.4/drawing.h | 135 +-- .../epd_interface.cpp | 15 +- .../epd_interface.h | 17 +- .../88MZ100_OpenEpaperLink_7.4/main.cpp | 179 ++-- ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h | 2 +- .../88MZ100_OpenEpaperLink_7.4/mz100/eeprom.h | 19 +- .../88MZ100_OpenEpaperLink_7.4/mz100/gpio.c | 107 +-- .../88MZ100_OpenEpaperLink_7.4/mz100/gpio.h | 2 + .../88MZ100_OpenEpaperLink_7.4/mz100/mz100.ld | 4 +- .../mz100/mz100_sleep.c | 2 +- .../88MZ100_OpenEpaperLink_7.4/mz100/util.c | 32 +- .../88MZ100_OpenEpaperLink_7.4/mz100/util.h | 2 + .../oepl-protocol.cpp | 90 ++ .../oepl-protocol.h | 10 + .../88MZ100_OpenEpaperLink_7.4/oepl_fs.cpp | 49 +- .../88MZ100_OpenEpaperLink_7.4/oepl_fs.h | 1 + .../88MZ100_OpenEpaperLink_7.4/powermgt.c | 19 +- .../88MZ100_OpenEpaperLink_7.4/powermgt.cpp | 159 ++++ .../88MZ100_OpenEpaperLink_7.4/powermgt.h | 26 +- .../88MZ100_OpenEpaperLink_7.4/settings.c | 28 - .../88MZ100_OpenEpaperLink_7.4/settings.cpp | 107 +++ .../88MZ100_OpenEpaperLink_7.4/settings.h | 36 +- .../88MZ100_OpenEpaperLink_7.4/syncedproto.c | 839 ------------------ .../88MZ100_OpenEpaperLink_7.4/syncedproto.h | 26 - .../tagprofile_struct.h | 11 + .../uc8159-var-m2.cpp | 60 +- .../userinterface.cpp | 53 +- 30 files changed, 802 insertions(+), 2050 deletions(-) create mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.cpp create mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.h create mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.cpp delete mode 100755 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c create mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.cpp delete mode 100755 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c delete mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h create mode 100644 ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/tagprofile_struct.h diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile index ae681145..6d593060 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/Makefile @@ -1,5 +1,4 @@ - MZ_FLASHER=python ../88MZ100_Flasher/88MZ100_Uart_flasher.py ARMGCC=/usr/bin/ @@ -11,6 +10,7 @@ OBJCOPY=$(ARMGCC)arm-none-eabi-objcopy #-Wall CC_WARNING_FLAGS=-Wall -Wformat=0 -Wattributes -Wstrict-aliasing=0 CPP_FLAGS=-lstdc++ -mcpu=cortex-m3 -g -O3 -mthumb -fdata-sections -ffunction-sections -std=c++98 -std=gnu++0x +CPP0_FLAGS=-lstdc++ -mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c++98 -std=gnu++0x CC_FLAGS=-mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c99 CC3_FLAGS=-mcpu=cortex-m3 -g -O3 -mthumb -fdata-sections -ffunction-sections -std=c99 CC_END_FLAGS=-lstdc++ -lc -lnosys -L. -T mz100/mz100.ld -fPIE --specs=nosys.specs -mcpu=cortex-m3 -mthumb -Wl,--gc-sections -O0 -flto -ffunction-sections -fdata-sections -DARM_GNU @@ -35,7 +35,7 @@ compile: @$(AS) -mcpu=cortex-m3 --gdwarf-2 -mthumb-interwork -o build/startup.o startup.S @$(CC) $(CC3_FLAGS) -c mz100/core_cm3.c -o build/core_cm3.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_ssp.c -o build/mz100_ssp.o - @$(CC) $(CC3_FLAGS) -c mz100/mz100_wdt.c -o build/mz100_wdt.o + @$(CC) $(CC_FLAGS) -c mz100/mz100_wdt.c -o build/mz100_wdt.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_gpio.c -o build/mz100_gpio.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_driver.c -o build/mz100_driver.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_adc.c -o build/mz100_adc.o @@ -43,7 +43,7 @@ compile: @$(CC) $(CC3_FLAGS) -c mz100/mz100_clock.c -o build/mz100_clock.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_rtc.c -o build/mz100_rtc.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_pinmux.c -o build/mz100_pinmux.o - @$(CC) $(CC3_FLAGS) -c mz100/mz100_pmu.c -o build/mz100_pmu.o + @$(CC) $(CC_FLAGS) -c mz100/mz100_pmu.c -o build/mz100_pmu.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_qspi.c -o build/mz100_qspi.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_aes.c -o build/mz100_aes.o @$(CC) $(CC3_FLAGS) -c mz100/mz100_gpt.c -o build/mz100_gpt.o @@ -62,18 +62,24 @@ compile: @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/tinflate.c -o build/uz-tinflate.o @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/tinfzlib.c -o build/uz-tinfzlib.o + @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -Wno-unknown-pragmas -c ../common/QRCode/src/qrcode.c -o build/qrcode.o + + + @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c compression.cpp -o build/compression.o @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c drawing.cpp -o build/drawing.o @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c epd_interface.cpp -o build/epd_interface.o - @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c powermgt.c -o build/powermgt.o - @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c syncedproto.c -o build/syncedproto.o + @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c powermgt.cpp -o build/powermgt.o +# @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c syncedproto.c -o build/syncedproto.o + @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLASGS) -c oepl-protocol.cpp -o build/oepl-protocol.o @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c comms.c -o build/comms.o @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c md5.c -o build/md5.o - @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c settings.c -o build/settings.o +# @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c settings.c -o build/settings.o + @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c settings.cpp -o build/settings.o @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c mz100/timer.c -o build/timer.o @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c mz100/util.c -o build/util.o - @$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c mz100/gpio.c -o build/gpio.o + @$(CC) $(CC_FLAGS) $(CC_WARNING_FLAGS) -c mz100/gpio.c -o build/gpio.o @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c uc8159-var-m2.cpp -o build/uc8159-var-m2.o @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c userinterface.cpp -o build/userinterface.o @$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c main.cpp -o build/main.o @@ -89,7 +95,7 @@ compile: build/compression.o \ build/drawing.o \ build/powermgt.o \ - build/syncedproto.o \ + build/oepl-protocol.o \ build/comms.o \ build/settings.o \ build/timer.o \ @@ -99,6 +105,7 @@ compile: build/uc8159-var-m2.o \ build/mz100_sleep.o \ build/core_cm3.o \ + build/qrcode.o \ build/uz-adler32.o build/uz-crc32.o build/uz-defl_static.o build/uz-genlz77.o build/uz-tinfgzip.o build/uz-tinflate.o build/uz-tinfzlib.o \ build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o \ build/startup.o -o main.axf diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.cpp index 596d602a..bdb0513d 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/compression.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "epd_interface.h" diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.cpp index 0655f393..0efbb668 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.cpp @@ -16,6 +16,8 @@ #include "compression.h" #include "oepl_fs.h" +#include "../common/QRCode/src/qrcode.h" + #include "../../oepl-definitions.h" #include "../../oepl-proto.h" @@ -23,802 +25,16 @@ extern "C" { extern void dump(const uint8_t *a, const uint16_t l); #include "mz100/util.h" #include "mz100/mz100_flash.h" +#include "../common/QRCode/src/qrcode.h" + } #include "userinterface.h" #include "epd_interface.h" -#define EEPROM_XFER_BLOCKSIZE 512 // shouldn't be any less than 256 bytes probably -#define DRAWITEM_LIST_SIZE 24 -struct __attribute__((packed)) imageHeader { - uint16_t width; - uint16_t height; - uint8_t bpp : 4; - uint8_t reserved : 4; -}; - -static drawItem *drawItems[DRAWITEM_LIST_SIZE] = {0}; - -void addBufferedImage(uint16_t x, uint16_t y, bool color, enum rotation ro, const uint8_t *image, bool mask) { - drawItem *di = new drawItem; - - di->setRotation(ro); - if (di->direction ^ epd->drawDirectionRight) { - int16_t temp = x; - x = y; - y = temp; - } - - uint16_t originalWidthBytes = (((uint16_t *)image)[0]) / 8; - uint16_t size = 0; - uint16_t width = ((uint16_t *)image)[0]; - - // find out if the original data was aligned in one byte; if not, add a byte - if (((uint16_t *)image)[0] % 8) originalWidthBytes++; - - // if we're drawing in X direction, we shift the content here. Add extra space for shifting! - if (!di->direction) { - width += x % 8; - } - - // check if the size is aligned in bytes; if not, add an extra for good measure; - if (width % 8) { - width /= 8; - width++; - } else { - width /= 8; - } - - size = width * ((uint16_t *)image)[1]; - size += 2; // not needed - - uint8_t *im = (uint8_t *)calloc(size, 1); - - for (uint16_t copyY = 0; copyY < ((uint16_t *)image)[1]; copyY++) { - memcpy(im + (copyY * width), image + 4 + (copyY * originalWidthBytes), originalWidthBytes); - - // if we draw in X direction, we need to shift bytes in the array - if (!di->direction && (x % 8)) { - drawItem::shiftBytesRight(im + (copyY * width), x % 8, width); - } - } - - di->addItem(im, width * 8, ((uint16_t *)image)[1]); - - di->xpos = x; - di->ypos = y; - di->color = color; - if (mask) - di->type = drawItem::drawType::DRAW_MASK; - else - di->type = drawItem::drawType::DRAW_BUFFERED_1BPP; - - di->addToList(); +uint32_t __attribute__((always_inline)) inline HAL_flashRead(uint32_t address, uint8_t *buffer, uint32_t num){ + return FLASH_Read(FLASH_FAST_READ_QUAD_OUT, address, buffer, num); } -void addFlashImage(uint16_t x, uint16_t y, bool color, enum rotation ro, const uint8_t *image) { - drawItem *di = new drawItem; - - di->setRotation(ro); - - if (di->direction ^ epd->drawDirectionRight) { - int16_t temp = x; - x = y; - y = temp; - } - - di->addItem((uint8_t *)(image + 4), ((uint16_t *)image)[0], ((uint16_t *)image)[1]); - - di->xpos = x; - di->ypos = y; - di->color = color; - di->cleanUp = false; - di->type = drawItem::drawType::DRAW_BUFFERED_1BPP; - di->addToList(); -} - -void addFSImage(uint16_t x, uint16_t y, uint8_t color, enum rotation ro, char *name) { - drawItem *di = new drawItem; - - di->setRotation(ro); - - if (di->direction ^ epd->drawDirectionRight) { - int16_t temp = x; - x = y; - y = temp; - } - - OEPLFile *file = fs->getFile(name); - if (!file) { - delete di; - return; - } - uint16_t width, height; - - file->getBlock(0, (uint8_t *)&width, 2); - file->getBlock(2, (uint8_t *)&height, 2); - - di->addItem((uint8_t *)file, width, height); - di->xpos = x; - di->ypos = y; - di->color = color; - di->cleanUp = true; - if (color == 2) { - di->type = drawItem::drawType::DRAW_OEPLFS_2BPP; - } else { - di->type = drawItem::drawType::DRAW_OEPLFS_1BPP; - } - di->addToList(); -} - -void addCompressedFSImage(uint16_t x, uint16_t y, enum rotation ro, char *name) { - drawItem *di = new drawItem; - di->type = drawItem::drawType::DRAW_COMPRESSED; - - di->setRotation(ro); - - if (di->direction ^ epd->drawDirectionRight) { - int16_t temp = x; - x = y; - y = temp; - } - - decompress *decomp = new decompress; - if (!decomp->openFromFile(name)) { - delete di; - delete decomp; - return; - } - - di->imageHeaderOffset = decomp->readByte(0); - - struct imageHeader imgheader; - decomp->getBlock(1, (uint8_t *)&imgheader, sizeof(struct imageHeader)); - - di->addItem((uint8_t *)decomp, imgheader.width, imgheader.height); - - di->xpos = x; - di->ypos = y; - di->color = imgheader.bpp; - di->cleanUp = true; - di->addToList(); -} - -void drawImageAtAddressWrap(uint32_t addr, uint8_t lut) { - // powerUp(INIT_EEPROM); - epdSetup(); - selectLUT(lut); - uint8_t *xferbuffer = (uint8_t *)malloc(EEPROM_XFER_BLOCKSIZE); - struct EepromImageHeader *eih = (struct EepromImageHeader *)xferbuffer; - FLASH_Read(FLASH_NORMAL_READ, addr, xferbuffer, sizeof(struct EepromImageHeader)); - switch (eih->dataType) { - case DATATYPE_IMG_RAW_1BPP: { - drawItem *di = new drawItem; - // di->setRotation(ro); - di->xpos = 0; - di->ypos = 0; - di->color = 0; - di->addItem((uint8_t *)addr, epd->effectiveXRes, epd->effectiveYRes); - di->type = drawItem::drawType::DRAW_EEPROM_1BPP; - di->direction = false; - di->cleanUp = false; - di->addToList(); - } break; - case DATATYPE_IMG_RAW_2BPP: { - drawItem *di = new drawItem; - // di->setRotation(ro); - di->xpos = 0; - di->ypos = 0; - di->color = 0; - di->addItem((uint8_t *)addr, epd->effectiveXRes, epd->effectiveYRes); - di->type = drawItem::drawType::DRAW_EEPROM_2BPP; - di->direction = false; - di->cleanUp = false; - di->addToList(); - } break; - case DATATYPE_IMG_ZLIB: { - drawItem *di = new drawItem; - decompress *decomp = new decompress; - di->type = drawItem::drawType::DRAW_COMPRESSED; - - addr += sizeof(struct EepromImageHeader); - - if (!decomp->openFromFlash(addr, eih->size)) { - delete di; - delete decomp; - return; - } - - di->imageHeaderOffset = decomp->readByte(0); - - struct imageHeader imgheader; - decomp->getBlock(1, (uint8_t *)&imgheader, sizeof(struct imageHeader)); - - di->addItem((uint8_t *)decomp, imgheader.width, imgheader.height); - - di->xpos = 0; - di->ypos = 0; - if (imgheader.bpp == 1) di->color = 0; - if (imgheader.bpp == 2) di->color = 2; - di->cleanUp = true; - di->addToList(); - } break; - } - free(xferbuffer); - addOverlay(); - - draw(); - epdEnterSleep(); -} - -extern "C" { -void drawImageAtAddress(uint32_t addr, uint8_t lut) { - drawImageAtAddressWrap(addr, 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; - uint8_t *framebuffer = (uint8_t *)calloc(framebufferSize + 4, 1); - if (framebuffer == NULL) { - return; - } - - ((uint16_t *)framebuffer)[0] = width + 1; - ((uint16_t *)framebuffer)[1] = height; - - framebuffer += 4; - - uint16_t w = width - 1; - uint16_t x = 1; - while (w--) { - framebuffer[(x / 8)] |= (uint8_t)(1 << (7 - ((uint8_t)x % 8))); - x++; - } - for (uint16_t curY = 1; curY < (height - 1); curY++) { - framebuffer[widthBytes * curY] = 0x80; - if (width % 8) - framebuffer[(widthBytes * curY) + widthBytes - 1] = (uint8_t)(1 << (7 - ((uint8_t)width % 8))); - else - framebuffer[(widthBytes * curY) + widthBytes - 1] = 0x01; - } - w = width - 1; - x = 1; - while (w--) { - framebuffer[(x / 8) + ((height - 1) * widthBytes)] |= (uint8_t)(1 << (7 - ((uint8_t)x % 8))); - x++; - } - framebuffer -= 4; - addBufferedImage(xpos, ypos, color, rotation::ROTATE_0, framebuffer, DRAW_NORMAL); - free(framebuffer); -} - -void drawMask(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 * height; - uint8_t *framebuffer = (uint8_t *)calloc(framebufferSize + 4, 1); - if (framebuffer == NULL) { - return; - } - - ((uint16_t *)framebuffer)[0] = width; - ((uint16_t *)framebuffer)[1] = height; - - framebuffer += 4; - - for (uint16_t curY = 0; curY < height; curY++) { - uint16_t w = width; - uint16_t x = 0; - while (w--) { - framebuffer[(x / 8) + (curY * widthBytes)] |= (uint8_t)(1 << (7 - ((uint8_t)x % 8))); - x++; - } - } - - framebuffer -= 4; - addBufferedImage(xpos, ypos, color, rotation::ROTATE_0, framebuffer, DRAW_INVERTED); - free(framebuffer); -} - -// drawItem (sprite) functions -void drawItem::shiftBytesRight(uint8_t *data, uint8_t shift, uint8_t len) { - // Ensure the shift value is within bounds (0 to 7) - shift = shift % 8; - - // Handle the case where shift is 0 or len is 0 - if (shift == 0 || len == 0) { - return; - } - - // Loop through the array from right to left - for (int i = len - 1; i > 0; i--) { - // Perform the shift by combining bits from the current byte - // and the next byte to its right - data[i] = (data[i] >> shift) | (data[i - 1] << (8 - shift)); - } - - // For the leftmost byte, simply shift it to the right - data[0] >>= shift; -} - -uint8_t drawItem::bitReverse(uint8_t byte) { - byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xAA); - byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xCC); - byte = (byte >> 4) | (byte << 4); - return byte; -} - -void drawItem::reverseBytes(uint8_t *src, uint8_t src_len) { - // Check for valid input - if (src == NULL || src_len == 0) { - return; - } - - // Reverse the entire source array - for (uint8_t i = 0; i < src_len / 2; i++) { - uint8_t temp = src[i]; - src[i] = src[src_len - i - 1]; - src[src_len - i - 1] = temp; - } - // Reverse the bits within the bytes - for (uint8_t i = 0; i < src_len; i++) { - src[i] = bitReverse(src[i]); - } -} - -void drawItem::copyWithByteShift(uint8_t *dst, uint8_t *src, uint8_t src_len, uint8_t offset) { - switch (type) { - case DRAW_MASK: - for (uint8_t i = 0; i < src_len; i++) { - dst[i + offset] &= ~(src[i]); - } - break; - default: - for (uint8_t i = 0; i < src_len; i++) { - dst[i + offset] |= src[i]; - } - break; - } -} - -void drawItem::renderDrawLine(uint8_t *line, uint16_t number, uint8_t c) { - drawItem *curDrawItem; - for (uint8_t i = 0; i < DRAWITEM_LIST_SIZE; i++) { - curDrawItem = drawItems[i]; - if (curDrawItem != nullptr) { - curDrawItem->getDrawLine(line, number, c); - } - } -} - -void drawItem::flushDrawItems() { - drawItem *curDrawItem; - for (uint8_t i = 0; i < DRAWITEM_LIST_SIZE; i++) { - curDrawItem = drawItems[i]; - if (curDrawItem != nullptr) { - delete curDrawItem; - drawItems[i] = nullptr; - } - } -} - -void drawItem::getXLine(uint8_t *line, uint16_t y, uint8_t c) { - switch (type) { - case DRAW_FONT: - case DRAW_BUFFERED_1BPP: - case DRAW_MASK: - if (c != color) return; - if ((y >= ypos) && (y < height + ypos)) { // was y > ypos, not >= - // y = height-y; - if (mirrorV) { - if (mirrorH) { - reverseBytes(&buffer[((height - (y - ypos)) * widthBytes)], widthBytes); - // reverseBytes(&buffer[((y - ypos) * widthBytes)], widthBytes); - } else { - reverseBytes(&buffer[((y - ypos) * widthBytes)], widthBytes); - } - } - if (mirrorH) { - copyWithByteShift(line, &buffer[((height - (y - ypos)) * widthBytes)], widthBytes, xpos / 8); - } else { - copyWithByteShift(line, &buffer[((y - ypos) * widthBytes)], widthBytes, xpos / 8); - } - } - break; - case DRAW_OEPLFS_1BPP: - case DRAW_OEPLFS_2BPP: - if ((color < 2) && (c != color)) return; - if ((y >= ypos) && (y < height + ypos)) { // was y > ypos, not >= - uint32_t offset = 4; - offset += c * height * widthBytes; - OEPLFile *file = (OEPLFile *)this->buffer; - uint8_t *dbuffer = (uint8_t *)malloc(widthBytes); - if (mirrorH) { - file->getBlock(offset + (height - (y - ypos)) * widthBytes, dbuffer, widthBytes); - } else { - file->getBlock(offset + (y - ypos) * widthBytes, dbuffer, widthBytes); - } - if (mirrorV) { - reverseBytes(dbuffer, widthBytes); - } - copyWithByteShift(line, dbuffer, widthBytes, xpos / 8); - free(dbuffer); - } - break; - case DRAW_COMPRESSED: - if ((color < 2) && (c != color)) return; - if ((y >= ypos) && (y < height + ypos)) { - uint32_t offset = this->imageHeaderOffset; - offset += c * height * widthBytes; - decompress *decomp = (decompress *)this->buffer; - uint8_t *dbuffer = (uint8_t *)malloc(widthBytes); - if (mirrorH) { - decomp->getBlock(offset + (height - (y - ypos)) * widthBytes, dbuffer, widthBytes); - } else { - decomp->getBlock(offset + (y - ypos) * widthBytes, dbuffer, widthBytes); - } - if (mirrorV) { - reverseBytes(dbuffer, widthBytes); - } - copyWithByteShift(line, dbuffer, widthBytes, xpos / 8); - free(dbuffer); - } - break; - case DRAW_EEPROM_1BPP: - if (c != color) return; - if (epd->drawDirectionRight) - y = epd->effectiveYRes - 1 - y; - FLASH_Read(FLASH_NORMAL_READ, (uint32_t)buffer + sizeof(struct EepromImageHeader) + (y * (epd->effectiveXRes / 8)), line, (epd->effectiveXRes / 8)); - break; - case DRAW_EEPROM_2BPP: - if (epd->drawDirectionRight) - y = epd->effectiveYRes - 1 - y; - FLASH_Read(FLASH_NORMAL_READ, (uint32_t)(buffer + sizeof(struct EepromImageHeader) + ((y + (c * epd->effectiveYRes)) * (epd->effectiveXRes / 8))), line, (epd->effectiveXRes / 8)); - break; - default: - printf("Not supported mode!\n"); - break; - } -} - -void drawItem::getYLine(uint8_t *line, uint16_t x, uint8_t c) { - switch (type) { - case DRAW_FONT: - case DRAW_BUFFERED_1BPP: - if (c != color) return; - if ((x >= xpos) && (x < width + xpos)) { - x -= xpos; - for (uint16_t curY = 0; curY < height; curY++) { - uint16_t curYMirrored = curY; - if (!mirrorH) curYMirrored = height - 1 - curY; - if (mirrorV) { - if (buffer[((width - x) / 8) + (curYMirrored * widthBytes)] & (1 << (7 - ((width - x) % 8)))) { - line[(curY + ypos) / 8] |= (1 << (7 - ((curY + ypos) % 8))); - } - } else { - if (buffer[(x / 8) + (curYMirrored * widthBytes)] & (1 << (7 - (x % 8)))) { - line[(curY + ypos) / 8] |= (1 << (7 - ((curY + ypos) % 8))); - } - } - } - } - break; - case DRAW_MASK: - if (c != color) return; - if ((x >= xpos) && (x < width + xpos)) { - x -= xpos; - for (uint16_t curY = 0; curY < height; curY++) { - uint16_t curYMirrored = curY; - if (!mirrorH) curYMirrored = height - 1 - curY; - if (mirrorV) { - if (buffer[((width - x) / 8) + (curYMirrored * widthBytes)] & (1 << (7 - ((width - x) % 8)))) { - line[(curY + ypos) / 8] &= ~(1 << (7 - ((curY + ypos) % 8))); - } - } else { - if (buffer[(x / 8) + (curYMirrored * widthBytes)] & (1 << (7 - (x % 8)))) { - line[(curY + ypos) / 8] &= ~(1 << (7 - ((curY + ypos) % 8))); - } - } - } - } - break; - case DRAW_OEPLFS_1BPP: - case DRAW_OEPLFS_2BPP: - // this is incredibly slow. For larger images, it'll probably read 128 bytes of eeprom for every -bit- in the image. - if ((color < 2) && (c != color)) return; - if ((x >= xpos) && (x < width + xpos)) { - uint32_t offset = 4; - offset += c * height * widthBytes; - OEPLFile *file = (OEPLFile *)this->buffer; - x -= xpos; - for (uint16_t curY = 0; curY < height; curY++) { - uint16_t curYMirrored = curY; - if (!mirrorH) curYMirrored = height - 1 - curY; - if (mirrorV) { - if (file->readByte(offset + ((width - x) / 8) + (curYMirrored * widthBytes)) & (1 << (7 - ((width - x) % 8)))) { - line[(curY + ypos) / 8] |= (1 << (7 - ((curY + ypos) % 8))); - } - } else { - if (file->readByte(offset + (x / 8) + (curYMirrored * widthBytes)) & (1 << (7 - (x % 8)))) { - line[(curY + ypos) / 8] |= (1 << (7 - ((curY + ypos) % 8))); - } - } - } - } - break; - - default: - break; - } -} - -void drawItem::getDrawLine(uint8_t *line, uint16_t number, uint8_t c) { - if (direction) { - getYLine(line, number, c); - } else { - getXLine(line, number, c); - } -} - -void drawItem::addItem(uint8_t *data, uint16_t w, uint16_t h) { - width = w; - height = h; - widthBytes = w / 8; - if (w % 8) widthBytes++; - buffer = data; -} - -bool drawItem::addToList() { - for (uint8_t i = 0; i < DRAWITEM_LIST_SIZE; i++) { - if (drawItems[i] == nullptr) { - drawItems[i] = this; - return true; - }; - } - return false; -} - -drawItem::~drawItem() { - if (cleanUp) { - switch (this->type) { - case drawItem::drawType::DRAW_OEPLFS_1BPP: - case drawItem::drawType::DRAW_OEPLFS_2BPP: { - OEPLFile *file = (OEPLFile *)this->buffer; - if (file) delete file; - } break; - case drawItem::drawType::DRAW_COMPRESSED: { - decompress *dec = (decompress *)this->buffer; - if (dec) delete dec; - } break; - default: - free(buffer); - break; - } - } -} - -drawItem::drawItem() { - if (epd->drawDirectionRight) { - direction = true; - mirrorH = true; - } -} - -void drawItem::setRotation(enum rotation ro) { - if (epd->drawDirectionRight) { - direction = true; - mirrorH = true; - } - - switch (ro) { - case ROTATE_0: - break; - case ROTATE_270: - direction = !direction; - mirrorH = !mirrorH; - mirrorV = !mirrorV; - break; - case ROTATE_180: - mirrorH = !mirrorH; - mirrorV = !mirrorV; - break; - case ROTATE_90: - direction = !direction; - break; - }; -} - -// font rendering functions -fontrender::fontrender(char *name) { - this->setFont(name); -} - -void fontrender::setFont(char *name) { - if (this->glyphFile) delete this->glyphFile; - if (this->bitmapFile) delete this->bitmapFile; - OEPLFile *font = fs->getFile(name); - if (!font) - printf("Couldn't open font file %s\n", name); - // else - // printf("Opened %s\n", name); - font->getBlock(0, (uint8_t *)&this->gfxFont, sizeof(GFXFontOEPL)); - this->glyphFile = fs->getFile(this->gfxFont.glyphFile); - this->bitmapFile = fs->getFile(this->gfxFont.bitmapFile); - - if (!this->glyphFile) printf("Couldn't open font file %s\n", name); - if (!this->bitmapFile) printf("Couldn't open font file %s\n", name); - if (font) delete (font); -} - -fontrender::~fontrender() { - if (this->glyphFile) delete this->glyphFile; - if (this->bitmapFile) delete this->bitmapFile; -} - -void fontrender::drawFastHLine(uint16_t x, uint16_t y, uint16_t w) { - while (w--) { - fb[(x / 8) + (y * bufferByteWidth)] |= (uint8_t)(1 << (7 - ((uint8_t)x % 8))); - x++; - } -} - -void fontrender::fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - for (uint16_t curY = y; curY < y + h; curY++) { - drawFastHLine(x, curY, w); - } -} - -uint8_t fontrender::getCharWidth(uint16_t c) { - if ((c >= gfxFont.first) && (c <= gfxFont.last)) { - c -= gfxFont.first; - // GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); - GFXglyph glyph = this->getGlyph(c); - return glyph.xAdvance; - } - return 0; -} - -uint8_t fontrender::drawChar(int32_t x, int32_t y, uint16_t c, uint8_t size) { - // Filter out bad characters not present in font - if ((c >= gfxFont.first) && (c <= gfxFont.last)) { - c -= gfxFont.first; - GFXglyph glyph = this->getGlyph(c); - // uint8_t *bitmap = (uint8_t *)gfxFont->bitmap; - uint32_t bo = glyph.bitmapOffset; - uint8_t w = glyph.width, - h = glyph.height; - int8_t xo = glyph.xOffset, - yo = glyph.yOffset; - uint8_t xx, yy, bits = 0, bit = 0; - int16_t xo16 = 0, yo16 = 0; - - if (size > 1) { - xo16 = xo; - yo16 = yo; - } - - // GFXFF rendering speed up - uint16_t hpc = 0; // Horizontal foreground pixel count - for (yy = 0; yy < h; yy++) { - for (xx = 0; xx < w; xx++) { - if (bit == 0) { - // bits = bitmap[bo++]; - bits = (*this->bitmapFile)(bo++); - bit = 0x80; - } - if (bits & bit) - hpc++; - else { - if (hpc) { - if (size == 1) - drawFastHLine(x + xo + xx - hpc, y + yo + yy, hpc); - else - fillRect(x + (xo16 + xx - hpc) * size, y + (yo16 + yy) * size, size * hpc, size); - hpc = 0; - } - } - bit >>= 1; - } - // Draw pixels for this line as we are about to increment yy - if (hpc) { - if (size == 1) - drawFastHLine(x + xo + xx - hpc, y + yo + yy, hpc); - else - fillRect(x + (xo16 + xx - hpc) * size, y + (yo16 + yy) * size, size * hpc, size); - hpc = 0; - } - } - return glyph.xAdvance; - } - return 0; -} - -void fontrender::epdPrintf(uint16_t x, uint16_t y, bool color, enum rotation ro, const char *c, ...) { - drawItem *di = new drawItem; - if (di == nullptr) return; - di->setRotation(ro); - - // prepare a drawItem, exchange x/y if necessary. - if (di->direction ^ epd->drawDirectionRight) { - int16_t temp = x; - x = y; - y = temp; - } - - // output string using vsnprintf - char out_buffer[256]; - va_list lst; - va_start(lst, c); - uint8_t len = vsnprintf(out_buffer, 255, c, lst); - va_end(lst); - - // account for offset in font rendering - if (!di->direction) { - Xpixels = x % 8; // total drawing width increased by x%8 - } else { - Xpixels = 0; - } - - // find out the total length of the string - for (uint8_t c = 0; c < len; c++) { - Xpixels += (uint16_t)getCharWidth(out_buffer[c]); - } - - // find out the high and low points for given font - int8_t high = 0; - int8_t low = 0; - for (uint8_t curchar = 0; curchar < len; curchar++) { - uint8_t c = out_buffer[curchar]; - if ((c >= gfxFont.first) && (c <= gfxFont.last)) { - c -= gfxFont.first; - GFXglyph g = this->getGlyph(c); - int8_t glyphUL = g.yOffset; - if (glyphUL < high) high = glyphUL; - int8_t glyphHeight = g.height; - if ((glyphUL + glyphHeight) > low) low = glyphUL + glyphHeight; - } - } - // Actual font height (reduces memory footprint) - int8_t height = -1 * (high - low) + 1; - - // determine actual width - bufferByteWidth = Xpixels / 8; - if (Xpixels % 8) bufferByteWidth++; - - // allocate framebuffer - fb = (uint8_t *)calloc(bufferByteWidth * height, 1); - - if (!fb) { - printf("Failed to allocate buffer for drawitem, we can't render this text!\n"); - printf("Tried to allocate a buffer %d x %d\n", bufferByteWidth, height); - delete di; - return; - } - - uint16_t curX; - if (!di->direction) { - curX = x % 8; // start drawing at x%8s - } else { - curX = 0; - } - for (uint8_t c = 0; c < len; c++) { - curX += (uint16_t)drawChar(curX, height - low, out_buffer[c], 1); - } - - di->addItem(fb, curX, height); - di->ypos = y; - di->xpos = x; - di->color = color; - di->type = drawItem::drawType::DRAW_FONT; - di->addToList(); -} - -GFXglyph fontrender::getGlyph(uint16_t c) { - GFXglyph g; - this->glyphFile->getBlock(sizeof(GFXglyph) * c, (uint8_t *)&g, sizeof(GFXglyph)); - return g; -} \ No newline at end of file +#include "../common/drawing.cpp" \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.h index a83e9bc2..b6ac6c65 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/drawing.h @@ -2,132 +2,13 @@ #define _DRAWING_H_ #include + +#define ENABLE_OEPLFS + +#ifdef ENABLE_OEPLFS #include "oepl_fs.h" - -#define COLOR_RED 1 -#define COLOR_BLACK 0 -#define COLOR_DUAL 2 - -#define IMAGE_OR 1 -#define IMAGE_REPLACE 0 - -#define DRAW_INVERTED 1 -#define DRAW_NORMAL 0 - -#define FILENAME_LENGTH 32 - -typedef struct __attribute__ ((packed)) { - uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap - uint8_t width; ///< Bitmap dimensions in pixels - uint8_t height; ///< Bitmap dimensions in pixels - uint8_t xAdvance; ///< Distance to advance cursor (x axis) - int8_t xOffset; ///< X dist from cursor pos to UL corner - int8_t yOffset; ///< Y dist from cursor pos to UL corner -} GFXglyph; - -enum rotation { - ROTATE_0, - ROTATE_90, - ROTATE_180, - ROTATE_270 -}; - -typedef struct __attribute__ ((packed)) { - uint16_t first; - uint16_t last; - uint8_t yAdvance; - char glyphFile[FILENAME_LENGTH]; - char bitmapFile[FILENAME_LENGTH]; -} GFXFontOEPL; - - -extern "C"{ - void drawImageAtAddress(uint32_t addr, uint8_t lut); -} - -void addBufferedImage(uint16_t x, uint16_t y, bool color, enum rotation ro, const uint8_t *image, bool mask); -// void addFlashImage(uint16_t x, uint16_t y, bool color, enum rotation ro, const uint8_t *image); -void addQR(uint16_t x, uint16_t y, uint8_t version, uint8_t scale, const char *c, ...); -void drawRoundedRectangle(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, bool color); -void drawMask(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, bool color); -void addFSImage(uint16_t x, uint16_t y, uint8_t color, enum rotation ro, char *name); -void addCompressedFSImage(uint16_t x, uint16_t y, enum rotation ro, char *name); - -class drawItem { - public: - drawItem(); - ~drawItem(); - void setRotation(enum rotation ro); - void addItem(uint8_t *data, uint16_t width, uint16_t height); - bool addToList(); - - static void shiftBytesRight(uint8_t *data, uint8_t shift, uint8_t len); - static void renderDrawLine(uint8_t *line, uint16_t number, uint8_t c); - static void flushDrawItems(); - - // these are also used for rotated screens - static void reverseBytes(uint8_t *src, uint8_t src_len); - static uint8_t bitReverse(uint8_t byte); - - enum drawType { - DRAW_FONT, - DRAW_BUFFERED_1BPP, - DRAW_MASK, - DRAW_EEPROM_1BPP, - DRAW_EEPROM_2BPP, - DRAW_COMPRESSED, - DRAW_OEPLFS_1BPP, - DRAW_OEPLFS_2BPP - } type; - - int16_t xpos; - int16_t ypos; - - enum rotation rotate = ROTATE_0; - - uint8_t color = 0; - - bool direction = false; - - bool mirrorH = false; - bool mirrorV = false; - uint16_t width; - uint16_t height; - - uint8_t imageHeaderOffset = 0; - - // if this is true, clean up the reference (free memory). - bool cleanUp = true; - - protected: - void copyWithByteShift(uint8_t *dst, uint8_t *src, uint8_t src_len, uint8_t offset); - - void getDrawLine(uint8_t *line, uint16_t number, uint8_t c); - 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 *buffer = nullptr; -}; - -class fontrender { - public: - void epdPrintf(uint16_t x, uint16_t y, bool color, enum rotation ro, const char *c, ...); - fontrender(char* name); - ~fontrender(); - void setFont(char* name); - - protected: - GFXFontOEPL gfxFont; - uint16_t bufferByteWidth = 0; - uint8_t *fb = nullptr; - uint16_t Xpixels; - uint8_t drawChar(int32_t x, int32_t y, uint16_t c, uint8_t size); - uint8_t getCharWidth(uint16_t c); - void drawFastHLine(uint16_t x, uint16_t y, uint16_t w); - void fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h); - GFXglyph getGlyph(uint16_t c); - OEPLFile *glyphFile = nullptr; - OEPLFile *bitmapFile = nullptr; -}; - #endif + +#include "../common/drawing.h" + +#endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.cpp index 561d2048..36ac59bb 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.cpp @@ -23,21 +23,24 @@ extern "C" { #include "mz100/util.h" } +#include "settings.h" + #include "../../oepl-definitions.h" #include "../../oepl-proto.h" -epdInterface *epd; - +__attribute__((section(".aonshadow"))) epdInterface *epd; +__attribute__((section(".aonshadow"))) tagSpecs tag; epdInterface::~epdInterface(){ } void epdSetup() { epd = new uc8159; - epd->effectiveXRes = 640; - epd->effectiveYRes = 384; - epd->Xres = 640; - epd->Yres = 384; + epd->effectiveXRes = tagProfile.xRes; + epd->effectiveYRes = tagProfile.yRes; + epd->Xres = tagProfile.xRes; + epd->Yres = tagProfile.yRes; + epd->bpp = tagProfile.bpp; epd->epdSetup(); } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.h index ac9738f3..9d8c5e7c 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd_interface.h @@ -1,5 +1,5 @@ #pragma once -//#include +// #include #include #include #include @@ -20,13 +20,26 @@ class epdInterface { uint16_t effectiveYRes; uint16_t XOffset = 0; uint16_t YOffset = 0; + uint8_t bpp = 0; bool drawDirectionRight = false; bool epdMirrorV = false; bool epdMirrorH = false; }; +struct tagSpecs { + uint8_t buttonCount = 0; + bool hasNFC = false; + bool hasLED = false; + uint16_t macSuffix = 0x0000; + uint8_t OEPLtype = 0; + uint8_t solumType = 0; + uint32_t imageSize = 0; +} __attribute__((packed)); + +extern __attribute__((section(".aonshadow"))) tagSpecs tag; + //__attribute__((section(".aonshadow"))) -extern epdInterface* epd; +extern epdInterface *epd; void epdSetup(); void epdEnterSleep(); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.cpp index 04a2d21a..4d1b3127 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.cpp @@ -6,10 +6,13 @@ #include #include "epd_interface.h" - -extern "C" { +#include "powermgt.h" #include "main.h" + +#include "settings.h" +extern "C" { + #include "comms.h" #include "mz100/core_cm3.h" #include "mz100/eeprom.h" @@ -25,11 +28,9 @@ extern "C" { #include "mz100/mz100_sleep.h" #include "mz100/mz100_ssp.h" #include "mz100/mz100_uart.h" -#include "powermgt.h" #include "mz100/printf.h" #include "proto.h" -#include "settings.h" -#include "syncedproto.h" + #include "mz100/timer.h" #include "mz100/util.h" @@ -37,6 +38,8 @@ extern "C" { extern void dump(const uint8_t *a, const uint16_t l); } +#include "oepl-protocol.h" + #include "compression.h" #include "userinterface.h" @@ -50,7 +53,6 @@ uint64_t __attribute__((section(".default_mac"))) default_mac = SW_DEFAULT_MAC; char macStr[32]; char macStr1[32]; -// uint8_t mSelfMac[8]; #define TAG_MODE_CHANSEARCH 0 #define TAG_MODE_ASSOCIATED 1 @@ -78,17 +80,18 @@ bool protectedFlashWrite(uint32_t address, uint8_t *buffer, uint32_t num) { return false; } -static void prvGetSelfMac(void) { - FLASH_Read((FLASH_ReadMode_Type)0, EEPROM_MAC_INFO_START, mSelfMac, 8); - +static void initTagProfile() { + for (uint8_t c = 0; c < 8; c++) { + mSelfMac[c] = tagProfile.macAddress[7 - c]; + } if ((((uint32_t *)mSelfMac)[0] | ((uint32_t *)mSelfMac)[1]) == 0 || (((uint32_t *)mSelfMac)[0] & ((uint32_t *)mSelfMac)[1]) == 0xffffffff) { // fastest way to check for all ones or all zeroes - printf("mac unknown\r\n"); - // Write a blank mac to have something to work with. - memcpy(&mSelfMac, (uint8_t *)&default_mac, 8); - FLASH_Write((FLASH_ProgramMode_Type)0, EEPROM_MAC_INFO_START, mSelfMac, 8); - // sleep_with_with_wakeup(0); + printf("MAC: mac unknown, taking random Flash ID\n"); + *((uint64_t *)&tagProfile.macAddress) = FLASH_GetUniqueID(); } + + tag.imageSize = flashRoundUp(sizeof(struct EepromImageHeader) + (tagProfile.xRes * tagProfile.yRes * tagProfile.bpp) / 8); + tag.OEPLtype = 0x05; } uint8_t showChannelSelect() { // returns 0 if no accesspoints were found @@ -147,6 +150,7 @@ uint8_t channelSelect() { // returns 0 if no accesspoints were found void __attribute__((interrupt)) NMIException(void) { printf("-----------> NMIException\r\n"); + delay(1000); PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; PMU->PWR_MODE.BF.PWR_MODE = 0; NVIC_SystemReset(); @@ -181,25 +185,42 @@ void __attribute__((interrupt)) UsageFaultException(void) { } void __attribute__((interrupt)) SVCHandler(void) { + printf("-----------> SVCHandler\r\n"); + PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; + PMU->PWR_MODE.BF.PWR_MODE = 0; + NVIC_SystemReset(); } void __attribute__((interrupt)) DebugMonitor(void) { + printf("-----------> DebugMonitor\r\n"); + PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; + PMU->PWR_MODE.BF.PWR_MODE = 0; + NVIC_SystemReset(); } void __attribute__((interrupt)) PendSVC(void) { + printf("-----------> PendSVC\r\n"); + PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1; + PMU->PWR_MODE.BF.PWR_MODE = 0; + NVIC_SystemReset(); } -void setupRTC() { - CLK_Xtal32MEnable(CLK_OSC_INTERN); - while (!CLK_GetClkStatus(CLK_OUT_XTAL64M)) - ; +int32_t setupRTC(uint32_t calibrate) { + // CLK_Xtal32MEnable(CLK_OSC_INTERN); + // while (!CLK_GetClkStatus(CLK_OUT_XTAL64M)) + // ; RC32K_CalClk_Div(63, 31); CLK_ModuleClkEnable(CLK_RC32K_CAL); CLK_RC32KEnable(); while (!CLK_GetClkStatus(CLK_OUT_RC32K)) ; PMU->RC32K_CAL_CNTL.BF.RC32K_CAL_DIV = 0; - CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_AUTO_CAL, 0); + int32_t calres; + if (!calibrate) { + calres = CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_AUTO_CAL, 0); + } else { + calres = CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_MANUAL_CAL, calibrate); + } CLK_ModuleClkEnable(CLK_RTC); CLK_RTCClkSrc(CLK_RTC_RC32K); RTC_Stop(); @@ -212,6 +233,7 @@ void setupRTC() { NVIC_ClearPendingIRQ(RTC_IRQn); RTC_IntMask(RTC_INT_CNT_UPP, UNMASK); NVIC_EnableIRQ(RTC_IRQn); + return calres; } void setupUART() { @@ -238,17 +260,6 @@ void setupUART() { // UART 1 DEBUG OUT } -void setupWDT() { - //** WATCHDOG - CLK_ModuleClkEnable(CLK_WDT); - WDT_SetMode(WDT_MODE_RESET); - WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256); - WDT_SetTimeoutVal(30); - WDT_RestartCounter(); - WDT_Enable(); - //** WATCHDOG -} - void setupGPIO() { //** GPIOS init_GPIO_boot(); @@ -265,9 +276,9 @@ void setupGPIO() { } } -void setupCLKCalib() { +int32_t setupCLKCalib() { (*(volatile unsigned int *)0x4A070004) = ((*(volatile unsigned int *)0x4A070004) & 0xFFFFFFE0) + 2; - PMU->PWR_MODE.BF.PWR_MODE = 2; + // PMU->PWR_MODE.BF.PWR_MODE = 2; // hmmm uint32_t v0 = FLASH_WordRead(FLASH_NORMAL_READ, 4u); char v1; if (!(~v0 << 25)) { @@ -276,13 +287,14 @@ void setupCLKCalib() { ; v1 = CLK_RC32MCalibration(CLK_AUTO_CAL, 0); FLASH_WordWrite(FLASH_PROGRAM_NORMAL, 4u, (v0 & 0xFFFFFF00) | (v1 & 0x7F)); + return v1; } + return -1; } void TagAssociated() { // associated struct AvailDataInfo *avail; - printf("longDataReqCounter = %d\n", longDataReqCounter); // Is there any reason why we should do a long (full) get data request (including reason, status)? if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) { // check if we should do a voltage measurement (those are pretty expensive) @@ -302,9 +314,10 @@ void TagAssociated() { if (curImgSlot != 0xFF) { powerUp(INIT_EEPROM | INIT_EPD); wdt60s(); - drawImageFromEeprom(curImgSlot); + drawImageFromEeprom(curImgSlot, 0); powerDown(INIT_EEPROM | INIT_EPD); } else { + WDT_RestartCounter(); powerUp(INIT_EPD); showAPFound(); powerDown(INIT_EPD); @@ -314,6 +327,7 @@ void TagAssociated() { powerUp(INIT_RADIO); printf("full request\n"); avail = getAvailDataInfo(); + avail = getAvailDataInfo(); powerDown(INIT_RADIO); if (avail != NULL) { @@ -389,7 +403,7 @@ void TagChanSearch() { wdt60s(); if (curImgSlot != 0xFF) { powerUp(INIT_EEPROM); - drawImageFromEeprom(curImgSlot); + drawImageFromEeprom(curImgSlot, 0); powerDown(INIT_EEPROM); } else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) { showLongTermSleep(); @@ -401,12 +415,13 @@ void TagChanSearch() { // did we find a working channel? if (currentChannel) { + printf("PROTO: Found a working channel from the TagChanSearch loop\n"); // now associated! set up and bail out of this loop. scanAttempts = 0; wakeUpReason = WAKEUP_REASON_NETWORK_SCAN; initPowerSaving(INTERVAL_BASE); - doSleep(getNextSleep() * 1000UL); currentTagMode = TAG_MODE_ASSOCIATED; + sleep_with_with_wakeup(getNextSleep() * 1000UL); return; } else { // still not associated @@ -419,65 +434,80 @@ int main(void) { (*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000 (*(volatile unsigned int *)0xE000E41A) = 0x40; // ?? - timerInit(); - CLK_SystemClkInit(CLK_SYS_XTAL64M, CLK_SYS_64M); CLK_Xtal32MEnable(CLK_OSC_INTERN); while (CLK_GetClkStatus(CLK_OUT_XTAL64M) != 1) ; - + setupUART(); + setupCLKCalib(); if (!loadValidateAonRam() || PMU_GetLastResetCause()) { - setupWDT(); + // cold boot! + + // calibrate the 32K RC oscillator (autocal), we'll store the result to flash later + uint32_t rtccal = setupRTC(0); setupGPIO(); - setupCLKCalib(); - setupUART(); - // fs = new OEPLFs(); - printf("Rst reason: %i\r\n", PMU_GetLastResetCause()); - printf("AON is not valid!\n"); - setupRTC(); + timerInit(); + setupWDT(); + clearAonRam(); - prvGetSelfMac(); + // all variables are set to 0 now. This might not be appropriate for all variables, such as: + curImgSlot = 0xFF; + + // try to load settings + if (!loadSettings()) { + // if we couldn't load settings, we'll try to get it from the tagprofile file. Useful during development + fs->init(); + if (!loadProfileFromFile((char *)"tagprofile.bin")) { + // whoops. Empty profile, that shouldn't really ever happen, ever. + printf("We don't know the type of this tag. That's kinda bad, I guess...\n"); + } else { + fs->deleteFile((char *)"tagprofile.bin"); + } + } + printf("MAIN: MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", tagProfile.macAddress[0], tagProfile.macAddress[1], tagProfile.macAddress[2], tagProfile.macAddress[3], tagProfile.macAddress[4], tagProfile.macAddress[5], tagProfile.macAddress[6], tagProfile.macAddress[7]); + + tagProfile.RC32Kcal = rtccal; + + printf("MAIN: Rst reason: %i\r\n", PMU_GetLastResetCause()); + + initTagProfile(); + + wdt10s(); showSplashScreen(); delay(10000); currentChannel = 0; zigbeeCalibData.isValid = false; wakeUpReason = WAKEUP_REASON_FIRSTBOOT; initializeProto(); - printf("Erz data\r\n"); initPowerSaving(INTERVAL_BASE); - loadDefaultSettings(); + doVoltageReading(); - // qspiEraseRange(EEPROM_SETTINGS_AREA_START, EEPROM_SETTINGS_AREA_LEN); - - sprintf(macStr, "(" MACFMT ")", MACCVT(mSelfMac)); currentChannel = showChannelSelect(); - WDT_RestartCounter(); if (currentChannel) { - printf("AP Found\r\n"); + printf("MAIN: AP Found\r\n"); + wdt10s(); delay(10000); showAPFound(); - sprintf(macStr1, "OpenEPaperLink Ch: %i", currentChannel); + sprintf(macStr1, "MAIN: OpenEPaperLink Ch: %i", currentChannel); + wdt10s(); timerDelay(TIMER_TICKS_PER_MSEC * 1000); currentTagMode = TAG_MODE_ASSOCIATED; } else { printf("No AP found\r\n"); + wdt10s(); + delay(10000); showNoAP(); - sleep_with_with_wakeup(120000UL); + wdt10s(); + timerDelay(TIMER_TICKS_PER_MSEC * 1000); currentTagMode = TAG_MODE_CHANSEARCH; } - powerUp(INIT_UART); - + writeSettings(); } else { - setupWDT(); // turn me off + setupRTC(tagProfile.RC32Kcal); + setupWDT(); setupGPIO(); - setupCLKCalib(); // turn me off - // setupUART();// turn me off - // setupRTC();// turn me off - memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES); - powerUp(INIT_UART); - - // fs = new OEPLFs(); + timerInit(); } while (1) { @@ -503,30 +533,29 @@ void _putchar(char c) { _write(0, &c, 1); } -void applyUpdate() { - uint32_t ofst, now, size, pieceSz = 0x2000; +void applyUpdate(uint32_t size) { + uint32_t ofst, now, pieceSz = 0x2000; uint8_t chunkStore[0x2000]; printf("Applying update\r\n"); // apparently, the flash process is more reliable if we do these two first setupCLKCalib(); - setupRTC(); + setupRTC(0); showApplyUpdate(); - printf("Applying update\r\n"); - qspiEraseRange(EEPROM_OS_START, EEPROM_OS_LEN); + // qspiEraseRange(EEPROM_OS_START, EEPROM_OS_LEN); - size = EEPROM_OS_LEN; for (ofst = 0; ofst < size; ofst += now) { now = size - ofst; if (now > pieceSz) now = pieceSz; - printf("Cpy 0x%06x + 0x%04x to 0x%06x\r\n", EEPROM_UPDATE_START + ofst, now, EEPROM_OS_START + ofst); - FLASH_Read((FLASH_ReadMode_Type)0, EEPROM_UPDATE_START + ofst, chunkStore, now); - protectedFlashWrite(EEPROM_OS_START + ofst, chunkStore, now); + printf("Cpy 0x%06x + 0x%04x to 0x%06x\r\n", fsEnd + ofst, now, ofst); + FLASH_Read((FLASH_ReadMode_Type)0, fsEnd + ofst, chunkStore, now); + // qspiEraseRange(ofst, now); + protectedFlashWrite(ofst, chunkStore, now); WDT_RestartCounter(); } printf("Resetting!\n"); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h index a1e3f4b3..842a788c 100755 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h @@ -30,4 +30,4 @@ #define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 -void applyUpdate(); +void applyUpdate(uint32_t len); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/eeprom.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/eeprom.h index 81fbf849..76b50d7d 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/eeprom.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/eeprom.h @@ -8,29 +8,16 @@ //pages are 4K in size //an update can be stored in any 2 image slots -#define EEPROM_PAGE_SIZE (0x01000UL) +#define EEPROM_SETTINGS_AREA_START (0x7F000UL) +#define EEPROM_SETTINGS_SIZE (0x01000UL) -#define EEPROM_OS_START (0x00000UL) -#define EEPROM_OS_LEN (0x1FFFFUL) //0xE820 of image, rounded up to 4K - -#define EEPROM_IMG_START (0x20000UL) -#define EEPROM_IMG_EACH (0x1F000UL) -#define EEPROM_IMG_LEN (EEPROM_IMG_START + 0x13FFFUL) - -#define EEPROM_UPDATE_START (0x20000UL) //same header as images -#define EEPROM_UPDATE_LEN (0x1FFFFUL) - -#define EEPROM_SETTINGS_AREA_START (0x14000UL) -#define EEPROM_SETTINGS_AREA_LEN (0x03000UL) +#define EEPROM_TOTAL_SIZE (0x80000UL) #define EEPROM_MAC_INFO_START (0x6c000UL) //not same as stock #define EEPROM_MAC_INFO_LEN (0x01000UL) - -#define EEPROM_IMG_INPROGRESS (0x7fffffff) #define EEPROM_IMG_VALID (0x494d4721) - //#define EEPROM_PIECE_SZ (88) #include "../../common/eeprom_struct.h" diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.c index 53d06e39..a4f524f1 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.c @@ -1,6 +1,6 @@ #include "nfc.h" -//#include +// #include #include #include #include @@ -14,38 +14,46 @@ #include "util.h" #include "printf.h" +#include "mz100_clock.h" -void NVIC_some_IRQ1(unsigned int a1) -{ +volatile bool RTCintFired = false; + +void setupWDT() { + //** WATCHDOG + CLK_ModuleClkEnable(CLK_WDT); + WDT_SetMode(WDT_MODE_RESET); + WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256); + WDT_SetTimeoutVal(30); + WDT_RestartCounter(); + WDT_Enable(); + //** WATCHDOG +} + +void NVIC_some_IRQ1(unsigned int a1) { *(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1E80) = 1 << (a1 & 0x1F); } -void NIVC_some_IRQ(unsigned int a1) -{ +void NIVC_some_IRQ(unsigned int a1) { *(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1D80) = 1 << (a1 & 0x1F); } -void Pin_pad_set_Low(int pin) -{ +void Pin_pad_set_Low(int pin) { GPIO_PinPadOutputEnable(pin); GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW); GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD); } -void Pin_pad_set_High(int pin) -{ +void Pin_pad_set_High(int pin) { GPIO_PinPadOutputEnable(pin); GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_HIGH); GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD); } -void Pin_pad_set_Normal(int pin) -{ +void Pin_pad_set_Normal(int pin) { GPIO_PinPadOutputEnable(pin); GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW); GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_NORMAL_FUNCTION); } -void init_GPIO_boot() -{ +void init_GPIO_boot() { Pin_pad_set_Normal(NFC_POWER); Pin_pad_set_Normal(NFC_IRQ); Pin_pad_set_Normal(EPD_MOSI); @@ -59,10 +67,9 @@ void init_GPIO_boot() Pin_pad_set_Normal(EPD_RESET); Pin_pad_set_Normal(EPD_HLT_CTRL); } -void init_GPIO_sleep() -{ +void init_GPIO_sleep() { Pin_pad_set_Low(NFC_POWER); - //Pin_pad_set_Low(NFC_IRQ); + // Pin_pad_set_Low(NFC_IRQ); Pin_pad_set_Low(EPD_MOSI); Pin_pad_set_Low(EPD_MISO); Pin_pad_set_Low(EPD_CLK); @@ -77,10 +84,8 @@ void init_GPIO_sleep() uint8_t WAKEUP_RF = 0; -void __attribute__((interrupt)) ExtPin5_IRQHandler(void) -{ - if (!WAKEUP_RF) - { +void __attribute__((interrupt)) ExtPin5_IRQHandler(void) { + if (!WAKEUP_RF) { NVIC_ClearPendingIRQ(ExtPin5_IRQn); GPIO_IntMask(RF_WAKEUP_PIN, MASK); NVIC_some_IRQ1(ExtPin5_IRQn); @@ -90,10 +95,17 @@ void __attribute__((interrupt)) ExtPin5_IRQHandler(void) } } -uint32_t gSleepRtcCounter = 0; -uint8_t Ext_Pin27_triggered = 0; -void __attribute__((interrupt)) ExtPin27_IRQHandler(void) -{ +void __attribute__((interrupt)) ExtPin7_IRQHandler(void) { + NVIC_ClearPendingIRQ(ExtPin7_IRQn); + GPIO_IntMask(NFC_IRQ, MASK); + NVIC_some_IRQ1(ExtPin7_IRQn); + PMU_ClearWakeupExtpin(PMU_GPIO7_INT); + NVIC_ClearPendingIRQ(ExtPin7_IRQn); +} + +volatile uint32_t gSleepRtcCounter = 0; +volatile uint8_t Ext_Pin27_triggered = 0; +void __attribute__((interrupt)) ExtPin27_IRQHandler(void) { WDT_RestartCounter(); printf(">>PIN_27_IRQHandler\r\n"); NVIC_ClearPendingIRQ(ExtPin27_IRQn); @@ -104,33 +116,26 @@ void __attribute__((interrupt)) ExtPin27_IRQHandler(void) Ext_Pin27_triggered = 1; } -void enable_irq_for_pin(int a1, unsigned int a2) -{ - PMU_WakeupPinSrc_Type v4; // r0 - PMU_WakeupPinSrc_Type v5; // r5 - char v6; // r7 - PMU_WakeupTrigMode_Type v7; // r1 +void enable_irq_for_pin(int a1, unsigned int a2) { + PMU_WakeupPinSrc_Type v4; // r0 + PMU_WakeupPinSrc_Type v5; // r5 + char v6; // r7 + PMU_WakeupTrigMode_Type v7; // r1 GPIO_PinMuxFun(a2, 7); - if (a2 > 7) - { + if (a2 > 7) { if (a2 - 26 > 5) return; v4 = a2 - 19; - } - else - { + } else { v4 = a2 - 1; } v5 = v4; v6 = a2 + 31; - if (a1 == 1) - { + if (a1 == 1) { GPIO_PinModeConfig(a2, PINMODE_PULLDOWN); v7 = PMU_WAKEUP_EDGE_RISING; - } - else - { + } else { if (a1 != 2) goto LABEL_11; GPIO_PinModeConfig(a2, PINMODE_PULLUP); @@ -144,13 +149,13 @@ LABEL_11: NVIC_EnableIRQ(v6); } -void wait_busy_sleep(int a1) -{ +void wait_busy_sleep(int a1) { unsigned int v1 = 0; gSleepRtcCounter = 0; - printf("=> EPD_BUSYN_PIN : %d\r\n", 27); - while (1) - { + // printf("=> EPD_BUSYN_PIN : %d\r\n", 27); + delay(1); + + while (1) { RTC_CounterReset(); RTC_IntClr(RTC_INT_CNT_UPP); NIVC_some_IRQ(0); @@ -163,10 +168,7 @@ void wait_busy_sleep(int a1) if (Ext_Pin27_triggered == 1) break; v1++; - delay(2000); - printf("busypin:%d,SCNT:%d\r\n", GPIO_ReadPinLevel(EPD_BUSY), v1); - if (v1 >= 0x5A) - { + if (v1 >= 0x5A) { printf("DRF BUSY CHECK FAIL\r\n"); break; } @@ -176,7 +178,7 @@ void wait_busy_sleep(int a1) NIVC_some_IRQ(0); (*(volatile unsigned int *)0xE000E180) = 1; gSleepRtcCounter = 1000 * RTC_GetCounterVal() / 0x7FFFu + a1 * v1; - printf("RTC_GetCounterVal(): %d, gSleepRtcCounter:%d(ms)\r\n", RTC_GetCounterVal(), gSleepRtcCounter); + // printf("RTC_GetCounterVal(): %d, gSleepRtcCounter:%d(ms)\r\n", RTC_GetCounterVal(), gSleepRtcCounter); RTC_CounterReset(); Ext_Pin27_triggered = 0; GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT); @@ -184,14 +186,13 @@ void wait_busy_sleep(int a1) GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP); } -void do_sleeped_epd_refresh() -{ +void do_sleeped_epd_refresh() { printf("PM2 MODE START!\r\n"); PMU->PMIP_BRN.BF.BRNDET_EN = 0; PMU->PWR_MODE.BF.CAU_ON = 0; PMU->PMIP_CHP_CTRL.BF.CHP_ON_OFF = 1; PMU_SetSleepMode(PMU_PM2); PMU_ClearWakeupExtpin(PMU_GPIO5_INT); - wait_busy_sleep(2000); + wait_busy_sleep(500); printf("uDisTime : %d ms\r\n", gSleepRtcCounter); } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.h index 3009c8f3..f2ee367b 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/gpio.h @@ -1,5 +1,7 @@ #pragma once +void setupWDT(); + void NVIC_some_IRQ1(unsigned int a1); void NIVC_some_IRQ(unsigned int a1); void init_GPIO_boot(); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100.ld b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100.ld index bfbcf36c..415f8098 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100.ld +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100.ld @@ -3,8 +3,8 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0x100000, LENGTH = 80k - RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 2k + FLASH (rx) : ORIGIN = 0x100000, LENGTH = 90k + RAM (rwx) : ORIGIN = 0x20100000 + 90k, LENGTH = 160k - 90k - 2k AONSHADOW (rwx) : ORIGIN = 0x20128000 - 2k, LENGTH = 2k AON (rwx) : ORIGIN = 0x20130000 , LENGTH = 4k } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100_sleep.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100_sleep.c index e1fd150c..cfd94179 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100_sleep.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/mz100_sleep.c @@ -97,7 +97,7 @@ void sleep_with_with_wakeup(uint32_t sleep_time_ms) //memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest)); //memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo)); //sleep_time_ms = 10000; - printf("sleep! %u\n", sleep_time_ms); + //printf("sleep! %u\n", sleep_time_ms); uint32_t sleep_time_ms_1; AON_level_VDD(7); AON_level_VAA(0); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.c index 128f9823..6fce70b6 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.c @@ -1,7 +1,7 @@ #include "util.h" #include -//#include +// #include #include "printf.h" #include "eeprom.h" @@ -12,7 +12,7 @@ #include "timer.h" void wdt10s() { - WDT_RestartCounter(); + WDT_RestartCounter(); } void wdt30s() { WDT_RestartCounter(); @@ -120,19 +120,19 @@ uint32_t measureBattery(void) { void qspiEraseRange(uint32_t addr, uint32_t len) { uint64_t time; // round starting address down - if (addr % EEPROM_PAGE_SIZE) { - len += addr % EEPROM_PAGE_SIZE; - addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; + if (addr % EEPROM_ERZ_SECTOR_SZ) { + len += addr % EEPROM_ERZ_SECTOR_SZ; + addr = addr / EEPROM_ERZ_SECTOR_SZ * EEPROM_ERZ_SECTOR_SZ; } // round length up - len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE; + len = (len + EEPROM_ERZ_SECTOR_SZ - 1) / EEPROM_ERZ_SECTOR_SZ * EEPROM_ERZ_SECTOR_SZ; while (len) { uint32_t now; bool ok; - WDT_RestartCounter(); + //WDT_RestartCounter(); if (!(addr % 0x10000) && len >= 0x10000) { ok = FLASH_Block64KErase(addr / 0x10000); now = 0x10000; @@ -156,16 +156,16 @@ void qspiEraseRange(uint32_t addr, uint32_t len) { ; } } - WDT_RestartCounter(); + //WDT_RestartCounter(); } bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len) { - FLASH_Write(0, addr, (void*)srcP, len); + FLASH_Write(0, addr, (void *)srcP, len); return true; } bool eepromErase(uint32_t addr, uint16_t nSec) { - qspiEraseRange(addr, nSec); + qspiEraseRange(addr, nSec*EEPROM_ERZ_SECTOR_SZ); return true; } @@ -173,8 +173,18 @@ void eepromRead(uint32_t addr, void *dstP, uint16_t len) { uint8_t *dst = (uint8_t *)dstP; FLASH_Read(0, addr, dst, len); } + +extern __attribute__((section(".aonshadow"))) uint32_t fsEnd; + uint32_t eepromGetSize(void) { - return EEPROM_IMG_LEN; + return EEPROM_TOTAL_SIZE - fsEnd; +} + +uint32_t flashRoundUp(uint32_t in) { + uint32_t temp = in / EEPROM_ERZ_SECTOR_SZ; + if (in % EEPROM_ERZ_SECTOR_SZ) + temp++; + return temp * EEPROM_ERZ_SECTOR_SZ; } void radioShutdown(void) { diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.h index f6e57fdc..dc5cdbb5 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100/util.h @@ -18,6 +18,8 @@ bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len); bool eepromErase(uint32_t addr, uint16_t nSec); void eepromRead(uint32_t addr, void *dstP, uint16_t len); +uint32_t flashRoundUp(uint32_t in); + uint32_t eepromGetSize(void); void radioShutdown(void); //experimentally written. suggest reset after use to bring radio back :) diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.cpp new file mode 100644 index 00000000..9d0bfd26 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.cpp @@ -0,0 +1,90 @@ + +#include "oepl-protocol.h" + +#include "powermgt.h" +#include "main.h" + +extern "C" { +#include "board.h" +#include "comms.h" +#include "mz100/eeprom.h" +#include "mz100/mz100_sleep.h" +#include "mz100/printf.h" +#include "proto.h" +#include "mz100/timer.h" +#include "mz100/util.h" +#include "mz100/mz100_flash.h" +#include "zigbee.h" +#include "md5.h" +} + +#include "drawing.h" + +#include "oepl_fs.h" + +#include "epd_interface.h" + +#include "settings.h" + +#define BLOCKSIZE_MS 270 // was 270 + +#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) { +} + +#define EEPROM_IMG_START fsEnd + +#define FW_LOC fsEnd +#define FW_METADATA_LOC 0 + +void dump(const uint8_t *a, const uint16_t l); + +static bool validateEepromMD5(uint64_t ver, uint32_t eepromstart, uint32_t flen) { +#define CHUNK_SIZE 512 + uint8_t chunk[CHUNK_SIZE]; + MD5Context ctx; + md5Init(&ctx); + // Open the executable itself for reading + for (uint32_t offset = 0; offset < flen; offset += CHUNK_SIZE) { + uint32_t len = flen - offset; + if (len > CHUNK_SIZE) len = CHUNK_SIZE; + FLASH_Read(FLASH_NORMAL_READ, eepromstart + offset, chunk, len); + // eepromRead(eepromstart + offset, chunk, 512); + md5Update(&ctx, chunk, len); + } + + // Retrieve the final hash + md5Finalize(&ctx); + + bool isValid = ver == *((uint64_t *)ctx.digest); + if (!isValid) { + printf("MD5 failed check! This is what we should get:\n"); + dump((const uint8_t *)&(ver), 8); + printf("This is what we got:\n"); + dump(ctx.digest, 16); + } else { +#ifdef DEBUG_PROTO + printf("PROTO: MD5 Pass\n"); +#endif + } +#ifdef DEBUG_DONTVALIDATEPROTO + return true; +#else + return isValid; +#endif +} + +#include "../common/oepl-protocol.cpp" \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.h new file mode 100644 index 00000000..dfb96569 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl-protocol.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +#include "settings.h" + +#define PERSISTENTVAR __attribute__((section(".aonshadow"))) + +#include "../common/oepl-protocol.h" \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.cpp index 16b096a7..a94fd4d0 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.cpp @@ -2,9 +2,11 @@ #include #include #include +#include "settings.h" extern "C" { #include "mz100/mz100_flash.h" #include "mz100/printf.h" +#include "mz100/util.h" } // #pragma pack(1) @@ -14,9 +16,10 @@ extern "C" { extern "C" { __attribute__((section(".aonshadow"))) uint32_t fsEntry; __attribute__((section(".aonshadow"))) uint32_t fsEnd; -extern void dump(const uint8_t *a, const uint16_t l); } +extern void dump(const uint8_t *a, const uint16_t l); + OEPLFs oeplfs; OEPLFs *fs = &oeplfs; @@ -41,7 +44,9 @@ OEPLFs::~OEPLFs() { } uint32_t OEPLFs::findEntry() { +#ifdef DEBUG_FS printf("FS: Trying to find OEPL FS...\n"); +#endif uint8_t *scan = (uint8_t *)malloc(1024); uint32_t offset = 0; // scan flash with some overlap, to ensure the entire string is in the buffer at some point @@ -69,7 +74,9 @@ uint32_t OEPLFs::findEntry() { } if (offset) { +#ifdef DEBUG_FS printf("FS: Found at 0x%08X\n", offset); +#endif } else { printf("FS: Not found. Did you forget to add it?\n"); FLASH_Read(FLASH_FAST_READ_QUAD_OUT, 0x109C0, scan, 1024); @@ -79,6 +86,40 @@ uint32_t OEPLFs::findEntry() { return offset; } +void OEPLFs::deleteFile(char *name) { + // get file list inside of the vector + uint8_t *buffer = (uint8_t *)malloc(1024); + FLASH_Read(FLASH_FAST_READ_QUAD_OUT, fsEntry, buffer, 1024); + bool firstFile = true; + uint8_t *fatEnd = nullptr; + uint8_t *curFileP = buffer; + curFileP += 11; // set to begin file table + while (1) { + OEPLFSFile *file; + file = new OEPLFSFile; + memcpy((void *)file, curFileP, sizeof(OEPLFSFile)); + + if (firstFile) { + firstFile = false; + fatEnd = buffer + file->offset - 1; + } + + if (strncmp(name, file->name, FILENAME_LENGTH) == 0) { + char overwriteName[FILENAME_LENGTH]; + memset(overwriteName, 0x00, FILENAME_LENGTH); + FLASH_Write(FLASH_PROGRAM_NORMAL, fsEntry + (curFileP - buffer), (uint8_t *)overwriteName, FILENAME_LENGTH); + break; + } + + curFileP += sizeof(OEPLFSFile); + + if (curFileP > fatEnd) { + break; + } + } + free(buffer); +} + void OEPLFs::populateFiles() { // get file list inside of the vector uint8_t *buffer = (uint8_t *)malloc(1024); @@ -104,8 +145,9 @@ void OEPLFs::populateFiles() { char tmp[32]; memcpy(tmp, file->name, 32); tmp[31] = 0x00; - if(!silent)printf("name=%s, size=%u, offset=%u\n", tmp, file->len, file->offset); - +#ifdef DEBUG_FS + if (!silent) printf("name=%s, size=%u, offset=%u\n", tmp, file->len, file->offset); +#endif fsend = file->len + file->offset; if (curFileP > fatEnd) { done = true; @@ -113,6 +155,7 @@ void OEPLFs::populateFiles() { } } fsEnd = fsend + fsEntry; + fsEnd = flashRoundUp(fsEnd); free(buffer); } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.h index a22b7878..e0006e28 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/oepl_fs.h @@ -38,6 +38,7 @@ class OEPLFs { OEPLFs(); std::vector files; OEPLFile* getFile(char* name); + void deleteFile(char* name); void init(); bool isStarted = false; diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c index 4a92ef07..a31000f2 100755 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c @@ -6,15 +6,24 @@ // #include #include +#include "epd_interface.h" #include "board.h" -#include "mz100/eeprom.h" + + #include "main.h" + +#include "oepl-protocol.h" + +#include "settings.h" + +extern "C" { +#include "mz100/eeprom.h" #include "mz100/mz100_sleep.h" #include "mz100/printf.h" #include "screen.h" -#include "syncedproto.h" #include "mz100/util.h" #include "zigbee.h" +} __attribute__((section(".aonshadow"))) uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in __attribute__((section(".aonshadow"))) uint8_t dataReqAttemptArrayIndex = 0; @@ -47,7 +56,7 @@ void setupPortsInitial() { uint16_t doVoltageReading() { batteryVoltage = (uint16_t)measureBattery(); - if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) { + if (batteryVoltage < tagSettings.batLowVoltage) { lowBattery = true; } else { lowBattery = false; @@ -98,6 +107,7 @@ void powerUp(const uint8_t parts) { } if (parts & INIT_EPD) { configSPI(true); + epdSetup(); } if (parts & INIT_EEPROM) { configEEPROM(true); @@ -108,6 +118,9 @@ void powerUp(const uint8_t parts) { } void powerDown(const uint8_t parts) { + if(parts & INIT_EPD){ + epdEnterSleep(); + } // printf("Power down: %d\r\n", parts); } diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.cpp new file mode 100644 index 00000000..41d18368 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.cpp @@ -0,0 +1,159 @@ +#include "powermgt.h" + +#include +#include +#include +// #include +#include + +#include "epd_interface.h" +#include "main.h" +#include "oepl-protocol.h" +#include "board.h" + +extern "C"{ +#include "mz100/eeprom.h" +#include "mz100/mz100_sleep.h" +#include "mz100/printf.h" +#include "screen.h" +#include "mz100/util.h" +#include "zigbee.h" +} + +__attribute__((section(".aonshadow"))) uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in +__attribute__((section(".aonshadow"))) uint8_t dataReqAttemptArrayIndex = 0; +__attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt = 0; +__attribute__((section(".aonshadow"))) uint16_t nextCheckInFromAP = 0; +__attribute__((section(".aonshadow"))) uint8_t wakeUpReason = 0; +__attribute__((section(".aonshadow"))) uint8_t scanAttempts = 0; + +__attribute__((section(".aonshadow"))) int8_t temperature = 0; +__attribute__((section(".aonshadow"))) uint16_t batteryVoltage = 0; +__attribute__((section(".aonshadow"))) bool lowBattery = false; +__attribute__((section(".aonshadow"))) uint16_t longDataReqCounter = 0; +__attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter = 0; + +__attribute__((section(".aonshadow"))) uint8_t capabilities = 0; + +bool spiActive = false; +bool uartActive = false; +bool eepromActive = false; +bool i2cActive = false; + +extern int8_t adcSampleTemperature(void); // in degrees C + +uint8_t checkButtonOrJig() { + return DETECT_P1_0_NOTHING; +} + +void setupPortsInitial() { +} + +uint16_t doVoltageReading() { + batteryVoltage = (uint16_t)measureBattery(); + if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) { + lowBattery = true; + } else { + lowBattery = false; + } + return batteryVoltage; +} + +void initPowerSaving(const uint16_t initialValue) { + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { + dataReqAttemptArr[c] = initialValue; + } +} + +static void configSPI(const bool setup) { + spiActive = setup; +} + +static void configUART(const bool setup) { + /* if (setup == uartActive) + return; + uartActive = setup; + if (setup) + Serial.begin(115200); + else + Serial.end();*/ +} + +static void configEEPROM(const bool setup) { +} + +static void configI2C(const bool setup) { +} + +void powerUp(const uint8_t parts) { + // printf("Power up: %d\r\n", parts); + if (parts & INIT_RADIO) { + radioInit(); + // radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID); + // radioSetTxPower(10); + if (currentChannel >= 11 && currentChannel <= 27) { + radioSetChannel(currentChannel); + } else { + radioSetChannel(RADIO_FIRST_CHANNEL); + } + } + if (parts & INIT_UART) { + configUART(true); + } + if (parts & INIT_EPD) { + configSPI(true); + epdSetup(); + } + if (parts & INIT_EEPROM) { + configEEPROM(true); + } + if (parts & INIT_I2C) { + configI2C(true); + } +} + +void powerDown(const uint8_t parts) { + if(parts & INIT_EPD){ + epdEnterSleep(); + } + // printf("Power down: %d\r\n", parts); +} + +void doSleep(const uint32_t t) { + printf("Sleeping for: %d ms\r\n", t); + // sleepForMs(t); + delay(t); +} + +uint32_t getNextScanSleep(const bool increment) { + if (increment) { + if (scanAttempts < 255) + scanAttempts++; + } + + if (scanAttempts < INTERVAL_1_ATTEMPTS) { + return INTERVAL_1_TIME; + } else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)) { + return INTERVAL_2_TIME; + } else { + return INTERVAL_3_TIME; + } +} + +void addAverageValue() { + uint16_t curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE; + curval *= dataReqLastAttempt; + curval /= DATA_REQ_MAX_ATTEMPTS; + curval += INTERVAL_BASE; + dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval; + dataReqAttemptArrayIndex++; +} + +uint16_t getNextSleep() { + uint16_t avg = 0; + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { + avg += dataReqAttemptArr[c]; + } + avg /= POWER_SAVING_SMOOTHING; + return avg; +} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h index f44632ef..7c558eb1 100755 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.h @@ -29,7 +29,7 @@ #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. // 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 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 @@ -37,7 +37,7 @@ #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) -#define BATTERY_VOLTAGE_MINIMUM 2450 // 2600 or below is the best we can do on the EPD +#define BATTERY_VOLTAGE_MINIMUM 2950 // 2900 or below is the best we can do on the EPD // 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 @@ -55,7 +55,7 @@ extern void powerUp(const uint8_t parts); extern void powerDown(const uint8_t parts); extern void initAfterWake(); -extern void doSleep(const uint32_t t); +extern void doSleep(const uint32_t t); extern void addAverageValue(); extern uint16_t getNextSleep(); @@ -65,17 +65,17 @@ extern uint16_t doVoltageReading(); extern uint32_t getNextScanSleep(const bool increment); extern void initPowerSaving(const uint16_t initialValue); -extern uint8_t wakeUpReason; +extern uint8_t wakeUpReason; -extern __attribute__((section(".aonshadow"))) uint8_t capabilities; +extern __attribute__((section(".aonshadow"))) uint8_t capabilities; -extern uint16_t nextCheckInFromAP; -extern __attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt; -extern __attribute__((section(".aonshadow"))) int8_t temperature; -extern __attribute__((section(".aonshadow"))) uint16_t batteryVoltage; -extern __attribute__((section(".aonshadow"))) bool lowBattery; -extern __attribute__((section(".aonshadow"))) uint8_t scanAttempts; -extern __attribute__((section(".aonshadow"))) uint16_t longDataReqCounter; -extern __attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter; +extern uint16_t nextCheckInFromAP; +extern __attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt; +extern __attribute__((section(".aonshadow"))) int8_t temperature; +extern __attribute__((section(".aonshadow"))) uint16_t batteryVoltage; +extern __attribute__((section(".aonshadow"))) bool lowBattery; +extern __attribute__((section(".aonshadow"))) uint8_t scanAttempts; +extern __attribute__((section(".aonshadow"))) uint16_t longDataReqCounter; +extern __attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter; #endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c deleted file mode 100755 index 3aba475d..00000000 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "settings.h" -#include "proto.h" -#include -#include "mz100/eeprom.h" -#include "mz100/util.h" -#include "mz100/mz100_flash.h" -#include "powermgt.h" - - - __attribute__((section(".aonshadow"))) struct tagsettings tagSettings = {0}; -extern uint8_t blockXferBuffer[]; -uint8_t* infopageTempBuffer = 1024 + blockXferBuffer; - - -void loadDefaultSettings() { - tagSettings.settingsVer = SETTINGS_STRUCT_VERSION; - tagSettings.enableFastBoot = DEFAULT_SETTING_FASTBOOT; - tagSettings.enableRFWake = DEFAULT_SETTING_RFWAKE; - tagSettings.enableTagRoaming = DEFAULT_SETTING_TAGROAMING; - tagSettings.enableScanForAPAfterTimeout = DEFAULT_SETTING_SCANFORAP; - tagSettings.enableLowBatSymbol = DEFAULT_SETTING_LOWBATSYMBOL; - tagSettings.enableNoRFSymbol = DEFAULT_SETTING_NORFSYMBOL; - tagSettings.customMode = 0; - tagSettings.fastBootCapabilities = 0; - tagSettings.minimumCheckInTime = INTERVAL_BASE; - tagSettings.fixedChannel = 0; - tagSettings.batLowVoltage = BATTERY_VOLTAGE_MINIMUM; -} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.cpp new file mode 100644 index 00000000..5d75e6d2 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +#include "settings.h" +#include "proto.h" + +extern "C" { +#include +#include "mz100/eeprom.h" +#include "mz100/util.h" +#include "mz100/mz100_flash.h" +#include "powermgt.h" +#include "mz100/printf.h" +} + +#include "oepl_fs.h" + +__attribute__((section(".aonshadow"))) struct tagsettings tagSettings = {0}; +__attribute__((section(".aonshadow"))) struct tagHardwareProfile tagProfile = {0}; + +void loadDefaultSettings() { + tagSettings.settingsVer = SETTINGS_STRUCT_VERSION; + tagSettings.enableFastBoot = DEFAULT_SETTING_FASTBOOT; + tagSettings.enableRFWake = DEFAULT_SETTING_RFWAKE; + tagSettings.enableTagRoaming = DEFAULT_SETTING_TAGROAMING; + tagSettings.enableScanForAPAfterTimeout = DEFAULT_SETTING_SCANFORAP; + tagSettings.enableLowBatSymbol = DEFAULT_SETTING_LOWBATSYMBOL; + tagSettings.enableNoRFSymbol = DEFAULT_SETTING_NORFSYMBOL; + tagSettings.customMode = 0; + tagSettings.fastBootCapabilities = 0; + tagSettings.minimumCheckInTime = INTERVAL_BASE; + tagSettings.fixedChannel = 0; + tagSettings.batLowVoltage = BATTERY_VOLTAGE_MINIMUM; +} + +#define SETTINGS_OFFSET 8 +#define TAGPROFILE_OFFSET 32 + +void invalidateSettings() { + uint64_t buffer = 0x5555555555555555ull; + FLASH_Write(FLASH_PROGRAM_NORMAL, EEPROM_SETTINGS_AREA_START, (uint8_t*)&buffer, 8); +} + +static bool compareSettings() { + // check if the values are already the same, to ensure we don't write the same values to flash + uint8_t buffer[256]; + uint64_t magic; + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START, (uint8_t*)&magic, 8); + if (magic != MAGIC_NUMBER_SETTINGS) { + return false; + } + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START + SETTINGS_OFFSET, buffer, sizeof(struct tagsettings) + 64); + if (memcmp((void*)buffer, (void*)&tagSettings, sizeof(struct tagsettings)) != 0) { + return false; + } + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START + TAGPROFILE_OFFSET, buffer, sizeof(struct tagHardwareProfile)); + if (memcmp((void*)buffer, (void*)&tagProfile, sizeof(struct tagHardwareProfile)) != 0) { + return false; + } +#ifdef DEBUG_SETTINGS + printf("SETTINGS: Settings/profile match, not saving.\n"); +#endif + return true; +} + +void writeSettings() { + if (compareSettings()) return; +#ifdef DEBUG_SETTINGS + printf("SETTINGS: Writing settings\n"); +#endif + FLASH_Erase(EEPROM_SETTINGS_AREA_START, EEPROM_SETTINGS_AREA_START + 4095); + FLASH_Write(FLASH_PROGRAM_NORMAL, EEPROM_SETTINGS_AREA_START + SETTINGS_OFFSET, (uint8_t*)&tagSettings, sizeof(struct tagsettings)); + FLASH_Write(FLASH_PROGRAM_NORMAL, EEPROM_SETTINGS_AREA_START + TAGPROFILE_OFFSET, (uint8_t*)&tagProfile, sizeof(struct tagHardwareProfile)); + uint64_t magic = MAGIC_NUMBER_SETTINGS; + FLASH_Write(FLASH_PROGRAM_NORMAL, EEPROM_SETTINGS_AREA_START, (uint8_t*)&magic, 8); +} + +bool loadSettings() { + uint64_t magic; + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START, (uint8_t*)&magic, 8); + if (magic == MAGIC_NUMBER_SETTINGS) { +#ifdef DEBUG_SETTINGS + printf("SETTINGS: Succesfully loaded settings\n"); +#endif + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START + SETTINGS_OFFSET, (uint8_t*)&tagSettings, sizeof(struct tagsettings)); + FLASH_Read(FLASH_NORMAL_READ, EEPROM_SETTINGS_AREA_START + TAGPROFILE_OFFSET, (uint8_t*)&tagProfile, sizeof(struct tagHardwareProfile)); + return true; + } else { +#ifdef DEBUG_SETTINGS + printf("SETTINGS: Default settings loaded\n"); +#endif + loadDefaultSettings(); + return false; + } +} + +bool loadProfileFromFile(char* filename) { + OEPLFile* file = fs->getFile(filename); + if (!file) { + return false; + } + file->getBlock(0, (uint8_t*)&tagProfile, sizeof(struct tagHardwareProfile)); + writeSettings(); + return true; +} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h index a606f906..131e73ab 100755 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/settings.h @@ -3,16 +3,27 @@ #include -#define FW_VERSION 0x0027 // version number (max 2.5.5 :) ) -#define FW_VERSION_SUFFIX "-75" // suffix, like -RC1 or whatever. -// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers -// #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket +#define FW_VERSION 0x0027 // version number (max 2.5.5 :) ) +#define FW_VERSION_SUFFIX "-zlib" // suffix, like -RC1 or whatever. -#define DEBUG_EPD -#define DEBUG_FS +//#define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers +//#define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket + +//#define DEBUG_EPD +//#define DEBUG_FS + +//#define DEBUG_COMPRESSION +//#define DEBUG_PROTO +//#define DEBUG_SETTINGS +//#define DEBUG_DONTVALIDATEPROTO + + + +#if defined(DEBUG_SETTINGS) || defined(DEBUG_EPD) || defined(DEBUGBLOCKS) || defined(DEBUG_PROTO) || defined(DEBUG_COMPRESSION) || defined(DEBUG_FS) #define DEBUG_BUILD -#define DEBUG_COMPRESSION +#endif + #define SETTINGS_STRUCT_VERSION 0x01 @@ -24,10 +35,17 @@ #define DEFAULT_SETTING_LOWBATSYMBOL 1 #define DEFAULT_SETTING_NORFSYMBOL 1 -extern __attribute__((section(".aonshadow")))struct tagsettings tagSettings; +#define MAGIC_NUMBER_SETTINGS (0xD34DBEEFD0D0CAFEull) +#include "tagprofile_struct.h" + +extern __attribute__((section(".aonshadow"))) struct tagsettings tagSettings; +extern __attribute__((section(".aonshadow"))) struct tagHardwareProfile tagProfile; + +void invalidateSettings(); void loadDefaultSettings(); void writeSettings(); -void loadSettings(); +bool loadSettings(); void loadSettingsFromBuffer(uint8_t* p); +bool loadProfileFromFile(char* filename); #endif \ No newline at end of file diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c deleted file mode 100755 index 0589b9cb..00000000 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.c +++ /dev/null @@ -1,839 +0,0 @@ - -#include "syncedproto.h" - -#include "board.h" -#include "comms.h" -#include "mz100/eeprom.h" -#include "main.h" -#include "mz100/mz100_sleep.h" -#include "powermgt.h" -#include "mz100/printf.h" -#include "proto.h" -#include "mz100/timer.h" -#include "mz100/util.h" -#include "mz100/mz100_flash.h" -#include "zigbee.h" -#include "md5.h" - -// download-stuff -uint8_t blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0}; -__attribute__((section(".aonshadow"))) struct blockRequest curBlock = {0}; // used by the block-requester, contains the next request that we'll send -__attribute__((section(".aonshadow"))) struct AvailDataInfo xferDataInfo = {0}; // last 'AvailDataInfo' we received from the AP -bool requestPartialBlock = false; // if we should ask the AP to get this block from the host or not -#define BLOCK_TRANSFER_ATTEMPTS 10 - -__attribute__((section(".aonshadow"))) uint8_t prevImgSlot = 0xFF; -__attribute__((section(".aonshadow"))) uint8_t curImgSlot = 0xFF; -__attribute__((section(".aonshadow"))) static uint32_t curHighSlotId = 0; -__attribute__((section(".aonshadow"))) static uint8_t nextImgSlot = 0; -__attribute__((section(".aonshadow"))) static uint8_t imgSlots = 0; -__attribute__((section(".aonshadow"))) uint8_t drawWithLut = 0; - -// stuff we need to keep track of related to the network/AP -uint8_t APmac[8] = {0}; -uint16_t APsrcPan = 0; -__attribute__((section(".aonshadow"))) uint8_t mSelfMac[8] = {0}; -__attribute__((section(".aonshadow"))) static uint8_t seq = 0; -__attribute__((section(".aonshadow"))) volatile uint8_t currentChannel = 0; - -// buffer we use to prepare/read packets -static uint8_t inBuffer[128] = {0}; -static uint8_t outBuffer[128] = {0}; - -// #define DEBUGBLOCKS 1 - -// from drawing.cpp -extern void drawImageAtAddress(uint32_t addr, uint8_t lut); - -// tools -static uint8_t getPacketType(const void *buffer) { - const struct MacFcs *fcs = buffer; - if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) { - // broadcast frame - uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)]; - return type; - } else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) { - // normal frame - uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)]; - return type; - } - return 0; -} -static bool pktIsUnicast(const void *buffer) { - const struct MacFcs *fcs = buffer; - if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) { - return false; - } else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) { - // normal frame - return true; - } - // unknown type... - return false; -} -void dump(const uint8_t *a, const uint16_t l) { - printf("\n "); -#define ROWS 16 - for (uint8_t c = 0; c < ROWS; c++) { - printf(" %02X", c); - } - printf("\n--------"); - for (uint8_t c = 0; c < ROWS; c++) { - printf("---"); - } - for (uint16_t c = 0; c < l; c++) { - if ((c % ROWS) == 0) { - printf("\n0x%04X | ", c); - } - printf("%02X ", a[c]); - } - printf("\n--------"); - for (uint8_t c = 0; c < ROWS; c++) { - printf("---"); - } - printf("\n"); -} -static bool checkCRC(const void *p, const uint8_t len) { - uint8_t total = 0; - for (uint8_t c = 1; c < len; c++) { - total += ((uint8_t *)p)[c]; - } - // printf("CRC: rx %d, calc %d\n", ((uint8_t *)p)[0], total); - return ((uint8_t *)p)[0] == total; -} -static void addCRC(void *p, const uint8_t len) { - uint8_t total = 0; - for (uint8_t c = 1; c < len; c++) { - total += ((uint8_t *)p)[c]; - } - ((uint8_t *)p)[0] = total; -} - -// radio stuff -static void sendPing() { - struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); - memset(outBuffer, 0, sizeof(struct MacFrameBcast) + 2 + 4); - outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2; - outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_PING; - memcpy(txframe->src, mSelfMac, 8); - txframe->fcs.frameType = 1; - txframe->fcs.ackReqd = 1; - txframe->fcs.destAddrType = 2; - txframe->fcs.srcAddrType = 3; - txframe->seq = seq++; - txframe->dstPan = PROTO_PAN_ID; - txframe->dstAddr = 0xFFFF; - txframe->srcPan = PROTO_PAN_ID; - commsTxNoCpy(outBuffer); -} -uint8_t detectAP(const uint8_t channel) { - uint32_t t; - radioRxEnable(false); - radioSetChannel(channel); - radioRxFlush(); - radioRxEnable(true); - for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++) { - sendPing(); - t = timerGet() + (TIMER_TICKS_PER_MSEC * 5); - while (timerGet() < t) { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - if ((inBuffer[sizeof(struct MacFrameNormal) + 1] == channel) && (getPacketType(inBuffer) == PKT_PONG)) { - if (pktIsUnicast(inBuffer)) { - // dump(inBuffer,32); - struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; - memcpy(APmac, f->src, 8); - APsrcPan = f->pan; - return c; - } - } - } - timerDelay(TIMER_TICKS_PER_MSEC * 2); - } - } - return 0; -} - -// data xfer stuff -static void sendShortAvailDataReq() { - struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); - outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2; - outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_SHORTREQ; - memcpy(txframe->src, mSelfMac, 8); - outBuffer[1] = 0x21; - outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet - txframe->seq = seq++; - txframe->dstPan = PROTO_PAN_ID; - txframe->dstAddr = 0xFFFF; - txframe->srcPan = PROTO_PAN_ID; - commsTxNoCpy(outBuffer); -} -static void sendAvailDataReq() { - struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1); - memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4); - struct AvailDataReq *availreq = (struct AvailDataReq *)(outBuffer + 2 + sizeof(struct MacFrameBcast)); - outBuffer[0] = sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 2; - outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_REQ; - memcpy(txframe->src, mSelfMac, 8); - txframe->fcs.frameType = 1; - txframe->fcs.ackReqd = 1; - txframe->fcs.destAddrType = 2; - txframe->fcs.srcAddrType = 3; - txframe->seq = seq++; - txframe->dstPan = PROTO_PAN_ID; - txframe->dstAddr = 0xFFFF; - txframe->srcPan = PROTO_PAN_ID; - // TODO: send some (more) meaningful data - availreq->hwType = 5; - availreq->wakeupReason = wakeUpReason; - availreq->lastPacketRSSI = mLastRSSI; - availreq->lastPacketLQI = mLastLqi; - availreq->temperature = temperature; - availreq->batteryMv = batteryVoltage; - availreq->capabilities = capabilities; - availreq->tagSoftwareVersion = FW_VERSION; - addCRC(availreq, sizeof(struct AvailDataReq)); - commsTxNoCpy(outBuffer); -} -struct AvailDataInfo *getAvailDataInfo() { - radioRxEnable(true); - uint32_t t; - for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { - sendAvailDataReq(); - t = timerGet() + (TIMER_TICKS_PER_MSEC * (DATA_REQ_RX_WINDOW_SIZE + 2)); - while (timerGet() < t) { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) { - if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) { - struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; - memcpy(APmac, f->src, 8); - APsrcPan = f->pan; - dataReqLastAttempt = c; - return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - } - } - } - } - } - dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; - return NULL; -} -struct AvailDataInfo *getShortAvailDataInfo() { - radioRxEnable(true); - uint32_t t; - for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { - sendShortAvailDataReq(); - // sendAvailDataReq(); - t = timerGet() + (TIMER_TICKS_PER_MSEC * 25); - while (timerGet() < t) { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO) { - if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo))) { - struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer; - memcpy(APmac, f->src, 8); - APsrcPan = f->pan; - dataReqLastAttempt = c; - printf("%d", dataReqLastAttempt); - return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - } - } - } - } - } - dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; - return NULL; -} -static bool processBlockPart(const struct blockPart *bp) { - uint16_t start = bp->blockPart * BLOCK_PART_DATA_SIZE; - uint16_t size = BLOCK_PART_DATA_SIZE; - // validate if it's okay to copy data - if (bp->blockId != curBlock.blockId) { - // printf("got a packet for block %02X\n", bp->blockId); - return false; - } - if (start >= (sizeof(blockXferBuffer) - 1)) - return false; - if (bp->blockPart > BLOCK_MAX_PARTS) - return false; - if ((start + size) > sizeof(blockXferBuffer)) { - size = sizeof(blockXferBuffer) - start; - } - if (checkCRC(bp, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE)) { - // copy block data to buffer - memcpy((void *)(blockXferBuffer + start), (const void *)bp->data, size); - // we don't need this block anymore, set bit to 0 so we don't request it again - curBlock.requestedParts[bp->blockPart / 8] &= ~(1 << (bp->blockPart % 8)); - return true; - } else { - return false; - } -} -static bool blockRxLoop(const uint32_t timeout) { - uint32_t t; - bool success = false; - radioRxEnable(true); - t = timerGet() + (TIMER_TICKS_PER_MSEC * (timeout + 20)); - while (timerGet() < t) { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - if (getPacketType(inBuffer) == PKT_BLOCK_PART) { - struct blockPart *bp = (struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - success = processBlockPart(bp); - } - } - } - radioRxEnable(false); - radioRxFlush(); - return success; -} -static struct blockRequestAck *continueToRX() { - struct blockRequestAck *ack = (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - ack->pleaseWaitMs = 0; - return ack; -} -static void sendBlockRequest() { - memset(outBuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2); - struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1); - struct blockRequest *blockreq = (struct blockRequest *)(outBuffer + 2 + sizeof(struct MacFrameNormal)); - outBuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2; - if (requestPartialBlock) { - ; - outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PARTIAL_REQUEST; - } else { - outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST; - } - memcpy(f->src, mSelfMac, 8); - memcpy(f->dst, APmac, 8); - f->fcs.frameType = 1; - f->fcs.secure = 0; - f->fcs.framePending = 0; - f->fcs.ackReqd = 0; - f->fcs.panIdCompressed = 1; - f->fcs.destAddrType = 3; - f->fcs.frameVer = 0; - f->fcs.srcAddrType = 3; - f->seq = seq++; - f->pan = APsrcPan; - memcpy(blockreq, &curBlock, sizeof(struct blockRequest)); - // printf("req ver: %02X%02X%02X%02X%02X%02X%02X%02X\n", ((uint8_t*)&blockreq->ver)[0],((uint8_t*)&blockreq->ver)[1],((uint8_t*)&blockreq->ver)[2],((uint8_t*)&blockreq->ver)[3],((uint8_t*)&blockreq->ver)[4],((uint8_t*)&blockreq->ver)[5],((uint8_t*)&blockreq->ver)[6],((uint8_t*)&blockreq->ver)[7]); - addCRC(blockreq, sizeof(struct blockRequest)); - commsTxNoCpy(outBuffer); -} -static struct blockRequestAck *performBlockRequest() { - uint32_t t; - radioRxEnable(true); - radioRxFlush(); - for (uint8_t c = 0; c < 30; c++) { - sendBlockRequest(); - t = timerGet() + (TIMER_TICKS_PER_MSEC * (7UL + c / 10)); - do { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - switch (getPacketType(inBuffer)) { - case PKT_BLOCK_REQUEST_ACK: - if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck))) - return (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - break; - case PKT_BLOCK_PART: - // block already started while we were waiting for a get block reply - // printf("!"); - // processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); - return continueToRX(); - break; - case PKT_CANCEL_XFER: - return NULL; - default: - printf("pkt w/type %02X\n", getPacketType(inBuffer)); - break; - } - } - - } while (timerGet() < t); - } - return continueToRX(); - // return NULL; -} -static void sendXferCompletePacket() { - memset(outBuffer, 0, sizeof(struct MacFrameNormal) + 2 + 4); - struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1); - outBuffer[0] = sizeof(struct MacFrameNormal) + 2 + 2; - outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE; - memcpy(f->src, mSelfMac, 8); - memcpy(f->dst, APmac, 8); - f->fcs.frameType = 1; - f->fcs.secure = 0; - f->fcs.framePending = 0; - f->fcs.ackReqd = 0; - f->fcs.panIdCompressed = 1; - f->fcs.destAddrType = 3; - f->fcs.frameVer = 0; - f->fcs.srcAddrType = 3; - f->pan = APsrcPan; - f->seq = seq++; - commsTxNoCpy(outBuffer); -} -static void sendXferComplete() { - radioRxEnable(true); - - for (uint8_t c = 0; c < 16; c++) { - sendXferCompletePacket(); - uint32_t start = timerGet(); - while ((timerGet() - start) < (TIMER_TICKS_PER_MSEC * 6UL)) { - int8_t ret = commsRxUnenc(inBuffer); - if (ret > 1) { - if (getPacketType(inBuffer) == PKT_XFER_COMPLETE_ACK) { - printf("XFC ACK\n"); - return; - } - } - } - } - printf("XFC NACK!\n"); - return; -} -static bool validateBlockData() { - struct blockData *bd = (struct blockData *)blockXferBuffer; - // printf("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum); - uint16_t t = 0; - for (uint16_t c = 0; c < bd->size; c++) { - t += bd->data[c]; - } - return bd->checksum == t; -} - -// EEprom related stuff -static bool validateEepromMD5(uint64_t ver, uint32_t eepromstart, uint32_t flen) { -#define CHUNK_SIZE 512 - uint8_t chunk[CHUNK_SIZE]; - MD5Context ctx; - md5Init(&ctx); - - // Open the executable itself for reading - for (uint32_t offset = 0; offset < flen; offset += CHUNK_SIZE) { - uint32_t len = flen - offset; - if (len > CHUNK_SIZE) len = CHUNK_SIZE; - FLASH_Read(FLASH_FAST_READ_QUAD_OUT, eepromstart + offset, chunk, len); - eepromRead(eepromstart + offset, chunk, 512); - md5Update(&ctx, chunk, len); - } - - // Retrieve the final hash - md5Finalize(&ctx); - - bool isValid = ver == *((uint64_t *)ctx.digest); - if (!isValid) { - printf("MD5 failed check! This is what we should get:\n"); - dump((const uint8_t *)&(xferDataInfo.dataVer), 8); - printf("This is what we got:\n"); - dump(ctx.digest, 16); - } - return isValid; -} -static uint32_t getAddressForSlot(const uint8_t s) { - return EEPROM_IMG_START + (EEPROM_IMG_EACH * s); -} -static void getNumSlots() { - printf("Checking slots\n"); - imgSlots = 1; - - /*uint32_t eeSize = eepromGetSize(); - uint16_t nSlots = (eeSize - EEPROM_IMG_START) / (EEPROM_IMG_EACH >> 8) >> 8; - if (eeSize < EEPROM_IMG_START || !nSlots) - { - printf("eeprom is too small\n"); - while (1) - ; - } - else if (nSlots >> 8) - { - printf("eeprom is too big, some will be unused\n"); - imgSlots = 254; - } - else - imgSlots = nSlots;*/ - printf("Got %i nr of slots\n", imgSlots); -} -static uint8_t findSlot(const uint8_t *ver) { - // return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere - uint32_t markerValid = EEPROM_IMG_VALID; - for (uint8_t c = 0; c < imgSlots; c++) { - struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer; - eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); - if (!memcmp(&eih->validMarker, &markerValid, 4)) { - if (!memcmp(&eih->version, (void *)ver, 8)) { - return c; - } - } - } - return 0xFF; -} -static void eraseUpdateBlock() { - qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN); -} -static void saveUpdateBlockData(uint8_t blockId) { - printf("EEPROM writing UpdateBlock %i\n", blockId); - if (!eepromWrite(EEPROM_UPDATE_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE)) - printf("EEPROM write failed\n"); -} -static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) { - printf("EEPROM writing Slot: %i ImageBlock %i\n", imgSlot, blockId); - uint32_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE)); - if (length > 4096) - length = 4096; - - if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length)) - printf("EEPROM write failed\n"); -} -void drawImageFromEeprom(const uint8_t imgSlot) { - drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut); - drawWithLut = 0; // default back to the regular ol' stock/OTP LUT -} -static uint32_t getHighSlotId() { - uint32_t temp = 0; - /*uint32_t markerValid = EEPROM_IMG_VALID; - for (uint8_t c = 0; c < imgSlots; c++) - { - struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer; - eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader)); - if (!memcmp(&eih->validMarker, &markerValid, 4)) - { - if (temp < eih->id) - { - temp = eih->id; - nextImgSlot = c; - } - } - }*/ - printf("found high id=%lu in slot %d\n", temp, nextImgSlot); - return temp; -} - - -static bool getDataBlock(const uint16_t blockSize) { - static uint8_t partsThisBlock = 0; - static uint8_t blockAttempts = 0; - blockAttempts = BLOCK_TRANSFER_ATTEMPTS; - if (blockSize == BLOCK_DATA_SIZE) { - partsThisBlock = BLOCK_MAX_PARTS; - memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES); - } else { - partsThisBlock = (sizeof(struct blockData) + blockSize) / BLOCK_PART_DATA_SIZE; - if (blockSize % BLOCK_PART_DATA_SIZE) - partsThisBlock++; - memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES); - for (uint8_t c = 0; c < partsThisBlock; c++) { - curBlock.requestedParts[c / 8] |= (1 << (c % 8)); - } - } - - requestPartialBlock = false; // this forces the AP to request the block data from the host - - while (blockAttempts--) { -#ifndef DEBUGBLOCKS - printf("REQ %d ", curBlock.blockId); -#else - printf("REQ %d[", curBlock.blockId); - for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) { - if ((c != 0) && (c % 8 == 0)) - printf("]["); - if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) { - printf("R"); - } else { - printf("_"); - } - } - printf("]\n"); -#endif - powerUp(INIT_RADIO); - struct blockRequestAck *ack = performBlockRequest(); - - if (ack == NULL) { - printf("Cancelled request\n"); - return false; - } - if (ack->pleaseWaitMs) { // SLEEP - until the AP is ready with the data - timerDelay(TIMER_TICKS_PER_MSEC * ack->pleaseWaitMs); - } else { - // immediately start with the reception of the block data - } - blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed - powerDown(INIT_RADIO); - -#ifdef DEBUGBLOCKS - printf("RX %d[", curBlock.blockId); - for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) { - if ((c != 0) && (c % 8 == 0)) - printf("]["); - if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) { - printf("."); - } else { - printf("R"); - } - } - printf("]\n"); -#endif - // check if we got all the parts we needed, e.g: has the block been completed? - bool blockComplete = true; - for (uint8_t c = 0; c < partsThisBlock; c++) { - if (curBlock.requestedParts[c / 8] & (1 << (c % 8))) - blockComplete = false; - } - - if (blockComplete) { -#ifndef DEBUGBLOCKS - printf("- COMPLETE\n"); -#endif - if (validateBlockData()) { - // block download complete, validated - return true; - } else { - for (uint8_t c = 0; c < partsThisBlock; c++) { - curBlock.requestedParts[c / 8] |= (1 << (c % 8)); - } - requestPartialBlock = false; - printf("blk failed validation!\n"); - } - } else { -#ifndef DEBUGBLOCKS - printf("- INCOMPLETE\n"); -#endif - // block incomplete, re-request a partial block - requestPartialBlock = true; - } - } - printf("failed getting block\n"); - return false; -} -uint16_t dataRequestSize = 0; -uint32_t curXferSize = 0; - -static bool downloadFWUpdate(const struct AvailDataInfo *avail) { - // 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. - } else { - // start, or restart the transfer from 0. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer - curBlock.blockId = 0; - memcpy(&(curBlock.ver), &(avail->dataVer), 8); - curBlock.type = avail->dataType; - memcpy(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - curXferSize = avail->dataSize; - eraseUpdateBlock(); - delay(100); - } - - while (xferDataInfo.dataSize) { - wdt10s(); - if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) { - // more than one block remaining - dataRequestSize = BLOCK_DATA_SIZE; - } else { - // only one block remains - dataRequestSize = xferDataInfo.dataSize; - } - if (getDataBlock(dataRequestSize)) { - // succesfully downloaded datablock, save to eeprom - powerUp(INIT_EEPROM); - saveUpdateBlockData(curBlock.blockId); - powerDown(INIT_EEPROM); - curBlock.blockId++; - xferDataInfo.dataSize -= dataRequestSize; - } else { - // failed to get the block we wanted, we'll stop for now, maybe resume later - return false; - } - } - // no more data, download complete - if (validateEepromMD5(xferDataInfo.dataVer, EEPROM_UPDATE_START, curXferSize)) { - // md5 matches - return true; - } else { - // md5 does not match, invalidate current transfer result, forcing a restart of the transfer - memset((void *)&xferDataInfo, 0, sizeof(struct AvailDataInfo)); - return false; - } -} - -uint16_t imageSize = 0; -static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) { - // 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. - printf("restarting image download"); - curImgSlot = nextImgSlot; - } else { - // go to the next image slot - nextImgSlot++; - if (nextImgSlot >= imgSlots) - nextImgSlot = 0; - curImgSlot = nextImgSlot; - printf("Saving to image slot %d\n", curImgSlot); - drawWithLut = avail->dataTypeArgument; - powerUp(INIT_EEPROM); - uint8_t attempt = 5; - while (attempt--) { - if (eepromErase(getAddressForSlot(curImgSlot), (uint16_t)EEPROM_IMG_EACH)) - goto eraseSuccess; - } - NVIC_SystemReset(); - eraseSuccess: - printf("new download, writing to slot %d\n", curImgSlot); - - // start, or restart the transfer. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer - curBlock.blockId = 0; - memcpy(&(curBlock.ver), &(avail->dataVer), 8); - curBlock.type = avail->dataType; - - memcpy(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - - imageSize = xferDataInfo.dataSize; - } - - while (xferDataInfo.dataSize) { - wdt10s(); - if (xferDataInfo.dataSize > BLOCK_DATA_SIZE) { - // more than one block remaining - dataRequestSize = BLOCK_DATA_SIZE; - } else { - // only one block remains - dataRequestSize = xferDataInfo.dataSize; - } - if (getDataBlock(dataRequestSize)) { - // succesfully downloaded datablock, save to eeprom - powerUp(INIT_EEPROM); -#ifdef DEBUGBLOCKS - printf("Saving block %d to slot %d\n", curBlock.blockId, curImgSlot); -#endif - saveImgBlockData(curImgSlot, curBlock.blockId); - powerDown(INIT_EEPROM); - curBlock.blockId++; - xferDataInfo.dataSize -= dataRequestSize; - } else { - // failed to get the block we wanted, we'll stop for now, probably resume later - return false; - } - } - // no more data, download complete - - // borrow the blockXferBuffer temporarily - struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer; - memcpy(&eih->version, &xferDataInfo.dataVer, 8); - eih->validMarker = EEPROM_IMG_VALID; - eih->id = ++curHighSlotId; - eih->size = imageSize; - eih->dataType = xferDataInfo.dataType; - -#ifdef DEBUGBLOCKS - printf("Now writing datatype 0x%02X to slot %d\n", curDataInfo.dataType, curImgSlot); -#endif - if (validateEepromMD5(xferDataInfo.dataVer, getAddressForSlot(curImgSlot) + sizeof(struct EepromImageHeader), imageSize)) { - // md5 matches - eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader)); - powerDown(INIT_EEPROM); - printf("md5 okay"); - return true; - } else { - // md5 does not match, invalidate current transfer result, forcing a restart of the transfer - memset((void *)&xferDataInfo, 0, sizeof(struct AvailDataInfo)); - powerDown(INIT_EEPROM); - return false; - } -} - -bool processAvailDataInfo(struct AvailDataInfo *avail) { - switch (avail->dataType) { - case DATATYPE_IMG_BMP: - case DATATYPE_IMG_DIFF: - case DATATYPE_IMG_RAW_1BPP: - case DATATYPE_IMG_RAW_2BPP: - case DATATYPE_IMG_ZLIB: - // check if this download is currently displayed or active - if (xferDataInfo.dataSize == 0 && !memcmp((const void *)&avail->dataVer, (const void *)&xferDataInfo.dataVer, 8)) { - // we've downloaded this already, we're guessing it's already displayed - printf("currently shown image, send xfc\n"); - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - return true; - } - - // check if we've seen this version before - powerUp(INIT_EEPROM); - curImgSlot = findSlot((uint8_t *)&(avail->dataVer)); - powerDown(INIT_EEPROM); - if (curImgSlot != 0xFF) { - // found a (complete)valid image slot for this version - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - - printf("already seen, drawing from eeprom slot %d\n", curImgSlot); - - // mark as completed and draw from EEPROM - memcpy(&xferDataInfo, (void *)avail, sizeof(struct AvailDataInfo)); - xferDataInfo.dataSize = 0; // mark as transfer not pending - - drawWithLut = avail->dataTypeArgument; - wdt60s(); - powerUp(INIT_EPD | INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EPD | INIT_EEPROM); - return true; - } else { - // not found in cache, prepare to download - printf("downloading to imgslot\n"); - drawWithLut = avail->dataTypeArgument; - powerUp(INIT_EEPROM); - if (downloadImageDataToEEPROM(avail)) { - printf("download complete!\n"); - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - - wdt60s(); - powerUp(INIT_EPD | INIT_EEPROM); - drawImageFromEeprom(curImgSlot); - powerDown(INIT_EPD | INIT_EEPROM); - return true; - } else { - powerDown(INIT_EEPROM); - return false; - } - } - break; - case DATATYPE_FW_UPDATE: - powerUp(INIT_EEPROM); - if (downloadFWUpdate(avail)) { - printf("firmware download complete, doing update.\n"); - - powerUp(INIT_EPD); - // uiPrvFullscreenMsg("Updating", NULL, NULL); - - powerUp(INIT_RADIO); - sendXferComplete(); - powerDown(INIT_RADIO); - - powerUp(INIT_EEPROM); - wdt60s(); - applyUpdate(); - } else { - return false; - } - break; - case DATATYPE_NFC_URL_DIRECT: - case DATATYPE_NFC_RAW_CONTENT: { - return false; - break; - } - case DATATYPE_CUSTOM_LUT_OTA: - return false; - break; - } - return true; -} - -void initializeProto() { - getNumSlots(); - curHighSlotId = getHighSlotId(); -} diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h deleted file mode 100644 index d1532d33..00000000 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/syncedproto.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -#include "settings.h" - -extern __attribute__((section(".aonshadow"))) uint8_t mSelfMac[]; -extern __attribute__((section(".aonshadow"))) volatile uint8_t currentChannel; -extern __attribute__((section(".aonshadow"))) struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send -extern __attribute__((section(".aonshadow"))) struct AvailDataInfo xferDataInfo; // last 'AvailDataInfo' we received from the AP // __attribute__((section(".aon"))) - - -extern uint8_t APmac[]; - -extern __attribute__((section(".aonshadow"))) uint8_t curImgSlot; - -extern void setupRadio(void); -extern void killRadio(void); - -extern struct AvailDataInfo *getAvailDataInfo(); -extern struct AvailDataInfo *getShortAvailDataInfo(); -extern void drawImageFromEeprom(const uint8_t imgSlot); -extern bool processAvailDataInfo(struct AvailDataInfo *avail); -extern void initializeProto(); -extern uint8_t detectAP(const uint8_t channel); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/tagprofile_struct.h b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/tagprofile_struct.h new file mode 100644 index 00000000..6703b985 --- /dev/null +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/tagprofile_struct.h @@ -0,0 +1,11 @@ +struct tagHardwareProfile { + uint8_t macAddress[8]; + uint16_t xRes; + uint16_t yRes; + uint8_t bpp; + uint8_t controllerType; + uint8_t OEPLType; + uint32_t RC32Mcal; + uint32_t RC32Kcal; + uint8_t reserved[8]; +} __attribute__((packed)); diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/uc8159-var-m2.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/uc8159-var-m2.cpp index 3e6e422a..8f7e2087 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/uc8159-var-m2.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/uc8159-var-m2.cpp @@ -120,7 +120,9 @@ struct __attribute__((packed)) epd_xonlut { }; void uc8159::epdSetup() { +#ifdef DEBUG_EPD printf("EPD: Init begin\n"); +#endif initEPDGPIO(); this->epdReset(); epdWrite(EPD_POWER_ON, 0); @@ -149,10 +151,11 @@ void uc8159::epdSetup() { this->loadFrameRatePLL(EPDtempBracket); this->loadTempVCOMDC(EPDtempBracket); - // this->loadTempVSH(EPDtempBracket); - // epdWrite(EPD_POWER_SETTING, 4, 0x37, 0x00, this->vshc, this->vslc); // this doesn't work - +// this->loadTempVSH(EPDtempBracket); +// epdWrite(EPD_POWER_SETTING, 4, 0x37, 0x00, this->vshc, this->vslc); // this doesn't work +#ifdef DEBUG_EPD printf("EPD: Init complete\n"); +#endif } void uc8159::selectLUT(uint8_t lut) { @@ -183,7 +186,9 @@ uint8_t uc8159::getTempBracket() { break; } } +#ifdef DEBUG_EPD printf("EPD: Temp bracket = %d\n", bracket); +#endif return bracket; } void uc8159::loadFrameRatePLL(uint8_t bracket) { @@ -193,8 +198,10 @@ void uc8159::loadFrameRatePLL(uint8_t bracket) { eepromReadBlock(0, 25039, plltable, 10); epdWrite(EPD_SPI_FLASH_CONTROL, 1, 0x00); pllvalue = plltable[bracket]; +#ifdef DEBUG_EPD printf("loading pll value 0x%02X\n", pllvalue); - pllvalue = 0x3A; // was 0x3C +#endif + // pllvalue = 0x3A; // was 0x3C epdWrite(EPD_PLL_CONTROL, 1, pllvalue); } void uc8159::loadTempVCOMDC(uint8_t bracket) { @@ -269,6 +276,7 @@ void xonLutSkip(struct epd_xonlut *colorlut, uint8_t skip) { } void uc8159::loadLUTSfromEEPROM(uint8_t bracket, bool doRed) { + doRed = false; for (uint8_t c = EPD_LUT_B; c <= EPD_LUT_R3; c++) { struct epd_colorlut *colorlut = (struct epd_colorlut *)loadLUT(c, bracket); @@ -277,9 +285,10 @@ void uc8159::loadLUTSfromEEPROM(uint8_t bracket, bool doRed) { colorlut->part[0].repeat = 1; colorLutSkip(colorlut, 2); if (!doRed) { - colorLutSkip(colorlut, 3); - colorLutSkip(colorlut, 3); - colorLutSkip(colorlut, 3); + colorLutSkip(colorlut, 2); + colorLutSkip(colorlut, 2); + colorLutSkip(colorlut, 2); + colorLutSkip(colorlut, 2); } // colorLutSkip(colorlut, 3); @@ -295,9 +304,10 @@ void uc8159::loadLUTSfromEEPROM(uint8_t bracket, bool doRed) { vcomLutSkip(vcomlut, 2); if (!doRed) { - vcomLutSkip(vcomlut, 3); - vcomLutSkip(vcomlut, 3); - vcomLutSkip(vcomlut, 3); + vcomLutSkip(vcomlut, 2); + vcomLutSkip(vcomlut, 2); + vcomLutSkip(vcomlut, 2); + vcomLutSkip(vcomlut, 2); } epdBlockWrite(EPD_LUT_VCOM, (uint8_t *)vcomlut, 220); if (vcomlut) free(vcomlut); @@ -309,16 +319,19 @@ void uc8159::loadLUTSfromEEPROM(uint8_t bracket, bool doRed) { xonlut->part[0].repeat = 1; xonLutSkip(xonlut, 2); if (!doRed) { - xonLutSkip(xonlut, 3); - xonLutSkip(xonlut, 3); - xonLutSkip(xonlut, 3); + xonLutSkip(xonlut, 2); + xonLutSkip(xonlut, 2); + xonLutSkip(xonlut, 2); + xonLutSkip(xonlut, 2); } epdBlockWrite(EPD_LUT_XON, (uint8_t *)xonlut, 200); if (xonlut) free(xonlut); } void uc8159::epdReset() { uint8_t v0 = 5; +#ifdef DEBUG_EPD printf("EPD: Reset... "); +#endif while (1) { GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH); delay(100); @@ -335,7 +348,9 @@ void uc8159::epdReset() { } } delay(5000); +#ifdef DEBUG_EPD printf("complete.\n"); +#endif } void uc8159::eepromReadBlock(char a1, uint16_t readaddress, uint8_t *target, uint16_t length) { @@ -406,6 +421,7 @@ void uc8159::epdWriteDisplayData() { enableHardSPI(true); GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW); for (uint16_t curY = 0; curY < this->effectiveYRes; curY += blocksize) { // + wdt10s(); memset(screenrow_bw, 0, byteWidth * blocksize); memset(screenrow_r, 0, byteWidth * blocksize); @@ -413,7 +429,11 @@ void uc8159::epdWriteDisplayData() { drawItem::renderDrawLine(screenrow_bw + (byteWidth * bcount), curY + bcount, 0); } for (uint8_t bcount = 0; bcount < blocksize; bcount++) { - drawItem::renderDrawLine(screenrow_r + (byteWidth * bcount), curY + bcount, 1); + if (this->bpp == 1) { + drawItem::renderDrawLine(screenrow_bw + (byteWidth * bcount), curY + bcount, 1); + } else { + drawItem::renderDrawLine(screenrow_r + (byteWidth * bcount), curY + bcount, 1); + } } for (uint8_t bcount = 0; bcount < blocksize; bcount++) { @@ -435,9 +455,9 @@ void uc8159::draw() { } void uc8159::drawNoWait() { - wdt60s(); epdWriteDisplayData(); if (drawLut) { + // epdWrite(EPD_PLL_CONTROL, 1, 0x3A); // scan the gates a little faster epdWrite(EPD_PANEL_SETTING, 2, 0xC3, 0x88); // 0xC3-0x88 // lut from register bool doReds = true; if (drawLut == 2) doReds = false; @@ -448,15 +468,21 @@ void uc8159::drawNoWait() { busyWaitUntil(EPD_IS_BUSY, 10); busyWaitUntil(!EPD_IS_BUSY, 100); } +#ifdef DEBUG_EPD printf("EPD: Draw start\n"); +#endif + wdt10s(); epdWrite(EPD_REFRESH, 0); busyWaitUntil(EPD_IS_BUSY, 10); } void uc8159::epdWaitRdy() { - // do_sleeped_epd_refresh(); - busyWaitUntil(!EPD_IS_BUSY, 300000); + delay(15000); + do_sleeped_epd_refresh(); + // busyWaitUntil(!EPD_IS_BUSY, 300000); +#ifdef DEBUG_EPD printf("EPD: Draw done!\n"); +#endif } void uc8159::epdEnterSleep() { diff --git a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.cpp b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.cpp index 4141b1a4..b382dad5 100644 --- a/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.cpp +++ b/ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.cpp @@ -12,7 +12,7 @@ #include "proto.h" #include "screen.h" #include "settings.h" -#include "syncedproto.h" // for APmac / Channel +#include "oepl-protocol.h" // for APmac / Channel #include "mz100/timer.h" #include "drawing.h" @@ -28,12 +28,17 @@ bool __attribute__((section(".aonshadow"))) noAPShown = false; void addOverlay() { if ((currentChannel == 0) && (tagSettings.enableNoRFSymbol)) { // drawImg(0, 3, norf); + drawMask((epd->Xres - 48) - 5, 8, 48, 42, COLOR_BLACK); + drawMask((epd->Xres - 48) - 5, 8, 48, 42, COLOR_RED); + addCompressedFSImage((epd->Xres - 48) - 5, 8, rotation::ROTATE_0, (char *)"norf.bin.z"); noAPShown = true; } else { noAPShown = false; } if ((batteryVoltage < tagSettings.batLowVoltage) && (tagSettings.enableLowBatSymbol)) { - // drawImg(0, 366, batlow); + drawMask((epd->Xres - 48) - 5, (epd->Yres - 26) - 7, 48, 26, COLOR_BLACK); + drawMask((epd->Xres - 48) - 5, (epd->Yres - 26) - 7, 48, 26, COLOR_RED); + addCompressedFSImage((epd->Xres - 48) - 5, (epd->Yres - 26) - 7, rotation::ROTATE_0, (char *)"lowbat.bin.z"); lowBatteryShown = true; } else { lowBatteryShown = false; @@ -63,16 +68,14 @@ void afterFlashScreenSaver() { void showSplashScreen() { fs->init(); epdSetup(); - // addCompressedFSImage(300, 80,rotation::ROTATE_0, (char *)"img_tbird.bin.z"); - - // addCompressedFSImage(228, 24, rotation::ROTATE_0, (char *)"img/sadpanda.z"); - // addCompressedFSImage(0, 0, rotation::ROTATE_0, (char *)"forecast75.raw.z"); - + addCompressedFSImage((640 - 365) - 20, (384 - 237) / 2, rotation::ROTATE_0, (char *)"tbird2.bin.z"); fontrender fr((char *)"font/FreeSansBold24pt7b"); fr.epdPrintf(5, 5, 0, rotation::ROTATE_0, (char *)"OpenEPaperLink"); fr.setFont((char *)"font/FreeSansBold18pt7b"); fr.epdPrintf(20, 70, 1, rotation::ROTATE_0, "M2 7.5\""); 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]); + selectLUT(1); draw(); epdEnterSleep(); @@ -80,12 +83,14 @@ void showSplashScreen() { void showApplyUpdate() { epdSetup(); - fontrender fr((char *)"font/FreeSansBold24pt7b"); - fr.epdPrintf(5, 5, 0, rotation::ROTATE_0, (char *)"Updating..."); - fr.setFont((char *)"font/FreeSansBold18pt7b"); - fr.epdPrintf(40, 160, 1, rotation::ROTATE_0, "This shouldn't take too long!"); - // epdPrintf(90, 170, 1, "Performing update... This shouldn't take too long!"); + fs->init(); + fontrender fr((char *)"font/FreeSansBold24pt7b"); + fr.epdPrintf(5, 5, 0, rotation::ROTATE_0, (char *)"Updating......"); + fr.setFont((char *)"font/FreeSansBold18pt7b"); + fr.epdPrintf(40, 140, 1, rotation::ROTATE_0, "This shouldn't take too long!"); + // epdPrintf(90, 170, 1, "Performing update... This shouldn't take too long!"); + addCompressedFSImage((640 - 551) / 2, 384 - 198, rotation::ROTATE_0, (char *)"jet.bin.z"); addOverlay(); drawNoWait(); } @@ -93,6 +98,9 @@ void showApplyUpdate() { void showAPFound() { fs->init(); epdSetup(); + + // addCompressedFSImage(228, 24, rotation::ROTATE_0, (char *)"img/sadpanda.z"); + fontrender fr((char *)"font/FreeSansBold24pt7b"); fr.epdPrintf(5, 5, 0, rotation::ROTATE_0, (char *)"OpenEPaperLink"); fr.setFont((char *)"font/FreeSansBold18pt7b"); @@ -100,25 +108,32 @@ void showAPFound() { fr.epdPrintf(20, 110, 0, rotation::ROTATE_0, "AP MAC: %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, 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]); - selectLUT(1); + addOverlay(); + if (lowBatteryShown) { + selectLUT(0); + } else { + selectLUT(1); + } draw(); epdEnterSleep(); } void showNoAP() { fs->init(); - epdSetup(); - addCompressedFSImage(228, 24, rotation::ROTATE_0, (char *)"img/sadpanda.z"); - // addCompressedFSImage(0, 0, rotation::ROTATE_0, (char *)"forecast75.raw.z"); - + selectLUT(0); + addCompressedFSImage(640 - 415, 384 - 198, rotation::ROTATE_0, (char *)"sadpanda.bin.z"); fontrender fr((char *)"font/FreeSansBold24pt7b"); fr.epdPrintf(5, 5, 0, rotation::ROTATE_0, (char *)"No AP Found!"); fr.setFont((char *)"font/FreeSansBold18pt7b"); - fr.epdPrintf(20, 70, 1, rotation::ROTATE_0, "We'll try again later\""); + fr.epdPrintf(20, 70, 0, rotation::ROTATE_0, "We'll try again later"); // epdPrintf(10, 10, 1, "OpenEPaperLink "); // epdPrintf(10, 40, 1, "No AP found... We'll try again in a little while though!"); - // epdPrintf(10, 350, 1, "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]); + + drawMask(10, 360, 300, 16, COLOR_BLACK); + drawMask(10, 360, 300, 16, COLOR_RED); + fr.setFont((char *)"font/FreeSans9pt7b"); + fr.epdPrintf(10, 360, 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]); addOverlay(); draw(); epdEnterSleep();