Files
nrf51_2in13_epd/epd/epd_ses_266.c
2025-04-26 15:58:00 +08:00

646 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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<msec; i++)
for (j=0; j<535; j++);
}
void SendByte_softSPI(uint8 sdbyte)
{
uint8 i;
for (i = 0; i < 8; i++)
{
EPD_SCLK_L;
if (sdbyte & 0x80)
{
EPD_SDI_H;
}
else
{
EPD_SDI_L;
}
sdbyte <<= 1;
EPD_SCLK_H;
}
EPD_SCLK_L;
}
void EPD_2IN66_SendCommand(uint8 cmd)
{
EPD_DC_L;
EPD_CS_L;
SendByte_softSPI(cmd);
EPD_CS_H;
EPD_DC_H;
}
void EPD_2IN66_SendData(uint8 data)
{
EPD_DC_H;
EPD_CS_L;
SendByte_softSPI(data);
EPD_CS_H;
}
void EPD_2IN66_SendData_Multi(const uint8 *data, uint16 data_size)
{
// EPD_DC_H;
// EPD_CS_L;
while (data_size)
{
EPD_2IN66_SendData((*data++));
data_size--;
}
// EPD_CS_H;
}
void _writeDataPGM(const uint8 *data, uint16 n, uint16 fill_with_zeroes)
{
for (uint16_t i = 0; i < n; i++)
{
EPD_2IN66_SendData(*data++);
}
while (fill_with_zeroes > 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);
}