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