Skip to content

Commit e87c101

Browse files
committed
feat: Add POC ST7586 LCD controller driver service
1 parent 152f458 commit e87c101

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

services/Kconfig

+4
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ menu "High level device drivers"
204204
depends on SERVICE_STM32_SPI
205205
bool "ADI ADXL355 3 axis accelerometer"
206206
default n
207+
208+
config SERVICE_LCD_ST7586
209+
bool "ST7586 LCD driver"
210+
default n
207211
endmenu
208212

209213
menu "Filesystem and memory management services"

services/lcd-st7586/SConscript

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Import("env")
2+
Import("objs")
3+
Import("conf")
4+
5+
if conf["SERVICE_LCD_ST7586"] == "y":
6+
objs.append(env.Object(File(Glob("*.c"))))

services/lcd-st7586/lcd-st7586.c

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/* SPDX-License-Identifier: GPL-3.0-or-later
2+
*
3+
* ST7586 LCD driver service
4+
*
5+
* Copyright (c) 2024, Marek Koza (qyx@krtko.org)
6+
* All rights reserved.
7+
*/
8+
9+
#include <stdint.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <stdio.h>
13+
14+
#include <main.h>
15+
#include <interfaces/spi.h>
16+
17+
#include "lcd-st7586.h"
18+
19+
#define MODULE_NAME "lcd-st7586"
20+
21+
22+
/***************************************************************************************************
23+
* Framebuffer interface API
24+
***************************************************************************************************/
25+
26+
27+
//static const struct power_vmt generic_power_vmt = {
28+
//.enable = generic_power_enable,
29+
//.set_voltage = generic_power_set_voltage,
30+
//};
31+
32+
33+
/*
34+
static void lcd_send_spi(uint8_t data) {
35+
spi_send8(SPI1, data);
36+
spi_read8(SPI1);
37+
}
38+
39+
40+
static void lcd_write(uint8_t v) {
41+
gpio_clear(LCD_CS_PORT, LCD_CS_PIN);
42+
lcd_send_spi(v);
43+
gpio_set(LCD_CS_PORT, LCD_CS_PIN);
44+
}
45+
46+
47+
static void lcd_write_buf(uint8_t *buf, size_t len) {
48+
gpio_clear(LCD_CS_PORT, LCD_CS_PIN);
49+
while (len) {
50+
lcd_send_spi(*buf);
51+
buf++;
52+
len--;
53+
}
54+
gpio_set(LCD_CS_PORT, LCD_CS_PIN);
55+
}
56+
*/
57+
58+
static lcd_st7586_ret_t lcd_reset(LcdSt7586 *self) {
59+
gpio_set(self->reset_port, self->reset_pin);
60+
vTaskDelay(10);
61+
gpio_clear(self->reset_port, self->reset_pin);
62+
vTaskDelay(10);
63+
gpio_set(self->reset_port, self->reset_pin);
64+
vTaskDelay(10);
65+
}
66+
67+
68+
static lcd_st7586_ret_t lcd_send_command(LcdSt7586 *self, uint8_t reg) {
69+
gpio_clear(self->cd_port, self->cd_pin);
70+
71+
self->spi->vmt->select(self->spi);
72+
self->spi->vmt->send(self->spi, &reg, sizeof(reg));
73+
self->spi->vmt->deselect(self->spi);
74+
}
75+
76+
77+
static lcd_st7586_ret_t lcd_send_data(LcdSt7586 *self, uint8_t reg) {
78+
gpio_set(self->cd_port, self->cd_pin);
79+
80+
self->spi->vmt->select(self->spi);
81+
self->spi->vmt->send(self->spi, &reg, sizeof(reg));
82+
self->spi->vmt->deselect(self->spi);
83+
}
84+
85+
86+
static lcd_st7586_ret_t lcd_send_data_buf(LcdSt7586 *self, const uint8_t *buf, size_t len) {
87+
gpio_set(self->cd_port, self->cd_pin);
88+
89+
self->spi->vmt->select(self->spi);
90+
self->spi->vmt->send(self->spi, buf, len);
91+
self->spi->vmt->deselect(self->spi);
92+
}
93+
94+
95+
static lcd_st7586_ret_t lcd_init_controller(LcdSt7586 *self) {
96+
lcd_reset(self);
97+
98+
lcd_send_command(self, 0x11); // Sleep Out
99+
lcd_send_command(self, 0x28); // Display OFF
100+
vTaskDelay(10);
101+
lcd_send_command(self, 0xC0); // Vop = B9h
102+
lcd_send_data(self, 0x40);
103+
lcd_send_data(self, 0x01);
104+
lcd_send_command(self, 0xC3); // BIAS = 1/14
105+
lcd_send_data(self, 0x00);
106+
lcd_send_command(self, 0xC4); // Booster = x8
107+
lcd_send_data(self, 0x07);
108+
lcd_send_command(self, 0xD0); // Enable Analog Circuit
109+
lcd_send_data(self, 0x1D);
110+
lcd_send_command(self, 0xB5); // N-Line = 0
111+
lcd_send_data(self, 0x00);
112+
lcd_send_command(self, 0x38); // Grayscale mode
113+
lcd_send_command(self, 0x3A); // Enable DDRAM Interface
114+
lcd_send_data(self, 0x02);
115+
lcd_send_command(self, 0x36); // Scan Direction Setting
116+
lcd_send_data(self, 0xc0); //COM:C160--C1 SEG: SEG384-SEG1
117+
lcd_send_command(self, 0xB0); // Duty Setting
118+
lcd_send_data(self, 0x9F);
119+
120+
lcd_send_command(self, 0x20); // Display Inversion OFF
121+
lcd_send_command(self, 0x2A); // Column Address Setting
122+
lcd_send_data(self, 0x00); // SEG0 -> SEG384
123+
lcd_send_data(self, 0x00);
124+
lcd_send_data(self, 0x00);
125+
lcd_send_data(self, 0x7F);
126+
lcd_send_command(self, 0x2B); // Row Address Setting
127+
lcd_send_data(self, 0x00); // COM0 -> COM160
128+
lcd_send_data(self, 0x00);
129+
lcd_send_data(self, 0x00);
130+
lcd_send_command(self, 0x9F);
131+
// display_white(); // Clear whole DDRAM by ¡°0¡± (384 x 160 x 2)
132+
133+
lcd_send_command(self, 0x29); // Display ON
134+
}
135+
136+
/*
137+
static void lcd_black(void) {
138+
uint8_t data[121];
139+
for (size_t i = 0; i < 120; i++) {
140+
data[i] = 0xff;
141+
}
142+
143+
lcd_send_command(0x2c);
144+
for(uint32_t i = 0; i < 170; i++) {
145+
lcd_send_data_buf(data, 121);
146+
}
147+
}
148+
*/
149+
150+
static void lcd_pattern(LcdSt7586 *self) {
151+
uint8_t data[128] = {0};
152+
153+
lcd_send_command(self, 0x2c);
154+
for(uint32_t i = 0; i < 160; i++) {
155+
for (size_t j = 0; j < 128; j++) {
156+
data[j] = ((i % 4) << 6) | ((i % 4) << 3);
157+
}
158+
lcd_send_data_buf(self, data, 128);
159+
}
160+
}
161+
162+
163+
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) {
164+
memset(self, 0, sizeof(LcdSt7586));
165+
166+
//self->power.parent = self;
167+
//self->power.vmt = &generic_power_vmt;
168+
self->spi = spi;
169+
self->reset_port = reset_port;
170+
self->reset_pin = reset_pin;
171+
self->cd_port = cd_port;
172+
self->cd_pin = cd_pin;
173+
174+
lcd_init_controller(self);
175+
lcd_pattern(self);
176+
177+
u_log(system_log, LOG_TYPE_INFO, U_LOG_MODULE_PREFIX("initialized"));
178+
return LCD_ST7586_RET_OK;
179+
}
180+
181+
182+
lcd_st7586_ret_t lcd_st7586_free(LcdSt7586 *self) {
183+
(void)self;
184+
return LCD_ST7586_RET_OK;
185+
}
186+
187+
188+

services/lcd-st7586/lcd-st7586.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* SPDX-License-Identifier: GPL-3.0-or-later
2+
*
3+
* ST7586 LCD driver service
4+
*
5+
* Copyright (c) 2024, Marek Koza (qyx@krtko.org)
6+
* All rights reserved.
7+
*/
8+
9+
#pragma once
10+
11+
#include <main.h>
12+
#include <interfaces/spi.h>
13+
14+
typedef enum {
15+
LCD_ST7586_RET_OK = 0,
16+
LCD_ST7586_RET_FAILED,
17+
} lcd_st7586_ret_t;
18+
19+
20+
typedef struct lcs_st7586 {
21+
uint32_t reset_port;
22+
uint32_t reset_pin;
23+
uint32_t cd_port;
24+
uint32_t cd_pin;
25+
26+
SpiDev *spi;
27+
28+
} LcdSt7586;
29+
30+
31+
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);
32+
lcd_st7586_ret_t lcd_st7586_free(LcdSt7586 *self);
33+

0 commit comments

Comments
 (0)