#include #include "mcc_generated_files/mcc.h" #include #include "epd.h" #define TOPDOWN const uint8_t lut_full_update[] = { 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00 }; const uint8_t lut_partial_update[] = { 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void SPI_Transfer(uint8_t dat) { EPD_CS_LAT = 0; SPI_Exchange8bit(dat); EPD_CS_LAT = 1; } void EpdSendCommand(uint8_t cmd) { EPD_DC_LAT = 0; SPI_Transfer(cmd); } void EpdSendData(uint8_t dat) { EPD_DC_LAT = 1; SPI_Transfer(dat); } void EpdReset(void) { EPD_RST_LAT = 0; __delay_ms(200); EPD_RST_LAT = 1; __delay_ms(200); } void EpdWaitUntilIdle(void) { while(EPD_BUSY_PORT == 1) { // NOP(); __delay_ms(100); } } void EpdSetLUT(const uint8_t * lut) { uint8_t i; EpdSendCommand(WRITE_LUT_REGISTER); for(i = 0; i < 30; i++) { EpdSendData(lut[i]); } } void EpdSetMemoryArea(int16_t x_start, int16_t y_start, int16_t x_end, int16_t y_end) { #if defined(TOPDOWN) EpdSendCommand(SET_RAM_X_ADDRESS_START_END_POSITION); /* x point must be the multiple of 8 or the last 3 bits will be ignored */ EpdSendData(((EPD_WIDTH - x_start- 1) >> 3) & 0xFF); EpdSendData(((EPD_WIDTH - x_end - 1) >> 3) & 0xFF); EpdSendCommand(SET_RAM_Y_ADDRESS_START_END_POSITION); EpdSendData((EPD_HEIGHT - y_start - 1) & 0xFF); EpdSendData(((EPD_HEIGHT - y_start - 1) >> 8) & 0xFF); EpdSendData((EPD_HEIGHT - y_end - 1) & 0xFF); EpdSendData(((EPD_HEIGHT - y_end - 1) >> 8) & 0xFF); #else EpdSendCommand(SET_RAM_X_ADDRESS_START_END_POSITION); /* x point must be the multiple of 8 or the last 3 bits will be ignored */ EpdSendData((x_start >> 3) & 0xFF); EpdSendData((x_end >> 3) & 0xFF); EpdSendCommand(SET_RAM_Y_ADDRESS_START_END_POSITION); EpdSendData(y_start & 0xFF); EpdSendData((y_start >> 8) & 0xFF); EpdSendData(y_end & 0xFF); EpdSendData((y_end >> 8) & 0xFF); #endif } void EpdSetMemoryPointer(int16_t x, int16_t y) { #if defined(TOPDOWN) EpdSendCommand(SET_RAM_X_ADDRESS_COUNTER); /* x point must be the multiple of 8 or the last 3 bits will be ignored */ EpdSendData(((EPD_WIDTH - x - 1) >> 3) & 0xFF); EpdSendCommand(SET_RAM_Y_ADDRESS_COUNTER); EpdSendData((EPD_HEIGHT - y - 1) & 0xFF); EpdSendData(((EPD_HEIGHT - y - 1) >> 8) & 0xFF); EpdWaitUntilIdle(); #else // EpdSendCommand(SET_RAM_X_ADDRESS_COUNTER); // /* x point must be the multiple of 8 or the last 3 bits will be ignored */ // EpdSendData((x >> 3) & 0xFF); // EpdSendCommand(SET_RAM_Y_ADDRESS_COUNTER); // EpdSendData(y & 0xFF); // EpdSendData((y >> 8) & 0xFF); // EpdWaitUntilIdle(); #endif } void EpdSetFrameMemory(const uint8_t* image_buffer, int16_t width, int16_t height) { EpdSetMemoryArea(0, 0, width - 1, height - 1); EpdSetMemoryPointer(0, 0); EpdSendCommand(WRITE_RAM); /* send the image data */ for (int16_t i = 0; i < width / 8 * height; i++) { // EpdSendData(pgm_read_byte(&image_buffer[i])); EpdSendData(~image_buffer[i]); } } void EpdClearFrameMemory(uint8_t color) { EpdSetMemoryArea(0, 0, EPD_WIDTH - 1, EPD_HEIGHT - 1); EpdSetMemoryPointer(0, 0); EpdSendCommand(WRITE_RAM); /* send the color data */ for (int16_t i = 0; i < EPD_WIDTH / 8 * EPD_HEIGHT; i++) { EpdSendData(color); } } void EpdDisplayFrame(void) { EpdSendCommand(DISPLAY_UPDATE_CONTROL_2); EpdSendData(0xC4); EpdSendCommand(MASTER_ACTIVATION); EpdSendCommand(TERMINATE_FRAME_READ_WRITE); EpdWaitUntilIdle(); } void EpdSleep() { EpdSendCommand(DEEP_SLEEP_MODE); EpdSendData(0x01); // Bug behoben, hier hat das Datenwort gefehlt // EpdWaitUntilIdle(); } //void EpdTemperatureControl() { // EpdSendCommand(TEMPERATURE_SENSOR_CONTROL); // EpdSendData(0xC4); // EpdSendData(0xC4); // EpdWaitUntilIdle(); //} void EpdInit(void) { EpdReset(); EpdSendCommand(DRIVER_OUTPUT_CONTROL); EpdSendData((EPD_HEIGHT - 1) & 0xFF); EpdSendData(((EPD_HEIGHT - 1) >> 8) & 0xFF); EpdSendData(0x00); // GD = 0; SM = 0; TB = 0; EpdSendCommand(BOOSTER_SOFT_START_CONTROL); // EpdSendData(0xD7); // EpdSendData(0xD6); // EpdSendData(0x9D); EpdSendData(0x87); EpdSendData(0x86); EpdSendData(0x85); EpdSendCommand(GATE_SCAN_START_POSITION); EpdSendData(0); EpdSendData(0); EpdSendCommand(WRITE_VCOM_REGISTER); // EpdSendData(0xA8); // VCOM 7C EpdSendData(0x8f); // VCOM 7C EpdSendCommand(SET_DUMMY_LINE_PERIOD); EpdSendData(0x1A); // 4 dummy lines per gate // EpdSendCommand(SET_GATE_TIME); // EpdSendData(0x08); // 2us per line EpdSendCommand(DATA_ENTRY_MODE_SETTING); #if defined(TOPDOWN) EpdSendData(0x00); // X decrement; Y decrement #else // EpdSendData(0x03); // X increment; Y increment #endif EpdSetLUT(lut_full_update); } void EpdClear(void) { EpdClearFrameMemory(0xff); EpdDisplayFrame(); EpdClearFrameMemory(0xff); EpdDisplayFrame(); EpdSetLUT(lut_partial_update); }