Merge remote-tracking branch 'upstream/master' into development

This commit is contained in:
Nic Limper
2023-02-01 19:51:29 +01:00
44 changed files with 2907 additions and 3137 deletions

View File

@@ -3,9 +3,9 @@ BUILD ?= zbs29v033
#file containing main() must be first!
SOURCES += main.c eeprom.c drawing.c
SOURCES += comms.c chars.c
SOURCES += syncedproto.c
SOURCES += comms.c
SOURCES += syncedproto.c epd.c userinterface.c
SOURCES += powermgt.c barcode.c
all: #make sure it is the first target
@@ -18,21 +18,7 @@ FLAGS += -Icpu/$(CPU)
SOURCES += cpu/$(CPU)/cpu.c
SOURCES += board/$(BUILD)/board.c
SOURCES += board/$(BUILD)/screen.c
ifeq ($(BARCODE),barcode)
FLAGS += -DBARCODE
SOURCES += barcode.c
else ifeq ($(BARCODE),datamatrix)
# FLAGS += -DDATAMATRIX
# SOURCES += datamatrix.c
#i might release this later, but for now, just use barcodes :P
FLAGS += -DBARCODE
SOURCES += barcode.c
else
SOURCES += $(warning "no barcode type set")
endif
#SOURCES += board/$(BUILD)/screen.c
EEPROMDRV ?= eeprom.c

View File

@@ -1,16 +0,0 @@
#ifndef _ADC_H_
#define _ADC_H_
#include <stdint.h>
extern uint16_t __xdata mAdcSlope;
extern uint16_t __xdata mAdcIntercept;
uint16_t adcSampleBattery(void); //in mV
int8_t adcSampleTemperature(void); //in degrees C
#endif

210
tag_fw/bitmaps.h Normal file
View File

@@ -0,0 +1,210 @@
#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>
static const uint8_t __code solum[] = {
128, 26,
0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0xfc,
0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x03, 0xfc,
0x00, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x07, 0xfc,
0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x0f, 0xfc,
0x00, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xc0, 0x78, 0x03, 0x80, 0x1c, 0x01, 0xff, 0x80, 0x0f, 0xf8,
0x00, 0xff, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x78, 0x07, 0xc0, 0x3e, 0x01, 0xff, 0x80, 0x1f, 0xf8,
0x01, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xf8, 0xf8, 0x07, 0xc0, 0x3e, 0x01, 0xff, 0x80, 0x3e, 0xf8,
0x01, 0xfe, 0x03, 0xfe, 0x0f, 0xe1, 0xfc, 0xf8, 0x0f, 0x80, 0x7c, 0x03, 0xef, 0x80, 0x7d, 0xf8,
0x01, 0xfe, 0x00, 0x7f, 0x0f, 0x80, 0xfc, 0xf8, 0x0f, 0x80, 0x7c, 0x03, 0xef, 0x80, 0x7d, 0xf0,
0x01, 0xff, 0x80, 0x3f, 0x9f, 0x00, 0x7c, 0xf0, 0x0f, 0x80, 0x7c, 0x03, 0xe7, 0xc0, 0xf9, 0xf0,
0x00, 0x7f, 0xf0, 0x3f, 0xbf, 0x00, 0x7d, 0xf0, 0x0f, 0x00, 0x78, 0x03, 0xe7, 0xc1, 0xf1, 0xf0,
0x00, 0x00, 0x00, 0x3f, 0xbe, 0x00, 0x7d, 0xf0, 0x1f, 0x00, 0xf8, 0x07, 0xc7, 0xc3, 0xf3, 0xe0,
0x00, 0x00, 0x00, 0x7f, 0xbc, 0x00, 0x7d, 0xe0, 0x1f, 0x00, 0xf8, 0x07, 0xc7, 0xc3, 0xe3, 0xe0,
0x00, 0x00, 0x01, 0xff, 0x7c, 0x00, 0x7f, 0xe0, 0x1f, 0x00, 0xf0, 0x07, 0xc3, 0xc7, 0xc3, 0xe0,
0x00, 0x00, 0x03, 0xff, 0x7c, 0x00, 0x7f, 0xe0, 0x1e, 0x01, 0xf0, 0x07, 0xc3, 0xef, 0x87, 0xe0,
0x00, 0x00, 0x0f, 0xfc, 0x7c, 0x00, 0xfb, 0xe0, 0x3e, 0x01, 0xf0, 0x0f, 0x83, 0xef, 0x87, 0xc0,
0x00, 0x00, 0x3f, 0xf8, 0x7c, 0x01, 0xfb, 0xc0, 0x3e, 0x01, 0xe0, 0x0f, 0x83, 0xff, 0x07, 0xc0,
0x00, 0x00, 0xff, 0xf0, 0x7c, 0x01, 0xf7, 0xc0, 0x3e, 0x03, 0xe0, 0x0f, 0x83, 0xfe, 0x07, 0xc0,
0x00, 0x07, 0xff, 0xc0, 0x7e, 0x07, 0xe7, 0xc0, 0x3e, 0x07, 0xc0, 0x0f, 0x81, 0xfe, 0x0f, 0xc0,
0x00, 0x3f, 0xff, 0x00, 0x3f, 0x9f, 0xc7, 0xff, 0xbf, 0x9f, 0xc0, 0x1f, 0x01, 0xfc, 0x0f, 0x80,
0x01, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0x87, 0xff, 0x9f, 0xff, 0x80, 0x1f, 0x01, 0xf8, 0x0f, 0x80,
0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xfe, 0x07, 0xff, 0x8f, 0xfe, 0x00, 0x1f, 0x01, 0xf0, 0x1f, 0x80,
};
static const uint8_t __code hacked[] = {
112, 56,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x03, 0xff, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x87, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x87, 0xc3, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x87, 0x83, 0xf8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x81, 0xfb, 0x8f, 0x03, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x03, 0x81, 0xf3, 0x8f, 0x03, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x07, 0x81, 0xe7, 0x8f, 0x07, 0xbf,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x07, 0x81, 0xc7, 0x8f, 0x07, 0x9f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x07, 0x81, 0xc7, 0x87, 0x8f, 0x8f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x07, 0x01, 0xcf, 0x07, 0x9f, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x0f, 0x01, 0xef, 0x07, 0xff, 0x00,
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe1, 0xf8, 0x0f, 0x01, 0xff, 0x03, 0xfe, 0x00,
0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0x0f, 0x01, 0xfe, 0x03, 0xfc, 0x00,
0x38, 0x07, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x7c, 0x1e, 0x00, 0xff, 0xf0, 0x00, 0x00,
0x3c, 0x07, 0x80, 0x00, 0x00, 0x01, 0xe0, 0x3e, 0x1e, 0x00, 0xff, 0xf0, 0x00, 0x00,
0x3c, 0x07, 0x80, 0x00, 0x00, 0x03, 0xe0, 0x1f, 0x1e, 0x00, 0x3f, 0xf0, 0x00, 0x00,
0x3e, 0x07, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x1f, 0x9f, 0xe0, 0x1f, 0xc0, 0x00, 0x00,
0x1e, 0x03, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
0x1f, 0x03, 0xc0, 0x00, 0x00, 0x07, 0x80, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
0x0f, 0x03, 0xe0, 0x03, 0xc0, 0x07, 0x80, 0x03, 0xfc, 0xff, 0xc0, 0x00, 0x00, 0x00,
0x0f, 0x01, 0xe0, 0x07, 0xc0, 0x07, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0x81, 0xfc, 0x07, 0xf8, 0x07, 0x80, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x81, 0xfc, 0x0f, 0xf8, 0x07, 0x80, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x80, 0xfc, 0x0f, 0x7c, 0x07, 0xc0, 0x78, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xc0, 0xfc, 0x0f, 0x7e, 0x03, 0xe0, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xc3, 0xfc, 0x0e, 0x3e, 0x03, 0xf3, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xdf, 0xfc, 0x0e, 0x3f, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xff, 0xfe, 0x0e, 0x1f, 0x80, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xff, 0x9e, 0x0f, 0x1f, 0x80, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xfc, 0x1e, 0x0f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xf0, 0x1f, 0x0f, 0xbf, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xf0, 0x0f, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xf8, 0x0f, 0x87, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x78, 0x07, 0x83, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x78, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3e, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1e, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
};
#endif

View File

