#include "epd_ses_266.h" uint8 part_flag=0; const unsigned char CODE lut_20_vcom0_full[] = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x60, 0x28, 0x28, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char CODE lut_21_ww_full[] = { 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char CODE lut_22_bw_full[] = { 0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char CODE lut_23_wb_full[] = { 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14, 0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char CODE lut_24_bb_full[] = { 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14, 0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /******************************partial screen update LUT*********************************/ const unsigned char CODE lut_20_vcom0_partial[] = { 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, }; const unsigned char CODE lut_21_ww_partial[] = { // 10 w 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, }; const unsigned char CODE lut_22_bw_partial[] = { // 10 w 0x80, 0x19, 0x01, 0x00, 0x00, 0x01, }; const unsigned char CODE lut_23_wb_partial[] = { // 01 b 0x40, 0x19, 0x01, 0x00, 0x00, 0x01, }; const unsigned char CODE lut_24_bb_partial[] = { // 01 b 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, }; void DelayMS(uint msec) { uint i,j; for (i=0; i 0) { EPD_2IN66_SendData(0x00); fill_with_zeroes--; } } void EPD_2IN66_ReadBusy(void) { while(!EPD_READ_BUSY){ } } void EPD_2IN66_Reset(void) { EPD_RST_L; DelayMS(10); EPD_RST_H; DelayMS(10); } void EPD_2IN66_TurnOnDisplay(void) { if (part_flag) { EPD_2IN66_SendCommand(0x92); } EPD_2IN66_SendCommand(0x12); EPD_2IN66_ReadBusy(); } void EPD_2IN66_TurnOnDisplayEX(void) { if (part_flag) { EPD_2IN66_SendCommand(0x92); } EPD_2IN66_SendCommand(0x12); } void _InitDisplay() { EPD_2IN66_Reset(); EPD_2IN66_ReadBusy(); EPD_2IN66_SendCommand(0x01); // POWER SETTING EPD_2IN66_SendData(0x03); EPD_2IN66_SendData(0x00); EPD_2IN66_SendData(0x2b); EPD_2IN66_SendData(0x2b); EPD_2IN66_SendData(0x03); EPD_2IN66_SendCommand(0x06); // boost soft start EPD_2IN66_SendData(0x17); // A EPD_2IN66_SendData(0x17); // B EPD_2IN66_SendData(0x17); // C EPD_2IN66_SendCommand(0x00); // panel setting EPD_2IN66_SendData(0xbf&(~(1<<3))); // LUT from REG 128x296 // EPD_2IN66_SendData(0x8b); // LUT from REG 128x296 EPD_2IN66_SendData(0x0d); // VCOM to 0V fast EPD_2IN66_SendCommand(0x30); // PLL setting EPD_2IN66_SendData(0x3a); // 3a 100HZ 29 150Hz 39 200HZ 31 171HZ EPD_2IN66_SendCommand(0x61); // resolution setting EPD_2IN66_SendData(EPD_2IN66_WIDTH); EPD_2IN66_SendData(EPD_2IN66_HEIGHT / 256); EPD_2IN66_SendData(EPD_2IN66_HEIGHT % 256); EPD_2IN66_SendCommand(0x82); // vcom_DC setting // EPD_2IN66_SendData (0x00); // -0.1 // EPD_2IN66_SendData (0x08); // -0.1 + 8 * -0.05 = -0.5V from demo // EPD_2IN66_SendData (0x12); // -0.1 + 18 * -0.05 = -1.0V from OTP, slightly better EPD_2IN66_SendData(0x1c); // -0.1 + 28 * -0.05 = -1.5V test, better // EPD_2IN66_SendData (0x26); // -0.1 + 38 * -0.05 = -2.0V test, same // EPD_2IN66_SendData (0x30); // -0.1 + 48 * -0.05 = -2.5V test, darker // EPD_2IN66_SendCommand(0xe0); // resolution setting // EPD_2IN66_SendData(0x02); // EPD_2IN66_SendCommand(0xe5); // resolution setting // EPD_2IN66_SendData(0x32); EPD_2IN66_SendCommand(0x50); // VCOM AND DATA INTERVAL SETTING EPD_2IN66_SendData(0x17); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7 } static void EPD_2IN66_SetLUA(const uint8_t *data, uint16_t n) { uint16_t count; for (count = 0; count < n; count++) { EPD_2IN66_SendData(*(data + count)); } } void EPD_2IN66_Init(void) { part_flag = 0; _InitDisplay(); EPD_2IN66_SendCommand(0x20); EPD_2IN66_SetLUA((const uint8 *)lut_20_vcom0_full, sizeof(lut_20_vcom0_full)); EPD_2IN66_SendCommand(0x21); EPD_2IN66_SetLUA((const uint8 *)lut_21_ww_full, sizeof(lut_21_ww_full)); EPD_2IN66_SendCommand(0x22); EPD_2IN66_SetLUA((const uint8 *)lut_22_bw_full, sizeof(lut_22_bw_full)); EPD_2IN66_SendCommand(0x23); EPD_2IN66_SetLUA((const uint8 *)lut_23_wb_full, sizeof(lut_23_wb_full)); EPD_2IN66_SendCommand(0x24); EPD_2IN66_SetLUA((const uint8 *)lut_24_bb_full, sizeof(lut_24_bb_full)); EPD_2IN66_SendCommand(0x04); // POWER ON EPD_2IN66_ReadBusy(); } void EPD_2IN66_Init_Partial(void) { part_flag = 1; _InitDisplay(); EPD_2IN66_SendCommand(0x20); _writeDataPGM((const uint8 *)lut_20_vcom0_partial, sizeof(lut_20_vcom0_partial), 44 - sizeof(lut_20_vcom0_partial)); EPD_2IN66_SendCommand(0x21); _writeDataPGM((const uint8 *)lut_21_ww_partial, sizeof(lut_21_ww_partial), 42 - sizeof(lut_21_ww_partial)); EPD_2IN66_SendCommand(0x22); _writeDataPGM((const uint8 *)lut_22_bw_partial, sizeof(lut_22_bw_partial), 42 - sizeof(lut_22_bw_partial)); EPD_2IN66_SendCommand(0x23); _writeDataPGM((const uint8 *)lut_23_wb_partial, sizeof(lut_23_wb_partial), 42 - sizeof(lut_23_wb_partial)); EPD_2IN66_SendCommand(0x24); _writeDataPGM((const uint8 *)lut_24_bb_partial, sizeof(lut_24_bb_partial), 42 - sizeof(lut_24_bb_partial)); EPD_2IN66_SendCommand(0x04); // POWER ON EPD_2IN66_ReadBusy(); EPD_2IN66_SendCommand(0x91); // This command makes the display enter partial mode EPD_2IN66_SendCommand(0x90); // resolution setting EPD_2IN66_SendData(0); // x-start EPD_2IN66_SendData(EPD_2IN66_WIDTH - 1); // x-end EPD_2IN66_SendData(0); EPD_2IN66_SendData(0); // y-start EPD_2IN66_SendData(EPD_2IN66_HEIGHT / 256); EPD_2IN66_SendData(EPD_2IN66_HEIGHT % 256 - 1); // y-end EPD_2IN66_SendData(0x28); } void EPD_2IN66_Clear(void) { unsigned int i; // Write Data EPD_2IN66_SendCommand(0x10); // Transfer old data for (i = 0; i < (EPD_2IN66_WIDTH / 8) * EPD_2IN66_HEIGHT; i++) { EPD_2IN66_SendData(0x00); } EPD_2IN66_SendCommand(0x13); // Transfer new data for (i = 0; i < (EPD_2IN66_WIDTH / 8) * EPD_2IN66_HEIGHT; i++) { EPD_2IN66_SendData(0xFF); // Transfer the actual displayed data } // Refresh EPD_2IN66_TurnOnDisplay(); } /* * Image 为NULL,发送0xFF isold 1发送OLD RAM 0发送NEW RAM */ void EPD_2IN66_part_Display(const uint8 *Image, uint8_t isold) { uint16 Width, Height; Width = (EPD_2IN66_WIDTH % 8 == 0) ? (EPD_2IN66_WIDTH / 8) : (EPD_2IN66_WIDTH / 8 + 1); Height = EPD_2IN66_HEIGHT; volatile uint16 Addr = 0; EPD_2IN66_SendCommand(isold == 1 ? 0x10 : 0x13); if (Image != NULL) { EPD_2IN66_SendData_Multi(Image, Height * Width); } else { for (int j = 0; j < Height; j++) { for (int i = 0; i < Width; i++) { Addr = i + j * Width; EPD_2IN66_SendData(0xFF); } } } } /****************************************************************************** function : Sends the image buffer in RAM to e-Paper and displays parameter: ******************************************************************************/ void EPD_2IN66_Display(uint8 *Image) { EPD_2IN66_part_Display(NULL, 1); EPD_2IN66_part_Display(Image, 0); EPD_2IN66_SendCommand(0x11); } /****************************************************************************** function : Enter sleep mode parameter: ******************************************************************************/ void EPD_2IN66_Sleep(void) { EPD_2IN66_SendCommand(0X50); EPD_2IN66_SendData(0xf7); EPD_2IN66_SendCommand(0X02); EPD_2IN66_ReadBusy(); EPD_2IN66_SendCommand(0x07); EPD_2IN66_SendData(0xA5); } /** * @brief 向EPD控制器发送指定大小的显示数据。 * @param data 要发送数据的指针。 * @param data_size 要发送数据的大小。 */ void EPD_SendData_Multi(const uint8 *data, uint16 data_size, uint8 Inverse) { EPD_DC_H; EPD_CS_L; if (data == NULL) { for (uint i = 0; i < data_size; i++) { SendByte_softSPI(Inverse == 1 ? 0x00 : 0xff); } } else { for (uint i = 0; i < data_size; i++) { SendByte_softSPI(Inverse == 1 ? ~data[i] : data[i]); } } EPD_CS_H; } /** * @brief 设置EPD显示窗口位置和大小。 * @param x 显示窗口起始X位置。 * @param y_x8 显示窗口起始Y位置,设置1等于8像素。 * @param x_size 显示窗口X方向大小。 * @param y_size_x8 显示窗口Y方向大小,设置1等于8像素。 * @note 指针已被自动设置至窗口的左上角。 */ void EPD_SetWindow(uint16 x, uint8 y_x8, uint16 x_size, uint8 y_size_x8) { } /** * @brief 绘制UTF8字符串。 * @param x 绘制起始X位置。 * @param y_x8 绘制起始Y位置,设置1等于8像素。 * @param gap 字符间额外间距。 * @param str 要绘制的字符串指针。 * @param ascii_font ASCII字符字模指针。 * @param utf8_font UTF8字符字模指针。 * @param ramX 写ram选择 1新 2旧 。 * @note 调用的文件必须是utf-8编码 否则中文会错误 */ #define Interval_Ascii_Utf8 0 //ASCII字符与UTF8的间隔 void EPD_DrawFonts(uint16 x, uint8 y_x8, uint8 gap, const char *str, const epdFONT_ascii *ascii_font, const epdFONT_utf8 *utf8_font,uint8 ramX) { uint8 i = 0, utf8_size = 0; uint16 x_count = 0, font_size = 0; const uint8 *ascii_base_addr = NULL; uint32 unicode = 0, unicodeemp = 0; x_count = 0; while (*str != '\0') { if ((*str & 0x80) == 0x00) /* 普通ASCII字符 */ { if (ascii_font != NULL) { font_size = ascii_font->Width * ascii_font->Hight / 8; ascii_base_addr = ascii_font->fp + (*str - ascii_font->StartChar) * font_size; if ((*str - ascii_font->StartChar) >= 0 && ascii_base_addr + font_size <= ascii_font->fp + font_size * ascii_font->num) /* 限制数组范围 */ { EPD_draw(x + x_count, y_x8, ascii_font->Width, ascii_font->Hight / 8,ascii_base_addr,ramX); // EPD_SetWindow(x + x_count, y_x8, ascii_font->Width, ascii_font->Hight / 8); // EPD_SendRAM(ascii_base_addr, font_size); } else { EPD_draw(x + x_count, y_x8, ascii_font->Width, ascii_font->Hight / 8,NULL,ramX); // font_size = (ascii_font->Width) * (ascii_font->Hight / 8); // EPD_SetWindow(x + x_count, y_x8, ascii_font->Width, ascii_font->Hight / 8); // for (i = 0; i < font_size; i++) // { // utf8_size = 0xFF; /* 借用变量 */ // EPD_SendRAM(&utf8_size, 1); // } } x_count += ascii_font->Width + gap; } else if (*str == ' ' && utf8_font != NULL) /* 未指定ASCII字体时空格为UTF8字体宽度除2 */ { EPD_draw(x + x_count, y_x8, ascii_font->Width, ascii_font->Hight / 8,NULL,ramX); // font_size = (utf8_font->Width / 2) * (utf8_font->Hight / 8); // EPD_SetWindow(x + x_count, y_x8, utf8_font->Width / 2, utf8_font->Hight / 8); // for (i = 0; i < font_size; i++) // { // utf8_size = 0xFF; /* 借用变量 */ // EPD_SendRAM(&utf8_size, 1); // } x_count += utf8_font->Width / 2 + gap; } } else if (utf8_font != NULL) /* UTF8字符 */ { unicode = 0x000000; utf8_size = 0; for (i = 0; i < 5; i++) { if (*str & (0x80 >> i)) { utf8_size += 1; } else { break; } } switch (utf8_size) { case 2: if (*(str + 1) != '\0') { unicode = ((uint32) (*str & 0x1F)) << 6; str += 1; unicode |= (uint32) *str & 0x3F; } break; case 3: if (*(str + 1) != '\0' && *(str + 2) != '\0') { unicode = ((uint32) (*str & 0x0F)) << 12; str += 1; unicode |= ((uint32) (*str & 0x3F)) << 6; str += 1; unicode |= (uint32) *str & 0x3F; } break; case 4: if (*(str + 1) != '\0' && *(str + 2) != '\0' && *(str + 3) != '\0') { unicode = ((uint32) (*str & 0x07)) << 18; str += 1; unicode |= ((uint32) (*str & 0x3F)) << 12; str += 1; unicode |= ((uint32) (*str & 0x3F)) << 6; str += 1; unicode |= (uint32) *str & 0x3F; } break; } if (unicode != 0) { font_size = utf8_font->Width * utf8_font->Hight / 8; for (i = 0; i < utf8_font->num; i++) /* 限制数组范围 */ { unicodeemp = (uint32) utf8_font->fp[0 + (font_size + 3) * i] << 16; unicodeemp |= (uint32) utf8_font->fp[1 + (font_size + 3) * i] << 8; unicodeemp |= (uint32) utf8_font->fp[2 + (font_size + 3) * i]; if (unicodeemp == unicode) { EPD_draw(x + x_count + Interval_Ascii_Utf8, y_x8, utf8_font->Width, utf8_font->Hight / 8,utf8_font->fp + 3 + (font_size + 3) * i,ramX); // EPD_SetWindow(x + x_count + Interval_Ascii_Utf8, y_x8, utf8_font->Width, utf8_font->Hight / 8); // EPD_SendRAM(utf8_font->fp + 3 + (font_size + 3) * i, font_size); break; } } } x_count += utf8_font->Width + gap; } str += 1; } } void EPD_draw(uint16 x, uint8 y_x8, uint16 x_size, uint8 y_size_x8, const uint8 *dat, uint8 ramX) { uint16 data_size = x_size * y_size_x8; EPD_2IN66_SendCommand(0x90); EPD_2IN66_SendData(y_x8 << 3); EPD_2IN66_SendData(((y_x8 + y_size_x8) << 3) - 1); EPD_2IN66_SendData((x >> 8) & 0xff); EPD_2IN66_SendData(x & 0xff); EPD_2IN66_SendData(((x + x_size) >> 8) & 0xff); EPD_2IN66_SendData((x + x_size) & 0xff); if (dat == NULL) { if (ramX & 1) { EPD_2IN66_SendCommand(0x10); EPD_SendData_Multi(dat, data_size, 1); } if (ramX & 2) { EPD_2IN66_SendCommand(0x13); EPD_SendData_Multi(dat, data_size, 0); } } else { if (ramX & 1) { EPD_2IN66_SendCommand(0x10); EPD_SendData_Multi(dat, data_size, 1); } if (ramX & 2) { EPD_2IN66_SendCommand(0x13); EPD_SendData_Multi(dat, data_size,0); } } } const uint8_t CODE *Battery_ICON[] = {Bitmap_bat0, Bitmap_bat20, Bitmap_bat40, Bitmap_bat60, Bitmap_bat80, Bitmap_bat100}; void Draw_Battery(uint16_t x, uint8_t y, uint16_t max_voltage, uint16_t min_voltage, uint16_t voltage) { const uint8_t * battery = NULL; uint16_t voltage_size =0; if (voltage <= min_voltage) { battery =(const uint8_t *) Bitmap_bat0; goto END; } if (voltage >= max_voltage) { battery = (const uint8_t *)Bitmap_bat100; goto END; } voltage_size = (uint16_t)(max_voltage - min_voltage); for (int i = 1; i < sizeof(Battery_ICON); i++) { if ((voltage_size * i / 5 + min_voltage) >= voltage) { battery = (const uint8_t *)Battery_ICON[i]; break; } } END: EPD_draw(x, y, 27, 2, battery,3); }