preparations for UI

This commit is contained in:
Jelmer
2023-01-28 21:27:33 +01:00
parent 3ad39ecd5d
commit 7bb2c6e0e5
21 changed files with 1108 additions and 1897 deletions

View File

@@ -3,8 +3,8 @@ 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
all: #make sure it is the first target
@@ -18,21 +18,7 @@ FLAGS += -Icpu/$(CPU)
SOURCES += cpu/$(CPU)/cpu.c
SOURCES += board/$(BUILD)/board.c
SOURCES += board/$(BUILD)/screen.c
ifeq ($(BARCODE),barcode)
FLAGS += -DBARCODE
SOURCES += barcode.c
else ifeq ($(BARCODE),datamatrix)
# FLAGS += -DDATAMATRIX
# SOURCES += datamatrix.c
#i might release this later, but for now, just use barcodes :P
FLAGS += -DBARCODE
SOURCES += barcode.c
else
SOURCES += $(warning "no barcode type set")
endif
#SOURCES += board/$(BUILD)/screen.c
EEPROMDRV ?= eeprom.c

View File

@@ -1,101 +0,0 @@
#include <stdbool.h>
#include "barcode.h"
#include "asmUtil.h"
//code128 generator (c) 2021 Dmitry Grinberg https://dmitry.gr
//non-commercial use only, contact licensing@dmitry.gr for other options
#pragma nogcse
static const uint16_t __code mCode128[] = {
0b00110011011, 0b00110110011, 0b01100110011, 0b00011001001, 0b00110001001, 0b00110010001, 0b00010011001, 0b00100011001,
0b00100110001, 0b00010010011, 0b00100010011, 0b00100100011, 0b00111001101, 0b00111011001, 0b01110011001, 0b00110011101,
0b00110111001, 0b01100111001, 0b01001110011, 0b00111010011, 0b01110010011, 0b00100111011, 0b00101110011, 0b01110110111,
0b00110010111, 0b00110100111, 0b01100100111, 0b00100110111, 0b00101100111, 0b01001100111, 0b00011011011, 0b01100011011,
0b01101100011, 0b00011000101, 0b00011010001, 0b01100010001, 0b00010001101, 0b00010110001, 0b01000110001, 0b00010001011,
0b00010100011, 0b01000100011, 0b00011101101, 0b01110001101, 0b01110110001, 0b00011011101, 0b01100011101, 0b01101110001,
0b01101110111, 0b01110001011, 0b01110100011, 0b00010111011, 0b01000111011, 0b01110111011, 0b00011010111, 0b01100010111,
0b01101000111, 0b00010110111, 0b01000110111, 0b01011000111, 0b01011110111, 0b01000010011, 0b01010001111, 0b00001100101,
0b00110000101, 0b00001101001, 0b01100001001, 0b00110100001, 0b01100100001, 0b00001001101, 0b00100001101, 0b00001011001,
0b01000011001, 0b00101100001, 0b01001100001, 0b01001000011, 0b00001010011, 0b01011101111, 0b00101000011, 0b01011110001,
0b00111100101, 0b00111101001, 0b01111001001, 0b00100111101, 0b00101111001, 0b01001111001, 0b00100101111, 0b00101001111,
0b01001001111, 0b01111011011, 0b01101111011, 0b01101101111, 0b00011110101, 0b01111000101, 0b01111010001, 0b00010111101,
0b01000111101, 0b00010101111, 0b01000101111, 0b01111011101, 0b01110111101, 0b01111010111, 0b01110101111
};
#define CODE128_START_B (0b00001001011)
#define CODE128_STOP (0b1101011100011)
#define CODE128_IDX_START_A (103)
#define CODE128_IDX_START_B (104)
#define CODE128_IDX_START_C (105)
#define CODE128_IDX_CODE_STOP (106)
enum BarCodeState {
BarCodeInit,
BarCodeEmittingChar,
BarCodeEmittingChecksum,
BarCodeEmittingStop,
BarCodeDone,
};
__bit barcodeIsDone(struct BarcodeInfo __xdata *bci)
{
return bci->state == BarCodeDone;
}
__bit barcodeNextBar(struct BarcodeInfo __xdata *bci)
{
uint8_t t;
__bit ret;
if (!bci->barsLeft) switch (bci->state) {
case BarCodeInit:
bci->curBars = CODE128_START_B;
bci->barsLeft = 11;
bci->state = BarCodeEmittingChar;
bci->csum = CODE128_IDX_START_B;
break;
case BarCodeEmittingChar:
t = charsPrvDerefAndIncGenericPtr(&bci->str);
if (t) {
t -= 0x20;
if (t >= 0x60)
t = '?' - 0x20;
bci->csum = mathPrvMod16x8(mathPrvMul8x8(++bci->csumMul, t) + bci->csum, 103);
}
else {
bci->state = BarCodeEmittingChecksum;
t = bci->csum;
}
bci->curBars = mCode128[t];
bci->barsLeft = 11;
break;
case BarCodeEmittingChecksum:
bci->state = BarCodeEmittingStop;
bci->curBars = CODE128_STOP;
bci->barsLeft = 13;
break;
case BarCodeEmittingStop:
bci->state = BarCodeDone;
//fallthrough
case BarCodeDone:
default:
return false;
}
ret = bci->curBars & 1;
bci->curBars >>= 1;
bci->barsLeft--;
return ret;
}

View File

@@ -1,29 +0,0 @@
#ifndef _BARCODE_H_
#define _BARCODE_H_
#include <stdint.h>
//code128 generator (c) 2021 Dmitry Grinberg https://dmitry.gr
//non-commercial use only, contact licensing@dmitry.gr for other options
struct BarcodeInfo { //zero-init this except the string ptr
const char *str;
uint16_t curBars;
uint8_t barsLeft;
uint8_t state;
uint8_t csum;
uint8_t csumMul;
};
#define barcodeWidth(nChars) (11 * (nChars) + 11 /*start */+ 11 /*check sum */ + 13 /* stop */)
#pragma callee_saves barcodeIsDone
__bit barcodeIsDone(struct BarcodeInfo __xdata *bci);
#pragma callee_saves barcodeNextBar
__bit barcodeNextBar(struct BarcodeInfo __xdata *bci);
#endif

View File

