Added SSD1331_COLORORDER_RGB/BGR flag
[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 #define CMD(c) do { SET_CS; CLR_DC; CLR_CS; ssd1331SendByte( c ); SET_CS; } while (0)
53 #define DATA(c) do { SET_CS; SET_DC; CLR_CS; ssd1331SendByte( c ); SET_CS; } while (0);
54 #define DELAY(mS) do { systickDelay( mS / CFG_SYSTICK_DELAY_IN_MS ); } while(0);
55
56 /**************************************************************************/
57 /*!
58 @brief Simulates an SPI write using GPIO
59
60 @param[in] byte
61 The byte to send
62 */
63 /**************************************************************************/
64 void ssd1331SendByte(uint8_t byte)
65 {
66 int8_t i;
67
68 // Make sure clock pin starts high
69 SET_SCK;
70
71 // Write from MSB to LSB
72 for (i=7; i>=0; i--)
73 {
74 // Set clock pin low
75 CLR_SCK;
76 // Set data pin high or low depending on the value of the current bit
77 if (byte & (1 << i))
78 {
79 SET_SID;
80 }
81 else
82 {
83 CLR_SID;
84 }
85 // Set clock pin high
86 SET_SCK;
87 }
88 }
89
90 /**************************************************************************/
91 /*!
92 @brief Reads a 16-bit value from the 8-bit data bus
93 */
94 /**************************************************************************/
95 uint16_t ssd1331ReadData(void)
96 {
97 // ToDo
98 return 0;
99 }
100
101 /**************************************************************************/
102 /*!
103 @brief Reads a 16-bit value
104 */
105 /**************************************************************************/
106 uint16_t ssd1331Read(uint16_t addr)
107 {
108 // ToDo
109 return 0;
110 }
111
112 /**************************************************************************/
113 /*!
114 @brief Returns the 16-bit (4-hexdigit) controller code
115 */
116 /**************************************************************************/
117 uint16_t ssd1331Type(void)
118 {
119 return 0x1331;
120 }
121
122 /**************************************************************************/
123 /*!
124 @brief Sets the cursor to the specified X/Y position
125 */
126 /**************************************************************************/
127 void ssd1331SetCursor(uint8_t x, uint8_t y)
128 {
129 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
130 return;
131 // set x and y coordinate
132 CMD(SSD1331_CMD_SETCOLUMN);
133 CMD(x);
134 CMD(ssd1331Properties.width-1);
135
136 CMD(SSD1331_CMD_SETROW);
137 CMD(y);
138 CMD(ssd1331Properties.height-1);
139 }
140
141 /**************************************************************************/
142 /*!
143 @brief Draws a solid line using HW acceleration
144 */
145 /**************************************************************************/
146 void ssd1331DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
147 {
148 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
149 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
150 return;
151 }
152
153 CMD(SSD1331_CMD_DRAWLINE);
154 CMD(x1);
155 CMD(y1);
156 CMD(x2);
157 CMD(y2);
158 CMD((color >> 11) << 1);
159 CMD((color >> 5) & 0x3F);
160 CMD((color << 1)& 0x3F);
161 }
162
163 /**************************************************************************/
164 /*!
165 @brief Draws a filled rectangle using HW acceleration
166 */
167 /**************************************************************************/
168 void ssd1331FillRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t pencolor, uint16_t fillcolor)
169 {
170 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
171 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
172 return;
173 }
174
175 // fill!
176 CMD(SSD1331_CMD_FILL);
177 CMD(0x01);
178
179 CMD(SSD1331_CMD_DRAWRECT);
180 CMD(x1);
181 CMD(y1);
182 CMD(x2);
183 CMD(y2);
184 CMD((pencolor >> 11) << 1);
185 CMD((pencolor >> 5) & 0x3F);
186 CMD((pencolor << 1)& 0x3F);
187
188 CMD((fillcolor >> 11) << 1);
189 CMD((fillcolor >> 5) & 0x3F);
190 CMD((fillcolor << 1)& 0x3F);
191 }
192
193 /**************************************************************************/
194 /*!
195 @brief Inverts the R and B in an RGB565 color
196 */
197 /**************************************************************************/
198 uint16_t invert565Color(uint16_t color)
199 {
200 uint16_t r, g, b;
201
202 b = (color>>0) & 0x1f;
203 g = (color>>5) & 0x3f;
204 r = (color>>11) & 0x1f;
205
206 return( (b<<11) + (g<<5) + (r<<0) );
207 }
208
209 /*************************************************/
210 /* Public Methods */
211 /*************************************************/
212
213 /**************************************************************************/
214 /*!
215 @brief Configures any pins or HW and initialises the LCD controller
216 */
217 /**************************************************************************/
218 void lcdInit(void)
219 {
220 // Set all pins to output
221 gpioSetDir(SSD1331_SCK_PORT, SSD1331_SCK_PIN, gpioDirection_Output);
222 gpioSetDir(SSD1331_SID_PORT, SSD1331_SID_PIN, gpioDirection_Output);
223 gpioSetDir(SSD1331_DC_PORT, SSD1331_DC_PIN, gpioDirection_Output);
224 gpioSetDir(SSD1331_RST_PORT, SSD1331_RST_PIN, gpioDirection_Output);
225 gpioSetDir(SSD1331_CS_PORT, SSD1331_CS_PIN, gpioDirection_Output);
226
227 // Reset the LCD
228 SET_RST;
229 DELAY(1);
230 CLR_RST;
231 DELAY(10);
232 SET_RST;
233
234 // Disable pullups
235 SSD1331_DISABLEPULLUPS();
236
237 CMD(SSD1331_CMD_DISPLAYOFF); // 0xAE
238 CMD(SSD1331_CMD_SETREMAP); // 0xA0
239 // A[2] = 1 = color order (0 = RGB, 1 = BGR)
240 // A[7:6] = 01 = 65K color
241 #if defined SSD1331_COLORORDER_BGR
242 CMD(0x76);
243 #else
244 CMD(0x72);
245 #endif
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.069606 seconds and 5 git commands to generate.