Skip to content

Commit

Permalink
feat: Add POC ST7586 LCD controller driver service
Browse files Browse the repository at this point in the history
  • Loading branch information
iqyx committed Nov 24, 2024
1 parent 152f458 commit e87c101
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
4 changes: 4 additions & 0 deletions services/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ menu "High level device drivers"
depends on SERVICE_STM32_SPI
bool "ADI ADXL355 3 axis accelerometer"
default n

config SERVICE_LCD_ST7586
bool "ST7586 LCD driver"
default n
endmenu

menu "Filesystem and memory management services"
Expand Down
6 changes: 6 additions & 0 deletions services/lcd-st7586/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Import("env")
Import("objs")
Import("conf")

if conf["SERVICE_LCD_ST7586"] == "y":
objs.append(env.Object(File(Glob("*.c"))))
188 changes: 188 additions & 0 deletions services/lcd-st7586/lcd-st7586.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
*
* ST7586 LCD driver service
*
* Copyright (c) 2024, Marek Koza (qyx@krtko.org)
* All rights reserved.
*/

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <main.h>
#include <interfaces/spi.h>

#include "lcd-st7586.h"

#define MODULE_NAME "lcd-st7586"


/***************************************************************************************************
* Framebuffer interface API
***************************************************************************************************/


//static const struct power_vmt generic_power_vmt = {
//.enable = generic_power_enable,
//.set_voltage = generic_power_set_voltage,
//};


/*
static void lcd_send_spi(uint8_t data) {
spi_send8(SPI1, data);
spi_read8(SPI1);
}
static void lcd_write(uint8_t v) {
gpio_clear(LCD_CS_PORT, LCD_CS_PIN);
lcd_send_spi(v);
gpio_set(LCD_CS_PORT, LCD_CS_PIN);
}
static void lcd_write_buf(uint8_t *buf, size_t len) {
gpio_clear(LCD_CS_PORT, LCD_CS_PIN);
while (len) {
lcd_send_spi(*buf);
buf++;
len--;
}
gpio_set(LCD_CS_PORT, LCD_CS_PIN);
}
*/

static lcd_st7586_ret_t lcd_reset(LcdSt7586 *self) {
gpio_set(self->reset_port, self->reset_pin);
vTaskDelay(10);
gpio_clear(self->reset_port, self->reset_pin);
vTaskDelay(10);
gpio_set(self->reset_port, self->reset_pin);
vTaskDelay(10);
}


static lcd_st7586_ret_t lcd_send_command(LcdSt7586 *self, uint8_t reg) {
gpio_clear(self->cd_port, self->cd_pin);

self->spi->vmt->select(self->spi);
self->spi->vmt->send(self->spi, &reg, sizeof(reg));
self->spi->vmt->deselect(self->spi);
}


static lcd_st7586_ret_t lcd_send_data(LcdSt7586 *self, uint8_t reg) {
gpio_set(self->cd_port, self->cd_pin);

self->spi->vmt->select(self->spi);
self->spi->vmt->send(self->spi, &reg, sizeof(reg));
self->spi->vmt->deselect(self->spi);
}


static lcd_st7586_ret_t lcd_send_data_buf(LcdSt7586 *self, const uint8_t *buf, size_t len) {
gpio_set(self->cd_port, self->cd_pin);

self->spi->vmt->select(self->spi);
self->spi->vmt->send(self->spi, buf, len);
self->spi->vmt->deselect(self->spi);
}


