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