@@ -7,9 +7,10 @@
#include "spi.h"
#include "cpu.h"
#include "wdt.h"
#include "adc.h"
#include "i2c.h"
//extern uint8_t __xdata* tempBuffer;
uint8_t __xdata tempBuffer[320];
void powerPortsDownForSleep(void)
{
@@ -148,12 +149,12 @@ 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 = mScreenRow;
uint8_t __xdata *dst = tempBuffer;
for (i = len; i ; i--)
*dst++ = *src++;
if (!flashWrite(0xfc00, mScreenRow, len, true))
if (!flashWrite(0xfc00, tempBuffer, len, true))
pr("failed to write updater\n");
IEN_EA = 0; //ints off

View File

@@ -4,27 +4,11 @@
#include <stdint.h>
#include "spi.h"
#include "uart.h"
//colors for ui messages
#define UI_MSG_MAGNIFY1 1
#define UI_MSG_MAGNIFY2 1
#define UI_MSG_MAGNIFY3 1
#define UI_MSG_BACK_COLOR 4
#define UI_MSG_FORE_COLOR_1 0
#define UI_MSG_FORE_COLOR_2 5
#define UI_MSG_FORE_COLOR_3 5
#define UI_BARCODE_VERTICAL
#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)
//debug uart (enable only when needed, on some boards it inhibits eeprom access)
#define dbgUartOn()
#define dbgUartOff()
#define dbgUartByte uartTx
//eeprom map
#define EEPROM_SETTINGS_AREA_START (0x01000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
@@ -35,19 +19,10 @@
//till end of eeprom really. do not put anything after - it will be erased at pairing time!!!
#define EEPROM_PROGRESS_BYTES (128)
//radio cfg
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
#define RADIO_NUM_CHANNELS (1)
//hw types
#define HW_TYPE_NORMAL HW_TYPE_154_INCH_ZBS_033
#define HW_TYPE_CYCLING HW_TYPE_154_INCH_ZBS_033_FRAME_MODE
#include "../boardCommon.h"
#endif
#endif

View File

@@ -1,475 +0,0 @@
#include "screen.h"
#include <stdbool.h>
#include "adc.h"
#include "asmUtil.h"
#include "board.h"
#include "cpu.h"
#include "printf.h"
#include "sleep.h"
#include "spi.h"
#include "timer.h"
uint8_t __xdata mScreenRow[320];
static __bit mInited = false, mPartial;
static uint8_t __xdata mPassNo;
#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
static const uint8_t __code mColorMap[][6] =
{
// colors are: B, DG, G, LG, W, R
// phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
{
1, 1, 1, 1, 0, 0, // lo plane (B)
},
{
0, 0, 0, 0, 0, 1, // hi plane (R)
}};
static const uint8_t __code partial_lut[] = {
// lut0 (KEEP) voltages
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// lut1 (W2B) voltages
0x80,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// lut2 (B2W) voltages
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// lut3 (unused) voltages
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// lut4 (vcom) voltages
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
// group0 phase lengths and repeat count
45,
0x00,
0x00,
0x00,
0x00,
// group1 not used
0x00,
0x00,
0x00,
0x00,
0x00,
// group2 not used
0x00,
0x00,
0x00,
0x00,
0x00,
// group3 phase lengths and repeat count
0x00,
0x00,
0x00,
0x00,
0x00,
// group4 phase lengths and repeat count
0x00,
0x00,
0x00,
0x00,
0x00,
// group5 phase lengths and repeat count
0x00,
0x00,
0x00,
0x00,
0x00,
// group6 phase lengths and repeat count
0x00,
0x00,
0x00,
0x00,
0x00,
};
#define einkPrvSelect() \
do { \
P1_7 = 0; \
} while (0)
#define einkPrvDeselect() \
do { \
P1_7 = 1; \
} while (0)
// urx pin
#define einkPrvMarkCommand() \
do { \
P2_2 = 0; \
} while (0)
#define einkPrvMarkData() \
do { \
P2_2 = 1; \
} while (0)
#pragma callee_saves einkPrvCmd
static void einkPrvCmd(uint8_t cmd) // sets chip select
{
einkPrvSelect();
einkPrvMarkCommand();
spiByte(cmd);
}
#pragma callee_saves einkPrvData
static void einkPrvData(uint8_t byte) {
einkPrvMarkData();
spiByte(byte);
}
#pragma callee_saves einkPrvCmdWithOneByte
static void einkPrvCmdWithOneByte(uint16_t vals) // passing in one u16 is better than two params cause SDCC sucks
{
einkPrvCmd(vals >> 8);
einkPrvData(vals);
einkPrvDeselect();
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeout(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)
;
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeoutSleep(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);
P2CHSTA &= 0xfd;
P2INTEN &= 0xfd;
P2FUNC = tmp_P2FUNC;
P2DIR = tmp_P2DIR;
P2PULL = tmp_P2PULL;
P2LVLSEL = tmp_P2LVLSEL;
/*if (!P2_1)
return;
pr("screen timeout\n");
while(1);*/
}
#pragma callee_saves einkPrvReadByte
static uint8_t einkPrvReadByte(void) {
uint8_t val = 0, i;
P0DIR = (P0DIR & ~(1 << 0)) | (1 << 1);
P0 &= ~(1 << 0);
P0FUNC &= ~((1 << 0) | (1 << 1));
P2_2 = 1;
for (i = 0; i < 8; i++) {
P0_0 = 1;
__asm__("nop\nnop\nnop\nnop\nnop\n");
val <<= 1;
if (P0_1)
val++;
P0_0 = 0;
__asm__("nop\nnop\nnop\nnop\nnop\n");
}
// set up pins for spi (0.0,0.1,0.2)
P0FUNC |= (1 << 0) | (1 << 1);
return val;
}
#pragma callee_saves einkPrvReadStatus
static uint8_t einkPrvReadStatus(void) {
uint8_t sta;
einkPrvCmd(0x2f);
sta = einkPrvReadByte();
einkPrvDeselect();
return sta;
}
#pragma callee_saves screenPrvStartSubPhase
static void screenPrvStartSubPhase(__bit redSubphase) {
einkPrvCmd(0x4e);
einkPrvData(0);
einkPrvDeselect();
einkPrvCmd(0x4f);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmd(redSubphase ? 0x26 : 0x24);
einkPrvDeselect();
}
void moveToXY(uint8_t x, uint16_t y, bool color) {
einkPrvCmd(0x4e);
einkPrvData(x);
einkPrvDeselect();
einkPrvCmd(0x4f);
einkPrvData((uint8_t)(y & 0xFF));
einkPrvData((uint8_t)(y >> 8));
einkPrvDeselect();
einkPrvCmd(color ? 0x26 : 0x24);
einkPrvDeselect();
}
#pragma callee_saves screenInitIfNeeded
static void screenInitIfNeeded(__bit forPartial) {
if (mInited)
return;
mInited = true;
mPartial = forPartial;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 0;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 1;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
einkPrvCmd(0x12); // software reset
einkPrvDeselect();
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
einkPrvCmdWithOneByte(0x7454);
einkPrvCmdWithOneByte(0x7e3b);
einkPrvCmd(0x2b);
einkPrvData(0x04);
einkPrvData(0x63);
einkPrvDeselect();
einkPrvCmd(0x0c); // they send 8f 8f 8f 3f
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x3f);
einkPrvDeselect();
einkPrvCmd(0x01);
einkPrvData(0x97);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x1103);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
einkPrvCmd(0x20);
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 10);
einkPrvCmd(0x44);
einkPrvData(0x00);
einkPrvData(SCREEN_WIDTH / 8 - 1);
einkPrvDeselect();
einkPrvCmd(0x45);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvData(0x97);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x3c01); // border will be HiZ
einkPrvDeselect();
einkPrvCmdWithOneByte(0x1880); // internal temp sensor
einkPrvCmdWithOneByte(0x2108);
// turn on clock & analog
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (forPartial) {
einkPrvCmd(0x32);
for (int i = 0; i < sizeof(partial_lut); i++)
einkPrvData(partial_lut[i]);
}
einkPrvDeselect();
}
#pragma callee_saves screenPrvDraw
static void screenPrvDraw(void) {
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_REFRESH);
einkPrvCmd(0x20); // do actions
if (0) {
einkPrvWaitWithTimeoutSleep(1000 * 60UL);
screenSleep();
} else {
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 60UL);
}
}
__bit screenTxStart(__bit forPartial) {
screenInitIfNeeded(forPartial);
mPassNo = 0;
screenPrvStartSubPhase(false);
return true;
}
void screenEndPass(void) {
switch (mPassNo) {
case 0:
screenPrvStartSubPhase(true);
break;
default:
return;
}
mPassNo++;
}
void screenTxEnd(void) {
screenPrvDraw();
screenShutdown();
}
void screenShutdown(void) {
if (!mInited)
return;
mInited = false;
einkPrvCmdWithOneByte(0x1003); // shut down
}
void screenSleep(void) {
P2_0 = 0;
timerDelay(10);
P2_0 = 1;
timerDelay(50);
einkPrvCmd(0x12); // software reset
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND / 250);
einkPrvCmdWithOneByte(0x1003); // shut down
}
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte) {
static uint8_t __xdata prev, step = 0;
prev <<= 2;
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
if (++step == 4) {
step = 0;
einkPrvSelect();
einkPrvData(prev);
einkPrvDeselect();
}
}
void screenByteRawTx(uint8_t byte) {
einkPrvSelect();
einkPrvData(byte);
einkPrvDeselect();
}
// yes this is here...
uint16_t adcSampleBattery(void) {
__bit wasInited = mInited;
uint16_t voltage = 2600;
if (!mInited)
screenInitIfNeeded(false);
uint8_t val;
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
for (val = 3; val < 8; val++) {
einkPrvCmdWithOneByte(0x1500 + val);
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (einkPrvReadStatus() & 0x10) { // set if voltage is less than threshold ( == 1.9 + val / 10)
voltage = 1850 + mathPrvMul8x8(val, 100);
break;
}
}
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (!wasInited)
screenShutdown();
return voltage;
}

View File

@@ -4,12 +4,6 @@
#include <stdbool.h>
#include <stdint.h>
//i hate globals, but for 8051 this makes life a lot easier, sorry :(
extern uint8_t __xdata mScreenVcom;
extern int8_t __xdata mCurTemperature;
#define SCREEN_WIDTH 152
#define SCREEN_HEIGHT 152
@@ -27,24 +21,5 @@ extern int8_t __xdata mCurTemperature;
#define SCREEN_DATA_PASSES 2
void screenShutdown(void);
void screenTest(void);
__bit screenTxStart(__bit forPartial);
void screenEndPass(void); //at end of each pass
void moveToXY(uint8_t x, uint16_t y, bool red);
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte);
void screenByteRawTx(uint8_t byte);
void screenTxEnd(void);
void screenSleep(void);
extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight
#endif
#endif

View File

@@ -4,27 +4,11 @@
#include <stdint.h>
#include "spi.h"
#include "uart.h"
//colors for ui messages
#define UI_MSG_MAGNIFY1 1
#define UI_MSG_MAGNIFY2 1
#define UI_MSG_MAGNIFY3 1
#define UI_MSG_BACK_COLOR 4
#define UI_MSG_FORE_COLOR_1 0
#define UI_MSG_FORE_COLOR_2 5
#define UI_MSG_FORE_COLOR_3 5
#define UI_BARCODE_VERTICAL
#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)
//debug uart (enable only when needed, on some boards it inhibits eeprom access)
#define dbgUartOn()
#define dbgUartOff()
#define dbgUartByte uartTx
//eeprom map
#define EEPROM_SETTINGS_AREA_START (0x01000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
@@ -35,19 +19,10 @@
//till end of eeprom really. do not put anything after - it will be erased at pairing time!!!
#define EEPROM_PROGRESS_BYTES (128)
//radio cfg
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
#define RADIO_NUM_CHANNELS (1)
//hw types
#define HW_TYPE_NORMAL HW_TYPE_29_INCH_ZBS_026
#define HW_TYPE_CYCLING HW_TYPE_29_INCH_ZBS_026_FRAME_MODE
#include "../boardCommon.h"
#endif
#endif

View File

@@ -1,397 +0,0 @@
#include <stdbool.h>
#include "asmUtil.h"
#include "screen.h"
#include "printf.h"
#include "board.h"
#include "timer.h"
#include "sleep.h"
#include "adc.h"
#include "cpu.h"
#include "spi.h"
uint8_t __xdata mScreenRow[320];
static __bit mInited = false, mPartial;
static uint8_t __xdata mPassNo;
#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
static const uint8_t __code mColorMap[][6] =
{
// colors are: B, DG, G, LG, W, R
// phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
{
1, 1, 1, 1, 0, 0, // lo plane (B)
},
{
0, 0, 0, 0, 0, 1, // hi plane (R)
}};
#define einkPrvSelect() \
do \
{ \
P1_7 = 0; \
} while (0)
#define einkPrvDeselect() \
do \
{ \
P1_7 = 1; \
} while (0)
// urx pin
#define einkPrvMarkCommand() \
do \
{ \
P2_2 = 0; \
} while (0)
#define einkPrvMarkData() \
do \
{ \
P2_2 = 1; \
} while (0)
#pragma callee_saves einkPrvCmd
static void einkPrvCmd(uint8_t cmd) // sets chip select
{
einkPrvSelect();
einkPrvMarkCommand();
spiByte(cmd);
}
#pragma callee_saves einkPrvData
static void einkPrvData(uint8_t byte)
{
einkPrvMarkData();
spiByte(byte);
}
#pragma callee_saves einkPrvCmdWithOneByte
static void einkPrvCmdWithOneByte(uint16_t vals) // passing in one u16 is better than two params cause SDCC sucks
{
einkPrvCmd(vals >> 8);
einkPrvData(vals);
einkPrvDeselect();
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeout(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)
;
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeoutSleep(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);
P2CHSTA &= 0xfd;
P2INTEN &= 0xfd;
P2FUNC = tmp_P2FUNC;
P2DIR = tmp_P2DIR;
P2PULL = tmp_P2PULL;
P2LVLSEL = tmp_P2LVLSEL;
/*if (!P2_1)
return;
pr("screen timeout\n");
while(1);*/
}
#pragma callee_saves einkPrvReadByte
static uint8_t einkPrvReadByte(void)
{
uint8_t val = 0, i;
P0DIR = (P0DIR & ~(1 << 0)) | (1 << 1);
P0 &= ~(1 << 0);
P0FUNC &= ~((1 << 0) | (1 << 1));
P2_2 = 1;
for (i = 0; i < 8; i++)
{
P0_0 = 1;
__asm__("nop\nnop\nnop\nnop\nnop\n");
val <<= 1;
if (P0_1)
val++;
P0_0 = 0;
__asm__("nop\nnop\nnop\nnop\nnop\n");
}
// set up pins for spi (0.0,0.1,0.2)
P0FUNC |= (1 << 0) | (1 << 1);
return val;
}
#pragma callee_saves einkPrvReadStatus
static uint8_t einkPrvReadStatus(void)
{
uint8_t sta;
einkPrvCmd(0x2f);
sta = einkPrvReadByte();
einkPrvDeselect();
return sta;
}
#pragma callee_saves screenPrvStartSubPhase
static void screenPrvStartSubPhase(__bit redSubphase)
{
einkPrvCmd(0x4e);
einkPrvData(0);
einkPrvDeselect();
einkPrvCmd(0x4f);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmd(redSubphase ? 0x26 : 0x24);
einkPrvDeselect();
}
#pragma callee_saves screenInitIfNeeded
static void screenInitIfNeeded(__bit forPartial)
{
if (mInited)
return;
mInited = true;
mPartial = forPartial;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 0;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 1;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
einkPrvCmd(0x12); // software reset
einkPrvDeselect();
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
einkPrvCmdWithOneByte(0x7454);
einkPrvCmdWithOneByte(0x7e3b);
einkPrvCmd(0x2b);
einkPrvData(0x04);
einkPrvData(0x63);
einkPrvDeselect();
einkPrvCmd(0x0c); // they send 8f 8f 8f 3f
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x3f);
einkPrvDeselect();
einkPrvCmd(0x01);
einkPrvData((SCREEN_HEIGHT - 1) & 0xff);
einkPrvData((SCREEN_HEIGHT - 1) >> 8);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x1103);
einkPrvCmd(0x44);
einkPrvData(0x00);
einkPrvData(SCREEN_WIDTH / 8 - 1);
einkPrvDeselect();
einkPrvCmd(0x45);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvData((SCREEN_HEIGHT - 1) & 0xff);
einkPrvData((SCREEN_HEIGHT - 1) >> 8);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x3cc0); // border will be HiZ
einkPrvCmdWithOneByte(0x1880); // internal temp sensor
einkPrvCmdWithOneByte(0x2108);
// turn on clock & analog
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
}
#pragma callee_saves screenPrvDraw
static void screenPrvDraw(void)
{
/* einkPrvCmd(0x01);
einkPrvData(0x40);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmd(0x0f);
einkPrvData(0x64);
einkPrvData(0x00);
einkPrvDeselect();
*/
einkPrvCmdWithOneByte(0x3a16);
// einkPrvCmdWithOneByte(0x3b0f);
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_REFRESH);
einkPrvCmd(0x20); // do actions
if (1)
{
einkPrvWaitWithTimeoutSleep(1000 * 60UL);
screenSleep();
}
else
{
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 60UL);
}
}
__bit screenTxStart(__bit forPartial)
{
screenInitIfNeeded(forPartial);
mPassNo = 0;
screenPrvStartSubPhase(false);
return true;
}
void screenEndPass(void)
{
switch (mPassNo)
{
case 0:
screenPrvStartSubPhase(true);
break;
default:
return;
}
mPassNo++;
}
void screenTxEnd(void)
{
screenPrvDraw();
//screenShutdown();
}
void screenShutdown(void)
{
if (!mInited)
return;
mInited = false;
einkPrvCmdWithOneByte(0x1003); // shut down
}
void screenSleep(void)
{
P2_0 = 0;
timerDelay(TIMER_TICKS_PER_SECOND / 250);
P2_0 = 1;
timerDelay(TIMER_TICKS_PER_SECOND / 250);
einkPrvCmd(0x12); // software reset
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
einkPrvCmdWithOneByte(0x1003); // shut down
}
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte)
{
static uint8_t __xdata prev, step = 0;
prev <<= 2;
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
if (++step == 4)
{
step = 0;
einkPrvSelect();
einkPrvData(prev);
einkPrvDeselect();
}
}
// yes this is here...
uint16_t adcSampleBattery(void)
{
__bit wasInited = mInited;
uint16_t voltage = 2600;
if (!mInited)
screenInitIfNeeded(false);
uint8_t val;
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
for (val = 3; val < 8; val++)
{
einkPrvCmdWithOneByte(0x1500 + val);
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (einkPrvReadStatus() & 0x10)
{ // set if voltage is less than threshold ( == 1.9 + val / 10)
voltage = 1850 + mathPrvMul8x8(val, 100);
break;
}
}
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); // do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (!wasInited)
screenShutdown();
return voltage;
}

