Add PCD8544 driver

This commit is contained in:
Matthias Ringwald 2021-11-14 19:15:09 +01:00 committed by Carlos Diaz
parent b674d2d4f1
commit 37a4d3a4e6
8 changed files with 228 additions and 0 deletions

View file

@ -42,6 +42,8 @@ elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_GC9A01)
list(APPEND SOURCES "lvgl_tft/GC9A01.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C)
list(APPEND SOURCES "lvgl_tft/ili9163c.c")
elseif(CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
list(APPEND SOURCES "lvgl_tft/pcd8544.c")
else()
message(WARNING "LVGL ESP32 drivers: Display controller not defined.")
endif()

View file

@ -76,6 +76,8 @@ extern "C" {
#define DISP_BUF_SIZE ((LV_VER_RES_MAX * LV_VER_RES_MAX) / 8) // 2888 bytes
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * (LV_VER_RES_MAX / 8))
#else
#error "No display controller selected"
#endif

View file

@ -166,6 +166,8 @@ extern "C" {
#define SPI_TFT_CLOCK_SPEED_HZ (40 * 1000 * 1000)
#elif defined(CONFIG_LV_TFT_DISPLAY_CONTROLLER_FT81X)
#define SPI_TFT_CLOCK_SPEED_HZ (32*1000*1000)
#elif defined (CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544)
#define SPI_TFT_CLOCK_SPEED_HZ (4*1000*1000)
#else
#define SPI_TFT_CLOCK_SPEED_HZ (40*1000*1000)
#endif

View file

@ -174,6 +174,10 @@ menu "LVGL TFT Display controller"
help
ILI9163C display controller.
config LV_TFT_DISPLAY_CONTROLLER_PCD8544
bool
help
PCD8544 display controller (Nokia 3110/5110)
# Display controller communication protocol
#
# This symbols define the communication protocol used by the
@ -340,6 +344,11 @@ menu "LVGL TFT Display controller"
bool "ILI9163C"
select LV_TFT_DISPLAY_CONTROLLER_ILI9163C
select LV_TFT_DISPLAY_PROTOCOL_SPI
config LV_TFT_DISPLAY_USER_CONTROLLER_PCD8544
bool "PCD8544"
select LV_TFT_DISPLAY_CONTROLLER_PCD8544
select LV_TFT_DISPLAY_PROTOCOL_SPI
select LV_TFT_DISPLAY_MONOCHROME
endchoice
config CUSTOM_DISPLAY_BUFFER_SIZE

View file

@ -43,6 +43,8 @@ void *disp_driver_init(void)
uc8151d_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_init();
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_init();
#endif
// 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 *
uc8151d_lv_fb_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
ili9163c_flush(drv, area, color_map);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_flush(drv, area, color_map);
#endif
}
@ -122,6 +126,8 @@ void disp_driver_rounder(lv_disp_drv_t * disp_drv, lv_area_t * area)
jd79653a_lv_rounder_cb(disp_drv, area);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
uc8151d_lv_rounder_cb(disp_drv, area);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_rounder(disp_drv, area);
#endif
}
@ -138,5 +144,7 @@ void disp_driver_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_
jd79653a_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D
uc8151d_lv_set_fb_cb(disp_drv, buf, buf_w, x, y, color, opa);
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
pcd8544_set_px_cb(disp_drv, buf, buf_w, x, y, color, opa);
#endif
}

View file