@@ -10,6 +10,8 @@
#include "adc.h"
#include "i2c.h"
//extern uint8_t __xdata* tempBuffer;
uint8_t __xdata tempBuffer[320];
void powerPortsDownForSleep(void)
{
@@ -148,12 +150,12 @@ void selfUpdate(void)
uint32_t updaterInfo = prvUpdateApplierGet();
uint8_t __code *src = (uint8_t __code*)updaterInfo;
uint8_t i, len = updaterInfo >> 16;
uint8_t __xdata *dst = mScreenRow;
uint8_t __xdata *dst = tempBuffer;
for (i = len; i ; i--)
*dst++ = *src++;
if (!flashWrite(0xfc00, mScreenRow, len, true))
if (!flashWrite(0xfc00, tempBuffer, len, true))
pr("failed to write updater\n");
IEN_EA = 0; //ints off

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,12 +2,13 @@
// #include "datamatrix.h"
#include "adc.h"
#include "asmUtil.h"
#include "barcode.h"
// #include "barcode.h"
#include "board.h"
#include "chars.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 +58,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 +258,7 @@ static void drawPrvDecodeImageOnce(void) {
if (emit) {
emit = false;
screenByteTx(txPrev | val);
ByteDecode(txPrev | val);
nBytesOut++;
txPrev = 0;
} else {
@@ -260,7 +271,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 +283,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 +299,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,13 +317,25 @@ 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;
uint8_t __xdata iter;
@@ -322,105 +345,20 @@ void drawImageAtAddress(uint32_t addr) {
return;
drawPrvLoadAndMapClut(clutAddr);
screenTxStart(false);
for (iter = 0; iter < SCREEN_DATA_PASSES; iter++) {
pr(".");
drawPrvDecodeImageOnce();
screenEndPass();
}
//screenTxStart(false);
epdSetup();
mPassNo = 0;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
drawPrvDecodeImageOnce();
endWriteFramebuffer();
mPassNo++;
beginWriteFramebuffer(EPD_COLOR_RED);
drawPrvDecodeImageOnce();
endWriteFramebuffer();
pr(" complete.\n");
screenTxEnd();
screenShutdown();
}
#pragma callee_saves myStrlen
static uint16_t myStrlen(const char *str) {
const char *__xdata strP = str;
while (charsPrvDerefAndIncGenericPtr(&strP))
;
return strP - str;
}
void drawFullscreenMsg(const char *str) {
volatile uint16_t PDATA textRow, textRowEnd; // without volatile, compiler ignores "__pdata"
struct CharDrawingParams __xdata cdp;
uint8_t __xdata rowIdx;
uint8_t iteration;
uint16_t i, r;
getVolt();
pr("MESSAGE '%s'\n", str);
screenTxStart(false);
for (iteration = 0; iteration < SCREEN_DATA_PASSES; iteration++) {
__bit inBarcode = false;
rowIdx = 0;
cdp.magnify = UI_MSG_MAGNIFY1;
cdp.str = str;
cdp.x = mathPrvI16Asr1(SCREEN_WIDTH - mathPrvMul8x8(CHAR_WIDTH * cdp.magnify, myStrlen(cdp.str)));
cdp.foreColor = UI_MSG_FORE_COLOR_1;
cdp.backColor = UI_MSG_BACK_COLOR;
textRow = 5;
textRowEnd = textRow + (uint8_t)((uint8_t)CHAR_HEIGHT * (uint8_t)cdp.magnify);
for (r = 0; r < SCREEN_HEIGHT; r++) {
// clear the row
for (i = 0; i < SCREEN_WIDTH * SCREEN_TX_BPP / 8; i++)
mScreenRow[i] = SCREEN_BYTE_FILL;
if (r >= textRowEnd) {
switch (rowIdx) {
case 0:
rowIdx = 1;
textRow = textRowEnd + 3;
cdp.magnify = UI_MSG_MAGNIFY2;
cdp.foreColor = UI_MSG_FORE_COLOR_2;
// cdp.str = macSmallString();
cdp.x = 0;
textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify;
break;
case 1:
rowIdx = 2;
textRow = SCREEN_HEIGHT - CHAR_HEIGHT - CHAR_HEIGHT;
cdp.magnify = UI_MSG_MAGNIFY3;
cdp.foreColor = UI_MSG_FORE_COLOR_3;
// cdp.str = voltString();
cdp.x = 1;
inBarcode = false;
break;
case 2:
rowIdx = 3;
textRow = SCREEN_HEIGHT - CHAR_HEIGHT;
cdp.magnify = UI_MSG_MAGNIFY3;
cdp.foreColor = UI_MSG_FORE_COLOR_3;
// cdp.str = fwVerString();
cdp.x = 1;
inBarcode = false;
break;
case 3:
cdp.str = "";
break;
}
} else if (r > textRow) {
inBarcode = false;
cdp.imgRow = r - textRow;
charsDrawString(&cdp);
}
for (i = 0; i < SCREEN_WIDTH * SCREEN_TX_BPP / 8; i++)
screenByteTx(mScreenRow[i]);
}
screenEndPass();
}
screenTxEnd();
draw();
epdEnterSleep();
}

View File

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

View File

@@ -8,6 +8,8 @@
static uint32_t __xdata mEepromSize;
static uint8_t __xdata mOpcodeErz4K = 0, mOpcodeErz32K = 0, mOpcodeErz64K = 0;
//extern uint8_t __xdata* tempBuffer;
uint8_t __xdata tempBufferE[320];
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");

539
tag_fw/epd.c Normal file
View File

@@ -0,0 +1,539 @@
#include "epd.h"
#include <stdbool.h>
#include <string.h>
#include "adc.h"
#include "asmUtil.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)
static uint8_t __xdata currentLUT = 0x00; // Current selected LUT
static bool __idata epdPr = false; // wheter or not we copy the pr("") output to the EPD
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 where working with
static bool __xdata isInited = false;
#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(133300);
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(1333000UL);
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(133300);
for (val = 3; val < 8; val++) {
shortCommand1(CMD_SETUP_VOLT_DETECT, val);
epdBusyWait(133300);
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(133300);
if (!isInited)
epdEnterSleep();
return voltage;
}
void selectLUT(uint8_t lut) {
if (lut == currentLUT) return;
//lut = 1;
switch (lut) {
case 0:
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1?
shortCommand(CMD_ACTIVATION);
epdBusyWait(1333000UL);
break;
case 1:
commandBegin(CMD_WRITE_LUT);
for (uint8_t i = 0; i < 70; i++)
epdSend(lutorig[i]);
commandEnd();
break;
}
currentLUT = 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_WRITE_PATTERN_BW, 0x66);
epdBusyWait(133300UL);
shortCommand1(CMD_WRITE_PATTERN_RED, 0x66);
epdBusyWait(133300UL);
}
void draw() {
shortCommand1(0x22, 0xCF);
// shortCommand1(0x22, SCREEN_CMD_REFRESH);
shortCommand(0x20);
epdBusyWait(TIMER_TICKS_PER_SECOND * 120);
}
void drawLineHorizontal(bool red, uint16_t y, uint8_t width) {
setWindowX(0, SCREEN_WIDTH);
setWindowY(y, y + width);
if (red) {
shortCommand1(CMD_WRITE_PATTERN_RED, 0xE6);
} else {
shortCommand1(CMD_WRITE_PATTERN_BW, 0xE6);
}
epdBusyWait(133300UL);
}
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();
}
// 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 (byte1 & (1 << c)) rbuffer[c] |= (1 << offset);
}
for (uint8_t c = 0; c < 8; c++) {
if (byte2 & (1 << 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 (byte1 & (1 << c)) {
rbuffer[c * 2] |= (3 << offset);
rbuffer[(c * 2) + 1] |= (3 << offset);
}
}
for (uint8_t c = 0; c < 8; c++) {
if (byte2 & (1 << 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 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) {
epdSend(c);
c = 0;
}
}
for (uint8_t i = 7; i != 255; i--) {
if (byte2 & (1 << i)) c |= (0x03 << ((i % 4) * 2));
if ((i % 4) == 0) {
epdSend(c);
c = 0;
}
}
}
} else {
epdSend(byte1);
epdSend(byte2);
}
}
void writeCharEPD(uint8_t c) {
if (!epdPr) {
return;
}
// 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) {
if (epdCharSize == 2) {
setWindowX(x - 32, x);
setPosXY(x - 32, y);
} else {
setWindowX(x - 16, x);
setPosXY(x - 16, y);
}
setWindowY(y, SCREEN_HEIGHT);
shortCommand1(CMD_DATA_ENTRY_MODE, 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);
}
epdPr = true;
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();
epdPr = false;
}
extern uint8_t* __xdata tempBuffer;
extern void dump(uint8_t *__xdata a, uint16_t __xdata l);
void loadFixedTempLUT() {
shortCommand1(0x18, 0x48);
shortCommand2(0x1A, 0x05, 0x00); // < temp register
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1 (i2C)
shortCommand(CMD_ACTIVATION);
epdBusyWait(1333000UL);
}
static uint8_t readLut() {
uint8_t sta = 0;
commandReadBegin(0x33);
uint16_t checksum = 0;
uint16_t ident = 0;
uint16_t shortl = 0;
for (uint16_t c = 0; c < 76; c++) {
sta = epdReadByte();
checksum += sta;
if (c < 70) ident += sta;
if (c < 14) shortl += sta;
tempBuffer[c] = sta;
}
pr("ident=%04X checksum=%04X shortl=%04X\n", ident, checksum, shortl);
commandReadEnd();
dump(tempBuffer, 96);
return sta;
}

