#include #include "tl_common.h" #include "main.h" #include "epd.h" #include "epd_spi.h" #include "epd_bw.h" #include "epd_bwr.h" #include "drivers.h" #include "stack/ble/ble.h" #include "battery.h" #include "OneBitDisplay.h" #include "TIFF_G4.h" extern const uint8_t ucMirror[]; #include "Roboto_Black_80.h" #include "font_60.h" #include "font16.h" #include "font30.h" RAM uint8_t epd_model = 0; // 0 = Undetected, 1 = BW, 2 = BWR const char* epd_model_string[] = {"NC","BW","BWR"}; RAM uint8_t epd_update_state = 0; const char* BLE_conn_string[] = {"", "B"}; RAM uint8_t epd_temperature_is_read = 0; RAM uint8_t epd_temperature = 0; uint8_t epd_buffer[epd_buffer_size]; uint8_t epd_temp[epd_buffer_size]; // for OneBitDisplay to draw into OBDISP obd; // virtual display structure TIFFIMAGE tiff; // Here we detect what E-Paper display is connected _attribute_ram_code_ void EPD_detect_model(void) { EPD_init(); // system power EPD_POWER_ON(); WaitMs(10); // Reset the EPD driver IC gpio_write(EPD_RESET, 0); WaitMs(10); gpio_write(EPD_RESET, 1); WaitMs(10); // Here we neeed to detect it if (EPD_BWR_detect()) { epd_model = 2; } else { epd_model = 1; } EPD_POWER_OFF(); } _attribute_ram_code_ uint8_t EPD_read_temp(void) { if (epd_temperature_is_read) return epd_temperature; if (!epd_model) { EPD_detect_model(); } EPD_init(); // system power EPD_POWER_ON(); WaitMs(5); // Reset the EPD driver IC gpio_write(EPD_RESET, 0); WaitMs(10); gpio_write(EPD_RESET, 1); WaitMs(10); if (epd_model == 1) epd_temperature = EPD_BW_read_temp(); else if (epd_model == 2) epd_temperature = EPD_BWR_read_temp(); EPD_POWER_OFF(); epd_temperature_is_read = 1; return epd_temperature; } _attribute_ram_code_ void EPD_Display(unsigned char *image, int size, uint8_t full_or_partial) { if (!epd_model) { EPD_detect_model(); } EPD_init(); // system power EPD_POWER_ON(); WaitMs(5); // Reset the EPD driver IC gpio_write(EPD_RESET, 0); WaitMs(10); gpio_write(EPD_RESET, 1); WaitMs(10); if (epd_model == 1) epd_temperature = EPD_BW_Display(image, size, full_or_partial); else if (epd_model == 2) epd_temperature = EPD_BWR_Display(image, size, full_or_partial); epd_temperature_is_read = 1; epd_update_state = 1; } _attribute_ram_code_ void epd_set_sleep(void) { if (!epd_model) { EPD_detect_model(); } if (epd_model == 1) EPD_BW_set_sleep(); else if (epd_model == 2) EPD_BWR_set_sleep(); EPD_POWER_OFF(); epd_update_state = 0; } _attribute_ram_code_ uint8_t epd_state_handler(void) { switch (epd_update_state) { case 0: // Nothing todo break; case 1: // check if refresh is done and sleep epd if so if (epd_model == 1) { if (!EPD_IS_BUSY()) epd_set_sleep(); } else { if (EPD_IS_BUSY()) epd_set_sleep(); } break; } return epd_update_state; } _attribute_ram_code_ void FixBuffer(uint8_t *pSrc, uint8_t *pDst) { int x, y; uint8_t *s, *d; for (y = 0; y < 16; y++) { // byte rows d = &pDst[y]; s = &pSrc[y * 250]; for (x = 0; x < 250; x++) { d[x * 16] = ~ucMirror[s[249 - x]]; // invert and flip } // for x } // for y } _attribute_ram_code_ void TIFFDraw(TIFFDRAW *pDraw) { uint8_t uc = 0, ucSrcMask, ucDstMask, *s, *d; int x, y; s = pDraw->pPixels; y = pDraw->y; // current line d = &epd_buffer[(249 * 16) + (y / 8)]; // rotated 90 deg clockwise ucDstMask = 0x80 >> (y & 7); // destination mask ucSrcMask = 0; // src mask for (x = 0; x < pDraw->iWidth; x++) { // Slower to draw this way, but it allows us to use a single buffer // instead of drawing and then converting the pixels to be the EPD format if (ucSrcMask == 0) { // load next source byte ucSrcMask = 0x80; uc = *s++; } if (!(uc & ucSrcMask)) { // black pixel d[-(x * 16)] &= ~ucDstMask; } ucSrcMask >>= 1; } } _attribute_ram_code_ void epd_display_tiff(uint8_t *pData, int iSize) { // test G4 decoder memset(epd_buffer, 0xff, epd_buffer_size); // clear to white TIFF_openRAW(&tiff, 250, 122, BITDIR_MSB_FIRST, pData, iSize, TIFFDraw); TIFF_setDrawParameters(&tiff, 65536, TIFF_PIXEL_1BPP, 0, 0, 250, 122, NULL); TIFF_decode(&tiff); TIFF_close(&tiff); EPD_Display(epd_buffer, epd_buffer_size, 1); } extern uint8_t mac_public[6]; _attribute_ram_code_ void epd_display(uint32_t time_is, uint16_t battery_mv, int16_t temperature, uint8_t full_or_partial) { if (epd_update_state) return; obdCreateVirtualDisplay(&obd, 250, 122, epd_temp); obdFill(&obd, 0, 0); // fill with white char buff[100]; sprintf(buff, "ESL_%02X%02X%02X - %s", mac_public[2], mac_public[1], mac_public[0], epd_model_string[epd_model]); obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_16, 1, 17, (char *)buff, 1); sprintf(buff, "%s", BLE_conn_string[ble_get_connected()]); obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_16, 232, 20, (char *)buff, 1); sprintf(buff, "%02d:%02d", ((time_is / 60) / 60) % 24, (time_is / 60) % 60); obdWriteStringCustom(&obd, (GFXfont *)&DSEG14_Classic_Mini_Regular_40, 50, 65, (char *)buff, 1); sprintf(buff, "%d'C", EPD_read_temp()); obdWriteStringCustom(&obd, (GFXfont *)&Special_Elite_Regular_30, 10, 95, (char *)buff, 1); sprintf(buff, "Battery %dmV", battery_mv); obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_16, 10, 120, (char *)buff, 1); FixBuffer(epd_temp, epd_buffer); EPD_Display(epd_buffer, epd_buffer_size, full_or_partial); } _attribute_ram_code_ void epd_display_char(uint8_t data) { int i; for (i = 0; i < epd_buffer_size; i++) { epd_buffer[i] = data; } EPD_Display(epd_buffer, epd_buffer_size, 1); } _attribute_ram_code_ void epd_clear(void) { memset(epd_buffer, 0x00, epd_buffer_size); }