Skip to content

Commit 37a4d3a

Browse files
mringwalC47D
authored andcommitted
Add PCD8544 driver
1 parent b674d2d commit 37a4d3a

File tree

8 files changed

+228
-0
lines changed

8 files changed

+228
-0
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
4242
list(APPEND SOURCES "lvgl_tft/GC9A01.c")
4343
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
4444
list(APPEND SOURCES "lvgl_tft/ili9163c.c")
45+
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
46+
list(APPEND SOURCES "lvgl_tft/pcd8544.c")
4547
else()
4648
message(WARNING "LVGL ESP32 drivers: Display controller not defined.")
4749
endif()

lvgl_helpers.h

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ extern "C" {
7676
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
7777
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
7878
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
79+
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
80+
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8))
7981
#else
8082
#error "No display controller selected"
8183
#endif

lvgl_spi_conf.h

+2
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ extern "C" {
166166
#define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000)
167167
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
168168
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
169+
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
170+
#define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000)
169171
#else
170172
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
171173
#endif

lvgl_tft/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ menu "LVGL TFT Display controller"
174174
help
175175
ILI9163C display controller.
176176

177+
config LV_TFT_DISPLAY_CONTROLLER_PCD8544
178+
bool
179+
help
180+
PCD8544 display controller (Nokia 3110/5110)
177181
# Display controller communication protocol
178182
#
179183
# This symbols define the communication protocol used by the
@@ -340,6 +344,11 @@ menu "LVGL TFT Display controller"
340344
bool "ILI9163C"
341345
select LV_TFT_DISPLAY_CONTROLLER_ILI9163C
342346
select LV_TFT_DISPLAY_PROTOCOL_SPI
347+
config LV_TFT_DISPLAY_USER_CONTROLLER_PCD8544
348+
bool "PCD8544"
349+
select LV_TFT_DISPLAY_CONTROLLER_PCD8544
350+
select LV_TFT_DISPLAY_PROTOCOL_SPI
351+
select LV_TFT_DISPLAY_MONOCHROME
343352
endchoice
344353

345354
config CUSTOM_DISPLAY_BUFFER_SIZE

lvgl_tft/disp_driver.c

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ void *disp_driver_init(void)
4343
uc8151d_init();
4444
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
4545
ili9163c_init();
46+
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
47+
pcd8544_init();
4648
#endif
4749

4850
// We still use menuconfig for these settings
@@ -107,6 +109,8 @@ void disp_driver_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t *
107109
uc8151d_lv_fb_flush(drv, area, color_map);
108110
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
109111
ili9163c_flush(drv, area, color_map);
112+
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
113+
pcd8544_flush(drv, area, color_map);
110114
#endif
111115
}
112116

@@ -122,6 +126,8 @@ void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area)
122126
jd79653a_lv_rounder_cb(disp_drv, area);
123127
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
124128
uc8151d_lv_rounder_cb(disp_drv, area);
129+
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
130+
pcd8544_rounder(disp_drv, area);
125131
#endif
126132
}
127133

@@ -138,5 +144,7 @@ void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_
138144
jd79653a_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
139145
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
140146
uc8151d_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
147+
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
148+
pcd8544_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
141149
#endif
142150
}

