1 /*
2 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3 * Copyright (c) 2014 Intel Corporation.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <iostream>
26 #include <string>
27 #include <stdexcept>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "st7735.h"
34
35 using namespace upm;
36
ST7735(uint8_t csLCD,uint8_t cSD,uint8_t rs,uint8_t rst)37 ST7735::ST7735 (uint8_t csLCD, uint8_t cSD, uint8_t rs, uint8_t rst)
38 : GFX (160, 128, m_map, font), m_csLCDPinCtx(csLCD), m_cSDPinCtx(cSD),
39 m_rSTPinCtx(rst), m_rSPinCtx(rs), m_spi(0) {
40
41 initModule ();
42 configModule ();
43 }
44
45 void
initModule()46 ST7735::initModule () {
47 mraa::Result error = mraa::SUCCESS;
48
49 m_height = 160;
50 m_width = 128;
51
52 m_spi.frequency(15 * 1000000);
53
54 error = m_csLCDPinCtx.dir(mraa::DIR_OUT);
55 if (error != mraa::SUCCESS) {
56 mraa::printError (error);
57 }
58
59 error = m_cSDPinCtx.dir(mraa::DIR_OUT);
60 if (error != mraa::SUCCESS) {
61 mraa::printError (error);
62 }
63
64 error = m_rSTPinCtx.dir(mraa::DIR_OUT);
65 if (error != mraa::SUCCESS) {
66 mraa::printError (error);
67 }
68
69 error = m_rSPinCtx.dir(mraa::DIR_OUT);
70 if (error != mraa::SUCCESS) {
71 mraa::printError (error);
72 }
73
74 error = m_spi.frequency(15 * 1000000);
75 if (error != mraa::SUCCESS) {
76 mraa::printError (error);
77 }
78
79 lcdCSOn ();
80 }
81
82 void
write(uint8_t value)83 ST7735::write (uint8_t value) {
84 rsLOW ();
85 m_spi.writeByte(value);
86 }
87
88 void
data(uint8_t value)89 ST7735::data (uint8_t value) {
90 rsHIGH ();
91 m_spi.writeByte(value);
92 }
93
94 void
executeCMDList(const uint8_t * addr)95 ST7735::executeCMDList(const uint8_t *addr) {
96 uint8_t numCommands, numArgs;
97 uint16_t ms;
98
99 numCommands = *(addr++); // Number of commands to follow
100 while(numCommands--) { // For each command...
101 write (*(addr++)); // Read, issue command
102 numArgs = *(addr++); // Number of args to follow
103 ms = numArgs & DELAY; // If hibit set, delay follows args
104 numArgs &= ~DELAY; // Mask out delay bit
105 while(numArgs--) { // For each argument...
106 data (*(addr++)); // Read, issue argument
107 }
108
109 if(ms) {
110 ms = *(addr++); // Read post-command delay time (ms)
111 if (ms == 255) {
112 ms = 500; // If 255, delay for 500 ms
113 }
114 usleep (ms * 1000);
115 }
116 }
117 }
118
119 void
setAddrWindow(uint8_t x0,uint8_t y0,uint8_t x1,uint8_t y1)120 ST7735::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
121 uint8_t colstart, rowstart;
122 colstart = rowstart = 0;
123
124 write (ST7735_CASET); // Column addr set
125
126 rsHIGH ();
127 m_spiBuffer[0] = 0x00;
128 m_spiBuffer[1] = x0 + colstart; // XSTART
129 m_spiBuffer[2] = 0x00;
130 m_spiBuffer[3] = x1 + colstart; // XEND
131 m_spi.write(m_spiBuffer, 4);
132
133 write (ST7735_RASET); // Row addr set
134
135 rsHIGH ();
136 m_spiBuffer[0] = 0x00;
137 m_spiBuffer[1] = y0 + rowstart; // YSTART
138 m_spiBuffer[2] = 0x00;
139 m_spiBuffer[3] = y1 + rowstart; // YEND
140 m_spi.write(m_spiBuffer, 4);
141
142 write (ST7735_RAMWR); // write to RAM
143 }
144
145 void
drawPixel(int16_t x,int16_t y,uint16_t color)146 ST7735::drawPixel(int16_t x, int16_t y, uint16_t color) {
147 if (mraa::SUCCESS != setPixel (x, y, color)) {
148 return;
149 }
150
151 refresh ();
152 }
153
154 void
refresh()155 ST7735::refresh () {
156 rsHIGH ();
157
158 int fragmentSize = m_height * m_width * 2 / 20;
159 for (int fragment = 0; fragment < 20; fragment++) {
160 m_spi.write(&m_map[fragment * fragmentSize], fragmentSize);
161 }
162 }
163
164 void
configModule()165 ST7735::configModule() {
166 rsHIGH ();
167 lcdCSOff ();
168 lcdCSOn ();
169
170 m_rSTPinCtx.write(HIGH);
171 usleep (500000);
172 m_rSTPinCtx.write(LOW);
173 usleep (500000);
174 m_rSTPinCtx.write(HIGH);
175 usleep (500000);
176
177 executeCMDList (Rcmd1);
178 executeCMDList (Rcmd2red);
179 executeCMDList (Rcmd3);
180
181 write (ST7735_MADCTL);
182 data (0xC0);
183
184 setAddrWindow (0, 0, m_width - 1, m_height - 1);
185
186 fillScreen (ST7735_BLACK);
187 refresh ();
188 }
189
190 mraa::Result
lcdCSOn()191 ST7735::lcdCSOn () {
192 mraa::Result error = mraa::SUCCESS;
193
194 error = m_csLCDPinCtx.write(LOW);
195 if (error != mraa::SUCCESS) {
196 mraa::printError (error);
197 }
198
199 error = m_cSDPinCtx.write(HIGH);
200 if (error != mraa::SUCCESS) {
201 mraa::printError (error);
202 }
203
204 return error;
205 }
206
207 mraa::Result
lcdCSOff()208 ST7735::lcdCSOff () {
209 mraa::Result error = mraa::SUCCESS;
210
211 error = m_csLCDPinCtx.write(HIGH);
212 if (error != mraa::SUCCESS) {
213 mraa::printError (error);
214 }
215
216 return error;
217 }
218
219 mraa::Result
sdCSOn()220 ST7735::sdCSOn () {
221 mraa::Result error = mraa::SUCCESS;
222
223 error = m_cSDPinCtx.write(LOW);
224 if (error != mraa::SUCCESS) {
225 mraa::printError (error);
226 }
227
228 error = m_csLCDPinCtx.write(HIGH);
229 if (error != mraa::SUCCESS) {
230 mraa::printError (error);
231 }
232
233 return error;
234 }
235
236 mraa::Result
sdCSOff()237 ST7735::sdCSOff () {
238 mraa::Result error = mraa::SUCCESS;
239
240 error = m_cSDPinCtx.write(HIGH);
241 if (error != mraa::SUCCESS) {
242 mraa::printError (error);
243 }
244
245 return error;
246 }
247
248 mraa::Result
rsHIGH()249 ST7735::rsHIGH () {
250 mraa::Result error = mraa::SUCCESS;
251
252 error = m_rSPinCtx.write(HIGH);
253 if (error != mraa::SUCCESS) {
254 mraa::printError (error);
255 }
256
257 return error;
258 }
259
260 mraa::Result
rsLOW()261 ST7735::rsLOW () {
262 mraa::Result error = mraa::SUCCESS;
263
264 error = m_rSPinCtx.write(LOW);
265 if (error != mraa::SUCCESS) {
266 mraa::printError (error);
267 }
268
269 return error;
270 }
271