123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- * lcd.c
- *
- * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * See <http://www.gnu.org/licenses/>.
- */
-
- #include <math.h>
-
- #include "pico/stdlib.h"
- #include "hardware/spi.h"
- #include "hardware/pwm.h"
- #include "driver_st7789.h"
-
- #include "config.h"
- #include "log.h"
- #include "lcd.h"
-
- #define LCD_PIN_DC 8
- #define LCD_PIN_CS 9
- #define LCD_PIN_CLK 10
- #define LCD_PIN_DIN 11
- #define LCD_PIN_RST 12
- #define LCD_PIN_BL 13
-
- #define ST7789_PICO_COLUMN 240
- #define ST7789_PICO_ROW 240
-
- #define ST7789_PICO_ACCESS (ST7789_ORDER_PAGE_TOP_TO_BOTTOM | \
- ST7789_ORDER_COLUMN_LEFT_TO_RIGHT | \
- ST7789_ORDER_PAGE_COLUMN_NORMAL | \
- ST7789_ORDER_LINE_TOP_TO_BOTTOM | \
- ST7789_ORDER_COLOR_RGB | \
- ST7789_ORDER_REFRESH_LEFT_TO_RIGHT)
-
- #define ST7789_PICO_RGB_INTERFACE_COLOR_FORMAT 0
- #define ST7789_PICO_CONTROL_INTERFACE_COLOR_FORMAT ST7789_CONTROL_INTERFACE_COLOR_FORMAT_16_BIT
-
- #define ST7789_PICO_PORCH_NORMAL_BACK 0x0C
- #define ST7789_PICO_PORCH_NORMAL_FRONT 0x0C
- #define ST7789_PICO_PORCH_ENABLE ST7789_BOOL_FALSE
- #define ST7789_PICO_PORCH_IDEL_BACK 0x03
- #define ST7789_PICO_PORCH_IDEL_FRONT 0x03
- #define ST7789_PICO_PORCH_PART_BACK 0x03
- #define ST7789_PICO_PORCH_PART_FRONT 0x03
-
- #define ST7789_PICO_VGHS ST7789_VGHS_13P26_V
- #define ST7789_PICO_VGLS_NEGATIVE ST7789_VGLS_NEGATIVE_10P43
-
- #define ST7789_PICO_VCOMS 0.725f
-
- #define ST7789_PICO_XMY ST7789_BOOL_FALSE
- #define ST7789_PICO_XBGR ST7789_BOOL_TRUE
- #define ST7789_PICO_XINV ST7789_BOOL_FALSE
- #define ST7789_PICO_XMX ST7789_BOOL_TRUE
- #define ST7789_PICO_XMH ST7789_BOOL_TRUE
- #define ST7789_PICO_XMV ST7789_BOOL_FALSE
- #define ST7789_PICO_XGS ST7789_BOOL_FALSE
-
- #define ST7789_PICO_VDV_VRH_FROM ST7789_VDV_VRH_FROM_CMD
- #define ST7789_PICO_VRHS 4.45f
- #define ST7789_PICO_VDV 0.0f
-
- #define ST7789_PICO_INVERSION_SELECTION ST7789_INVERSION_SELECTION_DOT
- #define ST7789_PICO_FRAME_RATE ST7789_FRAME_RATE_60_HZ
-
- #define ST7789_PICO_AVDD ST7789_AVDD_6P8_V
- #define ST7789_PICO_AVCL_NEGTIVE ST7789_AVCL_NEGTIVE_4P8_V
- #define ST7789_PICO_VDS ST7789_VDS_2P3_V
-
- #define ST7789_PICO_POSITIVE_VOLTAGE_GAMMA {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, \
- 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}
- #define ST7789_PICO_NEGATIVA_VOLTAGE_GAMMA {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, \
- 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}
-
- static st7789_handle_t gs_handle;
- static uint16_t bl_value = 0;
-
- static uint8_t st7789_interface_spi_init(void) {
- // Use SPI1 at 100MHz
- spi_init(spi1, 100 * 1000 * 1000);
- gpio_set_function(LCD_PIN_CLK, GPIO_FUNC_SPI);
- gpio_set_function(LCD_PIN_DIN, GPIO_FUNC_SPI);
-
- // Chip select is active-low, so we'll initialise it to a driven-high state
- gpio_init(LCD_PIN_CS);
- gpio_set_dir(LCD_PIN_CS, GPIO_OUT);
- gpio_put(LCD_PIN_CS, 1);
-
- spi_set_format(spi1,
- 8, // Number of bits per transfer
- 0, // Polarity (CPOL)
- 0, // Phase (CPHA)
- SPI_MSB_FIRST);
-
- return 0;
- }
-
- static uint8_t st7789_interface_spi_deinit(void) {
- spi_deinit(spi1);
- gpio_deinit(LCD_PIN_CS);
- return 0;
- }
-
- static uint8_t st7789_interface_spi_write_cmd(uint8_t *buf, uint16_t len) {
- gpio_put(LCD_PIN_CS, 0);
- spi_write_blocking(spi1, buf, len);
- gpio_put(LCD_PIN_CS, 1);
- return 0;
- }
-
- static void st7789_interface_delay_ms(uint32_t ms) {
- sleep_ms(ms);
- }
-
- static void st7789_interface_debug_print(const char *const fmt, ...) {
- va_list args;
- va_start(args, fmt);
- debug_log_va(true, fmt, args);
- va_end(args);
- }
-
- static uint8_t st7789_interface_cmd_data_gpio_init(void) {
- gpio_init(LCD_PIN_DC);
- gpio_set_dir(LCD_PIN_DC, GPIO_OUT);
- return 0;
- }
-
- static uint8_t st7789_interface_cmd_data_gpio_deinit(void) {
- gpio_deinit(LCD_PIN_DC);
- return 0;
- }
-
- static uint8_t st7789_interface_cmd_data_gpio_write(uint8_t value) {
- gpio_put(LCD_PIN_DC, value);
- return 0;
- }
-
- static uint8_t st7789_interface_reset_gpio_init(void) {
- gpio_init(LCD_PIN_RST);
- gpio_set_dir(LCD_PIN_RST, GPIO_OUT);
- return 0;
- }
-
- static uint8_t st7789_interface_reset_gpio_deinit(void) {
- gpio_deinit(LCD_PIN_RST);
- return 0;
- }
-
- static uint8_t st7789_interface_reset_gpio_write(uint8_t value) {
- gpio_put(LCD_PIN_RST, value);
- return 0;
- }
-
- void lcd_init(void) {
- uint8_t reg;
-
- DRIVER_ST7789_LINK_INIT(&gs_handle, st7789_handle_t);
- DRIVER_ST7789_LINK_SPI_INIT(&gs_handle, st7789_interface_spi_init);
- DRIVER_ST7789_LINK_SPI_DEINIT(&gs_handle, st7789_interface_spi_deinit);
- DRIVER_ST7789_LINK_SPI_WRITE_COMMAND(&gs_handle, st7789_interface_spi_write_cmd);
- DRIVER_ST7789_LINK_COMMAND_DATA_GPIO_INIT(&gs_handle, st7789_interface_cmd_data_gpio_init);
- DRIVER_ST7789_LINK_COMMAND_DATA_GPIO_DEINIT(&gs_handle, st7789_interface_cmd_data_gpio_deinit);
- DRIVER_ST7789_LINK_COMMAND_DATA_GPIO_WRITE(&gs_handle, st7789_interface_cmd_data_gpio_write);
- DRIVER_ST7789_LINK_RESET_GPIO_INIT(&gs_handle, st7789_interface_reset_gpio_init);
- DRIVER_ST7789_LINK_RESET_GPIO_DEINIT(&gs_handle, st7789_interface_reset_gpio_deinit);
- DRIVER_ST7789_LINK_RESET_GPIO_WRITE(&gs_handle, st7789_interface_reset_gpio_write);
- DRIVER_ST7789_LINK_DELAY_MS(&gs_handle, st7789_interface_delay_ms);
- DRIVER_ST7789_LINK_DEBUG_PRINT(&gs_handle, st7789_interface_debug_print);
-
- st7789_init(&gs_handle);
-
- st7789_set_column(&gs_handle, ST7789_PICO_COLUMN);
-
- st7789_set_row(&gs_handle, ST7789_PICO_ROW);
-
- st7789_set_memory_data_access_control(&gs_handle, ST7789_PICO_ACCESS);
-
- st7789_set_interface_pixel_format(&gs_handle,
- ST7789_PICO_RGB_INTERFACE_COLOR_FORMAT,
- ST7789_PICO_CONTROL_INTERFACE_COLOR_FORMAT);
-
- st7789_set_porch(&gs_handle,
- ST7789_PICO_PORCH_NORMAL_BACK,
- ST7789_PICO_PORCH_NORMAL_FRONT,
- ST7789_PICO_PORCH_ENABLE,
- ST7789_PICO_PORCH_IDEL_BACK,
- ST7789_PICO_PORCH_IDEL_FRONT,
- ST7789_PICO_PORCH_PART_BACK,
- ST7789_PICO_PORCH_PART_FRONT);
-
- st7789_set_gate_control(&gs_handle, ST7789_PICO_VGHS, ST7789_PICO_VGLS_NEGATIVE);
-
- st7789_vcom_convert_to_register(&gs_handle, ST7789_PICO_VCOMS, ®);
- st7789_set_vcoms(&gs_handle, reg);
-
- st7789_set_lcm_control(&gs_handle,
- ST7789_PICO_XMY,
- ST7789_PICO_XBGR,
- ST7789_PICO_XINV,
- ST7789_PICO_XMX,
- ST7789_PICO_XMH,
- ST7789_PICO_XMV,
- ST7789_PICO_XGS);
-
- st7789_set_vdv_vrh_from(&gs_handle, ST7789_PICO_VDV_VRH_FROM);
-
- st7789_vrhs_convert_to_register(&gs_handle, ST7789_PICO_VRHS, ®);
- st7789_set_vrhs(&gs_handle, reg);
-
- st7789_vdv_convert_to_register(&gs_handle, ST7789_PICO_VDV, ®);
- st7789_set_vdv(&gs_handle, reg);
-
- st7789_set_frame_rate(&gs_handle, ST7789_PICO_INVERSION_SELECTION, ST7789_PICO_FRAME_RATE);
-
- st7789_set_power_control_1(&gs_handle,
- ST7789_PICO_AVDD,
- ST7789_PICO_AVCL_NEGTIVE,
- ST7789_PICO_VDS);
-
- uint8_t param_positive[14] = ST7789_PICO_POSITIVE_VOLTAGE_GAMMA;
- st7789_set_positive_voltage_gamma_control(&gs_handle, param_positive);
-
- uint8_t param_negative[14] = ST7789_PICO_NEGATIVA_VOLTAGE_GAMMA;
- st7789_set_negative_voltage_gamma_control(&gs_handle, param_negative);
-
- st7789_display_inversion_on(&gs_handle);
-
- st7789_sleep_out(&gs_handle);
-
- st7789_display_on(&gs_handle);
-
- st7789_clear(&gs_handle);
-
- // backlight
- uint bl_slice = pwm_gpio_to_slice_num(LCD_PIN_BL);
- uint bl_channel = pwm_gpio_to_channel(LCD_PIN_BL);
- gpio_set_function(LCD_PIN_BL, GPIO_FUNC_PWM);
- pwm_set_wrap(bl_slice, 0xFFFF);
- pwm_set_clkdiv(bl_slice, 1.0f);
- pwm_set_chan_level(bl_slice, bl_channel, bl_value);
- pwm_set_enabled(bl_slice, true);
- }
-
- uint16_t lcd_get_backlight(void) {
- return bl_value;
- }
-
- void lcd_set_backlight(uint16_t value) {
- uint bl_slice = pwm_gpio_to_slice_num(LCD_PIN_BL);
- uint bl_channel = pwm_gpio_to_channel(LCD_PIN_BL);
- bl_value = value;
- pwm_set_chan_level(bl_slice, bl_channel, bl_value);
- }
-
- void lcd_clear(void) {
- st7789_clear(&gs_handle);
- }
-
- void lcd_write_point(uint16_t x, uint16_t y, uint32_t color) {
- st7789_draw_point(&gs_handle, x, y, color);
- }
-
- void lcd_write_rect(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint32_t color) {
- st7789_fill_rect(&gs_handle, left, top, right, bottom, color);
- }
-
- uint32_t from_hsv(float h, float s, float v) {
- float i = floorf(h * 6.0f);
- float f = h * 6.0f - i;
- v *= 255.0f;
- float p = v * (1.0f - s);
- float q = v * (1.0f - f * s);
- float t = v * (1.0f - (1.0f - f) * s);
-
- switch (((uint32_t)i) % 6) {
- case 0:
- return RGB_565((uint32_t)v, (uint32_t)t, (uint32_t)p);
-
- case 1:
- return RGB_565((uint32_t)q, (uint32_t)v, (uint32_t)p);
-
- case 2:
- return RGB_565((uint32_t)p, (uint32_t)v, (uint32_t)t);
-
- case 3:
- return RGB_565((uint32_t)p, (uint32_t)q, (uint32_t)v);
-
- case 4:
- return RGB_565((uint32_t)t, (uint32_t)p, (uint32_t)v);
-
- case 5:
- return RGB_565((uint32_t)v, (uint32_t)p, (uint32_t)q);
-
- default:
- return RGB_565(0, 0, 0);
- }
- }
|