lvgl_tft/disp_driver.h

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ extern "C" {
5252
#include "uc8151d.h"
5353
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
5454
#include "ili9163c.h"
55+
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
56+
#include "pcd8544.h"
5557
#endif
5658

5759
/*********************

lvgl_tft/pcd8544.c

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* @file pcd8544.c
3+
*
4+
* Roughly based on:
5+
* https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library
6+
* https://github.com/olikraus/u8g2
7+
*/
8+
9+
#include "disp_spi.h"
10+
#include "driver/gpio.h"
11+
12+
#include <esp_log.h>
13+
#include "freertos/FreeRTOS.h"
14+
#include "freertos/task.h"
15+
16+
#include "pcd8544.h"
17+
18+
#define TAG "lv_pcd8544"
19+
20+
/**********************
21+
* MACROS
22+
**********************/
23+
24+
#define BIT_SET(a,b) ((a) |= (1U<<(b)))
25+
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
26+
27+
/**********************
28+
* STATIC FUNCTIONS
29+
**********************/
30+
31+
static void pcd8544_send_cmd(uint8_t cmd)
32+
{
33+
disp_wait_for_pending_transactions();
34+
gpio_set_level(PCD8544_DC, 0); /*Command mode*/
35+
disp_spi_send_data(&cmd, 1);
36+
}
37+
38+
static void pcd8544_send_data(void * data, uint16_t length)
39+
{
40+
disp_wait_for_pending_transactions();
41+
gpio_set_level(PCD8544_DC, 1); /*Data mode*/
42+
disp_spi_send_data(data, length);
43+
}
44+
45+
static void pcd8544_send_colors(void * data, uint16_t length)
46+
{
47+
gpio_set_level(PCD8544_DC, 1); /*Data mode*/
48+
disp_spi_send_colors(data, length);
49+
}
50+
51+
/**********************
52+
* GLOBAL FUNCTIONS
53+
**********************/
54+
55+
void pcd8544_init(void){
56+
57+
// TODO: orientation
58+
59+
// Initialize non-SPI GPIOs
60+
gpio_pad_select_gpio(PCD8544_DC);
61+
gpio_set_direction(PCD8544_DC, GPIO_MODE_OUTPUT);
62+
gpio_pad_select_gpio(PCD8544_RST);
63+
gpio_set_direction(PCD8544_RST, GPIO_MODE_OUTPUT);
64+
65+
// Reset the display
66+
gpio_set_level(PCD8544_RST, 0);
67+
vTaskDelay(100 / portTICK_RATE_MS);
68+
gpio_set_level(PCD8544_RST, 1);
69+
vTaskDelay(100 / portTICK_RATE_MS);
70+
71+
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
72+
pcd8544_send_cmd(0x06); /* temp. control: b10 = 2 */
73+
pcd8544_send_cmd(0x13); /* bias system 1:48 */
74+
pcd8544_send_cmd(0xc0); /* medium Vop = Contrast 0x40 = 64 */
75+
76+
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
77+
pcd8544_send_cmd(0x0c); /* display mode normal */
78+
}
79+
80+
void pcd8544_set_contrast (uint8_t contrast){
81+
if (contrast > 0x7f){
82+
contrast = 0x7f;
83+
}
84+
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
85+
pcd8544_send_cmd(0x80 | contrast); /* medium Vop = Contrast */
86+
}
87+
88+
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area){
89+
uint8_t hor_max = disp_drv->hor_res;
90+
uint8_t ver_max = disp_drv->ver_res;
91+
92+
area->x1 = 0;
93+
area->y1 = 0;
94+
area->x2 = hor_max - 1;
95+
area->y2 = ver_max - 1;
96+
}
97+
98+
void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
99+
lv_color_t color, lv_opa_t opa){
100+
101+
uint8_t set = (color.full == 0) && (LV_OPA_TRANSP != opa);
102+
103+
uint16_t byte_index = x + (( y>>3 ) * buf_w);
104+
uint8_t bit_index = y & 0x7;
105+
106+
if (set) {
107+
BIT_SET(buf[byte_index], bit_index);
108+
} else {
109+
BIT_CLEAR(buf[byte_index], bit_index);
110+
}
111+
}
112+
113+
void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_map){
114+
115+
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
116+
117+
uint8_t * buf = (uint8_t *) color_map;
118+
119+
if ((area->x1 == 0) && (area->y1 == 0) && (area->x2 == (disp_drv->hor_res - 1)) && (area->y2 == (disp_drv->ver_res - 1))){
120+
121+
// optimize flush of complete frame buffer in a single SPI transaction
122+
123+
pcd8544_send_cmd(0x40); /* set Y address */
124+
pcd8544_send_cmd(0x80); /* set X address */
125+
pcd8544_send_colors(buf, disp_drv->hor_res * disp_drv->ver_res / 8);
126+
127+
} else {
128+
129+
// send horizontal tiles
130+
131+
uint16_t bank_start = area->y1 / 8;
132+
uint16_t bank_end = area->y2 / 8;
133+
134+
uint16_t bank;
135+
uint16_t cols_to_update = area->x2 - area->x1 + 1;
136+
for (bank = bank_start ; bank <= bank_end ; bank++ ){
137+
pcd8544_send_cmd(0x40 | bank ); /* set Y address */
138+
pcd8544_send_cmd(0x80 | area->x1 ); /* set X address */
139+
uint16_t offset = bank * disp_drv->hor_res + area->x1;
140+
pcd8544_send_data(&buf[offset], cols_to_update);
141+
}
142+
143+
lv_disp_flush_ready(disp_drv);
144+
145+
}
146+
}

lvgl_tft/pcd8544.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
/**
3+
* @file pcd8544.h
4+
*
5+
*/
6+
7+
#ifndef PCD8544_H
8+
#define PCD8544_H
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
/*********************
15+
* INCLUDES
16+
*********************/
17+
#include <stdbool.h>
18+
19+
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
20+
#include "lvgl.h"
21+
#else
22+
#include "lvgl/lvgl.h"
23+
#endif
24+
25+
/*********************
26+
* DEFINES
27+
*********************/
28+
29+
#define PCD8544_DC CONFIG_LV_DISP_PIN_DC
30+
#define PCD8544_RST CONFIG_LV_DISP_PIN_RST
31+
#define PCD8544_BCKL CONFIG_LV_DISP_PIN_BCKL
32+
33+
/**********************
34+
* TYPEDEFS
35+
**********************/
36+
37+
/**********************
38+
* GLOBAL PROTOTYPES
39+
**********************/
40+
41+
void pcd8544_init(void);
42+
void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
43+
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
44+
void pcd8544_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
45+
lv_color_t color, lv_opa_t opa);
46+
void pcd8544_set_contrast(uint8_t contrast);
47+
48+
/**********************
49+
* MACROS
50+
**********************/
51+
52+
53+
#ifdef __cplusplus
54+
} /* extern "C" */
55+
#endif
56+
57+
#endif /*PCD8544_H*/

0 commit comments

Comments
 (0)