1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

driveres/st7735: add driver based on common lcd driver

This commit is contained in:
Francisco Molina 2021-03-15 14:59:29 +01:00 committed by Alexandre Abadie
parent 8f2fa772e9
commit 827fa976a6
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
10 changed files with 567 additions and 0 deletions

View File

@ -33,6 +33,7 @@ rsource "dsp0401/Kconfig"
rsource "hd44780/Kconfig"
rsource "ili9341/Kconfig"
rsource "lcd/Kconfig"
rsource "st7735/Kconfig"
rsource "touch_dev/Kconfig"
endmenu # Display Device Drivers

View File

@ -244,3 +244,7 @@ ifneq (,$(filter-out netdev_default, $(filter netdev_%,$(USEMODULE))))
USEMODULE += netdev_register
endif
endif
ifneq (,$(filter st7735,$(USEMODULE)))
USEMODULE += lcd
endif

107
drivers/include/st7735.h Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2018 Koen Zandberg
* 2021 Francisco Molina
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_st7735 ST7735 display driver
* @ingroup drivers_display
*
* @brief Driver for the ST7735 display
*
* @{
*
* @file
*
* @author Koen Zandberg <koen@bergzand.net>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* The ST7735 is a generic display driver for small RGB displays. The driver
* implemented here operates over SPI to communicate with the device.
*
* The device requires colors to be send in big endian RGB-565 format. The
* @ref CONFIG_LCD_LE_MODE compile time option can switch this, but only use this
* when strictly necessary. This option will slow down the driver as it
* certainly can't use DMA anymore, every short has to be converted before
* transfer.
*/
#ifndef ST7735_H
#define ST7735_H
#include "lcd.h"
#ifdef MODULE_DISP_DEV
#include "disp_dev.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ST7735 gvdd level.
*
* Default GVDD voltage of 4.8V. GVDD is reference level for the VCOM level and
* the grayscale voltage level. GVDD should be (AVDD - 0.5) V .
*/
#ifndef CONFIG_ST7735_GVDD
#define CONFIG_ST7735_GVDD 4800
#endif
/**
* @brief ST7735 VCOMH voltage level.
*
* Default VCOMH voltage of 4.25V. VCOMH represents the high level of VCOM AC
* voltage. VCOM levels needs to be adjusted to match the capacitance and
* performance specifications of the TFT panel to maximize contrast and minimize
* flickering.
*/
#ifndef CONFIG_ST7735_VCOMH
#define CONFIG_ST7735_VCOMH 4250
#endif
/**
* @brief ST7735 VCOML voltage level.
*
* Default VCOML voltage of -2V. VCOML represents the low level of VCOM AC
* voltage. VCOM levels needs to be adjusted to match the capacitance and
* performance specifications of the TFT panel to maximize contrast and minimize
* flickering
*/
#ifndef CONFIG_ST7735_VCOML
#define CONFIG_ST7735_VCOML -2000
#endif
/**
* @brief Device descriptor for a st7735
*
*/
typedef struct {
lcd_t dev; /**< Pointer to the common lcd device */
} st7735_t;
/**
* @brief Device initialization parameters
*/
typedef struct {
lcd_params_t params; /**< LCD struct params */
uint8_t offset_x; /**< LCD offset to apply on x axis. */
uint8_t offset_y; /**< LCD offset to apply on y axis. */
} st7735_params_t;
/**
* @brief LCD device operations table
*/
extern const lcd_driver_t lcd_st7735_driver;
#ifdef __cplusplus
}
#endif
#endif /* ST7735_H */
/** @} */

53
drivers/st7735/Kconfig Normal file
View File

