mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-24 22:08:47 +01:00
wip
This commit is contained in:
589
tag_fw/epd.c
589
tag_fw/epd.c
@@ -17,40 +17,151 @@
|
||||
#include "timer.h"
|
||||
#include "wdt.h"
|
||||
|
||||
#define CMD_DRV_OUTPUT_CTRL 0x01
|
||||
#define CMD_SOFT_START_CTRL 0x0C
|
||||
#define CMD_ENTER_SLEEP 0x10
|
||||
#define CMD_DATA_ENTRY_MODE 0x11
|
||||
#define CMD_SOFT_RESET 0x12
|
||||
#define CMD_SOFT_RESET2 0x13
|
||||
#define CMD_SETUP_VOLT_DETECT 0x15
|
||||
#define CMD_TEMP_SENSOR_CONTROL 0x18
|
||||
#define CMD_ACTIVATION 0x20
|
||||
#define CMD_DISP_UPDATE_CTRL 0x21
|
||||
#define CMD_DISP_UPDATE_CTRL2 0x22
|
||||
#define CMD_WRITE_FB_BW 0x24
|
||||
#define CMD_WRITE_FB_RED 0x26
|
||||
#define CMD_UNKNOWN_1 0x2B
|
||||
#define CMD_LOAD_OTP_LUT 0x31
|
||||
#define CMD_WRITE_LUT 0x32
|
||||
#define CMD_BORDER_WAVEFORM_CTRL 0x3C
|
||||
#define CMD_WINDOW_X_SIZE 0x44
|
||||
#define CMD_WINDOW_Y_SIZE 0x45
|
||||
#define CMD_WRITE_PATTERN_RED 0x46
|
||||
#define CMD_WRITE_PATTERN_BW 0x47
|
||||
#define CMD_XSTART_POS 0x4E
|
||||
#define CMD_YSTART_POS 0x4F
|
||||
#define CMD_ANALOG_BLK_CTRL 0x74
|
||||
#define CMD_DIGITAL_BLK_CTRL 0x7E
|
||||
#define CMD_PANEL_SETTING 0x00
|
||||
#define CMD_POWER_SETTING 0x01
|
||||
#define CMD_POWER_OFF 0x02
|
||||
#define CMD_POWER_OFF_SEQUENCE 0x03
|
||||
#define CMD_POWER_ON 0x04
|
||||
#define CMD_POWER_ON_MEASURE 0x05
|
||||
#define CMD_BOOSTER_SOFT_START 0x06
|
||||
#define CMD_DEEP_SLEEP 0x07
|
||||
#define CMD_DISPLAY_START_TRANSMISSION_DTM1 0x10
|
||||
#define CMD_DATA_STOP 0x11
|
||||
#define CMD_DISPLAY_REFRESH 0x12
|
||||
#define CMD_DISPLAY_START_TRANSMISSION_DTM2 0x13
|
||||
#define CMD_PLL_CONTROL 0x30
|
||||
#define CMD_TEMPERATURE_CALIB 0x40
|
||||
#define CMD_TEMPERATURE_SELECT 0x41
|
||||
#define CMD_TEMPERATURE_WRITE 0x42
|
||||
#define CMD_TEMPERATURE_READ 0x43
|
||||
#define CMD_VCOM_INTERVAL 0x50
|
||||
#define CMD_LOWER_POWER_DETECT 0x51
|
||||
#define CMD_TCON_SETTING 0x60
|
||||
#define CMD_RESOLUTION_SETING 0x61
|
||||
#define CMD_REVISION 0x70
|
||||
#define CMD_STATUS 0x71
|
||||
#define CMD_AUTO_MEASUREMENT_VCOM 0x80
|
||||
#define CMD_READ_VCOM 0x81
|
||||
#define CMD_VCOM_DC_SETTING 0x82
|
||||
#define CMD_PARTIAL_WINDOW 0x90
|
||||
#define CMD_PARTIAL_IN 0x91
|
||||
#define CMD_PARTIAL_OUT 0x92
|
||||
#define CMD_PROGRAM_MODE 0xA0
|
||||
#define CMD_ACTIVE_PROGRAM 0xA1
|
||||
#define CMD_READ_OTP 0xA2
|
||||
#define CMD_CASCADE_SET 0xE0
|
||||
#define CMD_POWER_SAVING 0xE3
|
||||
#define CMD_FORCE_TEMPERATURE 0xE5
|
||||
|
||||
#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
|
||||
enum PSR_FLAGS {
|
||||
RES_96x230 = 0b00000000,
|
||||
RES_96x252 = 0b01000000,
|
||||
RES_128x296 = 0b10000000,
|
||||
RES_160x296 = 0b11000000,
|
||||
|
||||
LUT_OTP = 0b00000000,
|
||||
LUT_REG = 0b00100000,
|
||||
|
||||
FORMAT_BWR = 0b00000000,
|
||||
FORMAT_BW = 0b00010000,
|
||||
|
||||
SCAN_DOWN = 0b00000000,
|
||||
SCAN_UP = 0b00001000,
|
||||
|
||||
SHIFT_LEFT = 0b00000000,
|
||||
SHIFT_RIGHT = 0b00000100,
|
||||
|
||||
BOOSTER_OFF = 0b00000000,
|
||||
BOOSTER_ON = 0b00000010,
|
||||
|
||||
RESET_SOFT = 0b00000000,
|
||||
RESET_NONE = 0b00000001
|
||||
};
|
||||
|
||||
enum PWR_FLAGS_1 {
|
||||
VDS_EXTERNAL = 0b00000000,
|
||||
VDS_INTERNAL = 0b00000010,
|
||||
|
||||
VDG_EXTERNAL = 0b00000000,
|
||||
VDG_INTERNAL = 0b00000001
|
||||
};
|
||||
|
||||
enum PWR_FLAGS_2 {
|
||||
VCOM_VD = 0b00000000,
|
||||
VCOM_VG = 0b00000100,
|
||||
|
||||
VGHL_16V = 0b00000000,
|
||||
VGHL_15V = 0b00000001,
|
||||
VGHL_14V = 0b00000010,
|
||||
VGHL_13V = 0b00000011
|
||||
};
|
||||
|
||||
enum BOOSTER_FLAGS {
|
||||
START_10MS = 0b00000000,
|
||||
START_20MS = 0b01000000,
|
||||
START_30MS = 0b10000000,
|
||||
START_40MS = 0b11000000,
|
||||
|
||||
STRENGTH_1 = 0b00000000,
|
||||
STRENGTH_2 = 0b00001000,
|
||||
STRENGTH_3 = 0b00010000,
|
||||
STRENGTH_4 = 0b00011000,
|
||||
STRENGTH_5 = 0b00100000,
|
||||
STRENGTH_6 = 0b00101000,
|
||||
STRENGTH_7 = 0b00110000,
|
||||
STRENGTH_8 = 0b00111000,
|
||||
|
||||
OFF_0_27US = 0b00000000,
|
||||
OFF_0_34US = 0b00000001,
|
||||
OFF_0_40US = 0b00000010,
|
||||
OFF_0_54US = 0b00000011,
|
||||
OFF_0_80US = 0b00000100,
|
||||
OFF_1_54US = 0b00000101,
|
||||
OFF_3_34US = 0b00000110,
|
||||
OFF_6_58US = 0b00000111
|
||||
};
|
||||
|
||||
enum PFS_FLAGS {
|
||||
FRAMES_1 = 0b00000000,
|
||||
FRAMES_2 = 0b00010000,
|
||||
FRAMES_3 = 0b00100000,
|
||||
FRAMES_4 = 0b00110000
|
||||
};
|
||||
|
||||
enum TSE_FLAGS {
|
||||
TEMP_INTERNAL = 0b00000000,
|
||||
TEMP_EXTERNAL = 0b10000000,
|
||||
|
||||
OFFSET_0 = 0b00000000,
|
||||
OFFSET_1 = 0b00000001,
|
||||
OFFSET_2 = 0b00000010,
|
||||
OFFSET_3 = 0b00000011,
|
||||
OFFSET_4 = 0b00000100,
|
||||
OFFSET_5 = 0b00000101,
|
||||
OFFSET_6 = 0b00000110,
|
||||
OFFSET_7 = 0b00000111,
|
||||
|
||||
OFFSET_MIN_8 = 0b00001000,
|
||||
OFFSET_MIN_7 = 0b00001001,
|
||||
OFFSET_MIN_6 = 0b00001010,
|
||||
OFFSET_MIN_5 = 0b00001011,
|
||||
OFFSET_MIN_4 = 0b00001100,
|
||||
OFFSET_MIN_3 = 0b00001101,
|
||||
OFFSET_MIN_2 = 0b00001110,
|
||||
OFFSET_MIN_1 = 0b00001111
|
||||
};
|
||||
|
||||
enum PLL_FLAGS {
|
||||
// other frequency options exist but there doesn't seem to be much
|
||||
// point in including them - this is a fair range of options...
|
||||
HZ_29 = 0b00111111,
|
||||
HZ_33 = 0b00111110,
|
||||
HZ_40 = 0b00111101,
|
||||
HZ_50 = 0b00111100,
|
||||
HZ_67 = 0b00111011,
|
||||
HZ_100 = 0b00111010,
|
||||
HZ_200 = 0b00111001
|
||||
};
|
||||
|
||||
#define commandEnd() \
|
||||
do { \
|
||||
@@ -96,7 +207,7 @@ static void epdBusySleep(uint32_t timeout) {
|
||||
P2FUNC &= 0xfd;
|
||||
P2DIR |= 2;
|
||||
P2PULL |= 2;
|
||||
P2LVLSEL |= 2;
|
||||
P2LVLSEL &= ~(2);
|
||||
|
||||
P2CHSTA &= 0xfd;
|
||||
P2INTEN |= 2;
|
||||
@@ -116,7 +227,7 @@ static void epdBusyWait(uint32_t timeout) {
|
||||
uint32_t __xdata start = timerGet();
|
||||
|
||||
while (timerGet() - start < timeout) {
|
||||
if (!P2_1)
|
||||
if (P2_1)
|
||||
return;
|
||||
}
|
||||
pr("screen timeout %lu ticks :(\n", timerGet() - start);
|
||||
@@ -189,11 +300,6 @@ static void epdReset() {
|
||||
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
|
||||
P2_0 = 1;
|
||||
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
|
||||
|
||||
shortCommand(CMD_SOFT_RESET); // software reset
|
||||
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
|
||||
shortCommand(CMD_SOFT_RESET2);
|
||||
timerDelay(TIMER_TICKS_PER_SECOND / 1000);
|
||||
}
|
||||
void epdConfigGPIO(bool setup) {
|
||||
// data / _command: 2.2
|
||||
@@ -205,7 +311,7 @@ void epdConfigGPIO(bool setup) {
|
||||
// GENERIC SPI BUS PINS
|
||||
// spi.clk 0.0
|
||||
// spi.mosi 0.1
|
||||
if(epdGPIOActive==setup)return;
|
||||
if (epdGPIOActive == setup) return;
|
||||
if (setup) {
|
||||
P2DIR |= (1 << 1); // busy as input
|
||||
P2DIR &= ~((1 << 2) | (1 << 0)); // D/C and Reset as output
|
||||
@@ -221,43 +327,56 @@ void epdConfigGPIO(bool setup) {
|
||||
epdGPIOActive = setup;
|
||||
}
|
||||
void epdEnterSleep() {
|
||||
P2_0 = 0;
|
||||
timerDelay(10);
|
||||
P2_0 = 1;
|
||||
timerDelay(50);
|
||||
shortCommand(CMD_SOFT_RESET2);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 15);
|
||||
shortCommand1(CMD_ENTER_SLEEP, 0x03);
|
||||
shortCommand1(CMD_VCOM_INTERVAL, 0x17);
|
||||
shortCommand1(CMD_VCOM_DC_SETTING, 0x00);
|
||||
shortCommand(CMD_POWER_OFF);
|
||||
epdWaitRdy();
|
||||
shortCommand1(CMD_DEEP_SLEEP, 0xA5);
|
||||
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);
|
||||
uint8_t psr_setting = RES_128x296 | FORMAT_BWR | BOOSTER_ON | RESET_NONE;
|
||||
|
||||
psr_setting |= LUT_OTP;
|
||||
|
||||
psr_setting |= SHIFT_RIGHT | SCAN_DOWN;
|
||||
|
||||
shortCommand1(CMD_PANEL_SETTING, psr_setting);
|
||||
|
||||
commandBegin(CMD_POWER_SETTING);
|
||||
epdSend(VDS_INTERNAL | VDG_INTERNAL);
|
||||
epdSend(VCOM_VD | VGHL_16V);
|
||||
epdSend(0b101011);
|
||||
epdSend(0b101011);
|
||||
epdSend(0b101011);
|
||||
commandEnd();
|
||||
|
||||
commandBegin(CMD_DRV_OUTPUT_CTRL);
|
||||
epdSend((SCREEN_HEIGHT - 1) & 0xff);
|
||||
epdSend((SCREEN_HEIGHT - 1) >> 8);
|
||||
epdSend(0x00);
|
||||
shortCommand(CMD_POWER_ON);
|
||||
epdWaitRdy();
|
||||
|
||||
commandBegin(CMD_BOOSTER_SOFT_START);
|
||||
epdSend(START_10MS | STRENGTH_3 | OFF_6_58US);
|
||||
epdSend(START_10MS | STRENGTH_3 | OFF_6_58US);
|
||||
epdSend(START_10MS | STRENGTH_3 | OFF_6_58US);
|
||||
commandEnd();
|
||||
|
||||
// shortCommand1(CMD_DATA_ENTRY_MODE, 0x03);
|
||||
shortCommand1(CMD_BORDER_WAVEFORM_CTRL, 0xC0);
|
||||
shortCommand1(CMD_TEMP_SENSOR_CONTROL, 0x80);
|
||||
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1 (i2C)
|
||||
// shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB9); // mode 2?
|
||||
shortCommand(CMD_ACTIVATION);
|
||||
epdBusyWait(TIMER_TICKS_PER_SECOND);
|
||||
isInited = true;
|
||||
currentLut = EPD_LUT_DEFAULT;
|
||||
commandBegin(CMD_RESOLUTION_SETING);
|
||||
epdSend(SCREEN_WIDTH);
|
||||
epdSend(SCREEN_HEIGHT >> 8);
|
||||
epdSend(SCREEN_HEIGHT & 0xFF);
|
||||
commandEnd();
|
||||
|
||||
shortCommand1(CMD_POWER_OFF_SEQUENCE, FRAMES_1);
|
||||
shortCommand1(CMD_TEMPERATURE_SELECT, TEMP_INTERNAL | OFFSET_0);
|
||||
shortCommand1(CMD_TCON_SETTING, 0x22);
|
||||
shortCommand1(CMD_VCOM_INTERVAL, 0x87); // 0b10'01'1100);
|
||||
shortCommand1(CMD_PLL_CONTROL, HZ_100);
|
||||
// shortCommand(POF);
|
||||
epdWaitRdy();
|
||||
shortCommand(CMD_POWER_ON);
|
||||
epdWaitRdy();
|
||||
}
|
||||
static uint8_t epdGetStatus() {
|
||||
uint8_t sta;
|
||||
@@ -267,53 +386,9 @@ static uint8_t epdGetStatus() {
|
||||
return sta;
|
||||
}
|
||||
uint16_t epdGetBattery(void) {
|
||||
uint16_t voltage = 2600;
|
||||
uint8_t val;
|
||||
|
||||
timerDelay(50);
|
||||
P2_0 = 0;
|
||||
timerDelay(50);
|
||||
P2_0 = 1;
|
||||
timerDelay(50);
|
||||
|
||||
shortCommand(CMD_SOFT_RESET); // software reset
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 30);
|
||||
shortCommand(CMD_SOFT_RESET2);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 30);
|
||||
|
||||
shortCommand1(CMD_DISP_UPDATE_CTRL2, SCREEN_CMD_CLOCK_ON | SCREEN_CMD_ANALOG_ON);
|
||||
shortCommand(CMD_ACTIVATION);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 100);
|
||||
|
||||
for (val = 3; val < 8; val++) {
|
||||
shortCommand1(CMD_SETUP_VOLT_DETECT, val);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 100);
|
||||
if (epdGetStatus() & 0x10) { // set if voltage is less than threshold ( == 1.9 + val / 10)
|
||||
voltage = 1850 + mathPrvMul8x8(val, 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shortCommand(CMD_SOFT_RESET2);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 15);
|
||||
shortCommand1(CMD_ENTER_SLEEP, 0x03);
|
||||
|
||||
return voltage;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void loadFixedTempOTPLUT() {
|
||||
shortCommand1(0x18, 0x48); // external temp sensor
|
||||
shortCommand2(0x1A, 0x05, 0x00); // < temp register
|
||||
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1 (i2C)
|
||||
shortCommand(CMD_ACTIVATION);
|
||||
epdBusyWait(TIMER_TICKS_PER_SECOND);
|
||||
}
|
||||
static void writeLut() {
|
||||
commandBegin(CMD_WRITE_LUT);
|
||||
for (uint8_t i = 0; i < (dispLutSize * 10); i++)
|
||||
epdSend(waveformbuffer[i]);
|
||||
commandEnd();
|
||||
}
|
||||
static void readLut() {
|
||||
commandReadBegin(0x33);
|
||||
uint16_t checksum = 0;
|
||||
@@ -371,138 +446,50 @@ static void lutGroupRepeatReduce(uint8_t group, uint8_t factor) {
|
||||
}
|
||||
}
|
||||
void selectLUT(uint8_t lut) {
|
||||
if (currentLut == lut) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentLut != EPD_LUT_DEFAULT) {
|
||||
// load the 'default' LUT for the current temperature in the EPD lut register
|
||||
shortCommand1(CMD_DISP_UPDATE_CTRL2, 0xB1); // mode 1?
|
||||
shortCommand(CMD_ACTIVATION);
|
||||
epdBusyWait(TIMER_TICKS_PER_SECOND);
|
||||
}
|
||||
|
||||
currentLut = lut;
|
||||
|
||||
// if we're going to be using the default LUT, we're done here.
|
||||
if (lut == EPD_LUT_DEFAULT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// download the current LUT from the waveform buffer
|
||||
readLut();
|
||||
|
||||
if (dispLutSize == 0) {
|
||||
dispLutSize = getLutSize();
|
||||
dispLutSize /= 10;
|
||||
pr("lut size = %d\n", dispLutSize);
|
||||
#ifdef PRINT_LUT
|
||||
dump(waveformbuffer, LUT_BUFFER_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (lut) {
|
||||
case EPD_LUT_NO_REPEATS:
|
||||
lutGroupDisable(LUTGROUP_NEGATIVE);
|
||||
lutGroupDisable(LUTGROUP_FASTBLINK);
|
||||
lutGroupRepeat(LUTGROUP_SLOWBLINK, 0);
|
||||
lutGroupSpeedup(LUTGROUP_SET, 2);
|
||||
lutGroupSpeedup(LUTGROUP_IMPROVE_SHARPNESS, 2);
|
||||
lutGroupRepeatReduce(LUTGROUP_IMPROVE_SHARPNESS, 2);
|
||||
lutGroupSpeedup(LUTGROUP_IMPROVE_REDS, 2);
|
||||
lutGroupRepeatReduce(LUTGROUP_IMPROVE_REDS, 2);
|
||||
lutGroupDisable(LUTGROUP_UNUSED);
|
||||
break;
|
||||
case EPD_LUT_FAST_NO_REDS:
|
||||
lutGroupDisable(LUTGROUP_NEGATIVE);
|
||||
lutGroupDisable(LUTGROUP_FASTBLINK);
|
||||
lutGroupDisable(LUTGROUP_SLOWBLINK);
|
||||
lutGroupSpeedup(LUTGROUP_SET, 2);
|
||||
lutGroupDisable(LUTGROUP_IMPROVE_REDS);
|
||||
lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS);
|
||||
lutGroupDisable(LUTGROUP_UNUSED);
|
||||
break;
|
||||
case EPD_LUT_FAST:
|
||||
lutGroupDisable(LUTGROUP_NEGATIVE);
|
||||
lutGroupDisable(LUTGROUP_FASTBLINK);
|
||||
lutGroupDisable(LUTGROUP_SLOWBLINK);
|
||||
lutGroupRepeat(LUTGROUP_SET, 1);
|
||||
lutGroupSpeedup(LUTGROUP_SET, 2);
|
||||
lutGroupDisable(LUTGROUP_IMPROVE_SHARPNESS);
|
||||
lutGroupDisable(LUTGROUP_IMPROVE_REDS);
|
||||
lutGroupDisable(LUTGROUP_UNUSED);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dispLutSize == 10) {
|
||||
lutGroupDisable(LUTGROUP_UNUSED);
|
||||
lutGroupDisable(LUTGROUP_UNKNOWN);
|
||||
lutGroupDisable(LUTGROUP_UNUSED3);
|
||||
lutGroupDisable(LUTGROUP_UNUSED4);
|
||||
}
|
||||
writeLut();
|
||||
wdtSetResetVal(0xFFC73CBF);
|
||||
wdtOn();
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
void setWindowXY(uint16_t xstart, uint16_t xend, uint16_t ystart, uint16_t yend) {
|
||||
shortCommand(CMD_PARTIAL_IN);
|
||||
commandBegin(CMD_PARTIAL_WINDOW);
|
||||
epdSend((xstart / 8) << 3);
|
||||
epdSend(((xend / 8 - 1) << 3) | 0x07);
|
||||
epdSend(ystart >> 8);
|
||||
epdSend(ystart & 0xFF);
|
||||
epdSend((yend - 1) >> 8);
|
||||
epdSend((yend - 1) & 0xff);
|
||||
epdSend(0x01);
|
||||
commandEnd();
|
||||
}
|
||||
|
||||
void setColorMode(uint8_t red, uint8_t bw) {
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void clearScreen() {
|
||||
setWindowX(0, SCREEN_WIDTH);
|
||||
setWindowY(0, SCREEN_HEIGHT);
|
||||
setPosXY(0, 0);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 3); // was 3
|
||||
shortCommand1(CMD_WRITE_PATTERN_BW, 0x66);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 100);
|
||||
shortCommand1(CMD_WRITE_PATTERN_RED, 0x66);
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 100);
|
||||
shortCommand(CMD_PARTIAL_OUT);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2);
|
||||
for (uint16_t c = 0; c < ((1UL * SCREEN_HEIGHT * SCREEN_WIDTH) / 8); c++) {
|
||||
epdSend(0x00);
|
||||
}
|
||||
commandEnd();
|
||||
epdWaitRdy();
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1);
|
||||
for (uint16_t c = 0; c < ((1UL * SCREEN_HEIGHT * SCREEN_WIDTH) / 8); c++) {
|
||||
epdSend(0x00);
|
||||
}
|
||||
commandEnd();
|
||||
}
|
||||
void draw() {
|
||||
shortCommand1(0x22, 0xCF);
|
||||
// shortCommand1(0x22, SCREEN_CMD_REFRESH);
|
||||
shortCommand(0x20);
|
||||
epdBusyWait(TIMER_TICKS_PER_SECOND * 120);
|
||||
shortCommand(CMD_DISPLAY_REFRESH);
|
||||
epdWaitRdy();
|
||||
}
|
||||
void drawNoWait() {
|
||||
shortCommand1(0x22, 0xCF);
|
||||
// shortCommand1(0x22, SCREEN_CMD_REFRESH);
|
||||
shortCommand(0x20);
|
||||
shortCommand(CMD_DISPLAY_REFRESH);
|
||||
}
|
||||
void drawWithSleep() {
|
||||
shortCommand1(0x22, 0xCF);
|
||||
// shortCommand1(0x22, SCREEN_CMD_REFRESH);
|
||||
shortCommand(0x20);
|
||||
shortCommand(CMD_DISPLAY_REFRESH);
|
||||
uint8_t tmp_P2FUNC = P2FUNC;
|
||||
uint8_t tmp_P2DIR = P2DIR;
|
||||
uint8_t tmp_P2PULL = P2PULL;
|
||||
@@ -510,10 +497,10 @@ void drawWithSleep() {
|
||||
P2FUNC &= 0xfd;
|
||||
P2DIR |= 2;
|
||||
P2PULL |= 2;
|
||||
P2LVLSEL |= 2;
|
||||
P2LVLSEL &= ~(2);
|
||||
|
||||
P2CHSTA &= 0xfd;
|
||||
P2INTEN |= 2;
|
||||
P2INTEN = 2;
|
||||
P2CHSTA &= 0xfd;
|
||||
sleepForMsec(TIMER_TICKS_PER_SECOND * 120);
|
||||
wdtOn();
|
||||
@@ -529,45 +516,16 @@ void drawWithSleep() {
|
||||
void epdWaitRdy() {
|
||||
epdBusyWait(TIMER_TICKS_PER_SECOND * 120);
|
||||
}
|
||||
void drawLineHorizontal(bool color, uint16_t x1, uint16_t x2, uint16_t y) {
|
||||
setWindowX(x1, x2);
|
||||
setWindowY(y, y + 1);
|
||||
if (color) {
|
||||
shortCommand1(CMD_WRITE_PATTERN_RED, 0xE6);
|
||||
} else {
|
||||
shortCommand1(CMD_WRITE_PATTERN_BW, 0xE6);
|
||||
}
|
||||
epdBusyWait(TIMER_TICKS_PER_MS * 100);
|
||||
}
|
||||
void drawLineVertical(bool color, uint16_t x, uint16_t y1, uint16_t y2) {
|
||||
setWindowY(y1, y2);
|
||||
setWindowX(x, x + 8);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 3);
|
||||
setPosXY(x, y1);
|
||||
if (color) {
|
||||
commandBegin(CMD_WRITE_FB_RED);
|
||||
} else {
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
}
|
||||
uint8_t __xdata c = 0x80;
|
||||
c >>= (x % 8);
|
||||
for (; y1 < y2; y1++) {
|
||||
epdSend(c);
|
||||
}
|
||||
commandEnd();
|
||||
}
|
||||
void beginFullscreenImage() {
|
||||
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
|
||||
setWindowX(0, SCREEN_WIDTH);
|
||||
setWindowY(0, SCREEN_HEIGHT);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 3);
|
||||
setPosXY(0, 0);
|
||||
shortCommand(CMD_PARTIAL_OUT);
|
||||
// shortCommand1(CMD_DATA_ENTRY_MODE, 3);
|
||||
// setPosXY(0, 0);
|
||||
}
|
||||
void beginWriteFramebuffer(bool color) {
|
||||
if (color == EPD_COLOR_RED) {
|
||||
commandBegin(CMD_WRITE_FB_RED);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2);
|
||||
} else {
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1);
|
||||
}
|
||||
epdDeselect();
|
||||
}
|
||||
@@ -575,30 +533,39 @@ void endWriteFramebuffer() {
|
||||
commandEnd();
|
||||
}
|
||||
void loadRawBitmap(uint8_t* bmp, uint16_t x, uint16_t y, bool color) {
|
||||
uint16_t xsize = bmp[0] / 8;
|
||||
// this function is very badly hurt by the switch to UC8151, taking up LOTS of valuable idata space. fix me, or put me out of my misery
|
||||
uint16_t __xdata xsize = bmp[0] / 8;
|
||||
if (bmp[0] % 8) xsize++;
|
||||
uint16_t size = xsize * bmp[1];
|
||||
setWindowX(x, x + (xsize * 8));
|
||||
setWindowY(y, bmp[1] + y);
|
||||
setPosXY(x, y);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 3);
|
||||
if (color) {
|
||||
commandBegin(CMD_WRITE_FB_RED);
|
||||
} else {
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
}
|
||||
uint16_t __xdata ysize = bmp[1];
|
||||
uint16_t __xdata size = xsize * bmp[1];
|
||||
|
||||
// shortCommand1(CMD_DATA_ENTRY_MODE, 3);
|
||||
|
||||
bmp += 2;
|
||||
while (size--) {
|
||||
|
||||
uint16_t __xdata c = 0;
|
||||
uint16_t __xdata curY = y;
|
||||
while (1) {
|
||||
if (c % xsize == 0) {
|
||||
commandEnd();
|
||||
setWindowXY(x, x + xsize * 8, SCREEN_HEIGHT - curY - 1, SCREEN_HEIGHT - curY);
|
||||
curY++;
|
||||
if (color) {
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2);
|
||||
} else {
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1);
|
||||
}
|
||||
}
|
||||
epdSend(*(bmp++));
|
||||
c++;
|
||||
if (!size--) break;
|
||||
}
|
||||
commandEnd();
|
||||
shortCommand(CMD_PARTIAL_OUT);
|
||||
}
|
||||
void printBarcode(const uint8_t* string, uint16_t x, uint16_t y) {
|
||||
setWindowY(y, 1);
|
||||
setWindowX(x, x + 8);
|
||||
setPosXY(x, y);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 1);
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
setWindowXY(x, x + 8, SCREEN_HEIGHT - y, SCREEN_HEIGHT);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1);
|
||||
struct BarcodeInfo __xdata bci = {
|
||||
.str = string,
|
||||
};
|
||||
@@ -610,6 +577,7 @@ void printBarcode(const uint8_t* string, uint16_t x, uint16_t y) {
|
||||
}
|
||||
}
|
||||
commandEnd();
|
||||
shortCommand(CMD_PARTIAL_OUT);
|
||||
}
|
||||
// stuff for printing text
|
||||
static void pushXFontBytesToEPD(uint8_t byte1, uint8_t byte2) {
|
||||
@@ -756,34 +724,34 @@ void epdPrintBegin(uint16_t x, uint16_t y, bool direction, bool fontsize, bool c
|
||||
rbuffer[1] = 0;
|
||||
}
|
||||
|
||||
setWindowY(y, 1);
|
||||
// setWindowY(y, 1);
|
||||
if (epdCharSize == 2) {
|
||||
setWindowX(x, x + 32 + extra);
|
||||
setPosXY(x, y);
|
||||
setWindowXY(x, x + 32 + extra, SCREEN_HEIGHT - y, SCREEN_HEIGHT);
|
||||
// setPosXY(x, y);
|
||||
} else {
|
||||
setWindowX(x, x + 16 + extra);
|
||||
setPosXY(x, y);
|
||||
setWindowXY(x, x + 16 + extra, SCREEN_HEIGHT - y, SCREEN_HEIGHT);
|
||||
// setPosXY(x, y);
|
||||
}
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3
|
||||
// shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3
|
||||
} else {
|
||||
if (epdCharSize == 2) {
|
||||
x /= 2;
|
||||
x *= 2;
|
||||
setWindowY(y, y + 32);
|
||||
setWindowXY(x, SCREEN_WIDTH, y, y + 32);
|
||||
} else {
|
||||
setWindowY(y, y + 16);
|
||||
setWindowXY(x, SCREEN_WIDTH, y, y + 16);
|
||||
}
|
||||
setPosXY(x, y);
|
||||
// setPosXY(x, y);
|
||||
fontCurXpos = x;
|
||||
setWindowX(x, SCREEN_WIDTH);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 7);
|
||||
// setWindowXY(x, SCREEN_WIDTH);
|
||||
// shortCommand1(CMD_DATA_ENTRY_MODE, 7);
|
||||
memset(rbuffer, 0, 32);
|
||||
}
|
||||
|
||||
if (color) {
|
||||
commandBegin(CMD_WRITE_FB_RED);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM2);
|
||||
} else {
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
commandBegin(CMD_DISPLAY_START_TRANSMISSION_DTM1);
|
||||
}
|
||||
}
|
||||
void epdPrintEnd() {
|
||||
@@ -793,26 +761,7 @@ void epdPrintEnd() {
|
||||
}
|
||||
}
|
||||
commandEnd();
|
||||
shortCommand(CMD_PARTIAL_OUT);
|
||||
}
|
||||
|
||||
extern uint8_t __xdata blockXferBuffer[];
|
||||
|
||||
void readRam() {
|
||||
setWindowY(296, 0);
|
||||
setWindowX(0, 8);
|
||||
setPosXY(0, 296);
|
||||
shortCommand1(CMD_DATA_ENTRY_MODE, 1); // was 3
|
||||
shortCommand1(0x41, 0x00);
|
||||
commandReadBegin(0x27);
|
||||
epdReadByte();
|
||||
|
||||
for (uint16_t c = 0; c < 293; c++) {
|
||||
blockXferBuffer[c] = epdReadByte() | 0x10;
|
||||
}
|
||||
commandReadEnd();
|
||||
commandBegin(CMD_WRITE_FB_BW);
|
||||
for (uint16_t c = 0; c < 296; c++) {
|
||||
epdSend(blockXferBuffer[c]);
|
||||
}
|
||||
commandEnd();
|
||||
}
|
||||
extern uint8_t __xdata blockXferBuffer[];
|
||||
@@ -71,6 +71,8 @@ void beginWriteFramebuffer(bool color);
|
||||
|
||||
void lutTest();
|
||||
|
||||
void epdTest();
|
||||
|
||||
// for printf.c
|
||||
void writeCharEPD(uint8_t c);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user