mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/st77xx: fix initialization sequences fror ST77xx
This commit is contained in:
parent
85c7bd937c
commit
9447f59d59
@ -53,6 +53,273 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 Customized Configuration Enable
|
||||
*
|
||||
* Define CONFIG_ST7735_CUSTOM_CONFIG=1 to use customized voltage
|
||||
* configurations. Otherwise ST7735 is using reset defaults.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_CUSTOM_CONFIG
|
||||
#define CONFIG_ST7735_CUSTOM_CONFIG 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 AVDD voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 4.9V is used for AVDD.
|
||||
* Valid values must be in the range of 4500 (4.5V) to 5100 (5.1V)
|
||||
* in steps of 100.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_AVDD
|
||||
#define CONFIG_ST7735_AVDD 4900
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 GVDD voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 4.6V is used for GVDD (gamma reference positive voltage).
|
||||
* Valid values must be in the range of 3150 (3.15V) to 4700 (4.7V)
|
||||
* in steps of 50.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_GVDD
|
||||
#define CONFIG_ST7735_GVDD 4600
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 GVL voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of -4.6V is used for GVCL (gamma reference negative voltage).
|
||||
* Valid values must be in the range of -4700 (-4.7V) to -3150 (-3.15V)
|
||||
* in steps of 50.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_GVCL
|
||||
#define CONFIG_ST7735_GVCL -4600
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 VCOM voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of -0.425V is used for VCOM. VCOM needs to be adjusted
|
||||
* to match the capacitance and performance specifications of the TFT panel
|
||||
* to maximize contrast and minimize flickering.
|
||||
* Valid values must be in the range of -2000 (-2.0V) to -425 (-0.425V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_VCOM
|
||||
#define CONFIG_ST7735_VCOM -775
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 VGH voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 14.7V is used for VGH, the high voltage for gate drivers.
|
||||
* Valid values must be in the range of 10000 (10V) to 15000 (15V) and
|
||||
* in the range of (2 * AVDD + 2.1V) and (3 * AVDD + 2.4 V).
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_VGH
|
||||
#define CONFIG_ST7735_VGH 14700
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7735 VGL voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of -10V is used for VGL, the low voltage for gate drivers.
|
||||
* Valid values must be in the range of -13000 (-13V) to -7500 (-7.5V)
|
||||
* in steps of 2500.
|
||||
*/
|
||||
#ifndef CONFIG_ST7735_VGL
|
||||
#define CONFIG_ST7735_VGL -10000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 Customized Configuration Enable
|
||||
*
|
||||
* Define CONFIG_ST7789_CUSTOM_CONFIG=1 to use customized voltage
|
||||
* configurations. Otherwise ST7735 is using reset defaults.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_CUSTOM_CONFIG
|
||||
#define CONFIG_ST7789_CUSTOM_CONFIG 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 AVDD voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 6.8V is used for AVDD.
|
||||
* Valid values must be in the range of 6400 (6.4V) to 6800 (6.8V)
|
||||
* in steps of 100.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_AVDD
|
||||
#define CONFIG_ST7789_AVDD 6800
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 AVCL voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of -4.8V is used for AVCL.
|
||||
* Valid values must be in the range of -5000 (-5.0V) to -4400 (-4.4V)
|
||||
* in steps of 100.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_AVCL
|
||||
#define CONFIG_ST7789_AVCL -4800
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 VCOM voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 0.9V is used for VCOM. VCOM needs to be adjusted
|
||||
* to match the capacitance and performance specifications of the TFT panel
|
||||
* to maximize contrast and minimize flickering. VCOM is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET + (0.5 * VDV)
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET - (0.5 * VDV)
|
||||
*
|
||||
* Valid values must be in the range of 100 (0.1V) to 1675 (1.675V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_VCOM
|
||||
#define CONFIG_ST7789_VCOM 900
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 VCOM voltage offset (in millivolts)
|
||||
*
|
||||
* A default voltage of 0V is used for VCOM voltage offset (VCOM_OFFSET).
|
||||
* VCOM_OFFSET is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET + (0.5 * VDV)
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET - (0.5 * VDV)
|
||||
*
|
||||
* Valid values must be in the range of -800 (-0.8V) to 775 (0.775V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_VCOM_OFFSET
|
||||
#define CONFIG_ST7789_VCOM_OFFSET 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 VDV voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 0V is used for VDV. VDV is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET + (0.5 * VDV)
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET - (0.5 * VDV)
|
||||
*
|
||||
* Valid values must be in the range of -800 (-0.8V) to 775 (0.775V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_VDV
|
||||
#define CONFIG_ST7789_VDV 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7789 VRH voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 4.1V is used for VRH. VRH is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET + (0.5 * VDV)
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET - (0.5 * VDV)
|
||||
*
|
||||
* Valid values must be in the range of 3350 (3.35V) to 5500 (5.5V)
|
||||
* in steps of 50.
|
||||
*/
|
||||
#ifndef CONFIG_ST7789_VRH
|
||||
#define CONFIG_ST7789_VRH 4100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 Customized Configuration Enable
|
||||
*
|
||||
* Define CONFIG_ST7796_CUSTOM_CONFIG=1 to use customized voltage
|
||||
* configurations. Otherwise ST7735 is using reset defaults.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_CUSTOM_CONFIG
|
||||
#define CONFIG_ST7796_CUSTOM_CONFIG 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 AVDD voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 6.6V is used for AVDD.
|
||||
* Valid values must be in the range of 6200 (6.2V) to 6800 (6.8V)
|
||||
* in steps of 100.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_AVDD
|
||||
#define CONFIG_ST7796_AVDD 6600
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 AVCL voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of -4.4V is used for AVCL.
|
||||
* Valid values must be in the range of -5000 (-5.0V) to -4400 (-4.4V)
|
||||
* in steps of 100.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_AVCL
|
||||
#define CONFIG_ST7796_AVCL -4400
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 VCOM voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 1.0V is used for VCOM. VCOM needs to be adjusted
|
||||
* to match the capacitance and performance specifications of the TFT panel
|
||||
* to maximize contrast and minimize flickering. VCOM is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET
|
||||
*
|
||||
* Valid values must be in the range of 100 (0.1V) to 1875 (1.875V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_VCOM
|
||||
#define CONFIG_ST7796_VCOM 1000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 VCOM voltage offset (in millivolts)
|
||||
*
|
||||
* A default voltage of 0V is used for VCOM voltage offset (VCOM_OFFSET).
|
||||
* VCOM_OFFSET is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET
|
||||
*
|
||||
* Valid values must be in the range of -800 (-0.8V) to 775 (0.775V)
|
||||
* in steps of 25.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_VCOM_OFFSET
|
||||
#define CONFIG_ST7796_VCOM_OFFSET 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ST7796 VRH voltage (in millivolts)
|
||||
*
|
||||
* A default voltage of 4.1V is used for VRH. VRH is used to derive
|
||||
* the GVDD (gamma reference positive voltage) and
|
||||
* the GVCL (gamma reference negative voltage) as follows:
|
||||
*
|
||||
* GDDV = +VRH + VCOM + VCOM_OFFSET
|
||||
* GVCL = -VRH + VCOM + VCOM_OFFSET
|
||||
*
|
||||
* Valid values must be in the range of 3350 (3.35V) to 5500 (5.5V)
|
||||
* in steps of 50.
|
||||
*/
|
||||
#ifndef CONFIG_ST7796_VRH
|
||||
#define CONFIG_ST7796_VRH 4100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name ST77xx display rotation modes
|
||||
* @{
|
||||
|
@ -51,6 +51,9 @@ extern "C" {
|
||||
#define LCD_CMD_MADCTL 0x36 /**< Memory data access control */
|
||||
#define LCD_CMD_IDMOFF 0x38 /**< Idle Mode OFF */
|
||||
#define LCD_CMD_IDMON 0x39 /**< Idle Mode ON */
|
||||
#define LCD_CMD_TEOFF 0x34 /**< Tearing Effect Line Off */
|
||||
#define LCD_CMD_TEON 0x35 /**< Tearing Effect Line On */
|
||||
#define LCD_CMD_COLMOD 0x3A /**< Interface Pixel Format Set */
|
||||
#define LCD_CMD_PIXSET 0x3A /**< COLMOD: Pixel Format Set */
|
||||
#define LCD_CMD_WRDISBV 0x51 /**< Write Display Brightness */
|
||||
#define LCD_CMD_WRCTRLD 0x53 /**< Write Control Display */
|
||||
|
@ -1 +1,15 @@
|
||||
SRC = st77xx.c
|
||||
|
||||
ifneq (,$(filter st7735,$(USEMODULE)))
|
||||
SRC += st7735_init.c
|
||||
endif
|
||||
|
||||
ifneq (,$(filter st7789,$(USEMODULE)))
|
||||
SRC += st7789_init.c
|
||||
endif
|
||||
|
||||
ifneq (,$(filter st7796,$(USEMODULE)))
|
||||
SRC += st7796_init.c
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
54
drivers/st77xx/include/st7735_internal.h
Normal file
54
drivers/st77xx/include/st7735_internal.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Koen Zandberg
|
||||
* 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Specific internal definitions for the ST7735 controller variant
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef ST7735_INTERNAL_H
|
||||
#define ST7735_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "st77xx_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 */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief ST7735 controller specific initialization part
|
||||
*/
|
||||
int st7735_init(lcd_t *dev, const lcd_params_t *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ST7735_INTERNAL_H */
|
61
drivers/st77xx/include/st7789_internal.h
Normal file
61
drivers/st77xx/include/st7789_internal.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Koen Zandberg
|
||||
* 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Specific internal definitions for the ST7789 controller variant
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef ST7789_INTERNAL_H
|
||||
#define ST7789_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "st77xx_internal.h"
|
||||
|
||||
/**
|
||||
* @name LCD ST7789 commands
|
||||
*
|
||||
* LCD commands extension available for ST7789 LCD controllers
|
||||
* @{
|
||||
*/
|
||||
#define LCD_CMD_RAMWRC 0x3c /**< Memory Write Continue */
|
||||
#define LCD_CMD_RAMRDC 0x3e /**< Memory Read Continue */
|
||||
#define LCD_CMD_PORCTRL 0xb2 /**< Porch Control */
|
||||
#define LCD_CMD_GCTRL 0xb7 /**< Gate Control */
|
||||
#define LCD_CMD_VCOMS 0xbb /**< VCOM Setting */
|
||||
#define LCD_CMD_LCMCTRL 0xc0 /**< LCM Control */
|
||||
#define LCD_CMD_VDVVRHEN 0xc2 /**< VDV and VRH Command Enable */
|
||||
#define LCD_CMD_VRHS 0xc3 /**< VRH Set */
|
||||
#define LCD_CMD_VDVS 0xc4 /**< VDV Set */
|
||||
#define LCD_CMD_VCMOFSET 0xc4 /**< VCOM Offset Set */
|
||||
#define LCD_CMD_FRCTRL2 0xc6 /**< Frame Rate Control in Normal Mode */
|
||||
#define LCD_CMD_PWCTRL1X 0xd0 /**< Power Control 1 */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief ST7789 controller specific initialization part
|
||||
*/
|
||||
int st7789_init(lcd_t *dev, const lcd_params_t *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ST7789_INTERNAL_H */
|
51
drivers/st77xx/include/st7796_internal.h
Normal file
51
drivers/st77xx/include/st7796_internal.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Koen Zandberg
|
||||
* 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Specific internal definitions for the ST7789 controller variant
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef ST7796_INTERNAL_H
|
||||
#define ST7796_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "st77xx_internal.h"
|
||||
|
||||
/**
|
||||
* @name LCD ST7796 commands
|
||||
*
|
||||
* LCD commands extension available for ST7796 LCD controllers
|
||||
* @{
|
||||
*/
|
||||
#define LCD_CMD_VCMPCTL 0xc5 /**< VCOM Control */
|
||||
#define LCD_CMD_VCM 0xc6 /**< VCOM Offset */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief ST7796 controller specific initialization part
|
||||
*/
|
||||
int st7796_init(lcd_t *dev, const lcd_params_t *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ST7796_INTERNAL_H */
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Koen Zandberg
|
||||
* 2023 Gunar Schorcht
|
||||
*
|
||||
* 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
|
||||
@ -11,9 +12,10 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for the ST77xx display controller
|
||||
* @brief Internal definitions that are common for all ST77xx controllers
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
261
drivers/st77xx/st7735_init.c
Normal file
261
drivers/st77xx/st7735_init.c
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Controller specific initialization for ST7735
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* This file is only compiled if the `st7735` module is enabled.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "kernel_defines.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "st77xx.h"
|
||||
#include "st7735_internal.h"
|
||||
#include "lcd.h"
|
||||
#include "lcd_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if CONFIG_ST7735_CUSTOM_CONFIG
|
||||
/* avdd in mV with in 100 mV steps: 4600 = 4.6V
|
||||
* Datasheet page 130:
|
||||
*
|
||||
* y = 0 for avdd < 4500 (< 4.5V)
|
||||
* y = (5100 - avdd) / 100 for avdd = 4500 to 5100 (4.5V to 5.1V)
|
||||
* y = 6 for avdd > 5100 (> 5.1V)
|
||||
*
|
||||
* default value after reset is 4.9 V (0x04)
|
||||
*/
|
||||
static inline uint8_t _st7735_calc_avdd(uint16_t avdd)
|
||||
{
|
||||
assert((avdd >= 4500) && (avdd <= 5100));
|
||||
assert((avdd % 100) == 0);
|
||||
|
||||
return (5100 - avdd) / 100;
|
||||
}
|
||||
|
||||
/* gvdd in mV with 50 mV increments: 4650 = 4.65V
|
||||
* Datasheet page 130:
|
||||
*
|
||||
* y = 31 for gddv < 3150 (< 3.15V)
|
||||
* y = 31 - ((gddv - 3150) / 50) for gddv = 3150 to 4700 (3.15V to 4.7V)
|
||||
* y = 0 for gddv > 4700 (> 4.7V)
|
||||
*
|
||||
* default value after reset is 4.6 V (0x02)
|
||||
*/
|
||||
static inline uint8_t _st7735_calc_gvdd(uint16_t gvdd)
|
||||
{
|
||||
assert((gvdd >= 3150) && (gvdd <= 4700));
|
||||
assert((gvdd % 50) == 0);
|
||||
|
||||
return 31 - ((gvdd - 3150) / 50);
|
||||
}
|
||||
|
||||
/* gvcl in mV with 50 mV increments: -4650 = -4.65V
|
||||
* Datasheet page 130:
|
||||
*
|
||||
* y = 0 for gdcl < -4700 (< -4.7V)
|
||||
* y = 31 - (-3150 - gvcl) / 50) for gddv = -4700 to -3150 (-4.7V to -3.15V)
|
||||
* y = 31 for gddv > -3150 (> -3.15V)
|
||||
*
|
||||
* default value after reset is -4.6 V (0x02)
|
||||
*/
|
||||
static inline uint8_t _st7735_calc_gvcl(int16_t gvcl)
|
||||
{
|
||||
assert((gvcl >= -4700) && (gvcl <= -3150));
|
||||
assert((gvcl % 50) == 0);
|
||||
|
||||
return 31 - ((-3150 - gvcl) / 50);
|
||||
}
|
||||
|
||||
/* vcom in mV with 25 mV increments: -625 = -0.625V
|
||||
* Datasheet page 140:
|
||||
*
|
||||
* y = 63 for vcom < -2000 (> 2V)
|
||||
* y = 63 - ((2000 + vcom) / 25) for vcom = -2000 to -425 (-2V to -0.425V)
|
||||
* y = 0 for vcom > -425 (< -0.425V)
|
||||
*
|
||||
* default value after reset is 4.9 V (4)
|
||||
*/
|
||||
static inline uint8_t _st7735_calc_vcom(int16_t vcom)
|
||||
{
|
||||
assert((vcom >= -2000) && (vcom <= 425));
|
||||
assert((vcom % 25) == 0);
|
||||
|
||||
return 63 - ((2000 + vcom) / 25);
|
||||
}
|
||||
|
||||
/* vgh in mV with 100 mV increments: 11200 = 11.2V
|
||||
* vgl in mV with 2500 mV increments: 12500 = 12.5V
|
||||
* Datasheet page 132
|
||||
*/
|
||||
static inline uint8_t _st7735_calc_vghl(uint16_t vgh, int16_t vgl, uint16_t avdd)
|
||||
{
|
||||
assert((vgh >= 10000) && (vgh <= 15000));
|
||||
assert((vgl >= -13000) && (vgl <= 7500));
|
||||
assert((vgh >= ((avdd * 2) + 2100)) && (vgh <= ((3 * avdd) + 2400)));
|
||||
|
||||
uint16_t bt = vgh / avdd;
|
||||
uint16_t h25 = 0;
|
||||
assert((bt == 2) || (bt == 3)); /* bt must be either 2 or 3 */
|
||||
|
||||
if ((vgh - (bt * avdd)) > 2100) {
|
||||
/* if there remains an offset of at least 2.1V, use VGH25 */
|
||||
h25 = ((vgh - (bt * avdd)) - 2100) / 100;
|
||||
assert(h25 <= 3);
|
||||
}
|
||||
|
||||
bt -= 2; /* convert (3 * AVDD) to 01b and (2 * AVDD) to 00b */
|
||||
|
||||
if (bt && h25) {
|
||||
/* represents 3 * AVDD + VGH25 */
|
||||
bt++;
|
||||
}
|
||||
else {
|
||||
h25 = 3;
|
||||
}
|
||||
|
||||
uint16_t sel = (vgl < -12500) ? 3 : 2 - ((vgl + 12500) / 2500);
|
||||
|
||||
return (h25 << 6) + (sel << 2) + bt;
|
||||
}
|
||||
#endif /* CONFIG_ST7735_CUSTOM_CONFIG */
|
||||
|
||||
int st7735_init(lcd_t *dev, const lcd_params_t *params)
|
||||
{
|
||||
assert(params->lines <= 162);
|
||||
assert(params->rgb_channels <= 132);
|
||||
|
||||
uint8_t command_params[6] = { 0 };
|
||||
|
||||
/* INVCTR (B4h): Display Inversion Control */
|
||||
command_params[0] = 0x07; /* NLA=1, NLB=1, NLC=1 Line inversion in all modes */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_INVCTR, command_params, 1);
|
||||
|
||||
#if CONFIG_ST7735_CUSTOM_CONFIG
|
||||
|
||||
/* PWCTR1 (C0h): Power Control 1 */
|
||||
command_params[0] = (_st7735_calc_avdd(CONFIG_ST7735_AVDD) << 5) |
|
||||
_st7735_calc_gvdd(CONFIG_ST7735_GVDD);
|
||||
com mand_params[1] = _st7735_calc_gvcl(CONFIG_ST7735_GVCL);
|
||||
command_params[2] = 0x84; /* AUTO mode */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 3);
|
||||
DEBUG("PWCTRL1 (C0h): %02x %02x %02x\n",
|
||||
command_params[0], command_params[1], command_params[2]);
|
||||
|
||||
/* PWCTR2 (C1h): Power Control 2 (== reset defaults) */
|
||||
command_params[0] = _st7735_calc_vghl(CONFIG_ST7735_VGH, CONFIG_ST7735_VGL,
|
||||
CONFIG_ST7735_AVDD);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
|
||||
DEBUG("PWCTRL2 (C1h): %02x\n", command_params[0]);
|
||||
|
||||
/* VMCTR1 (C5h): VCOM Control 1 */
|
||||
command_params[0] = _st7735_calc_vcom(CONFIG_ST7735_VCOM);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 1);
|
||||
DEBUG("VMCTR1 (C5h): %02x\n", command_params[0]);
|
||||
|
||||
#else /* CONFIG_ST7735_CUSTOM_CONFIG */
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* PWCTR1 (C0h): Power Control 1 (== reset defaults) */
|
||||
command_params[0] = 0x82; /* AVDD=4.9V, GVDD=4.6V */
|
||||
command_params[1] = 0x02; /* GVCL=-4.6V */
|
||||
command_params[2] = 0x84; /* AUTO mode */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 3);
|
||||
|
||||
/* PWCTR2 (C1h): Power Control 2 (== reset defaults) */
|
||||
command_params[0] = 0xc5; /* VGH=3*AVDD, VGL=-10V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
|
||||
|
||||
/* VMCTR1 (C5h): VCOM Control 1 (== reset defaults) */
|
||||
command_params[0] = 0x04; /* VCOM=-0.525V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 1);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
#endif /* CONFIG_ST7735_CUSTOM_CONFIG */
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* PWCTR3 (C2h): Power Control 3 Normal Mode (== reset defaults) */
|
||||
command_params[0] = 0x0a; /* AP=Medium Low, SAP=Small */
|
||||
command_params[0] = 0x00; /* DCA=BCLK/1 BCLK/1 BCLK/1 BCLK/1 BCLK/1 */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL3, command_params, 2);
|
||||
|
||||
/* PWCTR4 (C3h): Power Control 4 Idle Mode (== reset defaults) */
|
||||
command_params[0] = 0x8a; /* AP=Medium Low, SAP=Small */
|
||||
command_params[1] = 0x2e; /* DCA=BCLK/2 BCLK/1 BCLK/2 BCLK/4 BCLK/2 */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL4, command_params, 2);
|
||||
|
||||
/* PWCTR5 (C4h): Power Control 5 Partial Mode (== reset defaults) */
|
||||
command_params[0] = 0x8a; /* AP=Medium Low, SAP=Small */
|
||||
command_params[1] = 0xaa; /* DCA=BCLK/2 BCLK/2 BCLK/2 BCLK/2 BCLK/2 */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL5, command_params, 2);
|
||||
|
||||
/* FRMCTRL1 (B1H): Frame Control 1 in Normal mode (== reset defaults) */
|
||||
/* Frame rate = fosc/((RNTA * 2 + 40) x (lines + FPA + BPA)) with fosc = 624 kHz */
|
||||
command_params[0] = 0x01; /* RNTA=1 */
|
||||
command_params[1] = 0x2c; /* FPA (Front Porch) = 44 lines */
|
||||
command_params[2] = 0x2d; /* BPA (Back Porch) = 45 lines */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_FRAMECTL1, command_params, 3);
|
||||
|
||||
/* FRMCTRL2 (B2H): Frame Control 2 in Idle mode (== reset defaults) */
|
||||
/* Frame rate = fosc/((RNTB * 2 + 40) x (lines + FPB + BPB)) with fosc = 624 kHz */
|
||||
command_params[0] = 0x01; /* RNTB=1 */
|
||||
command_params[1] = 0x2c; /* FPB (Front Porch) = 44 lines */
|
||||
command_params[2] = 0x2d; /* BPB (Back Porch) = 45 lines */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_FRAMECTL2, command_params, 3);
|
||||
|
||||
/* FRMCTRL3 (B3H): Frame Control 3 in Partal mode (== reset defaults) */
|
||||
/* Frame rate = fosc/((RNTC * 2 + 40) x (lines + FPC + BPC)) with fosc = 624 kHz */
|
||||
command_params[0] = 0x01; /* RNTC=1 */
|
||||
command_params[1] = 0x2c; /* FPC (Front Porch) = 44 lines */
|
||||
command_params[2] = 0x2d; /* BPC (Back Porch) = 45 lines */
|
||||
command_params[3] = 0x01; /* RNTD=1 */
|
||||
command_params[4] = 0x2c; /* FPD (Front Porch) = 44 lines */
|
||||
command_params[5] = 0x2d; /* BPD (Back Porch) = 45 lines */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_FRAMECTL3, command_params, 6);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* GMCTRP1 (E0h): Gamma +polarity Correction Characteristics Setting */
|
||||
{
|
||||
static const uint8_t gamma_pos[] = {
|
||||
0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d,
|
||||
0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos,
|
||||
sizeof(gamma_pos));
|
||||
}
|
||||
/* GMCTRN1 (E1h): Gamma -polarity Correction Characteristics Setting */
|
||||
{
|
||||
static const uint8_t gamma_neg[] = {
|
||||
0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D,
|
||||
0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg,
|
||||
sizeof(gamma_neg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
245
drivers/st77xx/st7789_init.c
Normal file
245
drivers/st77xx/st7789_init.c
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Controller specific initialization for ST7789
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* This file is only compiled if the `st7789` module is enabled.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "kernel_defines.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "st77xx.h"
|
||||
#include "st7789_internal.h"
|
||||
#include "lcd.h"
|
||||
#include "lcd_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if CONFIG_ST7789_CUSTOM_CONFIG
|
||||
/* avdd in mV with 200 mV increments: 6600 = 6.6V
|
||||
* Datasheet page 289:
|
||||
*
|
||||
* y = 0 for avdd < 6400 (< 6.4V)
|
||||
* y = (avdd - 6400) / 200 for avdd = 6400 to 6800 (6.4 to 6.8V)
|
||||
* y = 2 for avdd > 6800 (> 6.8V)
|
||||
*
|
||||
* default value after reset is 6.8 V (0x02)
|
||||
*/
|
||||
static inline uint8_t _st7789_calc_avdd(int16_t avdd)
|
||||
{
|
||||
assert((avdd >= 6400) && (avdd <= 6800));
|
||||
assert((avdd % 200) == 0);
|
||||
|
||||
return (avdd - 6400) / 200;
|
||||
}
|
||||
|
||||
/* avcl in mV with 200 mV increments: -4800 = -4.8V
|
||||
* Datasheet page 289:
|
||||
*
|
||||
* y = 0 for avcl < -5000 (< -5.0V)
|
||||
* y = 3 - ((avcl + 5000) / 200) for avcl = -5000 to -4400 (-5.0V to -4.4V)
|
||||
* y = 3 for avcl > -4400 (> -4.4V)
|
||||
*
|
||||
* default value after reset is -4.8 V (0x02)
|
||||
*/
|
||||
static inline uint8_t _st7789_calc_avcl(int16_t avcl)
|
||||
{
|
||||
assert((avcl >= -5000) && (avcl <= -4400));
|
||||
assert((avcl % 200) == 0);
|
||||
|
||||
return 3 - ((avcl + 5000) / 200);
|
||||
}
|
||||
|
||||
/* vcom in mV with 25 mV increments: 1325 = 1.325V
|
||||
* Datasheet page 270:
|
||||
*
|
||||
* y = 0 for vcom < 100 (< 0.1V)
|
||||
* y = (vcom - 100) / 25 for vcom = 100 to 1675 (0.1V to 1.675V)
|
||||
* y = 63 for vcom > 1675 (> 1.675V)
|
||||
*
|
||||
* default value after reset is 0.9 V (0x20)
|
||||
*/
|
||||
static inline uint8_t _st7789_calc_vcom(int16_t vcom)
|
||||
{
|
||||
assert((vcom >= 100) && (vcom <= 1675));
|
||||
assert((vcom % 25) == 0);
|
||||
|
||||
return (vcom - 100) / 25;
|
||||
}
|
||||
|
||||
/* vol in mV with 25 mV increments: 100 = 0.1V
|
||||
* Datasheet page 279:
|
||||
*
|
||||
* y = 0 for vol < -800 (< -0.8V)
|
||||
* y = (vol + 800) / 25 for vol = -800 to 775 (-0.8V to 0.775V)
|
||||
* y = 63 for vol > 0.775 (> 0.775V)
|
||||
*
|
||||
* default value after reset is 0 V (0x00)
|
||||
*/
|
||||
static inline uint8_t _st7789_calc_vcom_offset_vdv(int16_t vol)
|
||||
{
|
||||
assert((vol >= -800) && (vol <= 775));
|
||||
assert((vol % 25) == 0);
|
||||
|
||||
return (vol + 800) / 25;
|
||||
}
|
||||
|
||||
/* vrh in mV with 50 mV increments: 4800 = 4.8V
|
||||
* Datasheet page 277:
|
||||
*
|
||||
* y = 0 for vrh < 3550 (< 3.55V)
|
||||
* y = (vrh - 3550) / 50 for vrh = 3550 to 5500 (3.55V to 5.5V)
|
||||
* y = 39 for vrh > 5500 (> -4.4V)
|
||||
*
|
||||
* default value after reset is 4.1 V (0x0b)
|
||||
*/
|
||||
static inline uint8_t _st7789_calc_vrh(int16_t vrh)
|
||||
{
|
||||
assert((vrh >= 3550) && (vrh <= 5500));
|
||||
assert((vrh % 50) == 0);
|
||||
|
||||
return (vrh - 3550) / 50;
|
||||
}
|
||||
#endif /* CONFIG_ST7789_CUSTOM_CONFIG */
|
||||
|
||||
int st7789_init(lcd_t *dev, const lcd_params_t *params)
|
||||
{
|
||||
assert(params->lines <= 320);
|
||||
assert(params->rgb_channels <= 240);
|
||||
|
||||
uint8_t command_params[5] = { 0 };
|
||||
(void)command_params;
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* LCMCTRL (C0h): LCM Control (== reset defaults) */
|
||||
command_params[0] = 0x2c; /* XOR RGB, MX and MH setting in command 36h */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_LCMCTRL, command_params, 1);
|
||||
DEBUG("LCMCTRL (C0h) %02x\n", command_params[0]);
|
||||
|
||||
/* VDVVRHEN (C2h): VDV and VRH Command Enable (== reset defaults) */
|
||||
command_params[0] = 0x01; /* CMDEN=1 (VDV and VDH command write enable */
|
||||
command_params[1] = 0xff;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VDVVRHEN, command_params, 2);
|
||||
DEBUG("VDVVRHEN (C2h) %02x %02x\n", command_params[0], command_params[1]);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
#if CONFIG_ST7789_CUSTOM_CONFIG
|
||||
|
||||
/* VCOMS (BBh): VCOM Setting */
|
||||
command_params[0] = _st7789_calc_vcom(CONFIG_ST7789_VCOM);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCOMS, command_params, 1);
|
||||
DEBUG("VCOMS (BBh) %02x\n", command_params[0]);
|
||||
|
||||
/* VRHS (C3h): VRH Set */
|
||||
command_params[0] = _st7789_calc_vrh(CONFIG_ST7789_VRH);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VRHS, command_params, 1);
|
||||
DEBUG("VRHS (C3h) %02x\n", command_params[0]);
|
||||
|
||||
/* VDVS (C4h): VDV Set */
|
||||
command_params[0] = _st7789_calc_vcom_offset_vdv(CONFIG_ST7789_VDV);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VDVS, command_params, 1);
|
||||
DEBUG("VDVS (C4h) %02x\n", command_params[0]);
|
||||
|
||||
/* VCMOFSET (C5h): VCOM Offset Set */
|
||||
command_params[0] = _st7789_calc_vcom_offset_vdv(CONFIG_ST7789_VCOM_OFFSET);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCMOFSET, command_params, 1);
|
||||
DEBUG("VCMOFSET (C5h) %02x\n", command_params[0]);
|
||||
|
||||
/* PWCTRL1 (D0h): Power Control 1 */
|
||||
command_params[0] = 0xa4;
|
||||
command_params[1] = (_st7789_calc_avdd(CONFIG_ST7789_AVDD) << 6) |
|
||||
(_st7789_calc_avcl(CONFIG_ST7789_AVCL) << 4) | 0x01;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1X, command_params, 2);
|
||||
DEBUG("PWCTRL1 (D0h): %02x %02x\n", command_params[0], command_params[1]);
|
||||
|
||||
#else /* CONFIG_ST7789_CUSTOM_CONFIG */
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* VCOMS (BBh): VCOM Setting (== reset defaults) */
|
||||
command_params[0] = 0x20; /* VCOM=0.9V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCOMS, command_params, 1);
|
||||
|
||||
/* VRHS (C3h): VRH Set (== reset defaults) */
|
||||
command_params[0] = 0x0b; /* VRH=4.1V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VRHS, command_params, 1);
|
||||
|
||||
/* VDVS (C4h): VDV Set (== reset defaults)*/
|
||||
command_params[0] = 0x20; /* VDV=0V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VDVS, command_params, 1);
|
||||
|
||||
/* VCMOFSET (C5h): VCOM Offset Set (== reset defaults) */
|
||||
command_params[0] = 0x20; /* VCOMFS=0V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCMOFSET, command_params, 1);
|
||||
|
||||
/* PWCTRL1 (D0h): Power Control 1 (== reset defaults) */
|
||||
command_params[0] = 0xa4;
|
||||
command_params[1] = 0xa1; /* AVDD=6.8V, AVCL=4.8V, VDS=2.3 */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1X, command_params, 2);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
#endif /* CONFIG_ST7789_CUSTOM_CONFIG */
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* FRCTRL2 (C6h): Frame Rate Control in Normal Mode */
|
||||
command_params[0] = 0x0f; /* == reset default (60 Hz) */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_FRCTRL2, command_params, 1);
|
||||
DEBUG("FRCTRL2 (C6h) %02x\n", command_params[0]);
|
||||
|
||||
/* PORCTRL (B2h): Porch Setting */
|
||||
command_params[0] = 0x0c; /* == reset defaults */
|
||||
command_params[1] = 0x0c;
|
||||
command_params[2] = 0x00;
|
||||
command_params[3] = 0x33;
|
||||
command_params[4] = 0x33;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PORCTRL, command_params, 5);
|
||||
|
||||
/* GCTRL (B7h): Gate Control */
|
||||
command_params[0] = 0x35; /* == reset defaults */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_GCTRL, command_params, 1);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* VGAMCTRL (E0h): Positive Voltage Gamma Control */
|
||||
{
|
||||
static const uint8_t gamma_pos[] = {
|
||||
0xd0, 0x08, 0x11, 0x08, 0x0c, 0x15, 0x39,
|
||||
0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2d
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos, sizeof(gamma_pos));
|
||||
}
|
||||
/* NVGAMCTRL (E1h): Negative Voltage Gamma Control */
|
||||
{
|
||||
static const uint8_t gamma_neg[] = {
|
||||
0xd0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39,
|
||||
0x44, 0x51, 0x0b, 0x16, 0x14, 0x2f, 0x32
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg, sizeof(gamma_neg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
204
drivers/st77xx/st7796_init.c
Normal file
204
drivers/st77xx/st7796_init.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_st77xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Controller specific initialization for ST7796
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* This file is only compiled if the `st7796` module is enabled.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "kernel_defines.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "st77xx.h"
|
||||
#include "st7796_internal.h"
|
||||
#include "lcd.h"
|
||||
#include "lcd_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if CONFIG_ST7796_CUSTOM_CONFIG
|
||||
/* avdd in mV with 200 mV increments: 6600 = 6.6V
|
||||
* Datasheet page 223:
|
||||
*
|
||||
* y = 0 for avdd < 6200 (< 6.2V)
|
||||
* y = (avdd - 6200) / 200 for avdd = 6200 to 6800 (6.2 to 6.8V)
|
||||
* y = 3 for avdd > 6800 (> 6.8V)
|
||||
*
|
||||
* default value after reset is 6.6 V (0x02)
|
||||
*/
|
||||
static inline uint8_t _st7796_calc_avdd(int16_t avdd)
|
||||
{
|
||||
assert((avdd >= 6200) && (avdd <= 6800));
|
||||
assert((avdd % 200) == 0);
|
||||
|
||||
return (avdd - 6200) / 200;
|
||||
}
|
||||
|
||||
/* avcl in mV with 200 mV increments: -4800 = -4.8V
|
||||
* Datasheet page 223:
|
||||
*
|
||||
* y = 0 for avcl < -5000 (< -5.0V)
|
||||
* y = 3 - ((avcl + 5000) / 200) for avcl = -5000 to -4400 (-5.0V to -4.4V)
|
||||
* y = 3 for avcl > -4400 (> -4.4V)
|
||||
*
|
||||
* default value after reset is -4.4 V (0x00)
|
||||
*/
|
||||
static inline uint8_t _st7796_calc_avcl(int16_t avcl)
|
||||
{
|
||||
assert((avcl >= -5000) && (avcl <= -4400));
|
||||
assert((avcl % 200) == 0);
|
||||
|
||||
return 3 - ((avcl + 5000) / 200);
|
||||
}
|
||||
|
||||
/* vcom in mV with 25 mV increments: 1325 = 1.325V
|
||||
* Datasheet page 227:
|
||||
*
|
||||
* y = 0 for vcom < 300 (< 0.3V)
|
||||
* y = (vcom - 300) / 25 for vcom = 100 to 1875 (0.3V to 1.875V)
|
||||
* y = 63 for vcom > 1685 (> 1.875V)
|
||||
*
|
||||
* default value after reset is 1.0V (0x1c)
|
||||
*/
|
||||
static inline uint8_t _st7796_calc_vcom(int16_t vcom)
|
||||
{
|
||||
assert((vcom >= 300) && (vcom <= 1875));
|
||||
assert((vcom % 25) == 0);
|
||||
|
||||
return (vcom - 300) / 25;
|
||||
}
|
||||
|
||||
/* vol in mV with 25 mV increments: 100 = 0.1V
|
||||
* Datasheet page 229:
|
||||
*
|
||||
* y = 0 for vol < -800 (< -0.8V)
|
||||
* y = (vol + 800) / 25 for vol = -800 to 775 (-0.8V to 0.775V)
|
||||
* y = 63 for vol > 0.775 (> 0.775V)
|
||||
*
|
||||
* default value after reset is 0 V (0x00)
|
||||
*/
|
||||
static inline uint8_t _st7796_calc_vcom_offset(int16_t off)
|
||||
{
|
||||
assert((off >= -800) && (off <= 775));
|
||||
assert((off % 25) == 0);
|
||||
|
||||
return (off < 0) ? 32 + ((off + 800) / 25) : off / 25;
|
||||
}
|
||||
|
||||
/* vrh in mV with 50 mV increments: 4800 = 4.8V
|
||||
* Datasheet page 224:
|
||||
*
|
||||
* y = 0 for vrh < 3550 (< 3.55V)
|
||||
* y = (vrh - 3550) / 50 for vrh = 3550 to 5500 (3.55V to 5.5V)
|
||||
* y = 39 for vrh > 5500 (> -4.4V)
|
||||
*
|
||||
* default value after reset is 4.5 V (0x13)
|
||||
*/
|
||||
static inline uint8_t _st7796_calc_vrh(int16_t vrh)
|
||||
{
|
||||
assert((vrh >= 3550) && (vrh <= 5500));
|
||||
assert((vrh % 50) == 0);
|
||||
|
||||
return (vrh - 3550) / 50;
|
||||
}
|
||||
#endif /* CONFIG_ST7796_CUSTOM_CONFIG */
|
||||
|
||||
int st7796_init(lcd_t *dev, const lcd_params_t *params)
|
||||
{
|
||||
assert(params->lines <= 480);
|
||||
assert(params->rgb_channels <= 320);
|
||||
|
||||
uint8_t command_params[5] = { 0 };
|
||||
(void)command_params;
|
||||
|
||||
#if CONFIG_ST7796_CUSTOM_CONFIG
|
||||
|
||||
/* PWR1 (c0h): Power Control 1 */
|
||||
command_params[0] = (_st7796_calc_avdd(CONFIG_ST7796_AVDD) << 6) |
|
||||
(_st7796_calc_avcl(CONFIG_ST7796_AVCL) << 4);
|
||||
command_params[1] = 0x25; /* use reset default, TODO VGH and VGL config */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 2);
|
||||
DEBUG("PWR1 (c0h): %02x %02x\n", command_params[0], command_params[1]);
|
||||
|
||||
/* PWR2 (C1h): Power Control 2 */
|
||||
command_params[0] = _st7796_calc_vrh(CONFIG_ST7796_VRH);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
|
||||
DEBUG("PWR2 (C1h) %02x\n", command_params[0]);
|
||||
|
||||
/* VCMPCTL (C5h): VCOM Control */
|
||||
command_params[0] = _st7796_calc_vcom(CONFIG_ST7796_VCOM);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCMPCTL, command_params, 1);
|
||||
DEBUG("VCMPCTL (C5h) %02x\n", command_params[0]);
|
||||
|
||||
/* VCM Offset (C6h): Vcom Offset Register */
|
||||
command_params[0] = _st7796_calc_vcom_offset(CONFIG_ST7796_VCOM_OFFSET);
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCM, command_params, 1);
|
||||
DEBUG("VCM (C6h) %02x\n", command_params[0]);
|
||||
|
||||
#else /* CONFIG_ST7796_CUSTOM_CONFIG */
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* PWR1 (c0h): Power Control 1 (== reset defaults) */
|
||||
command_params[0] = 0x80; /* AVDD=6.6V, AVCL=-4.4 */
|
||||
command_params[1] = 0x25; /* use reset default, TODO VGH and VGL config */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 2);
|
||||
DEBUG("PWR1 (c0h): %02x %02x\n", command_params[0], command_params[1]);
|
||||
|
||||
/* PWR2 (C1h): Power Control 2 (== reset defaults) */
|
||||
command_params[0] = 0x0b; /* VRH=4.1V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
|
||||
DEBUG("PWR2 (C1h) %02x\n", command_params[0]);
|
||||
|
||||
/* VCMPCTL (C5h): VCOM Control (== reset defaults) */
|
||||
command_params[0] = 0x1c; /* VCOM=1.0V */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCMPCTL, command_params, 1);
|
||||
DEBUG("VCMPCTL (C5h) %02x\n", command_params[0]);
|
||||
|
||||
/* VCM Offset (C6h): Vcom Offset Register (== reset defaults) */
|
||||
command_params[0] = 0x00; /* VCOM Offset=0V (VMF_REG=0) */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCM, command_params, 1);
|
||||
DEBUG("VCM (C6h) %02x\n", command_params[0]);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
#endif /* CONFIG_ST7796_CUSTOM_CONFIG */
|
||||
|
||||
/* VGAMCTRL (E0h): Positive Voltage Gamma Control */
|
||||
{
|
||||
static const uint8_t gamma_pos[] = {
|
||||
0xf0, 0x09, 0x0b, 0x06, 0x04, 0x15, 0x2f,
|
||||
0x54, 0x42, 0x3c, 0x17, 0x14, 0x18, 0x1b,
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos, sizeof(gamma_pos));
|
||||
}
|
||||
/* NVGAMCTRL (E1h): Negative Voltage Gamma Control */
|
||||
{
|
||||
static const uint8_t gamma_neg[] = {
|
||||
0xe0, 0x09, 0x0b, 0x06, 0x04, 0x03, 0x2b,
|
||||
0x43, 0x42, 0x3b, 0x16, 0x14, 0x17, 0x1b
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg, sizeof(gamma_neg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -29,12 +29,12 @@
|
||||
#include "kernel_defines.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#if IS_USED(MODULE_LCD_SPI)
|
||||
#include "periph/spi.h"
|
||||
#endif
|
||||
|
||||
#include "st77xx.h"
|
||||
#include "st77xx_internal.h"
|
||||
#include "st7735_internal.h"
|
||||
#include "st7789_internal.h"
|
||||
#include "st7796_internal.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include "lcd_internal.h"
|
||||
|
||||
@ -43,72 +43,59 @@
|
||||
|
||||
static int _init(lcd_t *dev, const lcd_params_t *params)
|
||||
{
|
||||
if (params->cntrl == ST77XX_CNTRL_ST7735) {
|
||||
assert(params->lines <= 162);
|
||||
assert(params->rgb_channels <= 132);
|
||||
}
|
||||
if (params->cntrl == ST77XX_CNTRL_ST7789) {
|
||||
assert(params->lines <= 320);
|
||||
assert(params->rgb_channels <= 240);
|
||||
}
|
||||
if (params->cntrl == ST77XX_CNTRL_ST7796) {
|
||||
assert(params->lines <= 480);
|
||||
assert(params->rgb_channels <= 320);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
uint8_t command_params[4] = { 0 };
|
||||
uint8_t command_params[1] = { 0 };
|
||||
|
||||
/* Acquire once and release at the end */
|
||||
lcd_ll_acquire(dev);
|
||||
|
||||
/* Soft Reset */
|
||||
/* Soft Reset (requires 120 ms if in Sleep In mode), default display off */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_SWRESET, NULL, 0);
|
||||
ztimer_sleep(ZTIMER_MSEC, 120);
|
||||
|
||||
/* Display off */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_DISPOFF, NULL, 0);
|
||||
/* Sleep Out command to leave Sleep In state after reset, requires 120 ms */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0);
|
||||
ztimer_sleep(ZTIMER_MSEC, 120);
|
||||
|
||||
/* TODO: instead of using a wrong initialization command sequence for power
|
||||
* and frame control, default values after reset are used. */
|
||||
/* COLMOD (3Ah): Interface Pixel Format */
|
||||
command_params[0] = 0x55; /* 16 bit mode RGB & Control */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_COLMOD, command_params, 1);
|
||||
|
||||
/* Memory access CTL */
|
||||
/* controller specific initialization part called */
|
||||
if (IS_USED(MODULE_ST7735) && (params->cntrl == ST77XX_CNTRL_ST7735)) {
|
||||
DEBUG("ST7735 used ...\n");
|
||||
st7735_init(dev, params);
|
||||
}
|
||||
else if (IS_USED(MODULE_ST7789) && (params->cntrl == ST77XX_CNTRL_ST7789)) {
|
||||
DEBUG("ST7789 used ...\n");
|
||||
st7789_init(dev, params);
|
||||
}
|
||||
else if (IS_USED(MODULE_ST7735) && (params->cntrl == ST77XX_CNTRL_ST7735)) {
|
||||
DEBUG("ST7735 used ...\n");
|
||||
st7735_init(dev, params);
|
||||
}
|
||||
|
||||
#if 0 /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* GAMSET (26h): Gamma Set (== reset defaults) */
|
||||
command_params[0] = 0x01;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_GAMSET, command_params, 1);
|
||||
|
||||
/* TEON (35h): Tearing Effect Line ON (== reset defaults) */
|
||||
command_params[0] = 0x00; /* TEM=0 (only V-Blanking) */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_VCOMS, command_params, 1);
|
||||
|
||||
#endif /* no need to write reset defaults, just for documentation purpose */
|
||||
|
||||
/* MADCTL (36h): Memory Data Access Control */
|
||||
command_params[0] = dev->params->rotation;
|
||||
command_params[0] |= dev->params->rgb ? 0 : LCD_MADCTL_BGR;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_MADCTL, command_params, 1);
|
||||
|
||||
/* Pixel format */
|
||||
command_params[0] = 0x55; /* 16 bit mode */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PIXSET, command_params, 1);
|
||||
|
||||
command_params[0] = 0x01;
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_GAMSET, command_params, 1);
|
||||
|
||||
/* Gamma correction */
|
||||
{
|
||||
static const uint8_t gamma_pos[] = {
|
||||
0xf0, 0x09, 0x0b, 0x06, 0x04, 0x15, 0x2f,
|
||||
0x54, 0x42, 0x3c, 0x17, 0x14, 0x18, 0x1b,
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos,
|
||||
sizeof(gamma_pos));
|
||||
}
|
||||
{
|
||||
static const uint8_t gamma_neg[] = {
|
||||
0xe0, 0x09, 0x0b, 0x06, 0x04, 0x03, 0x2b,
|
||||
0x43, 0x42, 0x3b, 0x16, 0x14, 0x17, 0x1b
|
||||
};
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg,
|
||||
sizeof(gamma_neg));
|
||||
}
|
||||
|
||||
/* enable Inversion if configured, reset default is off */
|
||||
if (dev->params->inverted) {
|
||||
/* INVON (21h): Display Inversion On */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_DINVON, NULL, 0);
|
||||
}
|
||||
/* Sleep out (turn off sleep mode) */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0);
|
||||
|
||||
/* Normal display mode on */
|
||||
lcd_ll_write_cmd(dev, LCD_CMD_NORON, NULL, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user