b9e5d1a069c9e02d66e77f161bea8c9a33b0af58
[hackover2013-badge-firmware.git] / drivers / displays / 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 Sets the cursor to the specified X/Y position
115 */
116 /**************************************************************************/
117 void ssd1331SetCursor(uint8_t x, uint8_t y)
118 {
119 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
120 return;
121 // set x and y coordinate
122 CMD(SSD1331_CMD_SETCOLUMN);
123 CMD(x);
124 CMD(ssd1331Properties.width-1);
125
126 CMD(SSD1331_CMD_SETROW);
127 CMD(y);
128 CMD(ssd1331Properties.height-1);
129 }
130
131 /**************************************************************************/
132 /*!
133 @brief Draws a solid line using HW acceleration
134 */
135 /**************************************************************************/
136 void ssd1331DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
137 {
138 uint16_t x, pixels;
139
140 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
141 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
142 return;
143 }
144
145 // Switch x2 and x1 if required
146 if (x2 < x1)
147 {
148 x = x2;
149 x2 = x1;
150 x1 = x;
151 }
152
153 // Switch y2 and y1 if required
154 if (y2 < y1)
155 {
156 x = y2;
157 y2 = y1;
158 y1 = x;
159 }
160
161 CMD(SSD1331_CMD_DRAWLINE);
162 CMD(x1);
163 CMD(y1);
164 CMD(x2);
165 CMD(y2);
166 CMD((uint8_t)((color >> 11) & 0x1F));
167 CMD((uint8_t)((color >> 5) & 0x3F));
168 CMD((uint8_t)(color & 0x1F));
169
170 }
171
172 /**************************************************************************/
173 /*!
174 @brief Draws a filled rectangle using HW acceleration
175 */
176 /**************************************************************************/
177 void ssd1331FillRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t pencolor, uint16_t fillcolor)
178 {
179 if ((x1 >= ssd1331Properties.width) || (x2 >= ssd1331Properties.width) ||
180 (y1 >= ssd1331Properties.height) || (y2 >= ssd1331Properties.height)) {
181 return;
182 }
183
184 // fill!
185 CMD(SSD1331_CMD_FILL);
186 CMD(0x01);
187
188 CMD(SSD1331_CMD_DRAWRECT);
189 CMD(x1);
190 CMD(y1);
191 CMD(x2);
192 CMD(y2);
193 CMD((pencolor >> 11) << 1);
194 CMD((pencolor >> 5) & 0x3F);
195 CMD((pencolor << 1)& 0x3F);
196
197 CMD((fillcolor >> 11) << 1);
198 CMD((fillcolor >> 5) & 0x3F);
199 CMD((fillcolor << 1)& 0x3F);
200 }
201
202 /**************************************************************************/
203 /*!
204 @brief Inverts the R and B in an RGB565 color
205 */
206 /**************************************************************************/
207 uint16_t invert565Color(uint16_t color)
208 {
209 uint16_t r, g, b;
210
211 b = (color>>0) & 0x1f;
212 g = (color>>5) & 0x3f;
213 r = (color>>11) & 0x1f;
214
215 return( (b<<11) + (g<<5) + (r<<0) );
216 }
217
218 /*************************************************/
219 /* Public Methods */
220 /*************************************************/
221
222 /**************************************************************************/
223 /*!
224 @brief Configures any pins or HW and initialises the LCD controller
225 */
226 /**************************************************************************/
227 void lcdInit(void)
228 {
229 // Set all pins to output
230 gpioSetDir(SSD1331_SCK_PORT, SSD1331_SCK_PIN, gpioDirection_Output);
231 gpioSetDir(SSD1331_SID_PORT, SSD1331_SID_PIN, gpioDirection_Output);
232 gpioSetDir(SSD1331_DC_PORT, SSD1331_DC_PIN, gpioDirection_Output);
233 gpioSetDir(SSD1331_RST_PORT, SSD1331_RST_PIN, gpioDirection_Output);
234 gpioSetDir(SSD1331_CS_PORT, SSD1331_CS_PIN, gpioDirection_Output);
235
236 // Reset the LCD
237 SET_RST;
238 DELAY(1);
239 CLR_RST;
240 DELAY(10);
241 SET_RST;
242
243 // Disable pullups
244 SSD1331_DISABLEPULLUPS();
245
246 CMD(SSD1331_CMD_DISPLAYOFF); // 0xAE
247 CMD(SSD1331_CMD_SETREMAP); // 0xA0
248 // A[2] = 1 = color order (0 = RGB, 1 = BGR)
249 // A[7:6] = 01 = 65K color
250 #if defined SSD1331_COLORORDER_BGR
251 CMD(0x76);
252 #else
253 CMD(0x72);
254 #endif
255 CMD(SSD1331_CMD_STARTLINE); // 0xA1
256 CMD(0x0);
257 CMD(SSD1331_CMD_DISPLAYOFFSET); // 0xA2
258 CMD(0x0);
259 CMD(SSD1331_CMD_NORMALDISPLAY); // 0xA4
260 CMD(SSD1331_CMD_SETMULTIPLEX); // 0xA8
261 CMD(0x3F); // 0x3F 1/64 duty
262 CMD(SSD1331_CMD_SETMASTER); // 0xAD
263 CMD(0x8E);
264 CMD(SSD1331_CMD_POWERMODE); // 0xB0
265 CMD(0x0B);
266 CMD(SSD1331_CMD_PRECHARGE); // 0xB1
267 CMD(0x31);
268 CMD(SSD1331_CMD_CLOCKDIV); // 0xB3
269 CMD(0xF0); // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
270 CMD(SSD1331_CMD_PRECHARGEA); // 0x8A
271 CMD(0x64);
272 CMD(SSD1331_CMD_PRECHARGEB); // 0x8B
273 CMD(0x78);
274 CMD(SSD1331_CMD_PRECHARGEA); // 0x8C
275 CMD(0x64);
276 CMD(SSD1331_CMD_PRECHARGELEVEL); // 0xBB
277 CMD(0x3A);
278 CMD(SSD1331_CMD_VCOMH); // 0xBE
279 CMD(0x3E);
280 CMD(SSD1331_CMD_MASTERCURRENT); // 0x87
281 CMD(0x06);
282 CMD(SSD1331_CMD_CONTRASTA); // 0x81
283 CMD(0x91);
284 CMD(SSD1331_CMD_CONTRASTB); // 0x82
285 CMD(0x50);
286 CMD(SSD1331_CMD_CONTRASTC); // 0x83
287 CMD(0x7D);
288 CMD(SSD1331_CMD_DISPLAYON);//--turn on oled panel
289
290 // Fill black
291 lcdFillRGB(COLOR_BLACK);
292 }
293
294 /**************************************************************************/
295 /*!
296 @brief Enables or disables the LCD backlight
297 */
298 /**************************************************************************/
299 void lcdBacklight(bool state)
300 {
301 // No backlight ... do nothing
302 }
303
304 /**************************************************************************/
305 /*!
306 @brief Renders a simple test pattern on the LCD
307 */
308 /**************************************************************************/
309 void lcdTest(void)
310 {
311 uint32_t i,j;
312 ssd1331SetCursor(0, 0);
313
314 for(i=0;i<64;i++)
315 {
316 for(j=0;j<96;j++)
317 {
318 if(i>55){DATA((uint8_t)COLOR_WHITE>>8);DATA((uint8_t)COLOR_WHITE);}
319 else if(i>47){DATA((uint8_t)COLOR_BLUE>>8);DATA((uint8_t)COLOR_BLUE);}
320 else if(i>39){DATA((uint8_t)COLOR_GREEN>>8);DATA((uint8_t)COLOR_GREEN);}
321 else if(i>31){DATA((uint8_t)COLOR_CYAN>>8);DATA((uint8_t)COLOR_CYAN);}
322 else if(i>23){DATA((uint8_t)COLOR_RED>>8);DATA((uint8_t)COLOR_RED);}
323 else if(i>15){DATA((uint8_t)COLOR_MAGENTA>>8);DATA((uint8_t)COLOR_MAGENTA);}
324 else if(i>7){DATA((uint8_t)COLOR_YELLOW>>8);DATA((uint8_t)COLOR_YELLOW);}
325 else {DATA((uint8_t)COLOR_BLACK>>8);DATA((uint8_t)COLOR_BLACK);}
326 }
327 }
328 }
329
330 /**************************************************************************/
331 /*!
332 @brief Fills the LCD with the specified 16-bit color
333 */
334 /**************************************************************************/
335 void lcdFillRGB(uint16_t data)
336 {
337 ssd1331FillRect(0,0,ssd1331Properties.width-1,ssd1331Properties.height-1, data, data);
338 }
339
340 /**************************************************************************/
341 /*!
342 @brief Draws a single pixel at the specified X/Y location
343 */
344 /**************************************************************************/
345 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
346 {
347 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
348 return;
349
350 ssd1331SetCursor((uint8_t)x, (uint8_t)y);
351 DATA(color >> 8);
352 DATA(color);
353 }
354
355 /**************************************************************************/
356 /*!
357 @brief Draws an array of consecutive RGB565 pixels (much
358 faster than addressing each pixel individually)
359 */
360 /**************************************************************************/
361 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
362 {
363 // ToDo
364 }
365
366 /**************************************************************************/
367 /*!
368 @brief Optimised routine to draw a horizontal line faster than
369 setting individual pixels
370 */
371 /**************************************************************************/
372 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
373 {
374 ssd1331DrawLine((uint8_t)x0, (uint8_t)y, (uint8_t)x1, (uint8_t)y, color);
375 }
376
377 /**************************************************************************/
378 /*!
379 @brief Optimised routine to draw a vertical line faster than
380 setting individual pixels
381 */
382 /**************************************************************************/
383 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
384 {
385 ssd1331DrawLine((uint8_t)x, (uint8_t)y0, (uint8_t)x, (uint8_t)y1, color);
386 }
387
388 /**************************************************************************/
389 /*!
390 @brief Gets the 16-bit color of the pixel at the specified location
391 */
392 /**************************************************************************/
393 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
394 {
395 // ToDo
396 return 0;
397 }
398
399 /**************************************************************************/
400 /*!
401 @brief Sets the LCD orientation to horizontal and vertical
402 */
403 /**************************************************************************/
404 void lcdSetOrientation(lcdOrientation_t orientation)
405 {
406 // Not supported
407 }
408
409 /**************************************************************************/
410 /*!
411 @brief Gets the current screen orientation (horizontal or vertical)
412 */
413 /**************************************************************************/
414 lcdOrientation_t lcdGetOrientation(void)
415 {
416 return lcdOrientation;
417 }
418
419 /**************************************************************************/
420 /*!
421 @brief Gets the width in pixels of the LCD screen (varies depending
422 on the current screen orientation)
423 */
424 /**************************************************************************/
425 uint16_t lcdGetWidth(void)
426 {
427 return ssd1331Properties.width;
428 }
429
430 /**************************************************************************/
431 /*!
432 @brief Gets the height in pixels of the LCD screen (varies depending
433 on the current screen orientation)
434 */
435 /**************************************************************************/
436 uint16_t lcdGetHeight(void)
437 {
438 return ssd1331Properties.height;
439 }
440
441 /**************************************************************************/
442 /*!
443 @brief Scrolls the contents of the LCD screen vertically the
444 specified number of pixels using a HW optimised routine
445 */
446 /**************************************************************************/
447 void lcdScroll(int16_t pixels, uint16_t fillColor)
448 {
449 // ToDo
450 }
451
452 /**************************************************************************/
453 /*!
454 @brief Gets the controller's 16-bit (4 hexdigit) ID
455 */
456 /**************************************************************************/
457 uint16_t lcdGetControllerID(void)
458 {
459 return 0x1331;
460 }
461
462 /**************************************************************************/
463 /*!
464 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
465 generic capabilities and dimensions
466 */
467 /**************************************************************************/
468 lcdProperties_t lcdGetProperties(void)
469 {
470 return ssd1331Properties;
471 }
This page took 0.06626 seconds and 3 git commands to generate.