bug fixes
[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 CMD(0x76); // 0x74
240 CMD(SSD1331_CMD_STARTLINE); // 0xA1
241 CMD(0x0);
242 CMD(SSD1331_CMD_DISPLAYOFFSET); // 0xA2
243 CMD(0x0);
244 CMD(SSD1331_CMD_NORMALDISPLAY); // 0xA4
245 CMD(SSD1331_CMD_SETMULTIPLEX); // 0xA8
246 CMD(0x3F); // 0x3F 1/64 duty
247 CMD(SSD1331_CMD_SETMASTER); // 0xAD
248 CMD(0x8E);
249 CMD(SSD1331_CMD_POWERMODE); // 0xB0
250 CMD(0x0B);
251 CMD(SSD1331_CMD_PRECHARGE); // 0xB1
252 CMD(0x31);
253 CMD(SSD1331_CMD_CLOCKDIV); // 0xB3
254 CMD(0xF0); // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
255 CMD(SSD1331_CMD_PRECHARGEA); // 0x8A
256 CMD(0x64);
257 CMD(SSD1331_CMD_PRECHARGEB); // 0x8B
258 CMD(0x78);
259 CMD(SSD1331_CMD_PRECHARGEA); // 0x8C
260 CMD(0x64);
261 CMD(SSD1331_CMD_PRECHARGELEVEL); // 0xBB
262 CMD(0x3A);
263 CMD(SSD1331_CMD_VCOMH); // 0xBE
264 CMD(0x3E);
265 CMD(SSD1331_CMD_MASTERCURRENT); // 0x87
266 CMD(0x06);
267 CMD(SSD1331_CMD_CONTRASTA); // 0x81
268 CMD(0x91);
269 CMD(SSD1331_CMD_CONTRASTB); // 0x82
270 CMD(0x50);
271 CMD(SSD1331_CMD_CONTRASTC); // 0x83
272 CMD(0x7D);
273 CMD(SSD1331_CMD_DISPLAYON);//--turn on oled panel
274
275 // Fill black
276 lcdFillRGB(COLOR_BLACK);
277 }
278
279 /**************************************************************************/
280 /*!
281 @brief Enables or disables the LCD backlight
282 */
283 /**************************************************************************/
284 void lcdBacklight(bool state)
285 {
286 // No backlight ... do nothing
287 }
288
289 /**************************************************************************/
290 /*!
291 @brief Renders a simple test pattern on the LCD
292 */
293 /**************************************************************************/
294 void lcdTest(void)
295 {
296 uint32_t i,j;
297 ssd1331SetCursor(0, 0);
298
299 for(i=0;i<64;i++)
300 {
301 for(j=0;j<96;j++)
302 {
303 if(i>55){DATA(invert565Color(COLOR_WHITE)>>8);DATA(invert565Color(COLOR_WHITE));}
304 else if(i>47){DATA(invert565Color(COLOR_BLUE)>>8);DATA(invert565Color(COLOR_BLUE));}
305 else if(i>39){DATA(invert565Color(COLOR_GREEN)>>8);DATA(invert565Color(COLOR_GREEN));}
306 else if(i>31){DATA(invert565Color(COLOR_CYAN)>>8);DATA(invert565Color(COLOR_CYAN));}
307 else if(i>23){DATA(invert565Color(COLOR_RED)>>8);DATA(invert565Color(COLOR_RED));}
308 else if(i>15){DATA(invert565Color(COLOR_MAGENTA)>>8);DATA(invert565Color(COLOR_MAGENTA));}
309 else if(i>7){DATA(invert565Color(COLOR_YELLOW)>>8);DATA(invert565Color(COLOR_YELLOW));}
310 else {DATA(invert565Color(COLOR_BLACK)>>8);DATA(invert565Color(COLOR_BLACK));}
311 }
312 }
313 }
314
315 /**************************************************************************/
316 /*!
317 @brief Fills the LCD with the specified 16-bit color
318 */
319 /**************************************************************************/
320 void lcdFillRGB(uint16_t data)
321 {
322 data = invert565Color(data);
323 ssd1331FillRect(0,0,ssd1331Properties.width-1,ssd1331Properties.height-1, data, data);
324 }
325
326 /**************************************************************************/
327 /*!
328 @brief Draws a single pixel at the specified X/Y location
329 */
330 /**************************************************************************/
331 void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color)
332 {
333 if ((x >= ssd1331Properties.width) || (y >= ssd1331Properties.height))
334 return;
335
336 ssd1331SetCursor((uint8_t)x, (uint8_t)y);
337 color = invert565Color(color);
338 DATA(color >> 8);
339 DATA(color);
340 }
341
342 /**************************************************************************/
343 /*!
344 @brief Draws an array of consecutive RGB565 pixels (much
345 faster than addressing each pixel individually)
346 */
347 /**************************************************************************/
348 void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len)
349 {
350 // ToDo
351 }
352
353 /**************************************************************************/
354 /*!
355 @brief Optimised routine to draw a horizontal line faster than
356 setting individual pixels
357 */
358 /**************************************************************************/
359 void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color)
360 {
361 color = invert565Color(color);
362 ssd1331DrawLine((uint8_t)x0, (uint8_t)y, (uint8_t)x1, (uint8_t)y, color);
363 }
364
365 /**************************************************************************/
366 /*!
367 @brief Optimised routine to draw a vertical line faster than
368 setting individual pixels
369 */
370 /**************************************************************************/
371 void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color)
372 {
373 color = invert565Color(color);
374 ssd1331DrawLine((uint8_t)x, (uint8_t)y0, (uint8_t)x, (uint8_t)y1, color);
375 }
376
377 /**************************************************************************/
378 /*!
379 @brief Gets the 16-bit color of the pixel at the specified location
380 */
381 /**************************************************************************/
382 uint16_t lcdGetPixel(uint16_t x, uint16_t y)
383 {
384 // ToDo
385 return 0;
386 }
387
388 /**************************************************************************/
389 /*!
390 @brief Sets the LCD orientation to horizontal and vertical
391 */
392 /**************************************************************************/
393 void lcdSetOrientation(lcdOrientation_t orientation)
394 {
395 // Not supported
396 }
397
398 /**************************************************************************/
399 /*!
400 @brief Gets the current screen orientation (horizontal or vertical)
401 */
402 /**************************************************************************/
403 lcdOrientation_t lcdGetOrientation(void)
404 {
405 return lcdOrientation;
406 }
407
408 /**************************************************************************/
409 /*!
410 @brief Gets the width in pixels of the LCD screen (varies depending
411 on the current screen orientation)
412 */
413 /**************************************************************************/
414 uint16_t lcdGetWidth(void)
415 {
416 return ssd1331Properties.width;
417 }
418
419 /**************************************************************************/
420 /*!
421 @brief Gets the height in pixels of the LCD screen (varies depending
422 on the current screen orientation)
423 */
424 /**************************************************************************/
425 uint16_t lcdGetHeight(void)
426 {
427 return ssd1331Properties.height;
428 }
429
430 /**************************************************************************/
431 /*!
432 @brief Scrolls the contents of the LCD screen vertically the
433 specified number of pixels using a HW optimised routine
434 */
435 /**************************************************************************/
436 void lcdScroll(int16_t pixels, uint16_t fillColor)
437 {
438 // ToDo
439 }
440
441 /**************************************************************************/
442 /*!
443 @brief Gets the controller's 16-bit (4 hexdigit) ID
444 */
445 /**************************************************************************/
446 uint16_t lcdGetControllerID(void)
447 {
448 return ssd1331Type();
449 }
450
451 /**************************************************************************/
452 /*!
453 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
454 generic capabilities and dimensions
455 */
456 /**************************************************************************/
457 lcdProperties_t lcdGetProperties(void)
458 {
459 return ssd1331Properties;
460 }
This page took 0.078153 seconds and 5 git commands to generate.