@ -52,6 +52,8 @@ extern "C" {
#include "uc8151d.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9163C
#include "ili9163c.h"
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_PCD8544
#include "pcd8544.h"
#endif
/*********************

146
lvgl_tft/pcd8544.c Normal file
View file

@ -0,0 +1,146 @@
/**
* @file pcd8544.c
*
* Roughly based on:
* https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library
* https://github.com/olikraus/u8g2
*/
#include "disp_spi.h"
#include "driver/gpio.h"
#include <esp_log.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "pcd8544.h"
#define TAG "lv_pcd8544"
/**********************
* MACROS
**********************/
#define BIT_SET(a,b) ((a) |= (1U<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1U<<(b)))
/**********************
* STATIC FUNCTIONS
**********************/
static void pcd8544_send_cmd(uint8_t cmd)
{
disp_wait_for_pending_transactions();
gpio_set_level(PCD8544_DC, 0); /*Command mode*/
disp_spi_send_data(&cmd, 1);
}
static void pcd8544_send_data(void * data, uint16_t length)
{
disp_wait_for_pending_transactions();
gpio_set_level(PCD8544_DC, 1); /*Data mode*/
disp_spi_send_data(data, length);
}
static void pcd8544_send_colors(void * data, uint16_t length)
{
gpio_set_level(PCD8544_DC, 1); /*Data mode*/
disp_spi_send_colors(data, length);
}
/**********************
* GLOBAL FUNCTIONS
**********************/
void pcd8544_init(void){
// TODO: orientation
// Initialize non-SPI GPIOs
gpio_pad_select_gpio(PCD8544_DC);
gpio_set_direction(PCD8544_DC, GPIO_MODE_OUTPUT);
gpio_pad_select_gpio(PCD8544_RST);
gpio_set_direction(PCD8544_RST, GPIO_MODE_OUTPUT);
// Reset the display
gpio_set_level(PCD8544_RST, 0);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(PCD8544_RST, 1);
vTaskDelay(100 / portTICK_RATE_MS);
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(0x06); /* temp. control: b10 = 2 */
pcd8544_send_cmd(0x13); /* bias system 1:48 */
pcd8544_send_cmd(0xc0); /* medium Vop = Contrast 0x40 = 64 */
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
pcd8544_send_cmd(0x0c); /* display mode normal */
}
void pcd8544_set_contrast (uint8_t contrast){
if (contrast > 0x7f){
contrast = 0x7f;
}
pcd8544_send_cmd(0x21); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
pcd8544_send_cmd(0x80 | contrast); /* medium Vop = Contrast */
}
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area){
uint8_t hor_max = disp_drv->hor_res;
uint8_t ver_max = disp_drv->ver_res;
area->x1 = 0;
area->y1 = 0;
area->x2 = hor_max - 1;
area->y2 = ver_max - 1;
}
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,
lv_color_t color, lv_opa_t opa){
uint8_t set = (color.full == 0) && (LV_OPA_TRANSP != opa);
uint16_t byte_index = x + (( y>>3 ) * buf_w);
uint8_t bit_index = y & 0x7;
if (set) {
BIT_SET(buf[byte_index], bit_index);
} else {
BIT_CLEAR(buf[byte_index], bit_index);
}
}
void pcd8544_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_map){
pcd8544_send_cmd(0x20); /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=0) */
uint8_t * buf = (uint8_t *) color_map;
if ((area->x1 == 0) && (area->y1 == 0) && (area->x2 == (disp_drv->hor_res - 1)) && (area->y2 == (disp_drv->ver_res - 1))){
// optimize flush of complete frame buffer in a single SPI transaction
pcd8544_send_cmd(0x40); /* set Y address */
pcd8544_send_cmd(0x80); /* set X address */
pcd8544_send_colors(buf, disp_drv->hor_res * disp_drv->ver_res / 8);
} else {
// send horizontal tiles
uint16_t bank_start = area->y1 / 8;
uint16_t bank_end = area->y2 / 8;
uint16_t bank;
uint16_t cols_to_update = area->x2 - area->x1 + 1;
for (bank = bank_start ; bank <= bank_end ; bank++ ){
pcd8544_send_cmd(0x40 | bank ); /* set Y address */
pcd8544_send_cmd(0x80 | area->x1 ); /* set X address */
uint16_t offset = bank * disp_drv->hor_res + area->x1;
pcd8544_send_data(&buf[offset], cols_to_update);
}
lv_disp_flush_ready(disp_drv);
}
}

57
lvgl_tft/pcd8544.h Normal file
View file

@ -0,0 +1,57 @@
/**
* @file pcd8544.h
*
*/
#ifndef PCD8544_H
#define PCD8544_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <stdbool.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
#define PCD8544_DC CONFIG_LV_DISP_PIN_DC
#define PCD8544_RST CONFIG_LV_DISP_PIN_RST
#define PCD8544_BCKL CONFIG_LV_DISP_PIN_BCKL
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void pcd8544_init(void);
void pcd8544_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map);
void pcd8544_rounder(lv_disp_drv_t * disp_drv, lv_area_t *area);
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,
lv_color_t color, lv_opa_t opa);
void pcd8544_set_contrast(uint8_t contrast);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*PCD8544_H*/