static lcd_st7586_ret_t lcd_init_controller(LcdSt7586 *self) {
lcd_reset(self);

lcd_send_command(self, 0x11); // Sleep Out
lcd_send_command(self, 0x28); // Display OFF
vTaskDelay(10);
lcd_send_command(self, 0xC0); // Vop = B9h
lcd_send_data(self, 0x40);
lcd_send_data(self, 0x01);
lcd_send_command(self, 0xC3); // BIAS = 1/14
lcd_send_data(self, 0x00);
lcd_send_command(self, 0xC4); // Booster = x8
lcd_send_data(self, 0x07);
lcd_send_command(self, 0xD0); // Enable Analog Circuit
lcd_send_data(self, 0x1D);
lcd_send_command(self, 0xB5); // N-Line = 0
lcd_send_data(self, 0x00);
lcd_send_command(self, 0x38); // Grayscale mode
lcd_send_command(self, 0x3A); // Enable DDRAM Interface
lcd_send_data(self, 0x02);
lcd_send_command(self, 0x36); // Scan Direction Setting
lcd_send_data(self, 0xc0); //COM:C160--C1 SEG: SEG384-SEG1
lcd_send_command(self, 0xB0); // Duty Setting
lcd_send_data(self, 0x9F);

lcd_send_command(self, 0x20); // Display Inversion OFF
lcd_send_command(self, 0x2A); // Column Address Setting
lcd_send_data(self, 0x00); // SEG0 -> SEG384
lcd_send_data(self, 0x00);
lcd_send_data(self, 0x00);
lcd_send_data(self, 0x7F);
lcd_send_command(self, 0x2B); // Row Address Setting
lcd_send_data(self, 0x00); // COM0 -> COM160
lcd_send_data(self, 0x00);
lcd_send_data(self, 0x00);
lcd_send_command(self, 0x9F);
// display_white(); // Clear whole DDRAM by ¡°0¡± (384 x 160 x 2)

lcd_send_command(self, 0x29); // Display ON
}

/*
static void lcd_black(void) {
uint8_t data[121];
for (size_t i = 0; i < 120; i++) {
data[i] = 0xff;
}
lcd_send_command(0x2c);
for(uint32_t i = 0; i < 170; i++) {
lcd_send_data_buf(data, 121);
}
}
*/

static void lcd_pattern(LcdSt7586 *self) {
uint8_t data[128] = {0};

lcd_send_command(self, 0x2c);
for(uint32_t i = 0; i < 160; i++) {
for (size_t j = 0; j < 128; j++) {
data[j] = ((i % 4) << 6) | ((i % 4) << 3);
}
lcd_send_data_buf(self, data, 128);
}
}


lcd_st7586_ret_t lcd_st7586_init(LcdSt7586 *self, SpiDev *spi, uint32_t reset_port, uint32_t reset_pin, uint32_t cd_port, uint32_t cd_pin) {
memset(self, 0, sizeof(LcdSt7586));

//self->power.parent = self;
//self->power.vmt = &generic_power_vmt;
self->spi = spi;
self->reset_port = reset_port;
self->reset_pin = reset_pin;
self->cd_port = cd_port;
self->cd_pin = cd_pin;

lcd_init_controller(self);
lcd_pattern(self);

u_log(system_log, LOG_TYPE_INFO, U_LOG_MODULE_PREFIX("initialized"));
return LCD_ST7586_RET_OK;
}


lcd_st7586_ret_t lcd_st7586_free(LcdSt7586 *self) {
(void)self;
return LCD_ST7586_RET_OK;
}



33 changes: 33 additions & 0 deletions services/lcd-st7586/lcd-st7586.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
*
* ST7586 LCD driver service
*
* Copyright (c) 2024, Marek Koza (qyx@krtko.org)
* All rights reserved.
*/

#pragma once

#include <main.h>
#include <interfaces/spi.h>

typedef enum {
LCD_ST7586_RET_OK = 0,
LCD_ST7586_RET_FAILED,
} lcd_st7586_ret_t;


typedef struct lcs_st7586 {
uint32_t reset_port;
uint32_t reset_pin;
uint32_t cd_port;
uint32_t cd_pin;

SpiDev *spi;

} LcdSt7586;


lcd_st7586_ret_t lcd_st7586_init(LcdSt7586 *self, SpiDev *spi, uint32_t reset_port, uint32_t reset_pin, uint32_t cd_port, uint32_t cd_pin);
lcd_st7586_ret_t lcd_st7586_free(LcdSt7586 *self);

0 comments on commit e87c101

Please sign in to comment.