View File

@@ -4,12 +4,6 @@
#include <stdbool.h>
#include <stdint.h>
//i hate globals, but for 8051 this makes life a lot easier, sorry :(
extern uint8_t __xdata mScreenVcom;
extern int8_t __xdata mCurTemperature;
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 296
@@ -27,22 +21,5 @@ extern int8_t __xdata mCurTemperature;
#define SCREEN_DATA_PASSES 2
void screenShutdown(void);
void screenTest(void);
__bit screenTxStart(__bit forPartial);
void screenEndPass(void); //at end of each pass
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte);
void screenTxEnd(void);
void screenSleep(void);
extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight
#endif
#endif

View File

@@ -4,27 +4,11 @@
#include <stdint.h>
#include "spi.h"
#include "uart.h"
//colors for ui messages
#define UI_MSG_MAGNIFY1 1
#define UI_MSG_MAGNIFY2 1
#define UI_MSG_MAGNIFY3 1
#define UI_MSG_BACK_COLOR 4
#define UI_MSG_FORE_COLOR_1 0
#define UI_MSG_FORE_COLOR_2 5
#define UI_MSG_FORE_COLOR_3 5
#define UI_BARCODE_VERTICAL
#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)
//debug uart (enable only when needed, on some boards it inhibits eeprom access)
#define dbgUartOn()
#define dbgUartOff()
#define dbgUartByte uartTx
//eeprom map
#define EEPROM_SETTINGS_AREA_START (0x01000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
@@ -35,19 +19,10 @@
//till end of eeprom really. do not put anything after - it will be erased at pairing time!!!
#define EEPROM_PROGRESS_BYTES (128)
//radio cfg
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
#define RADIO_NUM_CHANNELS (1)
//hw types
#define HW_TYPE_NORMAL HW_TYPE_42_INCH_ZBS_026
#define HW_TYPE_CYCLING HW_TYPE_42_INCH_ZBS_026_FRAME_MODE
#include "../boardCommon.h"
#endif
#endif

View File

