ddc8694aacd50f30b2979ab1910d23bd91cfb519
[hackover2013-badge-firmware.git] / drivers / lcd / tft / hw / ssd1331.c
1 /**************************************************************************/
2 /*!
3 @file SSD1331.c
4 @author K. Townsend (microBuilder.eu)
5
6 @section DESCRIPTION
7
8 Driver for SSD1331 96x64 pixel RGB OLED displays.
9
10 This driver uses a bit-banged SPI interface and 16-bit RGB565 colours.
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2010, microBuilder SARL
17 All rights reserved.
18
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 /**************************************************************************/
42 #include "ssd1331.h"
43 #include "core/systick/systick.h"
44
45 static volatile lcdOrientation_t lcdOrientation = LCD_ORIENTATION_PORTRAIT;
46 static lcdProperties_t ssd1331Properties = { 96, 64, false, false, false };
47
48 /*************************************************/
49 /* Private Methods */
50 /*************************************************/
51
52 // You can speed all of these slow GPIO calls up by using the SET/CLR macros!
53
54 #define CMD(c) do { gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
55 gpioSetValue( SSD1331_DC_PORT, SSD1331_DC_PIN, 0 ); \
56 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 0 ); \
57 ssd1331SendByte( c ); \
58 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
59 } while (0);
60 #define DATA(c) do { gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
61 gpioSetValue( SSD1331_DC_PORT, SSD1331_DC_PIN, 1 ); \
62 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 0 ); \
63 ssd1331SendByte( c ); \
64 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
65 } while (0);
66 #define DELAY(mS) do { systickDelay( mS / CFG_SYSTICK_DELAY_IN_MS ); } while(0);
67
68 /**************************************************************************/
69 /*!
70 @brief Simulates an SPI write using GPIO
71
72 @param[in] byte
73 The byte to send
74 */
75 /**************************************************************************/
76 void ssd1331SendByte(uint8_t byte)
77 {
78 int8_t i;
79
80 // Make sure clock pin starts high
81 gpioSetValue(SSD1331_SCK_PORT, SSD1331_SCK_PIN, 1);
82
83 // Write from MSB to LSB
84 for (i=7; i>=0; i--)
85 {
86 // Set clock pin low
87 gpioSetValue(SSD1331_SCK_PORT, SSD1331_SCK_PIN, 0);
88 // Set data pin high or low depending on the value of the current bit
89 gpioSetValue(SSD1331_SID_PORT, SSD1331_SID_PIN, byte & (1 << i) ? 1 : 0);
90 // Set clock pin high
91 gpioSetValue(SSD1331_SCK_PORT, SSD1331_SCK_PIN, 1);
92 }
93 }
94
95 /**************************************************************************/
96 /*!
97 @brief Reads a 16-bit value from the 8-bit data bus
98 */
99 /**************************************************************************/
100 uint16_t ssd1331ReadData(void)
101 {
102 // ToDo
103 return 0;
104 }
105
106 /**************************************************************************/
107 /*!
108 @brief Reads a 16-bit value
109 */
110 /**************************************************************************/
111 uint16_t ssd1331Read(uint16_t addr)
112 {
113 // ToDo
114 return 0;
115 }
116
117 /**************************************************************************/
118 /*!
119 @brief Returns the 16-bit (4-hexdigit) controller code
120 */
121 /**************************************************************************/
122 uint16_t ssd1331Type(void)
123 {
124 // ToDo
125 return 0;
126 }
127
128 /**************************************************************************/
129 /*!
130 @brief Sets the cursor to the specified X/Y position
131 */
132 /**************************************************************************/
133 void ssd1331SetCursor(uint8_t x, uint8_t y)
134 {
135 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
136 return;
137 // set x and y coordinate
138 CMD(SSD1331_CMD_SETCOLUMN);
139 CMD(x);
140 CMD(ssd1331Properties.width-1);
141
142 CMD(SSD1331_CMD_SETROW);
143 CMD(y);
144 CMD(ssd1331Properties.height-1);
145 }
146
147 /**************************************************************************/
148 /*!
149 @brief Draws a solid line using HW acceleration
150 */
151 /**************************************************************************/
152 void ssd1331DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
153 {
154 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
155 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
156 return;
157 }
158
159 CMD(SSD1331_CMD_DRAWLINE);
160 CMD(x1);
161 CMD(y1);
162 CMD(x2);
163 CMD(y2);
164 CMD((color >> 11) << 1);
165 CMD((color >> 5) & 0x3F);
166 CMD((color << 1)& 0x3F);
167 }
168
169 /**************************************************************************/
170 /*!
171 @brief Draws a filled rectangle using HW acceleration
172 */
173 /**************************************************************************/
174 void ssd1331FillRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t pencolor, uint16_t fillcolor)
175 {
176 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
177 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
178 return;
179 }
180
181 // fill!
182 CMD(SSD1331_CMD_FILL);
183 CMD(0x01);
184
185 CMD(SSD1331_CMD_DRAWRECT);
186 CMD(x1);
187 CMD(y1);
188 CMD(x2);
189 CMD(y2);
190 CMD((pencolor >> 11) << 1);
191 CMD((pencolor >> 5) & 0x3F);
192 CMD((pencolor << 1)& 0x3F);
193
194 CMD((fillcolor >> 11) << 1);
195 CMD((fillcolor >> 5) & 0x3F);
196 CMD((fillcolor << 1)& 0x3F);
197 }
198
199 /**************************************************************************/
200 /*!
201 @brief Inverts the R and B in an RGB565 color
202 */
203 /**************************************************************************/
204 uint16_t invert565Color(uint16_t color)
205 {
206 uint16_t r, g, b;
207
208 b = (color>>0) & 0x1f;
209 g = (color>>5) & 0x3f;
210 r = (color>>11) & 0x1f;
211
212 return( (b<<11) + (g<<5) + (r<<0) );
213 }
214
215 /*************************************************/
216 /* Public Methods */
217 /*************************************************/
218
219 /**************************************************************************/
220 /*!
221 @brief Configures any pins or HW and initialises the LCD controller
222 */
223 /**************************************************************************/
224 void lcdInit(void)
225 {
226 // Set all pins to output
227 gpioSetDir(SSD1331_SCK_PORT, SSD1331_SCK_PIN, gpioDirection_Output);
228 gpioSetDir(SSD1331_SID_PORT, SSD1331_SID_PIN, gpioDirection_Output);
229 gpioSetDir(SSD1331_DC_PORT, SSD1331_DC_PIN, gpioDirection_Output);
230 gpioSetDir(SSD1331_RST_PORT, SSD1331_RST_PIN, gpioDirection_Output);
231 gpioSetDir(SSD1331_CS_PORT, SSD1331_CS_PIN, gpioDirection_Output);
232
233 // Reset the LCD
234 SET_RST;
235 DELAY(1);
236 CLR_RST;
237 DELAY(10);
238 SET_RST;
239
240 // Disable pullups
241 SSD1331_DISABLEPULLUPS();
242
243 CMD(SSD1331_CMD_DISPLAYOFF); // 0xAE
244 CMD(SSD1331_CMD_SETREMAP); // 0xA0
245 CMD(0x76); // 0x74
246 CMD(SSD1331_CMD_STARTLINE); // 0xA1
247 CMD(0x0);
248 CMD(SSD1331_CMD_DISPLAYOFFSET); // 0xA2
249 CMD(0x0);
250 CMD(SSD1331_CMD_NORMALDISPLAY); // 0xA4
251 CMD(SSD1331_CMD_SETMULTIPLEX); // 0xA8
252 CMD(0x3F); // 0x3F 1/64 duty
253 CMD(SSD1331_CMD_SETMASTER); // 0xAD
254 CMD(0x8E);
255 CMD(SSD1331_CMD_POWERMODE); // 0xB0
256 CMD(0x0B);
257 CMD(SSD1331_CMD_PRECHARGE); // 0xB1
258 CMD(0x31);
259 CMD(SSD1331_CMD_CLOCKDIV); // 0xB3
260 CMD(0xF0); // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
261 CMD(SSD1331_CMD_PRECHARGEA); // 0x8A
262 CMD(0x64);
263 CMD(SSD1331_CMD_PRECHARGEB); // 0x8B
264 CMD(0x78);
265 CMD(SSD1331_CMD_PRECHARGEA); // 0x8C
266 CMD(0x64);
267 CMD(SSD1331_CMD_PRECHARGELEVEL); // 0xBB
268 CMD(0x3A);
269 CMD(SSD1331_CMD_VCOMH); // 0xBE
270 CMD(0x3E);
271 CMD(SSD1331_CMD_MASTERCURRENT); // 0x87
272 CMD(0x06);
273 CMD(SSD1331_CMD_CONTRASTA); // 0x81
274 CMD(0x91);
275 CMD(SSD1331_CMD_CONTRASTB); // 0x82
276 CMD(0x50);
277 CMD(SSD1331_CMD_CONTRASTC); // 0x83
278 CMD(0x7D);
279 CMD(SSD1331_CMD_DISPLAYON);//--turn on oled panel
280
281 // Fill black
282 lcdFillRGB(COLOR_BLACK);
283 }
284
285 /**************************************************************************/
286 /*!
287 @brief Enables or disables the LCD backlight
288 */
289 /**************************************************************************/
290 void lcdBacklight(bool state)
291 {
292 // No backlight ... do nothing
293 }
294
295 /**************************************************************************/
296 /*!
297 @brief Renders a simple test pattern on the LCD
298 */
299 /**************************************************************************/
300 void lcdTest(void)
301 {
302 uint32_t i,j;
303 ssd1331SetCursor(0, 0);
304
305 for(i=0;i<64;i++)
306 {
307 for(j=0;j<96;j++)
308 {
309 if(i>55){DATA(invert565Color(COLOR_WHITE)>>8);DATA(invert565Color(COLOR_WHITE));}
310 else if(i>47){DATA(invert565Color(COLOR_BLUE)>>8);DATA(invert565Color(COLOR_BLUE));}
311 else if(i>39){DATA(invert565Color(COLOR_GREEN)>>8);DATA(invert565Color(COLOR_GREEN));}
312 else if(i>31){DATA(invert565Color(COLOR_CYAN)>>8);DATA(invert565Color(COLOR_CYAN));}
313 else if(i>23){DATA(invert565Color(COLOR_RED)>>8);DATA(invert565Color(COLOR_RED));}
314 else if(i>15){DATA(invert565Color(COLOR_MAGENTA)>>8);DATA(invert565Color(COLOR_MAGENTA));}
315 else if(i>7){DATA(invert565Color(COLOR_YELLOW)>>8);DATA(invert565Color(COLOR_YELLOW));}
316 else {DATA(invert565Color(COLOR_BLACK)>>8);DATA(invert565Color(COLOR_BLACK));}
317 }
318 }
319 }
320
321 /**************************************************************************/
322 /*!
323 @brief Fills the LCD with the specified 16-bit color
324 */
325 /**************************************************************************/
326 void lcdFillRGB(uint16_t data)
327 {
328 data = invert565Color(data);
329 ssd1331FillRect(0,0,ssd1331Properties.width-1,ssd1331Properties.height-1, data, data);
330 }
331
332 /**************************************************************************/
333 /*!
334 @brief Draws a single pixel at the specified X/Y location
335 */
336 /**************************************************************************/
337 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
338 {
339 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
340 return;
341
342 ssd1331SetCursor((uint8_t)x, (uint8_t)y);
343 color = invert565Color(color);
344 DATA(color >> 8);
345 DATA(color);
346 }
347
348 /**************************************************************************/
349 /*!
350 @brief Draws an array of consecutive RGB565 pixels (much
351 faster than addressing each pixel individually)
352 */
353 /**************************************************************************/
354 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
355 {
356 // ToDo
357 }
358
359 /**************************************************************************/
360 /*!
361 @brief Optimised routine to draw a horizontal line faster than
362 setting individual pixels
363 */
364 /**************************************************************************/
365 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
366 {
367 color = invert565Color(color);
368 ssd1331DrawLine((uint8_t)x0, (uint8_t)y, (uint8_t)x1, (uint8_t)y, color);
369 }
370
371 /**************************************************************************/
372 /*!
373 @brief Optimised routine to draw a vertical line faster than
374 setting individual pixels
375 */
376 /**************************************************************************/
377 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
378 {
379 color = invert565Color(color);
380 ssd1331DrawLine((uint8_t)x, (uint8_t)y0, (uint8_t)x, (uint8_t)y1, color);
381 }
382
383 /**************************************************************************/
384 /*!
385 @brief Gets the 16-bit color of the pixel at the specified location
386 */
387 /**************************************************************************/
388 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
389 {
390 // ToDo
391 return 0;
392 }
393
394 /**************************************************************************/
395 /*!
396 @brief Sets the LCD orientation to horizontal and vertical
397 */
398 /**************************************************************************/
399 void lcdSetOrientation(lcdOrientation_t orientation)
400 {
401 // Not supported
402 }
403
404 /**************************************************************************/
405 /*!
406 @brief Gets the current screen orientation (horizontal or vertical)
407 */
408 /**************************************************************************/
409 lcdOrientation_t lcdGetOrientation(void)
410 {
411 return lcdOrientation;
412 }
413
414 /**************************************************************************/
415 /*!
416 @brief Gets the width in pixels of the LCD screen (varies depending
417 on the current screen orientation)
418 */
419 /**************************************************************************/
420 uint16_t lcdGetWidth(void)
421 {
422 return ssd1331Properties.width;
423 }
424
425 /**************************************************************************/
426 /*!
427 @brief Gets the height in pixels of the LCD screen (varies depending
428 on the current screen orientation)
429 */
430 /**************************************************************************/
431 uint16_t lcdGetHeight(void)
432 {
433 return ssd1331Properties.height;
434 }
435
436 /**************************************************************************/
437 /*!
438 @brief Scrolls the contents of the LCD screen vertically the
439 specified number of pixels using a HW optimised routine
440 */
441 /**************************************************************************/
442 void lcdScroll(int16_t pixels, uint16_t fillColor)
443 {
444 // ToDo
445 }
446
447 /**************************************************************************/
448 /*!
449 @brief Gets the controller's 16-bit (4 hexdigit) ID
450 */
451 /**************************************************************************/
452 uint16_t lcdGetControllerID(void)
453 {
454 return ssd1331Type();
455 }
456
457 /**************************************************************************/
458 /*!
459 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
460 generic capabilities and dimensions
461 */
462 /**************************************************************************/
463 lcdProperties_t lcdGetProperties(void)
464 {
465 return ssd1331Properties;
466 }
This page took 0.083609 seconds and 3 git commands to generate.