@ -0,0 +1,53 @@
# Copyright (c) 2020 HAW Hamburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#
config MODULE_ST7735
bool "ST7735 display driver"
depends on HAS_PERIPH_SPI
depends on HAS_PERIPH_GPIO
depends on TEST_KCONFIG
select MODULE_PERIPH_SPI
select MODULE_PERIPH_GPIO
select MODULE_LCD
select MODULE_ZTIMER
select MODULE_ZTIMER_MSEC
menuconfig KCONFIG_USEMODULE_ST7735
bool "Configure ST7735 driver"
depends on USEMODULE_ST7735
help
Configure the ST7735 display driver using Kconfig.
if KCONFIG_USEMODULE_ST7735
config ST7735_GVDD
int "GVDD voltage level (in millivolts)"
default 4800
range 3000 6000
help
Configure GVDD level, which is a reference level for the VCOM level and
the grayscale voltage level. GVDD should be ≦ (AVDD - 0.5) V .
config ST7735_VCOMH
int "VCOMH voltage level (in millivolts)"
default 4250
range 2700 5875
help
Configure the high level of VCOM AC voltage. VCOM needs to be adjusted
to match the capacitance and performance specifications of the TFT panel
to maximize contrast and minimize flickering
config ST7735_VCOML
int "VCOML voltage level (in millivolts)"
default -2000
range -2500 0
help
Configure the low level of VCOM AC voltage. VCOM needs to be adjusted to
match the capacitance and performance specifications of the TFT panel to
maximize contrast and minimize flickering
endif # KCONFIG_USEMODULE_ST7735

1
drivers/st7735/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,5 @@
FEATURES_REQUIRED += periph_spi
FEATURES_REQUIRED += periph_gpio
USEMODULE += lcd
USEMODULE += ztimer
USEMODULE += ztimer_msec

View File

@ -0,0 +1,2 @@
USEMODULE_INCLUDES_st7735 := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_st7735)

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2018 Koen Zandberg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_st7735
* @{
*
* @file
* @brief Device driver implementation for the st7735 display controller
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#ifndef ST7735_INTERNAL_H
#define ST7735_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lcd_internal.h"
/**
* @name LCD ST7735 commands
*
* LCD commands extension available for st7735 LCD controllers
* @{
*/
#define LCD_CMD_INVCTR 0xb4 /**< Display Inversion Control */
#define LCD_CMD_PWCTRL3 0xc2 /**< Power control 3 */
#define LCD_CMD_PWCTRL4 0xc3 /**< Power control 4 */
#define LCD_CMD_PWCTRL5 0xc4 /**< Power control 5 */
#define LCD_CMD_PWCTRL6 0xfc /**< Power control 6 */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ST7735_INTERNAL_H */

View File

@ -0,0 +1,129 @@
/*
* Copyright (C) 2018 Koen Zandberg <koen@bergzand.net>
* 2021 Francisco Molina
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_st7735
*
* @{
* @file
* @brief Default configuration for st7735
*
* @author Koen Zandberg <koen@bergzand.net>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef ST7735_PARAMS_H
#define ST7735_PARAMS_H
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Default parameters for ST7735 display */
/**
* @name Set default configuration parameters for the ST7735
* @{
*/
#ifndef ST7735_PARAM_SPI
#define ST7735_PARAM_SPI SPI_DEV(0) /**< SPI device */
#endif
#ifndef ST7735_PARAM_SPI_CLK
#define ST7735_PARAM_SPI_CLK SPI_CLK_5MHZ /**< SPI clock frequency */
#endif
#ifndef ST7735_PARAM_CS
#define ST7735_PARAM_CS GPIO_PIN(2, 2) /**< Chip Select pin */
#endif
#ifndef ST7735_PARAM_DCX
#define ST7735_PARAM_DCX GPIO_PIN(3, 13) /**< DCX pin */
#endif
#ifndef ST7735_PARAM_RST
#define ST7735_PARAM_RST GPIO_UNDEF /**< Reset pin */
#endif
#ifndef ST7735_PARAM_SPI_MODE
#define ST7735_PARAM_SPI_MODE SPI_MODE_0 /**< SPI mode */
#endif
#ifndef ST7735_PARAM_RGB
#define ST7735_PARAM_RGB 0 /**< RGB mode enable */
#endif
#ifndef ST7735_PARAM_INVERTED
#define ST7735_PARAM_INVERTED 0 /**< Inverted mode enable */
#endif
#ifndef ST7735_PARAM_NUM_LINES
#define ST7735_PARAM_NUM_LINES 160U /**< Number of lines */
#endif
#ifndef ST7735_PARAM_RGB_CHANNELS
#define ST7735_PARAM_RGB_CHANNELS 128U /**< Number of RGB channels (e.g. columns) */
#endif
#ifndef ST7735_OFFSET_X
#define ST7735_OFFSET_X 0 /**< Horizontal offset */
#endif
#ifndef ST7735_OFFSET_Y
#define ST7735_OFFSET_Y 0 /**< Vertival offset */
#endif
/**
* @brief Default params
*/
#ifndef ST7735_PARAMS
#define ST7735_PARAMS { .params.spi = ST7735_PARAM_SPI, \
.params.spi_clk = ST7735_PARAM_SPI_CLK, \
.params.spi_mode = ST7735_PARAM_SPI_MODE, \
.params.cs_pin = ST7735_PARAM_CS, \
.params.dcx_pin = ST7735_PARAM_DCX, \
.params.rst_pin = ST7735_PARAM_RST, \
.params.rgb = ST7735_PARAM_RGB, \
.params.inverted = ST7735_PARAM_INVERTED, \
.params.lines = ST7735_PARAM_NUM_LINES, \
.params.rgb_channels = ST7735_PARAM_RGB_CHANNELS, \
.offset_x = ST7735_OFFSET_X, \
.offset_y = ST7735_OFFSET_Y, \
}
#endif
/** @} */
/**
* @brief Default screen identifiers
*/
#ifndef ST7735_PARAM_SCREEN_IDS
#define ST7735_PARAM_SCREEN_IDS 0
#endif
/**
* @brief Configure LCD
*/
static const st7735_params_t st7735_params[] =
{
ST7735_PARAMS,
};
/**
* @brief Configure screen identifiers
*/
static const uint8_t st7735_screen_ids[] =
{
ST7735_PARAM_SCREEN_IDS,
};
/**
* @brief Define the number of configured displays
*/
#define ST7735_NUMOF ARRAY_SIZE(st7735_params)
/**
* @brief Define the number screens this display driver is attached to
*/
#define ST7735_SCREEN_NUMOF ARRAY_SIZE(st7735_screen_ids)
#ifdef __cplusplus
}
#endif
#endif /* ST7735_PARAMS_H */
/** @} */