@@ -1,416 +0,0 @@
#include <stdbool.h>
#include "asmUtil.h"
#include "screen.h"
#include "printf.h"
#include "board.h"
#include "timer.h"
#include "sleep.h"
#include "adc.h"
#include "cpu.h"
#include "spi.h"
uint8_t __xdata mScreenRow[320];
static __bit mInited = false, mPartial;
static uint8_t __xdata mPassNo;
#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
static const uint8_t __code mColorMap[][6] =
{
//colors are: B, DG, G, LG, W, R
//phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
{
1, 1, 1, 1, 0, 0, //lo plane (B)
},
{
0, 0, 0, 0, 0, 1, //hi plane (R)
}
};
#define einkPrvSelect() \
do{ \
P1_7 = 0; \
} while (0)
#define einkPrvDeselect() \
do{ \
P1_7 = 1; \
} while (0)
//urx pin
#define einkPrvMarkCommand() \
do{ \
P2_2 = 0; \
} while (0)
#define einkPrvMarkData() \
do{ \
P2_2 = 1; \
} while (0)
#pragma callee_saves einkPrvCmd
static void einkPrvCmd(uint8_t cmd) //sets chip select
{
einkPrvSelect();
einkPrvMarkCommand();
spiByte(cmd);
}
#pragma callee_saves einkPrvData
static void einkPrvData(uint8_t byte)
{
einkPrvMarkData();
spiByte(byte);
}
#pragma callee_saves einkPrvCmdWithOneByte
static void einkPrvCmdWithOneByte(uint16_t vals) //passing in one u16 is better than two params cause SDCC sucks
{
einkPrvCmd(vals >> 8);
einkPrvData(vals);
einkPrvDeselect();
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeout(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);
}
#pragma callee_saves einkPrvWaitWithTimeout
static void einkPrvWaitWithTimeoutSleep(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);
P2CHSTA &= 0xfd;
P2INTEN &= 0xfd;
P2FUNC = tmp_P2FUNC;
P2DIR = tmp_P2DIR;
P2PULL = tmp_P2PULL;
P2LVLSEL = tmp_P2LVLSEL;
/*if (!P2_1)
return;
pr("screen timeout\n");
while(1);*/
}
#pragma callee_saves einkPrvReadByte
static uint8_t einkPrvReadByte(void)
{
uint8_t val = 0, i;
P0DIR = (P0DIR &~ (1 << 0)) | (1 << 1);
P0 &=~ (1 << 0);
P0FUNC &=~ ((1 << 0) | (1 << 1));
P2_2 = 1;
for (i = 0; i < 8; i++) {
P0_0 = 1;
__asm__("nop\nnop\nnop\nnop\nnop\n");
val <<= 1;
if (P0_1)
val++;
P0_0 = 0;
__asm__("nop\nnop\nnop\nnop\nnop\n");
}
//set up pins for spi (0.0,0.1,0.2)
P0FUNC |= (1 << 0) | (1 << 1);
return val;
}
#pragma callee_saves einkPrvReadStatus
static uint8_t einkPrvReadStatus(void)
{
uint8_t sta;
einkPrvCmd(0x2f);
sta = einkPrvReadByte();
einkPrvDeselect();
return sta;
}
#pragma callee_saves screenPrvStartSubPhase
static void screenPrvStartSubPhase(__bit redSubphase)
{
einkPrvCmd(0x4e);
einkPrvData(0x00);
einkPrvDeselect();
einkPrvCmd(0x4f);
einkPrvData(0x2b);
einkPrvData(0x01);
einkPrvDeselect();
einkPrvCmd(redSubphase ? 0x26 : 0x24);
einkPrvDeselect();
}
#pragma callee_saves screenInitIfNeeded
static void screenInitIfNeeded(__bit forPartial)
{
if (mInited)
return;
mInited = true;
mPartial = forPartial;
pr("init 4.2 screen\n");
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 0;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
P2_0 = 1;
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
einkPrvCmd(0x12); //software reset
einkPrvDeselect();
timerDelay(TIMER_TICKS_PER_SECOND);
einkPrvCmdWithOneByte(0x7454);
einkPrvCmdWithOneByte(0x7e3b);
einkPrvCmd(0x2b);
einkPrvData(0x04);
einkPrvData(0x63);
einkPrvDeselect();
einkPrvCmd(0x0c); //they send 8f 8f 8f 3f
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x8f);
einkPrvData(0x3f);
einkPrvDeselect();
einkPrvCmd(0x01);
einkPrvData(0x2b);
einkPrvData(0x01);
einkPrvData(0x01);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x1101);
einkPrvDeselect();
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
einkPrvCmd(0x20);
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 10);
einkPrvCmd(0x44);
einkPrvData(0x00);
einkPrvData(0x31);
einkPrvDeselect();
einkPrvCmd(0x45);
einkPrvData(0x2b);
einkPrvData(0x01);
einkPrvData(0x00);
einkPrvData(0x00);
einkPrvDeselect();
//einkPrvCmdWithOneByte(0x3c01); //border will be HiZ
einkPrvCmdWithOneByte(0x3cc0); //border will be HiZ
einkPrvDeselect();
einkPrvCmdWithOneByte(0x1880); //internal temp sensor
einkPrvDeselect();
einkPrvCmdWithOneByte(0x2108);
//turn on clock & analog
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); //do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
/*einkPrvCmd(0x32);
einkPrvData(0x00); einkPrvData(0x90); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x90); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x90);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x90); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x27); einkPrvData(0x27); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x01); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x00);
einkPrvData(0x00); einkPrvData(0x00); einkPrvData(0x15); einkPrvData(0x41);
einkPrvData(0xce); einkPrvData(0x32); einkPrvData(0x0f); einkPrvData(0x0c);
einkPrvDeselect();
*/
}
#pragma callee_saves screenPrvDraw
static void screenPrvDraw(void)
{
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_REFRESH);
einkPrvCmd(0x20); //do actions
if (1)
{
einkPrvWaitWithTimeoutSleep(1000 * 60UL);
screenSleep();
}
else
{
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND * 60UL);
}
}
__bit screenTxStart(__bit forPartial)
{
screenInitIfNeeded(forPartial);
mPassNo = 0;
screenPrvStartSubPhase(false);
return true;
}
void screenEndPass(void)
{
switch (mPassNo) {
case 0:
screenPrvStartSubPhase(true);
break;
default:
return;
}
mPassNo++;
}
void screenTxEnd(void)
{
screenPrvDraw();
screenShutdown();
}
void screenShutdown(void)
{
if (!mInited)
return;
mInited = false;
einkPrvCmdWithOneByte(0x1003); //shut down
}
void screenSleep(void)
{
P2_0 = 0;
timerDelay(20);
P2_0 = 1;
timerDelay(80);
einkPrvCmd(0x12); // software reset
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND/250);
einkPrvCmdWithOneByte(0x1003); // shut down
}
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte)
{
static uint8_t __xdata prev, step = 0;
prev <<= 2;
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
if (++step == 4) {
step = 0;
einkPrvSelect();
einkPrvData(prev);
einkPrvDeselect();
}
}
//yes this is here...
uint16_t adcSampleBattery(void)
{
__bit wasInited = mInited;
uint16_t voltage = 2600;
if (!mInited)
screenInitIfNeeded(false);
uint8_t val;
einkPrvCmdWithOneByte(0x2200 | SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
einkPrvCmd(0x20); //do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
for (val = 3; val < 8; val++) {
einkPrvCmdWithOneByte(0x1500 + val);
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (einkPrvReadStatus() & 0x10) {//set if voltage is less than threshold ( == 1.9 + val / 10)
voltage = 1850 + mathPrvMul8x8(val, 100);
break;
}
}
einkPrvCmdWithOneByte(0x22B1);
einkPrvCmd(0x20); //do action
einkPrvDeselect();
einkPrvWaitWithTimeout(TIMER_TICKS_PER_SECOND);
if (!wasInited)
screenShutdown();
return voltage;
}

View File

@@ -4,12 +4,6 @@
#include <stdbool.h>
#include <stdint.h>
//i hate globals, but for 8051 this makes life a lot easier, sorry :(
extern uint8_t __xdata mScreenVcom;
extern int8_t __xdata mCurTemperature;
#define SCREEN_WIDTH 400
#define SCREEN_HEIGHT 300
@@ -27,24 +21,5 @@ extern int8_t __xdata mCurTemperature;
#define SCREEN_DATA_PASSES 2
void screenShutdown(void);
void screenTest(void);
__bit screenTxStart(__bit forPartial);
void screenEndPass(void); //at end of each pass
#pragma callee_saves screenByteTx
void screenByteTx(uint8_t byte);
void screenTxEnd(void);
void screenSleep(void);
extern uint8_t __xdata mScreenRow[]; //320 bytes used as temp by many on cc where memory is tight
#endif
#endif

View File

@@ -1,182 +0,0 @@
#include "asmUtil.h"
#include "printf.h"
#include "screen.h"
#include "chars.h"
#include "cpu.h"
#define CANVAS_FLIP_H 0
#define CANVAS_MSB_FIRST 1
#define NUM_CHARS (0x64)
#define FIRST_CHAR (0x1c)
#define MISSING_CHAR ('?')
static const uint8_t __code mCharsImgs[];
//special RAM area that is not preserved across sleep
#pragma callee_saves charsPrvDrawCharRow
static void charsPrvDrawCharRow(uint8_t ch, int16_t x, uint8_t imgRow, uint8_t foreColor, uint8_t backColor, uint8_t mag) __reentrant /* save pseg */
{
uint8_t c, mc, charRow = imgRow / mag, bitMask = (1 << SCREEN_TX_BPP) - 1;
const uint8_t __code *imgInfoBuf;
if (ch < FIRST_CHAR || ch - FIRST_CHAR >= NUM_CHARS)
ch = MISSING_CHAR;
ch -= FIRST_CHAR;
//get pointer to proper char row
imgInfoBuf = mCharsImgs + (uint16_t)mathPrvMul16x8((CHAR_WIDTH * NUM_CHARS + 7) / 8, charRow) + mathPrvMul8x8(CHAR_WIDTH, ch) / 8;
for (c = 0; c < CHAR_WIDTH; c++) { //iterate over the char's columns for this row
uint8_t imgCol = ((uint8_t)((uint8_t)CHAR_WIDTH * (uint8_t)ch) & 7) + c; //sort out where in the row our data begins
uint8_t color = ((imgInfoBuf[imgCol >> 3] >> (7 - (imgCol % 8))) & 1) ? foreColor : backColor; //get the color
if (color == CHAR_COLOR_TRANSPARENT)
continue;
for (mc = 0; mc < mag; mc++, x++) { //set the pixel
uint8_t __xdata *dst = mScreenRow;
uint8_t bitOfst;
uint16_t c = x;
if (x < 0)
continue;
if (x >= SCREEN_WIDTH)
break;
#if CANVAS_FLIP_H
c = SCREEN_WIDTH - c - 1;
#endif
dst += mathPrvMul16x8(c, SCREEN_TX_BPP) / 8;
bitOfst = mathPrvMul16x8(c, SCREEN_TX_BPP) % 8;
#if CANVAS_MSB_FIRST
bitOfst = 8 - bitOfst - SCREEN_TX_BPP;
#endif
*dst = ((*dst) & ~(bitMask << bitOfst)) | ((color & bitMask) << bitOfst);
}
}
}
void charsDrawString(const struct CharDrawingParams __xdata *params)
{
const char *__xdata s = params->str;
int16_t x = params->x;
uint8_t ch;
while ((ch = charsPrvDerefAndIncGenericPtr(&s)) != 0) {
charsPrvDrawCharRow(ch, x, params->imgRow, params->foreColor, params->backColor, params->magnify);
x += (uint16_t)(uint8_t)(CHAR_WIDTH * params->magnify);
}
}
static const uint8_t __code mCharsImgs[] = {
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x0f, 0xdc,
0x00, 0x18, 0x7e, 0x36, 0x3c, 0xd8, 0x38, 0x1c, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x1e, 0x0c, 0x3c, 0x3c, 0x30, 0x7e, 0x1c, 0x7e, 0x3c, 0x3c, 0x00, 0x00, 0x06, 0x00, 0x60, 0x3c,
0x7e, 0x18, 0x7c, 0x3c, 0x78, 0x7e, 0x7e, 0x3c, 0x66, 0x3c, 0x06, 0x66, 0x60, 0x63, 0x63, 0x3c,
0x7c, 0x3c, 0x7c, 0x3c, 0x7e, 0x66, 0x66, 0x63, 0x66, 0x66, 0x7e, 0x3c, 0x60, 0x3c, 0x66, 0x00,
0x0c, 0x00, 0x60, 0x00, 0x06, 0x00, 0x1e, 0x00, 0x60, 0x18, 0x0c, 0x60, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x71, 0x00,
0x30, 0x0c, 0x30, 0x38, 0x00, 0x3c, 0x7e, 0x36, 0x66, 0xda, 0x6c, 0x1c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x33, 0x1c, 0x66, 0x66, 0x30, 0x60, 0x18, 0x06, 0x66, 0x66, 0x00, 0x00,
0x0c, 0x00, 0x30, 0x66, 0xc3, 0x3c, 0x66, 0x66, 0x6c, 0x60, 0x60, 0x66, 0x66, 0x18, 0x06, 0x66,
0x60, 0x63, 0x63, 0x66, 0x66, 0x66, 0x66, 0x66, 0x18, 0x66, 0x66, 0x63, 0x66, 0x66, 0x06, 0x30,
0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x60,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x18, 0xdb, 0x00, 0x40, 0x02, 0x40, 0x72, 0x00, 0x3c, 0x7e, 0x7f, 0x60, 0x76, 0x6c, 0x0c,
0x18, 0x18, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x37, 0x7c, 0x66, 0x66, 0x36, 0x60, 0x30, 0x0c,
0x66, 0x66, 0x1c, 0x1c, 0x18, 0x00, 0x18, 0x66, 0xc3, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x66,
0x66, 0x18, 0x06, 0x6c, 0x60, 0x77, 0x73, 0x66, 0x66, 0x66, 0x66, 0x60, 0x18, 0x66, 0x66, 0x63,
0x34, 0x66, 0x06, 0x30, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x7c, 0x3c, 0x3e, 0x3c, 0x30, 0x3e,
0x7c, 0x78, 0x3c, 0x66, 0x18, 0x7e, 0x7c, 0x3c, 0x7c, 0x3e, 0x66, 0x3e, 0x7e, 0x66, 0x66, 0x63,
0x66, 0x66, 0x7e, 0x18, 0x18, 0x18, 0x8e, 0x00, 0x87, 0xe1, 0x86, 0xe1, 0x00, 0x3c, 0x7e, 0x36,
0x30, 0x0c, 0x38, 0x18, 0x30, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x37, 0x0c, 0x06, 0x06,
0x36, 0x60, 0x7c, 0x0c, 0x76, 0x66, 0x1c, 0x1c, 0x30, 0x7e, 0x0c, 0x0c, 0xcf, 0x66, 0x66, 0x60,
0x66, 0x60, 0x60, 0x60, 0x66, 0x18, 0x06, 0x6c, 0x60, 0x6b, 0x7b, 0x66, 0x66, 0x66, 0x66, 0x30,
0x18, 0x66, 0x66, 0x6b, 0x18, 0x66, 0x0c, 0x30, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x66, 0x66,
0x66, 0x66, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x66, 0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x6e, 0x60,
0x30, 0x66, 0x66, 0x6b, 0x66, 0x66, 0x06, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x19, 0xd8,
0x00, 0x18, 0x7e, 0x36, 0x18, 0x18, 0x60, 0x00, 0x30, 0x0c, 0x7f, 0x7e, 0x00, 0x7e, 0x00, 0x18,
0x33, 0x0c, 0x0c, 0x1c, 0x36, 0x7c, 0x66, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x60, 0x00, 0x06, 0x18,
0xdb, 0x66, 0x7c, 0x60, 0x66, 0x7c, 0x7c, 0x60, 0x7e, 0x18, 0x06, 0x78, 0x60, 0x6b, 0x6f, 0x66,
0x7c, 0x66, 0x7c, 0x18, 0x18, 0x66, 0x66, 0x6b, 0x18, 0x3c, 0x18, 0x30, 0x18, 0x0c, 0x00, 0x00,
0x00, 0x06, 0x66, 0x60, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x18, 0x0c, 0x6c, 0x18, 0x6b, 0x66, 0x66,
0x66, 0x66, 0x70, 0x60, 0x30, 0x66, 0x66, 0x6b, 0x3c, 0x66, 0x0c, 0x30, 0x18, 0x0c, 0x00, 0x00,
0x20, 0x04, 0x23, 0x84, 0x00, 0x18, 0x7e, 0x36, 0x0c, 0x30, 0x6f, 0x00, 0x30, 0x0c, 0x1c, 0x18,
0x00, 0x00, 0x00, 0x18, 0x3b, 0x0c, 0x18, 0x06, 0x66, 0x06, 0x66, 0x18, 0x6e, 0x3e, 0x00, 0x00,
0x30, 0x7e, 0x0c, 0x18, 0xdb, 0x7e, 0x66, 0x60, 0x66, 0x60, 0x60, 0x6e, 0x66, 0x18, 0x06, 0x6c,
0x60, 0x6b, 0x67, 0x66, 0x60, 0x66, 0x6c, 0x0c, 0x18, 0x66, 0x66, 0x6b, 0x2c, 0x18, 0x30, 0x30,
0x18, 0x0c, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x60, 0x66, 0x7e, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x78,
0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x60, 0x3c, 0x30, 0x66, 0x66, 0x6b, 0x18, 0x66, 0x18, 0x60,
0x18, 0x06, 0x00, 0x00, 0x41, 0x82, 0x47, 0x02, 0x00, 0x00, 0x7e, 0x7f, 0x06, 0x6e, 0x66, 0x00,
0x30, 0x0c, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30, 0x3b, 0x0c, 0x30, 0x66, 0x7f, 0x06, 0x66, 0x30,
0x66, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0xcf, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x66,
0x66, 0x18, 0x66, 0x6c, 0x60, 0x63, 0x63, 0x66, 0x60, 0x66, 0x66, 0x06, 0x18, 0x66, 0x66, 0x36,
0x66, 0x18, 0x60, 0x30, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x60, 0x66, 0x60, 0x30, 0x66,
0x66, 0x18, 0x0c, 0x6c, 0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x60, 0x06, 0x30, 0x66, 0x66, 0x6b,
0x3c, 0x66, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x86, 0x61, 0x8e, 0x61, 0x00, 0x18, 0x7e, 0x36,
0x66, 0x5b, 0x66, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x30, 0x33, 0x0c, 0x60, 0x66,
0x06, 0x0c, 0x66, 0x30, 0x66, 0x18, 0x1c, 0x1c, 0x0c, 0x00, 0x30, 0x18, 0xc0, 0x66, 0x66, 0x66,
0x6c, 0x60, 0x60, 0x66, 0x66, 0x18, 0x66, 0x66, 0x60, 0x63, 0x63, 0x66, 0x60, 0x66, 0x66, 0x66,
0x18, 0x66, 0x3c, 0x36, 0x66, 0x18, 0x60, 0x30, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
0x66, 0x60, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x66, 0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x60, 0x06,
0x30, 0x66, 0x3c, 0x36, 0x66, 0x66, 0x60, 0x18, 0x18, 0x18, 0x00, 0x00, 0x88, 0x11, 0x9c, 0x11,
0x00, 0x18, 0x7e, 0x36, 0x3c, 0x1b, 0x3b, 0x00, 0x18, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x60,
0x1e, 0x0c, 0x7e, 0x3c, 0x06, 0x78, 0x3c, 0x30, 0x3c, 0x38, 0x1c, 0x1c, 0x06, 0x00, 0x60, 0x18,
0x7f, 0x66, 0x7c, 0x3c, 0x78, 0x7e, 0x60, 0x3e, 0x66, 0x3c, 0x3c, 0x66, 0x7e, 0x63, 0x63, 0x3c,
0x60, 0x3c, 0x66, 0x3c, 0x18, 0x3c, 0x18, 0x36, 0x66, 0x18, 0x7e, 0x30, 0x06, 0x0c, 0x00, 0x00,
0x00, 0x3e, 0x7c, 0x3c, 0x3e, 0x3c, 0x30, 0x3e, 0x66, 0x7e, 0x0c, 0x66, 0x7e, 0x63, 0x66, 0x3c,
0x7c, 0x3e, 0x60, 0x7c, 0x1e, 0x3e, 0x18, 0x36, 0x66, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00,
0x10, 0x08, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x18,
0x18, 0x18, 0x00, 0x00, 0x11, 0x88, 0x71, 0x88, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x0c, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x03, 0xc0, 0xe3, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x43, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@@ -1,32 +0,0 @@
#ifndef _CHARS_H_
#define _CHARS_H_
#include <stdbool.h>
#include <stdint.h>
#define CHAR_WIDTH 8
#define CHAR_HEIGHT 16
#define CHAR_COLOR_TRANSPARENT (0xff)
#define CHAR_SIGNAL_PT1 (0x1c)
#define CHAR_SIGNAL_PT2 (0x1d)
#define CHAR_NO_SIGNAL_PT1 (0x1e)
#define CHAR_NO_SIGNAL_PT2 (0x1f)
struct CharDrawingParams {
const char *str;
int16_t x;
uint8_t imgRow;
uint8_t foreColor;
uint8_t backColor;
uint8_t magnify;
};
//draws to screen the rows of this string. will draw 16 * magnify rows
void charsDrawString(const struct CharDrawingParams __xdata *params);
#endif

View File

@@ -21,34 +21,8 @@
static uint8_t __xdata mCommsBuf[127];
static uint8_t __xdata mSeq = 0;
static uint8_t __xdata mLastLqi = 0;
static int8_t __xdata mLastRSSI = 0;
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
};
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
};
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
};
uint8_t __xdata mLastLqi = 0;
int8_t __xdata mLastRSSI = 0;
uint8_t commsGetLastPacketLQI(void)
{

View File

@@ -3,21 +3,16 @@
#include <stdint.h>
#define COMMS_MAX_RADIO_WAIT_MSEC 200
#define COMMS_IV_SIZE (4) //zeroes except these 4 counter bytes
#define COMMS_MAX_RADIO_WAIT_MSEC 200
#define COMMS_RX_ERR_NO_PACKETS (-1)
#define COMMS_RX_ERR_INVALID_PACKET (-2)
#define COMMS_RX_ERR_MIC_FAIL (-3)
#define COMMS_MAX_PACKET_SZ (127)
#pragma callee_saves commsGetLastPacketLQI
uint8_t commsGetLastPacketLQI(void);
#pragma callee_saves commsGetLastPacketRSSI
int8_t commsGetLastPacketRSSI(void);
extern uint8_t __xdata mLastLqi;
extern int8_t __xdata mLastRSSI;
int8_t commsRxUnencrypted(void __xdata *data);
bool commsTxUnencrypted(const void __xdata *packetP, uint8_t len);

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,10 @@
#include <stdbool.h>
// #include "datamatrix.h"
#include "adc.h"
#include "asmUtil.h"
#include "barcode.h"
#include "board.h"
#include "chars.h"
#include "cpu.h"
#include "drawing.h"
#include "eeprom.h"
#include "epd.h"
#include "printf.h"
#include "screen.h"
#include "timer.h"
@@ -57,6 +54,16 @@ struct BitmapDrawInfo {
uint8_t bottomUp : 1;
};
uint8_t __xdata mPassNo = 0;
static const uint8_t __code mColorMap[][6] = {
// colors are: B, DG, G, LG, W, R
// phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
{1, 1, 1, 1, 0, 0}, // lo plane (B)
{0, 0, 0, 0, 0, 1} // hi plane (R)
};
static uint8_t __xdata mClutMap[256];
static struct BitmapDrawInfo __xdata mDrawInfo;
@@ -247,7 +254,7 @@ static void drawPrvDecodeImageOnce(void) {
if (emit) {
emit = false;
screenByteTx(txPrev | val);
ByteDecode(txPrev | val);
nBytesOut++;
txPrev = 0;
} else {
@@ -260,7 +267,7 @@ static void drawPrvDecodeImageOnce(void) {
bitpoolOut |= val;
bitpoolOutUsedUsed += SCREEN_TX_BPP;
if (bitpoolOutUsedUsed >= 8) {
screenByteTx(bitpoolOut >> (bitpoolOutUsedUsed -= 8));
ByteDecode(bitpoolOut >> (bitpoolOutUsedUsed -= 8));
bitpoolOut &= (1 << bitpoolOutUsedUsed) - 1;
nBytesOut++;
}
@@ -272,14 +279,14 @@ static void drawPrvDecodeImageOnce(void) {
#if SCREEN_TX_BPP == 4
if (emit) {
screenByteTx(txPrev);
ByteDecode(txPrev);
nBytesOut++;
}
#else
if (bitpoolOutUsedUsed) {
screenByteTx(bitpoolOut);
ByteDecode(bitpoolOut);
nBytesOut++;
}
@@ -288,7 +295,7 @@ static void drawPrvDecodeImageOnce(void) {
// if we did not produce enough bytes, do so
nBytesOut = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8 - nBytesOut;
while (nBytesOut--)
screenByteTx(SCREEN_BYTE_FILL);
ByteDecode(SCREEN_BYTE_FILL);
// update row
if (mDrawInfo.bottomUp) {
@@ -306,12 +313,23 @@ static void drawPrvDecodeImageOnce(void) {
// fill the rest of the screen
for (er = mDrawInfo.effectiveH - SCREEN_HEIGHT; er; er--) {
for (c = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8; c; c--) {
screenByteTx(SCREEN_BYTE_FILL);
ByteDecode(SCREEN_BYTE_FILL);
}
}
}
extern uint8_t blockXferBuffer[];
void ByteDecode(uint8_t byte) {
static uint8_t __xdata prev, step = 0;
prev <<= 2;
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
if (++step == 4) {
step = 0;
epdSelect();
epdSend(prev);
epdDeselect();
}
}
void drawImageAtAddress(uint32_t addr) {
uint32_t __xdata clutAddr;
@@ -322,105 +340,20 @@ void drawImageAtAddress(uint32_t addr) {
return;
drawPrvLoadAndMapClut(clutAddr);
screenTxStart(false);
for (iter = 0; iter < SCREEN_DATA_PASSES; iter++) {
pr(".");
drawPrvDecodeImageOnce();
screenEndPass();
}
epdSetup();
mPassNo = 0;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
drawPrvDecodeImageOnce();
endWriteFramebuffer();
mPassNo++;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_RED);
drawPrvDecodeImageOnce();
endWriteFramebuffer();
pr(" complete.\n");
screenTxEnd();
screenShutdown();
}
#pragma callee_saves myStrlen
static uint16_t myStrlen(const char *str) {
const char *__xdata strP = str;
while (charsPrvDerefAndIncGenericPtr(&strP))
;
return strP - str;
}
void drawFullscreenMsg(const char *str) {
volatile uint16_t PDATA textRow, textRowEnd; // without volatile, compiler ignores "__pdata"
struct CharDrawingParams __xdata cdp;
uint8_t __xdata rowIdx;
uint8_t iteration;
uint16_t i, r;
getVolt();
pr("MESSAGE '%s'\n", str);
screenTxStart(false);
for (iteration = 0; iteration < SCREEN_DATA_PASSES; iteration++) {
__bit inBarcode = false;
rowIdx = 0;
cdp.magnify = UI_MSG_MAGNIFY1;
cdp.str = str;
cdp.x = mathPrvI16Asr1(SCREEN_WIDTH - mathPrvMul8x8(CHAR_WIDTH * cdp.magnify, myStrlen(cdp.str)));
cdp.foreColor = UI_MSG_FORE_COLOR_1;
cdp.backColor = UI_MSG_BACK_COLOR;
textRow = 5;
textRowEnd = textRow + (uint8_t)((uint8_t)CHAR_HEIGHT * (uint8_t)cdp.magnify);
for (r = 0; r < SCREEN_HEIGHT; r++) {
// clear the row
for (i = 0; i < SCREEN_WIDTH * SCREEN_TX_BPP / 8; i++)
mScreenRow[i] = SCREEN_BYTE_FILL;
if (r >= textRowEnd) {
switch (rowIdx) {
case 0:
rowIdx = 1;
textRow = textRowEnd + 3;
cdp.magnify = UI_MSG_MAGNIFY2;
cdp.foreColor = UI_MSG_FORE_COLOR_2;
// cdp.str = macSmallString();
cdp.x = 0;
textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify;
break;
case 1:
rowIdx = 2;
textRow = SCREEN_HEIGHT - CHAR_HEIGHT - CHAR_HEIGHT;
cdp.magnify = UI_MSG_MAGNIFY3;
cdp.foreColor = UI_MSG_FORE_COLOR_3;
// cdp.str = voltString();
cdp.x = 1;
inBarcode = false;
break;
case 2:
rowIdx = 3;
textRow = SCREEN_HEIGHT - CHAR_HEIGHT;
cdp.magnify = UI_MSG_MAGNIFY3;
cdp.foreColor = UI_MSG_FORE_COLOR_3;
// cdp.str = fwVerString();
cdp.x = 1;
inBarcode = false;
break;
case 3:
cdp.str = "";
break;
}
} else if (r > textRow) {
inBarcode = false;
cdp.imgRow = r - textRow;
charsDrawString(&cdp);
}
for (i = 0; i < SCREEN_WIDTH * SCREEN_TX_BPP / 8; i++)
screenByteTx(mScreenRow[i]);
}
screenEndPass();
}
screenTxEnd();
draw();
epdEnterSleep();
}

View File

@@ -9,26 +9,5 @@ void set_offline(__bit state);
#pragma callee_saves drawImageAtAddress
void drawImageAtAddress(uint32_t addr);
#pragma callee_saves drawImageAtAddress
void drawFullscreenMsg(const char *str);
//expected external funcs
/*
#pragma callee_saves fwVerString
const char __xdata* fwVerString(void);
#pragma callee_saves voltString
const char __xdata* voltString(void);
void getVolt();
*/
#pragma callee_saves macString
//const char __xdata* macString(void);
#pragma callee_saves macSmallString
//const char __xdata* macSmallString(void);
extern uint8_t __xdata mSelfMac[];
#endif

View File

@@ -8,6 +8,8 @@
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)
{
@@ -158,27 +160,27 @@ __bit eepromInit(void)
uint8_t j;
eepromPrvSfdpRead(*(uint16_t __xdata*)(buf + 4), mScreenRow, 9 * 4);
if ((mScreenRow[0] & 3) != 1) {
eepromPrvSfdpRead(*(uint16_t __xdata*)(buf + 4), tempBufferE, 9 * 4);
if ((tempBufferE[0] & 3) != 1) {
pr("SFDP: no 4K ERZ\n");
break;
}
if (!(mScreenRow[0] & 0x04)) {
if (!(tempBufferE[0] & 0x04)) {
pr("SFDP: no large write buf\n");
break;
}
if ((mScreenRow[2] & 0x06)) {
if ((tempBufferE[2] & 0x06)) {
pr("SFDP: addr.len != 3\n");
break;
}
if (!mScreenRow[1] || mScreenRow[1] == 0xff) {
if (!tempBufferE[1] || tempBufferE[1] == 0xff) {
pr("SFDP: 4K ERZ opcode invalid\n");
break;
}
mOpcodeErz4K = mScreenRow[1];
mOpcodeErz4K = tempBufferE[1];
if (mScreenRow[7] & 0x80) {
if (tempBufferE[7] & 0x80) {
pr("SFDP: device too big\n");
break;
@@ -187,11 +189,11 @@ __bit eepromInit(void)
uint8_t t;
if (t = mScreenRow[7])
if (t = tempBufferE[7])
mEepromSize = 0x00200000UL;
else if (t = mScreenRow[6])
else if (t = tempBufferE[6])
mEepromSize = 0x00002000UL;
else if (t = mScreenRow[5])
else if (t = tempBufferE[5])
mEepromSize = 0x00000020UL;
else {
pr("SFDP: device so small?!\n");
@@ -206,12 +208,12 @@ __bit eepromInit(void)
//get erase opcodes
for (j = 0x1c; j < 0x24; j += 2) {
uint8_t instr = mScreenRow[j + 1];
uint8_t instr = tempBufferE[j + 1];
if (!instr || instr == 0xff)
continue;
switch (mScreenRow[j]) {
switch (tempBufferE[j]) {
case 0x0c:
if (mOpcodeErz4K != instr) {
pr("4K ERZ opcode disagreement\n");

679
tag_fw/epd.c Normal file
View File

@@ -0,0 +1,679 @@
#include "epd.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 "sleep.h"
#include "spi.h"
#include "timer.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 bool __xdata isInited = false;
struct waveform __xdata waveform; // 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);
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 epdEnterSleep() {
P2_0 = 0;
timerDelay(10);
P2_0 = 1;
timerDelay(50);
shortCommand(CMD_SOFT_RESET2);
epdBusyWait(TIMER_TICKS_PER_MS * 10);
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;
}
static uint8_t epdGetStatus() {
uint8_t sta;
commandReadBegin(0x2F);
sta = epdReadByte();
commandReadEnd();
return sta;
}
uint16_t epdGetBattery(void) {
uint16_t voltage = 2600;
if (!isInited)
epdReset();
uint8_t val;
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;
}
}
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1);
shortCommand(CMD_ACTIVATION);
epdBusyWait(TIMER_TICKS_PER_MS * 100);
if (!isInited)
epdEnterSleep();
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 sendCustomLut(uint8_t* lut, uint8_t len) {
commandBegin(CMD_WRITE_LUT);
for (uint8_t i = 0; i < len; i++)
epdSend(((uint8_t*)(lut))[i]);
commandEnd();
}
static void writeLut(bool lut) {
if (lut) {
commandBegin(CMD_WRITE_LUT);
for (uint8_t i = 0; i < 70; i++)
epdSend(((uint8_t*)(&waveform))[i]);
commandEnd();
} else {
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1?
shortCommand(CMD_ACTIVATION);
epdBusyWait(TIMER_TICKS_PER_SECOND);
}
}
extern uint8_t blockXferBuffer[];
static void readLut() {
commandReadBegin(0x33);
uint16_t checksum = 0;
uint16_t ident = 0;
uint16_t shortl = 0;
for (uint16_t c = 0; c < 512; c++) {
//((uint8_t*)&waveform)[c] = epdReadByte();
blockXferBuffer[c] = epdReadByte();
}
commandReadEnd();
}
void selectLUT(uint8_t lut) {
if (lut == 2) {
sendCustomLut(lut29, 70);
return;
}
if (SCREEN_WIDTH == 152) {
sendCustomLut(lut154, 100);
} else {
sendCustomLut(lutorig, 70);
}
return;
readLut();
// dump((uint8_t*)&waveform, 96);
dump(blockXferBuffer, 512);
memset(&(waveform.group[0]), 0x00, 5);
memset(&(waveform.group[1]), 0x00, 5);
memset(&(waveform.group[2]), 0x00, 5);
memset(&(waveform.group[3]), 0x00, 5);
memset(&(waveform.group[4]), 0x00, 5);
memset(&(waveform.group[5]), 0x00, 5); // slow blink
// dump((uint8_t*)&waveform, 96);
// writeLut(EPD_LOAD_CUSTOM_LUT);
}
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 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)) {
pr("1");
epdSend(0xFF);
} else {
pr("0");
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();
}
void lutTest() {
readLut();
dump((uint8_t*)&waveform, 96);
}

67
tag_fw/epd.h Normal file
View File

@@ -0,0 +1,67 @@
#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 epdSelect() \
do { \
P1_7 = 0; \
} while (0)
#define epdDeselect() \
do { \
P1_7 = 1; \
} while (0)
void epdSetup();
void epdEnterSleep();
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 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

258
tag_fw/font.h Normal file
View File

@@ -0,0 +1,258 @@
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
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

173
tag_fw/lut.h Normal file
View File

@@ -0,0 +1,173 @@
#define __packed
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 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;
static const uint8_t __code lut1542[] = {
// lut0 (KEEP) voltages
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut1 (W2B) voltages
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut2 (B2W) voltages
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut3 (unused) voltages
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut4 (vcom) voltages
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// group0 phase lengths and repeat count
0x40, 0x0, 0x00, 0x00, 0x00,
// group1 not used
0x00, 0x00, 0x00, 0x00, 0x00,
// group2 not used
0x00, 0x00, 0x00, 0x00, 0x00,
// group3 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group4 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group5 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group6 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
};
static const uint8_t __code lut29[] = {
// lut0 (KEEP) voltages
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut1 (W2B) voltages
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut2 (B2W) voltages
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut3 (unused) voltages
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// lut4 (vcom) voltages
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// group0 phase lengths and repeat count
// 0x10, 0x02, 0x00, 0x00, 0x03 - 1,
0x05, 0x02, 0x00, 0x00, 0x00,
// 0x40, 0x00, 0x00, 0x00, 0x00,
// group1 not used
0x00, 0x00, 0x00, 0x00, 0x00,
// group2 not used
0x00, 0x00, 0x00, 0x00, 0x00,
// group3 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group4 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group5 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
// group6 phase lengths and repeat count
0x00, 0x00, 0x00, 0x00, 0x00,
};
static const uint8_t __code lutSHA[] = {
// Voltages and other settings? Timing?
0xA0, 0x90, 0x50, 0x0, 0x0, 0x0, 0x0,
0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0,
0xA0, 0x90, 0x50, 0x0, 0x0, 0x0, 0x0,
0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0,
0x00, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0,
// Update program
//
// Top three lines are the main program (bottom 4 have unknown function)
// Line 1: Negative image
// Line 2: White/Black flashing
// Line 3: Positive image
//
// Line construction
// First two bytes denote Intensity (range 0x00 to 0x0F)
// Second two bytes denote lenght of each 'pulse' (range 0x00 to 0xFF)
// Last byte denotes number of repeats (0 = line runs 1 time, range 0x00 to 0xFF)
// If you don't want a line to do anything, set all bytes to 0x0.
// This way you can make a quick update cycle between two screens.
// Maybe not as pretty/crisp but nice and fast is also awesome!
// Negative image
// first two bytes negative image, length white pulse (0-FF), length black pulse (0-FF), last byte repeats
0x0, 0x0, 0x0, 0x0, 0x0,
//0xF, 0xF, 0x0, 0x0, 0x0,
// White or black flash
// white flash intensity, black flash intensity, length white pulse (0-FF), length black pulse (0-FF), repeats
//0x0, 0x0, 0x0, 0x0, 0x00,
0xF, 0xF, 0x1, 0x1, 0x00,
//0xF, 0xF, 0x0, 0x0, 0x02,
// Positive image
// first byte or second byte positive image (don't know why you need both), rest same as above
0xF, 0xF, 0x0, 0x0, 0x0,
// Unknown what lines below actually do.
// They seem to be programs to, but have no visible effect on dislay.
0x0F, 0x0F, 0x0, 0x0, 0x0,
0x0F, 0x0F, 0x0, 0x0, 0x0,
0x0F, 0x0F, 0x0, 0x0, 0x0,
0x0F, 0x0F, 0x0, 0x0, 0x0,
};
static const uint8_t __code lutorig[] = {
0x00, 0x66, 0x21, 0x45, 0x40, 0x00, 0x00,
0x15, 0x66, 0x21, 0xA8, 0x20, 0xA0, 0x00,
0xA0, 0x66, 0x21, 0x85, 0x2B, 0x2F, 0x00,
0xA0, 0x66, 0x21, 0x85, 0x2B, 0x2F, 0x00,
0x00, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00,
//0x04, 0x49, 0x2F, 0x2A, 0x00,
0x0, 0x0, 0x0, 0x0, 0x0, // reverse
0x02, 0x04, 0x01, 0x03, 0x00, // was 11 repeat // fast blink
0x01, 0x14, 0x01, 0x14, 0x00, // was 3 repeat // slow pump
0x02, 0x0A, 0x03, 0x0A, 0x00, // was 2 repeat
0x06, 0x04, 0x04, 0x20, 0x00, // was 3 rpeat
0x04, 0x04, 0x02, 0x26, 0x00, // was 3 repeat
0x00, 0x00, 0x00, 0x00, 0x0,
};
static const uint8_t __code lut154[] = {
0x80, 0x66, 0x96, 0x51, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00,
0x10, 0x66, 0x96, 0x88, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
0x8A, 0x66, 0x96, 0x51, 0x0B, 0x2F, 0x00, 0x00, 0x00, 0x00,
0x8A, 0x66, 0x96, 0x51, 0x0B, 0x2F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2D, 0x55, 0x28, 0x25, 0x00,
0x02, 0x03, 0x01, 0x02, 0x00,
0x12, 0x01, 0x12, 0x01, 0x00,
0x05, 0x05, 0x02, 0x05, 0x00,
0x07, 0x01, 0x07, 0x2A, 0x00,
0x04, 0x06, 0x02, 0x2A, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x2A, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@@ -5,33 +5,131 @@
#include <stdio.h>
#include <string.h>
#include "adc.h"
#include "asmUtil.h"
#include "board.h"
#include "chars.h"
#include "comms.h"
#include "cpu.h"
#include "drawing.h"
#include "comms.h" // for mLastLqi and mLastRSSI
#include "eeprom.h"
#include "epd.h"
#include "powermgt.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "sleep.h"
#include "timer.h"
#include "wdt.h"
#include "syncedproto.h"
#include "timer.h"
#include "userinterface.h"
#include "wdt.h"
uint16_t __xdata battery_voltage = 0;
int8_t __xdata mCurTemperature;
void getVolt(void) {
if (battery_voltage == 0)
battery_voltage = adcSampleBattery();
uint8_t showChannelSelect() {
uint8_t __xdata result[16];
memset(result, 0, sizeof(result));
showScanningWindow();
for (uint8_t i = 0; i < 3; i++) {
for (uint8_t c = 11; c < 27; c++) {
if (probeChannel(c)) {
if (mLastLqi > result[c - 11]) result[c - 11] = mLastLqi;
pr("Channel: %d - LQI: %d RSSI %d\n", c, mLastLqi, mLastRSSI);
}
}
epdWaitRdy();
for (uint8_t c = 0; c < 16; c++) {
addScanResult(11 + c, result[c]);
}
drawNoWait();
}
uint8_t __xdata highestLqi = 0;
uint8_t __xdata highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++) {
if (result[c] > highestLqi) {
highestSlot = c + 11;
highestLqi = result[c];
}
}
epdWaitRdy();
return highestSlot;
}
void main(void){
void mainProtocolLoop(void) {
clockingAndIntsInit();
timerInit();
boardInit();
if (!boardGetOwnMac(mSelfMac)) {
pr("failed to get MAC. Aborting\n");
while (1)
;
} else {
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X\n", mSelfMac[6], mSelfMac[7]);
}
irqsOn();
boardInitStage2();
pr("BOOTED> (UI 0.03-1)\n\n");
if (!eepromInit()) {
pr("failed to init eeprom\n");
while (1)
;
} else {
initializeProto();
}
eepromDeepPowerDown();
// initialize Powers-saving-attempt-array with the default value;
initPowerSaving();
// show the splashscreen
showSplashScreen();
eepromDeepPowerDown();
initRadio();
currentChannel = showChannelSelect();
if (currentChannel == 0) {
// couldn't find an AP :()
showNoAP();
} else {
// Found an AP.
showAPFound();
}
epdEnterSleep();
P1CHSTA &= ~(1 << 0);
while (1) {
radioRxEnable(true, true);
struct AvailDataInfo *__xdata avail = getAvailDataInfo();
if (avail == NULL) {
// no data :(
nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period
} else {
nextCheckInFromAP = avail->nextCheckIn;
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE) {
// data transfer
if (doDataDownload(avail)) {
// succesful transfer, next wake time is determined by the NextCheckin;
} else {
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
} else {
// no data transfer, just sleep.
}
}
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP) {
doSleep(nextCheckInFromAP * 60000UL);
} else {
doSleep(getNextSleep() * 1000UL);
}
}
}
void main(void) {
mainProtocolLoop();
}

92
tag_fw/powermgt.c Normal file
View File

@@ -0,0 +1,92 @@
#include "powermgt.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "asmUtil.h"
#include "board.h"
#include "comms.h"
#include "cpu.h"
#include "drawing.h"
#include "eeprom.h"
#include "epd.h"
#include "i2c.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "sleep.h"
#include "syncedproto.h"
#include "timer.h"
#include "userinterface.h"
#include "wdt.h"
#include "settings.h"
uint16_t __xdata dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
uint8_t __xdata dataReqAttemptArrayIndex = 0;
uint8_t __xdata dataReqLastAttempt = 0;
uint16_t __xdata nextCheckInFromAP = 0;
void initPowerSaving() {
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
dataReqAttemptArr[c] = INTERVAL_BASE;
}
}
// init/sleep
void initAfterWake() {
clockingAndIntsInit();
timerInit();
// partialInit();
boardInit();
epdEnterSleep();
irqsOn();
boardInitStage2();
initRadio();
}
void doSleep(uint32_t __xdata t) {
if (t > 1000) pr("s=%lu\n ", t / 1000);
powerPortsDownForSleep();
#ifdef HAS_BUTTON
// Button setup on TEST pin 1.0 (input pullup)
P1FUNC &= ~(1 << 0);
P1DIR |= (1 << 0);
P1PULL |= (1 << 0);
P1LVLSEL |= (1 << 0);
P1INTEN = (1 << 0);
P1CHSTA &= ~(1 << 0);
#endif
// sleepy
sleepForMsec(t);
#ifdef HAS_BUTTON
P1INTEN = 0;
#endif
initAfterWake();
}
uint16_t getNextSleep() {
uint16_t __xdata curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE;
curval *= dataReqLastAttempt;
curval /= DATA_REQ_MAX_ATTEMPTS;
curval += INTERVAL_BASE;
dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval;
dataReqAttemptArrayIndex++;
uint16_t avg = 0;
bool noNetwork = true;
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
avg += dataReqAttemptArr[c];
if (dataReqAttemptArr[c] != INTERVAL_AT_MAX_ATTEMPTS) {
noNetwork = false;
}
}
if (noNetwork == true) return INTERVAL_NO_SIGNAL;
avg /= POWER_SAVING_SMOOTHING;
return avg;
}

24
tag_fw/powermgt.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef _POWERMGT_H_
#define _POWERMGT_H_
#include <stdint.h>
// power saving algorithm
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current
#define INTERVAL_NO_SIGNAL 1800 // interval (in seconds) when no answer for POWER_SAVING_SMOOTHING attempts,
// (INTERVAL_AT_MAX_ATTEMPTS * POWER_SAVING_SMOOTHING) seconds
#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request.
// If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address
#define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP
#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval
#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life!
extern void initAfterWake();
extern void doSleep(uint32_t __xdata t);
extern uint16_t getNextSleep();
extern void initPowerSaving();
extern uint16_t __xdata nextCheckInFromAP;
extern uint8_t __xdata dataReqLastAttempt;
#endif

View File

@@ -19,6 +19,9 @@
#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;

View File

@@ -1,47 +1,8 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#define __packed
#include <stdint.h>
/*
All communications are direct from tag to station, EXCEPT association (tag will broadcast).
All comms shall be encrypted and authenticated with AES-CCM. Shared key shall be burned into the firmware.
Master shall provision new key at association. All non-bcast packets shall have pan id compression.
Master may skip "from" field. Tag checking in confirms it got the master's provisioning reply.
Sadly filtering on MZ100 fails for long addr with no src addr. so short addr for src is used
T = tag, S = station
PACKET TYPE USE PAYLOAD STRUCT NOTES
ASSOC_REQ T2bcast TagInfo tag's info and assoc request (encrypted with shared key)
ASSOC_RESP S2T AssocInfo tag's association info (encrypted with shared key)
CHECKIN T2S CheckinInfo tag checking in occasionally
CHECKOUT S2T PendingInfo station's checkin reply telling tag what we have for it
CHUNK_REQ T2S ChunkReqInfo tag requesting a piece of data
CHUNK_RESP S2T ChunkInfo station provides chunk
*/
#define PROTO_PRESHARED_KEY {0x34D906D3, 0xE3E5298E, 0x3429BF58, 0xC1022081}
#define PROTO_PAN_ID (0x4447) //PAN ID compression shall be used
#define PKT_ASSOC_REQ (0xF0)
#define PKT_ASSOC_RESP (0xF1)
#define PKT_CHECKIN (0xF2)
#define PKT_CHECKOUT (0xF3)
#define PKT_CHUNK_REQ (0xF4)
#define PKT_CHUNK_RESP (0xF5)
#define PROTO_VER_0 (0)
#define PROTO_VER_CURRENT (PROTO_VER_0)
#define PROTO_COMPR_TYPE_LZ (0x0001)
#define PROTO_COMPR_TYPE_BITPACK (0x0002)
#define PROTO_MAX_DL_LEN (88)
enum TagScreenType {
TagScreenEink_BW_1bpp,
TagScreenEink_BW_2bpp,
@@ -72,111 +33,135 @@ enum TagScreenType {
#define __packed __attribute__((packed))
#endif
struct TagState {
uint64_t swVer;
uint16_t hwType;
uint16_t batteryMv;
#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 TagInfo {
uint8_t protoVer; //PROTO_VER_*
struct TagState state;
uint8_t rfu1[1]; //shall be ignored for now
uint16_t screenPixWidth;
uint16_t screenPixHeight;
uint16_t screenMmWidth;
uint16_t screenMmHeight;
uint16_t compressionsSupported; //COMPR_TYPE_* bitfield
uint16_t maxWaitMsec; //how long tag will wait for packets before going to sleep
uint8_t screenType; //enum TagScreenType
uint8_t rfu[11]; //shall be zero for now
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} __packed;
struct AssocInfo {
uint32_t checkinDelay; //space between checkins, in msec
uint32_t retryDelay; //if download fails mid-way wait thi smany msec to retry (IFF progress was made)
uint16_t failedCheckinsTillBlank; //how many fails till we go blank
uint16_t failedCheckinsTillDissoc; //how many fails till we dissociate
uint32_t newKey[4];
uint8_t rfu[8]; //shall be zero for now
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} __packed;
#define CHECKIN_TEMP_OFFSET 0x7f
#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
struct CheckinInfo {
struct TagState state;
uint8_t lastPacketLQI; //zero if not reported/not supported to be reported
int8_t lastPacketRSSI; //zero if not reported/not supported to be reported
uint8_t temperature; //zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C
uint8_t rfu[6]; //shall be zero for now
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI; // zero if not reported/not supported to be reported
int8_t lastPacketRSSI; // zero if not reported/not supported to be reported
uint8_t temperature; // zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C
uint16_t batteryMv;
uint8_t softVer;
uint8_t hwType;
uint8_t protoVer;
uint8_t buttonState;
} __packed;
struct PendingInfo {
uint64_t imgUpdateVer;
uint32_t imgUpdateSize;
uint64_t osUpdateVer; //version of OS update avail
uint32_t osUpdateSize;
uint8_t rfu[8]; //shall be zero for now
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG 1
#define DATATYPE_IMGRAW 2
#define DATATYPE_UPDATE 3
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer;
uint32_t dataSize;
uint8_t dataType;
uint16_t nextCheckIn;
} __packed;
struct ChunkReqInfo {
uint64_t versionRequested;
uint32_t offset;
uint8_t len;
uint8_t osUpdatePlz : 1;
uint8_t rfu[6]; //shall be zero for now
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} __packed;
struct ChunkInfo {
uint32_t offset;
uint8_t osUpdatePlz : 1;
uint8_t rfu; //shall be zero for now
uint8_t data[]; //no data means request is out of bounds of this version no longer exists
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]
#define VERSION_SIGNIFICANT_MASK (0x0000ffffffffffffull)
#define HW_TYPE_42_INCH_SAMSUNG (1)
#define HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST (0xEFF8)
#define HW_TYPE_74_INCH_DISPDATA (2)
#define HW_TYPE_74_INCH_DISPDATA_FRAME_MODE (3)
#define HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST (0x008b)
#define HW_TYPE_ZBD_EPOP50 (4)
#define HW_TYPE_ZBD_EPOP50_ROM_VER_OFST (0x008b)
#define HW_TYPE_ZBD_EPOP900 (5)
#define HW_TYPE_ZBD_EPOP900_ROM_VER_OFST (0x008b)
#define HW_TYPE_29_INCH_DISPDATA (6)
#define HW_TYPE_29_INCH_DISPDATA_FRAME_MODE (7)
#define HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST (0x008b)
#define HW_TYPE_29_INCH_ZBS_026 (8)
#define HW_TYPE_29_INCH_ZBS_026_FRAME_MODE (9)
#define HW_TYPE_154_INCH_ZBS_033 (18)
#define HW_TYPE_154_INCH_ZBS_033_FRAME_MODE (19)
#define HW_TYPE_42_INCH_ZBS_026 (28)
#define HW_TYPE_42_INCH_ZBS_026_FRAME_MODE (29)
#define HW_TYPE_29_INCH_ZBS_025 (10)
#define HW_TYPE_29_INCH_ZBS_025_FRAME_MODE (11)
#define HW_TYPE_29_INCH_ZBS_ROM_VER_OFST (0x008b)
#endif
#endif

12
tag_fw/settings.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef SYNCED_H
#define SYNCED_H
#include <stdint.h>
#define FW_VERSION 012 // version number (max 2.5.5 :) )
#define FW_VERSION_SUFFIX "-rf15" // suffix, like -RC1 or whatever.
#define HAS_BUTTON // uncomment to enable reading a push button (connect between 'TEST' en 'GND' on the tag, along with a 100nF capacitor in parallel).
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
#endif

View File

@@ -5,6 +5,10 @@
#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
@@ -20,22 +24,6 @@
#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;
};
void radioInit(void);
bool radioTx(const void __xdata* packet); //waits for tx end

View File

@@ -29,4 +29,14 @@ uint8_t spiByte(uint8_t val)
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

@@ -11,6 +11,9 @@ 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,7 +1,6 @@
#include "asmUtil.h"
#include "flash.h"
#include "timer.h"
#include "adc.h"
#include "cpu.h"
static volatile uint8_t __xdata mTempRet[4];

View File

@@ -4,7 +4,7 @@
#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);

View File

@@ -1,24 +1,20 @@
#include "uart.h"
#include "cpu.h"
void uartInit(void) {
// clock it up
CLKEN |= 0x20;
void uartInit(void)
{
//clock it up
CLKEN |= 0x20;
//configure
UARTBRGH = 0x00; //config for 115200
UARTBRGL = 0x8A;
UARTSTA = 0x12; //also set the "empty" bit else we wait forever for it to go up
// configure
UARTBRGH = 0x00; // config for 115200
UARTBRGL = 0x8A;
UARTSTA = 0x12; // also set the "empty" bit else we wait forever for it to go up
}
void uartTx(uint8_t val)
{
while (!(UARTSTA & (1 << 1)));
UARTSTA &=~ (1 << 1);
UARTBUF = val;
void uartTx(uint8_t val) {
while (!(UARTSTA & (1 << 1)))
;
UARTSTA &= ~(1 << 1);
UARTBUF = val;
}

View File

@@ -7,123 +7,22 @@
#include <stdio.h>
#include <string.h>
#include "adc.h"
#include "asmUtil.h"
#include "board.h"
#include "chars.h"
#include "comms.h"
#include "cpu.h"
#include "drawing.h"
#include "eeprom.h"
#include "i2c.h"
#include "powermgt.h"
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "settings.h"
#include "sleep.h"
#include "timer.h"
#include "userinterface.h"
#include "wdt.h"
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_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
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI; // zero if not reported/not supported to be reported
int8_t lastPacketRSSI; // zero if not reported/not supported to be reported
uint8_t temperature; // zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C
uint16_t batteryMv;
uint8_t softVer;
uint8_t hwType;
uint8_t protoVer;
uint8_t buttonState;
} __packed;
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG 1
#define DATATYPE_IMGRAW 2
#define DATATYPE_UPDATE 3
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer;
uint32_t dataSize;
uint8_t dataType;
uint16_t nextCheckIn;
} __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 4096
#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 TIMER_TICKS_PER_MS 1333UL
// #define DEBUGBLOCKS
// download-stuff
bool __xdata dataPending = true;
uint8_t __xdata blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
@@ -133,6 +32,7 @@ uint16_t __xdata dataRemaining = 0;
bool __xdata curXferComplete = false;
bool __xdata requestPartialBlock = false;
// uint8_t __xdata *tempBuffer = blockXferBuffer;
uint8_t __xdata curImgSlot = 0;
uint32_t __xdata curHighSlotId = 0;
uint8_t __xdata nextImgSlot = 0;
@@ -149,24 +49,7 @@ uint8_t __xdata APmac[8] = {0};
uint16_t __xdata APsrcPan = 0;
uint8_t __xdata mSelfMac[8] = {0};
uint8_t __xdata seq = 0;
// power saving algorithm
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current
#define INTERVAL_NO_SIGNAL 1800 // interval (in seconds) when no answer for POWER_SAVING_SMOOTHING attempts,
// (INTERVAL_AT_MAX_ATTEMPTS * POWER_SAVING_SMOOTHING) seconds
#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request.
// If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address
#define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP
#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval
#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life!
#define HAS_BUTTON // uncomment to enable reading a push button (connect between 'TEST' en 'GND' on the tag, along with a 100nF capacitor in parallel).
uint16_t __xdata dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
uint8_t __xdata dataReqAttemptArrayIndex = 0;
uint8_t __xdata dataReqLastAttempt = 0;
uint16_t __xdata nextCheckInFromAP = 0;
uint8_t __xdata currentChannel = 0;
// buffer we use to prepare/read packets
// static uint8_t __xdata mRxBuf[130];
@@ -225,11 +108,15 @@ void addCRC(void *p, uint8_t len) {
((uint8_t *)p)[0] = total;
}
// init/sleep
// radio stuff
void initRadio() {
radioInit();
radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID);
radioSetChannel(RADIO_FIRST_CHANNEL);
if (currentChannel >= 11 && currentChannel <= 25) {
radioSetChannel(currentChannel);
} else {
radioSetChannel(RADIO_FIRST_CHANNEL);
}
radioSetTxPower(10);
}
void killRadio() {
@@ -243,58 +130,14 @@ void killRadio() {
RADIO_command = 0xC5;
CFGPAGE = cfgPg;
}
void initAfterWake() {
clockingAndIntsInit();
timerInit();
// partialInit();
boardInit();
screenSleep();
irqsOn();
boardInitStage2();
initRadio();
}
void doSleep(uint32_t __xdata t) {
if(t>1000)pr("s=%lu\n ", t / 1000);
powerPortsDownForSleep();
bool probeChannel(uint8_t channel) {
radioRxEnable(false, true);
radioRxFlush();
radioSetChannel(channel);
radioRxEnable(true, true);
getAvailDataInfo();
return(dataReqLastAttempt != DATA_REQ_MAX_ATTEMPTS);
#ifdef HAS_BUTTON
//Button setup on TEST pin 1.0 (input pullup)
P1FUNC &=~ (1 << 0);
P1DIR |= (1 << 0);
P1PULL |= (1 << 0);
P1LVLSEL |= (1 << 0);
P1INTEN = (1 << 0);
P1CHSTA &=~ (1 << 0);
#endif
// sleepy
sleepForMsec(t);
#ifdef HAS_BUTTON
P1INTEN = 0;
#endif
initAfterWake();
}
uint16_t getNextSleep() {
uint16_t __xdata curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE;
curval *= dataReqLastAttempt;
curval /= DATA_REQ_MAX_ATTEMPTS;
curval += INTERVAL_BASE;
dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval;
dataReqAttemptArrayIndex++;
uint16_t avg = 0;
bool noNetwork = true;
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
avg += dataReqAttemptArr[c];
if (dataReqAttemptArr[c] != INTERVAL_AT_MAX_ATTEMPTS) {
noNetwork = false;
}
}
if (noNetwork == true) return INTERVAL_NO_SIGNAL;
avg /= POWER_SAVING_SMOOTHING;
return avg;
}
// data xfer stuff
@@ -312,14 +155,14 @@ void sendAvailDataReq() {
txframe->seq = seq++;
txframe->dstPan = 0xFFFF;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = 0x4447;
txframe->srcPan = PROTO_PAN_ID;
// TODO: send some meaningful data
availreq->softVer = 1;
if (P1CHSTA && (1 << 0)) {
availreq->buttonState = 1;
pr("button pressed\n");
P1CHSTA &=~ (1 << 0);
}
if (P1CHSTA && (1 << 0)) {
availreq->buttonState = 1;
pr("button pressed\n");
P1CHSTA &= ~(1 << 0);
}
addCRC(availreq, sizeof(struct AvailDataReq));
commsTxNoCpy(outBuffer);
}
@@ -504,45 +347,6 @@ bool validateBlockData() {
return bd->checksum == t;
}
const uint8_t epd_bitmap_ant[] = {
0xff, 0xbf, 0xfd, 0xdf, 0xfe, 0xdf, 0xee, 0xdf, 0xee, 0xdf, 0xed, 0xdf, 0xd7, 0xbf, 0xd7, 0xff,
0xd7, 0xff, 0xbb, 0xff, 0xbb, 0xbb, 0xbb, 0xd7, 0xbb, 0xef, 0x7d, 0xd7, 0x7d, 0xbb, 0x01, 0xff};
void copyImage() {
uint8_t x_begin = 17;
uint16_t y_begin = 0;
uint8_t y_size = 16;
const uint8_t *p = epd_bitmap_ant;
pr("begin copy image to epd buffer");
for (uint16_t y = 0; y < y_size; y++) {
// moveToXY(x_begin, y_begin + y, false);
pr("d=%02X,", *p);
// screenByteRawTx(*p);
p++;
// screenByteRawTx(*p);
p++;
}
}
void drawPartial() {
screenSleep();
screenTxStart(true);
pr("sending bytes\n");
for (uint8_t iteration = 0; iteration < SCREEN_DATA_PASSES; iteration++) {
for (uint16_t y = 0; y < SCREEN_HEIGHT; y++) {
for (uint8_t x = 0; x < SCREEN_WIDTH / 8; x++) {
if (iteration == 0) {
// screenByteRawTx(0xFF);
} else {
// screenByteRawTx(0x00);
}
}
}
screenEndPass();
pr("pass complete\n");
}
copyImage();
screenTxEnd();
}
// EEprom related stuff
uint32_t getAddressForSlot(uint8_t s) {
return EEPROM_IMG_START + (EEPROM_IMG_EACH * s);
@@ -564,7 +368,7 @@ uint8_t findSlot(uint8_t *__xdata ver) {
// return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere
uint32_t __xdata markerValid = EEPROM_IMG_VALID;
for (uint8_t __xdata c = 0; c < imgSlots; c++) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)mScreenRow;
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (xMemEqual4(&eih->validMarker, &markerValid)) {
if (xMemEqual(&eih->version, (void *)ver, 8)) {
@@ -600,7 +404,7 @@ uint32_t getHighSlotId() {
uint32_t temp = 0;
uint32_t __xdata markerValid = EEPROM_IMG_VALID;
for (uint8_t __xdata c = 0; c < imgSlots; c++) {
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)mScreenRow;
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (xMemEqual4(&eih->validMarker, &markerValid)) {
if (temp < eih->id) {
@@ -613,7 +417,6 @@ uint32_t getHighSlotId() {
return temp;
}
// #define DEBUGBLOCKS
// Main download function
bool doDataDownload(struct AvailDataInfo *__xdata avail) {
// this is the main function for the download process
@@ -843,7 +646,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
case DATATYPE_IMG:
case DATATYPE_IMGRAW:;
// transfer complete. Save data info and mark data in image slot as 'valid'
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)mScreenRow;
struct EepromImageHeader __xdata *eih = (struct EepromImageHeader __xdata *)blockXferBuffer;
xMemCopy8(&eih->version, &curDataInfo.dataVer);
eih->size = curDataInfo.dataSize;
eih->validMarker = EEPROM_IMG_VALID;
@@ -858,6 +661,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
break;
case DATATYPE_UPDATE:
pr("firmware download complete, doing update.\n");
showApplyUpdate();
curXferComplete = true;
sendXferComplete();
killRadio();
@@ -874,88 +678,7 @@ bool doDataDownload(struct AvailDataInfo *__xdata avail) {
return true;
}
// main loop;
void mainProtocolLoop(void) {
clockingAndIntsInit();
timerInit();
boardInit();
if (!boardGetOwnMac(mSelfMac)) {
pr("failed to get MAC. Aborting\n");
while (1)
;
} else {
/*
for (uint8_t c = 0; c < 8; c++) {
mSelfMac[c] = c + 5;
}
*/
// really... if I do the call below, it'll cost me 8 bytes IRAM. Not the kind of 'optimization' I ever dreamed of doing
// pr("MAC>%02X%02X%02X%02X%02X%02X%02X%02X\n", mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3], mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7]);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X\n", mSelfMac[6], mSelfMac[7]);
}
irqsOn();
boardInitStage2();
// i2ctest();
pr("BOOTED> (new version!)\n\n");
if (!eepromInit()) {
pr("failed to init eeprom\n");
drawFullscreenMsg((const __xdata char *)"eeprom failed");
while (1)
;
} else {
getNumSlots();
curHighSlotId = getHighSlotId();
}
// initialize attempt-array with the default value;
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
dataReqAttemptArr[c] = INTERVAL_BASE;
}
screenSleep();
eepromDeepPowerDown();
initRadio();
P1CHSTA &=~ (1 << 0);
// drawPartial();
// i2ctest();
// doSleep(10000);
while (1) {
radioRxEnable(true, true);
struct AvailDataInfo *__xdata avail = getAvailDataInfo();
if (avail == NULL) {
// no data :(
nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period
} else {
nextCheckInFromAP = avail->nextCheckIn;
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE) {
// data transfer
if (doDataDownload(avail)) {
// succesful transfer, next wake time is determined by the NextCheckin;
} else {
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
} else {
// no data transfer, just sleep.
}
}
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP) {
doSleep(nextCheckInFromAP * 60000UL);
} else {
doSleep(getNextSleep() * 1000UL);
}
}
void initializeProto() {
getNumSlots();
curHighSlotId = getHighSlotId();
}

View File

@@ -3,8 +3,18 @@
#include <stdint.h>
void mainProtocolLoop(void);
extern uint8_t __xdata mSelfMac[];
extern uint8_t __xdata mSelfMac[8];
extern uint8_t __xdata currentChannel;
extern uint8_t __xdata APmac[];
extern void initRadio();
extern void killRadio();
extern struct AvailDataInfo *__xdata getAvailDataInfo();
extern bool doDataDownload(struct AvailDataInfo *__xdata avail);
extern void initializeProto();
extern struct AvailDataInfo *__xdata getAvailDataInfo();
bool probeChannel(uint8_t channel);
#endif

221
tag_fw/userinterface.c Normal file
View File

@@ -0,0 +1,221 @@
#include "userinterface.h"
#include <stdbool.h>
#include <string.h>
#include "asmUtil.h"
#include "bitmaps.h"
#include "board.h"
#include "comms.h"
#include "cpu.h"
#include "epd.h"
#include "font.h"
#include "lut.h"
#include "printf.h"
#include "screen.h"
#include "settings.h"
#include "sleep.h"
#include "spi.h"
#include "syncedproto.h" // for APmac / Channel
#include "timer.h"
extern uint8_t __xdata mSelfMac[8];
extern uint8_t __xdata currentChannel;
extern uint8_t __xdata APmac[];
static const uint8_t __code fwVersion = FW_VERSION;
static const char __code fwVersionSuffix[] = FW_VERSION_SUFFIX;
void showSplashScreen() {
epdSetup();
#if (SCREEN_WIDTH == 152) // 1.54"
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
selectLUT(1);
epdPrintBegin(12, 2, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Starting!");
epdPrintEnd();
loadRawBitmap(solum, 8, 34, EPD_COLOR_BLACK);
loadRawBitmap(hacked, 32, 46, EPD_COLOR_RED);
epdPrintBegin(5, 136, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("%02X%02X", mSelfMac[7], mSelfMac[6]);
epdpr("%02X%02X", mSelfMac[5], mSelfMac[4]);
epdpr("%02X%02X", mSelfMac[3], mSelfMac[2]);
epdpr("%02X%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
epdPrintBegin(2, 120, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs154v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
draw();
#endif
#if (SCREEN_WIDTH == 128) // 2.9"
selectLUT(1);
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
epdPrintBegin(0, 295, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Starting!");
epdPrintEnd();
epdPrintBegin(80, 295, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs29v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
epdPrintBegin(105, 270, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]);
epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]);
epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]);
epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
uint8_t __xdata buffer[17];
spr(buffer, "%02X%02X", mSelfMac[7], mSelfMac[6]);
spr(buffer + 4, "%02X%02X", mSelfMac[5], mSelfMac[4]);
spr(buffer + 8, "%02X%02X", mSelfMac[3], mSelfMac[2]);
spr(buffer + 12, "%02X%02X", mSelfMac[1], mSelfMac[0]);
printBarcode(buffer, 120, 284);
loadRawBitmap(solum, 0, 0, EPD_COLOR_BLACK);
loadRawBitmap(hacked, 16, 12, EPD_COLOR_RED);
// lutTest();
// drawLineVertical(EPD_COLOR_RED, 64, 10, 286);
// drawLineVertical(EPD_COLOR_BLACK, 65, 10, 286);
draw();
timerDelay(TIMER_TICKS_PER_SECOND * 10);
#endif
#if (SCREEN_WIDTH == 400) // 2.9"
selectLUT(1);
clearScreen();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
epdPrintBegin(300, 296, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_RED);
epdpr("Booting!Y");
epdpr();
epdPrintBegin(0, 0, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Starting!");
epdPrintEnd();
epdPrintBegin(16, 252, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("zbs42v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
epdPrintEnd();
epdPrintBegin(16, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]);
epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]);
epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]);
epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
loadRawBitmap(solum, 256, 10, EPD_COLOR_BLACK);
loadRawBitmap(hacked, 264, 22, EPD_COLOR_RED);
loadRawBitmap(solum, 253, 72, EPD_COLOR_BLACK);
loadRawBitmap(hacked, 261, 82, EPD_COLOR_RED);
draw();
#endif
}
void showApplyUpdate() {
epdSetup();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
selectLUT(1);
clearScreen();
setColorMode(EPD_MODE_IGNORE, EPD_MODE_NORMAL);
epdPrintBegin(8, 60, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Updating!");
epdPrintEnd();
drawNoWait();
}
uint8_t __xdata resultcounter = 0;
void showScanningWindow() {
epdSetup();
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
selectLUT(1);
clearScreen();
epdPrintBegin(0, 275, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Scanning for APs");
epdPrintEnd();
epdPrintBegin(40, 262, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("Channel - Quality");
epdPrintEnd();
loadRawBitmap(receive, 36, 24, EPD_COLOR_BLACK);
drawNoWait();
selectLUT(2);
resultcounter = 0;
}
void addScanResult(uint8_t channel, uint8_t lqi) {
if (channel == 11) resultcounter = 0;
epdPrintBegin(56 + ((resultcounter % 4) * 16), 282 - (47 * (resultcounter / 4)), EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("%d-%d", channel, lqi);
epdPrintEnd();
resultcounter++;
}
void showAPFound() {
pr("Showing AP found");
selectLUT(1);
clearScreen();
epdPrintBegin(0, 285, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Waiting for data...");
epdPrintEnd();
epdPrintBegin(48, 278, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("Found the following AP:");
epdPrintEnd();
epdPrintBegin(64, 293, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("AP MAC: %02X:%02X", APmac[7], APmac[6]);
epdpr(":%02X:%02X", APmac[5], APmac[4]);
epdpr(":%02X:%02X", APmac[3], APmac[2]);
epdpr(":%02X:%02X", APmac[1], APmac[0]);
epdPrintEnd();
epdPrintBegin(80, 293, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("Ch: %d RSSI: %d LQI: %d", currentChannel, mLastRSSI, mLastLqi);
epdPrintEnd();
epdPrintBegin(103, 258, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("Tag MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]);
epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]);
epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]);
epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]);
epdPrintEnd();
uint8_t __xdata buffer[17];
spr(buffer, "%02X%02X", mSelfMac[7], mSelfMac[6]);
spr(buffer + 4, "%02X%02X", mSelfMac[5], mSelfMac[4]);
spr(buffer + 8, "%02X%02X", mSelfMac[3], mSelfMac[2]);
spr(buffer + 12, "%02X%02X", mSelfMac[1], mSelfMac[0]);
printBarcode(buffer, 120, 253);
loadRawBitmap(receive, 36, 14, EPD_COLOR_BLACK);
draw();
}
void showNoAP() {
clearScreen();
epdPrintBegin(0, 285, EPD_DIRECTION_Y, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("No AP found :(");
epdPrintEnd();
epdPrintBegin(48, 285, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("We'll try again in a");
epdPrintEnd();
epdPrintBegin(64, 285, EPD_DIRECTION_Y, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
epdpr("little while...");
epdPrintEnd();
loadRawBitmap(receive, 36, 24, EPD_COLOR_BLACK);
loadRawBitmap(failed, 42, 26, EPD_COLOR_RED);
draw();
}

11
tag_fw/userinterface.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _UI_H_
#define _UI_H_
#include <stdint.h>
void showSplashScreen();
void showApplyUpdate();
void showScanningWindow();
void addScanResult(uint8_t channel, uint8_t lqi);
void showAPFound();
void showNoAP();
#endif