diff --git a/tag_fw/Makefile b/tag_fw/Makefile index 7dcae7e6..fae0f459 100644 --- a/tag_fw/Makefile +++ b/tag_fw/Makefile @@ -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 diff --git a/tag_fw/adc.h b/tag_fw/adc.h deleted file mode 100644 index c495bc07..00000000 --- a/tag_fw/adc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ADC_H_ -#define _ADC_H_ - -#include - -extern uint16_t __xdata mAdcSlope; -extern uint16_t __xdata mAdcIntercept; - - -uint16_t adcSampleBattery(void); //in mV -int8_t adcSampleTemperature(void); //in degrees C - - - - -#endif diff --git a/tag_fw/bitmaps.h b/tag_fw/bitmaps.h new file mode 100644 index 00000000..d16feecf --- /dev/null +++ b/tag_fw/bitmaps.h @@ -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 + +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 \ No newline at end of file diff --git a/tag_fw/board/boardZBS29common.c b/tag_fw/board/boardZBS29common.c index ee41370c..7a662eed 100644 --- a/tag_fw/board/boardZBS29common.c +++ b/tag_fw/board/boardZBS29common.c @@ -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 diff --git a/tag_fw/board/zbs154v033/board.h b/tag_fw/board/zbs154v033/board.h index 6e9a87ee..b5683d58 100644 --- a/tag_fw/board/zbs154v033/board.h +++ b/tag_fw/board/zbs154v033/board.h @@ -4,27 +4,11 @@ #include #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 \ No newline at end of file diff --git a/tag_fw/board/zbs154v033/screen.c b/tag_fw/board/zbs154v033/screen.c deleted file mode 100644 index 2bd46f4d..00000000 --- a/tag_fw/board/zbs154v033/screen.c +++ /dev/null @@ -1,475 +0,0 @@ -#include "screen.h" - -#include - -#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; -} diff --git a/tag_fw/board/zbs154v033/screen.h b/tag_fw/board/zbs154v033/screen.h index 479da353..034fd430 100644 --- a/tag_fw/board/zbs154v033/screen.h +++ b/tag_fw/board/zbs154v033/screen.h @@ -4,12 +4,6 @@ #include #include - -//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 \ No newline at end of file diff --git a/tag_fw/board/zbs29v033/board.h b/tag_fw/board/zbs29v033/board.h index 8951cd17..e63b5e11 100644 --- a/tag_fw/board/zbs29v033/board.h +++ b/tag_fw/board/zbs29v033/board.h @@ -4,27 +4,11 @@ #include #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 \ No newline at end of file diff --git a/tag_fw/board/zbs29v033/screen.c b/tag_fw/board/zbs29v033/screen.c deleted file mode 100644 index d434b693..00000000 --- a/tag_fw/board/zbs29v033/screen.c +++ /dev/null @@ -1,397 +0,0 @@ -#include -#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; -} diff --git a/tag_fw/board/zbs29v033/screen.h b/tag_fw/board/zbs29v033/screen.h index 576238d5..26f70666 100644 --- a/tag_fw/board/zbs29v033/screen.h +++ b/tag_fw/board/zbs29v033/screen.h @@ -4,12 +4,6 @@ #include #include - -//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 \ No newline at end of file diff --git a/tag_fw/board/zbs42v033/board.h b/tag_fw/board/zbs42v033/board.h index b23787ee..0cf71379 100644 --- a/tag_fw/board/zbs42v033/board.h +++ b/tag_fw/board/zbs42v033/board.h @@ -4,27 +4,11 @@ #include #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 \ No newline at end of file diff --git a/tag_fw/board/zbs42v033/screen.c b/tag_fw/board/zbs42v033/screen.c deleted file mode 100644 index eb36fdea..00000000 --- a/tag_fw/board/zbs42v033/screen.c +++ /dev/null @@ -1,416 +0,0 @@ -#include -#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; -} diff --git a/tag_fw/board/zbs42v033/screen.h b/tag_fw/board/zbs42v033/screen.h index e02a55d8..96501a0e 100644 --- a/tag_fw/board/zbs42v033/screen.h +++ b/tag_fw/board/zbs42v033/screen.h @@ -4,12 +4,6 @@ #include #include - -//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 \ No newline at end of file diff --git a/tag_fw/chars.c b/tag_fw/chars.c deleted file mode 100644 index c7ba9f26..00000000 --- a/tag_fw/chars.c +++ /dev/null @@ -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, -}; \ No newline at end of file diff --git a/tag_fw/chars.h b/tag_fw/chars.h deleted file mode 100644 index 176968d6..00000000 --- a/tag_fw/chars.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _CHARS_H_ -#define _CHARS_H_ - -#include -#include - - -#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 diff --git a/tag_fw/comms.c b/tag_fw/comms.c index 273f81a2..10c6557c 100644 --- a/tag_fw/comms.c +++ b/tag_fw/comms.c @@ -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) { diff --git a/tag_fw/comms.h b/tag_fw/comms.h index 7c1c67b9..c80f0113 100644 --- a/tag_fw/comms.h +++ b/tag_fw/comms.h @@ -3,21 +3,16 @@ #include -#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); diff --git a/tag_fw/cpu/8051/printf.c b/tag_fw/cpu/8051/printf.c index 93246c9c..be6dc10c 100644 --- a/tag_fw/cpu/8051/printf.c +++ b/tag_fw/cpu/8051/printf.c @@ -1,795 +1,799 @@ -#include -#include -#include #include "printf.h" -#include "zbs243.h" + +#include +#include +#include + #include "board.h" +#include "epd.h" +#include "uart.h" +#include "zbs243.h" typedef void (*StrFormatOutputFunc)(uint32_t param /* low byte is data, bits 24..31 is char */) __reentrant; -static __idata __at (0x00) unsigned char R0; -static __idata __at (0x01) unsigned char R1; -static __idata __at (0x02) unsigned char R2; -static __idata __at (0x03) unsigned char R3; -static __idata __at (0x04) unsigned char R4; -static __idata __at (0x05) unsigned char R5; -static __idata __at (0x06) unsigned char R6; -static __idata __at (0x07) unsigned char R7; +static __idata __at(0x00) unsigned char R0; +static __idata __at(0x01) unsigned char R1; +static __idata __at(0x02) unsigned char R2; +static __idata __at(0x03) unsigned char R3; +static __idata __at(0x04) unsigned char R4; +static __idata __at(0x05) unsigned char R5; +static __idata __at(0x06) unsigned char R6; +static __idata __at(0x07) unsigned char R7; static uint8_t __xdata mCvtBuf[18]; - -//callback must be reentrant and callee_saves +// callback must be reentrant and callee_saves #pragma callee_saves prvPrintFormat -void prvPrintFormat(StrFormatOutputFunc formatF, uint16_t formatD, const char __code *fmt, va_list vl) __reentrant __naked -{ - //formatF is in DPTR - //sp[0..-1] is return addr - //sp[-2..-3] is formatD - //sp[-4..-5] is fmt - //sp[-6] is vl - - __asm__ ( - " push _R7 \n" - " push DPH \n" //push formatF - " push DPL \n" - " mov _R7, sp \n" //save place on stack where we stashed it so we can call it easily - " push _R4 \n" - " push _R3 \n" - " push _R2 \n" - " push _R1 \n" - " push _R0 \n" - - " mov A, #-12 \n" - " add A, sp \n" - " mov R0, A \n" - //R0 now points to pushed params, for large values, we see high bytes first - // to get next byte, we need to DECEREMENT R0 - - " mov DPH, @R0 \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" - " dec R0 \n" - - //now format string is in DPTR, and R0 points to the top byte of whatever was in the first param - - //main loop: get a byte of the format string - "00001$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - //if zero, we're done - " jz 00098$ \n" - //if not '%', print it - " cjne A, #'%', 00097$ \n" - - //we got a percent sign - init state for format processing - " mov R4, #0 \n" //bit flags: - // 0x01 = '*' = pointer provided instead of value (integers only) - // 0x02 = '0' = zero-pad (for numbers only) - // 0x04 = have pad-to length - // 0x08 = long - // 0x10 = long long - // 0x20 = signed print requested. also: need to print a negative (used to reuse hex printing for decimal once converted to bcd) - " mov R2, #0 \n" //padLen - - //loop for format string ingestion - "00002$: \n" - " clr A \n" - " movc A, @A + DPTR \n" - " inc DPTR \n" - //if zero, we're done - " jz 00098$ \n" - //check for percent sign - " cjne A, #'%', 00003$ \n" - //fallthrough to print it and go read next non-format byte - //print a char in A, go read next format byte - "00097$: \n" - " lcall 00060$ \n" - " sjmp 00001$ \n" - - //exit label - placed for easy jumping to - "00098$: \n" - " pop _R0 \n" - " pop _R1 \n" - " pop _R2 \n" - " pop _R3 \n" - " pop _R4 \n" - " pop DPL \n" - " pop DPH \n" - " pop _R7 \n" - " ret \n" - - //continue to process format string - handle %c - "00003$: \n" - " cjne A, #'c', 00004$ \n" - " dec R0 \n" //param is pushed as int (16 bits) - " mov A, @R0 \n" - " dec R0 \n" - " sjmp 00097$ \n" //print and go read next non-format byte - - //continue to process format string - handle %m - "00004$: \n" - " mov R3, A \n" - " orl A, #0x20 \n" - " cjne A, #'m', 00008$ \n" - - //sort out which hexch charset to use - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R1, A \n" - - //go, do - " push DPH \n" - " push DPL \n" - " lcall 00090$ \n" //read the short (__xdata) pointer - >DPTR - " mov R4, #8 \n" //byteSel - "00005$: \n" - " push DPH \n" - " push DPL \n" - " mov A, R4 \n" - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0 \n" - " mov DPH, A \n" - " movx A, @DPTR \n" - " mov R2, A \n" - " swap A \n" - " mov R3, #2 \n" - "00006$: \n" - " anl A, #0x0f \n" - " add A, R1 \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " lcall 00060$ \n" - " mov A, R2 \n" - " djnz R3, 00006$ \n" - " pop DPL \n" - " pop DPH \n" - " djnz R4, 00007$ \n" - //done with mac addr - - "00055$: \n" - " pop DPL \n" - " pop DPH \n" - " sjmp 00001$ \n" - //print colon and contimue mac addr printing - "00007$: \n" - " mov A, #':' \n" - " lcall 00060$ \n" - " sjmp 00005$ \n" - - //continue to process format string - handle '*' - "00008$: \n" - " mov A, R3 \n" - " cjne A, #'*', 00009$ \n" - " cjne R2, #0, 00097$ \n" //only valid when no length/padding has been specified yet, else invalid specifier - " mov A, #0x01 \n" //"pointer mode" - "00010$: \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00002$ \n" //get next format specifier now - - //continue to process format string - handle '0' - "00009$: \n" - " cjne A, #'0', 00011$ \n" - " cjne R2, #0, 00011$ \n" //setting "zero pad" is only valid when pad length is zero - " mov A, #0x06 \n" //"have pad length" | "zero-pad" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle '1'...'9' - "00011$: \n" - " mov R3, A \n" - " add A, #-'0' \n" - " jnc 00012$ \n" //now 0..9 are valid - " add A, #-10 \n" - " jc 00012$ \n" - " add A, #10 \n" //get it back into 1..9 range - " mov R3, A \n" - " mov A, #10 \n" - " mov B, R2 \n" - " mul AB \n" - " add A, R3 \n" - " mov R2, A \n" - " mov A, #0x04 \n" //"have pad length" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle 'l' - "00012$: \n" - " cjne R3, #'l', 00014$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " jz 00013$ \n" //no "long" yet? set that - //have long - set long log - " mov A, #0x10 \n" //"long long" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - //first 'l' - set long - "00013$: \n" - " mov A, #0x08 \n" //"long" - " sjmp 00010$ \n" //orr A into R4, get next format specifier now - - //continue to process format string - handle 's' - "00014$: \n" - " cjne R3, #'s', 00025$ \n" - " mov A, R4 \n" - " anl A, #0x08 \n" - " push DPH \n" - " push DPL \n" - " jnz 00015$ \n" - " lcall 00091$ \n" //get and resolve generic pointer into DPTR - " sjmp 00016$ \n" - "00015$: \n" //get short pointer into DPTR, record that it is to XRAM - " clr PSW.5 \n" - " clr PSW.1 \n" - " lcall 00090$ \n" - "00016$: \n" //pointer to string now in DPTR - //we have the string pointer in {DPTR,PSW}, let's see if we have padding to do - " mov A, R4 \n" - " anl A, #0x04 \n" - " jnz 00018$ \n" - //print string with no length restrictions - "00017$: \n" - " lcall 00095$ \n" - " jz 00055$ \n" - " lcall 00060$ \n" - " sjmp 00017$ \n" - - //print string with length restrictions and/or padding - "00018$: \n" - " cjne R2, #0, 00019$ \n" //verify reqested len was not zero - " sjmp 00055$ \n" - - "00019$: \n" - " lcall 00095$ \n" - " jz 00020$ \n" - " lcall 00060$ \n" - " djnz R2, 00019$ \n" - //we get here if we ran out of allowable bytes - we're done then - " ljmp 00055$ \n" - - //just a trampoline for range issues - "00035$: \n" - " ljmp 00036$ \n" - - //we need to pad with spaces - "00020$: \n" - " mov A, #' ' \n" - " lcall 00060$ \n" - " djnz R2, 00020$ \n" - " ljmp 00055$ \n" - - //continue to process format string - handle 'x'/'X' - "00025$: \n" - " mov A, R3 \n" - " orl A, #0x20 \n" - " cjne A, #'x', 00035$ \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" //get pointer to the number in DPTR, length in bytes in B - //save it - - "00070$: \n" - " push DPH \n" - " push DPL \n" - - //sort out how long it would be if printed, first get a pointer to the highest - " mov A, B \n" - " rl A \n" - " mov R1, A \n" - " rr A \n" - " add A, #0xff \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - "00026$: \n" - " lcall 00079$ \n" - " anl A, #0xf0 \n" - " jnz 00028$ \n" - " dec R1 \n" - " lcall 00079$ \n" - " jnz 00028$ \n" - " dec R1 \n" - //dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00027$ \n" - " dec DPH \n" - "00027$: \n" - " djnz B, 00026$ \n" - - //we now know how many digits the number is (in R1), except that it has "0" if the number if zero, we cannot have that - "00028$: \n" - " cjne R1, #0, 00029$ \n" - " inc R1 \n" - "00029$: \n" //we now finally have the full length of the digits - - //if the number is negative (happens when we're printing decimals) - // the length of it is one more, also in case of zero-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00051$ \n" - " inc R1 \n" //the length is one more - " mov A, R4 \n" - " anl A, #02 \n" //if zero-padding, the negative comes now - " jz 00051$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00051$: \n" - - //sort out if we need padding at all and if there is space - " mov A, R4 \n" - " anl A, #0x04 \n" - " jz 00031$ \n" //no padding requested - //padding was requested len is in R2 - " mov A, R2 \n" - " clr C \n" - " subb A, R1 \n" - " jc 00031$ \n" //pad-to len < number_len -> no padding needed - " jz 00031$ \n" //pad-to len == number_len -> no padding needed - " mov R2, A \n" - - //sort out which character to use -> DPL - " mov A, R4 \n" //fancy way to create space/zero as needed - " anl A, #0x02 \n" - " swap A \n" - " rr A \n" - " add A, #0x20 \n" - " mov DPL, A \n" - - //pad! - "00030$: \n" - " mov A, DPL \n" - " lcall 00060$ \n" - " djnz R2, 00030$ \n" - "00031$: \n" - - //if the number is negative (happens when we're printing decimals) - // we made the length of it is one more, which we need to undo - // also in case of space-padding, we need to print the minus sign here now - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00052$ \n" - " dec R1 \n" //the length is one less than we had increased it to - " mov A, R4 \n" - " anl A, #02 \n" //if space-padding, the negative comes now - " jnz 00052$ \n" - " mov A, #'-' \n" - " lcall 00060$ \n" - "00052$: \n" - - //time to print the number itself - //sort out which hexch charset to use -> R2 - " mov A, R3 \n" - " anl A, #0x20 \n" - " rr A \n" - " mov R2, A \n" - //re-get the number pointer - " pop DPL \n" - " pop DPH \n" - //currently DPTR points to the number low byte, R1 is now many digits we expect to print, R2 is the charset selection, R4 and R3 are free - //let's calculate how many bytes we expect to process -> R4 - " mov A, R1 \n" - " inc A \n" - " clr C \n" - " rrc A \n" - " mov R4, A \n" - //let's repoint DPTR to the first byte we'll print in (remember we print 2 digits per byte) - " dec A \n" - " add A, DPL \n" - " mov DPL, A \n" - " mov A, DPH \n" - " addc A, #0x00 \n" - " mov DPH, A \n" - - //decide if we need to print just a nibble of the high byte or the whole thing. Free up R1 - " mov A, R1 \n" - " anl A, #0x01 \n" - " jz 00032$ \n" - - //we're printing just the low nibble of the first byte - set up for it - " lcall 00079$ \n" - " mov R1, #1 \n" - " sjmp 00033$ \n" - - //print loop - "00032$: \n" - " lcall 00079$ \n" - " mov R1, #2 \n" - " mov R3, A \n" - " swap A \n" - "00033$: \n" - " anl A, #0x0f \n" - " add A, R2 \n" - " push DPH \n" - " push DPL \n" - " mov DPTR, #00099$ \n" - " movc A, @A + DPTR \n" - " pop DPL \n" - " pop DPH \n" - " lcall 00060$ \n" - " mov A, R3 \n" - " djnz R1, 00033$ \n" - - //dec DPTR - " dec DPL \n" - " mov A, DPL \n" - " cjne A, #0xff, 00034$ \n" - " dec DPH \n" - "00034$: \n" - " djnz R4, 00032$ \n" - - //done! - " ljmp 00055$ \n" - - //continue to process format string - handle 'd' - "00036$: \n" - " cjne R3, #'d', 00037$ \n" - " mov A, #0x20 \n" - " orl A, R4 \n" - " mov R4, A \n" - " sjmp 00040$ \n" - - //continue to process format string - handle 'u' - "00037$: \n" - " cjne R3, #'u', 00038$ \n" - " sjmp 00040$ \n" - - //no more format strings exist that we can handle - bail - "00038$: \n" - " ljmp 00001$ \n" - - //handle decimal printing - "00040$: \n" - " push DPH \n" - " push DPL \n" - " lcall 00080$ \n" //get pointer to the number in DPTR, length in bytes in B - " push B \n" - - //copy the number to the double-dabble storage at proper offset (0 for u64, 4 for u32, 6 for u16) - //we do this so that the dabble area always starts at the same place... - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov R1, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov R3, A \n" - "00041$: \n" - " lcall 00079$ \n" - " inc DPTR \n" - " lcall 00086$ \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " lcall 00086$ \n" - " djnz B, 00041$ \n" - //leave DPTR pointing to dabble storage, past the number - " lcall 00086$ \n" - - //we now have the top byte of the number in A, good time to check for negatives, if needed - " mov B, A \n" - " mov A, R4 \n" - " anl A, #0x20 \n" - " jz 00050$ \n" //unsigned printing requested - " mov A, B \n" - " anl A, #0x80 \n" - " jnz 00043$ \n" //is negative - we need to invert, 0x20 bit in R1 stays - //positive - 0x20 bit in R1 needs to go - " mov A, R4 \n" - " anl A, #~0x20 \n" - " mov R4, A \n" - " sjmp 00050$ \n" - - //we need to negate the number - // but first we need a pointer to it, and its size - "00043$: \n" - " pop B \n" - " push B \n" - " mov A, #8 \n" - " clr C \n" - " subb A, B \n" - " add A, #_mCvtBuf \n" - " mov DPL, A \n" - " clr A \n" - " addc A, #(_mCvtBuf >> 8) \n" - " mov DPH, A \n" - - //ok, now we are ready to negate it - " clr C \n" - "00049$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " clr A \n" - " subb A, R1 \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00049$ \n" - - //zero out the rest of the storage (10 bytes) - "00050$: \n" - " mov B, #10 \n" - " clr A \n" - "00042$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00042$ \n" - - //calculate number of dabble steps - " pop A \n" - " swap A \n" - " rr A \n" - " mov R3, A \n" - - //do the thing - "00044$: \n" - - //dabble (10 iters for simplicity) - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - "00046$: \n" - " movx A, @DPTR \n" - " mov R1, A \n" - " anl A, #0x0f \n" - " add A,#-0x05 \n" - " mov A, R1 \n" - " jnc 00047$ \n" - " add A, #0x03 \n" - "00047$: \n" - " mov R1, A \n" - " anl A, #0xf0 \n" - " add A,#-0x50 \n" - " mov A, R1 \n" - " jnc 00048$ \n" - " add A, #0x30 \n" - "00048$: \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00046$ \n" - - //double (18 iters for simplicity) - " mov DPTR, #_mCvtBuf \n" - " clr C \n" - " mov B, #18 \n" - "00045$: \n" - " movx A, @DPTR \n" - " rlc A \n" - " movx @DPTR, A \n" - " inc DPTR \n" - " djnz B, 00045$ \n" - - " djnz R3, 00044$ \n" - - //dabbling is done, print it now using hex routine - " mov DPTR, #(_mCvtBuf + 8) \n" - " mov B, #10 \n" - " clr PSW.5 \n" //it is now for sure in XRAM - " ljmp 00070$ \n" - - //read short pointer from param stack - "00090$: \n" - " mov DPH, @R0 \n" - "00093$: \n" - " dec R0 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " ret \n" - - //read and increment pointer of the type provided by 00091$ (in {DPTR,PSW}) into A. clobber nothing - "00095$: \n" - " jb PSW.5, 00066$ \n" - " jb PSW.1, 00067$ \n" - //XRAM - " movx A, @DPTR \n" - " inc DPTR \n" - " ret \n" - //CODE - "00066$: \n" - " clr A \n" - " movc A, @A+DPTR \n" - " inc DPTR \n" - " ret \n" - //IRAM - "00067$: \n" - " mov DPH, R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " mov R0, DPH \n" - " inc DPL \n" - " ret \n" - - //resolve generic pointer on param stack to an pointer in DPTR and flags in PSW.5 and PSW.1 - //PSW.5 will be 0 and PSW.1 will be 0 for XRAM (PDATA goes here too) - //PSW.5 will be 1 and PSW.1 will be 0 for CODE - //PSW.5 will be 0 and PSW.1 will be 1 for IRAM - "00091$: \n" - " clr PSW.5 \n" - " clr PSW.1 \n" - " mov A, @R0 \n" - " dec R0 \n" - " jz 00090$ \n" //0x00: pointer type: xdata - " xrl A, #0x80 \n" - " jz 00094$ \n" //0x80: pointer type: code - " xrl A, #0xc0 \n" - " jz 00092$ \n" //0x40: pointer type: idata - //pdata - " mov DPH, _XPAGE \n" - " sjmp 00093$ \n" - //idata - "00092$: \n" - " setb PSW.1 \n" - " sjmp 00093$ \n" - //code - "00094$: \n" - " setb PSW.5 \n" - " sjmp 00090$ \n" - - //read the pointer of the type that 00080$ returns (in DPTR) into A. clobber nothing - "00079$: \n" - " jnb PSW.5, 00078$ \n" - " push _R0 \n" - " mov R0, DPL \n" - " mov A, @R0 \n" - " pop _R0 \n" - " ret \n" - "00078$: \n" - " movx A, @DPTR \n" - " ret \n" - - //get pointer to a number, might be pushed or might be pointed to, size might vary. return pointer to number's LOW byte in DPTR - "00080$: \n" - " mov A, R4 \n" - " anl A, #0x01 \n" - " jnz 00083$ \n" - //param is itself on stack - now we care about size, but either way, PSW.5 will be 1 - " setb PSW.5 \n" - " mov B, #0 \n" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00081$ \n" - " anl A, #0x10 \n" - " jz 00082$ \n" - //long long (8 bytes) \n" - " setb B.2 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - //long (4 bytes) - "00082$: \n" - " setb B.1 \n" - " dec R0 \n" - " dec R0 \n" - //int (2 bytes) \n" - "00081$: \n" - " setb B.0 \n" - " dec R0 \n" - " mov DPL, R0 \n" - " dec R0 \n" - " inc B \n" - " ret \n" - //pointer it on stack itself, number is in xram, but we still need to provide the length - "00083$: \n" - " clr PSW.5 \n" //mark as "in xram" - " mov A, R4 \n" - " anl A, #0x18 \n" - " jz 00084$ \n" - " anl A, #0x10 \n" - " jz 00085$ \n" - //long long - " mov B, #8 \n" - " ljmp 00090$ \n" - //long - "00085$: \n" - " mov B, #4 \n" - " ljmp 00090$ \n" - //int - "00084$: \n" - " mov B, #2 \n" - " ljmp 00090$ \n" +void prvPrintFormat(StrFormatOutputFunc formatF, uint16_t formatD, const char __code *fmt, va_list vl) __reentrant __naked { + // formatF is in DPTR + // sp[0..-1] is return addr + // sp[-2..-3] is formatD + // sp[-4..-5] is fmt + // sp[-6] is vl - //swap R3:R1 <-> DPH:DPL - "00086$: \n" - " xch A, DPH \n" - " xch A, R3 \n" - " xch A, DPH \n" - " xch A, DPL \n" - " xch A, R1 \n" - " xch A, DPL \n" - " ret \n" + __asm__( + " push _R7 \n" + " push DPH \n" // push formatF + " push DPL \n" + " mov _R7, sp \n" // save place on stack where we stashed it so we can call it easily + " push _R4 \n" + " push _R3 \n" + " push _R2 \n" + " push _R1 \n" + " push _R0 \n" - /* putchar func - called via call. char is in A, R7 has pointer to stack as needed - can clobber B, CANNOT clobber DPTR - a mess because...8051 - */ - "00060$: \n" - " push DPH \n" - " push DPL \n" - " push _R1 \n" - " push _R0 \n" - " mov _R0, R7 \n" - " mov DPL, @R0 \n" - " dec R0 \n" - " mov DPH, @R0 \n" //DPTR is now func ptr - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " dec R0 \n" - " mov _R1, @R0 \n" - " dec R0 \n" - " mov _R0, @R0 \n" //R1:R0 is now "formatD" - " lcall 00061$ \n" //to set ret addr - " pop _R0 \n" - " pop _R1 \n" - " pop DPL \n" - " pop DPH \n" - " ret \n" - "00061$: \n" - " push DPL \n" - " push DPH \n" - " mov DPL, _R0 \n" - " mov DPH, _R1 \n" - " ret \n" - - "00099$: \n" - " .ascii \"01234567\" \n" - " .ascii \"89ABCDEF\" \n" - " .ascii \"01234567\" \n" - " .ascii \"89abcdef\" \n" - ); - (void)fmt; - (void)vl; - (void)formatF; - (void)formatD; + " mov A, #-12 \n" + " add A, sp \n" + " mov R0, A \n" + // R0 now points to pushed params, for large values, we see high bytes first + // to get next byte, we need to DECEREMENT R0 + + " mov DPH, @R0 \n" + " dec R0 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " mov _R0, @R0 \n" + " dec R0 \n" + + // now format string is in DPTR, and R0 points to the top byte of whatever was in the first param + + // main loop: get a byte of the format string + "00001$: \n" + " clr A \n" + " movc A, @A + DPTR \n" + " inc DPTR \n" + // if zero, we're done + " jz 00098$ \n" + // if not '%', print it + " cjne A, #'%', 00097$ \n" + + // we got a percent sign - init state for format processing + " mov R4, #0 \n" // bit flags: + // 0x01 = '*' = pointer provided instead of value (integers only) + // 0x02 = '0' = zero-pad (for numbers only) + // 0x04 = have pad-to length + // 0x08 = long + // 0x10 = long long + // 0x20 = signed print requested. also: need to print a negative (used to reuse hex printing for decimal once converted to bcd) + " mov R2, #0 \n" // padLen + + // loop for format string ingestion + "00002$: \n" + " clr A \n" + " movc A, @A + DPTR \n" + " inc DPTR \n" + // if zero, we're done + " jz 00098$ \n" + // check for percent sign + " cjne A, #'%', 00003$ \n" + // fallthrough to print it and go read next non-format byte + // print a char in A, go read next format byte + "00097$: \n" + " lcall 00060$ \n" + " sjmp 00001$ \n" + + // exit label - placed for easy jumping to + "00098$: \n" + " pop _R0 \n" + " pop _R1 \n" + " pop _R2 \n" + " pop _R3 \n" + " pop _R4 \n" + " pop DPL \n" + " pop DPH \n" + " pop _R7 \n" + " ret \n" + + // continue to process format string - handle %c + "00003$: \n" + " cjne A, #'c', 00004$ \n" + " dec R0 \n" // param is pushed as int (16 bits) + " mov A, @R0 \n" + " dec R0 \n" + " sjmp 00097$ \n" // print and go read next non-format byte + + // continue to process format string - handle %m + "00004$: \n" + " mov R3, A \n" + " orl A, #0x20 \n" + " cjne A, #'m', 00008$ \n" + + // sort out which hexch charset to use + " mov A, R3 \n" + " anl A, #0x20 \n" + " rr A \n" + " mov R1, A \n" + + // go, do + " push DPH \n" + " push DPL \n" + " lcall 00090$ \n" // read the short (__xdata) pointer - >DPTR + " mov R4, #8 \n" // byteSel + "00005$: \n" + " push DPH \n" + " push DPL \n" + " mov A, R4 \n" + " dec A \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0 \n" + " mov DPH, A \n" + " movx A, @DPTR \n" + " mov R2, A \n" + " swap A \n" + " mov R3, #2 \n" + "00006$: \n" + " anl A, #0x0f \n" + " add A, R1 \n" + " mov DPTR, #00099$ \n" + " movc A, @A + DPTR \n" + " lcall 00060$ \n" + " mov A, R2 \n" + " djnz R3, 00006$ \n" + " pop DPL \n" + " pop DPH \n" + " djnz R4, 00007$ \n" + // done with mac addr + + "00055$: \n" + " pop DPL \n" + " pop DPH \n" + " sjmp 00001$ \n" + // print colon and contimue mac addr printing + "00007$: \n" + " mov A, #':' \n" + " lcall 00060$ \n" + " sjmp 00005$ \n" + + // continue to process format string - handle '*' + "00008$: \n" + " mov A, R3 \n" + " cjne A, #'*', 00009$ \n" + " cjne R2, #0, 00097$ \n" // only valid when no length/padding has been specified yet, else invalid specifier + " mov A, #0x01 \n" //"pointer mode" + "00010$: \n" + " orl A, R4 \n" + " mov R4, A \n" + " sjmp 00002$ \n" // get next format specifier now + + // continue to process format string - handle '0' + "00009$: \n" + " cjne A, #'0', 00011$ \n" + " cjne R2, #0, 00011$ \n" // setting "zero pad" is only valid when pad length is zero + " mov A, #0x06 \n" //"have pad length" | "zero-pad" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle '1'...'9' + "00011$: \n" + " mov R3, A \n" + " add A, #-'0' \n" + " jnc 00012$ \n" // now 0..9 are valid + " add A, #-10 \n" + " jc 00012$ \n" + " add A, #10 \n" // get it back into 1..9 range + " mov R3, A \n" + " mov A, #10 \n" + " mov B, R2 \n" + " mul AB \n" + " add A, R3 \n" + " mov R2, A \n" + " mov A, #0x04 \n" //"have pad length" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle 'l' + "00012$: \n" + " cjne R3, #'l', 00014$ \n" + " mov A, R4 \n" + " anl A, #0x08 \n" + " jz 00013$ \n" // no "long" yet? set that + // have long - set long log + " mov A, #0x10 \n" //"long long" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + // first 'l' - set long + "00013$: \n" + " mov A, #0x08 \n" //"long" + " sjmp 00010$ \n" // orr A into R4, get next format specifier now + + // continue to process format string - handle 's' + "00014$: \n" + " cjne R3, #'s', 00025$ \n" + " mov A, R4 \n" + " anl A, #0x08 \n" + " push DPH \n" + " push DPL \n" + " jnz 00015$ \n" + " lcall 00091$ \n" // get and resolve generic pointer into DPTR + " sjmp 00016$ \n" + "00015$: \n" // get short pointer into DPTR, record that it is to XRAM + " clr PSW.5 \n" + " clr PSW.1 \n" + " lcall 00090$ \n" + "00016$: \n" // pointer to string now in DPTR + // we have the string pointer in {DPTR,PSW}, let's see if we have padding to do + " mov A, R4 \n" + " anl A, #0x04 \n" + " jnz 00018$ \n" + // print string with no length restrictions + "00017$: \n" + " lcall 00095$ \n" + " jz 00055$ \n" + " lcall 00060$ \n" + " sjmp 00017$ \n" + + // print string with length restrictions and/or padding + "00018$: \n" + " cjne R2, #0, 00019$ \n" // verify reqested len was not zero + " sjmp 00055$ \n" + + "00019$: \n" + " lcall 00095$ \n" + " jz 00020$ \n" + " lcall 00060$ \n" + " djnz R2, 00019$ \n" + // we get here if we ran out of allowable bytes - we're done then + " ljmp 00055$ \n" + + // just a trampoline for range issues + "00035$: \n" + " ljmp 00036$ \n" + + // we need to pad with spaces + "00020$: \n" + " mov A, #' ' \n" + " lcall 00060$ \n" + " djnz R2, 00020$ \n" + " ljmp 00055$ \n" + + // continue to process format string - handle 'x'/'X' + "00025$: \n" + " mov A, R3 \n" + " orl A, #0x20 \n" + " cjne A, #'x', 00035$ \n" + " push DPH \n" + " push DPL \n" + " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B + // save it + + "00070$: \n" + " push DPH \n" + " push DPL \n" + + // sort out how long it would be if printed, first get a pointer to the highest + " mov A, B \n" + " rl A \n" + " mov R1, A \n" + " rr A \n" + " add A, #0xff \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0x00 \n" + " mov DPH, A \n" + "00026$: \n" + " lcall 00079$ \n" + " anl A, #0xf0 \n" + " jnz 00028$ \n" + " dec R1 \n" + " lcall 00079$ \n" + " jnz 00028$ \n" + " dec R1 \n" + // dec DPTR + " dec DPL \n" + " mov A, DPL \n" + " cjne A, #0xff, 00027$ \n" + " dec DPH \n" + "00027$: \n" + " djnz B, 00026$ \n" + + // we now know how many digits the number is (in R1), except that it has "0" if the number if zero, we cannot have that + "00028$: \n" + " cjne R1, #0, 00029$ \n" + " inc R1 \n" + "00029$: \n" // we now finally have the full length of the digits + + // if the number is negative (happens when we're printing decimals) + // the length of it is one more, also in case of zero-padding, we need to print the minus sign here now + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00051$ \n" + " inc R1 \n" // the length is one more + " mov A, R4 \n" + " anl A, #02 \n" // if zero-padding, the negative comes now + " jz 00051$ \n" + " mov A, #'-' \n" + " lcall 00060$ \n" + "00051$: \n" + + // sort out if we need padding at all and if there is space + " mov A, R4 \n" + " anl A, #0x04 \n" + " jz 00031$ \n" // no padding requested + // padding was requested len is in R2 + " mov A, R2 \n" + " clr C \n" + " subb A, R1 \n" + " jc 00031$ \n" // pad-to len < number_len -> no padding needed + " jz 00031$ \n" // pad-to len == number_len -> no padding needed + " mov R2, A \n" + + // sort out which character to use -> DPL + " mov A, R4 \n" // fancy way to create space/zero as needed + " anl A, #0x02 \n" + " swap A \n" + " rr A \n" + " add A, #0x20 \n" + " mov DPL, A \n" + + // pad! + "00030$: \n" + " mov A, DPL \n" + " lcall 00060$ \n" + " djnz R2, 00030$ \n" + "00031$: \n" + + // if the number is negative (happens when we're printing decimals) + // we made the length of it is one more, which we need to undo + // also in case of space-padding, we need to print the minus sign here now + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00052$ \n" + " dec R1 \n" // the length is one less than we had increased it to + " mov A, R4 \n" + " anl A, #02 \n" // if space-padding, the negative comes now + " jnz 00052$ \n" + " mov A, #'-' \n" + " lcall 00060$ \n" + "00052$: \n" + + // time to print the number itself + // sort out which hexch charset to use -> R2 + " mov A, R3 \n" + " anl A, #0x20 \n" + " rr A \n" + " mov R2, A \n" + // re-get the number pointer + " pop DPL \n" + " pop DPH \n" + // currently DPTR points to the number low byte, R1 is now many digits we expect to print, R2 is the charset selection, R4 and R3 are free + // let's calculate how many bytes we expect to process -> R4 + " mov A, R1 \n" + " inc A \n" + " clr C \n" + " rrc A \n" + " mov R4, A \n" + // let's repoint DPTR to the first byte we'll print in (remember we print 2 digits per byte) + " dec A \n" + " add A, DPL \n" + " mov DPL, A \n" + " mov A, DPH \n" + " addc A, #0x00 \n" + " mov DPH, A \n" + + // decide if we need to print just a nibble of the high byte or the whole thing. Free up R1 + " mov A, R1 \n" + " anl A, #0x01 \n" + " jz 00032$ \n" + + // we're printing just the low nibble of the first byte - set up for it + " lcall 00079$ \n" + " mov R1, #1 \n" + " sjmp 00033$ \n" + + // print loop + "00032$: \n" + " lcall 00079$ \n" + " mov R1, #2 \n" + " mov R3, A \n" + " swap A \n" + "00033$: \n" + " anl A, #0x0f \n" + " add A, R2 \n" + " push DPH \n" + " push DPL \n" + " mov DPTR, #00099$ \n" + " movc A, @A + DPTR \n" + " pop DPL \n" + " pop DPH \n" + " lcall 00060$ \n" + " mov A, R3 \n" + " djnz R1, 00033$ \n" + + // dec DPTR + " dec DPL \n" + " mov A, DPL \n" + " cjne A, #0xff, 00034$ \n" + " dec DPH \n" + "00034$: \n" + " djnz R4, 00032$ \n" + + // done! + " ljmp 00055$ \n" + + // continue to process format string - handle 'd' + "00036$: \n" + " cjne R3, #'d', 00037$ \n" + " mov A, #0x20 \n" + " orl A, R4 \n" + " mov R4, A \n" + " sjmp 00040$ \n" + + // continue to process format string - handle 'u' + "00037$: \n" + " cjne R3, #'u', 00038$ \n" + " sjmp 00040$ \n" + + // no more format strings exist that we can handle - bail + "00038$: \n" + " ljmp 00001$ \n" + + // handle decimal printing + "00040$: \n" + " push DPH \n" + " push DPL \n" + " lcall 00080$ \n" // get pointer to the number in DPTR, length in bytes in B + " push B \n" + + // copy the number to the double-dabble storage at proper offset (0 for u64, 4 for u32, 6 for u16) + // we do this so that the dabble area always starts at the same place... + " mov A, #8 \n" + " clr C \n" + " subb A, B \n" + " add A, #_mCvtBuf \n" + " mov R1, A \n" + " clr A \n" + " addc A, #(_mCvtBuf >> 8) \n" + " mov R3, A \n" + "00041$: \n" + " lcall 00079$ \n" + " inc DPTR \n" + " lcall 00086$ \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " lcall 00086$ \n" + " djnz B, 00041$ \n" + // leave DPTR pointing to dabble storage, past the number + " lcall 00086$ \n" + + // we now have the top byte of the number in A, good time to check for negatives, if needed + " mov B, A \n" + " mov A, R4 \n" + " anl A, #0x20 \n" + " jz 00050$ \n" // unsigned printing requested + " mov A, B \n" + " anl A, #0x80 \n" + " jnz 00043$ \n" // is negative - we need to invert, 0x20 bit in R1 stays + // positive - 0x20 bit in R1 needs to go + " mov A, R4 \n" + " anl A, #~0x20 \n" + " mov R4, A \n" + " sjmp 00050$ \n" + + // we need to negate the number + // but first we need a pointer to it, and its size + "00043$: \n" + " pop B \n" + " push B \n" + " mov A, #8 \n" + " clr C \n" + " subb A, B \n" + " add A, #_mCvtBuf \n" + " mov DPL, A \n" + " clr A \n" + " addc A, #(_mCvtBuf >> 8) \n" + " mov DPH, A \n" + + // ok, now we are ready to negate it + " clr C \n" + "00049$: \n" + " movx A, @DPTR \n" + " mov R1, A \n" + " clr A \n" + " subb A, R1 \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00049$ \n" + + // zero out the rest of the storage (10 bytes) + "00050$: \n" + " mov B, #10 \n" + " clr A \n" + "00042$: \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00042$ \n" + + // calculate number of dabble steps + " pop A \n" + " swap A \n" + " rr A \n" + " mov R3, A \n" + + // do the thing + "00044$: \n" + + // dabble (10 iters for simplicity) + " mov DPTR, #(_mCvtBuf + 8) \n" + " mov B, #10 \n" + "00046$: \n" + " movx A, @DPTR \n" + " mov R1, A \n" + " anl A, #0x0f \n" + " add A,#-0x05 \n" + " mov A, R1 \n" + " jnc 00047$ \n" + " add A, #0x03 \n" + "00047$: \n" + " mov R1, A \n" + " anl A, #0xf0 \n" + " add A,#-0x50 \n" + " mov A, R1 \n" + " jnc 00048$ \n" + " add A, #0x30 \n" + "00048$: \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00046$ \n" + + // double (18 iters for simplicity) + " mov DPTR, #_mCvtBuf \n" + " clr C \n" + " mov B, #18 \n" + "00045$: \n" + " movx A, @DPTR \n" + " rlc A \n" + " movx @DPTR, A \n" + " inc DPTR \n" + " djnz B, 00045$ \n" + + " djnz R3, 00044$ \n" + + // dabbling is done, print it now using hex routine + " mov DPTR, #(_mCvtBuf + 8) \n" + " mov B, #10 \n" + " clr PSW.5 \n" // it is now for sure in XRAM + " ljmp 00070$ \n" + + // read short pointer from param stack + "00090$: \n" + " mov DPH, @R0 \n" + "00093$: \n" + " dec R0 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " ret \n" + + // read and increment pointer of the type provided by 00091$ (in {DPTR,PSW}) into A. clobber nothing + "00095$: \n" + " jb PSW.5, 00066$ \n" + " jb PSW.1, 00067$ \n" + // XRAM + " movx A, @DPTR \n" + " inc DPTR \n" + " ret \n" + // CODE + "00066$: \n" + " clr A \n" + " movc A, @A+DPTR \n" + " inc DPTR \n" + " ret \n" + // IRAM + "00067$: \n" + " mov DPH, R0 \n" + " mov R0, DPL \n" + " mov A, @R0 \n" + " mov R0, DPH \n" + " inc DPL \n" + " ret \n" + + // resolve generic pointer on param stack to an pointer in DPTR and flags in PSW.5 and PSW.1 + // PSW.5 will be 0 and PSW.1 will be 0 for XRAM (PDATA goes here too) + // PSW.5 will be 1 and PSW.1 will be 0 for CODE + // PSW.5 will be 0 and PSW.1 will be 1 for IRAM + "00091$: \n" + " clr PSW.5 \n" + " clr PSW.1 \n" + " mov A, @R0 \n" + " dec R0 \n" + " jz 00090$ \n" // 0x00: pointer type: xdata + " xrl A, #0x80 \n" + " jz 00094$ \n" // 0x80: pointer type: code + " xrl A, #0xc0 \n" + " jz 00092$ \n" // 0x40: pointer type: idata + // pdata + " mov DPH, _XPAGE \n" + " sjmp 00093$ \n" + // idata + "00092$: \n" + " setb PSW.1 \n" + " sjmp 00093$ \n" + // code + "00094$: \n" + " setb PSW.5 \n" + " sjmp 00090$ \n" + + // read the pointer of the type that 00080$ returns (in DPTR) into A. clobber nothing + "00079$: \n" + " jnb PSW.5, 00078$ \n" + " push _R0 \n" + " mov R0, DPL \n" + " mov A, @R0 \n" + " pop _R0 \n" + " ret \n" + "00078$: \n" + " movx A, @DPTR \n" + " ret \n" + + // get pointer to a number, might be pushed or might be pointed to, size might vary. return pointer to number's LOW byte in DPTR + "00080$: \n" + " mov A, R4 \n" + " anl A, #0x01 \n" + " jnz 00083$ \n" + // param is itself on stack - now we care about size, but either way, PSW.5 will be 1 + " setb PSW.5 \n" + " mov B, #0 \n" + " mov A, R4 \n" + " anl A, #0x18 \n" + " jz 00081$ \n" + " anl A, #0x10 \n" + " jz 00082$ \n" + // long long (8 bytes) \n" + " setb B.2 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + // long (4 bytes) + "00082$: \n" + " setb B.1 \n" + " dec R0 \n" + " dec R0 \n" + // int (2 bytes) \n" + "00081$: \n" + " setb B.0 \n" + " dec R0 \n" + " mov DPL, R0 \n" + " dec R0 \n" + " inc B \n" + " ret \n" + // pointer it on stack itself, number is in xram, but we still need to provide the length + "00083$: \n" + " clr PSW.5 \n" // mark as "in xram" + " mov A, R4 \n" + " anl A, #0x18 \n" + " jz 00084$ \n" + " anl A, #0x10 \n" + " jz 00085$ \n" + // long long + " mov B, #8 \n" + " ljmp 00090$ \n" + // long + "00085$: \n" + " mov B, #4 \n" + " ljmp 00090$ \n" + // int + "00084$: \n" + " mov B, #2 \n" + " ljmp 00090$ \n" + + // swap R3:R1 <-> DPH:DPL + "00086$: \n" + " xch A, DPH \n" + " xch A, R3 \n" + " xch A, DPH \n" + " xch A, DPL \n" + " xch A, R1 \n" + " xch A, DPL \n" + " ret \n" + + /* putchar func + called via call. char is in A, R7 has pointer to stack as needed + can clobber B, CANNOT clobber DPTR + a mess because...8051 + */ + "00060$: \n" + " push DPH \n" + " push DPL \n" + " push _R1 \n" + " push _R0 \n" + " mov _R0, R7 \n" + " mov DPL, @R0 \n" + " dec R0 \n" + " mov DPH, @R0 \n" // DPTR is now func ptr + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " dec R0 \n" + " mov _R1, @R0 \n" + " dec R0 \n" + " mov _R0, @R0 \n" // R1:R0 is now "formatD" + " lcall 00061$ \n" // to set ret addr + " pop _R0 \n" + " pop _R1 \n" + " pop DPL \n" + " pop DPH \n" + " ret \n" + "00061$: \n" + " push DPL \n" + " push DPH \n" + " mov DPL, _R0 \n" + " mov DPH, _R1 \n" + " ret \n" + + "00099$: \n" + " .ascii \"01234567\" \n" + " .ascii \"89ABCDEF\" \n" + " .ascii \"01234567\" \n" + " .ascii \"89abcdef\" \n"); + (void)fmt; + (void)vl; + (void)formatF; + (void)formatD; } #pragma callee_saves prPrvPutchar -static void prPrvPutchar(uint32_t data) __reentrant -{ - char ch = data >> 24; - - if (ch == '\n') - dbgUartByte('\r'); - dbgUartByte(ch); +static void prPrvPutchar(uint32_t data) __reentrant { + char ch = data >> 24; + if (ch == '\n') + uartTx('\r'); + uartTx(ch); +} +#pragma callee_saves epdPutchar +static void epdPutchar(uint32_t data) __reentrant { + char ch = data >> 24; + writeCharEPD(ch); } -void pr(const char __code *fmt, ...) __reentrant -{ - va_list vl; - - va_start(vl, fmt); - dbgUartOn(); - prvPrintFormat(prPrvPutchar, 0, fmt, vl); - dbgUartOff(); - va_end(vl); +void pr(const char __code *fmt, ...) __reentrant { + va_list vl; + va_start(vl, fmt); + prvPrintFormat(prPrvPutchar, 0, fmt, vl); + va_end(vl); +} + +void epdpr(const char __code *fmt, ...) __reentrant { + va_list vl; + va_start(vl, fmt); + prvPrintFormat(epdPutchar, 0, fmt, vl); + va_end(vl); } #pragma callee_saves prPrvPutS -static void prPrvPutS(uint32_t data) __reentrant -{ - char __xdata * __idata *strPP = (char __xdata * __idata *)data; - char ch = data >> 24; - - *(*strPP)++ = ch; +static void prPrvPutS(uint32_t data) __reentrant { + char __xdata *__idata *strPP = (char __xdata *__idata *)data; + char ch = data >> 24; + + *(*strPP)++ = ch; } -void spr(char __xdata* out, const char __code *fmt, ...) __reentrant -{ - char __xdata* outStart = out; - - va_list vl; - - va_start(vl, fmt); - prvPrintFormat(prPrvPutS, (uint16_t)&out, fmt, vl); - va_end(vl); - - *out = 0; -} +void spr(char __xdata *out, const char __code *fmt, ...) __reentrant { + char __xdata *outStart = out; + va_list vl; + + va_start(vl, fmt); + prvPrintFormat(prPrvPutS, (uint16_t)&out, fmt, vl); + va_end(vl); + + *out = 0; +} diff --git a/tag_fw/drawing.c b/tag_fw/drawing.c index ce97dead..641199a1 100644 --- a/tag_fw/drawing.c +++ b/tag_fw/drawing.c @@ -1,13 +1,10 @@ #include -// #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(); } diff --git a/tag_fw/drawing.h b/tag_fw/drawing.h index defc621f..4e216e9e 100644 --- a/tag_fw/drawing.h +++ b/tag_fw/drawing.h @@ -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 diff --git a/tag_fw/eeprom.c b/tag_fw/eeprom.c index 7044ed0e..ab01bbc7 100644 --- a/tag_fw/eeprom.c +++ b/tag_fw/eeprom.c @@ -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"); diff --git a/tag_fw/epd.c b/tag_fw/epd.c new file mode 100644 index 00000000..a5baff0a --- /dev/null +++ b/tag_fw/epd.c @@ -0,0 +1,679 @@ +#include "epd.h" + +#include +#include + +#include "asmUtil.h" +#include "barcode.h" +#include "board.h" +#include "cpu.h" +#include "font.h" +#include "lut.h" +#include "printf.h" +#include "screen.h" +#include "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); +} diff --git a/tag_fw/epd.h b/tag_fw/epd.h new file mode 100644 index 00000000..94de8eb2 --- /dev/null +++ b/tag_fw/epd.h @@ -0,0 +1,67 @@ +#ifndef _JSCREEN_H_ +#define _JSCREEN_H_ + +#include +#include + +#define epdSend spiTXByte +#define EPD_DIRECTION_X false +#define EPD_DIRECTION_Y true +#define EPD_SIZE_SINGLE false +#define EPD_SIZE_DOUBLE true +#define EPD_COLOR_RED true +#define EPD_COLOR_BLACK false +#define EPD_LOAD_CUSTOM_LUT true +#define EPD_LOAD_OTP_LUT false +#define EPD_MODE_NORMAL 0x00 +#define EPD_MODE_INVERT 0x08 +#define EPD_MODE_IGNORE 0x04 + +#define 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 \ No newline at end of file diff --git a/tag_fw/font.h b/tag_fw/font.h new file mode 100644 index 00000000..3dece553 --- /dev/null +++ b/tag_fw/font.h @@ -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 +}; \ No newline at end of file diff --git a/tag_fw/fw154.bin b/tag_fw/fw154.bin deleted file mode 100644 index 4aaa1593..00000000 Binary files a/tag_fw/fw154.bin and /dev/null differ diff --git a/tag_fw/fw29.bin b/tag_fw/fw29.bin deleted file mode 100644 index 60dda2ec..00000000 Binary files a/tag_fw/fw29.bin and /dev/null differ diff --git a/tag_fw/fw42.bin b/tag_fw/fw42.bin deleted file mode 100644 index dcf0d475..00000000 Binary files a/tag_fw/fw42.bin and /dev/null differ diff --git a/tag_fw/lut.h b/tag_fw/lut.h new file mode 100644 index 00000000..d164767a --- /dev/null +++ b/tag_fw/lut.h @@ -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, +}; + + diff --git a/tag_fw/main.c b/tag_fw/main.c index 7c8ecb45..35a967fc 100644 --- a/tag_fw/main.c +++ b/tag_fw/main.c @@ -5,33 +5,131 @@ #include #include -#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(); } diff --git a/tag_fw/powermgt.c b/tag_fw/powermgt.c new file mode 100644 index 00000000..df441448 --- /dev/null +++ b/tag_fw/powermgt.c @@ -0,0 +1,92 @@ +#include "powermgt.h" + +#include +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/tag_fw/powermgt.h b/tag_fw/powermgt.h new file mode 100644 index 00000000..7f641671 --- /dev/null +++ b/tag_fw/powermgt.h @@ -0,0 +1,24 @@ +#ifndef _POWERMGT_H_ +#define _POWERMGT_H_ +#include + +// 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 \ No newline at end of file diff --git a/tag_fw/printf.h b/tag_fw/printf.h index b04e0590..8ca2eea5 100644 --- a/tag_fw/printf.h +++ b/tag_fw/printf.h @@ -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; diff --git a/tag_fw/proto.h b/tag_fw/proto.h index 2dd14159..e71224fe 100644 --- a/tag_fw/proto.h +++ b/tag_fw/proto.h @@ -1,47 +1,8 @@ #ifndef _PROTO_H_ #define _PROTO_H_ - +#define __packed #include -/* - 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 \ No newline at end of file diff --git a/tag_fw/settings.h b/tag_fw/settings.h new file mode 100644 index 00000000..763a26ef --- /dev/null +++ b/tag_fw/settings.h @@ -0,0 +1,12 @@ +#ifndef SYNCED_H +#define SYNCED_H + +#include + +#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 \ No newline at end of file diff --git a/tag_fw/soc/radioCommon.h b/tag_fw/soc/radioCommon.h index 61c4f8f5..99937234 100644 --- a/tag_fw/soc/radioCommon.h +++ b/tag_fw/soc/radioCommon.h @@ -5,6 +5,10 @@ #include +//radio cfg +#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11 +#define RADIO_NUM_CHANNELS (15) + #define RADIO_MAX_PACKET_LEN (125) //useful payload, not including the crc @@ -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 diff --git a/tag_fw/soc/zbs243/spi.c b/tag_fw/soc/zbs243/spi.c index c4088d4b..e2a8f7f6 100644 --- a/tag_fw/soc/zbs243/spi.c +++ b/tag_fw/soc/zbs243/spi.c @@ -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; } \ No newline at end of file diff --git a/tag_fw/soc/zbs243/spi.h b/tag_fw/soc/zbs243/spi.h index b869e4a9..b2aeb4aa 100644 --- a/tag_fw/soc/zbs243/spi.h +++ b/tag_fw/soc/zbs243/spi.h @@ -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 diff --git a/tag_fw/soc/zbs243/temperature.c b/tag_fw/soc/zbs243/temperature.c index f51b492f..11b20544 100644 --- a/tag_fw/soc/zbs243/temperature.c +++ b/tag_fw/soc/zbs243/temperature.c @@ -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]; diff --git a/tag_fw/soc/zbs243/timer.h b/tag_fw/soc/zbs243/timer.h index bce2b700..26aa216b 100644 --- a/tag_fw/soc/zbs243/timer.h +++ b/tag_fw/soc/zbs243/timer.h @@ -4,7 +4,7 @@ #include #define TIMER_TICKS_PER_SECOND (16000000 / 12) //overflows every 53 minutes - +#define TIMER_TICKS_PER_MS 1333UL //this is a requirement by SDCC. is this prototype is missing when compiling main(), we get no irq handler void T0_ISR(void) __interrupt (1); diff --git a/tag_fw/soc/zbs243/uart.c b/tag_fw/soc/zbs243/uart.c index 3bf25bc8..5b0c8199 100644 --- a/tag_fw/soc/zbs243/uart.c +++ b/tag_fw/soc/zbs243/uart.c @@ -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; } - - diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index 56e23fd1..f0aa3d85 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -7,123 +7,22 @@ #include #include -#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(); } \ No newline at end of file diff --git a/tag_fw/syncedproto.h b/tag_fw/syncedproto.h index 718babfb..583296dc 100644 --- a/tag_fw/syncedproto.h +++ b/tag_fw/syncedproto.h @@ -3,8 +3,18 @@ #include -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 \ No newline at end of file diff --git a/tag_fw/userinterface.c b/tag_fw/userinterface.c new file mode 100644 index 00000000..1b55306b --- /dev/null +++ b/tag_fw/userinterface.c @@ -0,0 +1,221 @@ + + +#include "userinterface.h" + +#include +#include + +#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(); +} diff --git a/tag_fw/userinterface.h b/tag_fw/userinterface.h new file mode 100644 index 00000000..7b697e72 --- /dev/null +++ b/tag_fw/userinterface.h @@ -0,0 +1,11 @@ +#ifndef _UI_H_ +#define _UI_H_ +#include + +void showSplashScreen(); +void showApplyUpdate(); +void showScanningWindow(); +void addScanResult(uint8_t channel, uint8_t lqi); +void showAPFound(); +void showNoAP(); +#endif \ No newline at end of file