From 7bd0c8c8156a41f0547cdbeff5e1eb435b82096c Mon Sep 17 00:00:00 2001 From: jjwbruijn Date: Tue, 28 Mar 2023 00:09:01 +0200 Subject: [PATCH] even moar symlinks --- binaries/Tag_FW_1.54.bin | Bin 57431 -> 57431 bytes binaries/Tag_FW_2.9-uc8151.bin | Bin 56030 -> 56030 bytes binaries/Tag_FW_2.9.bin | Bin 57393 -> 57393 bytes binaries/Tag_FW_4.2.bin | Bin 57407 -> 57407 bytes ...{zigbeebase000F.bin => zigbeebase000E.bin} | Bin zbs243_AP_FW/ap_fw.bin | Bin 16180 -> 0 bytes zbs243_Tag_FW/asmUtil.h | 115 +- zbs243_Tag_FW/barcode.c | 102 +- zbs243_Tag_FW/barcode.h | 30 +- zbs243_Tag_FW/bitmaps.h | 299 +--- zbs243_Tag_FW/board | 1 + zbs243_Tag_FW/board/boardCommon.h | 52 - zbs243_Tag_FW/board/boardZBS29common.c | 160 -- zbs243_Tag_FW/board/ssd1619.c | 817 --------- zbs243_Tag_FW/board/ssd1619.h | 76 - zbs243_Tag_FW/board/uc8151.c | 787 --------- zbs243_Tag_FW/board/uc8151.h | 74 - zbs243_Tag_FW/board/zbs154v033/board.c | 1 - zbs243_Tag_FW/board/zbs154v033/board.h | 28 - zbs243_Tag_FW/board/zbs154v033/make.mk | 7 - zbs243_Tag_FW/board/zbs154v033/screen.c | 1 - zbs243_Tag_FW/board/zbs154v033/screen.h | 26 - zbs243_Tag_FW/board/zbs29_uc8151/board.c | 1 - zbs243_Tag_FW/board/zbs29_uc8151/board.h | 28 - zbs243_Tag_FW/board/zbs29_uc8151/make.mk | 7 - zbs243_Tag_FW/board/zbs29_uc8151/screen.c | 1 - zbs243_Tag_FW/board/zbs29_uc8151/screen.h | 25 - zbs243_Tag_FW/board/zbs29v033/board.c | 1 - zbs243_Tag_FW/board/zbs29v033/board.h | 28 - zbs243_Tag_FW/board/zbs29v033/make.mk | 7 - zbs243_Tag_FW/board/zbs29v033/screen.c | 1 - zbs243_Tag_FW/board/zbs29v033/screen.h | 26 - zbs243_Tag_FW/board/zbs42v033/board.c | 1 - zbs243_Tag_FW/board/zbs42v033/board.h | 28 - zbs243_Tag_FW/board/zbs42v033/make.mk | 7 - zbs243_Tag_FW/board/zbs42v033/screen.c | 1 - zbs243_Tag_FW/board/zbs42v033/screen.h | 27 - zbs243_Tag_FW/buildfw.sh | 0 zbs243_Tag_FW/cpu | 1 + zbs243_Tag_FW/cpu/8051/asmUtil.c | 1502 ----------------- zbs243_Tag_FW/cpu/8051/cpu.c | 1 - zbs243_Tag_FW/cpu/8051/cpu.h | 18 - zbs243_Tag_FW/cpu/8051/make.mk | 9 - zbs243_Tag_FW/cpu/8051/peep.def | 115 -- zbs243_Tag_FW/cpu/8051/printf.c | 799 --------- zbs243_Tag_FW/cpu/8051/random.c | 261 --- zbs243_Tag_FW/eeprom.c | 325 +--- zbs243_Tag_FW/eeprom.h | 52 +- zbs243_Tag_FW/font.h | 259 +-- zbs243_Tag_FW/fw154.bin | Bin 57438 -> 0 bytes zbs243_Tag_FW/fw29-uc8151.bin | Bin 56030 -> 0 bytes zbs243_Tag_FW/fw29.bin | Bin 57393 -> 0 bytes zbs243_Tag_FW/fw42.bin | Bin 57407 -> 0 bytes zbs243_Tag_FW/lut.h | 55 +- zbs243_Tag_FW/printf.h | 31 +- zbs243_Tag_FW/proto.h | 189 +-- zbs243_Tag_FW/sleep.h | 11 +- zbs243_Tag_FW/soc | 1 + zbs243_Tag_FW/soc/radioCommon.h | 55 - zbs243_Tag_FW/soc/zbs243/.uart.asm.swp | Bin 1024 -> 0 bytes zbs243_Tag_FW/soc/zbs243/flash.c | 182 -- zbs243_Tag_FW/soc/zbs243/flash.h | 23 - zbs243_Tag_FW/soc/zbs243/i2c.c | 126 -- zbs243_Tag_FW/soc/zbs243/i2c.h | 34 - zbs243_Tag_FW/soc/zbs243/make.mk | 8 - zbs243_Tag_FW/soc/zbs243/radio.c | 336 ---- zbs243_Tag_FW/soc/zbs243/radio.h | 22 - zbs243_Tag_FW/soc/zbs243/sleep.c | 66 - zbs243_Tag_FW/soc/zbs243/soc.c | 12 - zbs243_Tag_FW/soc/zbs243/soc.h | 30 - zbs243_Tag_FW/soc/zbs243/spi.c | 42 - zbs243_Tag_FW/soc/zbs243/spi.h | 19 - zbs243_Tag_FW/soc/zbs243/temperature.c | 112 -- zbs243_Tag_FW/soc/zbs243/timer.c | 65 - zbs243_Tag_FW/soc/zbs243/timer.h | 24 - zbs243_Tag_FW/soc/zbs243/uart.c | 102 -- zbs243_Tag_FW/soc/zbs243/uart.h | 27 - zbs243_Tag_FW/soc/zbs243/wdt.c | 59 - zbs243_Tag_FW/soc/zbs243/zbs243.h | 289 ---- zbs243_Tag_FW/wdt.h | 48 +- 80 files changed, 15 insertions(+), 8060 deletions(-) rename binaries/{zigbeebase000F.bin => zigbeebase000E.bin} (100%) delete mode 100644 zbs243_AP_FW/ap_fw.bin mode change 100644 => 120000 zbs243_Tag_FW/asmUtil.h mode change 100644 => 120000 zbs243_Tag_FW/barcode.c mode change 100644 => 120000 zbs243_Tag_FW/barcode.h mode change 100644 => 120000 zbs243_Tag_FW/bitmaps.h create mode 120000 zbs243_Tag_FW/board delete mode 100644 zbs243_Tag_FW/board/boardCommon.h delete mode 100644 zbs243_Tag_FW/board/boardZBS29common.c delete mode 100644 zbs243_Tag_FW/board/ssd1619.c delete mode 100644 zbs243_Tag_FW/board/ssd1619.h delete mode 100644 zbs243_Tag_FW/board/uc8151.c delete mode 100644 zbs243_Tag_FW/board/uc8151.h delete mode 100644 zbs243_Tag_FW/board/zbs154v033/board.c delete mode 100644 zbs243_Tag_FW/board/zbs154v033/board.h delete mode 100644 zbs243_Tag_FW/board/zbs154v033/make.mk delete mode 100644 zbs243_Tag_FW/board/zbs154v033/screen.c delete mode 100644 zbs243_Tag_FW/board/zbs154v033/screen.h delete mode 100644 zbs243_Tag_FW/board/zbs29_uc8151/board.c delete mode 100644 zbs243_Tag_FW/board/zbs29_uc8151/board.h delete mode 100644 zbs243_Tag_FW/board/zbs29_uc8151/make.mk delete mode 100644 zbs243_Tag_FW/board/zbs29_uc8151/screen.c delete mode 100644 zbs243_Tag_FW/board/zbs29_uc8151/screen.h delete mode 100644 zbs243_Tag_FW/board/zbs29v033/board.c delete mode 100644 zbs243_Tag_FW/board/zbs29v033/board.h delete mode 100644 zbs243_Tag_FW/board/zbs29v033/make.mk delete mode 100644 zbs243_Tag_FW/board/zbs29v033/screen.c delete mode 100644 zbs243_Tag_FW/board/zbs29v033/screen.h delete mode 100644 zbs243_Tag_FW/board/zbs42v033/board.c delete mode 100644 zbs243_Tag_FW/board/zbs42v033/board.h delete mode 100644 zbs243_Tag_FW/board/zbs42v033/make.mk delete mode 100644 zbs243_Tag_FW/board/zbs42v033/screen.c delete mode 100644 zbs243_Tag_FW/board/zbs42v033/screen.h mode change 100644 => 100755 zbs243_Tag_FW/buildfw.sh create mode 120000 zbs243_Tag_FW/cpu delete mode 100644 zbs243_Tag_FW/cpu/8051/asmUtil.c delete mode 100644 zbs243_Tag_FW/cpu/8051/cpu.c delete mode 100644 zbs243_Tag_FW/cpu/8051/cpu.h delete mode 100644 zbs243_Tag_FW/cpu/8051/make.mk delete mode 100644 zbs243_Tag_FW/cpu/8051/peep.def delete mode 100644 zbs243_Tag_FW/cpu/8051/printf.c delete mode 100644 zbs243_Tag_FW/cpu/8051/random.c mode change 100644 => 120000 zbs243_Tag_FW/eeprom.c mode change 100644 => 120000 zbs243_Tag_FW/eeprom.h mode change 100644 => 120000 zbs243_Tag_FW/font.h delete mode 100644 zbs243_Tag_FW/fw154.bin delete mode 100644 zbs243_Tag_FW/fw29-uc8151.bin delete mode 100644 zbs243_Tag_FW/fw29.bin delete mode 100644 zbs243_Tag_FW/fw42.bin mode change 100644 => 120000 zbs243_Tag_FW/lut.h mode change 100644 => 120000 zbs243_Tag_FW/printf.h mode change 100644 => 120000 zbs243_Tag_FW/proto.h mode change 100644 => 120000 zbs243_Tag_FW/sleep.h create mode 120000 zbs243_Tag_FW/soc delete mode 100644 zbs243_Tag_FW/soc/radioCommon.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/.uart.asm.swp delete mode 100644 zbs243_Tag_FW/soc/zbs243/flash.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/flash.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/i2c.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/i2c.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/make.mk delete mode 100644 zbs243_Tag_FW/soc/zbs243/radio.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/radio.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/sleep.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/soc.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/soc.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/spi.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/spi.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/temperature.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/timer.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/timer.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/uart.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/uart.h delete mode 100644 zbs243_Tag_FW/soc/zbs243/wdt.c delete mode 100644 zbs243_Tag_FW/soc/zbs243/zbs243.h mode change 100644 => 120000 zbs243_Tag_FW/wdt.h diff --git a/binaries/Tag_FW_1.54.bin b/binaries/Tag_FW_1.54.bin index 97603658a6dd9886f9d3546e686f8f5367faa9c7..7a43a5049bb4aa6682fad6fa05d97875c5384124 100644 GIT binary patch delta 19 bcmcb9fcg3X<_$^#ER)_(;oPhiU^oE)TZ#x{ delta 19 bcmcb9fcg3X<_$^#EE?~paBWr#Fq{AYSJnsm diff --git a/binaries/Tag_FW_2.9-uc8151.bin b/binaries/Tag_FW_2.9-uc8151.bin index 081fe4fa7f6a6860775af6dd7758c25630d6ea27..5912d8616d8c8a69c5a217bf0053e02ca91c1d50 100644 GIT binary patch delta 19 bcmcb&mHFOQ<_(+tSth-o!nt{yzeYCzWA6!T delta 19 bcmcb&mHFOQ<_(+tSv1~H;o7{-U!xlUU^@u{ diff --git a/binaries/Tag_FW_2.9.bin b/binaries/Tag_FW_2.9.bin index b8331b58d86360f13cdfdb37c0a9dc81678d516e..f64f1a36eee073bec74052829583ae542e06cb38 100644 GIT binary patch delta 19 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 -#include "cpu.h" - - - -//SDCC may have uint64_t support, but it is so shitty, we're better off not using it -//sdcc is brain dead when compiling multiplication, so we write our own asm code to make it better...le sigh... -//SDCC also has issues managing xdata memory ops, we write our own - -#pragma callee_saves u64_copy -#pragma callee_saves u64_isLt -#pragma callee_saves u64_isEq -#pragma callee_saves u64_sub -#pragma callee_saves u64_add -#pragma callee_saves u64_inc -#pragma callee_saves u64_dec - -#pragma callee_saves xMemSet -#pragma callee_saves xMemEqual -#pragma callee_saves xMemEqual4 -#pragma callee_saves xMemCopy -#pragma callee_saves xMemCopyShort -#pragma callee_saves xMemCopy8 -#pragma callee_saves xStrLen - -#pragma callee_saves rngGen - -#pragma callee_saves mathPrvMul8x8 -#pragma callee_saves mathPrvMul16x8 -#pragma callee_saves mathPrvMul16x16 -#pragma callee_saves mathPrvMul32x8 -#pragma callee_saves mathPrvDiv32x8 -#pragma callee_saves mathPrvDiv32x16 -#pragma callee_saves mathPrvMod32x16 -#pragma callee_saves mathPrvDiv16x8 -#pragma callee_saves mathPrvMod16x8 -#pragma callee_saves mathPrvCopyPostinc - -#pragma callee_saves mathPrvI16Asr1 - -#pragma callee_saves mathPrvU8bitswap - -#pragma callee_saves charsPrvDerefAndIncGenericPtr //return *(*generic_charPtr)++ - - -//it saddens me that i need these....but i do -#pragma callee_saves mathPrvU16from2xU8 -#pragma callee_saves mathPrvU32from4xU8 -#pragma callee_saves u32minusU16 -#pragma callee_saves u32plusU16 -#pragma callee_saves u32Nonzero -#pragma callee_saves i32Negative - - -__bit u32minusU16(uint32_t __xdata *u32, uint16_t u16) __reentrant; //sets carry -__bit u32plusU16(uint32_t __xdata *u32, uint16_t u16) __reentrant; //sets carry -uint8_t u32Nonzero(uint32_t __xdata *u32) __reentrant; -__bit i32Negative(uint32_t __xdata *u32) __reentrant; - - -void u64_copy(uint64_t __xdata *dst, const uint64_t __xdata *src) __reentrant; -void u64_copyFromCode(uint64_t __xdata *dst, const uint64_t __code *src) __reentrant; -__bit u64_isLt(const uint64_t __xdata *lhs, const uint64_t __xdata *rhs) __reentrant; -__bit u64_isEq(const uint64_t __xdata *lhs, const uint64_t __xdata *rhs) __reentrant; -void u64_sub(uint64_t __xdata *lhs, const uint64_t __xdata *rhs) __reentrant; -void u64_add(uint64_t __xdata *lhs, const uint64_t __xdata *rhs) __reentrant; -void u64_and(uint64_t __xdata *lhs, const uint64_t __xdata *rhs) __reentrant; -void u64_inc(uint64_t __xdata *dst) __reentrant; -void u64_dec(uint64_t __xdata *dst) __reentrant; - -#define U64FMT "%04x%04x%04x%04x" -#define U64CVT(v) ((uint16_t __xdata*)&v)[3], ((uint16_t __xdata*)&v)[2], ((uint16_t __xdata*)&v)[1], ((uint16_t __xdata*)&v)[0] - -int16_t mathPrvI16Asr1(int16_t val) __reentrant; - -uint16_t mathPrvMul8x8(uint8_t a, uint8_t b) __reentrant; -uint32_t mathPrvMul16x8(uint16_t a, uint8_t b) __reentrant; -uint32_t mathPrvMul16x16(uint16_t a, uint16_t b) __reentrant; -uint32_t mathPrvMul32x8(uint32_t a, uint8_t b) __reentrant; -uint32_t mathPrvDiv32x8(uint32_t num, uint8_t denom) __reentrant; -uint32_t mathPrvDiv32x16(uint32_t num, uint16_t denom) __reentrant; -uint16_t mathPrvMod32x16(uint32_t num, uint16_t denom) __reentrant; -uint16_t mathPrvDiv16x8(uint16_t num, uint8_t denom) __reentrant; -uint8_t mathPrvMod16x8(uint16_t num, uint8_t denom) __reentrant; - -uint8_t mathPrvU8bitswap(uint8_t val) __reentrant; - -uint16_t mathPrvU16from2xU8(uint8_t hi, uint8_t lo) __reentrant; -uint32_t mathPrvU32from4xU8(uint8_t hi, uint8_t midhi, uint8_t midlo, uint8_t lo) __reentrant; - -char charsPrvDerefAndIncGenericPtr(const char * __xdata* __xdata str); - -void xMemSet(void __xdata* mem, uint8_t val, uint16_t num) __reentrant; -__bit xMemEqual(const void __xdata* memA, const void __xdata* memB, uint8_t num) __reentrant; -__bit xMemEqual4(const void __xdata* memA, const void __xdata* memB) __reentrant; -void xMemCopy(void __xdata* dst, const void __xdata* src, uint16_t num) __reentrant; -void xMemCopyShort(void __xdata* dst, const void __xdata* src, uint8_t num) __reentrant; -uint16_t xStrLen(const char __xdata *str) __reentrant; - -#define xMemCopy8(_dst, _src) u64_copy((uint64_t __xdata*)(_dst), (const uint64_t __xdata*)(_src)) - - -void mathPrvCopyPostinc(uint32_t __xdata *dst, uint32_t __xdata *src) __reentrant; //*dst = (*src)++ - -//private -void mathPrvSwapDptrR1R0(void) __reentrant; - - - -#endif diff --git a/zbs243_Tag_FW/asmUtil.h b/zbs243_Tag_FW/asmUtil.h new file mode 120000 index 00000000..d26a7877 --- /dev/null +++ b/zbs243_Tag_FW/asmUtil.h @@ -0,0 +1 @@ +../zbs243_shared/asmUtil.h \ No newline at end of file diff --git a/zbs243_Tag_FW/barcode.c b/zbs243_Tag_FW/barcode.c deleted file mode 100644 index c431d148..00000000 --- a/zbs243_Tag_FW/barcode.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include "barcode.h" -#include "asmUtil.h" - -//code128 generator (c) 2021 Dmitry Grinberg https://dmitry.gr -//non-commercial use only, contact licensing@dmitry.gr for other options - -#pragma nogcse - -static const uint16_t __code mCode128[] = { - 0b00110011011, 0b00110110011, 0b01100110011, 0b00011001001, 0b00110001001, 0b00110010001, 0b00010011001, 0b00100011001, - 0b00100110001, 0b00010010011, 0b00100010011, 0b00100100011, 0b00111001101, 0b00111011001, 0b01110011001, 0b00110011101, - 0b00110111001, 0b01100111001, 0b01001110011, 0b00111010011, 0b01110010011, 0b00100111011, 0b00101110011, 0b01110110111, - 0b00110010111, 0b00110100111, 0b01100100111, 0b00100110111, 0b00101100111, 0b01001100111, 0b00011011011, 0b01100011011, - 0b01101100011, 0b00011000101, 0b00011010001, 0b01100010001, 0b00010001101, 0b00010110001, 0b01000110001, 0b00010001011, - 0b00010100011, 0b01000100011, 0b00011101101, 0b01110001101, 0b01110110001, 0b00011011101, 0b01100011101, 0b01101110001, - 0b01101110111, 0b01110001011, 0b01110100011, 0b00010111011, 0b01000111011, 0b01110111011, 0b00011010111, 0b01100010111, - 0b01101000111, 0b00010110111, 0b01000110111, 0b01011000111, 0b01011110111, 0b01000010011, 0b01010001111, 0b00001100101, - 0b00110000101, 0b00001101001, 0b01100001001, 0b00110100001, 0b01100100001, 0b00001001101, 0b00100001101, 0b00001011001, - 0b01000011001, 0b00101100001, 0b01001100001, 0b01001000011, 0b00001010011, 0b01011101111, 0b00101000011, 0b01011110001, - 0b00111100101, 0b00111101001, 0b01111001001, 0b00100111101, 0b00101111001, 0b01001111001, 0b00100101111, 0b00101001111, - 0b01001001111, 0b01111011011, 0b01101111011, 0b01101101111, 0b00011110101, 0b01111000101, 0b01111010001, 0b00010111101, - 0b01000111101, 0b00010101111, 0b01000101111, 0b01111011101, 0b01110111101, 0b01111010111, 0b01110101111 -}; - - -#define CODE128_START_B (0b00001001011) -#define CODE128_STOP (0b1101011100011) - -#define CODE128_IDX_START_A (103) -#define CODE128_IDX_START_B (104) -#define CODE128_IDX_START_C (105) -#define CODE128_IDX_CODE_STOP (106) - - -enum BarCodeState { - BarCodeInit, - BarCodeEmittingChar, - BarCodeEmittingChecksum, - BarCodeEmittingStop, - BarCodeDone, -}; - - - - -__bit barcodeIsDone(struct BarcodeInfo __xdata *bci) -{ - return bci->state == BarCodeDone; -} - -__bit barcodeNextBar(struct BarcodeInfo __xdata *bci) -{ - uint8_t t; - __bit ret; - - if (!bci->barsLeft) switch (bci->state) { - case BarCodeInit: - bci->curBars = CODE128_START_B; - bci->barsLeft = 11; - bci->state = BarCodeEmittingChar; - bci->csum = CODE128_IDX_START_B; - break; - - case BarCodeEmittingChar: - t = charsPrvDerefAndIncGenericPtr(&bci->str); - if (t) { - t -= 0x20; - if (t >= 0x60) - t = '?' - 0x20; - bci->csum = mathPrvMod16x8(mathPrvMul8x8(++bci->csumMul, t) + bci->csum, 103); - } - else { - - bci->state = BarCodeEmittingChecksum; - t = bci->csum; - } - bci->curBars = mCode128[t]; - bci->barsLeft = 11; - break; - - case BarCodeEmittingChecksum: - bci->state = BarCodeEmittingStop; - bci->curBars = CODE128_STOP; - bci->barsLeft = 13; - break; - - case BarCodeEmittingStop: - bci->state = BarCodeDone; - //fallthrough - - case BarCodeDone: - default: - return false; - } - - ret = bci->curBars & 1; - bci->curBars >>= 1; - bci->barsLeft--; - return ret; -} diff --git a/zbs243_Tag_FW/barcode.c b/zbs243_Tag_FW/barcode.c new file mode 120000 index 00000000..c94aa5e4 --- /dev/null +++ b/zbs243_Tag_FW/barcode.c @@ -0,0 +1 @@ +../zbs243_shared/barcode.c \ No newline at end of file diff --git a/zbs243_Tag_FW/barcode.h b/zbs243_Tag_FW/barcode.h deleted file mode 100644 index f6d784b9..00000000 --- a/zbs243_Tag_FW/barcode.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _BARCODE_H_ -#define _BARCODE_H_ - -#include - -//code128 generator (c) 2021 Dmitry Grinberg https://dmitry.gr -//non-commercial use only, contact licensing@dmitry.gr for other options - - -struct BarcodeInfo { //zero-init this except the string ptr - const char *str; - uint16_t curBars; - uint8_t barsLeft; - uint8_t state; - uint8_t csum; - uint8_t csumMul; -}; - -#define barcodeWidth(nChars) (11 * (nChars) + 11 /*start */+ 11 /*check sum */ + 13 /* stop */) - -#pragma callee_saves barcodeIsDone -__bit barcodeIsDone(struct BarcodeInfo __xdata *bci); - -#pragma callee_saves barcodeNextBar -__bit barcodeNextBar(struct BarcodeInfo __xdata *bci); - - - -#endif diff --git a/zbs243_Tag_FW/barcode.h b/zbs243_Tag_FW/barcode.h new file mode 120000 index 00000000..d98efd2b --- /dev/null +++ b/zbs243_Tag_FW/barcode.h @@ -0,0 +1 @@ +../zbs243_shared/barcode.h \ No newline at end of file diff --git a/zbs243_Tag_FW/bitmaps.h b/zbs243_Tag_FW/bitmaps.h deleted file mode 100644 index 049ecd9f..00000000 --- a/zbs243_Tag_FW/bitmaps.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef _BITMAPS_H_ -#define _BITMAPS_H_ - -// images generated by https://lvgl.io/tools/imageconverter, prepended with width, height. "CF_INDEXED_1_BIT"-mode, little-endian -#include - -#include "screen.h" - -static const uint8_t __code oepli[] = { - 128, 26, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0, - 0xf7, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xc0, - 0xe3, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xc0, - 0xe3, 0x9d, 0xc1, 0xc7, 0x70, 0x1f, 0x9c, 0xe7, 0x73, 0xb8, 0x71, 0xd0, 0x38, 0x73, 0xb9, 0xc7, - 0xe3, 0x9f, 0xe3, 0xe7, 0xf8, 0x1f, 0x9f, 0xef, 0xf3, 0xfc, 0xf9, 0xf0, 0x38, 0x73, 0xfd, 0xce, - 0xe3, 0x9f, 0xe7, 0x77, 0xf8, 0x1f, 0x9f, 0xcf, 0xf3, 0xfd, 0xdd, 0xf0, 0x38, 0x73, 0xfd, 0xdc, - 0xe3, 0x9c, 0xe7, 0xf7, 0x38, 0x1c, 0x1f, 0x8e, 0x73, 0x9d, 0xfd, 0xc0, 0x38, 0x73, 0x9d, 0xf8, - 0xe3, 0x9c, 0xe7, 0xf7, 0x38, 0x1c, 0x1c, 0x0e, 0x73, 0x9d, 0xfd, 0xc0, 0x38, 0x73, 0x9d, 0xf8, - 0xf7, 0x9c, 0xe7, 0x07, 0x38, 0x1c, 0x1c, 0x0e, 0x73, 0x9d, 0xc1, 0xc0, 0x38, 0x73, 0x9d, 0xdc, - 0x7f, 0x1f, 0xe7, 0xf7, 0x38, 0x1f, 0x9c, 0x0f, 0xf3, 0xfd, 0xfd, 0xc0, 0x3f, 0x73, 0x9d, 0xdc, - 0x7f, 0x1f, 0xe3, 0xe7, 0x38, 0x1f, 0x9c, 0x0f, 0xf3, 0xfc, 0xf9, 0xc0, 0x3f, 0x73, 0x9d, 0xce, - 0x1e, 0x1d, 0xc1, 0xc7, 0x38, 0x1f, 0x9c, 0x07, 0x73, 0xb8, 0x71, 0xc0, 0x3f, 0x73, 0x9d, 0xc7, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; - -static const uint8_t __code cloud[] = { - 128, 50, - 0x00, 0x08, 0x82, 0xa2, 0xab, 0x55, 0xbf, 0xff, 0xff, 0xff, 0x7d, 0xb4, 0x62, 0x28, 0x00, 0x00, - 0x00, 0x10, 0x10, 0x11, 0x76, 0xff, 0x7b, 0xff, 0xff, 0x7f, 0xb7, 0xa9, 0x55, 0x50, 0x51, 0x00, - 0x00, 0x29, 0x22, 0x96, 0x6f, 0xf7, 0xbf, 0xff, 0xff, 0xff, 0xea, 0xe6, 0x22, 0xaa, 0x08, 0x00, - 0x00, 0x02, 0x54, 0x2a, 0xbf, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x59, 0xb4, 0x10, 0x20, 0x00, - 0x00, 0x24, 0x23, 0xb5, 0xb5, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xae, 0x48, 0x55, 0x10, 0x00, - 0x00, 0x88, 0x90, 0x54, 0x6a, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xf5, 0xa3, 0x82, 0x00, 0x00, - 0x00, 0x01, 0x2d, 0xa3, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xbe, 0x4e, 0x52, 0x09, 0x00, - 0x04, 0x90, 0x02, 0x0d, 0x55, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xdd, 0x68, 0xa9, 0x00, 0x10, - 0x00, 0x49, 0x0c, 0xfb, 0xab, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xeb, 0x95, 0x5a, 0x00, 0x20, - 0x00, 0x12, 0x91, 0x22, 0xbf, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x65, 0x81, 0x40, 0x40, - 0x00, 0x28, 0x12, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xab, 0x28, 0x00, 0x00, - 0x00, 0x42, 0x0a, 0x97, 0x75, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x4a, 0xc2, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x02, 0x9c, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x8d, 0x00, 0x20, - 0x00, 0x04, 0x4d, 0x72, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xd5, 0x74, 0x80, 0x00, - 0x02, 0x40, 0x12, 0x8e, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xae, 0xaa, 0x0a, 0x11, 0x20, - 0x00, 0x20, 0x52, 0x5f, 0xf5, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x72, 0x94, 0xaa, 0x24, 0x00, - 0x00, 0x01, 0x0a, 0xab, 0x6f, 0x77, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xaf, 0x54, 0x54, 0x88, 0x00, - 0x00, 0x04, 0x80, 0x4d, 0x95, 0xeb, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x58, 0xb5, 0x51, 0x40, 0x00, - 0x00, 0x08, 0x08, 0xa6, 0xb3, 0xf7, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xad, 0x4a, 0xa0, 0x10, 0x00, - 0x00, 0x02, 0x96, 0x41, 0xdc, 0xae, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xbf, 0xea, 0x48, 0x02, 0x00, - 0x00, 0x00, 0x09, 0x3e, 0xab, 0x75, 0xef, 0xff, 0xff, 0xff, 0xff, 0xd4, 0xb1, 0x21, 0x08, 0x00, - 0x00, 0x00, 0x0a, 0xc3, 0x5d, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xef, 0xef, 0x44, 0x4a, 0x64, 0x80, - 0x00, 0x00, 0xa1, 0x52, 0xa6, 0xef, 0xef, 0xff, 0xff, 0xff, 0xd6, 0xca, 0xf5, 0x10, 0x18, 0x00, - 0x00, 0x00, 0x02, 0x15, 0x4b, 0xd5, 0xdf, 0xff, 0xff, 0xf7, 0xeb, 0xd4, 0xd8, 0x85, 0x00, 0x00, -}; - -static const uint8_t __code receive[] = { - 56, 56, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, - 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xe0, - 0x00, 0x00, 0x7f, 0x80, 0x00, 0x7f, 0xf0, - 0x00, 0x00, 0xfe, 0x00, 0x03, 0xff, 0xf0, - 0x00, 0x01, 0xfc, 0x00, 0x0f, 0xff, 0xf0, - 0x00, 0x01, 0xf8, 0x00, 0x3f, 0xff, 0xf0, - 0x00, 0x03, 0xf8, 0x00, 0xff, 0xff, 0x80, - 0x00, 0x07, 0xf0, 0x01, 0xff, 0xe0, 0x00, - 0x00, 0x0f, 0xe0, 0x03, 0xff, 0x00, 0x00, - 0x00, 0x0f, 0xc0, 0x0f, 0xf8, 0x00, 0x00, - 0x00, 0x1f, 0x80, 0x1f, 0xf0, 0x00, 0x00, - 0x00, 0x1f, 0x80, 0x3f, 0xc0, 0x00, 0x00, - 0x00, 0x3f, 0x00, 0x3f, 0x80, 0x00, 0x00, - 0x00, 0x3f, 0x00, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x7e, 0x00, 0xfe, 0x00, 0x07, 0xe0, - 0x00, 0x7e, 0x01, 0xfc, 0x00, 0x1f, 0xf0, - 0x00, 0xfc, 0x01, 0xf8, 0x00, 0x7f, 0xf0, - 0x00, 0xfc, 0x03, 0xf0, 0x01, 0xff, 0xf0, - 0x00, 0xf8, 0x03, 0xf0, 0x03, 0xff, 0xf0, - 0x01, 0xf8, 0x07, 0xe0, 0x07, 0xff, 0x00, - 0x01, 0xf8, 0x07, 0xe0, 0x0f, 0xf0, 0x00, - 0x01, 0xf0, 0x0f, 0xc0, 0x1f, 0xe0, 0x00, - 0x01, 0xf0, 0x0f, 0xc0, 0x3f, 0x80, 0x00, - 0x03, 0xf0, 0x0f, 0x80, 0x3f, 0x00, 0x00, - 0x03, 0xf0, 0x1f, 0x80, 0x7e, 0x00, 0x00, - 0x03, 0xe0, 0x1f, 0x80, 0x7e, 0x00, 0x00, - 0x03, 0xe0, 0x1f, 0x00, 0xfc, 0x01, 0xe0, - 0x03, 0xe0, 0x1f, 0x00, 0xfc, 0x07, 0xf8, - 0x03, 0xe0, 0x1f, 0x00, 0xf8, 0x0f, 0xfc, - 0x03, 0xe0, 0x3f, 0x00, 0xf8, 0x0f, 0xfc, - 0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe, - 0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe, - 0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe, - 0x03, 0xc0, 0x3e, 0x01, 0xf0, 0x1f, 0xfe, - 0x01, 0xc0, 0x1e, 0x00, 0xf0, 0x0f, 0xfc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - - -static const uint8_t __code failed[] = { - 48, 48, - 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, - 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, - 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, - 0x00, 0x7f, 0xf0, 0x0f, 0xfe, 0x00, - 0x00, 0xff, 0x80, 0x01, 0xff, 0x00, - 0x01, 0xfe, 0x00, 0x00, 0x7f, 0x80, - 0x03, 0xf8, 0x00, 0x00, 0x1f, 0xc0, - 0x07, 0xf0, 0x00, 0x00, 0x3f, 0xe0, - 0x0f, 0xe0, 0x00, 0x00, 0x7f, 0xf0, - 0x0f, 0xc0, 0x00, 0x00, 0xff, 0xf0, - 0x1f, 0x80, 0x00, 0x01, 0xff, 0xf8, - 0x1f, 0x00, 0x00, 0x03, 0xff, 0xf8, - 0x3f, 0x00, 0x00, 0x07, 0xfe, 0xfc, - 0x3e, 0x00, 0x00, 0x0f, 0xfc, 0x7c, - 0x7e, 0x00, 0x00, 0x1f, 0xf8, 0x7e, - 0x7c, 0x00, 0x00, 0x3f, 0xf0, 0x3e, - 0x7c, 0x00, 0x00, 0x7f, 0xe0, 0x3e, - 0xfc, 0x00, 0x00, 0xff, 0xc0, 0x3f, - 0xf8, 0x00, 0x01, 0xff, 0x80, 0x1f, - 0xf8, 0x00, 0x03, 0xff, 0x00, 0x1f, - 0xf8, 0x00, 0x07, 0xfe, 0x00, 0x1f, - 0xf8, 0x00, 0x0f, 0xfc, 0x00, 0x1f, - 0xf8, 0x00, 0x1f, 0xf8, 0x00, 0x1f, - 0xf8, 0x00, 0x3f, 0xf0, 0x00, 0x1f, - 0xf8, 0x00, 0x7f, 0xe0, 0x00, 0x1f, - 0xf8, 0x00, 0xff, 0xc0, 0x00, 0x1f, - 0xfc, 0x01, 0xff, 0x80, 0x00, 0x3f, - 0x7c, 0x03, 0xff, 0x00, 0x00, 0x3e, - 0x7c, 0x07, 0xfe, 0x00, 0x00, 0x3e, - 0x7e, 0x0f, 0xfc, 0x00, 0x00, 0x7e, - 0x3e, 0x1f, 0xf8, 0x00, 0x00, 0x7c, - 0x3f, 0x3f, 0xf0, 0x00, 0x00, 0xfc, - 0x3f, 0x7f, 0xe0, 0x00, 0x00, 0xfc, - 0x1f, 0xff, 0xc0, 0x00, 0x01, 0xf8, - 0x0f, 0xff, 0x80, 0x00, 0x03, 0xf0, - 0x0f, 0xff, 0x00, 0x00, 0x07, 0xf0, - 0x07, 0xfe, 0x00, 0x00, 0x0f, 0xe0, - 0x03, 0xfc, 0x00, 0x00, 0x1f, 0xc0, - 0x01, 0xfe, 0x00, 0x00, 0x7f, 0x80, - 0x00, 0xff, 0x80, 0x01, 0xff, 0x00, - 0x00, 0x7f, 0xf0, 0x0f, 0xfe, 0x00, - 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, - 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, - 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, -}; - -#if (SCREEN_WIDTH != 128) -static const uint8_t __code ant[] = { - 16, 16, - 0x00, 0x40, - 0x02, 0x20, - 0x01, 0x20, - 0x11, 0x20, - 0x11, 0x20, - 0x12, 0x20, - 0x28, 0x40, - 0x28, 0x00, - 0x28, 0x00, - 0x44, 0x00, - 0x44, 0x00, - 0x44, 0x00, - 0x44, 0x00, - 0x82, 0x00, - 0x82, 0x00, - 0xfe, 0x00, -}; -#else -static const uint8_t __code ant[] = { - // rotated 90 degrees - 16,16, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x7c, 0x00, - 0x82, 0x00, - 0x00, 0x00, - 0x38, 0x00, - 0x44, 0x07, - 0x00, 0x79, - 0x03, 0x81, - 0x1c, 0x01, - 0x03, 0x81, - 0x00, 0x79, - 0x00, 0x07, -}; -#endif -static const uint8_t __code cross[] = { - 8,8, - 0x00, - 0x63, - 0x77, - 0x3e, - 0x1c, - 0x3e, - 0x77, - 0x63 -}; - -#if (SCREEN_WIDTH != 128) -static const uint8_t __code battery[] = { - 16,10, - 0x00, 0x00, - 0x7f, 0xfc, - 0x40, 0x04, - 0x58, 0x06, - 0x58, 0x06, - 0x58, 0x06, - 0x58, 0x06, - 0x40, 0x04, - 0x7f, 0xfc, - 0x00, 0x00, -}; -#else -// this battery symbol is rotated 90' -static const uint8_t __code battery[] = { -16,16, - 0x00, 0x00, - 0x03, 0xc0, - 0x0f, 0xf0, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x08, 0x10, - 0x0b, 0xd0, - 0x0b, 0xd0, - 0x08, 0x10, - 0x0f, 0xf0, - 0x00, 0x00, -}; - -#endif - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/bitmaps.h b/zbs243_Tag_FW/bitmaps.h new file mode 120000 index 00000000..1d4d18fd --- /dev/null +++ b/zbs243_Tag_FW/bitmaps.h @@ -0,0 +1 @@ +../zbs243_shared/bitmaps.h \ No newline at end of file diff --git a/zbs243_Tag_FW/board b/zbs243_Tag_FW/board new file mode 120000 index 00000000..af42b18b --- /dev/null +++ b/zbs243_Tag_FW/board @@ -0,0 +1 @@ +../zbs243_shared/board \ No newline at end of file diff --git a/zbs243_Tag_FW/board/boardCommon.h b/zbs243_Tag_FW/board/boardCommon.h deleted file mode 100644 index cef1474d..00000000 --- a/zbs243_Tag_FW/board/boardCommon.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _BOARD_COMMON_H_ -#define _BOARD_COMMON_H_ - -#include - -#pragma callee_saves powerPortsDownForSleep -void powerPortsDownForSleep(void); - -#pragma callee_saves boardInit -void boardInit(void); - -//late, after eeprom -#pragma callee_saves boardInit -__bit boardGetOwnMac(uint8_t __xdata *mac); - - -#ifndef AP_FW -//some sanity checks -#include "eeprom.h" - - -#if !EEPROM_SETTINGS_AREA_START - #error "settings cannot be at address 0" -#endif - -#if (EEPROM_SETTINGS_AREA_LEN % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "settings area must be an integer number of eeprom blocks" -#endif - -#if (EEPROM_SETTINGS_AREA_START % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "settings must begin at an integer number of eeprom blocks" -#endif - -#if (EEPROM_IMG_EACH % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "each image must be an integer number of eeprom blocks" -#endif - -#if (EEPROM_IMG_START % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "images must begin at an integer number of eeprom blocks" -#endif - -#if (EEPROM_UPDATE_AREA_LEN % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "update must be an integer number of eeprom blocks" -#endif - -#if (EEPROM_UPDATA_AREA_START % EEPROM_ERZ_SECTOR_SZ) != 0 - #error "images must begin at an integer number of eeprom blocks" -#endif - -#endif - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/boardZBS29common.c b/zbs243_Tag_FW/board/boardZBS29common.c deleted file mode 100644 index 80667c6c..00000000 --- a/zbs243_Tag_FW/board/boardZBS29common.c +++ /dev/null @@ -1,160 +0,0 @@ -#include -#include "printf.h" -#include "screen.h" -#include "board.h" -#include "flash.h" -#include "uart.h" -#include "spi.h" -#include "cpu.h" -#include "wdt.h" -#include "i2c.h" - -//extern uint8_t __xdata* tempBuffer; -uint8_t __xdata tempBuffer[320]; - -void powerPortsDownForSleep(void) -{ - P0FUNC = 0; - P1FUNC = 0; - P2FUNC = 0; - P0DIR = 0; - P0 = 0; - P0PULL = 0; - P1DIR = 0; - P1 = 2; - P1PULL = 0; - P2DIR = 2; - P2 =1; - P2PULL = 0; -} - -void boardInit(void) -{ - //set up pins for spi(0.0,0.1,0.2), UART (0.6) - P0FUNC |= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 6); - P0DIR = (P0DIR &~ ((1 << 0) | (1 << 1) | (1 << 6))) | (1 << 2); - - //pulls for spi in - P0PULL = (P0PULL &~ ((1 << 0) | (1 << 1) | (1 << 6))) | (1 << 2); - - //setup 1.1(eeprom_nCS), 1.2(eink_BS1), 1.7(eink_nCS) - P1FUNC &=~ ((1 << 1) | (1 << 2) | (1 << 7)); - P1DIR &= ~((1 << 1) | (1 << 2) | (1 << 7)); - - //setup 2.0(eink_nRST), 2.1(eink_BUSY), 2.2(eink_D/nC) - P2FUNC &= ~((1 << 0) | (1 << 1) | (1 << 2)); - P2DIR = (P2DIR &~ ((1 << 0) | (1 << 2))) | (1 << 1); - - //raise chip select(s) - P1_1 = 1; - P1_7 = 1; - - //BS1 = low - P1_2 = 0; - - spiInit(); -} - - -__bit boardGetOwnMac(uint8_t __xdata *mac) -{ - return flashRead(FLASH_INFOPAGE_ADDR + 0x10, mac, 8); -} - -#pragma callee_saves prvUpdateApplierGet -static uint32_t prvUpdateApplierGet(void) __naked -{ - __asm__( - " mov DPTR, #00098$ \n" - " mov A, #00099$ \n" - " clr C \n" - " subb A, DPL \n" - " mov B, A \n" - " ret \n" - - ///actual updater code - "00098$: \n" - - - //copied to last page of flash for updating, called with ints off and eeprom ready to read update - //flashes 63 flash pages, uses xram for buffer. uses combined erase+flash flash op - - " mov _CLKSPEED, #0x21 \n" - " mov _CFGPAGE, #0x04 \n" - " mov R0, #0 \n" - - "00001$: \n" - - //read a page of update - " mov DPTR, #0xe000 \n" - " mov R1, #0x04 \n" - " mov R2, #0x00 \n" - "000010$: \n" - " mov _SPITX, #0x00 \n" - " mov _SPICFG, #0xa0 \n" - "000011$: \n" - " mov A, _SPICFG \n" - " jb A.5, 000011$ \n" - " mov A, _SPIRX \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz R2, 000010$ \n" - " djnz R1, 000010$ \n" - - //flash it - " clr A \n" - " orl _SETTINGS, #0x38 \n" - " mov _FWRTHREE, #0x03 \n" - " mov _FPGNO, R0 \n" - " mov _FWRDSTL, A \n" - " mov _FWRDSTH, A \n" - " mov _FWRLENL, #0xff \n" - " mov _FWRLENH, #0x03 \n" - " mov _FWRSRCL, A \n" - " mov _FWRSRCH, #0xe0 \n" - " orl _TRIGGER, #0x08 \n" - "00050$: \n" - " mov A, _TCON2 \n" - " jnb A.3, 00050$ \n" - " anl _TCON2, #~0x48 \n" - " anl _SETTINGS, #~0x10 \n" - - //go do next page - " inc R0 \n" - " cjne R0, #63, 00001$ \n" - - //done? reset - " mov _WDTCONF, #0x80 \n" - " mov _WDTENA, #0x01 \n" - " mov A, #0xff \n" - " mov _WDTRSTVALH, A \n" - " mov _WDTRSTVALM, A \n" - " mov _WDTRSTVALL, A \n" - "00090$: \n" - " sjmp 00090$ \n" - - "00099$: \n" - ); -} - -void selfUpdate(void) -{ - uint32_t updaterInfo = prvUpdateApplierGet(); - uint8_t __code *src = (uint8_t __code*)updaterInfo; - uint8_t i, len = updaterInfo >> 16; - uint8_t __xdata *dst = tempBuffer; - - for (i = len; i ; i--) - *dst++ = *src++; - - if (!flashWrite(0xfc00, tempBuffer, len, true)) - pr("failed to write updater\n"); - - IEN_EA = 0; //ints off - - __asm__( - " mov dptr, #0xfc00 \n" - " clr a \n" - " jmp @a+dptr \n" - ); -} \ No newline at end of file diff --git a/zbs243_Tag_FW/board/ssd1619.c b/zbs243_Tag_FW/board/ssd1619.c deleted file mode 100644 index 89530ec6..00000000 --- a/zbs243_Tag_FW/board/ssd1619.c +++ /dev/null @@ -1,817 +0,0 @@ -#include -#include - -#include "asmUtil.h" -#include "barcode.h" -#include "board.h" -#include "cpu.h" -#include "ssd1619.h" -#include "font.h" -#include "lut.h" -#include "printf.h" -#include "screen.h" -#include "settings.h" -#include "sleep.h" -#include "spi.h" -#include "timer.h" -#include "wdt.h" - -#define CMD_DRV_OUTPUT_CTRL 0x01 -#define CMD_SOFT_START_CTRL 0x0C -#define CMD_ENTER_SLEEP 0x10 -#define CMD_DATA_ENTRY_MODE 0x11 -#define CMD_SOFT_RESET 0x12 -#define CMD_SOFT_RESET2 0x13 -#define CMD_SETUP_VOLT_DETECT 0x15 -#define CMD_TEMP_SENSOR_CONTROL 0x18 -#define CMD_ACTIVATION 0x20 -#define CMD_DISP_UPDATE_CTRL 0x21 -#define CMD_DISP_UPDATE_CTRL2 0x22 -#define CMD_WRITE_FB_BW 0x24 -#define CMD_WRITE_FB_RED 0x26 -#define CMD_UNKNOWN_1 0x2B -#define CMD_LOAD_OTP_LUT 0x31 -#define CMD_WRITE_LUT 0x32 -#define CMD_BORDER_WAVEFORM_CTRL 0x3C -#define CMD_WINDOW_X_SIZE 0x44 -#define CMD_WINDOW_Y_SIZE 0x45 -#define CMD_WRITE_PATTERN_RED 0x46 -#define CMD_WRITE_PATTERN_BW 0x47 -#define CMD_XSTART_POS 0x4E -#define CMD_YSTART_POS 0x4F -#define CMD_ANALOG_BLK_CTRL 0x74 -#define CMD_DIGITAL_BLK_CTRL 0x7E - -#define SCREEN_CMD_CLOCK_ON 0x80 -#define SCREEN_CMD_CLOCK_OFF 0x01 -#define SCREEN_CMD_ANALOG_ON 0x40 -#define SCREEN_CMD_ANALOG_OFF 0x02 -#define SCREEN_CMD_LATCH_TEMPERATURE_VAL 0x20 -#define SCREEN_CMD_LOAD_LUT 0x10 -#define SCREEN_CMD_USE_MODE_2 0x08 // modified commands 0x10 and 0x04 -#define SCREEN_CMD_REFRESH 0xC7 - -#define commandEnd() \ - do { \ - P1_7 = 1; \ - } while (0) - -#define markCommand() \ - do { \ - P2_2 = 0; \ - } while (0) - -#define markData() \ - do { \ - P2_2 = 1; \ - } while (0) - -extern void dump(uint8_t* __xdata a, uint16_t __xdata l); // remove me when done - -static uint8_t __xdata epdCharSize = 1; // character size, 1 or 2 (doubled) -static bool __xdata directionY = true; // print direction, X or Y (true) -static uint8_t __xdata rbuffer[32]; // used to rotate bits around -static uint16_t __xdata fontCurXpos = 0; // current X value we're working with -static uint16_t __xdata fontCurYpos = 0; // current Y value we're working with -static uint8_t __xdata currentLut = 0; -static uint8_t __xdata dispLutSize = 0; - -static bool __xdata isInited = false; - -bool __xdata epdGPIOActive = false; - -#define LUT_BUFFER_SIZE 128 -uint8_t waveformbuffer[LUT_BUFFER_SIZE]; -struct waveform10* __xdata waveform10 = (struct waveform10*)waveformbuffer; // holds the LUT/waveform -struct waveform* __xdata waveform7 = (struct waveform*)waveformbuffer; // holds the LUT/waveform - -#pragma callee_saves epdBusySleep -#pragma callee_saves epdBusyWait -static void epdBusySleep(uint32_t timeout) { - uint8_t tmp_P2FUNC = P2FUNC; - uint8_t tmp_P2DIR = P2DIR; - uint8_t tmp_P2PULL = P2PULL; - uint8_t tmp_P2LVLSEL = P2LVLSEL; - P2FUNC &= 0xfd; - P2DIR |= 2; - P2PULL |= 2; - P2LVLSEL |= 2; - - P2CHSTA &= 0xfd; - P2INTEN |= 2; - P2CHSTA &= 0xfd; - sleepForMsec(timeout); - wdtOn(); - P2CHSTA &= 0xfd; - P2INTEN &= 0xfd; - - P2FUNC = tmp_P2FUNC; - P2DIR = tmp_P2DIR; - P2PULL = tmp_P2PULL; - P2LVLSEL = tmp_P2LVLSEL; - eepromPrvDeselect(); -} -static void epdBusyWait(uint32_t timeout) { - uint32_t __xdata start = timerGet(); - - while (timerGet() - start < timeout) { - if (!P2_1) - return; - } - pr("screen timeout %lu ticks :(\n", timerGet() - start); - while (1) - ; -} -static void commandReadBegin(uint8_t cmd) { - epdSelect(); - markCommand(); - spiByte(cmd); // dump LUT - - P0DIR = (P0DIR & ~(1 << 0)) | (1 << 1); - P0 &= ~(1 << 0); - P0FUNC &= ~((1 << 0) | (1 << 1)); - P2_2 = 1; -} -static void commandReadEnd() { - // set up pins for spi (0.0,0.1,0.2) - P0FUNC |= (1 << 0) | (1 << 1); - epdDeselect(); -} -#pragma callee_saves epdReadByte -static uint8_t epdReadByte() { - uint8_t val = 0, i; - - for (i = 0; i < 8; i++) { - P0_0 = 1; - __asm__("nop\nnop\nnop\nnop\nnop\nnop\n"); - val <<= 1; - if (P0_1) - val++; - P0_0 = 0; - __asm__("nop\nnop\nnop\nnop\nnop\nnop\n"); - } - - return val; -} -static void shortCommand(uint8_t cmd) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - epdDeselect(); -} -static void shortCommand1(uint8_t cmd, uint8_t arg) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); - spiTXByte(arg); - epdDeselect(); -} -static void shortCommand2(uint8_t cmd, uint8_t arg1, uint8_t arg2) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); - spiTXByte(arg1); - spiTXByte(arg2); - epdDeselect(); -} -static void commandBegin(uint8_t cmd) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); -} -static void epdReset() { - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 0; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 1; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - - shortCommand(CMD_SOFT_RESET); // software reset - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - shortCommand(CMD_SOFT_RESET2); - timerDelay(TIMER_TICKS_PER_SECOND / 1000); -} -void epdConfigGPIO(bool setup) { - // data / _command: 2.2 - // busy 2.1 - // reset 2.0 - // _select 1.7 - // bs1 1.2 - - // GENERIC SPI BUS PINS - // spi.clk 0.0 - // spi.mosi 0.1 - if (epdGPIOActive == setup) return; - if (setup) { - P2DIR |= (1 << 1); // busy as input - P2DIR &= ~((1 << 2) | (1 << 0)); // D/C and Reset as output - P1DIR &= ~((1 << 7) | (1 << 2)); // select and bs1 as output - P1_2 = 0; // select 4-wire SPI / BS1 = low - P1_7 = 1; // deselect EPD - } else { - P2DIR |= ((1 << 2) | (1 << 0)); // DC and Reset as input - P2 &= ~((1 << 2) | (1 << 0)); - P1DIR |= ((1 << 7) | (1 << 2)); // Select and BS1 as input - P2 &= ~((1 << 7)); - } - epdGPIOActive = setup; -} -void epdEnterSleep() { - P2_0 = 0; - timerDelay(10); - P2_0 = 1; - timerDelay(50); - shortCommand(CMD_SOFT_RESET2); - epdBusyWait(TIMER_TICKS_PER_MS * 15); - shortCommand1(CMD_ENTER_SLEEP, 0x03); - isInited = false; -} -void epdSetup() { - epdReset(); - shortCommand1(CMD_ANALOG_BLK_CTRL, 0x54); - shortCommand1(CMD_DIGITAL_BLK_CTRL, 0x3B); - shortCommand2(CMD_UNKNOWN_1, 0x04, 0x63); - - commandBegin(CMD_SOFT_START_CTRL); - epdSend(0x8f); - epdSend(0x8f); - epdSend(0x8f); - epdSend(0x3f); - commandEnd(); - - commandBegin(CMD_DRV_OUTPUT_CTRL); - epdSend((SCREEN_HEIGHT - 1) & 0xff); - epdSend((SCREEN_HEIGHT - 1) >> 8); - epdSend(0x00); - commandEnd(); - - // shortCommand1(CMD_DATA_ENTRY_MODE, 0x03); - shortCommand1(CMD_BORDER_WAVEFORM_CTRL, 0xC0); - shortCommand1(CMD_TEMP_SENSOR_CONTROL, 0x80); - shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1 (i2C) - // shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB9); // mode 2? - shortCommand(CMD_ACTIVATION); - epdBusyWait(TIMER_TICKS_PER_SECOND); - isInited = true; - currentLut = EPD_LUT_DEFAULT; -} -static uint8_t epdGetStatus() { - uint8_t sta; - commandReadBegin(0x2F); - sta = epdReadByte(); - commandReadEnd(); - return sta; -} -uint16_t epdGetBattery(void) { - uint16_t voltage = 2600; - uint8_t val; - - timerDelay(50); - P2_0 = 0; - timerDelay(50); - P2_0 = 1; - timerDelay(50); - - shortCommand(CMD_SOFT_RESET); // software reset - epdBusyWait(TIMER_TICKS_PER_MS * 30); - shortCommand(CMD_SOFT_RESET2); - epdBusyWait(TIMER_TICKS_PER_MS * 30); - - shortCommand1(CMD_DISP_UPDATE_CTRL2, SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON); - shortCommand(CMD_ACTIVATION); - epdBusyWait(TIMER_TICKS_PER_MS * 100); - - for (val = 3; val < 8; val++) { - shortCommand1(CMD_SETUP_VOLT_DETECT, val); - epdBusyWait(TIMER_TICKS_PER_MS * 100); - if (epdGetStatus() & 0x10) { // set if voltage is less than threshold ( == 1.9 + val / 10) - voltage = 1850 + mathPrvMul8x8(val, 100); - break; - } - } - - shortCommand(CMD_SOFT_RESET2); - epdBusyWait(TIMER_TICKS_PER_MS * 15); - shortCommand1(CMD_ENTER_SLEEP, 0x03); - - return voltage; -} - -void loadFixedTempOTPLUT() { - shortCommand1(0x18, 0x48); // external temp sensor - shortCommand2(0x1A, 0x05, 0x00); // < temp register - shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1 (i2C) - shortCommand(CMD_ACTIVATION); - epdBusyWait(TIMER_TICKS_PER_SECOND); -} -static void writeLut() { - commandBegin(CMD_WRITE_LUT); - for (uint8_t i = 0; i < (dispLutSize * 10); i++) - epdSend(waveformbuffer[i]); - commandEnd(); -} -static void readLut() { - commandReadBegin(0x33); - uint16_t checksum = 0; - uint16_t ident = 0; - uint16_t shortl = 0; - for (uint16_t c = 0; c < LUT_BUFFER_SIZE; c++) { - waveformbuffer[c] = epdReadByte(); - } - commandReadEnd(); -} -static uint8_t getLutSize() { - uint8_t ref = 0; - for (uint8_t c = (LUT_BUFFER_SIZE - 4); c > 16; c--) { - uint8_t check = waveformbuffer[c]; - for (uint8_t d = 1; d < 4; d++) { - if (waveformbuffer[c + d] != check) { - ref = c; - goto end; - } - } - } -end:; - return ref + 1; -} -static void lutGroupDisable(uint8_t group) { - if (dispLutSize == 7) { - memset(&(waveform7->group[group]), 0x00, 5); - } else { - memset(&(waveform10->group[group]), 0x00, 5); - } -} -static void lutGroupSpeedup(uint8_t group, uint8_t speed) { - if (dispLutSize == 7) { - for (uint8_t i = 0; i < 4; i++) { - waveform7->group[group].phaselength[i] = 1 + (waveform7->group[group].phaselength[i] / speed); - } - } else { - for (uint8_t i = 0; i < 4; i++) { - waveform10->group[group].phaselength[i] = 1 + (waveform10->group[group].phaselength[i] / speed); - } - } -} -static void lutGroupRepeat(uint8_t group, uint8_t repeat) { - if (dispLutSize == 7) { - waveform7->group[group].repeat = repeat; - } else { - waveform10->group[group].repeat = repeat; - } -} -static void lutGroupRepeatReduce(uint8_t group, uint8_t factor) { - if (dispLutSize == 7) { - waveform7->group[group].repeat = waveform7->group[group].repeat / factor; - } else { - waveform10->group[group].repeat = waveform10->group[group].repeat / factor; - } -} -void selectLUT(uint8_t lut) { - if (currentLut == lut) { - return; - } - - if (currentLut != EPD_LUT_DEFAULT) { - // load the 'default' LUT for the current temperature in the EPD lut register - shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1? - shortCommand(CMD_ACTIVATION); - epdBusyWait(TIMER_TICKS_PER_SECOND); - } - - currentLut = lut; - - // if we're going to be using the default LUT, we're done here. - if (lut == EPD_LUT_DEFAULT) { - return; - } - - // download the current LUT from the waveform buffer - readLut(); - - if (dispLutSize == 0) { - dispLutSize = getLutSize(); - dispLutSize /= 10; - pr("lut size = %d\n", dispLutSize); -#ifdef PRINT_LUT - dump(waveformbuffer, LUT_BUFFER_SIZE); -#endif - } - - switch (lut) { - case EPD_LUT_NO_REPEATS: - lutGroupDisable(LUTGROUP_NEGATIVE); - lutGroupDisable(LUTGROUP_FASTBLINK); - lutGroupRepeat(LUTGROUP_SLOWBLINK, 0); - lutGroupSpeedup(LUTGROUP_SET, 2); - lutGroupSpeedup(LUTGROUP_IMPROVE_SHARPNESS, 2); - lutGroupRepeatReduce(LUTGROUP_IMPROVE_SHARPNESS, 2); - lutGroupSpeedup(LUTGROUP_IMPROVE_REDS, 2); - lutGroupRepeatReduce(LUTGROUP_IMPROVE_REDS, 2); - lutGroupDisable(LUTGROUP_UNUSED); - break; - case EPD_LUT_FAST_NO_REDS: - lutGroupDisable(LUTGROUP_NEGATIVE); - lutGroupDisable(LUTGROUP_FASTBLINK); - lutGroupDisable(LUTGROUP_SLOWBLINK); - lutGroupSpeedup(LUTGROUP_SET, 2); - lutGroupDisable(LUTGROUP_IMPROVE_REDS); - lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS); - lutGroupDisable(LUTGROUP_UNUSED); - break; - case EPD_LUT_FAST: - lutGroupDisable(LUTGROUP_NEGATIVE); - lutGroupDisable(LUTGROUP_FASTBLINK); - lutGroupDisable(LUTGROUP_SLOWBLINK); - lutGroupRepeat(LUTGROUP_SET, 1); - lutGroupSpeedup(LUTGROUP_SET, 2); - lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS); - lutGroupDisable(LUTGROUP_IMPROVE_REDS); - lutGroupDisable(LUTGROUP_UNUSED); - break; - } - - if (dispLutSize == 10) { - lutGroupDisable(LUTGROUP_UNUSED); - lutGroupDisable(LUTGROUP_UNKNOWN); - lutGroupDisable(LUTGROUP_UNUSED3); - lutGroupDisable(LUTGROUP_UNUSED4); - } - writeLut(); -} - -void setWindowX(uint16_t start, uint16_t end) { - shortCommand2(CMD_WINDOW_X_SIZE, start / 8, end / 8 - 1); -} -void setWindowY(uint16_t start, uint16_t end) { - commandBegin(CMD_WINDOW_Y_SIZE); - epdSend((start)&0xff); - epdSend((start) >> 8); - epdSend((end - 1) & 0xff); - epdSend((end - 1) >> 8); - commandEnd(); -} -void setPosXY(uint16_t x, uint16_t y) { - shortCommand1(CMD_XSTART_POS, (uint8_t)(x / 8)); - commandBegin(CMD_YSTART_POS); - epdSend((y)&0xff); - epdSend((y) >> 8); - commandEnd(); -} -void setColorMode(uint8_t red, uint8_t bw) { - shortCommand1(CMD_DISP_UPDATE_CTRL, (red << 4) | bw); -} -void fillWindowWithPattern(bool color) { - if (color == EPD_COLOR_RED) { - shortCommand1(CMD_WRITE_PATTERN_RED, 0x00); - } else { - shortCommand1(CMD_WRITE_PATTERN_BW, 0x00); - } -} -void clearWindow(bool color) { - if (color == EPD_COLOR_RED) { - shortCommand1(CMD_WRITE_PATTERN_RED, 0x66); - } else { - shortCommand1(CMD_WRITE_PATTERN_BW, 0x66); - } -} -void clearScreen() { - setWindowX(0, SCREEN_WIDTH); - setWindowY(0, SCREEN_HEIGHT); - setPosXY(0, 0); - shortCommand1(CMD_DATA_ENTRY_MODE, 3); // was 3 - shortCommand1(CMD_WRITE_PATTERN_BW, 0x66); - epdBusyWait(TIMER_TICKS_PER_MS * 100); - shortCommand1(CMD_WRITE_PATTERN_RED, 0x66); - epdBusyWait(TIMER_TICKS_PER_MS * 100); -} -void draw() { - shortCommand1(0x22, 0xCF); - // shortCommand1(0x22, SCREEN_CMD_REFRESH); - shortCommand(0x20); - epdBusyWait(TIMER_TICKS_PER_SECOND * 120); -} -void drawNoWait() { - shortCommand1(0x22, 0xCF); - // shortCommand1(0x22, SCREEN_CMD_REFRESH); - shortCommand(0x20); -} -void drawWithSleep() { - shortCommand1(0x22, 0xCF); - // shortCommand1(0x22, SCREEN_CMD_REFRESH); - shortCommand(0x20); - uint8_t tmp_P2FUNC = P2FUNC; - uint8_t tmp_P2DIR = P2DIR; - uint8_t tmp_P2PULL = P2PULL; - uint8_t tmp_P2LVLSEL = P2LVLSEL; - P2FUNC &= 0xfd; - P2DIR |= 2; - P2PULL |= 2; - P2LVLSEL |= 2; - - P2CHSTA &= 0xfd; - P2INTEN |= 2; - P2CHSTA &= 0xfd; - sleepForMsec(TIMER_TICKS_PER_SECOND * 120); - wdtOn(); - P2CHSTA &= 0xfd; - P2INTEN &= 0xfd; - - P2FUNC = tmp_P2FUNC; - P2DIR = tmp_P2DIR; - P2PULL = tmp_P2PULL; - P2LVLSEL = tmp_P2LVLSEL; - eepromPrvDeselect(); -} -void epdWaitRdy() { - epdBusyWait(TIMER_TICKS_PER_SECOND * 120); -} -void drawLineHorizontal(bool color, uint16_t x1, uint16_t x2, uint16_t y) { - setWindowX(x1, x2); - setWindowY(y, y + 1); - if (color) { - shortCommand1(CMD_WRITE_PATTERN_RED, 0xE6); - } else { - shortCommand1(CMD_WRITE_PATTERN_BW, 0xE6); - } - epdBusyWait(TIMER_TICKS_PER_MS * 100); -} -void drawLineVertical(bool color, uint16_t x, uint16_t y1, uint16_t y2) { - setWindowY(y1, y2); - setWindowX(x, x + 8); - shortCommand1(CMD_DATA_ENTRY_MODE, 3); - setPosXY(x, y1); - if (color) { - commandBegin(CMD_WRITE_FB_RED); - } else { - commandBegin(CMD_WRITE_FB_BW); - } - uint8_t __xdata c = 0x80; - c >>= (x % 8); - for (; y1 < y2; y1++) { - epdSend(c); - } - commandEnd(); -} -void beginFullscreenImage() { - setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT); - setWindowX(0, SCREEN_WIDTH); - setWindowY(0, SCREEN_HEIGHT); - shortCommand1(CMD_DATA_ENTRY_MODE, 3); - setPosXY(0, 0); -} -void beginWriteFramebuffer(bool color) { - if (color == EPD_COLOR_RED) { - commandBegin(CMD_WRITE_FB_RED); - } else { - commandBegin(CMD_WRITE_FB_BW); - } - epdDeselect(); -} -void endWriteFramebuffer() { - commandEnd(); -} -void loadRawBitmap(uint8_t* bmp, uint16_t x, uint16_t y, bool color) { - uint16_t xsize = bmp[0] / 8; - if (bmp[0] % 8) xsize++; - uint16_t size = xsize * bmp[1]; - setWindowX(x, x + (xsize * 8)); - setWindowY(y, bmp[1] + y); - setPosXY(x, y); - shortCommand1(CMD_DATA_ENTRY_MODE, 3); - if (color) { - commandBegin(CMD_WRITE_FB_RED); - } else { - commandBegin(CMD_WRITE_FB_BW); - } - bmp += 2; - while (size--) { - epdSend(*(bmp++)); - } - commandEnd(); -} -void printBarcode(const uint8_t* string, uint16_t x, uint16_t y) { - setWindowY(y, 1); - setWindowX(x, x + 8); - setPosXY(x, y); - shortCommand1(CMD_DATA_ENTRY_MODE, 1); - commandBegin(CMD_WRITE_FB_BW); - struct BarcodeInfo __xdata bci = { - .str = string, - }; - while (!barcodeIsDone(&bci)) { - if (barcodeNextBar(&bci)) { - epdSend(0xFF); - } else { - epdSend(0x00); - } - } - commandEnd(); -} -// stuff for printing text -static void pushXFontBytesToEPD(uint8_t byte1, uint8_t byte2) { - if (epdCharSize == 1) { - uint8_t offset = 7 - (fontCurXpos % 8); - for (uint8_t c = 0; c < 8; c++) { - if (byte2 & (1 << (7 - c))) rbuffer[c] |= (1 << offset); - } - for (uint8_t c = 0; c < 8; c++) { - if (byte1 & (1 << (7 - c))) rbuffer[8 + c] |= (1 << offset); - } - fontCurXpos++; - } else { - uint8_t offset = 6 - (fontCurXpos % 8); - // double font size - for (uint8_t c = 0; c < 8; c++) { - if (byte2 & (1 << (7 - c))) { - rbuffer[c * 2] |= (3 << offset); - rbuffer[(c * 2) + 1] |= (3 << offset); - } - } - for (uint8_t c = 0; c < 8; c++) { - if (byte1 & (1 << (7 - c))) { - rbuffer[(c * 2) + 16] |= (3 << offset); - rbuffer[(c * 2) + 17] |= (3 << offset); - } - } - fontCurXpos += 2; - } - if (fontCurXpos % 8 == 0) { - // next byte, flush current byte to EPD - for (uint8_t i = 0; i < (16 * epdCharSize); i++) { - epdSend(rbuffer[i]); - } - memset(rbuffer, 0, 32); - } -} -static void bufferByteShift(uint8_t byte) { - /* - rbuffer[0] = 0; // previous value - rbuffer[1] = y%8; // offset - rbuffer[2] = 0; // current byte counter; - rbuffer[3] = 1+(epdCharsize*2); - */ - - if (rbuffer[1] == 0) { - epdSend(byte); - } else { - uint8_t offset = rbuffer[1]; - rbuffer[0] |= (byte >> offset); - epdSend(rbuffer[0]); - // epdSend(byte); - rbuffer[0] = (byte << (8 - offset)); - rbuffer[2]++; - if (rbuffer[2] == rbuffer[3]) { - epdSend(rbuffer[0]); - rbuffer[0] = 0; - rbuffer[2] = 0; - } - } -} -static void pushYFontBytesToEPD(uint8_t byte1, uint8_t byte2) { - if (epdCharSize == 2) { - for (uint8_t j = 0; j < 2; j++) { - uint8_t c = 0; - for (uint8_t i = 7; i != 255; i--) { - if (byte1 & (1 << i)) c |= (0x03 << ((i % 4) * 2)); - if ((i % 4) == 0) { - bufferByteShift(c); - c = 0; - } - } - for (uint8_t i = 7; i != 255; i--) { - if (byte2 & (1 << i)) c |= (0x03 << ((i % 4) * 2)); - if ((i % 4) == 0) { - bufferByteShift(c); - c = 0; - } - } - } - } else { - bufferByteShift(byte1); - bufferByteShift(byte2); - } -} -void writeCharEPD(uint8_t c) { - // Writes a single character to the framebuffer - bool empty = true; - for (uint8_t i = 0; i < 20; i++) { - if (font[c][i]) empty = false; - } - if (empty) { - for (uint8_t i = 0; i < 8; i++) { - if (directionY) { - pushYFontBytesToEPD(0x00, 0x00); - } else { - pushXFontBytesToEPD(0x00, 0x00); - } - } - return; - } - - uint8_t begin = 0; - while (font[c][begin] == 0x00 && font[c][begin + 1] == 0x00) { - begin += 2; - } - - uint8_t end = 20; - while (font[c][end - 1] == 0x00 && font[c][end - 2] == 0x00) { - end -= 2; - } - - for (uint8_t pos = begin; pos < end; pos += 2) { - if (directionY) { - pushYFontBytesToEPD(font[c][pos + 1], font[c][pos]); - } else { - pushXFontBytesToEPD(font[c][pos], font[c][pos + 1]); - } - } - - // spacing between characters - if (directionY) { - pushYFontBytesToEPD(0x00, 0x00); - } else { - pushXFontBytesToEPD(0x00, 0x00); - } -} - -// Print text to the EPD. Origin is top-left -void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool color) { - directionY = direction; - epdCharSize = 1 + fontsize; - if (directionY) { - uint8_t extra = 0; - - // provisions for dealing with font in Y direction, byte-unaligned - if (x % 8) { - extra = 8; - rbuffer[0] = 0; // previous value - rbuffer[1] = x % 8; // offset - rbuffer[2] = 0; // current byte counter; - rbuffer[3] = (epdCharSize * 2); - } else { - rbuffer[1] = 0; - } - - setWindowY(y, 1); - if (epdCharSize == 2) { - setWindowX(x, x + 32 + extra); - setPosXY(x, y); - } else { - setWindowX(x, x + 16 + extra); - setPosXY(x, y); - } - shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3 - } else { - if (epdCharSize == 2) { - x /= 2; - x *= 2; - setWindowY(y, y + 32); - } else { - setWindowY(y, y + 16); - } - setPosXY(x, y); - fontCurXpos = x; - setWindowX(x, SCREEN_WIDTH); - shortCommand1(CMD_DATA_ENTRY_MODE, 7); - memset(rbuffer, 0, 32); - } - - if (color) { - commandBegin(CMD_WRITE_FB_RED); - } else { - commandBegin(CMD_WRITE_FB_BW); - } -} -void epdPrintEnd() { - if (!directionY && ((fontCurXpos % 8) != 0)) { - for (uint8_t i = 0; i < (16 * epdCharSize); i++) { - epdSend(rbuffer[i]); - } - } - commandEnd(); -} - -extern uint8_t __xdata blockXferBuffer[]; - -void readRam() { - setWindowY(296, 0); - setWindowX(0, 8); - setPosXY(0, 296); - shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3 - shortCommand1(0x41, 0x00); - commandReadBegin(0x27); - epdReadByte(); - - for (uint16_t c = 0; c < 293; c++) { - blockXferBuffer[c] = epdReadByte() | 0x10; - } - commandReadEnd(); - commandBegin(CMD_WRITE_FB_BW); - for (uint16_t c = 0; c < 296; c++) { - epdSend(blockXferBuffer[c]); - } - commandEnd(); -} diff --git a/zbs243_Tag_FW/board/ssd1619.h b/zbs243_Tag_FW/board/ssd1619.h deleted file mode 100644 index a94bb934..00000000 --- a/zbs243_Tag_FW/board/ssd1619.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _JSCREEN_H_ -#define _JSCREEN_H_ - -#include -#include - -#define epdSend spiTXByte -#define EPD_DIRECTION_X false -#define EPD_DIRECTION_Y true -#define EPD_SIZE_SINGLE false -#define EPD_SIZE_DOUBLE true -#define EPD_COLOR_RED true -#define EPD_COLOR_BLACK false -#define EPD_LOAD_CUSTOM_LUT true -#define EPD_LOAD_OTP_LUT false -#define EPD_MODE_NORMAL 0x00 -#define EPD_MODE_INVERT 0x08 -#define EPD_MODE_IGNORE 0x04 - -#define EPD_LUT_DEFAULT 0 -#define EPD_LUT_NO_REPEATS 1 -#define EPD_LUT_FAST_NO_REDS 2 -#define EPD_LUT_FAST 3 - -#define epdSelect() \ - do { \ - P1_7 = 0; \ - } while (0) - -#define epdDeselect() \ - do { \ - P1_7 = 1; \ - } while (0) - -void epdSetup(); -void epdEnterSleep(); -uint16_t epdGetBattery(); -void epdConfigGPIO(bool setup); - -extern bool __xdata epdGPIOActive; - -void setWindowX(uint16_t start, uint16_t end); -void setWindowY(uint16_t start, uint16_t end); -void setPosXY(uint16_t x, uint16_t y); -void setColorMode(uint8_t red, uint8_t bw); -void fillWindowWithPattern(bool color); -void clearWindow(bool color); -void clearScreen(); -void draw(); -void drawNoWait(); -void drawWithSleep(); -void epdWaitRdy(); -void drawLineHorizontal(bool color, uint16_t x1, uint16_t x2, uint16_t y); -void drawLineVertical(bool color, uint16_t x, uint16_t y1, uint16_t y2); -void beginFullscreenImage(); -void beginWriteFramebuffer(bool color); -void endWriteFramebuffer(); -void loadRawBitmap(uint8_t* bmp, uint16_t x, uint16_t y, bool color); -void printBarcode(const uint8_t* string, uint16_t x, uint16_t y); - -void selectLUT(uint8_t lut); - -void ByteDecode(uint8_t byte); - -void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool red); -void epdPrintEnd(); - -void beginFullscreenImage(); -void beginWriteFramebuffer(bool color); - -void lutTest(); - -// for printf.c -void writeCharEPD(uint8_t c); - -#endif diff --git a/zbs243_Tag_FW/board/uc8151.c b/zbs243_Tag_FW/board/uc8151.c deleted file mode 100644 index 9fe32796..00000000 --- a/zbs243_Tag_FW/board/uc8151.c +++ /dev/null @@ -1,787 +0,0 @@ -#include "uc8151.h" - -#include -#include - -#include "asmUtil.h" -#include "barcode.h" -#include "board.h" -#include "cpu.h" -#include "font.h" -#include "lut.h" -#include "printf.h" -#include "screen.h" -#include "settings.h" -#include "sleep.h" -#include "spi.h" -#include "timer.h" -#include "wdt.h" - -#define CMD_PANEL_SETTING 0x00 -#define CMD_POWER_SETTING 0x01 -#define CMD_POWER_OFF 0x02 -#define CMD_POWER_OFF_SEQUENCE 0x03 -#define CMD_POWER_ON 0x04 -#define CMD_POWER_ON_MEASURE 0x05 -#define CMD_BOOSTER_SOFT_START 0x06 -#define CMD_DEEP_SLEEP 0x07 -#define CMD_DISPLAY_START_TRANSMISSION_DTM1 0x10 -#define CMD_DATA_STOP 0x11 -#define CMD_DISPLAY_REFRESH 0x12 -#define CMD_DISPLAY_START_TRANSMISSION_DTM2 0x13 -#define CMD_PLL_CONTROL 0x30 -#define CMD_TEMPERATURE_CALIB 0x40 -#define CMD_TEMPERATURE_SELECT 0x41 -#define CMD_TEMPERATURE_WRITE 0x42 -#define CMD_TEMPERATURE_READ 0x43 -#define CMD_VCOM_INTERVAL 0x50 -#define CMD_LOWER_POWER_DETECT 0x51 -#define CMD_TCON_SETTING 0x60 -#define CMD_RESOLUTION_SETING 0x61 -#define CMD_REVISION 0x70 -#define CMD_STATUS 0x71 -#define CMD_AUTO_MEASUREMENT_VCOM 0x80 -#define CMD_READ_VCOM 0x81 -#define CMD_VCOM_DC_SETTING 0x82 -#define CMD_PARTIAL_WINDOW 0x90 -#define CMD_PARTIAL_IN 0x91 -#define CMD_PARTIAL_OUT 0x92 -#define CMD_PROGRAM_MODE 0xA0 -#define CMD_ACTIVE_PROGRAM 0xA1 -#define CMD_READ_OTP 0xA2 -#define CMD_CASCADE_SET 0xE0 -#define CMD_POWER_SAVING 0xE3 -#define CMD_FORCE_TEMPERATURE 0xE5 - -enum PSR_FLAGS { - RES_96x230 = 0b00000000, - RES_96x252 = 0b01000000, - RES_128x296 = 0b10000000, - RES_160x296 = 0b11000000, - - LUT_OTP = 0b00000000, - LUT_REG = 0b00100000, - - FORMAT_BWR = 0b00000000, - FORMAT_BW = 0b00010000, - - SCAN_DOWN = 0b00000000, - SCAN_UP = 0b00001000, - - SHIFT_LEFT = 0b00000000, - SHIFT_RIGHT = 0b00000100, - - BOOSTER_OFF = 0b00000000, - BOOSTER_ON = 0b00000010, - - RESET_SOFT = 0b00000000, - RESET_NONE = 0b00000001 -}; - -enum PWR_FLAGS_1 { - VDS_EXTERNAL = 0b00000000, - VDS_INTERNAL = 0b00000010, - - VDG_EXTERNAL = 0b00000000, - VDG_INTERNAL = 0b00000001 -}; - -enum PWR_FLAGS_2 { - VCOM_VD = 0b00000000, - VCOM_VG = 0b00000100, - - VGHL_16V = 0b00000000, - VGHL_15V = 0b00000001, - VGHL_14V = 0b00000010, - VGHL_13V = 0b00000011 -}; - -enum BOOSTER_FLAGS { - START_10MS = 0b00000000, - START_20MS = 0b01000000, - START_30MS = 0b10000000, - START_40MS = 0b11000000, - - STRENGTH_1 = 0b00000000, - STRENGTH_2 = 0b00001000, - STRENGTH_3 = 0b00010000, - STRENGTH_4 = 0b00011000, - STRENGTH_5 = 0b00100000, - STRENGTH_6 = 0b00101000, - STRENGTH_7 = 0b00110000, - STRENGTH_8 = 0b00111000, - - OFF_0_27US = 0b00000000, - OFF_0_34US = 0b00000001, - OFF_0_40US = 0b00000010, - OFF_0_54US = 0b00000011, - OFF_0_80US = 0b00000100, - OFF_1_54US = 0b00000101, - OFF_3_34US = 0b00000110, - OFF_6_58US = 0b00000111 -}; - -enum PFS_FLAGS { - FRAMES_1 = 0b00000000, - FRAMES_2 = 0b00010000, - FRAMES_3 = 0b00100000, - FRAMES_4 = 0b00110000 -}; - -enum TSE_FLAGS { - TEMP_INTERNAL = 0b00000000, - TEMP_EXTERNAL = 0b10000000, - - OFFSET_0 = 0b00000000, - OFFSET_1 = 0b00000001, - OFFSET_2 = 0b00000010, - OFFSET_3 = 0b00000011, - OFFSET_4 = 0b00000100, - OFFSET_5 = 0b00000101, - OFFSET_6 = 0b00000110, - OFFSET_7 = 0b00000111, - - OFFSET_MIN_8 = 0b00001000, - OFFSET_MIN_7 = 0b00001001, - OFFSET_MIN_6 = 0b00001010, - OFFSET_MIN_5 = 0b00001011, - OFFSET_MIN_4 = 0b00001100, - OFFSET_MIN_3 = 0b00001101, - OFFSET_MIN_2 = 0b00001110, - OFFSET_MIN_1 = 0b00001111 -}; - -enum PLL_FLAGS { - // other frequency options exist but there doesn't seem to be much - // point in including them - this is a fair range of options... - HZ_29 = 0b00111111, - HZ_33 = 0b00111110, - HZ_40 = 0b00111101, - HZ_50 = 0b00111100, - HZ_67 = 0b00111011, - HZ_100 = 0b00111010, - HZ_200 = 0b00111001 -}; - -#define commandEnd() \ - do { \ - P1_7 = 1; \ - } while (0) - -#define markCommand() \ - do { \ - P2_2 = 0; \ - } while (0) - -#define markData() \ - do { \ - P2_2 = 1; \ - } while (0) - -extern void dump(uint8_t* __xdata a, uint16_t __xdata l); // remove me when done - -static uint8_t __xdata epdCharSize = 1; // character size, 1 or 2 (doubled) -static bool __xdata directionY = true; // print direction, X or Y (true) -static uint8_t __xdata rbuffer[32]; // used to rotate bits around -static uint16_t __xdata fontCurXpos = 0; // current X value we're working with -static uint16_t __xdata fontCurYpos = 0; // current Y value we're working with -static uint8_t __xdata currentLut = 0; -static uint8_t __xdata dispLutSize = 0; -static bool __xdata drawDirection = false; -static bool __xdata isInited = false; - -bool __xdata epdGPIOActive = false; - -#define LUT_BUFFER_SIZE 128 -uint8_t waveformbuffer[LUT_BUFFER_SIZE]; -struct waveform10* __xdata waveform10 = (struct waveform10*)waveformbuffer; // holds the LUT/waveform -struct waveform* __xdata waveform7 = (struct waveform*)waveformbuffer; // holds the LUT/waveform - -#pragma callee_saves epdBusySleep -#pragma callee_saves epdBusyWait -static void epdBusySleep(uint32_t timeout) { - uint8_t tmp_P2FUNC = P2FUNC; - uint8_t tmp_P2DIR = P2DIR; - uint8_t tmp_P2PULL = P2PULL; - uint8_t tmp_P2LVLSEL = P2LVLSEL; - P2FUNC &= 0xfd; - P2DIR |= 2; - P2PULL |= 2; - P2LVLSEL &= ~(2); - - P2CHSTA &= 0xfd; - P2INTEN |= 2; - P2CHSTA &= 0xfd; - sleepForMsec(timeout); - wdtOn(); - P2CHSTA &= 0xfd; - P2INTEN &= 0xfd; - - P2FUNC = tmp_P2FUNC; - P2DIR = tmp_P2DIR; - P2PULL = tmp_P2PULL; - P2LVLSEL = tmp_P2LVLSEL; - eepromPrvDeselect(); -} -static void epdBusyWait(uint32_t timeout) { - uint32_t __xdata start = timerGet(); - - while (timerGet() - start < timeout) { - if (P2_1) - return; - } - pr("screen timeout %lu ticks :(\n", timerGet() - start); - while (1) - ; -} -static void commandReadBegin(uint8_t cmd) { - epdSelect(); - markCommand(); - spiByte(cmd); // dump LUT - - P0DIR = (P0DIR & ~(1 << 0)) | (1 << 1); - P0 &= ~(1 << 0); - P0FUNC &= ~((1 << 0) | (1 << 1)); - P2_2 = 1; -} -static void commandReadEnd() { - // set up pins for spi (0.0,0.1,0.2) - P0FUNC |= (1 << 0) | (1 << 1); - epdDeselect(); -} -#pragma callee_saves epdReadByte -static uint8_t epdReadByte() { - uint8_t val = 0, i; - - for (i = 0; i < 8; i++) { - P0_0 = 1; - __asm__("nop\nnop\nnop\nnop\nnop\nnop\n"); - val <<= 1; - if (P0_1) - val++; - P0_0 = 0; - __asm__("nop\nnop\nnop\nnop\nnop\nnop\n"); - } - - return val; -} -static void shortCommand(uint8_t cmd) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - epdDeselect(); -} -static void shortCommand1(uint8_t cmd, uint8_t arg) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); - spiTXByte(arg); - epdDeselect(); -} -static void shortCommand2(uint8_t cmd, uint8_t arg1, uint8_t arg2) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); - spiTXByte(arg1); - spiTXByte(arg2); - epdDeselect(); -} -static void commandBegin(uint8_t cmd) { - epdSelect(); - markCommand(); - spiTXByte(cmd); - markData(); -} -static void epdReset() { - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 0; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - P2_0 = 1; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); -} -void epdConfigGPIO(bool setup) { - // data / _command: 2.2 - // busy 2.1 - // reset 2.0 - // _select 1.7 - // bs1 1.2 - - // GENERIC SPI BUS PINS - // spi.clk 0.0 - // spi.mosi 0.1 - if (epdGPIOActive == setup) return; - if (setup) { - P2DIR |= (1 << 1); // busy as input - P2DIR &= ~((1 << 2) | (1 << 0)); // D/C and Reset as output - P1DIR &= ~((1 << 7) | (1 << 2)); // select and bs1 as output - P1_2 = 0; // select 4-wire SPI / BS1 = low - P1_7 = 1; // deselect EPD - } else { - P2DIR |= ((1 << 2) | (1 << 0)); // DC and Reset as input - P2 &= ~((1 << 2) | (1 << 0)); - P1DIR |= ((1 << 7) | (1 << 2)); // Select and BS1 as input - P2 &= ~((1 << 7)); - } - epdGPIOActive = setup; -} -void epdEnterSleep() { - shortCommand1(CMD_VCOM_INTERVAL, 0x17); - shortCommand1(CMD_VCOM_DC_SETTING, 0x00); - // shortCommand(CMD_POWER_OFF); - // epdWaitRdy(); - shortCommand1(CMD_DEEP_SLEEP, 0xA5); - isInited = false; -} - -static void epdDrawDirection(bool direction) { - if (direction == drawDirection) return; - - drawDirection = direction; - - uint8_t psr_setting = RES_128x296 | FORMAT_BWR | BOOSTER_ON | RESET_NONE | LUT_OTP | SHIFT_RIGHT; - if (drawDirection) { - psr_setting |= SCAN_DOWN; - } else { - psr_setting |= SCAN_UP; - } - shortCommand1(CMD_PANEL_SETTING, psr_setting); -} - -void epdSetup() { - epdReset(); - - drawDirection = false; - epdDrawDirection(true); - - commandBegin(CMD_POWER_SETTING); - epdSend(VDS_INTERNAL | VDG_INTERNAL); - epdSend(VCOM_VD | VGHL_16V); - epdSend(0b101011); - epdSend(0b101011); - epdSend(0b101011); - commandEnd(); - - shortCommand(CMD_POWER_ON); - epdWaitRdy(); - - commandBegin(CMD_BOOSTER_SOFT_START); - epdSend(START_10MS | STRENGTH_3 | OFF_6_58US); - epdSend(START_10MS | STRENGTH_3 | OFF_6_58US); - epdSend(START_10MS | STRENGTH_3 | OFF_6_58US); - commandEnd(); - - commandBegin(CMD_RESOLUTION_SETING); - epdSend(SCREEN_WIDTH); - epdSend(SCREEN_HEIGHT >> 8); - epdSend(SCREEN_HEIGHT & 0xFF); - commandEnd(); - - shortCommand1(CMD_POWER_OFF_SEQUENCE, FRAMES_1); - shortCommand1(CMD_TEMPERATURE_SELECT, TEMP_INTERNAL | OFFSET_0); - shortCommand1(CMD_TCON_SETTING, 0x22); - shortCommand1(CMD_VCOM_INTERVAL, 0x8d); // 0x87 - shortCommand1(CMD_PLL_CONTROL, HZ_200); - epdWaitRdy(); - shortCommand(CMD_POWER_ON); - epdWaitRdy(); -} -static uint8_t epdGetStatus() { - uint8_t sta; - commandReadBegin(0x2F); - sta = epdReadByte(); - commandReadEnd(); - return sta; -} -uint16_t epdGetBattery(void) { - return 0; -} - -static void readLut() { - commandReadBegin(0x33); - uint16_t checksum = 0; - uint16_t ident = 0; - uint16_t shortl = 0; - for (uint16_t c = 0; c < LUT_BUFFER_SIZE; c++) { - waveformbuffer[c] = epdReadByte(); - } - commandReadEnd(); -} -static uint8_t getLutSize() { - uint8_t ref = 0; - for (uint8_t c = (LUT_BUFFER_SIZE - 4); c > 16; c--) { - uint8_t check = waveformbuffer[c]; - for (uint8_t d = 1; d < 4; d++) { - if (waveformbuffer[c + d] != check) { - ref = c; - goto end; - } - } - } -end:; - return ref + 1; -} -static void lutGroupDisable(uint8_t group) { - if (dispLutSize == 7) { - memset(&(waveform7->group[group]), 0x00, 5); - } else { - memset(&(waveform10->group[group]), 0x00, 5); - } -} -static void lutGroupSpeedup(uint8_t group, uint8_t speed) { - if (dispLutSize == 7) { - for (uint8_t i = 0; i < 4; i++) { - waveform7->group[group].phaselength[i] = 1 + (waveform7->group[group].phaselength[i] / speed); - } - } else { - for (uint8_t i = 0; i < 4; i++) { - waveform10->group[group].phaselength[i] = 1 + (waveform10->group[group].phaselength[i] / speed); - } - } -} -static void lutGroupRepeat(uint8_t group, uint8_t repeat) { - if (dispLutSize == 7) { - waveform7->group[group].repeat = repeat; - } else { - waveform10->group[group].repeat = repeat; - } -} -static void lutGroupRepeatReduce(uint8_t group, uint8_t factor) { - if (dispLutSize == 7) { - waveform7->group[group].repeat = waveform7->group[group].repeat / factor; - } else { - waveform10->group[group].repeat = waveform10->group[group].repeat / factor; - } -} -void selectLUT(uint8_t lut) { - // implement alternative LUTs here. Currently just reset the watchdog to two minutes, - // to ensure it doesn't reset during the much longer bootup procedure - wdtSetResetVal(0xFF8E797F); // 120 s - wdtOn(); - return; -} - -void setWindowXY(uint16_t xstart, uint16_t xend, uint16_t ystart, uint16_t yend) { - shortCommand(CMD_PARTIAL_IN); - commandBegin(CMD_PARTIAL_WINDOW); - epdSend((xstart / 8) << 3); - epdSend(((xend / 8 - 1) << 3) | 0x07); - epdSend(ystart >> 8); - epdSend(ystart & 0xFF); - epdSend((yend - 1) >> 8); - epdSend((yend - 1) & 0xff); - epdSend(0x01); - commandEnd(); -} - -void setColorMode(uint8_t red, uint8_t bw) { - return; -} -void clearScreen() { - shortCommand(CMD_PARTIAL_OUT); - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2); - for (uint16_t c = 0; c < ((1UL * SCREEN_HEIGHT * SCREEN_WIDTH) / 8); c++) { - epdSend(0x00); - } - commandEnd(); - epdWaitRdy(); - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1); - for (uint16_t c = 0; c < ((1UL * SCREEN_HEIGHT * SCREEN_WIDTH) / 8); c++) { - epdSend(0x00); - } - commandEnd(); -} -void draw() { - shortCommand(CMD_DISPLAY_REFRESH); - epdWaitRdy(); -} -void drawNoWait() { - shortCommand(CMD_DISPLAY_REFRESH); -} -void drawWithSleep() { - shortCommand(CMD_DISPLAY_REFRESH); - uint8_t tmp_P2FUNC = P2FUNC; - uint8_t tmp_P2DIR = P2DIR; - uint8_t tmp_P2PULL = P2PULL; - uint8_t tmp_P2LVLSEL = P2LVLSEL; - P2FUNC &= 0xfd; - P2DIR |= 2; - P2PULL |= 2; - P2LVLSEL &= ~(2); - - P2CHSTA &= 0xfd; - P2INTEN = 2; - P2CHSTA &= 0xfd; - sleepForMsec(TIMER_TICKS_PER_SECOND * 120); - wdtOn(); - P2CHSTA &= 0xfd; - P2INTEN &= 0xfd; - - P2FUNC = tmp_P2FUNC; - P2DIR = tmp_P2DIR; - P2PULL = tmp_P2PULL; - P2LVLSEL = tmp_P2LVLSEL; - eepromPrvDeselect(); -} -void epdWaitRdy() { - epdBusyWait(TIMER_TICKS_PER_SECOND * 120); -} -void beginFullscreenImage() { - shortCommand(CMD_PARTIAL_OUT); - epdDrawDirection(false); - // shortCommand1(CMD_DATA_ENTRY_MODE, 3); - // setPosXY(0, 0); -} -void beginWriteFramebuffer(bool color) { - if (color == EPD_COLOR_RED) { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2); - } else { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1); - } - epdDeselect(); -} -void endWriteFramebuffer() { - commandEnd(); -} - -void loadRawBitmap(uint8_t* bmp, uint16_t x, uint16_t y, bool color) __reentrant { - // this function is very badly hurt by the switch to UC8151, taking up LOTS of valuable idata space. Only defining variables - // as static, or the function as reentrant (relegating variables to the stack) seemed to fix the idata issue. Fix me, or put me out of my misery... - - uint16_t xsize = bmp[0] / 8; - if (bmp[0] % 8) xsize++; - uint16_t ysize = bmp[1]; - uint16_t size = xsize * bmp[1]; - - // shortCommand1(CMD_DATA_ENTRY_MODE, 3); - - bmp += 2; - - uint16_t c = 0; - uint16_t curY = y; - while (1) { - if (c % xsize == 0) { - commandEnd(); - if (drawDirection) { - setWindowXY(x, x + xsize * 8, SCREEN_HEIGHT - curY - 1, SCREEN_HEIGHT - curY); - } else { - setWindowXY(x, x + xsize * 8, curY - 1, curY); - } - curY++; - if (color) { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2); - } else { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1); - } - } - epdSend(*(bmp++)); - c++; - if (!size--) break; - } - commandEnd(); - shortCommand(CMD_PARTIAL_OUT); -} -void printBarcode(const uint8_t* string, uint16_t x, uint16_t y) { - setWindowXY(x, x + 8, SCREEN_HEIGHT - y, SCREEN_HEIGHT); - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1); - struct BarcodeInfo __xdata bci = { - .str = string, - }; - while (!barcodeIsDone(&bci)) { - if (barcodeNextBar(&bci)) { - epdSend(0xFF); - } else { - epdSend(0x00); - } - } - commandEnd(); - shortCommand(CMD_PARTIAL_OUT); -} -// stuff for printing text -static void pushXFontBytesToEPD(uint8_t byte1, uint8_t byte2) { - if (epdCharSize == 1) { - uint8_t offset = 7 - (fontCurXpos % 8); - for (uint8_t c = 0; c < 8; c++) { - if (byte2 & (1 << (7 - c))) rbuffer[c] |= (1 << offset); - } - for (uint8_t c = 0; c < 8; c++) { - if (byte1 & (1 << (7 - c))) rbuffer[8 + c] |= (1 << offset); - } - fontCurXpos++; - } else { - uint8_t offset = 6 - (fontCurXpos % 8); - // double font size - for (uint8_t c = 0; c < 8; c++) { - if (byte2 & (1 << (7 - c))) { - rbuffer[c * 2] |= (3 << offset); - rbuffer[(c * 2) + 1] |= (3 << offset); - } - } - for (uint8_t c = 0; c < 8; c++) { - if (byte1 & (1 << (7 - c))) { - rbuffer[(c * 2) + 16] |= (3 << offset); - rbuffer[(c * 2) + 17] |= (3 << offset); - } - } - fontCurXpos += 2; - } - if (fontCurXpos % 8 == 0) { - // next byte, flush current byte to EPD - for (uint8_t i = 0; i < (16 * epdCharSize); i++) { - epdSend(rbuffer[i]); - } - memset(rbuffer, 0, 32); - } -} -static void bufferByteShift(uint8_t byte) { - /* - rbuffer[0] = 0; // previous value - rbuffer[1] = y%8; // offset - rbuffer[2] = 0; // current byte counter; - rbuffer[3] = 1+(epdCharsize*2); - */ - - if (rbuffer[1] == 0) { - epdSend(byte); - } else { - uint8_t offset = rbuffer[1]; - rbuffer[0] |= (byte >> offset); - epdSend(rbuffer[0]); - // epdSend(byte); - rbuffer[0] = (byte << (8 - offset)); - rbuffer[2]++; - if (rbuffer[2] == rbuffer[3]) { - epdSend(rbuffer[0]); - rbuffer[0] = 0; - rbuffer[2] = 0; - } - } -} -static void pushYFontBytesToEPD(uint8_t byte1, uint8_t byte2) { - if (epdCharSize == 2) { - for (uint8_t j = 0; j < 2; j++) { - uint8_t c = 0; - for (uint8_t i = 7; i != 255; i--) { - if (byte1 & (1 << i)) c |= (0x03 << ((i % 4) * 2)); - if ((i % 4) == 0) { - bufferByteShift(c); - c = 0; - } - } - for (uint8_t i = 7; i != 255; i--) { - if (byte2 & (1 << i)) c |= (0x03 << ((i % 4) * 2)); - if ((i % 4) == 0) { - bufferByteShift(c); - c = 0; - } - } - } - } else { - bufferByteShift(byte1); - bufferByteShift(byte2); - } -} -void writeCharEPD(uint8_t c) { - // Writes a single character to the framebuffer - bool empty = true; - for (uint8_t i = 0; i < 20; i++) { - if (font[c][i]) empty = false; - } - if (empty) { - for (uint8_t i = 0; i < 8; i++) { - if (directionY) { - pushYFontBytesToEPD(0x00, 0x00); - } else { - pushXFontBytesToEPD(0x00, 0x00); - } - } - return; - } - - uint8_t begin = 0; - while (font[c][begin] == 0x00 && font[c][begin + 1] == 0x00) { - begin += 2; - } - - uint8_t end = 20; - while (font[c][end - 1] == 0x00 && font[c][end - 2] == 0x00) { - end -= 2; - } - - for (uint8_t pos = begin; pos < end; pos += 2) { - if (directionY) { - pushYFontBytesToEPD(font[c][pos + 1], font[c][pos]); - } else { - pushXFontBytesToEPD(font[c][pos], font[c][pos + 1]); - } - } - - // spacing between characters - if (directionY) { - pushYFontBytesToEPD(0x00, 0x00); - } else { - pushXFontBytesToEPD(0x00, 0x00); - } -} - -// Print text to the EPD. Origin is top-left -void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool color) { - directionY = direction; - epdCharSize = 1 + fontsize; - if (directionY) { - uint8_t extra = 0; - - // provisions for dealing with font in Y direction, byte-unaligned - if (x % 8) { - extra = 8; - rbuffer[0] = 0; // previous value - rbuffer[1] = x % 8; // offset - rbuffer[2] = 0; // current byte counter; - rbuffer[3] = (epdCharSize * 2); - } else { - rbuffer[1] = 0; - } - - // setWindowY(y, 1); - if (epdCharSize == 2) { - setWindowXY(x, x + 32 + extra, SCREEN_HEIGHT - y, SCREEN_HEIGHT); - // setPosXY(x, y); - } else { - setWindowXY(x, x + 16 + extra, SCREEN_HEIGHT - y, SCREEN_HEIGHT); - // setPosXY(x, y); - } - // shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3 - } else { - if (epdCharSize == 2) { - x /= 2; - x *= 2; - setWindowXY(x, SCREEN_WIDTH, y, y + 32); - } else { - setWindowXY(x, SCREEN_WIDTH, y, y + 16); - } - // setPosXY(x, y); - fontCurXpos = x; - // setWindowXY(x, SCREEN_WIDTH); - // shortCommand1(CMD_DATA_ENTRY_MODE, 7); - memset(rbuffer, 0, 32); - } - - if (color) { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2); - } else { - commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1); - } -} -void epdPrintEnd() { - if (!directionY && ((fontCurXpos % 8) != 0)) { - for (uint8_t i = 0; i < (16 * epdCharSize); i++) { - epdSend(rbuffer[i]); - } - } - commandEnd(); - shortCommand(CMD_PARTIAL_OUT); - epdDrawDirection(true); -} - -extern uint8_t __xdata blockXferBuffer[]; \ No newline at end of file diff --git a/zbs243_Tag_FW/board/uc8151.h b/zbs243_Tag_FW/board/uc8151.h deleted file mode 100644 index 0bf5de3b..00000000 --- a/zbs243_Tag_FW/board/uc8151.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef _JSCREEN_H_ -#define _JSCREEN_H_ - -#include -#include - -#define epdSend spiTXByte -#define EPD_DIRECTION_X false -#define EPD_DIRECTION_Y true -#define EPD_SIZE_SINGLE false -#define EPD_SIZE_DOUBLE true -#define EPD_COLOR_RED true -#define EPD_COLOR_BLACK false -#define EPD_LOAD_CUSTOM_LUT true -#define EPD_LOAD_OTP_LUT false -#define EPD_MODE_NORMAL 0x00 -#define EPD_MODE_INVERT 0x08 -#define EPD_MODE_IGNORE 0x04 - -#define EPD_LUT_DEFAULT 0 -#define EPD_LUT_NO_REPEATS 1 -#define EPD_LUT_FAST_NO_REDS 2 -#define EPD_LUT_FAST 3 - - -#define epdSelect() \ - do { \ - P1_7 = 0; \ - } while (0) - -#define epdDeselect() \ - do { \ - P1_7 = 1; \ - } while (0) - -void epdSetup(); -void epdEnterSleep(); -uint16_t epdGetBattery(); -void epdConfigGPIO(bool setup); - -extern bool __xdata epdGPIOActive; - -void setColorMode(uint8_t red, uint8_t bw) ; -void clearWindow(bool color); -void clearScreen(); -void draw(); -void drawNoWait(); -void drawWithSleep(); -void epdWaitRdy(); - -void beginFullscreenImage(); -void beginWriteFramebuffer(bool color); -void endWriteFramebuffer(); -void loadRawBitmap(uint8_t* bmp, uint16_t x, uint16_t y, bool color) __reentrant; -void printBarcode(const uint8_t* string, uint16_t x, uint16_t y); - -void selectLUT(uint8_t lut); - -void ByteDecode(uint8_t byte); - -void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool red); -void epdPrintEnd(); - -void beginFullscreenImage(); -void beginWriteFramebuffer(bool color); - -void lutTest(); - -void epdTest(); - -// for printf.c -void writeCharEPD(uint8_t c); - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs154v033/board.c b/zbs243_Tag_FW/board/zbs154v033/board.c deleted file mode 100644 index 15cf44cc..00000000 --- a/zbs243_Tag_FW/board/zbs154v033/board.c +++ /dev/null @@ -1 +0,0 @@ -#include "../boardZBS29common.c" diff --git a/zbs243_Tag_FW/board/zbs154v033/board.h b/zbs243_Tag_FW/board/zbs154v033/board.h deleted file mode 100644 index a31ce546..00000000 --- a/zbs243_Tag_FW/board/zbs154v033/board.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_H_ -#define _BOARD_H_ - -#include -#include "proto.h" -#include "spi.h" - -#define eepromByte spiByte -#define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) -#define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) - -//eeprom map -#define EEPROM_SETTINGS_AREA_START (0x01000UL) -#define EEPROM_SETTINGS_AREA_LEN (0x03000UL) -#define EEPROM_UPDATA_AREA_START (0x04000UL) -#define EEPROM_UPDATE_AREA_LEN (0x10000UL) -#define EEPROM_IMG_START (0x14000UL) -#define EEPROM_IMG_EACH (0x02000UL) -//till end of eeprom really. do not put anything after - it will be erased at pairing time!!! -#define EEPROM_PROGRESS_BYTES (128) - -//hw types -#define HW_TYPE SOLUM_154_033 - -#include "../boardCommon.h" - - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs154v033/make.mk b/zbs243_Tag_FW/board/zbs154v033/make.mk deleted file mode 100644 index d1083181..00000000 --- a/zbs243_Tag_FW/board/zbs154v033/make.mk +++ /dev/null @@ -1,7 +0,0 @@ -FLAGS += --code-size 0xfc00 - -SOC = zbs243 - -BARCODE = datamatrix - -# 0xfc00 and not 0x10000 to leave some space for update header and updater in flash \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs154v033/screen.c b/zbs243_Tag_FW/board/zbs154v033/screen.c deleted file mode 100644 index 9494884c..00000000 --- a/zbs243_Tag_FW/board/zbs154v033/screen.c +++ /dev/null @@ -1 +0,0 @@ -#include "../ssd1619.c" diff --git a/zbs243_Tag_FW/board/zbs154v033/screen.h b/zbs243_Tag_FW/board/zbs154v033/screen.h deleted file mode 100644 index a08dfdd8..00000000 --- a/zbs243_Tag_FW/board/zbs154v033/screen.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SCREEN_H_ -#define _SCREEN_H_ - -#include -#include -#include "../ssd1619.h" - -#define SCREEN_WIDTH 152 -#define SCREEN_HEIGHT 152 - -#define SCREEN_NUM_GREYS 5 -#define SCREEN_FIRST_GREY_IDX 0 -#define SCREEN_EXTRA_COLOR_INDEX 5 //set to negative if nonexistent -#define SCREEN_TX_BPP 4 //in transit - -#define SCREEN_WIDTH_MM 27 -#define SCREEN_HEIGHT_MM 27 - -#define SCREEN_BYTE_FILL 0x44 //white - -#define SCREEN_TYPE TagScreenEink_BWR_6colors - -#define SCREEN_DATA_PASSES 2 - - -#endif diff --git a/zbs243_Tag_FW/board/zbs29_uc8151/board.c b/zbs243_Tag_FW/board/zbs29_uc8151/board.c deleted file mode 100644 index 15cf44cc..00000000 --- a/zbs243_Tag_FW/board/zbs29_uc8151/board.c +++ /dev/null @@ -1 +0,0 @@ -#include "../boardZBS29common.c" diff --git a/zbs243_Tag_FW/board/zbs29_uc8151/board.h b/zbs243_Tag_FW/board/zbs29_uc8151/board.h deleted file mode 100644 index 0a242e14..00000000 --- a/zbs243_Tag_FW/board/zbs29_uc8151/board.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_H_ -#define _BOARD_H_ - -#include -#include "proto.h" -#include "spi.h" - -#define eepromByte spiByte -#define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) -#define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) - -//eeprom map -#define EEPROM_SETTINGS_AREA_START (0x01000UL) -#define EEPROM_SETTINGS_AREA_LEN (0x03000UL) -#define EEPROM_UPDATA_AREA_START (0x04000UL) -#define EEPROM_UPDATE_AREA_LEN (0x10000UL) -#define EEPROM_IMG_START (0x14000UL) -#define EEPROM_IMG_EACH (0x04000UL) -//till end of eeprom really. do not put anything after - it will be erased at pairing time!!! -#define EEPROM_PROGRESS_BYTES (128) - -//hw types -#define HW_TYPE SOLUM_29_033 - -#include "../boardCommon.h" - - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs29_uc8151/make.mk b/zbs243_Tag_FW/board/zbs29_uc8151/make.mk deleted file mode 100644 index d1083181..00000000 --- a/zbs243_Tag_FW/board/zbs29_uc8151/make.mk +++ /dev/null @@ -1,7 +0,0 @@ -FLAGS += --code-size 0xfc00 - -SOC = zbs243 - -BARCODE = datamatrix - -# 0xfc00 and not 0x10000 to leave some space for update header and updater in flash \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs29_uc8151/screen.c b/zbs243_Tag_FW/board/zbs29_uc8151/screen.c deleted file mode 100644 index 9a7aabff..00000000 --- a/zbs243_Tag_FW/board/zbs29_uc8151/screen.c +++ /dev/null @@ -1 +0,0 @@ -#include "../uc8151.c" diff --git a/zbs243_Tag_FW/board/zbs29_uc8151/screen.h b/zbs243_Tag_FW/board/zbs29_uc8151/screen.h deleted file mode 100644 index 7a331014..00000000 --- a/zbs243_Tag_FW/board/zbs29_uc8151/screen.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _SCREEN_H_ -#define _SCREEN_H_ - -#include -#include -#include "../uc8151.h" - -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 296 - -#define SCREEN_NUM_GREYS 5 -#define SCREEN_FIRST_GREY_IDX 0 -#define SCREEN_EXTRA_COLOR_INDEX 5 //set to negative if nonexistent -#define SCREEN_TX_BPP 4 //in transit - -#define SCREEN_WIDTH_MM 29 -#define SCREEN_HEIGHT_MM 67 - -#define SCREEN_BYTE_FILL 0x44 //white - -#define SCREEN_TYPE TagScreenEink_BWR_6colors - -#define SCREEN_DATA_PASSES 2 - -#endif diff --git a/zbs243_Tag_FW/board/zbs29v033/board.c b/zbs243_Tag_FW/board/zbs29v033/board.c deleted file mode 100644 index 15cf44cc..00000000 --- a/zbs243_Tag_FW/board/zbs29v033/board.c +++ /dev/null @@ -1 +0,0 @@ -#include "../boardZBS29common.c" diff --git a/zbs243_Tag_FW/board/zbs29v033/board.h b/zbs243_Tag_FW/board/zbs29v033/board.h deleted file mode 100644 index 0a242e14..00000000 --- a/zbs243_Tag_FW/board/zbs29v033/board.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_H_ -#define _BOARD_H_ - -#include -#include "proto.h" -#include "spi.h" - -#define eepromByte spiByte -#define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) -#define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) - -//eeprom map -#define EEPROM_SETTINGS_AREA_START (0x01000UL) -#define EEPROM_SETTINGS_AREA_LEN (0x03000UL) -#define EEPROM_UPDATA_AREA_START (0x04000UL) -#define EEPROM_UPDATE_AREA_LEN (0x10000UL) -#define EEPROM_IMG_START (0x14000UL) -#define EEPROM_IMG_EACH (0x04000UL) -//till end of eeprom really. do not put anything after - it will be erased at pairing time!!! -#define EEPROM_PROGRESS_BYTES (128) - -//hw types -#define HW_TYPE SOLUM_29_033 - -#include "../boardCommon.h" - - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs29v033/make.mk b/zbs243_Tag_FW/board/zbs29v033/make.mk deleted file mode 100644 index d1083181..00000000 --- a/zbs243_Tag_FW/board/zbs29v033/make.mk +++ /dev/null @@ -1,7 +0,0 @@ -FLAGS += --code-size 0xfc00 - -SOC = zbs243 - -BARCODE = datamatrix - -# 0xfc00 and not 0x10000 to leave some space for update header and updater in flash \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs29v033/screen.c b/zbs243_Tag_FW/board/zbs29v033/screen.c deleted file mode 100644 index 9494884c..00000000 --- a/zbs243_Tag_FW/board/zbs29v033/screen.c +++ /dev/null @@ -1 +0,0 @@ -#include "../ssd1619.c" diff --git a/zbs243_Tag_FW/board/zbs29v033/screen.h b/zbs243_Tag_FW/board/zbs29v033/screen.h deleted file mode 100644 index 6569cd44..00000000 --- a/zbs243_Tag_FW/board/zbs29v033/screen.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _SCREEN_H_ -#define _SCREEN_H_ - -#include -#include -#include "../ssd1619.h" - - -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 296 - -#define SCREEN_NUM_GREYS 5 -#define SCREEN_FIRST_GREY_IDX 0 -#define SCREEN_EXTRA_COLOR_INDEX 5 //set to negative if nonexistent -#define SCREEN_TX_BPP 4 //in transit - -#define SCREEN_WIDTH_MM 29 -#define SCREEN_HEIGHT_MM 67 - -#define SCREEN_BYTE_FILL 0x44 //white - -#define SCREEN_TYPE TagScreenEink_BWR_6colors - -#define SCREEN_DATA_PASSES 2 - -#endif diff --git a/zbs243_Tag_FW/board/zbs42v033/board.c b/zbs243_Tag_FW/board/zbs42v033/board.c deleted file mode 100644 index 15cf44cc..00000000 --- a/zbs243_Tag_FW/board/zbs42v033/board.c +++ /dev/null @@ -1 +0,0 @@ -#include "../boardZBS29common.c" diff --git a/zbs243_Tag_FW/board/zbs42v033/board.h b/zbs243_Tag_FW/board/zbs42v033/board.h deleted file mode 100644 index fc2aec98..00000000 --- a/zbs243_Tag_FW/board/zbs42v033/board.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_H_ -#define _BOARD_H_ - -#include -#include "proto.h" -#include "spi.h" - -#define eepromByte spiByte -#define eepromPrvSelect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 0; __asm__("nop\nnop\nnop\n"); } while(0) -#define eepromPrvDeselect() do { __asm__("nop\nnop\nnop\n"); P1_1 = 1; __asm__("nop\nnop\nnop\n"); } while(0) - -//eeprom map -#define EEPROM_SETTINGS_AREA_START (0x01000UL) -#define EEPROM_SETTINGS_AREA_LEN (0x03000UL) -#define EEPROM_UPDATA_AREA_START (0x04000UL) -#define EEPROM_UPDATE_AREA_LEN (0x10000UL) -#define EEPROM_IMG_START (0x14000UL) -#define EEPROM_IMG_EACH (0x08000UL) -//till end of eeprom really. do not put anything after - it will be erased at pairing time!!! -#define EEPROM_PROGRESS_BYTES (128) - -//hw types -#define HW_TYPE SOLUM_42_033 - -#include "../boardCommon.h" - - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs42v033/make.mk b/zbs243_Tag_FW/board/zbs42v033/make.mk deleted file mode 100644 index d1083181..00000000 --- a/zbs243_Tag_FW/board/zbs42v033/make.mk +++ /dev/null @@ -1,7 +0,0 @@ -FLAGS += --code-size 0xfc00 - -SOC = zbs243 - -BARCODE = datamatrix - -# 0xfc00 and not 0x10000 to leave some space for update header and updater in flash \ No newline at end of file diff --git a/zbs243_Tag_FW/board/zbs42v033/screen.c b/zbs243_Tag_FW/board/zbs42v033/screen.c deleted file mode 100644 index 9494884c..00000000 --- a/zbs243_Tag_FW/board/zbs42v033/screen.c +++ /dev/null @@ -1 +0,0 @@ -#include "../ssd1619.c" diff --git a/zbs243_Tag_FW/board/zbs42v033/screen.h b/zbs243_Tag_FW/board/zbs42v033/screen.h deleted file mode 100644 index 8b8c147a..00000000 --- a/zbs243_Tag_FW/board/zbs42v033/screen.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _SCREEN_H_ -#define _SCREEN_H_ - -#include -#include -#include "../ssd1619.h" - - -#define SCREEN_WIDTH 400 -#define SCREEN_HEIGHT 300 - -#define SCREEN_NUM_GREYS 5 -#define SCREEN_FIRST_GREY_IDX 0 -#define SCREEN_EXTRA_COLOR_INDEX 5 //set to negative if nonexistent -#define SCREEN_TX_BPP 4 //in transit - -#define SCREEN_WIDTH_MM 84 -#define SCREEN_HEIGHT_MM 63 - -#define SCREEN_BYTE_FILL 0x44 //white - -#define SCREEN_TYPE TagScreenEink_BWR_6colors - -#define SCREEN_DATA_PASSES 2 - - -#endif diff --git a/zbs243_Tag_FW/buildfw.sh b/zbs243_Tag_FW/buildfw.sh old mode 100644 new mode 100755 diff --git a/zbs243_Tag_FW/cpu b/zbs243_Tag_FW/cpu new file mode 120000 index 00000000..b9d44d5c --- /dev/null +++ b/zbs243_Tag_FW/cpu @@ -0,0 +1 @@ +../zbs243_shared/cpu \ No newline at end of file diff --git a/zbs243_Tag_FW/cpu/8051/asmUtil.c b/zbs243_Tag_FW/cpu/8051/asmUtil.c deleted file mode 100644 index 37e7502e..00000000 --- a/zbs243_Tag_FW/cpu/8051/asmUtil.c +++ /dev/null @@ -1,1502 +0,0 @@ -#include "asmUtil.h" -#include "cpu.h" - - -#pragma callee_saves mathPrvU8bitswap -uint16_t mathPrvU16from2xU8(uint8_t hi, uint8_t lo) __reentrant __naked -{ - __asm__( - " mov DPH, DPL \n" - " pop B \n" - " pop A \n" - " pop DPL \n" - " push DPL \n" - " push A \n" - " push B \n" - " ret \n" - ); - (void)hi; - (void)lo; -} - -//a is hi -uint32_t mathPrvU32from4xU8(uint8_t hi, uint8_t midhi, uint8_t midlo, uint8_t lo) __reentrant __naked -{ - __asm__( - " push _R0 \n" - " mov A, #-5 \n" //point to first pushed arg (last param - lo) - " add A, sp \n" - " mov R0, A \n" - " mov A, DPL \n" - " mov DPL, @R0 \n" - " inc R0 \n" - " mov DPH, @R0 \n" - " inc R0 \n" - " mov B, @R0 \n" - " pop _R0 \n" - " ret \n" - ); - (void)hi; - (void)midhi; - (void)midlo; - (void)lo; -} - - -#pragma callee_saves mathPrvU8bitswap -uint8_t mathPrvU8bitswap(uint8_t val) __reentrant __naked -{ - __asm__( - " mov B, #8 \n" - "00003$: \n" - " xch A, DPL \n" - " rrc A \n" - " xch A, DPL \n" - " rlc A \n" - " djnz B, 00003$ \n" - " xch A, DPL \n" - " ret \n" - ); - (void)val; -} - - -#pragma callee_saves mathPrvI16Asr1 -int16_t mathPrvI16Asr1(int16_t val) __reentrant __naked -{ - __asm__( - " mov A, DPH \n" - " mov C, A.7 \n" - " rrc A \n" - " mov DPH, A \n" - " mov A, DPL \n" - " rrc A \n" - " mov DPL, A \n" - " ret \n" - ); - (void)val; -} - -#pragma callee_saves mathPrvMul8x8 -uint16_t mathPrvMul8x8(uint8_t a, uint8_t b) __reentrant __naked -{ - //return expected in DPTR, first param is in DPL, second on stack - __asm__( - //grab param into B - " pop DPH \n\t" - " pop A \n\t" - " pop B \n\t" - " push B \n\t" - " push A \n\t" - " push DPH \n\t" - - //second param into A - " mov A, DPL \n\t" - - //do the deed - " mul AB \n\t" - - //return results - " mov DPL, A \n\t" - " mov DPH, B \n\t" - - " ret \n\t" - ); - (void)a; - (void)b; -} - -#pragma callee_saves mathPrvMul16x8 -uint32_t mathPrvMul16x8(uint16_t a, uint8_t b) __reentrant __naked -{ - //return expected in A:B:DPTR, first param is in DPTR, second on stack - __asm__( - //save r0 - " push _R0 \n\t" - - //get 2nd param into a & r0 - " mov A, SP \n\t" - " add A, #-0x03 \n\t" - " mov R0, A \n\t" - " mov A, @R0 \n\t" - " mov R0, A \n\t" - - //get first param.lo into B - " mov B, DPL \n\t" - - //mul - " mul AB \n\t" - - //lower result byte is ready! - " mov DPL, A \n\t" - - //save upper in r0, get 2nd param into A - " mov A, R0 \n\t" - " mov R0, B \n\t" - - //get first param.hi into B - " mov B, DPH \n\t" - - //mul - " mul AB \n\t" - - //add in the carry from before - " add A, R0 \n\t" - - //produce middle byte - " mov DPH, A \n\t" - - //calc high byte - " mov A, B \n\t" - " addc A, #0 \n\t" - " mov B, A \n\t" - - //set high high byte to 0 (guaranteed) - " clr A \n\t" - - //get out - " pop _R0 \n\t" - " ret \n\t" - ); - (void)a; - (void)b; -} - -#pragma callee_saves mathPrvMul32x8 -uint32_t mathPrvMul32x8(uint32_t a, uint8_t b) __reentrant __naked -{ - //return expected in A:B:DPTR, first param is in DPTR, second on stack - __asm__( - //save r0 - " push _R0 \n\t" - " push _R1 \n\t" - - //save A and B - " push A \n" - " push B \n" - - //get second param into R0 - " mov A, #-6 \n" - " add A, sp \n" - " mov R0, A \n" - " mov _R0, @R0 \n" - - //low - " mov A, DPL \n" - " mov B, R0 \n" - " mul AB \n" - " mov DPL, A \n" - " mov R1, B \n" - - //mid.lo - " mov A, DPH \n" - " mov B, R0 \n" - " mul AB \n" - " add A, R1 \n" - " mov DPH, A \n" - " mov A, B \n" - " addc A, #0 \n" - " mov R1, A \n" - - //mid.hi - " pop A \n" - " mov B, R0 \n" - " mul AB \n" - " add A, R1 \n" - " xch A, B \n" - " addc A, #0 \n" - " mov R1, A \n" - - //hi - " pop A \n" - " push B \n" - " mov B, R0 \n" - " mul AB \n" - " add A, R1 \n" - " pop B \n" - - //get out - " pop _R1 \n\t" - " pop _R0 \n\t" - " ret \n\t" - ); - (void)a; - (void)b; -} - -#pragma callee_saves mathPrvMul16x16 -uint32_t mathPrvMul16x16(uint16_t a, uint16_t b) __reentrant __naked -{ - //return expected in A:B:DPTR, first param is in DPTR, second on stack (low byte was pushed first) - __asm__( - //save r0,r1,r2 - " push _R0 \n\t" - " push _R1 \n\t" - " push _R2 \n\t" - - //get 2nd param into r1:r0 - " mov A, SP \n\t" - " add A, #-0x05 \n\t" - " mov R0, A \n\t" - " mov A, @R0 \n\t" - " mov R1, A \n\t" - " dec R0 \n\t" - " mov A, @R0 \n\t" - " mov R0, A \n\t" - - //mul low bytes, save low result byte - " mov B, DPL \n\t" - " mul AB \n\t" - " push A \n\t" - - //save high byte - " mov R2, B \n\t" - - //mul p2.lo * p1.hi. add in high from the low multiplication. we know this fits in 16 bits! - " mov A, DPH \n\t" - " mov B, R0 \n\t" - " mul AB \n\t" - " add A, R2 \n\t" - " mov R0, A \n\t" //save intermediate's lo in R0 - " mov A, B \n\t" - " addc A, #0 \n\t" - " mov R2, A \n\t" //save intermediate's hi in R2 - - //mul p2.hi * p1.lo, add in intermediate result - " mov A, R1 \n\t" - " mov B, DPL \n\t" - " mul AB \n\t" - " add A, R0 \n\t" //calc intermediate's lo - " push A \n\t" //push it - " mov A, B \n\t" - " addc A, R2 \n\t" - " mov R2, A \n\t" //calc intermediate's hi in R2 - " mov A, #0 \n\t" - " addc A, #0 \n\t" //calc high byte so far - " mov R0, A \n\t" //store in R0 - - //mul high bytes - " mov A, R1 \n\t" - " mov B, DPH \n\t" - " mul AB \n\t" - " add A, R2 \n\t" - " mov R2, A \n\t" //final value for intermediate's high - " mov A, B \n\t" - " addc A, R0 \n\t" //final high value is ready - - //produce the rest of the result bytes - " mov B, R2 \n\t" - " pop DPH \n\t" - " pop DPL \n\t" - - //return - " pop _R2 \n\t" - " pop _R1 \n\t" - " pop _R0 \n\t" - " ret \n\t" - ); - (void)a; - (void)b; -} - -//pushes R0..R2, gets second param into r1:r0 -#pragma callee_saves u64_start -static void u64_start(void) __reentrant __naked -{ - __asm__( - " pop A \n" //get ret addr - " pop B \n" //get ret addr - - " push _R0 \n" - " push _R1 \n" - " push _R2 \n" - - " push B \n" //re-push ret addr - " push A \n" - - " mov a, #0xf8 \n" // DPTR = pushed_arg - " add a, sp \n" - " mov R1, a \n" - " mov a, @R1 \n" - " mov R0, a \n" - " inc R1 \n" - " mov a, @R1 \n" - " mov R1, a \n" - - " ret \n" - ); -} - -//jump to this, do not call it -//does not clobber anything -#pragma callee_saves u64_end -static void u64_end(void) __reentrant __naked -{ - __asm__( - " pop _R2 \n" - " pop _R1 \n" - " pop _R0 \n" - " ret \n" - ); -} - -#pragma callee_saves mathPrvSwapDptrR1R0 -void mathPrvSwapDptrR1R0(void) __reentrant __naked -{ - __asm__( - " xch A, R1 \n\t" - " xch A, DPH \n\t" - " xch A, R1 \n\t" - " xch A, R0 \n\t" - " xch A, DPL \n\t" - " xch A, R0 \n\t" - " ret \n\t" - ); -} - -#pragma callee_saves u64_copy -void u64_copy(uint64_t __xdata *dst, const uint64_t __xdata *src) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)dst; - (void)src; -} - -void u64_copyFromCode(uint64_t __xdata *dst, const uint64_t __code *src) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " clr a \n" - " movc a, @a+dptr \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)dst; - (void)src; -} - -#pragma callee_saves u64_add -void u64_add(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - " clr C \n" - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " mov _R2, a \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " addc a, R2 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)lhsP; - (void)rhsP; -} - -#pragma callee_saves u64_and -void u64_and(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " mov _R2, a \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " anl a, R2 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)lhsP; - (void)rhsP; -} - -#pragma callee_saves u64_sub -void u64_sub(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - " clr C \n" - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " mov _R2, a \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " subb a, R2 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)lhsP; - (void)rhsP; -} - -#pragma callee_saves u64_isLt -__bit u64_isLt(const uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - " clr C \n" - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " mov _R2, a \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " subb a, R2 \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)lhsP; - (void)rhsP; -} - -#pragma callee_saves u64_isEq -__bit u64_isEq(const uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " mov _R2, a \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " xrl a, R2 \n" - " jnz 00004$ \n" - " djnz b, 00003$ \n" - - " setb C \n" - " ljmp _u64_end \n" - - "00004$: \n" - " clr C \n" - " ljmp _u64_end \n" - ); - (void)lhsP; - (void)rhsP; -} - -//c is set, A is what to add to each limb -#pragma callee_saves u64_incdec -static void u64_incdec(uint64_t __xdata *dst) __reentrant __naked -{ - __asm__( - " xch A, R0 \n" - " push A \n" - " mov b, #8 \n" //repeat 8 times: - "00003$: \n" - " movx a, @dptr \n" - " addc a, R0 \n" - " movx @dptr, a \n" - " inc dptr \n" - " djnz b, 00003$ \n" - " pop _R0 \n" - " ret \n" - ); - (void)dst; -} - -#pragma callee_saves u64_inc -void u64_inc(uint64_t __xdata *dst) __reentrant __naked -{ - __asm__( - " setb C \n" - " clr A \n" - " ljmp _u64_incdec \n" - ); - (void)dst; -} - -#pragma callee_saves u64_dec -void u64_dec(uint64_t __xdata *dst) __reentrant __naked -{ - __asm__( - " clr C \n" - " mov A, #0xFF \n" - " ljmp _u64_incdec \n" - ); - (void)dst; -} - - -#pragma callee_saves xMemSet -void xMemSet(void __xdata* mem, uint8_t val, uint16_t num) __reentrant __naked -{ - __asm__( - " push _R0 \n" - " push _R1 \n" - - " mov A, #-6 \n" - " add A, sp \n" - " mov R0, A \n" - " mov A, @R0 \n" //num.lo - " mov B, A \n" - " inc R0 \n" - " mov _R1, @R0 \n" //num.hi - " orl A, R1 \n" //zero check - " jz 00002$ \n" //num is R1:B - " inc R0 \n" - " mov _R0, @R0 \n" //val - "00003$: \n" - " mov A, R0 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " mov A, #0xff \n" - " add A, B \n" - " mov B, A \n" - " mov A, #0xff \n" - " addc A, R1 \n" - " mov _R1, A \n" - " orl A, B \n" - " jnz 00003$ \n" - "00002$: \n" - " pop _R1 \n" - " pop _R0 \n" - " ret \n" - ); - - (void)mem; - (void)val; - (void)num; -} - -#pragma callee_saves xMemEqual -__bit xMemEqual(const void __xdata* memA, const void __xdata* memB, uint8_t num) __reentrant __naked -{ - __asm__( - " push _R0 \n" - " push _R1 \n" - " push _R2 \n" - - " mov a, #-7 \n" - " add a, sp \n" - " mov R1, a \n" - " mov A, @R1 \n" - " setb C \n" //equal if len is zero - " jz 00004$ \n" - " mov B, A \n" - " inc R1 \n" - " mov _R0, @R1 \n" - " inc R1 \n" - " mov _R1, @R1 \n" - " clr C \n" - "00003$: \n" - " movx a, @dptr \n" - " mov _R2, a \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " xrl a, R2 \n" - " jnz 00004$ \n" - " djnz b, 00003$ \n" - " setb C \n" - "00004$: \n" - " pop _R2 \n" - " pop _R1 \n" - " pop _R0 \n" - " ret \n" - ); - - (void)memA; - (void)memB; - (void)num; -} - -#pragma callee_saves xMemCopy -void xMemCopy(void __xdata* dst, const void __xdata* src, uint16_t num) __reentrant __naked -{ - __asm__( - " push _R0 \n" - " push _R1 \n" - " push _R2 \n" - - " mov A, #-8 \n" - " add A, sp \n" - " mov R1, A \n" - " mov A, @R1 \n" - " mov B, A \n" - " inc R1 \n" - " mov _R2, @R1 \n" //R2:B is length - " orl A, R2 \n" - " jz 00004$ \n" //handle zero length - " inc R1 \n" - " mov _R0, @R1 \n" - " inc R1 \n" - " mov _R1, @R1 \n" //R1:R0 is src - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " mov A, #0xff \n" - " add A, B \n" - " mov B, A \n" - " mov A, #0xff \n" - " addc A, R2 \n" - " mov _R2, A \n" - " orl A, B \n" - " jnz 00003$ \n" - "00004$: \n" - " pop _R2 \n" - " pop _R1 \n" - " pop _R0 \n" - " ret \n" - ); - - (void)dst; - (void)src; - (void)num; -} - -#pragma callee_saves xMemCopyShort -void xMemCopyShort(void __xdata* dst, const void __xdata* src, uint8_t num) __reentrant __naked -{ - __asm__( - " push _R0 \n" - " push _R1 \n" - " push _R2 \n" - - " mov a, #-7 \n" - " add a, sp \n" - " mov R1, a \n" - " mov A, @R1 \n" - " jz 00004$ \n" - " mov B, A \n" - " inc R1 \n" - " mov _R0, @R1 \n" - " inc R1 \n" - " mov _R1, @R1 \n" - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx @dptr, a \n" - " inc dptr \n" - " djnz b, 00003$ \n" - "00004$: \n" - " pop _R2 \n" - " pop _R1 \n" - " pop _R0 \n" - " ret \n" - ); - - (void)dst; - (void)src; - (void)num; -} - -#pragma callee_saves xStrLen -uint16_t xStrLen(const char __xdata *str) __reentrant __naked -{ - __asm__( - " push DPH \n" - " push DPL \n" - "00003$: \n" - " movx a, @dptr \n" - " jz 00002$ \n" - " inc dptr \n" - " sjmp 00003$ \n" - "00002$: \n" - " clr C \n" - " mov A, DPL \n" - " pop B \n" - " subb A, B \n" - " mov DPL, A \n" - " mov A, DPH \n" - " pop B \n" - " subb A, B \n" - " mov DPH, A \n" - " ret \n" - ); - - (void)str; -} - -#pragma callee_saves static mathPrvDivMod32x16 -static uint32_t mathPrvDivMod32x16(uint32_t num, uint16_t denom) __reentrant __naked -{ - //PSW.5 determines if to produce quotient (0) or remainder(1) - - __asm__( - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - " push A \n" - " push B \n" - " push DPH \n" - " push DPL \n" - " mov R1, sp \n" //R1: point to bottom byte of numerator - - //get denom -> B:R0 - " mov A, #-10 \n" - " add A, sp \n" - " mov R0, A \n" //R0 = &denom.hi - " mov B, @R0 \n" //B = denom.hi - " dec R0 \n" - " mov _R0, @R0 \n" //R0 = denom.lo - - //shift it off (in B:R0), record how many iters we'll need (in DPL), generate proper top 8 bits for result mask (in R3:R2) - " mov _R2, #1 \n" - " mov _R3, #0 \n" - " mov DPL, #17 \n" - "00002$: \n" - " mov C, B.7 \n" - " jc 00003$ \n" - - " clr C \n" - " mov A, R0 \n" - " rlc A \n" - " mov R0, A \n" - " mov A, B \n" - " rlc A \n" - " mov B, A \n" - - " clr C \n" - " mov A, R2 \n" - " rlc A \n" - " mov R2, A \n" - " mov A, R3 \n" - " rlc A \n" - " mov R3, A \n" - - " inc DPL \n" - " sjmp 00002$ \n" - "00003$: \n" - - " clr A \n" - - //push result_mask to stack - " push _R3 \n" - " push _R2 \n" - " push A \n" - " push A \n" - " mov R2, sp \n" //R2: point to bottom byte of result_mask - - //push denom.shifted to stack - " push B \n" - " push _R0 \n" - " push A \n" - " push A \n" - " mov R0, sp \n" //R0: point to bottom byte of denom.shifted - - //push result to stack - " push A \n" - " push A \n" - " push A \n" - " push A \n" - " mov R3, sp \n" //R3: point to bottom byte of result - - //loop-divide - "00088$: \n" - - // check if denom.shifted >= num - " push _R0 \n" - " push _R1 \n" - " clr C \n" - " mov DPH, #4 \n" - "00001$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " dec R1 \n" - " subb A, B \n" - " djnz DPH, 00001$ \n" - " pop _R1 \n" - " pop _R0 \n" - " jc 00099$ \n" //no? skip this round - - //subtract - " push _R0 \n" - " push _R1 \n" - " clr C \n" - " mov DPH, #4 \n" - "00004$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " subb A, B \n" - " mov @R1, A \n" - " dec R1 \n" - " djnz DPH, 00004$ \n" - //keep r0 & r1 pushed - - //set bit in result - //r0 & r1 still pushed - " mov _R0, _R2 \n" - " mov _R1, _R3 \n" - " mov DPH, #4 \n" - "00005$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " orl A, B \n" - " mov @R1, A \n" - " dec R1 \n" - " djnz DPH, 00005$ \n" - " pop _R1 \n" - " pop _R0 \n" - - //set up next iteration - "00099$: \n" - - // shift denom right one (pointer ends up where needed) - " mov A, #0xfc \n" - " add A, R0 \n" - " mov R0, A \n" - " clr C \n" - " mov DPH, #4 \n" - "00006$: \n" - " inc R0 \n" - " mov A, @R0 \n" - " rrc A \n" - " mov @R0, A \n" - " djnz DPH, 00006$ \n" - - // shift result mask right one - " push _R0 \n" - " mov A, #0xfc \n" - " add A, R2 \n" - " mov R0, A \n" - " clr C \n" - " mov DPH, #4 \n" - "00007$: \n" - " inc R0 \n" - " mov A, @R0 \n" - " rrc A \n" - " mov @R0, A \n" - " djnz DPH, 00007$ \n" - " pop _R0 \n" - - //check on loop limit - " djnz DPL, 00088$ \n" - - //we're done. undo the terrible things we've done to the stack and get the result - - //quotient return? - " jb PSW.5, 00009$ \n" - //return quotient - " pop DPL \n" - " pop DPH \n" - " pop B \n" - " pop _R0 \n" - "00009$: \n" - - //now clear up the rest - " mov A, #-12 \n" - " add A, sp \n" - " mov sp, A \n" - - //remainder return? - " jnb PSW.5, 00010$ \n" - //return quotient - " pop DPL \n" - " pop DPH \n" - " pop B \n" - " pop _R0 \n" - "00010$: \n" - - " mov A, R0 \n" - - //pop off regs - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - - " ret \n" - - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves static mathPrvDiv32x16 -uint32_t mathPrvDiv32x16(uint32_t num, uint16_t denom) __reentrant __naked -{ - __asm__( - " clr PSW.5 \n" - " ljmp _mathPrvDivMod32x16 \n" - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves static mathPrvDiv32x16 -uint16_t mathPrvMod32x16(uint32_t num, uint16_t denom) __reentrant __naked -{ - __asm__( - " setb PSW.5 \n" - " ljmp _mathPrvDivMod32x16 \n" - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves mathPrvDiv32x8 -uint32_t mathPrvDiv32x8(uint32_t num, uint8_t denom) __reentrant __naked -{ - __asm__( - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - " push A \n" - " push B \n" - " push DPH \n" - " push DPL \n" - " mov R1, sp \n" //R1: point to bottom byte of numerator - - //get denom -> B - " mov A, #0xf6 \n" - " add A, sp \n" - " mov R0, A \n" - " mov B, @R0 \n" - - //shift it off (in B), record how many iters we'll need (in DPL), generate proper top 8 bits for result mask (in A) - " mov A, #1 \n" - " mov DPL, #25 \n" - "00002$: \n" - " mov C, B.7 \n" - " jc 00003$ \n" - " rl A \n" - " xch A, B \n" - " rl A \n" - " xch A, B \n" - " inc DPL \n" - " sjmp 00002$ \n" - "00003$: \n" - - //push result_mask to stack - " push A \n" - " clr A \n" - " push A \n" - " push A \n" - " push A \n" - " mov R2, sp \n" //R2: point to bottom byte of result_mask - - //push denom.shifted to stack - " push B \n" - " push A \n" - " push A \n" - " push A \n" - " mov R0, sp \n" //R0: point to bottom byte of denom.shifted - - //push result to stack - " push A \n" - " push A \n" - " push A \n" - " push A \n" - " mov R3, sp \n" //R3: point to bottom byte of result - - //loop-divide - "00088$: \n" - - // check if denom.shifted >= num - " push _R0 \n" - " push _R1 \n" - " clr C \n" - " mov DPH, #4 \n" - "00001$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " dec R1 \n" - " subb A, B \n" - " djnz DPH, 00001$ \n" - " pop _R1 \n" - " pop _R0 \n" - " jc 00099$ \n" //no? skip this round - - //subtract - " push _R0 \n" - " push _R1 \n" - " clr C \n" - " mov DPH, #4 \n" - "00004$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " subb A, B \n" - " mov @R1, A \n" - " dec R1 \n" - " djnz DPH, 00004$ \n" - //keep r0 & r1 pushed - - //set bit in result - //r0 & r1 still pushed - " mov _R0, _R2 \n" - " mov _R1, _R3 \n" - " mov DPH, #4 \n" - "00005$: \n" - " mov B, @R0 \n" - " dec R0 \n" - " mov A, @R1 \n" - " orl A, B \n" - " mov @R1, A \n" - " dec R1 \n" - " djnz DPH, 00005$ \n" - " pop _R1 \n" - " pop _R0 \n" - - //set up next iteration - "00099$: \n" - - // shift denom right one (pointer ends up where needed) - " mov A, #0xfc \n" - " add A, R0 \n" - " mov R0, A \n" - " clr C \n" - " mov DPH, #4 \n" - "00006$: \n" - " inc R0 \n" - " mov A, @R0 \n" - " rrc A \n" - " mov @R0, A \n" - " djnz DPH, 00006$ \n" - - // shift result mask right one - " push _R0 \n" - " mov A, #0xfc \n" - " add A, R2 \n" - " mov R0, A \n" - " clr C \n" - " mov DPH, #4 \n" - "00007$: \n" - " inc R0 \n" - " mov A, @R0 \n" - " rrc A \n" - " mov @R0, A \n" - " djnz DPH, 00007$ \n" - " pop _R0 \n" - - //check on loop limit - " djnz DPL, 00088$ \n" - - //we're done. undo the terrible things we've done to the stack - - //first, get the result - " pop DPL \n" - " pop DPH \n" - " pop B \n" - " pop _R0 \n" - - //now clear up the rest - " mov A, #-12 \n" - " add A, sp \n" - " mov sp, A \n" - - " mov A, R0 \n" - - //pop off regs - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - - " ret \n" - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves mathPrvDivMod16x8 -static uint16_t mathPrvDivMod16x8(uint16_t num, uint8_t denom) __reentrant __naked -{ - __asm__( - " push _R6 \n" - " push _R5 \n" - " push _R4 \n" - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - - //get denom -> B - " mov A, #-9 \n" - " add A, sp \n" - " mov R0, A \n" - " mov B, @R0 \n" - - //shift it off (in B), record how many iters we'll need (in R4), generate proper top 8 bits for result mask (in A) - " mov A, #1 \n" - " mov R4, #9 \n" - "00002$: \n" - " mov C, B.7 \n" - " jc 00003$ \n" - " rl A \n" - " xch A, B \n" - " rl A \n" - " xch A, B \n" - " inc R4 \n" - " sjmp 00002$ \n" - "00003$: \n" - - //result mask in R3:R2 \n" - " mov R3, A \n" - " clr A \n" - " mov R2, A \n" - - //quotient in R1:R0 \n" - " mov R1, B \n" - " mov R0, A \n" - - //iter count in B \n" - " mov B, DPL \n" - - //result in R6:R5 - " mov R5, A \n" - " mov R6, A \n" - - //loop-divide - "00088$: \n" - - // check if denom.shifted >= num - " clr C \n" - " mov A, DPL \n" - " subb A, R0 \n" - " mov A, DPH \n" - " subb A, R1 \n" - " jc 00099$ \n" //no? skip this round - - //subtract - " clr C \n" - " mov A, DPL \n" - " subb A, R0 \n" - " mov DPL, A \n" - " mov A, DPH \n" - " subb A, R1 \n" - " mov DPH, A \n" - - //set bit in result - " mov A, R2 \n" - " orl A, R5 \n" - " mov R5, A \n" - " mov A, R3 \n" - " orl A, R6 \n" - " mov R6, A \n" - - //set up next iteration - "00099$: \n" - - // shift denom right one - " clr C \n" - " mov A, R1 \n" - " rrc A \n" - " mov R1, A \n" - " mov A, R0 \n" - " rrc A \n" - " mov R0, A \n" - - // shift result mask right one - " clr C \n" - " mov A, R3 \n" - " rrc A \n" - " mov R3, A \n" - " mov A, R2 \n" - " rrc A \n" - " mov R2, A \n" - - //check on loop limit - " djnz R4, 00088$ \n" - - //we're done - produce the result (it is already in DPT Rif we want modulus) - " jb PSW.5, 00098$ \n" - " mov DPL, R5 \n" - " mov DPH, R6 \n" - "00098$: \n" - - //pop off regs - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - " pop _R4 \n" - " pop _R5 \n" - " pop _R6 \n" - - " ret \n" - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves mathPrvDiv16x8 -uint16_t mathPrvDiv16x8(uint16_t num, uint8_t denom) __reentrant __naked -{ - __asm__( - " clr PSW.5 \n" - " ljmp _mathPrvDivMod16x8 \n" - ); - - (void)num; - (void)denom; -} - -#pragma callee_saves mathPrvMod16x8 -uint8_t mathPrvMod16x8(uint16_t num, uint8_t denom) __reentrant __naked -{ - __asm__( - " setb PSW.5 \n" - " ljmp _mathPrvDivMod16x8 \n" - ); - - (void)num; - (void)denom; -} - -char charsPrvDerefAndIncGenericPtr(const char * __xdata* __xdata str) __naked -{ - __asm__( - " movx A, @DPTR \n" - " push A \n" - " add A, #1 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " movx A, @DPTR \n" - " push A \n" - " addc A, #0 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " movx A, @DPTR \n" - " pop _DPH \n" - " pop _DPL \n" - " jz 00001$ \n" //check for xdata, taken if yes - " cjne A, #0x60, 00002$ \n" //check for pdata, taken if no - - //pdata - " push _R0 \n" - " mov R0, DPL \n" - " movx A, @R0 \n" - " pop _R0 \n" - " mov DPL, A \n" - " ret \n" - - "00002$: \n" - " jc 00003$ \n" //check for idata. taken if yes - - //code - " clr A \n" - " movc A, @A+DPTR \n" - " mov DPL, A \n" - " ret \n" - - //xdata - "00001$: \n" - " movx A, @DPTR \n" - " mov DPL, A \n" - " ret \n" - - //idata - "00003$: \n" - " push _R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " pop _R0 \n" - " mov DPL, A \n" - " ret \n" - ); - - (void)str; -} - -void mathPrvCopyPostinc(uint32_t __xdata *dst, uint32_t __xdata *src) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - - " mov b, #4 \n" //repeat 4 times: - " setb C \n" - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " mov r2, a \n" - " addc a, #0 \n" - " movx @dptr, a \n" - " mov a, r2 \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx @dptr, a \n" - " inc dptr \n" - - " djnz b, 00003$ \n" - - " ljmp _u64_end \n" - ); - (void)dst; - (void)src; -} - -__bit xMemEqual4(const void __xdata* memA, const void __xdata* memB) __reentrant __naked -{ - __asm__( - " lcall _u64_start \n" //get second pointer into R1:R0 - " mov b, #4 \n" //repeat 4 times: - " clr C \n" - "00003$: \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " mov r2, a \n" - " inc dptr \n" - " lcall _mathPrvSwapDptrR1R0 \n" - " movx a, @dptr \n" - " inc dptr \n" - " xrl a, r2 \n" - " jnz 00004$ \n" - " djnz b, 00003$ \n" - " setb C \n" - "00004$: \n" - - " ljmp _u64_end \n" - ); - - (void)memA; - (void)memB; -} - -__bit u32minusU16(uint32_t __xdata *u32, uint16_t u16) __naked __reentrant -{ - __asm__( - " lcall _u64_start \n" - " clr C \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " subb A, R0 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " subb A, R1 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " subb A, #0 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " subb A, #0 \n" - " ljmp _u64_end \n" - ); - (void)u32; - (void)u16; -} - -__bit u32plusU16(uint32_t __xdata *u32, uint16_t u16) __naked __reentrant -{ - __asm__( - " lcall _u64_start \n" - " clr C \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " addc A, R0 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " addc A, R1 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " addc A, #0 \n" - " movx A, @DPTR \n" - " inc DPTR \n" - " addc A, #0 \n" - " ljmp _u64_end \n" - ); - (void)u32; - (void)u16; -} - -uint8_t u32Nonzero(uint32_t __xdata *u32) __naked __reentrant -{ - __asm__( - " mov B, #4 \n" - "00001$: \n" - " movx A, @DPTR \n" - " jnz 00002$ \n" - " inc DPTR \n" - " djnz B, 00001$ \n" - "00002$: \n" - " mov DPL, A \n" - " ret \n" - ); - (void)u32; -} - -__bit i32Negative(uint32_t __xdata *u32) __naked __reentrant -{ - __asm__( - " inc DPTR \n" - " inc DPTR \n" - " inc DPTR \n" - " movx A, @DPTR \n" - " rlc A \n" - " ret \n" - ); - (void)u32; -} - - diff --git a/zbs243_Tag_FW/cpu/8051/cpu.c b/zbs243_Tag_FW/cpu/8051/cpu.c deleted file mode 100644 index 254cdec1..00000000 --- a/zbs243_Tag_FW/cpu/8051/cpu.c +++ /dev/null @@ -1 +0,0 @@ -//nothing diff --git a/zbs243_Tag_FW/cpu/8051/cpu.h b/zbs243_Tag_FW/cpu/8051/cpu.h deleted file mode 100644 index f15e18f6..00000000 --- a/zbs243_Tag_FW/cpu/8051/cpu.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _CPUi_H_ -#define _CPUi_H_ - -#include - - -typedef uint16_t uintptr_near_t; - -#define VERSIONMARKER __at (0x008b) - -#define irqsOn() IEN_EA = 1 - - -#include "soc.h" - - - -#endif diff --git a/zbs243_Tag_FW/cpu/8051/make.mk b/zbs243_Tag_FW/cpu/8051/make.mk deleted file mode 100644 index 4482165d..00000000 --- a/zbs243_Tag_FW/cpu/8051/make.mk +++ /dev/null @@ -1,9 +0,0 @@ -FLAGS += -Icpu/8051 - -FLAGS += -mmcs51 --std-c2x --opt-code-size --peep-file cpu/8051/peep.def --fomit-frame-pointer -SOURCES += cpu/8051/asmUtil.c -CC = sdcc -TARGETS = main.ihx main.bin -OBJFILEEXT = rel - - diff --git a/zbs243_Tag_FW/cpu/8051/peep.def b/zbs243_Tag_FW/cpu/8051/peep.def deleted file mode 100644 index 6d3e47b9..00000000 --- a/zbs243_Tag_FW/cpu/8051/peep.def +++ /dev/null @@ -1,115 +0,0 @@ -replace restart { - movx a,@dptr - mov %1,a - inc dptr - movx a,@dptr - mov %2,a - inc dptr - movx a,@dptr - mov %3,a - inc dptr - movx a,@dptr - mov %4,a - clr c - mov a,%1 - subb a,#%5 - mov a,%2 - subb a,#%6 - mov a,%3 - subb a,#%7 - mov a,%4 - subb a,#%8 - DISABLED XXX -} by { - clr c - movx a,@dptr - mov %1,a - subb a,#%5 - inc dptr - movx a,@dptr - mov %2,a - subb a,#%6 - inc dptr - movx a,@dptr - mov %3,a - subb a,#%7 - inc dptr - movx a,@dptr - mov %4,a - subb a,#%8 ;dmitrygr - optimize dumb xdata handling -} if notSame(%1 %2),notSame(%1 %3),notSame(%1 %4),notSame(%2 %3),notSame(%3 %4),notSame(%3 %4) - -replace { - mov b,%1 - mov a,%2 - div ab - mov %3,b - mov b,%1 - mov a,%2 - div ab -} by { - mov b,%1 - mov a,%2 - div ab - mov %3,b ; Peephole dmitrygr.0006 - why divide twice? -} if notSame(%1 %3),notSame(%2 %3) - - -replace { - movx @dptr,a - movx a,@dptr -} by { - movx @dptr,a ; Peephole dmitrygr.0005 - SRSLY, WTF? -} - -replace restart { - mov r%1,%2 - mov r%3,%4 - mov r%5,%6 - mov r%7,%8 - push %9 - push %10 - mov %2,r%1 - mov %4,r%3 - mov %6,r%5 - mov %8,r%7 -} by { - mov r%1,%2 - mov r%3,%4 - mov r%5,%6 - mov r%7,%8 - push %9 - push %10; Peephole dmitrygr.000 - pointless shuffling when passing 32 from return to param -} if notSame(%1 %3),notSame(%1 %5),notSame(%1 %7),notSame(%3 %5),notSame(%3 %7),notSame(%5 %7),notSame(%2 %4),notSame(%2 %6),notSame(%2 %8),notSame(%4 %6),notSame(%4 %8),notSame(%6 %8) - - -replace restart { -%1: - mov dptr,#%2 - movx a,@dptr - mov %3,a - cjne %3,#%4,%1 -} by { - mov dptr,#%2 -%1: - movx a,@dptr - cjne a,#%4,%1 ; Peephole dmitrygr.001 - tighter loop, write extra var just once (i wish we knew if it were dead so we could write it zero times) - mov %3,a -} if labelRefCount(%1 1) - -replace restart { - mov a,#%1 - add a,#0x00 - mov %2,a - mov a,%3 -} by { - mov %2,#%1 - mov a,%3 - clr c ; Peephole dmitrygr.002 - remove pointless A-machinations -} - -replace restart { - add a,#0x00 -} by { - clr c ; Peephole dmitrygr.003 - adding zero is pointless, just clears C -} diff --git a/zbs243_Tag_FW/cpu/8051/printf.c b/zbs243_Tag_FW/cpu/8051/printf.c deleted file mode 100644 index 37223677..00000000 --- a/zbs243_Tag_FW/cpu/8051/printf.c +++ /dev/null @@ -1,799 +0,0 @@ -#include "printf.h" - -#include -#include -#include - -#include "board.h" -#include "screen.h" -#include "uart.h" -#include "zbs243.h" - -typedef void (*StrFormatOutputFunc)(uint32_t param /* low byte is data, bits 24..31 is char */) __reentrant; - -static __idata __at(0x00) unsigned char R0; -static __idata __at(0x01) unsigned char R1; -static __idata __at(0x02) unsigned char R2; -static __idata __at(0x03) unsigned char R3; -static __idata __at(0x04) unsigned char R4; -static __idata __at(0x05) unsigned char R5; -static __idata __at(0x06) unsigned char R6; -static __idata __at(0x07) unsigned char R7; - -static uint8_t __xdata mCvtBuf[18]; - -// callback must be reentrant and callee_saves -#pragma callee_saves prvPrintFormat -void prvPrintFormat(StrFormatOutputFunc formatF, uint16_t formatD, const char __code *fmt, va_list vl) __reentrant __naked { - // formatF is in DPTR - // sp[0..-1] is return addr - // sp[-2..-3] is formatD - // sp[-4..-5] is fmt - // sp[-6] is vl - - __asm__( - " push _R7 \n" - " push DPH \n" // push formatF - " push DPL \n" - " mov _R7, sp \n" // save place on stack where we stashed it so we can call it easily - " push _R4 \n" - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - - " mov A, #-12 \n" - " add A, sp \n" - " mov R0, A \n" - // R0 now points to pushed params, for large values, we see high bytes first - // to get next byte, we need to DECEREMENT R0 - - " mov DPH, @R0 \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" - " dec R0 \n" - - // now format string is in DPTR, and R0 points to the top byte of whatever was in the first param - - // main loop: get a byte of the format string - "00001$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - // if zero, we're done - " jz 00098$ \n" - // if not '%', print it - " cjne A, #'%', 00097$ \n" - - // we got a percent sign - init state for format processing - " mov R4, #0 \n" // bit flags: - // 0x01 = '*' = pointer provided instead of value (integers only) - // 0x02 = '0' = zero-pad (for numbers only) - // 0x04 = have pad-to length - // 0x08 = long - // 0x10 = long long - // 0x20 = signed print requested. also: need to print a negative (used to reuse hex printing for decimal once converted to bcd) - " mov R2, #0 \n" // padLen - - // loop for format string ingestion - "00002$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - // if zero, we're done - " jz 00098$ \n" - // check for percent sign - " cjne A, #'%', 00003$ \n" - // fallthrough to print it and go read next non-format byte - // print a char in A, go read next format byte - "00097$: \n" - " lcall 00060$ \n" - " sjmp 00001$ \n" - - // exit label - placed for easy jumping to - "00098$: \n" - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - " pop _R4 \n" - " pop DPL \n" - " pop DPH \n" - " pop _R7 \n" - " ret \n" - - // continue to process format string - handle %c - "00003$: \n" - " cjne A, #'c', 00004$ \n" - " dec R0 \n" // param is pushed as int (16 bits) - " mov A, @R0 \n" - " dec R0 \n" - " sjmp 00097$ \n" // print and go read next non-format byte - - // continue to process format string - handle %m - "00004$: \n" - " mov R3, A \n" - " orl A, #0x20 \n" - " cjne A, #'m', 00008$ \n" - - // sort out which hexch charset to use - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R1, A \n" - - // go, do - " push DPH \n" - " push DPL \n" - " lcall 00090$ \n" // read the short (__xdata) pointer - >DPTR - " mov R4, #8 \n" // byteSel - "00005$: \n" - " push DPH \n" - " push DPL \n" - " mov A, R4 \n" - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0 \n" - " mov DPH, A \n" - " movx A, @DPTR \n" - " mov R2, A \n" - " swap A \n" - " mov R3, #2 \n" - "00006$: \n" - " anl A, #0x0f \n" - " add A, R1 \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " lcall 00060$ \n" - " mov A, R2 \n" - " djnz R3, 00006$ \n" - " pop DPL \n" - " pop DPH \n" - " djnz R4, 00007$ \n" - // done with mac addr - - "00055$: \n" - " pop DPL \n" - " pop DPH \n" - " sjmp 00001$ \n" - // print colon and contimue mac addr printing - "00007$: \n" - " mov A, #':' \n" - " lcall 00060$ \n" - " sjmp 00005$ \n" - - // continue to process format string - handle '*' - "00008$: \n" - " mov A, R3 \n" - " cjne A, #'*', 00009$ \n" - " cjne R2, #0, 00097$ \n" // only valid when no length/padding has been specified yet, else invalid specifier - " mov A, #0x01 \n" //"pointer mode" - "00010$: \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00002$ \n" // get next format specifier now - - // continue to process format string - handle '0' - "00009$: \n" - " cjne A, #'0', 00011$ \n" - " cjne R2, #0, 00011$ \n" // setting "zero pad" is only valid when pad length is zero - " mov A, #0x06 \n" //"have pad length" | "zero-pad" - " sjmp 00010$ \n" // orr A into R4, get next format specifier now - - // continue to process format string - handle '1'...'9' - "00011$: \n" - " mov R3, A \n" - " add A, #-'0' \n" - " jnc 00012$ \n" // now 0..9 are valid - " add A, #-10 \n" - " jc 00012$ \n" - " add A, #10 \n" // get it back into 1..9 range - " mov R3, A \n" - " mov A, #10 \n" - " mov B, R2 \n" - " mul AB \n" - " add A, R3 \n" - " mov R2, A \n" - " mov A, #0x04 \n" //"have pad length" - " sjmp 00010$ \n" // orr A into R4, get next format specifier now - - // continue to process format string - handle 'l' - "00012$: \n" - " cjne R3, #'l', 00014$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " jz 00013$ \n" // no "long" yet? set that - // have long - set long log - " mov A, #0x10 \n" //"long long" - " sjmp 00010$ \n" // orr A into R4, get next format specifier now - // first 'l' - set long - "00013$: \n" - " mov A, #0x08 \n" //"long" - " sjmp 00010$ \n" // orr A into R4, get next format specifier now - - // continue to process format string - handle 's' - "00014$: \n" - " cjne R3, #'s', 00025$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " push DPH \n" - " push DPL \n" - " jnz 00015$ \n" - " lcall 00091$ \n" // get and resolve generic pointer into DPTR - " sjmp 00016$ \n" - "00015$: \n" // get short pointer into DPTR, record that it is to XRAM - " clr PSW.5 \n" - " clr PSW.1 \n" - " lcall 00090$ \n" - "00016$: \n" // pointer to string now in DPTR - // we have the string pointer in {DPTR,PSW}, let's see if we have padding to do - " mov A, R4 \n" - " anl A, #0x04 \n" - " jnz 00018$ \n" - // print string with no length restrictions - "00017$: \n" - " lcall 00095$ \n" - " jz 00055$ \n" - " lcall 00060$ \n" - " sjmp 00017$ \n" - - // print string with length restrictions and/or padding - "00018$: \n" - " cjne R2, #0, 00019$ \n" // verify reqested len was not zero - " sjmp 00055$ \n" - - "00019$: \n" - " lcall 00095$ \n" - " jz 00020$ \n" - " lcall 00060$ \n" - " djnz R2, 00019$ \n" - // we get here if we ran out of allowable bytes - we're done then - " ljmp 00055$ \n" - - // just a trampoline for range issues - "00035$: \n" - " ljmp 00036$ \n" - - // we need to pad with spaces - "00020$: \n" - " mov A, #' ' \n" - " lcall 00060$ \n" - " djnz R2, 00020$ \n" - " ljmp 00055$ \n" - - // continue to process format string - handle 'x'/'X' - "00025$: \n" - " mov A, R3 \n" - " orl A, #0x20 \n" - " cjne A, #'x', 00035$ \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B - // save it - - "00070$: \n" - " push DPH \n" - " push DPL \n" - - // sort out how long it would be if printed, first get a pointer to the highest - " mov A, B \n" - " rl A \n" - " mov R1, A \n" - " rr A \n" - " add A, #0xff \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - "00026$: \n" - " lcall 00079$ \n" - " anl A, #0xf0 \n" - " jnz 00028$ \n" - " dec R1 \n" - " lcall 00079$ \n" - " jnz 00028$ \n" - " dec R1 \n" - // dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00027$ \n" - " dec DPH \n" - "00027$: \n" - " djnz B, 00026$ \n" - - // we now know how many digits the number is (in R1), except that it has "0" if the number if zero, we cannot have that - "00028$: \n" - " cjne R1, #0, 00029$ \n" - " inc R1 \n" - "00029$: \n" // we now finally have the full length of the digits - - // if the number is negative (happens when we're printing decimals) - // the length of it is one more, also in case of zero-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00051$ \n" - " inc R1 \n" // the length is one more - " mov A, R4 \n" - " anl A, #02 \n" // if zero-padding, the negative comes now - " jz 00051$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00051$: \n" - - // sort out if we need padding at all and if there is space - " mov A, R4 \n" - " anl A, #0x04 \n" - " jz 00031$ \n" // no padding requested - // padding was requested len is in R2 - " mov A, R2 \n" - " clr C \n" - " subb A, R1 \n" - " jc 00031$ \n" // pad-to len < number_len -> no padding needed - " jz 00031$ \n" // pad-to len == number_len -> no padding needed - " mov R2, A \n" - - // sort out which character to use -> DPL - " mov A, R4 \n" // fancy way to create space/zero as needed - " anl A, #0x02 \n" - " swap A \n" - " rr A \n" - " add A, #0x20 \n" - " mov DPL, A \n" - - // pad! - "00030$: \n" - " mov A, DPL \n" - " lcall 00060$ \n" - " djnz R2, 00030$ \n" - "00031$: \n" - - // if the number is negative (happens when we're printing decimals) - // we made the length of it is one more, which we need to undo - // also in case of space-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00052$ \n" - " dec R1 \n" // the length is one less than we had increased it to - " mov A, R4 \n" - " anl A, #02 \n" // if space-padding, the negative comes now - " jnz 00052$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00052$: \n" - - // time to print the number itself - // sort out which hexch charset to use -> R2 - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R2, A \n" - // re-get the number pointer - " pop DPL \n" - " pop DPH \n" - // currently DPTR points to the number low byte, R1 is now many digits we expect to print, R2 is the charset selection, R4 and R3 are free - // let's calculate how many bytes we expect to process -> R4 - " mov A, R1 \n" - " inc A \n" - " clr C \n" - " rrc A \n" - " mov R4, A \n" - // let's repoint DPTR to the first byte we'll print in (remember we print 2 digits per byte) - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - - // decide if we need to print just a nibble of the high byte or the whole thing. Free up R1 - " mov A, R1 \n" - " anl A, #0x01 \n" - " jz 00032$ \n" - - // we're printing just the low nibble of the first byte - set up for it - " lcall 00079$ \n" - " mov R1, #1 \n" - " sjmp 00033$ \n" - - // print loop - "00032$: \n" - " lcall 00079$ \n" - " mov R1, #2 \n" - " mov R3, A \n" - " swap A \n" - "00033$: \n" - " anl A, #0x0f \n" - " add A, R2 \n" - " push DPH \n" - " push DPL \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " pop DPL \n" - " pop DPH \n" - " lcall 00060$ \n" - " mov A, R3 \n" - " djnz R1, 00033$ \n" - - // dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00034$ \n" - " dec DPH \n" - "00034$: \n" - " djnz R4, 00032$ \n" - - // done! - " ljmp 00055$ \n" - - // continue to process format string - handle 'd' - "00036$: \n" - " cjne R3, #'d', 00037$ \n" - " mov A, #0x20 \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00040$ \n" - - // continue to process format string - handle 'u' - "00037$: \n" - " cjne R3, #'u', 00038$ \n" - " sjmp 00040$ \n" - - // no more format strings exist that we can handle - bail - "00038$: \n" - " ljmp 00001$ \n" - - // handle decimal printing - "00040$: \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B - " push B \n" - - // copy the number to the double-dabble storage at proper offset (0 for u64, 4 for u32, 6 for u16) - // we do this so that the dabble area always starts at the same place... - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov R1, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov R3, A \n" - "00041$: \n" - " lcall 00079$ \n" - " inc DPTR \n" - " lcall 00086$ \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " lcall 00086$ \n" - " djnz B, 00041$ \n" - // leave DPTR pointing to dabble storage, past the number - " lcall 00086$ \n" - - // we now have the top byte of the number in A, good time to check for negatives, if needed - " mov B, A \n" - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00050$ \n" // unsigned printing requested - " mov A, B \n" - " anl A, #0x80 \n" - " jnz 00043$ \n" // is negative - we need to invert, 0x20 bit in R1 stays - // positive - 0x20 bit in R1 needs to go - " mov A, R4 \n" - " anl A, #~0x20 \n" - " mov R4, A \n" - " sjmp 00050$ \n" - - // we need to negate the number - // but first we need a pointer to it, and its size - "00043$: \n" - " pop B \n" - " push B \n" - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov DPL, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov DPH, A \n" - - // ok, now we are ready to negate it - " clr C \n" - "00049$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " clr A \n" - " subb A, R1 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00049$ \n" - - // zero out the rest of the storage (10 bytes) - "00050$: \n" - " mov B, #10 \n" - " clr A \n" - "00042$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00042$ \n" - - // calculate number of dabble steps - " pop A \n" - " swap A \n" - " rr A \n" - " mov R3, A \n" - - // do the thing - "00044$: \n" - - // dabble (10 iters for simplicity) - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - "00046$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " anl A, #0x0f \n" - " add A,#-0x05 \n" - " mov A, R1 \n" - " jnc 00047$ \n" - " add A, #0x03 \n" - "00047$: \n" - " mov R1, A \n" - " anl A, #0xf0 \n" - " add A,#-0x50 \n" - " mov A, R1 \n" - " jnc 00048$ \n" - " add A, #0x30 \n" - "00048$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00046$ \n" - - // double (18 iters for simplicity) - " mov DPTR, #_mCvtBuf \n" - " clr C \n" - " mov B, #18 \n" - "00045$: \n" - " movx A, @DPTR \n" - " rlc A \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00045$ \n" - - " djnz R3, 00044$ \n" - - // dabbling is done, print it now using hex routine - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - " clr PSW.5 \n" // it is now for sure in XRAM - " ljmp 00070$ \n" - - // read short pointer from param stack - "00090$: \n" - " mov DPH, @R0 \n" - "00093$: \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " ret \n" - - // read and increment pointer of the type provided by 00091$ (in {DPTR,PSW}) into A. clobber nothing - "00095$: \n" - " jb PSW.5, 00066$ \n" - " jb PSW.1, 00067$ \n" - // XRAM - " movx A, @DPTR \n" - " inc DPTR \n" - " ret \n" - // CODE - "00066$: \n" - " clr A \n" - " movc A, @A+DPTR \n" - " inc DPTR \n" - " ret \n" - // IRAM - "00067$: \n" - " mov DPH, R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " mov R0, DPH \n" - " inc DPL \n" - " ret \n" - - // resolve generic pointer on param stack to an pointer in DPTR and flags in PSW.5 and PSW.1 - // PSW.5 will be 0 and PSW.1 will be 0 for XRAM (PDATA goes here too) - // PSW.5 will be 1 and PSW.1 will be 0 for CODE - // PSW.5 will be 0 and PSW.1 will be 1 for IRAM - "00091$: \n" - " clr PSW.5 \n" - " clr PSW.1 \n" - " mov A, @R0 \n" - " dec R0 \n" - " jz 00090$ \n" // 0x00: pointer type: xdata - " xrl A, #0x80 \n" - " jz 00094$ \n" // 0x80: pointer type: code - " xrl A, #0xc0 \n" - " jz 00092$ \n" // 0x40: pointer type: idata - // pdata - " mov DPH, _XPAGE \n" - " sjmp 00093$ \n" - // idata - "00092$: \n" - " setb PSW.1 \n" - " sjmp 00093$ \n" - // code - "00094$: \n" - " setb PSW.5 \n" - " sjmp 00090$ \n" - - // read the pointer of the type that 00080$ returns (in DPTR) into A. clobber nothing - "00079$: \n" - " jnb PSW.5, 00078$ \n" - " push _R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " pop _R0 \n" - " ret \n" - "00078$: \n" - " movx A, @DPTR \n" - " ret \n" - - // get pointer to a number, might be pushed or might be pointed to, size might vary. return pointer to number's LOW byte in DPTR - "00080$: \n" - " mov A, R4 \n" - " anl A, #0x01 \n" - " jnz 00083$ \n" - // param is itself on stack - now we care about size, but either way, PSW.5 will be 1 - " setb PSW.5 \n" - " mov B, #0 \n" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00081$ \n" - " anl A, #0x10 \n" - " jz 00082$ \n" - // long long (8 bytes) \n" - " setb B.2 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - // long (4 bytes) - "00082$: \n" - " setb B.1 \n" - " dec R0 \n" - " dec R0 \n" - // int (2 bytes) \n" - "00081$: \n" - " setb B.0 \n" - " dec R0 \n" - " mov DPL, R0 \n" - " dec R0 \n" - " inc B \n" - " ret \n" - // pointer it on stack itself, number is in xram, but we still need to provide the length - "00083$: \n" - " clr PSW.5 \n" // mark as "in xram" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00084$ \n" - " anl A, #0x10 \n" - " jz 00085$ \n" - // long long - " mov B, #8 \n" - " ljmp 00090$ \n" - // long - "00085$: \n" - " mov B, #4 \n" - " ljmp 00090$ \n" - // int - "00084$: \n" - " mov B, #2 \n" - " ljmp 00090$ \n" - - // swap R3:R1 <-> DPH:DPL - "00086$: \n" - " xch A, DPH \n" - " xch A, R3 \n" - " xch A, DPH \n" - " xch A, DPL \n" - " xch A, R1 \n" - " xch A, DPL \n" - " ret \n" - - /* putchar func - called via call. char is in A, R7 has pointer to stack as needed - can clobber B, CANNOT clobber DPTR - a mess because...8051 - */ - "00060$: \n" - " push DPH \n" - " push DPL \n" - " push _R1 \n" - " push _R0 \n" - " mov _R0, R7 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov DPH, @R0 \n" // DPTR is now func ptr - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " mov _R1, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" // R1:R0 is now "formatD" - " lcall 00061$ \n" // to set ret addr - " pop _R0 \n" - " pop _R1 \n" - " pop DPL \n" - " pop DPH \n" - " ret \n" - "00061$: \n" - " push DPL \n" - " push DPH \n" - " mov DPL, _R0 \n" - " mov DPH, _R1 \n" - " ret \n" - - "00099$: \n" - " .ascii \"01234567\" \n" - " .ascii \"89ABCDEF\" \n" - " .ascii \"01234567\" \n" - " .ascii \"89abcdef\" \n"); - (void)fmt; - (void)vl; - (void)formatF; - (void)formatD; -} - -#pragma callee_saves prPrvPutchar -static void prPrvPutchar(uint32_t data) __reentrant { - char ch = data >> 24; - if (ch == '\n') - uartTx('\r'); - uartTx(ch); -} -#pragma callee_saves epdPutchar -static void epdPutchar(uint32_t data) __reentrant { - char ch = data >> 24; - writeCharEPD(ch); -} - -void pr(const char __code *fmt, ...) __reentrant { - va_list vl; - va_start(vl, fmt); - prvPrintFormat(prPrvPutchar, 0, fmt, vl); - va_end(vl); -} - -void epdpr(const char __code *fmt, ...) __reentrant { - va_list vl; - va_start(vl, fmt); - prvPrintFormat(epdPutchar, 0, fmt, vl); - va_end(vl); -} - -#pragma callee_saves prPrvPutS -static void prPrvPutS(uint32_t data) __reentrant { - char __xdata *__idata *strPP = (char __xdata *__idata *)data; - char ch = data >> 24; - - *(*strPP)++ = ch; -} - -void spr(char __xdata *out, const char __code *fmt, ...) __reentrant { - char __xdata *outStart = out; - - va_list vl; - - va_start(vl, fmt); - prvPrintFormat(prPrvPutS, (uint16_t)&out, fmt, vl); - va_end(vl); - - *out = 0; -} diff --git a/zbs243_Tag_FW/cpu/8051/random.c b/zbs243_Tag_FW/cpu/8051/random.c deleted file mode 100644 index 63e7be62..00000000 --- a/zbs243_Tag_FW/cpu/8051/random.c +++ /dev/null @@ -1,261 +0,0 @@ -#include "cpu.h" - - -struct RngState { - uint64_t a, b; - uint32_t c; -}; - -static struct RngState mState = {0, }; - -void rndSeed(uint8_t seedA, uint8_t seedB) -{ - mState.a = seedA; - mState.b = seedB; -} - -#pragma callee_saves rndPrvGen32 -static uint32_t rndPrvGen32(struct RngState __xdata *state) __naked -{ - // //xorshift128p with a small midification ( " retval ^= ++ c" ) - // - // state->a ^= state->a << 23; - // state->a ^= state->a >> 17; - // state->a ^= state->b; - // t = state->a; - // state->a = state->b; - // state->b >>= 26 - // state->b = t ^ state->b; - // state->c++; - // - // return (state->a + state->b) >> 32 + state->c; - - __asm__( - - " push _R0 \n" - - //state->a ^= state->a << 23 - " mov A, #5 \n" //point to a[5] - " lcall 00091$ \n" - " movx A, @DPTR \n" - " mov PSW.5, A.0 \n" - " mov B, #5 \n" - " mov A, #-1 \n" - "00001$: \n" - " lcall 00089$ \n" - " movx A, @DPTR \n" - " mov C, PSW.5 \n" - " rrc A \n" - " mov PSW.5, C \n" - " inc DPTR \n" - " inc DPTR \n" - " inc DPTR \n" - " mov _R0, A \n" - " movx A, @DPTR \n" - " xrl A, R0 \n" - " movx @DPTR, A \n" - " mov A, #-4 \n" - " djnz B, 00001$ \n" - - //repoint DPTR to state->a.8 - " mov A, #5 \n" - " lcall 00091$ \n" - - //state->a ^= state->a >> 17 - - " clr PSW.5 \n" - " mov B, #6 \n" - "00002$: \n" - " mov A, #-1 \n" - " lcall 00089$ \n" - " movx A, @DPTR \n" - " mov C, PSW.5 \n" - " rrc A \n" - " mov PSW.5, C \n" - " push A \n" - " djnz B, 00002$ \n" - - " mov A, #-2 \n" - " lcall 00089$ \n" - - " mov B, #6 \n" - "00003$: \n" - " movx A, @DPTR \n" - " pop _R0 \n" - " xrl A, R0 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00003$ \n" - - " inc DPTR \n" //point to B - " inc DPTR \n" - - // pushed_t = state->a ^ state->b //last pushe di nhigh byte - // state->a = state->b; - - " mov B, #8 \n" - "00004$: \n" - " movx A, @DPTR \n" - " mov _R0, A \n" //r0 = b[i] - " mov A, #-8 \n" - " lcall 00089$ \n" - " movx A, @DPTR \n" //a = a[i] - " xrl A, R0 \n" //a = a[i] ^ b[i] - " push A \n" - " mov A, R0 \n" - " movx @DPTR, A \n" - " mov A, #9 \n" - " lcall 00091$ \n" - " djnz B, 00004$ \n" - - //repoint DPTR to state->b.3 - " mov A, #-5 \n" - " lcall 00089$ \n" - - //state->b >>= 24 (top 3 bytes are garbage) - " mov B, #5 \n" - "00005$: \n" - " movx A, @DPTR \n" - " mov _R0, A \n" - " mov A, #-3 \n" - " lcall 00089$ \n" - " mov A, R0 \n" - " movx @DPTR, A \n" - " mov A, #4 \n" - " lcall 00091$ \n" - " djnz B, 00005$ \n" - - //state->b >>= 2 - " mov A, #-4 \n" - " lcall 00089$ \n" - - " mov B, #2 \n" - "00006$: \n" - " mov _R0, #5 \n" - " clr PSW.5 \n" - "00007$: \n" - " movx A, @DPTR \n" - " mov C, PSW.5 \n" - " rrc A \n" - " mov PSW.5, C \n" - " movx @DPTR, A \n" - " mov A, #-1 \n" - " lcall 00089$ \n" - " djnz _R0, 00007$ \n" - " mov A, #5 \n" - " lcall 00091$ \n" - " djnz B, 00006$ \n" - - //reset DPTR to end of state->b - " mov A, #3 \n" - " lcall 00091$ \n" - - //state->b = t ^ state->b - " mov B, #3 \n" - "00008$: \n" - " pop A \n" - " movx @DPTR, A \n" - " mov A, #-1 \n" - " lcall 00089$ \n" - " djnz B, 00008$ \n" - - " mov B, #5 \n" - "00009$: \n" - " movx A, @DPTR \n" - " pop _R0 \n" - " xrl A, R0 \n" - " movx @DPTR, A \n" - " mov A, #-1 \n" - " lcall 00089$ \n" - " djnz B, 00009$ \n" - - " mov A, #9 \n" - " lcall 00091$ \n" - - //state->c++ - " mov B, #4 \n" - " setb C \n" - "00010$: \n" - " movx A, @DPTR \n" - " addc A, #0 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00010$ \n" - - " mov A, #-16 \n" //point to top 32 bits of A - " lcall 00089$ \n" - - // push (state->a + state->b) >> 32 ^ state->c - " mov B, #4 \n" - " clr PSW.5 \n" - "00011$: \n" - " movx A, @DPTR \n" - " mov _R0, A \n" - " mov A, #8 \n" - " lcall 00091$ \n" - " movx A, @DPTR \n" - " mov C, PSW.5 \n" - " addc A, R0 \n" - " mov PSW.5, C \n" - " mov _R0, A \n" - " mov A, #4 \n" - " lcall 00091$ \n" - " movx A, @DPTR \n" - " xrl A, R0 \n" - " push A \n" - " mov A, #-11 \n" - " lcall 00089$ \n" - " djnz B, 00011$ \n" - - //pop result (pop it large to small) - " pop A \n" - " pop B \n" - " pop DPH \n" - " pop DPL \n" - - " pop _R0 \n" - " ret \n" - - //sub from DPTR - "00089$: \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, #0xff \n" - " addc A, DPH \n" - " mov DPH, A \n" - " ret \n" - - //add to DPTR - "00091$: \n" - " add A, DPL \n" - " mov DPL, A \n" - " clr A \n" - " addc A, DPH \n" - " mov DPH, A \n" - " ret \n" - ); - - (void)state; -} - -uint32_t rndGen32(void) __naked -{ - __asm__( - " mov DPTR, #_mState \n" - " ljmp _rndPrvGen32 \n" - ); -} - -uint8_t rndGen8(void) __naked -{ - __asm__( - " lcall _rndGen32 \n" - " rr A \n" - " xrl A, B \n" - " rr A \n" - " xrl A, DPH \n" - " rr A \n" - " xrl DPL, A \n" - " ret \n" - ); -} diff --git a/zbs243_Tag_FW/eeprom.c b/zbs243_Tag_FW/eeprom.c deleted file mode 100644 index ab01bbc7..00000000 --- a/zbs243_Tag_FW/eeprom.c +++ /dev/null @@ -1,324 +0,0 @@ -#include "asmUtil.h" -#include "screen.h" -#include "eeprom.h" -#include "printf.h" -#include "board.h" -#include "cpu.h" - -static uint32_t __xdata mEepromSize; -static uint8_t __xdata mOpcodeErz4K = 0, mOpcodeErz32K = 0, mOpcodeErz64K = 0; - -//extern uint8_t __xdata* tempBuffer; -uint8_t __xdata tempBufferE[320] = {0}; - -uint32_t eepromGetSize(void) -{ - return mEepromSize; -} - -void eepromReadStart(uint32_t addr) __reentrant -{ - eepromPrvSelect(); - eepromByte(0x03); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); -} - -void eepromRead(uint32_t addr, void __xdata *dstP, uint16_t len) __reentrant -{ - uint8_t __xdata *dst = (uint8_t __xdata*)dstP; - - eepromPrvSelect(); - eepromByte(0x03); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); - - while (len--) - *dst++ = eepromByte(0); - eepromPrvDeselect(); -} - -static void eepromPrvSimpleCmd(uint8_t cmd) -{ - eepromPrvSelect(); - eepromByte(cmd); - eepromPrvDeselect(); -} - -static bool eepromPrvBusyWait(void) -{ - uint8_t val; - - eepromPrvSelect(); - eepromByte(0x05); - while ((val = eepromByte(0x00)) & 1); - eepromPrvDeselect(); - - return true; -} - -static bool eepromWriteLL(uint32_t addr, const void __xdata *srcP, uint16_t len) -{ - const uint8_t __xdata *src = (const uint8_t __xdata*)srcP; - - eepromPrvSimpleCmd(0x06); - - eepromPrvSelect(); - eepromByte(0x02); - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr & 0xff); - - while (len--) - eepromByte(*src++); - eepromPrvDeselect(); - - return eepromPrvBusyWait(); -} - -void eepromDeepPowerDown(void) -{ - eepromPrvSimpleCmd(0xb9); -} - -static void eepromPrvWakeFromPowerdown(void) -{ - eepromPrvSimpleCmd(0xab); -} - -#pragma callee_saves eepromPrvSfdpRead -static void eepromPrvSfdpRead(uint16_t ofst, uint8_t __xdata *dst, uint8_t len) -{ - eepromPrvSelect(); - eepromByte(0x5a); //cmd - eepromByte(0); //addr - eepromByte(ofst >> 8); - eepromByte(ofst); - eepromByte(0x00); //dummy - while(len--) - *dst++ = eepromByte(0); - eepromPrvDeselect(); -} - -__bit eepromInit(void) -{ - uint8_t __xdata buf[8]; - uint8_t i, nParamHdrs; - - eepromPrvWakeFromPowerdown(); - - //process SFDP - - eepromPrvSfdpRead(0, buf, 8); - if (buf[0] != 0x53 || buf[1] != 0x46 || buf[2] != 0x44 || buf[3] != 0x50 || buf[7] != 0xff) { - pr("SFDP: header not found\n"); - - __bit valid = false; - - //try manual ID for chips we know of - eepromPrvSelect(); - eepromByte(0x90); - eepromByte(0x00); - eepromByte(0x00); - eepromByte(0x00); - if (eepromByte(0) == 0xc2) { //old macronix chips - valid = true; - mOpcodeErz4K = 0x20; - switch (eepromByte(0)) { - case 0x05: //MX25V512 - mEepromSize = 0x00010000ul; - break; - - case 0x12: //MX25V4005 - mEepromSize = 0x00080000ul; - break; - - default: - valid = false; - break; - } - } - eepromPrvDeselect(); - - return valid; - } - if (buf[5] != 0x01) { - pr("SFDP: version wrong: %u.%d\n", buf[5], buf[4]); - return false; - } - nParamHdrs = buf[6]; - if (nParamHdrs == 0xff) //that case is very unlikely and we just do not care - nParamHdrs--; - - //now we need to find the JEDEC parameter table header - for (i = 0; i <= nParamHdrs; i++) { - - eepromPrvSfdpRead(mathPrvMul8x8(i, 8) + 8, buf, 8); - if (buf[0] == 0x00 && buf[2] == 0x01 && buf[3] >= 9) { - - uint8_t j; - - eepromPrvSfdpRead(*(uint16_t __xdata*)(buf + 4), tempBufferE, 9 * 4); - if ((tempBufferE[0] & 3) != 1) { - pr("SFDP: no 4K ERZ\n"); - break; - } - if (!(tempBufferE[0] & 0x04)) { - pr("SFDP: no large write buf\n"); - break; - } - if ((tempBufferE[2] & 0x06)) { - pr("SFDP: addr.len != 3\n"); - break; - } - - if (!tempBufferE[1] || tempBufferE[1] == 0xff) { - pr("SFDP: 4K ERZ opcode invalid\n"); - break; - } - mOpcodeErz4K = tempBufferE[1]; - - if (tempBufferE[7] & 0x80) { - - pr("SFDP: device too big\n"); - break; - } - else { - - uint8_t t; - - if (t = tempBufferE[7]) - mEepromSize = 0x00200000UL; - else if (t = tempBufferE[6]) - mEepromSize = 0x00002000UL; - else if (t = tempBufferE[5]) - mEepromSize = 0x00000020UL; - else { - pr("SFDP: device so small?!\n"); - break; - } - - while (t) { - mEepromSize <<= 1; - t >>= 1; - } - } - - //get erase opcodes - for (j = 0x1c; j < 0x24; j += 2) { - uint8_t instr = tempBufferE[j + 1]; - - if (!instr || instr == 0xff) - continue; - - switch (tempBufferE[j]) { - case 0x0c: - if (mOpcodeErz4K != instr) { - pr("4K ERZ opcode disagreement\n"); - return false; - } - break; - - case 0x0f: //32K erase - mOpcodeErz32K = instr; - break; - - case 0x10: //64K erase - mOpcodeErz64K = instr; - break; - } - } - - /* - pr("EEPROM accepted\n"); - pr(" ERZ opcodes: \n"); - if (mOpcodeErz4K) - pr(" 4K: %02xh\n", mOpcodeErz4K); - if (mOpcodeErz32K) - pr(" 32K: %02xh\n", mOpcodeErz32K); - if (mOpcodeErz64K) - pr(" 64K: %02xh\n", mOpcodeErz64K); - pr(" Size: 0x%*08lx\n", (uint16_t)&mEepromSize); - */ - return true; - } - } - - pr("SFDP: no JEDEC table of expected version found\n"); - return false; -} - -bool eepromWrite(uint32_t addr, const void __xdata *srcP, uint16_t len) __reentrant -{ - const uint8_t __xdata *src = (const uint8_t __xdata*)srcP; - - while (len) { - - uint16_t lenNow = EEPROM_WRITE_PAGE_SZ - (addr & (EEPROM_WRITE_PAGE_SZ - 1)); - - if (lenNow > len) - lenNow = len; - - if (!eepromWriteLL(addr, src, lenNow)) - return false; - - addr += lenNow; - src += lenNow; - len -= lenNow; - } - return true; -} - -bool eepromErase(uint32_t addr, uint16_t nSec) __reentrant -{ - uint8_t now; - - if (((uint16_t)addr) & 0x0fff) - return false; - - for (;nSec; nSec -= now) { - - eepromPrvSimpleCmd(0x06); - eepromPrvSelect(); - - if (nSec >= 16 && !(uint16_t)addr && mOpcodeErz64K) { //erase 64K - - eepromByte(mOpcodeErz64K); - now = 16; - } - else if (nSec >= 8 && !(((uint16_t)addr) & 0x7fff) && mOpcodeErz32K) { //erase 32K - - eepromByte(mOpcodeErz32K); - now = 8; - } - else { //erase 4K - - eepromByte(mOpcodeErz4K); - now = 1; - } - - eepromByte(addr >> 16); - eepromByte(addr >> 8); - eepromByte(addr); - eepromPrvDeselect(); - - if (!eepromPrvBusyWait()) - return false; - - addr += mathPrvMul16x8(EEPROM_ERZ_SECTOR_SZ, now); - } - - return true; -} - -void eepromOtpModeEnter(void) -{ - eepromPrvSimpleCmd(0xb1); -} - -void eepromOtpModeExit(void) -{ - eepromPrvSimpleCmd(0xc1); -} \ No newline at end of file diff --git a/zbs243_Tag_FW/eeprom.c b/zbs243_Tag_FW/eeprom.c new file mode 120000 index 00000000..a36061b4 --- /dev/null +++ b/zbs243_Tag_FW/eeprom.c @@ -0,0 +1 @@ +../zbs243_shared/eeprom.c \ No newline at end of file diff --git a/zbs243_Tag_FW/eeprom.h b/zbs243_Tag_FW/eeprom.h deleted file mode 100644 index 59f36984..00000000 --- a/zbs243_Tag_FW/eeprom.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _EEPROM_H_ -#define _EEPROM_H_ - -#include -#include - -#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment -#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment - -//device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that - -__bit eepromInit(void); -void eepromOtpModeEnter(void); -void eepromOtpModeExit(void); - -#pragma callee_saves eepromRead -void eepromRead(uint32_t addr, void __xdata *dst, uint16_t len) __reentrant; - -#pragma callee_saves eepromWrite -bool eepromWrite(uint32_t addr, const void __xdata *src, uint16_t len) __reentrant; - -#pragma callee_saves eepromErase -bool eepromErase(uint32_t addr, uint16_t numSectors) __reentrant; - -void eepromDeepPowerDown(void); - -#pragma callee_saves eepromGetSize -uint32_t eepromGetSize(void); - -//this is for firmware update use -void eepromReadStart(uint32_t addr) __reentrant; - -//structures -#define EEPROM_IMG_INPROGRESS (0x7fffffffUL) -#define EEPROM_IMG_VALID (0x494d4721UL) -#include "board.h" - -struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them - uint64_t version; - uint32_t validMarker; - uint32_t size; - uint8_t dataType; - uint32_t id; - - //image data here - //we pre-erase so progress can be calculated by finding the first non-0xff byte -}; - - - -#endif diff --git a/zbs243_Tag_FW/eeprom.h b/zbs243_Tag_FW/eeprom.h new file mode 120000 index 00000000..4ebb90df --- /dev/null +++ b/zbs243_Tag_FW/eeprom.h @@ -0,0 +1 @@ +../zbs243_shared/eeprom.h \ No newline at end of file diff --git a/zbs243_Tag_FW/font.h b/zbs243_Tag_FW/font.h deleted file mode 100644 index 3dece553..00000000 --- a/zbs243_Tag_FW/font.h +++ /dev/null @@ -1,258 +0,0 @@ -static const uint8_t __code font[256][20]={ // https://raw.githubusercontent.com/basti79/LCD-fonts/master/10x16_vertikal_MSB_1.h -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00 -{0xE0,0x01,0x30,0x03,0x50,0x02,0x28,0x05,0x28,0x04,0x28,0x04,0x28,0x05,0x50,0x02,0x30,0x03,0xE0,0x01}, // 0x01 -{0xE0,0x01,0xF0,0x03,0xB0,0x03,0xD8,0x06,0xD8,0x07,0xD8,0x07,0xD8,0x06,0xB0,0x03,0xF0,0x03,0xE0,0x01}, // 0x02 -{0x00,0x3E,0x80,0x7F,0xE0,0x7F,0xF0,0x7F,0xF8,0x3F,0xF8,0x3F,0xF0,0x7F,0xE0,0x7F,0x80,0x7F,0x00,0x3E}, // 0x03 -{0x00,0x01,0x80,0x03,0xC0,0x0F,0xE0,0x1F,0xF8,0x7F,0xF0,0x1F,0xE0,0x0F,0xC0,0x07,0x80,0x03,0x00,0x01}, // 0x04 -{0x80,0x03,0xC0,0x07,0xC0,0x07,0xC0,0x3F,0xF8,0x7F,0xB8,0x7F,0xC0,0x3F,0xC0,0x07,0xC0,0x07,0x80,0x03}, // 0x05 -{0x80,0x03,0xC0,0x07,0xC0,0x0F,0xC0,0x1F,0xF8,0x3F,0xB8,0x7F,0xC0,0x1F,0xC0,0x0F,0xC0,0x07,0x80,0x03}, // 0x06 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A -{0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x2E,0xE0,0x71,0x00,0x70,0x00,0x18}, // 0x0B -{0x00,0x00,0x00,0x1E,0x20,0x21,0xA0,0x40,0xF8,0x40,0xA0,0x40,0xA0,0x41,0x00,0x21,0x00,0x1E,0x00,0x00}, // 0x0C -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D -{0x06,0x00,0x0E,0x00,0x0E,0x00,0xFC,0x1F,0x00,0x18,0x30,0x10,0x70,0x30,0x70,0x20,0xE0,0x7F,0x00,0x00}, // 0x0E -{0x00,0x01,0xC0,0x0F,0xC0,0x04,0x40,0x08,0x60,0x18,0x40,0x08,0x40,0x04,0xC0,0x0C,0xC0,0x0B,0x00,0x01}, // 0x0F -{0xF8,0x0F,0xF0,0x07,0xF0,0x07,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xC0,0x01,0xC0,0x01,0x80,0x00,0x80,0x00}, // 0x10 -{0x80,0x00,0x80,0x00,0xC0,0x01,0xC0,0x01,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xF0,0x07,0xF0,0x07,0xF8,0x0F}, // 0x11 -{0x00,0x00,0x00,0x00,0x08,0x10,0x04,0x20,0xFE,0x7F,0x04,0x20,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x12 -{0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x13 -{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0x14 -{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0x15 -{0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00}, // 0x16 -{0x00,0x00,0x00,0x00,0x11,0x10,0x09,0x20,0xFD,0x7F,0x09,0x20,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x17 -{0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x20,0xFE,0x7F,0x00,0x20,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x18 -{0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0xFE,0x7F,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x19 -{0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1A -{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00}, // 0x1B -{0x00,0x00,0xF8,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00}, // 0x1C -{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1D -{0x08,0x00,0x18,0x00,0x78,0x00,0xF8,0x01,0xF8,0x03,0xF8,0x0F,0xF8,0x03,0xF8,0x00,0x38,0x00,0x08,0x00}, // 0x1E -{0x00,0x08,0x00,0x0C,0x00,0x0F,0xC0,0x0F,0xE0,0x0F,0xF8,0x0F,0xE0,0x0F,0x80,0x0F,0x00,0x0E,0x00,0x08}, // 0x1F -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21 -{0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22 -{0x80,0x00,0x98,0x04,0xE0,0x05,0x80,0x1E,0x98,0x64,0xE0,0x05,0x80,0x1E,0x80,0x64,0x80,0x04,0x00,0x00}, // 0x23 -{0x00,0x00,0x00,0x00,0x18,0x38,0x08,0x64,0x08,0x42,0xFC,0xFF,0x88,0x41,0xF0,0x40,0x00,0x00,0x00,0x00}, // 0x24 -{0x08,0x38,0x10,0x44,0x20,0x44,0xC0,0x44,0x00,0x39,0x70,0x02,0x88,0x0C,0x88,0x10,0x88,0x20,0x70,0x40}, // 0x25 -{0xE0,0x00,0x10,0x01,0x08,0x3A,0x08,0x46,0x88,0x45,0xC8,0x4C,0x38,0x38,0x18,0x00,0x68,0x00,0x80,0x01}, // 0x26 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27 -{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x18,0x18,0x0C,0x30,0x04,0x20,0x02,0x40,0x02,0x40,0x00,0x00}, // 0x28 -{0x00,0x00,0x02,0x40,0x02,0x40,0x04,0x20,0x0C,0x30,0x18,0x18,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x29 -{0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x0F,0x00,0x72,0x00,0x0F,0x00,0x18,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x2A -{0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xF8,0x07,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0x2B -{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2C -{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x2D -{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E -{0x00,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00}, // 0x2F -{0x00,0x00,0xC0,0x0F,0x30,0x30,0x08,0x40,0x08,0x40,0x08,0x40,0x30,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00}, // 0x30 -{0x00,0x00,0x08,0x20,0x08,0x20,0x08,0x20,0xF8,0x7F,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x31 -{0x00,0x00,0x18,0x60,0x28,0x40,0x48,0x40,0x88,0x40,0x08,0x43,0x08,0x3C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32 -{0x00,0x00,0x00,0x00,0x08,0x40,0x08,0x42,0x08,0x42,0x08,0x42,0xF0,0x3D,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33 -{0xC0,0x00,0x40,0x03,0x40,0x04,0x40,0x18,0x40,0x20,0xF8,0x7F,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00}, // 0x34 -{0x00,0x00,0x00,0x00,0x08,0x7C,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x41,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35 -{0x00,0x00,0xE0,0x0F,0x10,0x32,0x08,0x44,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x36 -{0x00,0x00,0x00,0x40,0x18,0x40,0xE0,0x40,0x00,0x43,0x00,0x4C,0x00,0x50,0x00,0x60,0x00,0x00,0x00,0x00}, // 0x37 -{0x00,0x00,0xF0,0x38,0x08,0x45,0x08,0x42,0x08,0x42,0x08,0x45,0x90,0x45,0x60,0x38,0x00,0x00,0x00,0x00}, // 0x38 -{0x00,0x00,0x00,0x1E,0x08,0x21,0x88,0x40,0x88,0x40,0x88,0x40,0x30,0x21,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0x39 -{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x18,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A -{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x06,0x1E,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3B -{0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x20,0x01,0x20,0x01,0x10,0x02,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x3C -{0x00,0x00,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x00,0x00}, // 0x3D -{0x00,0x00,0x08,0x04,0x10,0x02,0x10,0x02,0x20,0x01,0x20,0x01,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00}, // 0x3E -{0x00,0x00,0x00,0x70,0x00,0x40,0xD8,0x40,0x00,0x41,0x00,0x42,0x00,0x64,0x00,0x38,0x00,0x00,0x00,0x00}, // 0x3F -{0xC0,0x0F,0x30,0x18,0x18,0x20,0xC8,0x47,0x28,0x48,0x68,0x50,0xD8,0x51,0xE0,0x3F,0x20,0x00,0x20,0x00}, // 0x40 -{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x41 -{0x00,0x00,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x88,0x12,0x70,0x0C,0x00,0x00,0x00,0x00}, // 0x42 -{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x18,0x00,0x00,0x00,0x00}, // 0x43 -{0x00,0x00,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0x44 -{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x45 -{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x46 -{0x00,0x00,0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x88,0x10,0x88,0x10,0xF8,0x18,0x00,0x00}, // 0x47 -{0x00,0x00,0xF8,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x48 -{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x49 -{0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A -{0x00,0x00,0xF8,0x1F,0x00,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x20,0x08,0x10,0x10,0x08,0x00,0x00,0x00}, // 0x4B -{0x00,0x00,0xF8,0x1F,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x4C -{0xF8,0x1F,0x00,0x1C,0x80,0x07,0xE0,0x00,0x60,0x00,0x80,0x03,0x00,0x1C,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4D -{0x00,0x00,0xF8,0x1F,0x00,0x08,0x00,0x06,0x80,0x01,0x60,0x00,0x10,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4E -{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x4F -{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0x50 -{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x0C,0x10,0x12,0x08,0xE2,0x07,0x00,0x00}, // 0x51 -{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0xC0,0x10,0x20,0x11,0x10,0x0E,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x52 -{0x00,0x00,0x18,0x0E,0x08,0x12,0x08,0x11,0x08,0x11,0x88,0x10,0x90,0x10,0x70,0x18,0x00,0x00,0x00,0x00}, // 0x53 -{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xF8,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00}, // 0x54 -{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x55 -{0x00,0x10,0x00,0x0C,0x80,0x03,0x60,0x00,0x18,0x00,0x18,0x00,0xE0,0x00,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0x56 -{0x00,0x18,0xC0,0x07,0x38,0x00,0xF0,0x00,0x00,0x07,0x80,0x03,0x70,0x00,0x38,0x00,0xC0,0x07,0x00,0x18}, // 0x57 -{0x08,0x10,0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10}, // 0x58 -{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0x59 -{0x00,0x00,0x18,0x10,0x28,0x10,0x48,0x10,0x88,0x10,0x08,0x11,0x08,0x12,0x08,0x14,0x08,0x18,0x00,0x00}, // 0x5A -{0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x5B -{0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0xC0,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x00,0x00}, // 0x5C -{0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5D -{0x00,0x00,0x20,0x00,0xC0,0x00,0x00,0x07,0x00,0x1C,0x00,0x70,0x00,0x0E,0xC0,0x01,0x20,0x00,0x00,0x00}, // 0x5E -{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00}, // 0x5F -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60 -{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x61 -{0x00,0x00,0xF8,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x62 -{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x63 -{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xF8,0x7F,0x00,0x00,0x00,0x00}, // 0x64 -{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x65 -{0x00,0x00,0x00,0x04,0x00,0x04,0xF8,0x3F,0x00,0x24,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x00}, // 0x66 -{0x00,0x00,0xE0,0x01,0x19,0x02,0x09,0x04,0x09,0x04,0x09,0x04,0x12,0x02,0xFC,0x07,0x00,0x00,0x00,0x00}, // 0x67 -{0x00,0x00,0xF8,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x68 -{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x64,0xF8,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69 -{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0x01,0x64,0xFE,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6A -{0x00,0x00,0xF8,0x7F,0x80,0x00,0xC0,0x00,0x20,0x01,0x20,0x02,0x10,0x02,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x6B -{0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0xF8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C -{0xF8,0x07,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00}, // 0x6D -{0x00,0x00,0xF8,0x07,0x00,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x6E -{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x6F -{0x00,0x00,0xFF,0x07,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x70 -{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xFF,0x07,0x00,0x00,0x00,0x00}, // 0x71 -{0x00,0x00,0x00,0x00,0xF8,0x07,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x00}, // 0x72 -{0x00,0x00,0x18,0x03,0x88,0x04,0x88,0x04,0x48,0x04,0x48,0x04,0x30,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73 -{0x00,0x00,0x00,0x04,0x00,0x04,0xF0,0x1F,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x74 -{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75 -{0x00,0x04,0x80,0x03,0x60,0x00,0x18,0x00,0x08,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x04,0x00,0x00}, // 0x76 -{0x00,0x06,0xE0,0x01,0x18,0x00,0x70,0x00,0x80,0x03,0x80,0x01,0x70,0x00,0x18,0x00,0xE0,0x01,0x00,0x06}, // 0x77 -{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x78 -{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x00,0x18,0x00,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x79 -{0x00,0x00,0x08,0x04,0x18,0x04,0x28,0x04,0x48,0x04,0x88,0x04,0x08,0x05,0x08,0x06,0x08,0x04,0x00,0x00}, // 0x7A -{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x7C,0x3F,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x7B -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7C -{0x00,0x00,0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x7C,0x3F,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x7D -{0xC0,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x80,0x01}, // 0x7E -{0x00,0x00,0xF8,0x01,0x08,0x03,0x08,0x04,0x08,0x08,0x08,0x04,0x08,0x03,0xF8,0x01,0x00,0x00,0x00,0x00}, // 0x7F -{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x09,0x10,0x0D,0x10,0x0B,0x18,0x00,0x00,0x00,0x00}, // 0x80 -{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x00,0x08,0x00,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x81 -{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x24,0x88,0x44,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x82 -{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x44,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x83 -{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x04,0x88,0x04,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x84 -{0x00,0x00,0x30,0x00,0x48,0x44,0x88,0x24,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x85 -{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x44,0x88,0xA4,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x86 -{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x09,0x04,0x0D,0x04,0x0B,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x87 -{0x00,0x00,0xE0,0x01,0x90,0x22,0x88,0x44,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x88 -{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x24,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x89 -{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x8A -{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x04,0xF8,0x07,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8B -{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x44,0xF8,0x47,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8C -{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x44,0xF8,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8D -{0x08,0x00,0x70,0x00,0xC0,0x81,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x8E -{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0xB0,0x40,0xB8,0x40,0x4F,0xC0,0x01,0x70,0x00,0x08,0x00}, // 0x8F -{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x90 -{0x70,0x04,0xC8,0x04,0x88,0x04,0x88,0x04,0xF0,0x03,0x98,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00}, // 0x91 -{0x08,0x00,0x30,0x00,0xE0,0x01,0x20,0x06,0x20,0x18,0xF8,0x1F,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00}, // 0x92 -{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x44,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x93 -{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x94 -{0x00,0x00,0xE0,0x01,0x10,0x42,0x08,0x24,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x95 -{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x40,0x08,0x40,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x96 -{0x00,0x00,0xF0,0x07,0x08,0x40,0x08,0x20,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x97 -{0x01,0x04,0x01,0x03,0xC1,0x20,0x62,0x00,0x1C,0x00,0x18,0x20,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x98 -{0x00,0x00,0xE0,0x07,0x10,0x88,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x99 -{0x00,0x00,0xE0,0x1F,0x18,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x80,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x9A -{0x00,0x00,0xE8,0x01,0x10,0x02,0x28,0x04,0xC8,0x04,0x08,0x05,0x10,0x02,0xE0,0x05,0x00,0x00,0x00,0x00}, // 0x9B -{0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x02,0xE8,0x3F,0x08,0x42,0x08,0x42,0x08,0x40,0x00,0x00,0x00,0x00}, // 0x9C -{0x00,0x00,0xE8,0x07,0x30,0x08,0x68,0x10,0x88,0x10,0x08,0x11,0x08,0x16,0x10,0x0C,0xE0,0x17,0x00,0x00}, // 0x9D -{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x9E -{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0xFE,0x7F,0x00,0x84,0x00,0x84,0x00,0x80,0x00,0x00,0x00,0x00}, // 0x9F -{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x24,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xA0 -{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x27,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA1 -{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x24,0x08,0x44,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xA2 -{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x20,0x10,0x40,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA3 -{0x00,0x00,0xF8,0x07,0x00,0x23,0x00,0x42,0x00,0x24,0x00,0x24,0x00,0x44,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0xA4 -{0x00,0x00,0xF8,0x1F,0x00,0x48,0x00,0x86,0x80,0xC1,0x60,0x40,0x10,0x80,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0xA5 -{0x00,0x00,0x00,0x00,0x00,0x4C,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x3E,0x00,0x02,0x00,0x00,0x00,0x00}, // 0xA6 -{0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00}, // 0xA7 -{0x00,0x00,0x0E,0x00,0x13,0x00,0x11,0x00,0x21,0x00,0xC1,0x06,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00}, // 0xA8 -{0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x5D,0x00,0x55,0x00,0x5D,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00}, // 0xA9 -{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xE0,0x01,0x00,0x00}, // 0xAA -{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x00,0x08,0x08,0x31,0x38,0x41,0x28,0x01,0xC8,0x00}, // 0xAB -{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x60,0x08,0xA0,0x30,0x20,0x41,0xF8,0x01,0x20,0x00}, // 0xAC -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xAD -{0x00,0x00,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x00,0x00}, // 0xAE -{0x00,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x00,0x00}, // 0xAF -{0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x00,0x00}, // 0xB0 -{0xDB,0x36,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0x36,0xDB}, // 0xB1 -{0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0x36,0xDB}, // 0xB2 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB3 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB4 -{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x58,0x40,0x8C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB5 -{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0x98,0x40,0x8C,0x40,0x43,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB6 -{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x8E,0x40,0x58,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB7 -{0xC0,0x0F,0x30,0x30,0x98,0x67,0xC8,0x4C,0x48,0x48,0x48,0x48,0x58,0x68,0x30,0x30,0xC0,0x0F,0x00,0x00}, // 0xB8 -{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB9 -{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBA -{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBB -{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBC -{0x00,0x00,0xC0,0x0F,0x20,0x10,0x30,0x20,0x10,0x20,0xF8,0x7F,0x10,0x20,0x10,0x20,0x00,0x00,0x00,0x00}, // 0xBD -{0x00,0x40,0x00,0x20,0x20,0x19,0x20,0x05,0xF8,0x03,0x20,0x05,0x20,0x09,0x00,0x10,0x00,0x20,0x00,0x40}, // 0xBE -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBF -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC0 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC1 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC2 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC3 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC4 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC5 -{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x24,0x90,0x24,0xF8,0x43,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xC6 -{0x08,0x00,0x70,0x00,0xC0,0x41,0x40,0x8E,0x40,0xD8,0x40,0x4C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xC7 -{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC8 -{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC9 -{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCA -{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCB -{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCC -{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCD -{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCE -{0x00,0x00,0x20,0x10,0xC0,0x0F,0x40,0x08,0x40,0x08,0x40,0x08,0x40,0x08,0xC0,0x0F,0x20,0x10,0x00,0x00}, // 0xCF -{0x00,0x00,0xE0,0x41,0x10,0x52,0x08,0x74,0x08,0x24,0x08,0x54,0x10,0x0E,0xE0,0x03,0x00,0x00,0x00,0x00}, // 0xD0 -{0x00,0x01,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0xD1 -{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x90,0x88,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD2 -{0x00,0x00,0xF8,0x1F,0x88,0x90,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD3 -{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x90,0x88,0x50,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD4 -{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD5 -{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x5F,0x08,0x90,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD6 -{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x50,0xF8,0x9F,0x08,0x90,0x08,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD7 -{0x00,0x00,0x08,0x10,0x08,0x90,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD8 -{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD9 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xDA -{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB -{0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00}, // 0xDC -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xDD -{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x90,0xF8,0x5F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xDE -{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, // 0xDF -{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x50,0x08,0x90,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE0 -{0x00,0x00,0xF8,0x3F,0x00,0x40,0x00,0x40,0x08,0x47,0x88,0x38,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00}, // 0xE1 -{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x50,0x08,0x90,0x08,0x90,0x08,0x50,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE2 -{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x90,0x08,0x50,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE3 -{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x24,0x08,0x24,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE4 -{0x00,0x00,0xE0,0x07,0x10,0x48,0x08,0x90,0x08,0xD0,0x08,0x50,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE5 -{0x00,0x00,0xFF,0x07,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xE6 -{0x00,0x00,0xFF,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE7 -{0x00,0x00,0xF8,0x1F,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x40,0x04,0x80,0x03,0x00,0x00,0x00,0x00}, // 0xE8 -{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x40,0x08,0x80,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xE9 -{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x40,0x08,0x80,0x08,0x80,0x10,0x40,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEA -{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x80,0x08,0x40,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEB -{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x20,0x18,0x40,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0xEC -{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x40,0x00,0x81,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0xED -{0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80}, // 0xEE -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF -{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0xF0 -{0x00,0x00,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0xC8,0x07,0x08,0x01,0x08,0x01,0x08,0x01,0x00,0x00}, // 0xF1 -{0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00}, // 0xF2 -{0x08,0x42,0x10,0x52,0x20,0x5A,0xC0,0x6C,0x00,0x01,0x60,0x02,0xA0,0x0C,0x20,0x11,0xF8,0x21,0x20,0x40}, // 0xF3 -{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0xF4 -{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0xF5 -{0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x58,0x06,0x58,0x06,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0xF6 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF7 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF8 -{0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9 -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFA -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFB -{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x6C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFC -{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x46,0x00,0x4A,0x00,0x4A,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFD -{0x00,0x00,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0x00,0x00}, // 0xFE -{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF -}; \ No newline at end of file diff --git a/zbs243_Tag_FW/font.h b/zbs243_Tag_FW/font.h new file mode 120000 index 00000000..995855e4 --- /dev/null +++ b/zbs243_Tag_FW/font.h @@ -0,0 +1 @@ +../zbs243_shared/font.h \ No newline at end of file diff --git a/zbs243_Tag_FW/fw154.bin b/zbs243_Tag_FW/fw154.bin deleted file mode 100644 index 81a5668addfb0320041834a31fdce562fdda2128..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57438 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≪1C@@?cd3f5mF} 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