218
drivers/st7735/st7735.c Normal file
View File

@ -0,0 +1,218 @@
/*
* Copyright (C) 2018 Koen Zandberg
* 2021 Francisco Molina
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_st7735
* @{
*
* @file
* @brief Device driver implementation for the st7735 display controller
*
* @author Koen Zandberg <koen@bergzand.net>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#include <assert.h>
#include <string.h>
#include "byteorder.h"
#include "periph/spi.h"
#include "ztimer.h"
#include "kernel_defines.h"
#include "st7735.h"
#include "st7735_internal.h"
#include "lcd.h"
#include "lcd_internal.h"
#define ENABLE_DEBUG 0
#include "debug.h"
static void _write_cmd(const lcd_t *dev, uint8_t cmd, const uint8_t *data,
size_t len)
{
gpio_clear(dev->params->dcx_pin);
spi_transfer_byte(dev->params->spi, dev->params->cs_pin, len ? true : false, cmd);
gpio_set(dev->params->dcx_pin);
if (len) {
spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, data,
NULL, len);
}
}
/* datasheet page 178, table converted to equation.
* gvdd in 1mv increments: 4850 = 4.85V */
static uint8_t _st7735_calc_pwrctl1(uint16_t gvdd)
{
return (gvdd - 2850) / 50;
}
static uint8_t _st7735_calc_vmh(uint16_t vcomh)
{
return (vcomh - 2700) / 25;
}
static uint8_t _st7735_calc_vml(int16_t vcoml)
{
return (vcoml + 2500) / 25;
}
static int _init(lcd_t *dev, const lcd_params_t *params)
{
assert(params->lines <= 162);
dev->params = params;
uint8_t command_params[4] = { 0 };
gpio_init(dev->params->dcx_pin, GPIO_OUT);
int res = spi_init_cs(dev->params->spi, dev->params->cs_pin);
if (res != SPI_OK) {
DEBUG("[st7735] init: error initializing the CS pin [%i]\n", res);
return -1;
}
if (gpio_is_valid(dev->params->rst_pin)) {
gpio_init(dev->params->rst_pin, GPIO_OUT);
gpio_clear(dev->params->rst_pin);
ztimer_sleep(ZTIMER_MSEC, 120);
gpio_set(dev->params->rst_pin);
}
ztimer_sleep(ZTIMER_MSEC, 120);
/* Acquire once at release at the end */
spi_acquire(dev->params->spi, dev->params->cs_pin, dev->params->spi_mode,
dev->params->spi_clk);
/* Soft Reset */
_write_cmd(dev, LCD_CMD_SWRESET, NULL, 0);
ztimer_sleep(ZTIMER_MSEC, 120);
/* Display off */
_write_cmd(dev, LCD_CMD_DISPOFF, NULL, 0);
/* PWRCTL1 */
command_params[0] = _st7735_calc_pwrctl1(CONFIG_ST7735_GVDD);
_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 1);
/* PWCTR2 VGH = 14.7V, VGL = -7.35V */
command_params[0] = 0x01;
command_params[1] = 0x05;
_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 2);
/* PWCTR3 Opamp current small, Boost frequency */
command_params[0] = 0x02;
command_params[1] = 0x01;
command_params[2] = 0x02;
_write_cmd(dev, LCD_CMD_PWCTRL3, command_params, 3);
/* PWCTR6 */
command_params[0] = 0x02;
command_params[1] = 0x11;
command_params[2] = 0x15;
_write_cmd(dev, LCD_CMD_PWCTRL6, command_params, 3);
/* No display Inversion , Line inversion */
command_params[0] = 0x07;
_write_cmd(dev, LCD_CMD_INVCTR, command_params, 1);
/* VCOMCTL */
command_params[0] = _st7735_calc_vmh(CONFIG_ST7735_VCOMH);
command_params[1] = _st7735_calc_vml(CONFIG_ST7735_VCOML);
_write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 2);
command_params[0] = 0x86;
_write_cmd(dev, LCD_CMD_VMCTRL2, command_params, 1);
/* Memory access CTL */
command_params[0] = LCD_MADCTL_MY | LCD_MADCTL_MV;
command_params[0] |= dev->params->rgb ? 0 : LCD_MADCTL_BGR;
_write_cmd(dev, LCD_CMD_MADCTL, command_params, 1);
/* Frame control */
command_params[0] = 0x00;
command_params[1] = 0x18;
_write_cmd(dev, LCD_CMD_FRAMECTL1, command_params, 2);
/* Display function control */
command_params[0] = 0x08;
command_params[1] = 0x82;
/* number of lines, see datasheet p. 166 (DISCTRL::NL) */
command_params[2] = (params->lines >> 3) - 1;
_write_cmd(dev, LCD_CMD_DFUNC, command_params, 3);
/* Pixel format */
command_params[0] = 0x55; /* 16 bit mode */
_write_cmd(dev, LCD_CMD_PIXSET, command_params, 1);
command_params[0] = 0x01;
_write_cmd(dev, LCD_CMD_GAMSET, command_params, 1);
/* Gamma correction */
{
static const uint8_t gamma_pos[] = {
0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d,
0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10
};
_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos,
sizeof(gamma_pos));
}
{
static const uint8_t gamma_neg[] = {
0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D,
0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10
};
_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg,
sizeof(gamma_neg));
}
if (dev->params->inverted) {
_write_cmd(dev, LCD_CMD_DINVON, NULL, 0);
}
/* Sleep out (turn off sleep mode) */
_write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0);
/* Normal display mode on */
_write_cmd(dev, LCD_CMD_NORON, NULL, 0);
ztimer_sleep(ZTIMER_MSEC, 1);
/* Display on */
_write_cmd(dev, LCD_CMD_DISPON, NULL, 0);
spi_release(dev->params->spi);
return 0;
}
static void _set_area(const lcd_t *dev, uint16_t x1, uint16_t x2,
uint16_t y1, uint16_t y2)
{
st7735_params_t *st7735_params = (st7735_params_t *)dev->params;
be_uint16_t params[2];
x1 += st7735_params->offset_x;
x2 += st7735_params->offset_x;
y1 += st7735_params->offset_y;
y2 += st7735_params->offset_y;
params[0] = byteorder_htons(x1);
params[1] = byteorder_htons(x2);
_write_cmd(dev, LCD_CMD_CASET, (uint8_t *)params,
sizeof(params));
params[0] = byteorder_htons(y1);
params[1] = byteorder_htons(y2);
_write_cmd(dev, LCD_CMD_PASET, (uint8_t *)params,
sizeof(params));
}
const lcd_driver_t lcd_st7735_driver = {
.init = _init,
.set_area = _set_area,
};