YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
ssd2119_drv.cpp
1/*
2 * ssd2119.cpp
3 *
4 * Created on: 24.05.2020
5 * Author: Andreas Terstegge
6 */
7
8#include <ssd2119_drv.h>
9#include "pixel_stream_const.h"
10#include "task.h"
11
12// Hardware Configurations
14ssd2119_drv::config ssd2119_drv::Kentec_K350QVG(320, 240);
15
16//*****************************************************************************
17//
18// This driver operates in four different screen orientations. They are:
19//
20// * Portrait - The screen is taller than it is wide, and the flex connector is
21// on the left of the display. This is selected by defining
22// PORTRAIT.
23//
24// * Landscape - The screen is wider than it is tall, and the flex connector is
25// on the bottom of the display. This is selected by defining
26// LANDSCAPE.
27//
28// * Portrait flip - The screen is taller than it is wide, and the flex
29// connector is on the right of the display. This is
30// selected by defining PORTRAIT_FLIP.
31//
32// * Landscape flip - The screen is wider than it is tall, and the flex
33// connector is on the top of the display. This is
34// selected by defining LANDSCAPE_FLIP.
35//
36// These can also be imagined in terms of screen rotation; if portrait mode is
37// 0 degrees of screen rotation, landscape is 90 degrees of counter-clockwise
38// rotation, portrait flip is 180 degrees of rotation, and landscape flip is
39// 270 degress of counter-clockwise rotation.
40//
41// If no screen orientation is selected, "landscape flip" mode will be used.
42//
43//*****************************************************************************
44#define LANDSCAPE
45
46#if !defined(PORTRAIT) && !defined(PORTRAIT_FLIP) && \
47 !defined(LANDSCAPE) && !defined(LANDSCAPE_FLIP)
48#define LANDSCAPE_FLIP
49#endif
50
51//*****************************************************************************
52//
53// Various definitions controlling coordinate space mapping and drawing
54// direction in the four supported orientations.
55//
56//*****************************************************************************
57#ifdef PORTRAIT
58#define HORIZ_DIRECTION 0x28
59#define VERT_DIRECTION 0x20
60#define MAPPED_X(x, y) (319 - (y))
61#define MAPPED_Y(x, y) (x)
62#endif
63#ifdef LANDSCAPE
64#define HORIZ_DIRECTION 0x00
65#define VERT_DIRECTION 0x08
66#define MAPPED_X(x, y) (319 - (x))
67#define MAPPED_Y(x, y) (239 - (y))
68#endif
69#ifdef PORTRAIT_FLIP
70#define HORIZ_DIRECTION 0x18
71#define VERT_DIRECTION 0x10
72#define MAPPED_X(x, y) (y)
73#define MAPPED_Y(x, y) (239 - (x))
74#endif
75#ifdef LANDSCAPE_FLIP
76#define HORIZ_DIRECTION 0x30
77#define VERT_DIRECTION 0x38
78#define MAPPED_X(x, y) (x)
79#define MAPPED_Y(x, y) (y)
80#endif
81
83// SD2119 registers numbers
85namespace SSD2119 {
86 const uint8_t DEVICE_CODE_READ_REG = 0x00;
87 const uint8_t OSC_START_REG = 0x00;
88 const uint8_t DRV_OUTPUT_CTRL_REG = 0x01;
89 const uint8_t LCD_DRIVE_AC_CTRL_REG = 0x02;
90 const uint8_t PWR_CTRL_1_REG = 0x03;
91 const uint8_t DISPLAY_CTRL_REG = 0x07;
92 const uint8_t FRAME_CYCLE_CTRL_REG = 0x0B;
93 const uint8_t PWR_CTRL_2_REG = 0x0C;
94 const uint8_t PWR_CTRL_3_REG = 0x0D;
95 const uint8_t PWR_CTRL_4_REG = 0x0E;
96 const uint8_t GATE_SCAN_START_REG = 0x0F;
97 const uint8_t SLEEP_MODE_1_REG = 0x10;
98 const uint8_t ENTRY_MODE_REG = 0x11;
99 const uint8_t SLEEP_MODE_2_REG = 0x12;
100 const uint8_t GEN_IF_CTRL_REG = 0x15;
101 const uint8_t HORZ_PORCH_REG = 0x16;
102 const uint8_t VERT_PORCH_REG = 0x17;
103 const uint8_t PWR_CTRL_5_REG = 0x1E;
104 const uint8_t UNIFORMITY_REG = 0x20;
105 const uint8_t RAM_DATA_REG = 0x22;
106 const uint8_t FRAME_FREQ_REG = 0x25;
107 const uint8_t ANALOG_SET_REG = 0x26;
108 const uint8_t VCOM_OTP_1_REG = 0x28;
109 const uint8_t VCOM_OTP_2_REG = 0x29;
110 const uint8_t GAMMA_CTRL_1_REG = 0x30;
111 const uint8_t GAMMA_CTRL_2_REG = 0x31;
112 const uint8_t GAMMA_CTRL_3_REG = 0x32;
113 const uint8_t GAMMA_CTRL_4_REG = 0x33;
114 const uint8_t GAMMA_CTRL_5_REG = 0x34;
115 const uint8_t GAMMA_CTRL_6_REG = 0x35;
116 const uint8_t GAMMA_CTRL_7_REG = 0x36;
117 const uint8_t GAMMA_CTRL_8_REG = 0x37;
118 const uint8_t GAMMA_CTRL_9_REG = 0x3A;
119 const uint8_t GAMMA_CTRL_10_REG = 0x3B;
120 const uint8_t VERT_SCRL_CTRL_1_REG = 0x41;
121 const uint8_t VERT_SCRL_CTRL_2_REG = 0x42;
122 const uint8_t V_RAM_POS_REG = 0x44;
123 const uint8_t H_RAM_START_REG = 0x45;
124 const uint8_t H_RAM_END_REG = 0x46;
125 const uint8_t FIRST_WIN_START_REG = 0x48;
126 const uint8_t FIRST_WIN_END_REG = 0x49;
127 const uint8_t SECOND_WIN_START_REG = 0x4A;
128 const uint8_t SECOND_WIN_END_REG = 0x4B;
129 const uint8_t X_RAM_ADDR_REG = 0x4E;
130 const uint8_t Y_RAM_ADDR_REG = 0x4F;
131}
132
133#define ENTRY_MODE_DEFAULT 0x6830
134#define MAKE_ENTRY_MODE(x) ((ENTRY_MODE_DEFAULT & 0xFF00) | (x))
135
136ssd2119_drv::ssd2119_drv(spi_interface & spi, gpio_interface & rst_pin,
137 gpio_interface & dc_pin, config & lcd,
139 : _spi(spi), _rst_pin(rst_pin), _dc_pin(dc_pin), _lcd(lcd), _mutex(mutex)
140{
141 // Initialize the SPI interface. Do not
142 // generate CS signal for every SPI transfer
143 // (this speeds up the display operation)
144 spi.generateCS(false);
145
146 // Initialize Reset & D/C pins
147 _rst_pin.gpioMode(GPIO::OUTPUT | GPIO::INIT_HIGH);
148 _dc_pin. gpioMode(GPIO::OUTPUT | GPIO::INIT_HIGH);
149
150 // Make a HW-reset
151 _rst_pin.gpioWrite(LOW); task::sleep_ms(100);
152 _rst_pin.gpioWrite(HIGH); task::sleep_ms(100);
153
154 // Activate CS
155 spi.setCS(LOW);
156
157 // Enter sleep mode
158 writeCmdData(SSD2119::SLEEP_MODE_1_REG, 0x0001);
159
160 // Set power control registers
161 writeCmdData(SSD2119::PWR_CTRL_2_REG, 0x0005);
162 writeCmdData(SSD2119::PWR_CTRL_3_REG, 0x000A);
163 writeCmdData(SSD2119::PWR_CTRL_4_REG, 0x2E00);
164 writeCmdData(SSD2119::PWR_CTRL_5_REG, 0x00B2);
165
166 writeCmdData(SSD2119::VCOM_OTP_1_REG, 0x0006);
167 writeCmdData(SSD2119::OSC_START_REG, 0x0001);
168 writeCmdData(SSD2119::DRV_OUTPUT_CTRL_REG, 0x30EF);
169 writeCmdData(SSD2119::LCD_DRIVE_AC_CTRL_REG,0x0600);
170
171 // Wake up from sleep mode
172 writeCmdData(SSD2119::SLEEP_MODE_1_REG, 0x0000);
173 task::sleep_ms(200);
174
175 writeCmdData(SSD2119::ENTRY_MODE_REG, ENTRY_MODE_DEFAULT);
176 writeCmdData(SSD2119::SLEEP_MODE_2_REG, 0x0999);
177 writeCmdData(SSD2119::ANALOG_SET_REG, 0x3800);
178 writeCmdData(SSD2119::DISPLAY_CTRL_REG, 0x0033);
179
180 // Set gamma control registers
181 writeCmdData(SSD2119::GAMMA_CTRL_1_REG, 0x0000);
182 writeCmdData(SSD2119::GAMMA_CTRL_2_REG, 0x0303);
183 writeCmdData(SSD2119::GAMMA_CTRL_3_REG, 0x0407);
184 writeCmdData(SSD2119::GAMMA_CTRL_4_REG, 0x0301);
185 writeCmdData(SSD2119::GAMMA_CTRL_5_REG, 0x0301);
186 writeCmdData(SSD2119::GAMMA_CTRL_6_REG, 0x0403);
187 writeCmdData(SSD2119::GAMMA_CTRL_7_REG, 0x0707);
188 writeCmdData(SSD2119::GAMMA_CTRL_8_REG, 0x0400);
189 writeCmdData(SSD2119::GAMMA_CTRL_9_REG, 0x0a00);
190 writeCmdData(SSD2119::GAMMA_CTRL_10_REG, 0x1000);
191 spi.setCS(HIGH);
192}
193
194ssd2119_drv::~ssd2119_drv()
195{
196}
197
198uint16_t ssd2119_drv::getSizeX()
199{
200#if defined(LANDSCAPE) || defined(LANDSCAPE_FLIP)
201 return _lcd.sizeX;
202#else
203 return _lcd.sizeY;
204#endif
205}
206
207uint16_t ssd2119_drv::getSizeY()
208{
209#if defined(LANDSCAPE) || defined(LANDSCAPE_FLIP)
210 return _lcd.sizeY;
211#else
212 return _lcd.sizeX;
213#endif
214}
215
216void ssd2119_drv::drawPixel(uint16_t x, uint16_t y, color_t c)
217{
218 color_t color = convertColor(c, LCD::COLORTYPE_RGB565);
219 if (_mutex) _mutex->lock();
220 _spi.setCS(LOW);
221 writeCmdData(SSD2119::X_RAM_ADDR_REG, MAPPED_X(x, y));
222 writeCmdData(SSD2119::Y_RAM_ADDR_REG, MAPPED_Y(x, y));
223 writeCmdData(SSD2119::RAM_DATA_REG, color);
224 _spi.setCS(HIGH);
225 if (_mutex) _mutex->unlock();
226}
227
228void ssd2119_drv::drawHLine(uint16_t xs, uint16_t y, uint16_t xe, color_t c)
229{
230 color_t color = convertColor(c, LCD::COLORTYPE_RGB565);
231 if (_mutex) _mutex->lock();
232 _spi.setCS(LOW);
233 setCursorLtoR(xs, y);
234 int index = 0;
235 while(xs++ <= xe) {
236 _tx_buffer[index++] = color >> 8;
237 _tx_buffer[index++] = color & 0xff;
238 }
239 writeDataBuffer(index);
240 _spi.setCS(HIGH);
241 if (_mutex) _mutex->unlock();
242}
243
244void ssd2119_drv::drawVLine(uint16_t x, uint16_t ys, uint16_t ye, color_t c)
245{
246 color_t color = convertColor(c, LCD::COLORTYPE_RGB565);
247 if (_mutex) _mutex->lock();
248 _spi.setCS(LOW);
249 setCursorTtoB(x, ys);
250 int index = 0;
251 while(ys++ <= ye) {
252 _tx_buffer[index++] = color >> 8;
253 _tx_buffer[index++] = color & 0xff;
254 }
255 writeDataBuffer(index);
256 _spi.setCS(HIGH);
257 if (_mutex) _mutex->unlock();
258}
259
260void ssd2119_drv::drawArea(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye,
261 pixel_stream & ps)
262{
263 bool color_conversion = (ps.getColorType() != LCD::COLORTYPE_RGB565);
264 if (_mutex) _mutex->lock();
265 _spi.setCS(LOW);
266 for (int y = ys; y <= ye; y++) {
267 setCursorLtoR(xs, y);
268 int index = 0;
269 for (int x = xs; x <= xe; x++) {
270 color_t color = ps.getNext();
271 if (color_conversion) {
272 color = convertColor(color, LCD::COLORTYPE_RGB565);
273 }
274 _tx_buffer[index++] = color >> 8;
275 _tx_buffer[index++] = color & 0xff;
276 }
277 writeDataBuffer(index);
278 }
279 _spi.setCS(HIGH);
280 if (_mutex) _mutex->unlock();
281}
282
283void ssd2119_drv::fillArea(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye,
284 color_t c)
285{
286 pixel_stream_const ps(convertColor(c, LCD::COLORTYPE_RGB565));
287 drawArea(xs, ys, xe, ye, ps);
288}
289
290
291void ssd2119_drv::clearScreen(color_t c)
292{
293 fillArea(0, 0, getSizeX(), getSizeY(), c);
294}
295
296void ssd2119_drv::setCursorLtoR(uint16_t x, uint16_t y)
297{
298 writeCmdData(SSD2119::ENTRY_MODE_REG, MAKE_ENTRY_MODE(HORIZ_DIRECTION));
299 writeCmdData(SSD2119::X_RAM_ADDR_REG, MAPPED_X(x, y));
300 writeCmdData(SSD2119::Y_RAM_ADDR_REG, MAPPED_Y(x, y));
301 writeCommand(SSD2119::RAM_DATA_REG);
302}
303
304void ssd2119_drv::setCursorTtoB(uint16_t x, uint16_t y)
305{
306 writeCmdData(SSD2119::ENTRY_MODE_REG, MAKE_ENTRY_MODE(VERT_DIRECTION));
307 writeCmdData(SSD2119::X_RAM_ADDR_REG, MAPPED_X(x, y));
308 writeCmdData(SSD2119::Y_RAM_ADDR_REG, MAPPED_Y(x, y));
309 writeCommand(SSD2119::RAM_DATA_REG);
310}
311
312//void ssd2119_drv::setCursorFrame(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye)
313//{
314// writeCmdData(SSD2119::ENTRY_MODE_REG, MAKE_ENTRY_MODE(HORIZ_DIRECTION));
315// writeCmdData(SSD2119::V_RAM_POS_REG, (ye << 8) | ys);
316// writeCmdData(SSD2119::H_RAM_START_REG, xs);
317// writeCmdData(SSD2119::H_RAM_END_REG, xe);
318// writeCmdData(SSD2119::X_RAM_ADDR_REG, xs);
319// writeCmdData(SSD2119::Y_RAM_ADDR_REG, ys);
320// writeCommand(SSD2119::RAM_DATA_REG);
321// // writeCmdData(SSD2119::V_RAM_POS_REG, (uint16_t)(240 - 1) << 8);
322// // writeCmdData(SSD2119::H_RAM_START_REG, 0x0000);
323// // writeCmdData(SSD2119::H_RAM_END_REG, 320 - 1);
324// // writeCmdData(SSD2119::X_RAM_ADDR_REG, 0x0000);
325// // writeCmdData(SSD2119::Y_RAM_ADDR_REG, 0x0000);
326// // writeCommand(SSD2119::RAM_DATA_REG);
327// // for(int ulCount = 0; ulCount < 76800; ulCount++)
328// // {
329// // writeData(0x0); // Black
330// // }
331//
332//}
333
334void ssd2119_drv::writeDataBuffer(int len)
335{
336 _spi.spiTx(_tx_buffer, len);
337}
338
339void ssd2119_drv::writeCommand(uint8_t cmd)
340{
341 // Write command byte
342 _dc_pin.gpioWrite(LOW);
343 _spi.spiTx(&cmd, 1);
344 _dc_pin.gpioWrite(HIGH);
345}
346
347void ssd2119_drv::writeCmdData(uint8_t cmd, uint16_t data)
348{
349 // Write command byte
350 _dc_pin.gpioWrite(LOW);
351 _spi.spiTx(&cmd, 1);
352 _dc_pin.gpioWrite(HIGH);
353 // Write 2 data bytes (MSB first)
354 data = __builtin_bswap16(data);
355 _spi.spiTx((uint8_t *)&data, 2);
356}
357
Definition mutex.h:27