%!C@a%pcJOwRq(mj666leSB9IjIb^6> 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 diff --git a/zbs243_Tag_FW/fw29.bin b/zbs243_Tag_FW/fw29.bin deleted file mode 100644 index b8331b58d86360f13cdfdb37c0a9dc81678d516e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57393 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 diff --git a/zbs243_Tag_FW/fw42.bin b/zbs243_Tag_FW/fw42.bin deleted file mode 100644 index 508b008544829983e45142dac44c6d48ad06b4fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57407 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 diff --git a/zbs243_Tag_FW/lut.h b/zbs243_Tag_FW/lut.h deleted file mode 100644 index 4f9eba67..00000000 --- a/zbs243_Tag_FW/lut.h +++ /dev/null @@ -1,54 +0,0 @@ -#define __packed - -#include "screen.h" - -#define LUTGROUP_NEGATIVE 0 -#define LUTGROUP_FASTBLINK 1 -#define LUTGROUP_SLOWBLINK 2 -#define LUTGROUP_SET 3 -#define LUTGROUP_IMPROVE_SHARPNESS 4 -#define LUTGROUP_IMPROVE_REDS 5 -#define LUTGROUP_UNUSED 6 - -#define LUTGROUP_UNKNOWN 7 -#define LUTGROUP_UNUSED3 8 -#define LUTGROUP_UNUSED4 9 - - -struct vgroup { - uint8_t A : 2; - uint8_t B : 2; - uint8_t C : 2; - uint8_t D : 2; -} __packed; - -struct lut { - struct vgroup group[7]; -} __packed; - -struct lut10 { - struct vgroup group[10]; -} __packed; - -struct group { - uint8_t phaselength[4]; - uint8_t repeat; -} __packed; - -struct waveform { - struct lut lut[5]; - struct group group[7]; - uint8_t gatelevel; - uint8_t sourcelevel[3]; - uint8_t dummyline; - uint8_t gatewidth; -} __packed; - -struct waveform10 { - struct lut10 lut[5]; - struct group group[10]; - uint8_t gatelevel; - uint8_t sourcelevel[3]; - uint8_t dummyline; - uint8_t gatewidth; -} __packed; \ No newline at end of file diff --git a/zbs243_Tag_FW/lut.h b/zbs243_Tag_FW/lut.h new file mode 120000 index 00000000..64d1fa03 --- /dev/null +++ b/zbs243_Tag_FW/lut.h @@ -0,0 +1 @@ +../zbs243_shared/lut.h \ No newline at end of file diff --git a/zbs243_Tag_FW/printf.h b/zbs243_Tag_FW/printf.h deleted file mode 100644 index 8ca2eea5..00000000 --- a/zbs243_Tag_FW/printf.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PRINTF_H_ -#define _PRINTF_H_ - - -//our printf has some special abilities -//for example "*" will modify the param to be a __xdata pointer to whatever it would have been instead -//it must then be paramed as "(uintptr_near_t)&value" -//for cc1110 (but not for ZBS) code and xdata addrs are the same, so __code pointers will also work! - -//"%s" param takes a generic pointer, but assumes it is an xdata/code (no string support in pdata/idata) -//"%ls" takes an xdata(/code in cc111x) pointer instead :) - -//"%m/%M" will print a mac, an __xdata pointer to which has been provided - -//no support for passing NULL to %s - -//not re-entrant if %d/%u are used - -#pragma callee_saves pr -void pr(const char __code *fmt, ...) __reentrant; - -#pragma callee_saves epdpr -void epdpr(const char __code *fmt, ...) __reentrant; - -#pragma callee_saves spr -void spr(char __xdata* out, const char __code *fmt, ...) __reentrant; - - - -#endif diff --git a/zbs243_Tag_FW/printf.h b/zbs243_Tag_FW/printf.h new file mode 120000 index 00000000..208adb6c --- /dev/null +++ b/zbs243_Tag_FW/printf.h @@ -0,0 +1 @@ +../zbs243_shared/printf.h \ No newline at end of file diff --git a/zbs243_Tag_FW/proto.h b/zbs243_Tag_FW/proto.h deleted file mode 100644 index 1a3e9f6e..00000000 --- a/zbs243_Tag_FW/proto.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef _PROTO_H_ -#define _PROTO_H_ -#define __packed -#include - -enum TagScreenType { - TagScreenEink_BW_1bpp, - TagScreenEink_BW_2bpp, - TagScreenEink_BW_4bpp, - TagScreenEink_BWY_only, // 2bpp, but only 3 colors (BW?Y) - TagScreenEink_BWY_2bpp, - TagScreenEink_BWY_4bpp, - TagScreenEink_BWR_only, // 2bpp, but only 3 colors (BW?R) - TagScreenEink_BWR_2bpp, - TagScreenEink_BWR_4bpp, - - TagScreenEink_BWY_3bpp, - TagScreenEink_BWR_3bpp, - TagScreenEink_BW_3bpp, - - TagScreenPersistentLcd_1bpp, - - TagScreenEink_BWY_5colors, - TagScreenEink_BWR_5colors, - - TagScreenEink_BWY_6colors, - TagScreenEink_BWR_6colors, - - TagScreenTypeOther = 0x7f, -}; - -#define SOLUM_154_033 0 -#define SOLUM_29_033 1 -#define SOLUM_42_033 2 - -#ifndef __packed -#define __packed __attribute__((packed)) -#endif - -#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used - -#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc - -#define ADDR_MODE_NONE (0) -#define ADDR_MODE_SHORT (2) -#define ADDR_MODE_LONG (3) - -#define FRAME_TYPE_BEACON (0) -#define FRAME_TYPE_DATA (1) -#define FRAME_TYPE_ACK (2) -#define FRAME_TYPE_MAC_CMD (3) - -#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac - -struct MacFcs { - uint8_t frameType : 3; - uint8_t secure : 1; - uint8_t framePending : 1; - uint8_t ackReqd : 1; - uint8_t panIdCompressed : 1; - uint8_t rfu1 : 1; - uint8_t rfu2 : 2; - uint8_t destAddrType : 2; - uint8_t frameVer : 2; - uint8_t srcAddrType : 2; -} __packed; - -struct MacFrameFromMaster { - struct MacFcs fcs; - uint8_t seq; - uint16_t pan; - uint8_t dst[8]; - uint16_t from; -} __packed; - -struct MacFrameNormal { - struct MacFcs fcs; - uint8_t seq; - uint16_t pan; - uint8_t dst[8]; - uint8_t src[8]; -} __packed; - -struct MacFrameBcast { - struct MacFcs fcs; - uint8_t seq; - uint16_t dstPan; - uint16_t dstAddr; - uint16_t srcPan; - uint8_t src[8]; -} __packed; - -#define PKT_AVAIL_DATA_SHORTREQ 0xE3 -#define PKT_AVAIL_DATA_REQ 0xE5 -#define PKT_AVAIL_DATA_INFO 0xE6 -#define PKT_BLOCK_PARTIAL_REQUEST 0xE7 -#define PKT_BLOCK_REQUEST_ACK 0xE9 -#define PKT_BLOCK_REQUEST 0xE4 -#define PKT_BLOCK_PART 0xE8 -#define PKT_XFER_COMPLETE 0xEA -#define PKT_XFER_COMPLETE_ACK 0xEB -#define PKT_CANCEL_XFER 0xEC -#define PKT_PING 0xED -#define PKT_PONG 0xEE - -struct AvailDataReq { - uint8_t checksum; - uint8_t lastPacketLQI; - int8_t lastPacketRSSI; - int8_t temperature; - uint16_t batteryMv; - uint8_t hwType; - uint8_t wakeupReason; - uint8_t capabilities; // undefined, as of now -} __packed; - -#define CAPABILITY_HAS_WAKE_BUTTON 0x20 -#define CAPABILITY_HAS_NFC 0x40 -#define CAPABILITY_NFC_WAKE 0x80 - -#define DATATYPE_NOUPDATE 0 -#define DATATYPE_IMG_BMP 2 -#define DATATYPE_FW_UPDATE 3 -#define DATATYPE_IMG_DIFF 0x10 // always 1BPP -#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2" -#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2" -#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD -#define DATATYPE_NFC_RAW_CONTENT 0xA0 // raw memory content for the NT3H1101 -#define DATATYPE_NFC_URL_DIRECT 0xA1 // URL format for NT3H1101 - - - -struct AvailDataInfo { - uint8_t checksum; - uint64_t dataVer; // MD5 of potential traffic - uint32_t dataSize; - uint8_t dataType; - uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image) - uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes -} __packed; - -struct pendingData { - struct AvailDataInfo availdatainfo; - uint16_t attemptsLeft; - uint8_t targetMac[8]; -} __packed; - -struct blockPart { - uint8_t checksum; - uint8_t blockId; - uint8_t blockPart; - uint8_t data[]; -} __packed; - -struct blockData { - uint16_t size; - uint16_t checksum; - uint8_t data[]; -} __packed; - -struct burstMacData { - uint16_t offset; - uint8_t targetMac[8]; -} __packed; - -#define BLOCK_PART_DATA_SIZE 99 -#define BLOCK_MAX_PARTS 42 -#define BLOCK_DATA_SIZE 4096UL -#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData) -#define BLOCK_REQ_PARTS_BYTES 6 - -struct blockRequest { - uint8_t checksum; - uint64_t ver; - uint8_t blockId; - uint8_t type; - uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES]; -} __packed; - -struct blockRequestAck { - uint8_t checksum; - uint16_t pleaseWaitMs; -} __packed; - -#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" -#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0] - -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/proto.h b/zbs243_Tag_FW/proto.h new file mode 120000 index 00000000..fed53c0e --- /dev/null +++ b/zbs243_Tag_FW/proto.h @@ -0,0 +1 @@ +../zbs243_shared/proto.h \ No newline at end of file diff --git a/zbs243_Tag_FW/sleep.h b/zbs243_Tag_FW/sleep.h deleted file mode 100644 index 02b06c46..00000000 --- a/zbs243_Tag_FW/sleep.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SLEEP_H_ -#define _SLEEP_H_ - -#include - - -void sleepForMsec(uint32_t msec); -void sleepTillInt(void); //assumes you left only one int enabled! - -#endif diff --git a/zbs243_Tag_FW/sleep.h b/zbs243_Tag_FW/sleep.h new file mode 120000 index 00000000..110761e6 --- /dev/null +++ b/zbs243_Tag_FW/sleep.h @@ -0,0 +1 @@ +../zbs243_shared/sleep.h \ No newline at end of file diff --git a/zbs243_Tag_FW/soc b/zbs243_Tag_FW/soc new file mode 120000 index 00000000..18e4afb2 --- /dev/null +++ b/zbs243_Tag_FW/soc @@ -0,0 +1 @@ +../zbs243_shared/soc \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/radioCommon.h b/zbs243_Tag_FW/soc/radioCommon.h deleted file mode 100644 index 99937234..00000000 --- a/zbs243_Tag_FW/soc/radioCommon.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _RADIO_COMMON_H_ -#define _RADIO_COMMON_H_ - -#include -#include - - -//radio cfg -#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 -#define RADIO_NUM_CHANNELS (15) - - -#define RADIO_MAX_PACKET_LEN (125) //useful payload, not including the crc - -#define ADDR_MODE_NONE (0) -#define ADDR_MODE_SHORT (2) -#define ADDR_MODE_LONG (3) - -#define FRAME_TYPE_BEACON (0) -#define FRAME_TYPE_DATA (1) -#define FRAME_TYPE_ACK (2) -#define FRAME_TYPE_MAC_CMD (3) - -#define SHORT_MAC_UNUSED (0x10000000UL) //for radioRxFilterCfg's myShortMac - - -void radioInit(void); -bool radioTx(const void __xdata* packet); //waits for tx end - -#pragma callee_saves radioRxAckReset -void radioRxAckReset(void); -#pragma callee_saves radioRxAckGetLast -int16_t radioRxAckGetLast(void); //get seq of lask ack we got or -1 if none -void radioRxFilterCfg(const uint8_t __xdata *filterForLong, uint32_t myShortMac, uint16_t myPan); -void radioRxEnable(__bit on, __bit autoAck); - -#pragma callee_saves radioSetTxPower -void radioSetTxPower(int8_t dBm); //-30..+10 dBm - -#pragma callee_saves radioSetChannel -void radioSetChannel(uint8_t ch); - -void radioRxFlush(void); -int8_t radioRxDequeuePktGet(const void __xdata * __xdata *dstBufP, uint8_t __xdata *lqiP, int8_t __xdata *rssiP); -void radioRxDequeuedPktRelease(void); - - - - - -#endif - - - - diff --git a/zbs243_Tag_FW/soc/zbs243/.uart.asm.swp b/zbs243_Tag_FW/soc/zbs243/.uart.asm.swp deleted file mode 100644 index 671c1db3d4f8e2ed309c159cbeabf013c4e7de29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYc?$V<%2S1{8vVn6}eQ92Ao`S~R%f;c$od8I{(DVg~=q~XG)iA5!PiN(2afl -#include "asmUtil.h" -#include "printf.h" -#include "flash.h" -#include "cpu.h" - - - -#pragma callee_saves flashAddrCheck -static uint8_t flashAddrCheck(uint32_t flashAddr, uint16_t len) __reentrant /* to save ram space */ // return 0xff for error, pgNo -{ - uint16_t dstOfst; - uint8_t pgNo; - - if (!len) - return 0xff; - - //verify address - if ((uint8_t)(flashAddr >> 24)) - return 0xff; - - switch ((uint8_t)(flashAddr >> 16)) { - case 0x00: - pgNo = ((uint8_t)(flashAddr >> 8)) >> 2; - break; - - case 0x80: - if (pgNo) - return 0xff; - pgNo = 0x80; - break; - - default: - return 0xff; - } - - dstOfst = flashAddr & 0x3ff; - //verify no boundary crossing - if (((uint8_t)((dstOfst + len - 1) >> 8)) >> 2) //yeah...sdcc - return 0xff; - - return pgNo; -} - -//info page is "at" 0x10000 -#pragma callee_saves flashWrite -__bit flashWrite(uint32_t dstAddr, const void __xdata *src, uint16_t len, __bit alsoErase /*whole page */) -{ - uint8_t pgNo, cfgPg, speed; - __bit irq; - - pgNo = flashAddrCheck(dstAddr, len); - if (pgNo == 0xff) - return false; - - irq = IEN_EA; - IEN_EA = false; - - speed = CLKSPEED; - CLKSPEED = 0x21; //flash ops only work at this speed - - cfgPg = CFGPAGE; - CFGPAGE = 4; - - if (alsoErase) - SETTINGS |= 0x38; - else - SETTINGS = 0x18; - FWRTHREE = 3; - FPGNO = pgNo; - FWRDSTL = (uint8_t)dstAddr; - FWRDSTH = (((uint16_t)dstAddr) >> 8) & 0x03; - FWRLENL = (uint8_t)(len - 1); - FWRLENH = (len - 1) >> 8; - FWRSRCL = (uint8_t)src; - FWRSRCH = ((uint16_t)src) >> 8; - TRIGGER |= 8; //start - while (!(TCON2 & 0x08)); //wait - - TCON2 &=~ 0x48; - SETTINGS &=~ 0x10; - - CFGPAGE = cfgPg; - - CLKSPEED = speed; - - IEN_EA = irq; - - return true; -} - -#pragma callee_saves flashRead -__bit flashRead(uint32_t srcAddr, void __xdata *dst, uint16_t len) -{ - uint8_t pgNo, cfgPg, speed; - __bit irq; - - pgNo = flashAddrCheck(srcAddr, len); - if (pgNo == 0xff) - return false; - - irq = IEN_EA; - IEN_EA = false; - - speed = CLKSPEED; - CLKSPEED = 0x21; //flash ops only work at this speed - - cfgPg = CFGPAGE; - CFGPAGE = 4; - - SETTINGS = 0x8; - FWRTHREE = 3; - FPGNO = pgNo; - FWRDSTL = (uint8_t)dst; - FWRDSTH = ((uint16_t)dst) >> 8; - FWRSRCL = (uint8_t)srcAddr; - FWRSRCH = (((uint16_t)srcAddr) >> 8) & 0x03; - FWRLENL = (uint8_t)(len - 1); - FWRLENH = (len - 1) >> 8; - TRIGGER |= 8; //start - - while (!(TCON2 & 0x08)); //wait - - TCON2 &=~ 0x48; - SETTINGS &=~ 0x10; - - CFGPAGE = cfgPg; - - CLKSPEED = speed; - - IEN_EA = irq; - - return true; -} - -#pragma callee_saves flashErase -__bit flashErase(uint32_t dstAddr) -{ - uint8_t __xdata dummyByte = 0xff; - uint8_t pgNo, cfgPg, speed; - __bit irq; - - pgNo = flashAddrCheck(dstAddr, 1); - - if (pgNo == 0xff) - return false; - - irq = IEN_EA; - IEN_EA = false; - - speed = CLKSPEED; - CLKSPEED = 0x21; //flash ops only work at this speed - - cfgPg = CFGPAGE; - CFGPAGE = 4; - - //this command does an erase AND a write (erase of page, write up to a page at given offset and len) - // i found no way to JUST erase. As len is encoded at "minus one", we cannot ask the hardware to write - // zeor bytes, so we write one - a 0xFF dummy - SETTINGS |= 0x38; - FWRTHREE = 3; - FPGNO = pgNo; - FWRDSTL = 0; - FWRDSTH = 0; - FWRLENL = 0; - FWRLENH = 0; - FWRSRCL = (uint8_t)&dummyByte; - FWRSRCH = ((uint16_t)&dummyByte) >> 8; - TRIGGER |= 8; //start - while (!(TCON2 & 0x08)); //wait - - TCON2 &=~ 0x48; - SETTINGS &=~ 0x10; - - CFGPAGE = cfgPg; - - CLKSPEED = speed; - - IEN_EA = irq; - - return true; -} diff --git a/zbs243_Tag_FW/soc/zbs243/flash.h b/zbs243_Tag_FW/soc/zbs243/flash.h deleted file mode 100644 index 2c03e2cb..00000000 --- a/zbs243_Tag_FW/soc/zbs243/flash.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _FLASH_ZBS_H_ -#define _FLASH_ZBS_H_ - -#include - -#define FLASH_PAGE_SHIFT (10) -#define FLASH_PAGE_SIZE (1 << FLASH_PAGE_SHIFT) -#define FLASH_NUM_PAGES (64) - -#define FLASH_INFOPAGE_ADDR (0x00800000ul) - - - -#pragma callee_saves flashErase -__bit flashErase(uint32_t dstAddr); - -#pragma callee_saves flashRead -__bit flashRead(uint32_t srcAddr, void __xdata *dst, uint16_t len); - -#pragma callee_saves flashWrite -__bit flashWrite(uint32_t dstAddr, const void __xdata *src, uint16_t len, __bit alsoErase /*whole page */); - -#endif diff --git a/zbs243_Tag_FW/soc/zbs243/i2c.c b/zbs243_Tag_FW/soc/zbs243/i2c.c deleted file mode 100644 index 633f389d..00000000 --- a/zbs243_Tag_FW/soc/zbs243/i2c.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "i2c.h" - -#include "printf.h" -#include "uart.h" -#include "zbs243.h" - -static volatile struct I2cTransaction __xdata *__xdata mCurTrans; -static volatile uint8_t __xdata mNumTrans; -static volatile uint8_t __xdata mResult; - -#pragma callee_saves i2cInit -void i2cInit(void) { - uint8_t bkp; - - CLKEN |= 0x10; - - bkp = CFGPAGE; - CFGPAGE = 0; - - IEN1 |= 4; // int on - I2CUNKNOWN |= 4; - - I2CCTL = 0x43; // master mode - I2CSPEED = 0x1a; // 100KHz - I2CCTL |= 0x80; // irq on - - CFGPAGE = bkp; -} - -// this code assumes HW stat emachine acts as it should. for this chip that seems to be true -// this is an 8051 so we value speed & code size over defensive programming. So sue me! -void I2C_IRQ(void) __interrupt(8) { - uint8_t bkp, sta; - - bkp = CFGPAGE; - CFGPAGE = 0; - - sta = I2CSTATE; - //pr("state=%02X\n", sta); - switch (sta >> 3) { - case 0x08 / 8: // start completed - case 0x10 / 8: // restart completed - I2CBUF = mCurTrans->deviceAddr; - break; - - case 0x30 / 8: // byte write was NAKed - if (mCurTrans->numBytes) { // we still had more bytes to send? - I2CCTL |= 0x10; // stop - mResult = I2cNonLastDataByteNAKed; - break; - } - // fallthough since it is ok to NAK last written byte - - case 0x28 / 8: // byte write was ACKed - case 0x18 / 8: // addr ACKED in write mode - if (mCurTrans->numBytes) { - mCurTrans->numBytes--; - I2CBUF = *mCurTrans->bytes++; - break; - } - transaction_over: - if (!--mNumTrans) { // byte(s)written and no more transactions? STOP - - mResult = I2cOK; - I2CCTL |= 0x10; // stop - } else { // we have another transaction? RESTART - - mCurTrans++; - I2CCTL |= 0x20; // do a restart - } - break; - - case 0x20 / 8: // addr NAKEd in write mode - mResult = I2cWrAddrNAKed; - I2CCTL |= 0x10; // stop - mNumTrans = 0; - break; - - case 0x48 / 8: // addr NACKed in read mode - mResult = I2cRdAddrNAKed; - I2CCTL |= 0x10; // stop - mNumTrans = 0; - break; - - case 0x58 / 8: // NAK to RXed byte sent (we still have th ebyte we got in buffer) - case 0x50 / 8: // got byte in read mode - *mCurTrans->bytes++ = I2CBUF; - mCurTrans->numBytes--; - // fallthrough - - case 0x40 / 8: // addr ACKED in read mode - if (!mCurTrans->numBytes) - goto transaction_over; - else if (mCurTrans->numBytes == 1) - I2CCTL &= ~0x04; // NAK - else - I2CCTL |= 0x04; // ACK - break; - - default: - mResult = I2cInternalError; - I2CCTL |= 0x10; // stop - mNumTrans = 0; - break; - } - - I2CCTL &= ~0x08; - CFGPAGE = bkp; -} - -#pragma callee_saves i2cTransact -enum I2cResult i2cTransact(struct I2cTransaction __xdata *trans, uint8_t nTrans) { - mCurTrans = trans; - mNumTrans = nTrans; - - mResult = I2cOK; - - if (nTrans) { - I2CCTL &= ~0x10; // clear stop - I2CCTL |= 0x20; // issue start - - while (mNumTrans) - ; // wait - } - return mResult; -} diff --git a/zbs243_Tag_FW/soc/zbs243/i2c.h b/zbs243_Tag_FW/soc/zbs243/i2c.h deleted file mode 100644 index 682209ce..00000000 --- a/zbs243_Tag_FW/soc/zbs243/i2c.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _I2C_H_ -#define _I2C_H_ - -#include - -enum I2cResult { - I2cOK, - I2cWrAddrNAKed, - I2cRdAddrNAKed, - I2cNonLastDataByteNAKed, - I2cInternalError, -}; - -struct I2cTransaction { - uint8_t deviceAddr; - uint8_t numBytes; //will be updated as we go along so you can figure out what was NAKed - uint8_t __xdata *bytes; -}; - -#pragma callee_saves i2cInit -void i2cInit(void); - -#pragma callee_saves i2cTransact -uint8_t i2cTransact(struct I2cTransaction __xdata *trans, uint8_t nTrans); //returns enum I2cResult - -void I2C_IRQ(void) __interrupt (8); - - - - - - -#endif - diff --git a/zbs243_Tag_FW/soc/zbs243/make.mk b/zbs243_Tag_FW/soc/zbs243/make.mk deleted file mode 100644 index 3b4f9da9..00000000 --- a/zbs243_Tag_FW/soc/zbs243/make.mk +++ /dev/null @@ -1,8 +0,0 @@ -FLAGS += -Isoc/zbs243 - -FLAGS += -DSOC_ZBS243 --xram-loc 0xe000 --xram-size 0x2000 --model-large - -SOURCES += soc/zbs243/soc.c soc/zbs243/wdt.c soc/zbs243/sleep.c soc/zbs243/spi.c soc/zbs243/uart.c soc/zbs243/timer.c soc/zbs243/radio.c -SOURCES += soc/zbs243/flash.c soc/zbs243/temperature.c cpu/8051/random.c cpu/8051/printf.c -SOURCES += soc/zbs243/i2c.c -CPU = 8051 diff --git a/zbs243_Tag_FW/soc/zbs243/radio.c b/zbs243_Tag_FW/soc/zbs243/radio.c deleted file mode 100644 index 802f2561..00000000 --- a/zbs243_Tag_FW/soc/zbs243/radio.c +++ /dev/null @@ -1,336 +0,0 @@ -#include "radio.h" - -#include "asmUtil.h" -#include "board.h" -#include "cpu.h" -#include "printf.h" -#include "timer.h" - -#define RX_BUFFER_SIZE (RADIO_MAX_PACKET_LEN + 1 /* len byte */ + 2 /* RSSI & LQI */) -#define RX_BUFFER_NUM 3 - -static volatile uint8_t __xdata mRxBufs[RX_BUFFER_NUM][RX_BUFFER_SIZE]; -static volatile uint8_t __xdata mLastRSSI, mLastTxedSeq, mRxOn, mRxBufNextR, mRxBufNextW, mRxBufNumFree; -static volatile __bit mAckTimePassed, mGotAck; - -// some things look like: https://www.ti.com/lit/ds/symlink/cc2430.pdf -// maybe a licensed and heavily modified version? - -// maybe rx on and tx cal? -// see segmented_ota.<> - -void RF_IRQ1(void) __interrupt(4) { - uint8_t cause = RADIO_IRQ4_pending; - static uint8_t __xdata lastRSSI; - - RADIO_IRQ4_pending = 0; - - if (cause & 0x40) { // ack time happened - - // radio will report ACK if we (1) got an ack or (2) sent a packet that did not require it - mAckTimePassed = true; - mGotAck = !!(cause & 0x10); - - } - if (cause & 0x20) { // radio has RXed a packet into its internal buffer. vet it quickly and set up DMA - - uint8_t len = RADIO_GOTLEN; - - if (len < 3 || len >= 0x80 || RADIO_rxFirstByte + 1 != len || !mRxOn || !mRxBufNumFree) { // detect invalid packets right away, or RX being off - - RADIO_command = RADIO_CMD_FLUSH_RX_FIFO; - } else { - uint8_t __xdata *buf = mRxBufs[mRxBufNextW]; - uint8_t bkp; - - buf[0] = len; - - bkp = CFGPAGE; - CFGPAGE = 4; - RADIO_RXLEN = len - 1; - RADIO_RXPTRL = ((uint16_t)(buf + 1)) & 0xff; - RADIO_RXPTRH = ((uint16_t)(buf + 1)) >> 8; - TRIGGER |= 4; // start rx dma - - TCON2 &= ~4; // without this we trigger next irq too fast and get garbage - - CFGPAGE = bkp; - } - } - if ((cause & 0x10) && !(RADIO_curRfState & 0x20)) { // radio got a valid preamble and is RXing a packet. this is our chance to sample some RSSI - uint8_t i; - - // we get here if radio is RXing a packet - tells us to capture some RSSI vals. - // Seems there is an offset. Value is signed and offset by 56 - for (i = 0; i < 0x3c; i++) - mLastRSSI = RADIO_currentRSSI; - } -} - -void RF_IRQ2(void) __interrupt(5) { - uint8_t bck = CFGPAGE; - CFGPAGE = 4; - - if (TCON2 & 0x04) { // RX dma over - time to check packet for valid CRC - - uint8_t __xdata *buf = mRxBufs[mRxBufNextW]; - uint8_t len; - - TCON2 &= ~0x04; - RADIO_command = RADIO_CMD_FLUSH_RX_FIFO; - - // last byte we got DMAed to us has top bit as flags for "crc ok" - - len = buf[0]; - - if (!(buf[len] & 0x80)) { - // CRC failed on packet - } else { - buf[len - 1] = mLastRSSI - 56; - - if (++mRxBufNextW == RX_BUFFER_NUM) - mRxBufNextW = 0; - mRxBufNumFree--; - } - } - if (TCON2 & 0x02) { // TX DMA completed - TCON2 &= ~2; - - // nothing to do here - } - if (TCON2 & 0x08) { // radio init over - TCON2 &= ~0x48; - SETTINGS &= ~0x10; - } - CFGPAGE = bck; -} - -bool radioTx(const void __xdata *packetP) // waits for tx end -{ - const uint8_t __xdata *packet = (const uint8_t __xdata *)packetP; - uint16_t bkp, wait; - __bit irqs; - - // this is how to do CCA. we do not bother because fuck it - // this is how WE do CCA. 'Fuck it' still somewhat applies if we don't get a clear channel in a reasonable amount of time - // okay fuck it. - /* - for (uint8_t i = 0; i < 0x80; i++) { - if (!(RADIO_curRfState & 1)) { - //pr("radio CCA fail\n"); - timerDelay(TIMER_TICKS_PER_SECOND / 2000); - //return; - } - } - */ - - mAckTimePassed = false; - mGotAck = false; - mLastTxedSeq = packet[3]; - - bkp = CFGPAGE; - CFGPAGE = 4; - - irqs = IEN_EA; - IEN_EA = 0; - - RADIO_TXLEN = packet[0] - 2; - RADIO_TXPTRL = ((uint16_t)packet) & 0xff; - RADIO_TXPTRH = ((uint16_t)packet) >> 8; - RADIO_command = RADIO_CMD_LOAD_TX_FIFO; - TRIGGER |= 2; // start TX fifo DMA - - IEN_EA = irqs; - - CFGPAGE = bkp; - - //RADIO_unk_C8 = 0xff; /// stock fw does this but seems unnecessary - - // wait for tx to start - wait = 0; - wait--; - do { - if (RADIO_curRfState & 0x80) - break; - } while (--wait); - - // wait for tx to end - if (wait) { - while (!mAckTimePassed) - ; - return true; - } else { - return false; - } - - //RADIO_unk_C8 = 0x7f; /// stock fw does this but seems unnecessary -} - -void radioRxAckReset(void) { - mGotAck = false; -} - -int16_t radioRxAckGetLast(void) { - if (mGotAck) - return (uint16_t)mLastTxedSeq; - else - return -1; -} - -void radioRxFilterCfg(const uint8_t __xdata *filterForLong, uint32_t myShortMac, uint16_t myPan) { - uint16_t shortMac = (myShortMac == SHORT_MAC_UNUSED) ? 0xffff : myShortMac; - uint8_t i; - - RADIO_PANID_Hi = myPan >> 8; - RADIO_PANID_Lo = myPan; - - RADIO_ownShortAddress_Hi = shortMac >> 8; - RADIO_ownShortAddress_Lo = shortMac; - - for (i = 0; i < 8; i++) - ((volatile uint8_t __xdata *)&RADIO_ownMac_7)[i] = filterForLong[(uint8_t)((uint8_t)7 - (uint8_t)i)]; -} - -void radioRxEnable(__bit on, __bit autoAck) { - if (!autoAck) { - pr("auto ack forced for now\n"); - while (1) - ; - } - mRxOn = on; -} - -void radioSetTxPower(int8_t dBm) { - if (dBm < -27) - dBm = -27; - else if (dBm > 8) - dBm = 8; - - dBm += 27; - - RADIO_txPower = (uint8_t)(((uint8_t)dBm) + 3) / 5; -} - -void radioSetChannel(uint8_t ch) { - static const uint8_t perChannelSetting1[] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x33, 0x33}; - static const uint8_t perChannelSetting2[] = {4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2}; - - if (ch < RADIO_FIRST_CHANNEL || ch >= RADIO_FIRST_CHANNEL + RADIO_NUM_CHANNELS) - return; - - RADIO_channel = ch; // configmed to be at least RX channel - RADIO_command = RADIO_CMD_RECEIVE; - RADIO_perChannelSetting1 = perChannelSetting1[ch - 11]; - RADIO_perChannelSetting2 = perChannelSetting2[ch - 11]; -} - -void radioRxFlush(void) { - mRxBufNumFree = RX_BUFFER_NUM; -} - -int8_t radioRxDequeuePktGet(const void __xdata *__xdata *dstBufP, uint8_t __xdata *lqiP, int8_t __xdata *rssiP) { - const uint8_t __xdata *buf = mRxBufs[mRxBufNextR]; - uint8_t lqi, len = buf[0]; - - if (mRxBufNumFree == RX_BUFFER_NUM) - return -1; - - lqi = (buf[len] & 0x7f); - - *lqiP = lqi; - *rssiP = buf[len - 1]; - *dstBufP = buf + 1; - - return len - 2; -} - -void radioRxDequeuedPktRelease(void) { - if (++mRxBufNextR == RX_BUFFER_NUM) - mRxBufNextR = 0; - - __critical { - mRxBufNumFree++; - } -} - -void radioInit(void) { - uint8_t bkp; - - mRxBufNextW = 0; - mRxBufNextR = 0; - mRxBufNumFree = RX_BUFFER_NUM; - - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - RADIO_unk_F0 |= 0x80; - timerDelay(TIMER_TICKS_PER_SECOND / 1000); - CFGPAGE = 0; - RESET &= ~4; - RESET |= 4; - RESET &= ~4; - timerDelay(TIMER_TICKS_PER_SECOND / 10000); - - RADIO_RadioPowerCtl |= 4; - - bkp = CFGPAGE; - CFGPAGE = 4; - SETTINGS |= 2; - RADIO_INITSEQ0 = 2; - RADIO_INITSEQ1 = 0xFA; - RADIO_INITSEQ2 = 0xDD; - SETTINGS |= 4; - RADIO_INITSEQ3 = 1; - RADIO_INITSEQ4 = 0xFA; - RADIO_INITSEQ5 = 0xDD; - IEN_RF2 = 1; - CFGPAGE = bkp; - - RADIO_command = 0xC1; - - RADIO_unk_C1 = 0x02; - RADIO_calibration_C2 = 0xf7; // mdmctrl0L? - RADIO_calibration_C3 = 0x05; - RADIO_calibration_C4 = 0x35; - RADIO_calibration_C5 = 0x24; - RADIO_calibration_C6 = 0x33; - RADIO_calibration_C7 = 0x70; - RADIO_unk_CA = 0x58; - RADIO_perChannelSetting2 = 0x02; - RADIO_unk_CD = (RADIO_unk_CD & ~7) | (0x11 & 7); - RADIO_txPower = 0; - RADIO_calibration_CF = 0x30; - RADIO_calibration_D0 = 0x00; - RADIO_calibration_D1 = 0x49; - RADIO_calibration_D2 = 0x06; - RADIO_unk_D7 = 0x43; - RADIO_unk_E2 = 0x08; // setting bit 0x40 breaks rx entirely - RADIO_unk_83 = 0xe5; // maybe sync word? - - RADIO_unk_C8 = 0x7f; // setting bit 0x80 breaks rx entirely - RADIO_calibration_81 = 0xf0; // removing bit 0x20 breask rx and tx - RADIO_FLAGS |= 0x08; - RADIO_unk_D8 = 0; - RADIO_calibration_9D = 0x3f; // firts untpouched calib val - RADIO_calibration_A1 = 0x04; - RADIO_calibration_94 = 0x7f; // IOCFG0 ? - RADIO_unk_CE = 0x55; - RADIO_calibration_D3 = 0x30; - RADIO_calibration_D4 = 0xcc; - RADIO_calibration_D5 = 0xf6; - RADIO_calibration_86 = 0x40; // setting this to values like 0x20, 0x80, and 0x60 breaks auto-ack and maybe tx - RADIO_calibration_95 = 0x08; - RADIO_calibration_96 = 0xd3; - RADIO_calibration_70 = 0x01; - RADIO_calibration_71 = 0x40; - - RADIO_unk_A6 = 0x00; - RADIO_command = 0xC8; - RADIO_command = 0xC7; - RADIO_command = 0xC6; - RADIO_unk_AF = 0x60; // int enable (we need 0x60) - - RADIO_unk_AF |= 0x10; - - IEN_RF1 = 1; - - RADIO_FLAGS |= 8; -} diff --git a/zbs243_Tag_FW/soc/zbs243/radio.h b/zbs243_Tag_FW/soc/zbs243/radio.h deleted file mode 100644 index d5922781..00000000 --- a/zbs243_Tag_FW/soc/zbs243/radio.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _RADIO_H_ -#define _RADIO_H_ - -#include -#include - - -void RF_IRQ1(void) __interrupt (4); -void RF_IRQ2(void) __interrupt (5); -#define RADIO_PAD_LEN_BY 2 - -#include "../radioCommon.h" - - - - - -#endif - - - - diff --git a/zbs243_Tag_FW/soc/zbs243/sleep.c b/zbs243_Tag_FW/soc/zbs243/sleep.c deleted file mode 100644 index fa7acae3..00000000 --- a/zbs243_Tag_FW/soc/zbs243/sleep.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "sleep.h" -#include "cpu.h" - -void sleepForMsec(uint32_t length) -{ - __bit irqEn = IEN_EA; - uint8_t prescaler, cfgPg; - IEN_EA = 0; - - if (!length) - length = 0xfffffffful; - - RADIO_IRQ4_pending = 0; - UNK_C1 &=~ 0x81; - TCON &=~ 0x20; - cfgPg = CFGPAGE; - CFGPAGE = 4; - RADIO_command = 0xCA; - RADIO_command = 0xC5; - - if (length <= 0x00008000ul) { - - length <<= 5; - prescaler = 0x56; //0x56 = one tick is 1/32k of sec - } - else { - if (length != 0xfffffffful) - length += 500; - - length /= 1000; - prescaler = 0x16; //0x16 = one tick is 1 second - } - - if (length > 0x000fffff) { - - RADIO_SleepTimerLo = 0xff; - RADIO_SleepTimerMid = 0xff; - RADIO_SleepTimerHi = 0x0f; - } - else { - - RADIO_SleepTimerLo = length; - RADIO_SleepTimerMid = length >> 8; - RADIO_SleepTimerHi = ((uint8_t)(length >> 16)) & 0x0f; - } - - __asm__("nop"); - RADIO_SleepTimerSettings = prescaler; - __asm__("nop\nnop\nnop\nnop\n"); - RADIO_SleepTimerSettings |= 0x80; - __asm__("nop\nnop\n"); - RADIO_RadioPowerCtl = 0x44; - __asm__("nop\nnop\n"); - - CFGPAGE = cfgPg; - - //make sure time does not run backwards - TL0 = 0x0; - TH0 = 0xFF; - while (TH0 == 0xFF); - - UNK_C1 |= 0x81; - TCON |= 0x20; - - IEN_EA = irqEn; -} \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/soc.c b/zbs243_Tag_FW/soc/zbs243/soc.c deleted file mode 100644 index 36ab6f4e..00000000 --- a/zbs243_Tag_FW/soc/zbs243/soc.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "asmUtil.h" -#include "printf.h" -#include "screen.h" -#include "cpu.h" - - -void clockingAndIntsInit(void) -{ - IEN0 = 0; - CLKEN = 0x00; //timers only for now - CLKSPEED = 0x01; //fast crystal -} \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/soc.h b/zbs243_Tag_FW/soc/zbs243/soc.h deleted file mode 100644 index a9f50fa1..00000000 --- a/zbs243_Tag_FW/soc/zbs243/soc.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _SOCi_H_ -#define _SOCi_H_ - -#define PDATA -#include "zbs243.h" - -#include -#include "i2c.h" - - -#pragma callee_saves clockingAndIntsInit -void clockingAndIntsInit(void); - -#pragma callee_saves rndGen8 -uint8_t rndGen8(void); - -#pragma callee_saves rndGen32 -uint32_t rndGen32(void); - -#pragma callee_saves rndSeed -void rndSeed(uint8_t seedA, uint8_t seedB); - -#pragma callee_saves selfUpdate -void selfUpdate(void); - - -void TEMP_ISR(void) __interrupt (10); -//extern void I2C_IRQ(void) __interrupt (8); - -#endif diff --git a/zbs243_Tag_FW/soc/zbs243/spi.c b/zbs243_Tag_FW/soc/zbs243/spi.c deleted file mode 100644 index e2a8f7f6..00000000 --- a/zbs243_Tag_FW/soc/zbs243/spi.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "spi.h" -#include "cpu.h" - - -void spiInit(void) -{ - uint8_t bcp; - - //clock it up - CLKEN |= 0x08; - - //enable the unit - bcp = CFGPAGE; - CFGPAGE = 4; - SPIENA = 0x81; - CFGPAGE = bcp; -} - -uint8_t spiByte(uint8_t val) -{ - uint8_t bcp = CFGPAGE; - CFGPAGE = 4; - - SPITX = val; - SPICFG = 0xa0; //spi at 4mhz, mode 0 - while(SPICFG & 0x20); - val = SPIRX; - - CFGPAGE = bcp; - - return val; -} - -void spiTXByte(uint8_t val) -{ - uint8_t bcp = CFGPAGE; - CFGPAGE = 4; - SPITX = val; - SPICFG = 0xa0; //spi at 4mhz, mode 0 - while(SPICFG & 0x20); - CFGPAGE = bcp; -} \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/spi.h b/zbs243_Tag_FW/soc/zbs243/spi.h deleted file mode 100644 index b2aeb4aa..00000000 --- a/zbs243_Tag_FW/soc/zbs243/spi.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _SPI_ZBS_H_ -#define _SPI_ZBS_H_ - -#include - -//pre-configured for 4mhz mode 0, but can be changed - -#pragma callee_saves spiInit -void spiInit(void); - -#pragma callee_saves spiByte -uint8_t spiByte(uint8_t val); - -#pragma callee_saves spiTXByte -void spiTXByte(uint8_t val); - - - -#endif diff --git a/zbs243_Tag_FW/soc/zbs243/temperature.c b/zbs243_Tag_FW/soc/zbs243/temperature.c deleted file mode 100644 index 11b20544..00000000 --- a/zbs243_Tag_FW/soc/zbs243/temperature.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "asmUtil.h" -#include "flash.h" -#include "timer.h" -#include "cpu.h" - -static volatile uint8_t __xdata mTempRet[4]; - - -void TEMP_ISR(void) __interrupt (10) -{ - uint8_t i; - - i = CFGPAGE; - CFGPAGE = 4; - mTempRet[0] = TEMPRETH; - mTempRet[1] = TEMPRETL; - CFGPAGE = i; - IEN1 &=~ 0x10; -} - -int8_t adcSampleTemperature(void) -{ - uint16_t sum = 0; - uint8_t i; - - CLKEN |= 0x80; - - //adcConfig - i = CFGPAGE; - CFGPAGE = 4; - TEMPCFG = 0x81; //0x08 set when done - TEMPCAL2 = 0x22; - TEMPCAL1 = 0x55; - TEMPCAL4 = 0; - TEMPCAL3 = 0; - TEMPCAL6 = 3; - TEMPCAL5 = 0xff; - TEMPCFG &=~ 0x08; - CFGPAGE = i; - IEN1 &=~ 0x10; - //adcConfig over - - /* - TEMPCAL2: (seemingly analog settings: gain + ???) - removing 0x02 lowers vals a little (9%) \__ these stack just as you'd expect - setting 0x04 moves the values up a bit (18%) / - setting 0x08 adds 2.5% or so - 0x30 is ADC gain/bitness. (x4 for each increment) - 0x80 seems to make no difference - - TEMPCAL1: (seemingly analog settings) - removing 1 decreases value by 5.7% \__ these stack - removing 4 decreases by 22% / - removing 0x10 increments value by 1% - removnig 0x40 increases by 5% - - using 0xaa increases width but decreases average - - other TEMPCALx values seem to have no effect - */ - - for (i = 0; i < 9; i++) { - - //int on - IEN1 |= 0x10; - - //wait for it to self-turn-off - while (IEN1 & 0x10); - - if (i) { //skip first - - sum += ((uint16_t)mathPrvU8bitswap(mTempRet[0])) << 2; - if (mTempRet[1] & 1) - sum += 2; - if (mTempRet[1] & 2) - sum += 1; - } - - timerDelay(TIMER_TICKS_PER_SECOND / 10000); - } - //turn it off - CLKEN &=~ 0x80; - - //reuse tempRet to get calib data - if (!flashRead(FLASH_INFOPAGE_ADDR + 0x0b, mTempRet, 4) || (mTempRet[0] == 0xff && mTempRet[1] == 0xff) || (mTempRet[2] == 0xff && mTempRet[3] == 0xff)) { - - //no calibration data - reporting 20 degrees, same as stock firmware - return 20; - } - else { - - uint16_t __xdata valB = mathPrvU16from2xU8(mTempRet[0], mTempRet[1]); //temp sensor reading at 30 degrees C - uint16_t __xdata valD = mathPrvU16from2xU8(mTempRet[2], mTempRet[3]); //temp sensor reading at 45 degrees C - uint16_t __xdata slope = valD - valB; - - sum = (sum + 4) / 8; //average it - - //we can get 1/10 degree accuracy as this is well calibrated, but our api only need degrees so let's do that - /* - //high-precision code is this: - if (sum > valB) //our math routines are unsigned - temp = (uint16_t)mathPrvDiv32x16(mathPrvMul16x16(sum - valB, 150) + (slope / 2), slope) + 300; - else - temp = 300 - (uint16_t)mathPrvDiv32x16(mathPrvMul16x16(valB - sum, 150) + (slope / 2), slope); - */ - - if (sum > valB) //our math routines are unsigned - return mathPrvDiv16x8(5 + (uint16_t)mathPrvDiv32x16(mathPrvMul16x16(sum - valB, 150) + (slope / 2), slope), 10) + 30; - else - return 30 - mathPrvDiv16x8(5 + (uint16_t)mathPrvDiv32x16(mathPrvMul16x16(valB - sum, 150) + (slope / 2), slope), 10); - } -} \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/timer.c b/zbs243_Tag_FW/soc/zbs243/timer.c deleted file mode 100644 index 3f0d9ec1..00000000 --- a/zbs243_Tag_FW/soc/zbs243/timer.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "timer.h" -#include "cpu.h" - - -static volatile uint16_t mTmrHi; - -void T0_ISR(void) __interrupt (1) -{ - TCON &=~ 0x20; //clear flag - mTmrHi++; -} - -uint32_t timerGet(void) -{ - union { - struct { - uint8_t tL; - uint8_t tH; - uint16_t hi; - }; - uint32_t ret; - } val; - - do { - val.hi = mTmrHi; - val.tH = TH0; - val.tL = TL0; //read order is important due ot hardware buffering - } while (val.hi != mTmrHi || val.tH != TH0); - - return val.ret; -} - -uint8_t timerGetLowBits(void) -{ - return TL0; -} - -void timerInit(void) -{ - //clock up timers - CLKEN |= 0x01; - - - //stop and clear int flags - TCON &=~ 0xf0; - - //reset - mTmrHi = 0; - T0 = 0; - - //timer 0 in 16 bit mode, timer 1 off - TMOD = 0x31; - - //start - TCON |= 0x10; - - //int on - IEN_TMR0 = 1; -} - -void timerDelay(uint32_t ticks) -{ - uint32_t start = timerGet(); - while (timerGet() - start <= ticks); -} diff --git a/zbs243_Tag_FW/soc/zbs243/timer.h b/zbs243_Tag_FW/soc/zbs243/timer.h deleted file mode 100644 index 26aa216b..00000000 --- a/zbs243_Tag_FW/soc/zbs243/timer.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ - -#include - -#define TIMER_TICKS_PER_SECOND (16000000 / 12) //overflows every 53 minutes -#define TIMER_TICKS_PER_MS 1333UL -//this is a requirement by SDCC. is this prototype is missing when compiling main(), we get no irq handler -void T0_ISR(void) __interrupt (1); - - -void timerInit(void); - -#pragma callee_saves timerGet -uint32_t timerGet(void); - -#pragma callee_saves timerGetLowBits -uint8_t timerGetLowBits(void); //probaly only useful for random seeds - -void timerDelay(uint32_t ticks); - - - -#endif diff --git a/zbs243_Tag_FW/soc/zbs243/uart.c b/zbs243_Tag_FW/soc/zbs243/uart.c deleted file mode 100644 index 781ac714..00000000 --- a/zbs243_Tag_FW/soc/zbs243/uart.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "uart.h" -#include "cpu.h" - -#ifdef AP_FW -#include "stdbool.h" -#include "string.h" -#endif - -void uartInit(void) { - // clock it up - CLKEN |= 0x20; - // configure baud rate - UARTBRGH = 0x00; -#ifdef AP_FW - UARTBRGL = 69; // nice. 230400 baud - IEN_UART0 = 1; -#else - UARTBRGL = 0x8A; // config for 115200 -#endif - UARTSTA = 0x12; // also set the "empty" bit else we wait forever for it to go up -} - -#ifndef AP_FW -void uartTx(uint8_t val) { - while (!(UARTSTA & (1 << 1))) - ; - UARTSTA &= ~(1 << 1); - UARTBUF = val; -} -#else -extern uint8_t __xdata blockbuffer[]; - -volatile uint8_t txtail = 0; -volatile uint8_t txhead = 0; -uint8_t __xdata txbuf[256] = {0}; - -volatile uint8_t __idata rxtail = 0; -volatile uint8_t __idata rxhead = 0; -uint8_t __xdata rxbuf[256] = {0}; - -void uartTx(uint8_t val) { - __critical { - txbuf[txhead] = val; - if (txhead == txtail) { - UARTBUF = val; - } - txhead++; - } -} - -uint8_t uartRx() { - if (rxhead == rxtail) { - return 0; - } else { - uint8_t ret = rxbuf[rxtail]; - rxtail++; - return ret; - } -} - -uint8_t uartBytesAvail() { - return rxhead - rxtail; -} - -uint8_t* __idata blockp; -uint8_t __idata cmd[3]; -volatile bool __idata serialBypassActive = false; - -void checkcommand(uint8_t rx) { - for (uint8_t c = 0; c < 2; c++) { - cmd[c] = cmd[c + 1]; - } - cmd[2] = rx; - if (strncmp(cmd, ">D>", 3) == 0) { - blockp = blockbuffer; - serialBypassActive = true; - } -} - -void UART_IRQ1(void) __interrupt(0) { - if (UARTSTA & 1) { // RXC - UARTSTA &= 0xfe; - if (serialBypassActive) { - *blockp++ = UARTBUF; - if (blockp == (blockbuffer + 4100)) { - serialBypassActive = false; - } - } else { - rxbuf[rxhead] = UARTBUF; - rxhead++; - checkcommand(UARTBUF); - } - } - if (UARTSTA & 2) { // TXC - UARTSTA &= 0xfd; - txtail++; - if (txhead != txtail) { - UARTBUF = txbuf[txtail]; - } - } -} -#endif \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/uart.h b/zbs243_Tag_FW/soc/zbs243/uart.h deleted file mode 100644 index 3c389fec..00000000 --- a/zbs243_Tag_FW/soc/zbs243/uart.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _UART_ZBS_H_ -#define _UART_ZBS_H_ - -#include - -//pre-configured for 115200 8n1 -//RX can be done but i do not need it - -#pragma callee_saves uartInit -void uartInit(void); - -#pragma callee_saves uartTx -void uartTx(uint8_t val); - - -#ifdef AP_FW -void UART_IRQ1(void) __interrupt (0); - -#pragma callee_saves uartBytesAvail -uint8_t uartBytesAvail(void); - -#pragma callee_saves uartRX -uint8_t uartRx(); -#endif - -#endif - diff --git a/zbs243_Tag_FW/soc/zbs243/wdt.c b/zbs243_Tag_FW/soc/zbs243/wdt.c deleted file mode 100644 index f34887d7..00000000 --- a/zbs243_Tag_FW/soc/zbs243/wdt.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "cpu.h" -#include "wdt.h" - -void wdtOn(void) -{ - uint8_t cfgPageBck; - - cfgPageBck = CFGPAGE; - CFGPAGE = 4; - WDTCONF |= 0x80; - WDTENA = 1; - CFGPAGE = cfgPageBck; -} - -void wdtOff(void) -{ - uint8_t cfgPageBck; - - cfgPageBck = CFGPAGE; - CFGPAGE = 4; - WDTENA = 0; - WDTCONF &=~ 0x80; - CFGPAGE = cfgPageBck; -} - -void wdtPet(void) -{ - uint8_t cfgPageBck; - - cfgPageBck = CFGPAGE; - CFGPAGE = 4; - WDTPET = 0; - CFGPAGE = cfgPageBck; -} - -void wdtSetResetVal(uint32_t val) //also pets it -{ - uint8_t cfgPageBck; - - cfgPageBck = CFGPAGE; - CFGPAGE = 4; - WDTPET = 0; - WDTRSTVALH = val >> 16; - WDTRSTVALM = val >> 8; - WDTRSTVALL = val; - - CFGPAGE = cfgPageBck; -} - -void wdtDeviceReset(void) -{ - CFGPAGE = 4; - WDTCONF = 0x80; - WDTENA = 1; - WDTRSTVALH = 0xff; - WDTRSTVALM = 0xff; - WDTRSTVALL = 0xff; - while(1); -} \ No newline at end of file diff --git a/zbs243_Tag_FW/soc/zbs243/zbs243.h b/zbs243_Tag_FW/soc/zbs243/zbs243.h deleted file mode 100644 index 88315e3b..00000000 --- a/zbs243_Tag_FW/soc/zbs243/zbs243.h +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef _ZBS243_H_ -#define _ZBS243_H_ - -#include - -//P2 selects XPAGE which sucks for us -//IRAM is not at all mapped into XRAM -//id page is not in xram either - - -static __idata __at (0x00) unsigned char R0; -static __idata __at (0x01) unsigned char R1; -static __idata __at (0x02) unsigned char R2; -static __idata __at (0x03) unsigned char R3; -static __idata __at (0x04) unsigned char R4; -static __idata __at (0x05) unsigned char R5; -static __idata __at (0x06) unsigned char R6; -static __idata __at (0x07) unsigned char R7; -__sfr __at (0xf0) B; -__sfr __at (0xe0) ACC; -__sfr __at (0x82) DPL; -__sfr __at (0x83) DPH; -__sfr __at (0x84) DPL1; -__sfr __at (0x85) DPH1; -__sfr __at (0x92) DPS; //low bit switched DPTR -__sfr __at (0x87) PCON; //lower 4 bits as per 8051 spec, bit4 set disables xram - -__sfr __at (0xb2) PERFMON0; -__sfr __at (0xb3) PERFMON1; -__sfr __at (0xb4) PCH; //current PC...yes... -__sfr __at (0xb5) PCL; -__sfr __at (0xb6) PERFMON4; - - - -__sbit __at (0x80) P0_0; -__sbit __at (0x81) P0_1; -__sbit __at (0x82) P0_2; -__sbit __at (0x83) P0_3; -__sbit __at (0x84) P0_4; -__sbit __at (0x85) P0_5; -__sbit __at (0x86) P0_6; -__sbit __at (0x87) P0_7; -__sbit __at (0x90) P1_0; -__sbit __at (0x91) P1_1; -__sbit __at (0x92) P1_2; -__sbit __at (0x93) P1_3; -__sbit __at (0x94) P1_4; -__sbit __at (0x95) P1_5; -__sbit __at (0x96) P1_6; -__sbit __at (0x97) P1_7; -__sbit __at (0xa0) P2_0; -__sbit __at (0xa1) P2_1; -__sbit __at (0xa2) P2_2; -__sbit __at (0xa3) P2_3; -__sbit __at (0xa4) P2_4; -__sbit __at (0xa5) P2_5; -__sbit __at (0xa6) P2_6; -__sbit __at (0xa7) P2_7; - -__sbit __at (0xA8) IEN_UART0; -__sbit __at (0xA9) IEN_TMR0; -__sbit __at (0xAB) IEN_TMR1; -__sbit __at (0xAC) IEN_RF1; //enable for RF interrupt #1 (irq #2) -__sbit __at (0xAD) IEN_RF2; //enable for RF interrupt #2 (irq #5) -__sbit __at (0xAF) IEN_EA; - -//gpio configs (all in cfg page 0 only) -__sfr __at (0x80) P0; //RO for input pins, WO for output pins (written state not read back) -__sfr __at (0x90) P1; -__sfr __at (0xA0) P2; //disabled ot avoid accidental use -__sfr __at (0xA3) P0LVLSEL; //pin change interrupt edge desired. 0 - rising 1 - falling -__sfr __at (0xA4) P1LVLSEL; -__sfr __at (0xA5) P2LVLSEL; -__sfr __at (0xA6) P0INTEN; //pin change interrupt enable (1 = enabled). will wake device from sleep -__sfr __at (0xA7) P1INTEN; -__sfr __at (0xA9) P2INTEN; -__sfr __at (0xAA) P0CHSTA; //pin change status 1 = changed (remember to clear in ISR & before enabling ISR) -__sfr __at (0xAB) P1CHSTA; -__sfr __at (0xAC) P2CHSTA; -__sfr __at (0xAD) P0FUNC; //1 = func, 0 = gpio -__sfr __at (0xAE) P1FUNC; -__sfr __at (0xAF) P2FUNC; -__sfr __at (0xB9) P0DIR; //1 = in, 0 = out -__sfr __at (0xBA) P1DIR; -__sfr __at (0xBB) P2DIR; -__sfr __at (0xBC) P0PULL; //1 = pull up -__sfr __at (0xBD) P1PULL; -__sfr __at (0xBE) P2PULL; - -__sfr __at (0xA0) XPAGE; //sadly this is accurate! same as P2 - -//these are both avail in both config pages -__sfr __at (0xA8) IEN0; -__sfr __at (0xA1) IEN1; //low 1, bits unknown, top 7 bits eable irqs (7..13) - - -__sfr __at (0x8E) CLKSPEED; //top bit likely selects osc (1 = crystal??), next 3 set divisor FOR CPU, not periphs, bottom 4 unknown - -__sfr __at (0xB7) CLKEN; //one bit per periph to enable clocks. 0x08 - spi, 0x10 - i2c, 0x20 - uart, 0x80 temp sensor, 0x01 - in-cpu-timers(T0 & T1) - -__sfr __at (0x8F) RESET; //resets periphs AND stores reset cause. bit 0x01 - we were reset due to WDT, 0x04 - resets radio (Active high), 0x02 resets cpu core - -//wdt (accessible in CFG page 4), runs at about 62KHz. counter counts up, overflow causes reset -__sfr __at (0xBA) WDTENA; //low bit is used for WDT off. same SFR addr used as P1DIR when cfg page 0 -__sfr __at (0xBB) WDTPET; //write 0 to pet, write 0xff to reset immediately. same SFR addr used as P2DIR when cfg page 0 -__sfr __at (0xBC) WDTRSTVALL; //wdt reset value low -__sfr __at (0xBD) WDTRSTVALM; //wdt reset value mid -__sfr __at (0xBE) WDTRSTVALH; //wdt reset value high -__sfr __at (0xBF) WDTCONF; //top bit enable, 0x08 to hang instead of reset. top bit only accessible in CFG page 4 - - -//SPI (accessible in CFG page 4) -__sfr __at (0xEB) SPIUNKNOWN; //existing code sets 0x08 after a byte tx. no idea why. not doing it works -__sfr __at (0xEC) SPICFG; //0x80 - 1, 0x40 - 0, 0x20 - do TX (cleared on done), {0x10,0x08}) - clock div {4mhz,2mhz,1mhz,500khz}, 0x04 - CPHA, 0x02 - CPOL, 0x01 ?? (breaks rx, maybe bidirectional or rx off) -__sfr __at (0xED) SPIENA; //0x80 - 1, 0x01 - unit enable. stock code also enables/disables after every byte but i do not think we need to -__sfr __at (0xEE) SPITX; //tx buffer -__sfr __at (0xEF) SPIRX; //rx buffer - -//I2C (accessible in CFG page 0) -//it is in theory possible to drive it without IRQs but there seem to be hw bugs in figuring out when handling is needed, so i wouldn't. stock also doesn't -__sfr __at (0x91) I2CSTATE; //top 5 bits are current state: {???, START_SENT, RESTART_SENT, WR_ADDR_ACKED, WR_ADDR_NAKED, TX_BYTE_ACKED, TX_BYTE_NAKED, unused, RD_ADDR_ACKED, RD_ADDR_NAKED, RXED_BYTE} -//0x93 written by 0xe0 by stock but seems not needed -__sfr __at (0x94) I2CBUF; //data for RX/TX -__sfr __at (0x95) I2CCTL; //0x80 = irqOn (#8), 0x40 = master(?), 0x20 = start/restart, 0x10 = stop, 0x08 = irqReqd, 0x04 = sendAck (to RXed btes) -__sfr __at (0x96) I2CSPEED; //bottom 3 bits = dividerA. next 4 are dividerB. clock = 16MHz / ((dividerB ? 10 *(1 + dividerB) : 12) << dividerA) -__sfr __at (0xA2) I2CUNKNOWN; //4 ORRED at init or it will not work - - -//uart is basically hard wired to be a uart. clock is divided from 16MHz. only bottom 4 bits of BRGH are used. divisor is (BRGH:BRGL + 1) -__sbit __at (0x98) UART_RXF; -__sbit __at (0x99) UART_TXE; -__sfr __at (0x98) UARTSTA; //0x10 needed. 0x02 - have tx space, 0x01 - have rx byte. both can cause interrupts. both need to be cleared in irq. flag bits do NOT work if accessed using "jbc" -__sfr __at (0x99) UARTBUF; //fifo access -__sfr __at (0x9A) UARTBRGL; -__sfr __at (0x9B) UARTBRGH; //divisor for uart - -//timers (same as 8051-classic) -__sfr __at (0x88) TCON; -__sfr __at (0x89) TMOD; -__sfr __at (0x8A) TL0; -__sfr __at (0x8B) TL1; -__sfr __at (0x8C) TH0; -__sfr __at (0x8D) TH1; -__sfr16 __at (0x8C8A) T0; -__sfr16 __at (0x8D8B) T1; //used by timer code for storage - -//flash writing (must be done with CFGPAGE == 4). each page is 0x400 bytes -__sfr __at (0xD8) FPGNO; //page number (0x00..0x3f for main flash, 0x80 for info block) -__sfr __at (0xD9) FWRSRCL; //(flash source data for write).lo for write, (flash start offset in page).lo for read -__sfr __at (0xDA) FWRSRCH; //(flash source data for write).hi for write, (flash start offset in page).hi for read -__sfr __at (0xDB) FWRDSTL; //(flash start offset in page).lo for write, (dest xram addr).lo for read -__sfr __at (0xDC) FWRDSTH; //(flash start offset in page).hi for write, (dest xram addr).hi for read -__sfr __at (0xDD) FWRLENL; //(num bytes to write minus 1).lo -__sfr __at (0xDE) FWRLENH; //(num bytes to write minus 1).hi -__sfr __at (0xDF) FWRTHREE; //always written to three - - -//temp sensor (CLKEN bit 0x80). these only accessible in config page 4 -__sfr __at (0xE6) TEMPCAL1; //purpose guessed -__sfr __at (0xE7) TEMPCAL2; //purpose guessed - -__sfr __at (0xF7) TEMPCFG; //purpose guessed - -__sfr __at (0xF8) TEMPRETH; //has high 8 bits of result. bitswapped -__sfr __at (0xF9) TEMPRETL; //has low two bits of result in lower 2 bits. bitswapped - -__sfr __at (0xFB) TEMPCAL3; //purpose guessed -__sfr __at (0xFC) TEMPCAL4; //purpose guessed -__sfr __at (0xFD) TEMPCAL5; //purpose guessed -__sfr __at (0xFE) TEMPCAL6; //purpose guessed - -//radio regs (cfg page 4) -__sfr __at (0xC9) RADIO_TXPTRL; //xram pointer to tx buffer's "length" byte. low byte -__sfr __at (0xCA) RADIO_TXPTRH; //xram pointer to tx buffer's "length" byte. high byte -__sfr __at (0xCB) RADIO_INITSEQ1; -__sfr __at (0xCC) RADIO_INITSEQ2; -__sfr __at (0xCD) RADIO_TXLEN; //data bytes to send (not incl "len" byte or crc) -__sfr __at (0xCE) RADIO_INITSEQ0; -__sfr __at (0xD1) RADIO_INITSEQ4; -__sfr __at (0xD2) RADIO_INITSEQ5; -__sfr __at (0xD3) RADIO_RXPTRL; //xram pointer to tx buffer's "length" byte. low byte -__sfr __at (0xD4) RADIO_RXPTRH; //xram pointer to tx buffer's "length" byte. high byte -__sfr __at (0xD5) RADIO_RXLEN; //data bytes to RX (not incl "len" byte or crc) 2 more than this will be RXed -__sfr __at (0xD6) RADIO_INITSEQ3; - -//radio regs (any cfg page) -__sfr __at (0xFA) RADIO_GOTLEN; //size packet we GOT (incl len byte) - - - -//shared regs -__sfr __at (0xC1) UNK_C1; //in cfg page 4 only, purpose unknown - -__sfr __at (0xD7) TRIGGER; //in both cfg page, seach bit starts something. 0x08 starts flash op, 0x04 - start radio rx fifo dma, 0x02 - start radio tx fifo dma - - -//in cfg page 4 -__sfr __at (0xC7) SETTINGS; //misc settings incl flasg access. 0x18 is flash write, 0x08 is flash read, -__sfr __at (0xCF) TCON2; //interrupt flags (0x08 is flash write) - - - -__sfr __at (0xFF) CFGPAGE; //partially swaps SFR set to another. only 0x04 bit is used - - -/* - 84 85 92 B2 B3 B4 B5 B6 B8 are visible on both pages - - 93 98 9D 9E 9F B9 C1-C7 E0-E9 are swapped - - 86 9C B0 B1 C0 C8 EA F1-F6 ?????? - -*/ - - - -//radio MMIO - -static __xdata __at (0xdf48) unsigned char RADIO_command; -static __xdata __at (0xdf70) unsigned char RADIO_calibration_70; -static __xdata __at (0xdf71) unsigned char RADIO_calibration_71; -static __xdata __at (0xdf80) unsigned char RADIO_FLAGS; -static __xdata __at (0xdf81) unsigned char RADIO_calibration_81; -static __xdata __at (0xdf83) unsigned char RADIO_unk_83; -static __xdata __at (0xdf84) unsigned char RADIO_currentRSSI; -static __xdata __at (0xdf86) unsigned char RADIO_calibration_86; -static __xdata __at (0xdf88) unsigned char RADIO_ownMac_7; -static __xdata __at (0xdf89) unsigned char RADIO_ownMac_6; -static __xdata __at (0xdf8a) unsigned char RADIO_ownMac_5; -static __xdata __at (0xdf8b) unsigned char RADIO_ownMac_4; -static __xdata __at (0xdf8c) unsigned char RADIO_ownMac_3; -static __xdata __at (0xdf8d) unsigned char RADIO_ownMac_2; -static __xdata __at (0xdf8e) unsigned char RADIO_ownMac_1; -static __xdata __at (0xdf8f) unsigned char RADIO_ownMac_0; -static __xdata __at (0xdf90) unsigned char RADIO_PANID_Hi; -static __xdata __at (0xdf91) unsigned char RADIO_PANID_Lo; -static __xdata __at (0xdf92) unsigned char RADIO_ownShortAddress_Hi; -static __xdata __at (0xdf93) unsigned char RADIO_ownShortAddress_Lo; -static __xdata __at (0xdf94) unsigned char RADIO_calibration_94; -static __xdata __at (0xdf95) unsigned char RADIO_calibration_95; -static __xdata __at (0xdf96) unsigned char RADIO_calibration_96; -static __xdata __at (0xdf98) unsigned char RADIO_rxFirstByte; // first byte of the message actualyl RXed -static __xdata __at (0xdf9b) unsigned char RADIO_curRfState; // RFSTATUS ? -static __xdata __at (0xdf9d) unsigned char RADIO_calibration_9D; -static __xdata __at (0xdfa1) unsigned char RADIO_calibration_A1; -static __xdata __at (0xdfa5) unsigned char RADIO_unk_rxAckSta; //in irqh4, when RADIO_IRQ4_pending has 0x40 set, this is 0x04 if we got ack, and 0x02 if not -static __xdata __at (0xdfa6) unsigned char RADIO_unk_A6; -static __xdata __at (0xdfad) unsigned char RADIO_IRQ4_pending; -static __xdata __at (0xdfaf) unsigned char RADIO_unk_AF; -static __xdata __at (0xdfc0) unsigned char RADIO_channel; -static __xdata __at (0xdfc1) unsigned char RADIO_unk_C1; -static __xdata __at (0xdfc2) unsigned char RADIO_calibration_C2; -static __xdata __at (0xdfc3) unsigned char RADIO_calibration_C3; -static __xdata __at (0xdfc4) unsigned char RADIO_calibration_C4; -static __xdata __at (0xdfc5) unsigned char RADIO_calibration_C5; -static __xdata __at (0xdfc6) unsigned char RADIO_calibration_C6; -static __xdata __at (0xdfc7) unsigned char RADIO_calibration_C7; -static __xdata __at (0xdfc8) unsigned char RADIO_unk_C8; -static __xdata __at (0xdfc9) unsigned char RADIO_txPower; // 0..7 for -5..+8 dBm -static __xdata __at (0xdfca) unsigned char RADIO_unk_CA; -static __xdata __at (0xdfcb) unsigned char RADIO_perChannelSetting2; //relevant for tx -static __xdata __at (0xdfcd) unsigned char RADIO_unk_CD; -static __xdata __at (0xdfce) unsigned char RADIO_unk_CE; -static __xdata __at (0xdfcf) unsigned char RADIO_calibration_CF; -static __xdata __at (0xdfd0) unsigned char RADIO_calibration_D0; -static __xdata __at (0xdfd1) unsigned char RADIO_calibration_D1; -static __xdata __at (0xdfd2) unsigned char RADIO_calibration_D2; -static __xdata __at (0xdfd3) unsigned char RADIO_calibration_D3; -static __xdata __at (0xdfd4) unsigned char RADIO_calibration_D4; -static __xdata __at (0xdfd5) unsigned char RADIO_calibration_D5; -static __xdata __at (0xdfd7) unsigned char RADIO_unk_D7; -static __xdata __at (0xdfd8) unsigned char RADIO_unk_D8; -static __xdata __at (0xdfd9) unsigned char RADIO_SleepTimerHi; //only bottom 4 bits implemented, counts down to wake -static __xdata __at (0xdfda) unsigned char RADIO_SleepTimerMid; -static __xdata __at (0xdfdb) unsigned char RADIO_SleepTimerLo; -static __xdata __at (0xdfe2) unsigned char RADIO_unk_E2; -static __xdata __at (0xdff0) unsigned char RADIO_unk_F0; -static __xdata __at (0xdff3) unsigned char RADIO_SleepTimerSettings; //0x16 for one second tick, 0x56 for 1/32k second tick -static __xdata __at (0xdff4) unsigned char RADIO_RadioPowerCtl; -static __xdata __at (0xdffd) unsigned char RADIO_perChannelSetting1; //relevant fo rRX - -#define RADIO_CMD_RECEIVE 0xc2 //tx always goes to RX anyways -#define RADIO_CMD_FLUSH_RX_FIFO 0xc6 -#define RADIO_CMD_FLUSH_TX_FIFO 0xc7 -#define RADIO_CMD_LOAD_TX_FIFO 0xcb - - -#endif diff --git a/zbs243_Tag_FW/wdt.h b/zbs243_Tag_FW/wdt.h deleted file mode 100644 index aa7b33d9..00000000 --- a/zbs243_Tag_FW/wdt.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _WDT_H_ -#define _WDT_H_ - -#include - - -#pragma callee_saves wdtOn -void wdtOn(void); - -#pragma callee_saves wdtOff -void wdtOff(void); - -#pragma callee_saves wdtPet -void wdtPet(void); - -#pragma callee_saves wdtSetResetVal -void wdtSetResetVal(uint32_t val); //speed is CPU-specific. On ZBS it is 62KHz or so - -#pragma callee_saves wdtDeviceReset -void wdtDeviceReset(void); - -#define wdt10s() \ - do { \ - wdtSetResetVal(0xFFF68A1F); \ - wdtOn(); \ - } while (0) - -#define wdt30s() \ - do { \ - wdtSetResetVal(0xFFE39E5F); \ - wdtOn(); \ - } while (0) - -#define wdt60s() \ - do { \ - wdtSetResetVal(0xFFC73CBF); \ - wdtOn(); \ - } while (0) - - -#define wdt120s() \ - do { \ - wdtSetResetVal(0xFF8E797F); \ - wdtOn(); \ - } while (0) - -#endif diff --git a/zbs243_Tag_FW/wdt.h b/zbs243_Tag_FW/wdt.h new file mode 120000 index 00000000..7992b8da --- /dev/null +++ b/zbs243_Tag_FW/wdt.h @@ -0,0 +1 @@ +../zbs243_shared/wdt.h \ No newline at end of file