even moar symlinks

This commit is contained in:
jjwbruijn
2023-03-28 00:09:01 +02:00
parent 92870a8886
commit 7bd0c8c815
80 changed files with 15 additions and 8060 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,114 +0,0 @@
#ifndef _ASM_UTIL_H_
#define _ASM_UTIL_H_
#include <stdint.h>
#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

1
zbs243_Tag_FW/asmUtil.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/asmUtil.h

View File

@@ -1,101 +0,0 @@
#include <stdbool.h>
#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;
}

1
zbs243_Tag_FW/barcode.c Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/barcode.c

View File

@@ -1,29 +0,0 @@
#ifndef _BARCODE_H_
#define _BARCODE_H_
#include <stdint.h>
//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

1
zbs243_Tag_FW/barcode.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/barcode.h

View File

@@ -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 <stdint.h>
#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

1
zbs243_Tag_FW/bitmaps.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/bitmaps.h

1
zbs243_Tag_FW/board Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/board

View File

@@ -1,52 +0,0 @@
#ifndef _BOARD_COMMON_H_
#define _BOARD_COMMON_H_
#include <stdint.h>
#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

View File

@@ -1,160 +0,0 @@
#include <stdbool.h>
#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"
);
}

View File

@@ -1,817 +0,0 @@
#include <stdbool.h>
#include <string.h>
#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();
}

View File

@@ -1,76 +0,0 @@
#ifndef _JSCREEN_H_
#define _JSCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

View File

@@ -1,787 +0,0 @@
#include "uc8151.h"
#include <stdbool.h>
#include <string.h>
#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[];

View File

@@ -1,74 +0,0 @@
#ifndef _JSCREEN_H_
#define _JSCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

View File

@@ -1 +0,0 @@
#include "../boardZBS29common.c"

View File

@@ -1,28 +0,0 @@
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -1 +0,0 @@
#include "../ssd1619.c"

View File

@@ -1,26 +0,0 @@
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

View File

@@ -1 +0,0 @@
#include "../boardZBS29common.c"

View File

@@ -1,28 +0,0 @@
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -1 +0,0 @@
#include "../uc8151.c"

View File

@@ -1,25 +0,0 @@
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

View File

@@ -1 +0,0 @@
#include "../boardZBS29common.c"

View File

@@ -1,28 +0,0 @@
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -1 +0,0 @@
#include "../ssd1619.c"

View File

@@ -1,26 +0,0 @@
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

View File

@@ -1 +0,0 @@
#include "../boardZBS29common.c"

View File

@@ -1,28 +0,0 @@
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -1 +0,0 @@
#include "../ssd1619.c"

View File

@@ -1,27 +0,0 @@
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#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

0
zbs243_Tag_FW/buildfw.sh Normal file → Executable file
View File

1
zbs243_Tag_FW/cpu Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/cpu

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
//nothing

View File

@@ -1,18 +0,0 @@
#ifndef _CPUi_H_
#define _CPUi_H_
#include <stdint.h>
typedef uint16_t uintptr_near_t;
#define VERSIONMARKER __at (0x008b)
#define irqsOn() IEN_EA = 1
#include "soc.h"
#endif

View File

@@ -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

View File

@@ -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
}

View File

@@ -1,799 +0,0 @@
#include "printf.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#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;
}

View File

@@ -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"
);
}

View File

@@ -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);
}

1
zbs243_Tag_FW/eeprom.c Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/eeprom.c

View File

@@ -1,51 +0,0 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdbool.h>
#include <stdint.h>
#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

1
zbs243_Tag_FW/eeprom.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/eeprom.h

View File

@@ -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
};

1
zbs243_Tag_FW/font.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/font.h

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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;

1
zbs243_Tag_FW/lut.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/lut.h

View File

@@ -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

1
zbs243_Tag_FW/printf.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/printf.h

View File

@@ -1,188 +0,0 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#define __packed
#include <stdint.h>
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

1
zbs243_Tag_FW/proto.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/proto.h

View File

@@ -1,10 +0,0 @@
#ifndef _SLEEP_H_
#define _SLEEP_H_
#include <stdint.h>
void sleepForMsec(uint32_t msec);
void sleepTillInt(void); //assumes you left only one int enabled!
#endif

1
zbs243_Tag_FW/sleep.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/sleep.h

1
zbs243_Tag_FW/soc Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/soc

View File

@@ -1,55 +0,0 @@
#ifndef _RADIO_COMMON_H_
#define _RADIO_COMMON_H_
#include <stdbool.h>
#include <stdint.h>
//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

View File

@@ -1,182 +0,0 @@
#include <stdbool.h>
#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;
}

View File

@@ -1,23 +0,0 @@
#ifndef _FLASH_ZBS_H_
#define _FLASH_ZBS_H_
#include <stdint.h>
#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

View File

@@ -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;
}

View File

@@ -1,34 +0,0 @@
#ifndef _I2C_H_
#define _I2C_H_
#include <stdint.h>
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

View File

@@ -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

View File

@@ -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.<<code:00006D7B radioRxEnable>>
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;
}

View File

@@ -1,22 +0,0 @@
#ifndef _RADIO_H_
#define _RADIO_H_
#include <stdbool.h>
#include <stdint.h>
void RF_IRQ1(void) __interrupt (4);
void RF_IRQ2(void) __interrupt (5);
#define RADIO_PAD_LEN_BY 2
#include "../radioCommon.h"
#endif

View File

@@ -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;
}

View File

@@ -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
}

View File

@@ -1,30 +0,0 @@
#ifndef _SOCi_H_
#define _SOCi_H_
#define PDATA
#include "zbs243.h"
#include <stdint.h>
#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

View File

@@ -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;
}

View File

@@ -1,19 +0,0 @@
#ifndef _SPI_ZBS_H_
#define _SPI_ZBS_H_
#include <stdint.h>
//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

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -1,24 +0,0 @@
#ifndef _TIMER_H_
#define _TIMER_H_
#include <stdint.h>
#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

View File

@@ -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

View File

@@ -1,27 +0,0 @@
#ifndef _UART_ZBS_H_
#define _UART_ZBS_H_
#include <stdint.h>
//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

View File

@@ -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);
}

View File

@@ -1,289 +0,0 @@
#ifndef _ZBS243_H_
#define _ZBS243_H_
#include <stdint.h>
//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

View File

@@ -1,47 +0,0 @@
#ifndef _WDT_H_
#define _WDT_H_
#include <stdint.h>
#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

1
zbs243_Tag_FW/wdt.h Symbolic link
View File

@@ -0,0 +1 @@
../zbs243_shared/wdt.h