54
tag_fw/epd.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef _JSCREEN_H_
#define _JSCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#define epdSend spiTXByte
#define EPD_DIRECTION_X false
#define EPD_DIRECTION_Y true
#define EPD_SIZE_SINGLE false
#define EPD_SIZE_DOUBLE true
#define EPD_COLOR_RED true
#define EPD_COLOR_BLACK false
#define EPD_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 drawLineHorizontal(bool red, uint16_t y, uint8_t width);
void beginFullscreenImage();
void beginWriteFramebuffer(bool color);
void endWriteFramebuffer();
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);
#endif

259
tag_fw/font.h Normal file
View File

@@ -0,0 +1,259 @@
static const uint8_t __code font[256][20]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
{0x80,0x07,0xC0,0x0C,0x40,0x0A,0xA0,0x14,0x20,0x14,0x20,0x14,0xA0,0x14,0x40,0x0A,0xC0,0x0C,0x80,0x07}, // 0x01
{0x80,0x07,0xC0,0x0F,0xC0,0x0D,0x60,0x1B,0xE0,0x1B,0xE0,0x1B,0x60,0x1B,0xC0,0x0D,0xC0,0x0F,0x80,0x07}, // 0x02
{0x7C,0x00,0xFE,0x01,0xFE,0x07,0xFE,0x0F,0xFC,0x1F,0xFC,0x1F,0xFE,0x0F,0xFE,0x07,0xFE,0x01,0x7C,0x00}, // 0x03
{0x80,0x00,0xC0,0x01,0xF0,0x03,0xF8,0x07,0xFE,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x01,0x80,0x00}, // 0x04
{0xC0,0x01,0xE0,0x03,0xE0,0x03,0xFC,0x03,0xFE,0x1F,0xFE,0x1D,0xFC,0x03,0xE0,0x03,0xE0,0x03,0xC0,0x01}, // 0x05
{0xC0,0x01,0xE0,0x03,0xF0,0x03,0xF8,0x03,0xFC,0x1F,0xFE,0x1D,0xF8,0x03,0xF0,0x03,0xE0,0x03,0xC0,0x01}, // 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
{0x80,0x07,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x24,0x10,0x74,0x08,0x8E,0x07,0x0E,0x00,0x18,0x00}, // 0x0B
{0x00,0x00,0x78,0x00,0x84,0x04,0x02,0x05,0x02,0x1F,0x02,0x05,0x82,0x05,0x84,0x00,0x78,0x00,0x00,0x00}, // 0x0C
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
{0x00,0x60,0x00,0x70,0x00,0x70,0xF8,0x3F,0x18,0x00,0x08,0x0C,0x0C,0x0E,0x04,0x0E,0xFE,0x07,0x00,0x00}, // 0x0E
{0x80,0x00,0xF0,0x03,0x20,0x03,0x10,0x02,0x18,0x06,0x10,0x02,0x20,0x02,0x30,0x03,0xD0,0x03,0x80,0x00}, // 0x0F
{0xF0,0x1F,0xE0,0x0F,0xE0,0x0F,0xC0,0x07,0xC0,0x07,0xC0,0x07,0x80,0x03,0x80,0x03,0x00,0x01,0x00,0x01}, // 0x10
{0x00,0x01,0x00,0x01,0x80,0x03,0x80,0x03,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xE0,0x0F,0xE0,0x0F,0xF0,0x1F}, // 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,0xFE,0x1B,0x00,0x00,0x00,0x00,0xFE,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x13
{0x00,0x00,0x1C,0x00,0x3E,0x00,0x7E,0x00,0xFE,0x7F,0x02,0x00,0x02,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0x14
{0x00,0x00,0x00,0x00,0xDC,0x61,0x32,0x43,0x22,0x42,0x62,0x46,0x42,0x4C,0x82,0x3B,0x00,0x00,0x00,0x00}, // 0x15
{0x00,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x00,0x00}, // 0x16
{0x00,0x00,0x00,0x00,0x08,0x88,0x04,0x90,0xFE,0xBF,0x04,0x90,0x08,0x88,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x17
{0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0xFE,0x7F,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x18
{0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x20,0xFE,0x7F,0x00,0x20,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x19
{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x40,0x05,0x80,0x03,0x00,0x01,0x00,0x00}, // 0x1A
{0x00,0x00,0x00,0x01,0x80,0x03,0x40,0x05,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00}, // 0x1B
{0x00,0x00,0xE0,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00}, // 0x1C
{0x00,0x00,0x00,0x01,0x80,0x03,0x40,0x05,0x00,0x01,0x00,0x01,0x40,0x05,0x80,0x03,0x00,0x01,0x00,0x00}, // 0x1D
{0x00,0x10,0x00,0x18,0x00,0x1E,0x80,0x1F,0xC0,0x1F,0xF0,0x1F,0xC0,0x1F,0x00,0x1F,0x00,0x1C,0x00,0x10}, // 0x1E
{0x10,0x00,0x30,0x00,0xF0,0x00,0xF0,0x03,0xF0,0x07,0xF0,0x1F,0xF0,0x07,0xF0,0x01,0x70,0x00,0x10,0x00}, // 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,0xFE,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21
{0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
{0x00,0x01,0x20,0x19,0xA0,0x07,0x78,0x01,0x26,0x19,0xA0,0x07,0x78,0x01,0x26,0x01,0x20,0x01,0x00,0x00}, // 0x23
{0x00,0x00,0x00,0x00,0x1C,0x18,0x26,0x10,0x42,0x10,0xFF,0x3F,0x82,0x11,0x02,0x0F,0x00,0x00,0x00,0x00}, // 0x24
{0x1C,0x10,0x22,0x08,0x22,0x04,0x22,0x03,0x9C,0x00,0x40,0x0E,0x30,0x11,0x08,0x11,0x04,0x11,0x02,0x0E}, // 0x25
{0x00,0x07,0x80,0x08,0x5C,0x10,0x62,0x10,0xA2,0x11,0x32,0x13,0x1C,0x1C,0x00,0x18,0x00,0x16,0x80,0x01}, // 0x26
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,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,0x08,0x00,0x18,0x00,0xF0,0x00,0x4E,0x00,0xF0,0x00,0x18,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x2A
{0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0xE0,0x1F,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00}, // 0x2B
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2C
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00}, // 0x2D
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E
{0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0xC0,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x00,0x00}, // 0x2F
{0x00,0x00,0xF0,0x03,0x0C,0x0C,0x02,0x10,0x02,0x10,0x02,0x10,0x0C,0x0C,0xF0,0x03,0x00,0x00,0x00,0x00}, // 0x30
{0x00,0x00,0x04,0x10,0x04,0x10,0x04,0x10,0xFE,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x31
{0x00,0x00,0x06,0x18,0x02,0x14,0x02,0x12,0x02,0x11,0xC2,0x10,0x3C,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32
{0x00,0x00,0x00,0x00,0x02,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0xBC,0x0F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33
{0x00,0x03,0xC0,0x02,0x20,0x02,0x18,0x02,0x04,0x02,0xFE,0x1F,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00}, // 0x34
{0x00,0x00,0x00,0x00,0x3E,0x10,0x22,0x10,0x22,0x10,0x42,0x08,0x82,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35
{0x00,0x00,0xF0,0x07,0x4C,0x08,0x22,0x10,0x22,0x10,0x22,0x10,0x42,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x36
{0x00,0x00,0x02,0x00,0x02,0x18,0x02,0x07,0xC2,0x00,0x32,0x00,0x0A,0x00,0x06,0x00,0x00,0x00,0x00,0x00}, // 0x37
{0x00,0x00,0x1C,0x0F,0xA2,0x10,0x42,0x10,0x42,0x10,0xA2,0x10,0xA2,0x09,0x1C,0x06,0x00,0x00,0x00,0x00}, // 0x38
{0x00,0x00,0x78,0x00,0x84,0x10,0x02,0x11,0x02,0x11,0x02,0x11,0x84,0x0C,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x39
{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x18,0x60,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A
{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x98,0x60,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3B
{0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x80,0x04,0x80,0x04,0x40,0x08,0x40,0x08,0x20,0x10,0x00,0x00}, // 0x3C
{0x00,0x00,0x80,0x04,0x80,0x04,0x80,0x04,0x80,0x04,0x80,0x04,0x80,0x04,0x80,0x04,0x80,0x04,0x00,0x00}, // 0x3D
{0x00,0x00,0x20,0x10,0x40,0x08,0x40,0x08,0x80,0x04,0x80,0x04,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00}, // 0x3E
{0x00,0x00,0x0E,0x00,0x02,0x00,0x02,0x1B,0x82,0x00,0x42,0x00,0x26,0x00,0x1C,0x00,0x00,0x00,0x00,0x00}, // 0x3F
{0xF0,0x03,0x18,0x0C,0x04,0x18,0xE2,0x13,0x12,0x14,0x0A,0x16,0x8A,0x1B,0xFC,0x07,0x00,0x04,0x00,0x04}, // 0x40
{0x00,0x10,0x00,0x0E,0x80,0x03,0x70,0x02,0x18,0x02,0x30,0x02,0xC0,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0x41
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x48,0x11,0x30,0x0E,0x00,0x00,0x00,0x00}, // 0x42
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x18,0x10,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,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x45
{0x00,0x00,0xF8,0x1F,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x46
{0x00,0x00,0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x11,0x08,0x11,0x18,0x1F,0x00,0x00}, // 0x47
{0x00,0x00,0xF8,0x1F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,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,0x00,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x0F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A
{0x00,0x00,0xF8,0x1F,0x80,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x04,0x08,0x08,0x00,0x10,0x00,0x00}, // 0x4B
{0x00,0x00,0xF8,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x4C
{0xF8,0x1F,0x38,0x00,0xE0,0x01,0x00,0x07,0x00,0x06,0xC0,0x01,0x38,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4D
{0x00,0x00,0xF8,0x1F,0x10,0x00,0x60,0x00,0x80,0x01,0x00,0x06,0x00,0x08,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,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0x88,0x00,0x70,0x00,0x00,0x00,0x00,0x00}, // 0x50
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x30,0x10,0x48,0xE0,0x47,0x00,0x00}, // 0x51
{0x00,0x00,0xF8,0x1F,0x08,0x01,0x08,0x01,0x08,0x03,0x88,0x04,0x70,0x08,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x52
{0x00,0x00,0x70,0x18,0x48,0x10,0x88,0x10,0x88,0x10,0x08,0x11,0x08,0x09,0x18,0x0E,0x00,0x00,0x00,0x00}, // 0x53
{0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x1F,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00}, // 0x54
{0x00,0x00,0xF8,0x07,0x00,0x18,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x08,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0x55
{0x08,0x00,0x30,0x00,0xC0,0x01,0x00,0x06,0x00,0x18,0x00,0x18,0x00,0x07,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x56
{0x18,0x00,0xE0,0x03,0x00,0x1C,0x00,0x0F,0xE0,0x00,0xC0,0x01,0x00,0x0E,0x00,0x1C,0xE0,0x03,0x18,0x00}, // 0x57
{0x08,0x10,0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10}, // 0x58
{0x08,0x00,0x10,0x00,0x60,0x00,0x80,0x00,0x00,0x1F,0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00}, // 0x59
{0x00,0x00,0x08,0x18,0x08,0x14,0x08,0x12,0x08,0x11,0x88,0x10,0x48,0x10,0x28,0x10,0x18,0x10,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,0x02,0x00,0x0C,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,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,0x00,0x04,0x00,0x03,0xE0,0x00,0x38,0x00,0x0E,0x00,0x70,0x00,0x80,0x03,0x00,0x04,0x00,0x00}, // 0x5E
{0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20}, // 0x5F
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
{0x00,0x00,0x00,0x0C,0x20,0x12,0x20,0x11,0x20,0x11,0x20,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x61
{0x00,0x00,0xFE,0x1F,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x60,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x62
{0x00,0x00,0x80,0x07,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}, // 0x63
{0x00,0x00,0x80,0x07,0x40,0x18,0x20,0x10,0x20,0x10,0x20,0x10,0x40,0x08,0xFE,0x1F,0x00,0x00,0x00,0x00}, // 0x64
{0x00,0x00,0x80,0x07,0x40,0x09,0x20,0x11,0x20,0x11,0x20,0x11,0x20,0x11,0xC0,0x11,0x00,0x00,0x00,0x00}, // 0x65
{0x00,0x00,0x20,0x00,0x20,0x00,0xFC,0x1F,0x24,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x00,0x00}, // 0x66
{0x00,0x00,0x80,0x07,0x40,0x98,0x20,0x90,0x20,0x90,0x20,0x90,0x40,0x48,0xE0,0x3F,0x00,0x00,0x00,0x00}, // 0x67
{0x00,0x00,0xFE,0x1F,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0x68
{0x00,0x00,0x20,0x00,0x20,0x00,0x26,0x00,0xE6,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69
{0x00,0x00,0x00,0x80,0x20,0x80,0x20,0x80,0x26,0x80,0xE6,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6A
{0x00,0x00,0xFE,0x1F,0x00,0x01,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x00,0x00,0x00,0x00}, // 0x6B
{0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0xFE,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C
{0xE0,0x1F,0x40,0x00,0x20,0x00,0x20,0x00,0xC0,0x1F,0x40,0x00,0x20,0x00,0x20,0x00,0xC0,0x1F,0x00,0x00}, // 0x6D
{0x00,0x00,0xE0,0x1F,0xC0,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0x6E
{0x00,0x00,0x80,0x07,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x40,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x6F
{0x00,0x00,0xE0,0xFF,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x60,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x70
{0x00,0x00,0x80,0x07,0x40,0x18,0x20,0x10,0x20,0x10,0x20,0x10,0x40,0x08,0xE0,0xFF,0x00,0x00,0x00,0x00}, // 0x71
{0x00,0x00,0x00,0x00,0xE0,0x1F,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0xE0,0x00,0x00,0x00,0x00,0x00}, // 0x72
{0x00,0x00,0xC0,0x18,0x20,0x11,0x20,0x11,0x20,0x12,0x20,0x12,0x20,0x0C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73
{0x00,0x00,0x20,0x00,0x20,0x00,0xF8,0x0F,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}, // 0x74
{0x00,0x00,0xE0,0x0F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75
{0x20,0x00,0xC0,0x01,0x00,0x06,0x00,0x18,0x00,0x10,0x00,0x0C,0x00,0x03,0xC0,0x00,0x20,0x00,0x00,0x00}, // 0x76
{0x60,0x00,0x80,0x07,0x00,0x18,0x00,0x0E,0xC0,0x01,0x80,0x01,0x00,0x0E,0x00,0x18,0x80,0x07,0x60,0x00}, // 0x77
{0x00,0x00,0x20,0x10,0x40,0x08,0x80,0x04,0x00,0x03,0x00,0x03,0x80,0x04,0x40,0x08,0x20,0x10,0x00,0x00}, // 0x78
{0x20,0x80,0xC0,0x80,0x00,0x83,0x00,0x46,0x00,0x38,0x00,0x18,0x00,0x06,0x00,0x01,0xC0,0x00,0x20,0x00}, // 0x79
{0x00,0x00,0x20,0x10,0x20,0x18,0x20,0x14,0x20,0x12,0x20,0x11,0xA0,0x10,0x60,0x10,0x20,0x10,0x00,0x00}, // 0x7A
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0xFC,0x3E,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,0xFC,0x3E,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00}, // 0x7D
{0x00,0x03,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x80,0x01}, // 0x7E
{0x00,0x00,0x80,0x1F,0xC0,0x10,0x20,0x10,0x10,0x10,0x20,0x10,0xC0,0x10,0x80,0x1F,0x00,0x00,0x00,0x00}, // 0x7F
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x90,0x08,0xB0,0x18,0xD0,0x00,0x00,0x00,0x00}, // 0x80
{0x00,0x00,0xE0,0x0F,0x04,0x10,0x00,0x10,0x00,0x10,0x04,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x81
{0x00,0x00,0x80,0x07,0x40,0x09,0x20,0x11,0x24,0x11,0x22,0x11,0x20,0x11,0xC0,0x11,0x00,0x00,0x00,0x00}, // 0x82
{0x00,0x00,0x00,0x0C,0x24,0x12,0x22,0x11,0x22,0x11,0x24,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x83
{0x00,0x00,0x00,0x0C,0x24,0x12,0x20,0x11,0x20,0x11,0x24,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x84
{0x00,0x00,0x00,0x0C,0x22,0x12,0x24,0x11,0x20,0x11,0x20,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x85
{0x00,0x00,0x00,0x0C,0x20,0x12,0x22,0x11,0x25,0x11,0x22,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x86
{0x00,0x00,0x80,0x07,0x40,0x08,0x20,0x10,0x20,0x90,0x20,0xB0,0x20,0xD0,0x20,0x10,0x00,0x00,0x00,0x00}, // 0x87
{0x00,0x00,0x80,0x07,0x44,0x09,0x22,0x11,0x22,0x11,0x24,0x11,0x20,0x11,0xC0,0x11,0x00,0x00,0x00,0x00}, // 0x88
{0x00,0x00,0x80,0x07,0x40,0x09,0x24,0x11,0x20,0x11,0x20,0x11,0x24,0x11,0xC0,0x11,0x00,0x00,0x00,0x00}, // 0x89
{0x00,0x00,0x80,0x07,0x40,0x09,0x22,0x11,0x24,0x11,0x20,0x11,0x20,0x11,0xC0,0x11,0x00,0x00,0x00,0x00}, // 0x8A
{0x00,0x00,0x20,0x00,0x24,0x00,0x20,0x00,0xE0,0x1F,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8B
{0x00,0x00,0x20,0x00,0x24,0x00,0x22,0x00,0xE2,0x1F,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8C
{0x00,0x00,0x20,0x00,0x20,0x00,0x22,0x00,0xE4,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8D
{0x00,0x10,0x00,0x0E,0x81,0x03,0x70,0x02,0x18,0x02,0x30,0x02,0xC1,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0x8E
{0x00,0x10,0x00,0x0E,0x80,0x03,0x72,0x02,0x0D,0x02,0x1D,0x02,0xF2,0x02,0x80,0x03,0x00,0x0E,0x00,0x10}, // 0x8F
{0x00,0x00,0xF8,0x1F,0x08,0x11,0x08,0x11,0x0A,0x11,0x09,0x11,0x08,0x11,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x90
{0x20,0x0E,0x20,0x13,0x20,0x11,0x20,0x11,0xC0,0x0F,0x20,0x19,0x20,0x11,0x20,0x11,0xC0,0x11,0x00,0x00}, // 0x91
{0x00,0x10,0x00,0x0C,0x80,0x07,0x60,0x04,0x18,0x04,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x10,0x00,0x00}, // 0x92
{0x00,0x00,0x80,0x07,0x44,0x08,0x22,0x10,0x22,0x10,0x24,0x10,0x40,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x93
{0x00,0x00,0x80,0x07,0x44,0x08,0x20,0x10,0x20,0x10,0x24,0x10,0x40,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x94
{0x00,0x00,0x80,0x07,0x42,0x08,0x24,0x10,0x20,0x10,0x20,0x10,0x40,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0x95
{0x00,0x00,0xE0,0x0F,0x04,0x10,0x02,0x10,0x02,0x10,0x04,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x96
{0x00,0x00,0xE0,0x0F,0x02,0x10,0x04,0x10,0x00,0x10,0x00,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x97
{0x20,0x80,0xC0,0x80,0x04,0x83,0x00,0x46,0x00,0x38,0x04,0x18,0x00,0x06,0x00,0x01,0xC0,0x00,0x20,0x00}, // 0x98
{0x00,0x00,0xE0,0x07,0x11,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x09,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x99
{0x00,0x00,0xF8,0x07,0x01,0x18,0x00,0x10,0x00,0x10,0x00,0x10,0x01,0x08,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0x9A
{0x00,0x00,0x80,0x17,0x40,0x08,0x20,0x14,0x20,0x13,0xA0,0x10,0x40,0x08,0xA0,0x07,0x00,0x00,0x00,0x00}, // 0x9B
{0x00,0x00,0x00,0x00,0x00,0x10,0x40,0x18,0xFC,0x17,0x42,0x10,0x42,0x10,0x02,0x10,0x00,0x00,0x00,0x00}, // 0x9C
{0x00,0x00,0xE0,0x17,0x10,0x0C,0x08,0x16,0x08,0x11,0x88,0x10,0x68,0x10,0x30,0x08,0xE8,0x07,0x00,0x00}, // 0x9D
{0x00,0x00,0x20,0x10,0x40,0x08,0x80,0x04,0x00,0x03,0x00,0x03,0x80,0x04,0x40,0x08,0x20,0x10,0x00,0x00}, // 0x9E
{0x00,0x00,0x00,0x80,0x20,0x80,0x20,0x80,0xFE,0x7F,0x21,0x00,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x00}, // 0x9F
{0x00,0x00,0x00,0x0C,0x20,0x12,0x20,0x11,0x24,0x11,0x22,0x09,0xC0,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0xA0
{0x00,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xE4,0x1F,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA1
{0x00,0x00,0x80,0x07,0x40,0x08,0x20,0x10,0x24,0x10,0x22,0x10,0x40,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0xA2
{0x00,0x00,0xE0,0x0F,0x00,0x10,0x00,0x10,0x04,0x10,0x02,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA3
{0x00,0x00,0xE0,0x1F,0xC4,0x00,0x42,0x00,0x24,0x00,0x24,0x00,0x22,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0xA4
{0x00,0x00,0xF8,0x1F,0x12,0x00,0x61,0x00,0x83,0x01,0x02,0x06,0x01,0x08,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0xA5
{0x00,0x00,0x00,0x00,0x32,0x00,0x4A,0x00,0x4A,0x00,0x4A,0x00,0x7C,0x00,0x40,0x00,0x00,0x00,0x00,0x00}, // 0xA6
{0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00}, // 0xA7
{0x00,0x00,0x00,0x70,0x00,0xC8,0x00,0x88,0x00,0x84,0x60,0x83,0x00,0x80,0x00,0xE0,0x00,0x00,0x00,0x00}, // 0xA8
{0x00,0x00,0x38,0x00,0x44,0x00,0xBA,0x00,0xAA,0x00,0xBA,0x00,0x44,0x00,0x38,0x00,0x00,0x00,0x00,0x00}, // 0xA9
{0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x07,0x00,0x00}, // 0xAA
{0x02,0x10,0x7E,0x0C,0x00,0x02,0x80,0x01,0x60,0x00,0x10,0x00,0x8C,0x10,0x82,0x1C,0x80,0x14,0x00,0x13}, // 0xAB
{0x02,0x10,0x7E,0x0C,0x00,0x02,0x80,0x01,0x60,0x00,0x10,0x06,0x0C,0x05,0x82,0x04,0x80,0x1F,0x00,0x04}, // 0xAC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xAD
{0x00,0x00,0x00,0x01,0x80,0x02,0x40,0x04,0x20,0x08,0x00,0x01,0x80,0x02,0x40,0x04,0x20,0x08,0x00,0x00}, // 0xAE
{0x00,0x00,0x20,0x08,0x40,0x04,0x80,0x02,0x00,0x01,0x20,0x08,0x40,0x04,0x80,0x02,0x00,0x01,0x00,0x00}, // 0xAF
{0xDB,0x6C,0xDB,0x6C,0x00,0x00,0xDB,0x6C,0xDB,0x6C,0x00,0x00,0xDB,0x6C,0xDB,0x6C,0x00,0x00,0x00,0x00}, // 0xB0
{0x6C,0xDB,0x6C,0xDB,0xDB,0x6C,0xFF,0xFF,0x6C,0xDB,0xDB,0x6C,0xFF,0xFF,0x6C,0xDB,0xDB,0x6C,0xDB,0x6C}, // 0xB1
{0xFF,0xFF,0xFF,0xFF,0xDB,0x6C,0xFF,0xFF,0xFF,0xFF,0xDB,0x6C,0xFF,0xFF,0xFF,0xFF,0xDB,0x6C,0xDB,0x6C}, // 0xB2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB3
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB4
{0x00,0x10,0x00,0x0E,0x80,0x03,0x70,0x02,0x1A,0x02,0x31,0x02,0xC0,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0xB5
{0x00,0x10,0x00,0x0E,0x80,0x03,0x72,0x02,0x19,0x02,0x31,0x02,0xC2,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0xB6
{0x00,0x10,0x00,0x0E,0x80,0x03,0x71,0x02,0x1A,0x02,0x30,0x02,0xC0,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0xB7
{0xF0,0x03,0x0C,0x0C,0xE6,0x19,0x32,0x13,0x12,0x12,0x12,0x12,0x16,0x1A,0x0C,0x0C,0xF0,0x03,0x00,0x00}, // 0xB8
{0x80,0x02,0x80,0x02,0x80,0x02,0xFF,0xFE,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
{0x80,0x02,0x80,0x02,0x80,0x02,0x80,0xFE,0x80,0x00,0x80,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBB
{0x80,0x02,0x80,0x02,0x80,0x02,0xFF,0x02,0x00,0x02,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBC
{0x00,0x00,0xF0,0x03,0x08,0x04,0x04,0x0C,0x04,0x08,0xFE,0x1F,0x04,0x08,0x04,0x08,0x00,0x00,0x00,0x00}, // 0xBD
{0x02,0x00,0x04,0x00,0x98,0x04,0xA0,0x04,0xC0,0x1F,0xA0,0x04,0x90,0x04,0x08,0x00,0x04,0x00,0x02,0x00}, // 0xBE
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBF
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC0
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFF,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC1
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC3
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC4
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFF,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xC5
{0x00,0x00,0x00,0x0C,0x24,0x12,0x22,0x11,0x24,0x11,0x24,0x09,0xC2,0x1F,0x00,0x10,0x00,0x00,0x00,0x00}, // 0xC6
{0x00,0x10,0x00,0x0E,0x82,0x03,0x71,0x02,0x1B,0x02,0x32,0x02,0xC1,0x02,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0xC7
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x00,0x02,0xFF,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xC8
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x80,0x00,0x80,0xFE,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xC9
{0x80,0x02,0x80,0x02,0x80,0x02,0xFF,0x02,0x00,0x02,0xFF,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xCA
{0x80,0x02,0x80,0x02,0x80,0x02,0x80,0xFE,0x80,0x00,0x80,0xFE,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xCB
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xCC
{0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xCD
{0x80,0x02,0x80,0x02,0x80,0x02,0xFF,0xFE,0x00,0x00,0xFF,0xFE,0x80,0x02,0x80,0x02,0x80,0x02,0x80,0x02}, // 0xCE
{0x00,0x00,0x08,0x04,0xF0,0x03,0x10,0x02,0x10,0x02,0x10,0x02,0x10,0x02,0xF0,0x03,0x08,0x04,0x00,0x00}, // 0xCF
{0x00,0x00,0x82,0x07,0x4A,0x08,0x2E,0x10,0x24,0x10,0x2A,0x10,0x70,0x08,0xC0,0x07,0x00,0x00,0x00,0x00}, // 0xD0
{0x80,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0xD1
{0x00,0x00,0xF8,0x1F,0x08,0x11,0x0A,0x11,0x09,0x11,0x09,0x11,0x0A,0x11,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD2
{0x00,0x00,0xF8,0x1F,0x09,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x09,0x11,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD3
{0x00,0x00,0xF8,0x1F,0x08,0x11,0x08,0x11,0x09,0x11,0x0A,0x11,0x08,0x11,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD4
{0x00,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD5
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xFA,0x1F,0x09,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD6
{0x00,0x00,0x08,0x10,0x08,0x10,0x0A,0x10,0xF9,0x1F,0x09,0x10,0x0A,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD7
{0x00,0x00,0x08,0x10,0x09,0x10,0x08,0x10,0xF8,0x1F,0x08,0x10,0x09,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD8
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}, // 0xDA
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB
{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, // 0xDC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xDD
{0x00,0x00,0x08,0x10,0x08,0x10,0x09,0x10,0xFA,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xDE
{0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00}, // 0xDF
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x0A,0x10,0x09,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE0
{0x00,0x00,0xFC,0x1F,0x02,0x00,0x02,0x00,0xE2,0x10,0x1C,0x11,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00}, // 0xE1
{0x00,0x00,0xE0,0x07,0x10,0x08,0x0A,0x10,0x09,0x10,0x09,0x10,0x0A,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE2
{0x00,0x00,0xE0,0x07,0x10,0x08,0x09,0x10,0x0A,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE3
{0x00,0x00,0x80,0x07,0x44,0x08,0x22,0x10,0x24,0x10,0x24,0x10,0x42,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0xE4
{0x00,0x00,0xE0,0x07,0x12,0x08,0x09,0x10,0x0B,0x10,0x0A,0x10,0x09,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE5
{0x00,0x00,0xE0,0xFF,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x08,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xE6
{0x00,0x00,0xFE,0xFF,0x40,0x08,0x20,0x10,0x20,0x10,0x20,0x10,0x60,0x08,0x80,0x07,0x00,0x00,0x00,0x00}, // 0xE7
{0x00,0x00,0xF8,0x1F,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x02,0xC0,0x01,0x00,0x00,0x00,0x00}, // 0xE8
{0x00,0x00,0xF8,0x07,0x00,0x18,0x00,0x10,0x02,0x10,0x01,0x10,0x00,0x08,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xE9
{0x00,0x00,0xF8,0x07,0x00,0x18,0x02,0x10,0x01,0x10,0x01,0x10,0x02,0x08,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xEA
{0x00,0x00,0xF8,0x07,0x00,0x18,0x01,0x10,0x02,0x10,0x00,0x10,0x00,0x08,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xEB
{0x20,0x80,0xC0,0x80,0x00,0x83,0x00,0x46,0x04,0x38,0x02,0x18,0x00,0x06,0x00,0x01,0xC0,0x00,0x20,0x00}, // 0xEC
{0x08,0x00,0x10,0x00,0x60,0x00,0x80,0x00,0x02,0x1F,0x81,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00}, // 0xED
{0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00}, // 0xEE
{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00}, // 0xF0
{0x00,0x00,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0xE0,0x13,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x00}, // 0xF1
{0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0}, // 0xF2
{0x42,0x10,0x4A,0x08,0x5A,0x04,0x36,0x03,0x80,0x00,0x40,0x06,0x30,0x05,0x88,0x04,0x84,0x1F,0x02,0x04}, // 0xF3
{0x00,0x00,0x1C,0x00,0x3E,0x00,0x7E,0x00,0xFE,0x7F,0x02,0x00,0x02,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0xF4
{0x00,0x00,0x00,0x00,0xDC,0x61,0x32,0x43,0x22,0x42,0x62,0x46,0x42,0x4C,0x82,0x3B,0x00,0x00,0x00,0x00}, // 0xF5
{0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x60,0x1A,0x60,0x1A,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00}, // 0xF6
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xA0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF7
{0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF8
{0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFA
{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFB
{0x00,0x00,0x00,0x00,0x42,0x00,0x4A,0x00,0x4A,0x00,0x4A,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFC
{0x00,0x00,0x00,0x00,0x42,0x00,0x62,0x00,0x52,0x00,0x52,0x00,0x4C,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFD
{0x00,0x00,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0xE0,0x1F,0x00,0x00}, // 0xFE
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
};

125
tag_fw/lut.h Normal file
View File

@@ -0,0 +1,125 @@
static const uint8_t __code lut154[] = {
// 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,
0x02, 0x04, 0x01, 0x03, 0x00, // was 11 repeat
0x01, 0x14, 0x01, 0x14, 0x00, // was 3 repeat
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,
};

View File

@@ -8,7 +8,6 @@
#include "adc.h"
#include "asmUtil.h"
#include "board.h"
#include "chars.h"
#include "comms.h"
#include "cpu.h"
#include "drawing.h"
@@ -22,16 +21,6 @@
#include "wdt.h"
#include "syncedproto.h"
uint16_t __xdata battery_voltage = 0;
int8_t __xdata mCurTemperature;
void getVolt(void) {
if (battery_voltage == 0)
battery_voltage = adcSampleBattery();
}
void main(void){
mainProtocolLoop();
}

View File

@@ -29,4 +29,14 @@ uint8_t spiByte(uint8_t val)
CFGPAGE = bcp;
return val;
}
void spiTXByte(uint8_t val)
{
uint8_t bcp = CFGPAGE;
CFGPAGE = 4;
SPITX = val;
SPICFG = 0xa0; //spi at 4mhz, mode 0
while(SPICFG & 0x20);
CFGPAGE = bcp;
}

View File

@@ -11,6 +11,9 @@ void spiInit(void);
#pragma callee_saves spiByte
uint8_t spiByte(uint8_t val);
#pragma callee_saves spiTXByte
void spiTXByte(uint8_t val);
#endif

View File

@@ -1,24 +1,23 @@
#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;
extern void writeCharEPD(uint8_t c);
void uartTx(uint8_t val) {
writeCharEPD(val);
while (!(UARTSTA & (1 << 1)))
;
UARTSTA &= ~(1 << 1);
UARTBUF = val;
}

View File

@@ -10,7 +10,6 @@
#include "adc.h"
#include "asmUtil.h"
#include "board.h"
#include "chars.h"
#include "comms.h"
#include "cpu.h"
#include "drawing.h"
@@ -19,7 +18,8 @@
#include "printf.h"
#include "proto.h"
#include "radio.h"
#include "screen.h"
#include "epd.h"
#include "sleep.h"
#include "timer.h"
#include "wdt.h"
@@ -133,6 +133,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;
@@ -151,17 +152,17 @@ 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 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).
#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;
@@ -248,30 +249,30 @@ void initAfterWake() {
timerInit();
// partialInit();
boardInit();
screenSleep();
epdEnterSleep();
irqsOn();
boardInitStage2();
initRadio();
}
void doSleep(uint32_t __xdata t) {
if(t>1000)pr("s=%lu\n ", t / 1000);
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);
// 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;
P1INTEN = 0;
#endif
initAfterWake();
@@ -315,11 +316,11 @@ void sendAvailDataReq() {
txframe->srcPan = 0x4447;
// 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 +505,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 +526,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 +562,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) {
@@ -843,7 +805,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;
@@ -902,11 +864,10 @@ void mainProtocolLoop(void) {
boardInitStage2();
// i2ctest();
pr("BOOTED> (new version!)\n\n");
pr("BOOTED> (new epd driver!!!)\n\n");
if (!eepromInit()) {
pr("failed to init eeprom\n");
drawFullscreenMsg((const __xdata char *)"eeprom failed");
while (1)
;
} else {
@@ -919,15 +880,12 @@ void mainProtocolLoop(void) {
dataReqAttemptArr[c] = INTERVAL_BASE;
}
screenSleep();
epdEnterSleep();
eepromDeepPowerDown();
initRadio();
P1CHSTA &=~ (1 << 0);
// drawPartial();
// i2ctest();
// doSleep(10000);
P1CHSTA &= ~(1 << 0);
while (1) {
radioRxEnable(true, true);