blob: c73f85dd2ba9b869c10f32fd3ce06332b1852bdb [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2015 Gurjant Kalsi <me@gurjantkalsi.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <err.h>
25#include <debug.h>
26#include <trace.h>
27#include <rand.h>
28
29#include <dev/display.h>
30#include <lib/gfx.h>
31#include <platform/gpio.h>
32#include <target/memory_lcd.h>
33
34#if defined (LCD_LS013B7DH06)
35#include <target/display/LS013B7DH06.h>
36#elif defined (LCD_LS027B7DH01)
37#include <target/display/LS027B7DH01.h>
38#endif
39
40#define LOCAL_TRACE 0
41
42SPI_HandleTypeDef SpiHandle;
43
44#define MLCD_WR 0x01 // LCD Write Command
45#define MLCD_CM 0x04 // LCD Clear Memory Command
46#define MLCD_NO 0x00 // LCD No-op command
47
48// 5 bytes used as control bytes, MLCD_BYTES_LINE bytes used to data
49#define MLCD_BUF_SIZE (MLCD_BYTES_LINE + 5)
50
51#define VCOM_HI 0x02
52#define VCOM_LO 0x00
53
54static uint8_t framebuffer[MLCD_HEIGHT * MLCD_WIDTH];
55static uint8_t vcom_state;
56
57static void chip_select(bool s)
58{
59 if (s) {
60 gpio_set(GPIO(GPIO_PORT_B, 12), GPIO_PIN_SET);
61 } else {
62 gpio_set(GPIO(GPIO_PORT_B, 12), GPIO_PIN_RESET);
63 }
64}
65
66static void lcd_power(bool s)
67{
68 if (s) {
69 gpio_set(GPIO(GPIO_PORT_K, 6), GPIO_PIN_SET);
70 } else {
71 gpio_set(GPIO(GPIO_PORT_K, 6), GPIO_PIN_RESET);
72 }
73}
74
75static void mlcd_clear(void)
76{
77
78 uint8_t clear[2];
79 clear[0] = MLCD_CM;
80 clear[1] = 0;
81
82 chip_select(true);
83 HAL_SPI_Transmit(&SpiHandle, clear, 2, HAL_MAX_DELAY);
84 chip_select(false);
85}
86
87
88status_t memory_lcd_init(void)
89{
90 SpiHandle.Instance = SPI2;
91 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
92 SpiHandle.Init.Direction = SPI_DIRECTION_1LINE;
93 SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
94 SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
95 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
96 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_LSB;
97 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
98 SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
99 SpiHandle.Init.CRCPolynomial = 7;
100 SpiHandle.Init.NSS = SPI_NSS_SOFT;
101 SpiHandle.Init.Mode = SPI_MODE_MASTER;
102
103 if (HAL_SPI_Init(&SpiHandle) != HAL_OK) {
104 return ERR_GENERIC;
105 }
106
107 vcom_state = VCOM_LO;
108
109 lcd_power(true);
110
111 mlcd_clear();
112
113 return NO_ERROR;
114}
115
116
117
118static void mlcd_flush(uint starty, uint endy)
119{
120 chip_select(true);
121
122 static uint8_t localbuf[MLCD_BUF_SIZE];
123 uint8_t *bufptr = localbuf;
124
125 // The first line is preceeded with a write command.
126 *bufptr++ = MLCD_WR | vcom_state;
127
128 vcom_state = vcom_state == VCOM_HI ? VCOM_LO : VCOM_HI;
129
130 // Send the image data.
131 for (uint j = starty; j <= endy; ++j) {
132 *bufptr++ = (j + 1);
133
134 bufptr += lcd_get_line(framebuffer, j, bufptr);
135
136 if (HAL_SPI_Transmit(&SpiHandle, localbuf, bufptr - localbuf, HAL_MAX_DELAY) != HAL_OK) {
137 goto finish;
138 }
139
140 bufptr = localbuf;
141
142 *bufptr++ = (j + 1);
143 }
144
145 uint8_t trailer = 0;
146 if (HAL_SPI_Transmit(&SpiHandle, &trailer, 1, HAL_MAX_DELAY) != HAL_OK) {
147 goto finish;
148 }
149
150
151finish:
152 chip_select(false);
153}
154
155status_t display_get_info(struct display_info *info)
156{
157 LTRACEF("display_info %p\n", info);
158
159 info->framebuffer = (void*)framebuffer;
160 info->format = MLCD_GFX_FORMAT;
161 info->width = MLCD_WIDTH;
162 info->height = MLCD_HEIGHT;
163 info->stride = MLCD_WIDTH;
164 info->flush = mlcd_flush;
165
166 return NO_ERROR;
167}