1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Driver for SSD1331 96x64 pixel RGB OLED displays.
10 This driver uses a bit-banged SPI interface and 16-bit RGB565 colours.
14 Software License Agreement (BSD License)
16 Copyright (c) 2010, microBuilder SARL
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.
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.
41 /**************************************************************************/
43 #include "core/systick/systick.h"
45 static volatile lcdOrientation_t lcdOrientation
= LCD_ORIENTATION_PORTRAIT
;
46 static lcdProperties_t ssd1331Properties
= { 96, 64, false, false, false };
48 /*************************************************/
50 /*************************************************/
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);
56 /**************************************************************************/
58 @brief Simulates an SPI write using GPIO
63 /**************************************************************************/
64 void ssd1331SendByte(uint8_t byte
)
68 // Make sure clock pin starts high
71 // Write from MSB to LSB
76 // Set data pin high or low depending on the value of the current bit
90 /**************************************************************************/
92 @brief Reads a 16-bit value from the 8-bit data bus
94 /**************************************************************************/
95 uint16_t ssd1331ReadData(void)
101 /**************************************************************************/
103 @brief Reads a 16-bit value
105 /**************************************************************************/
106 uint16_t ssd1331Read(uint16_t addr
)
112 /**************************************************************************/
114 @brief Returns the 16-bit (4-hexdigit) controller code
116 /**************************************************************************/
117 uint16_t ssd1331Type(void)
122 /**************************************************************************/
124 @brief Sets the cursor to the specified X/Y position
126 /**************************************************************************/
127 void ssd1331SetCursor(uint8_t x
, uint8_t y
)
129 if ((x
>= ssd1331Properties
.width
) || (y
>= ssd1331Properties
.height
))
131 // set x and y coordinate
132 CMD(SSD1331_CMD_SETCOLUMN
);
134 CMD(ssd1331Properties
.width
-1);
136 CMD(SSD1331_CMD_SETROW
);
138 CMD(ssd1331Properties
.height
-1);
141 /**************************************************************************/
143 @brief Draws a solid line using HW acceleration
145 /**************************************************************************/
146 void ssd1331DrawLine(uint8_t x1
, uint8_t y1
, uint8_t x2
, uint8_t y2
, uint16_t color
)
148 if ((x1
>= ssd1331Properties
.width
) || (x2
>= ssd1331Properties
.width
) ||
149 (y1
>= ssd1331Properties
.height
) || (y2
>= ssd1331Properties
.height
)) {
153 CMD(SSD1331_CMD_DRAWLINE
);
158 CMD((color
>> 11) << 1);
159 CMD((color
>> 5) & 0x3F);
160 CMD((color
<< 1)& 0x3F);
163 /**************************************************************************/
165 @brief Draws a filled rectangle using HW acceleration
167 /**************************************************************************/
168 void ssd1331FillRect(uint8_t x1
, uint8_t y1
, uint8_t x2
, uint8_t y2
, uint16_t pencolor
, uint16_t fillcolor
)
170 if ((x1
>= ssd1331Properties
.width
) || (x2
>= ssd1331Properties
.width
) ||
171 (y1
>= ssd1331Properties
.height
) || (y2
>= ssd1331Properties
.height
)) {
176 CMD(SSD1331_CMD_FILL
);
179 CMD(SSD1331_CMD_DRAWRECT
);
184 CMD((pencolor
>> 11) << 1);
185 CMD((pencolor
>> 5) & 0x3F);
186 CMD((pencolor
<< 1)& 0x3F);
188 CMD((fillcolor
>> 11) << 1);
189 CMD((fillcolor
>> 5) & 0x3F);
190 CMD((fillcolor
<< 1)& 0x3F);
193 /**************************************************************************/
195 @brief Inverts the R and B in an RGB565 color
197 /**************************************************************************/
198 uint16_t invert565Color(uint16_t color
)
202 b
= (color
>>0) & 0x1f;
203 g
= (color
>>5) & 0x3f;
204 r
= (color
>>11) & 0x1f;
206 return( (b
<<11) + (g
<<5) + (r
<<0) );
209 /*************************************************/
211 /*************************************************/
213 /**************************************************************************/
215 @brief Configures any pins or HW and initialises the LCD controller
217 /**************************************************************************/
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
);
235 SSD1331_DISABLEPULLUPS();
237 CMD(SSD1331_CMD_DISPLAYOFF
); // 0xAE
238 CMD(SSD1331_CMD_SETREMAP
); // 0xA0
240 CMD(SSD1331_CMD_STARTLINE
); // 0xA1
242 CMD(SSD1331_CMD_DISPLAYOFFSET
); // 0xA2
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
249 CMD(SSD1331_CMD_POWERMODE
); // 0xB0
251 CMD(SSD1331_CMD_PRECHARGE
); // 0xB1
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
257 CMD(SSD1331_CMD_PRECHARGEB
); // 0x8B
259 CMD(SSD1331_CMD_PRECHARGEA
); // 0x8C
261 CMD(SSD1331_CMD_PRECHARGELEVEL
); // 0xBB
263 CMD(SSD1331_CMD_VCOMH
); // 0xBE
265 CMD(SSD1331_CMD_MASTERCURRENT
); // 0x87
267 CMD(SSD1331_CMD_CONTRASTA
); // 0x81
269 CMD(SSD1331_CMD_CONTRASTB
); // 0x82
271 CMD(SSD1331_CMD_CONTRASTC
); // 0x83
273 CMD(SSD1331_CMD_DISPLAYON
);//--turn on oled panel
276 lcdFillRGB(COLOR_BLACK
);
279 /**************************************************************************/
281 @brief Enables or disables the LCD backlight
283 /**************************************************************************/
284 void lcdBacklight(bool state
)
286 // No backlight ... do nothing
289 /**************************************************************************/
291 @brief Renders a simple test pattern on the LCD
293 /**************************************************************************/
297 ssd1331SetCursor(0, 0);
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
));}
315 /**************************************************************************/
317 @brief Fills the LCD with the specified 16-bit color
319 /**************************************************************************/
320 void lcdFillRGB(uint16_t data
)
322 data
= invert565Color(data
);
323 ssd1331FillRect(0,0,ssd1331Properties
.width
-1,ssd1331Properties
.height
-1, data
, data
);
326 /**************************************************************************/
328 @brief Draws a single pixel at the specified X/Y location
330 /**************************************************************************/
331 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
333 if ((x
>= ssd1331Properties
.width
) || (y
>= ssd1331Properties
.height
))
336 ssd1331SetCursor((uint8_t)x
, (uint8_t)y
);
337 color
= invert565Color(color
);
342 /**************************************************************************/
344 @brief Draws an array of consecutive RGB565 pixels (much
345 faster than addressing each pixel individually)
347 /**************************************************************************/
348 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
353 /**************************************************************************/
355 @brief Optimised routine to draw a horizontal line faster than
356 setting individual pixels
358 /**************************************************************************/
359 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
361 color
= invert565Color(color
);
362 ssd1331DrawLine((uint8_t)x0
, (uint8_t)y
, (uint8_t)x1
, (uint8_t)y
, color
);
365 /**************************************************************************/
367 @brief Optimised routine to draw a vertical line faster than
368 setting individual pixels
370 /**************************************************************************/
371 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
373 color
= invert565Color(color
);
374 ssd1331DrawLine((uint8_t)x
, (uint8_t)y0
, (uint8_t)x
, (uint8_t)y1
, color
);
377 /**************************************************************************/
379 @brief Gets the 16-bit color of the pixel at the specified location
381 /**************************************************************************/
382 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
388 /**************************************************************************/
390 @brief Sets the LCD orientation to horizontal and vertical
392 /**************************************************************************/
393 void lcdSetOrientation(lcdOrientation_t orientation
)
398 /**************************************************************************/
400 @brief Gets the current screen orientation (horizontal or vertical)
402 /**************************************************************************/
403 lcdOrientation_t
lcdGetOrientation(void)
405 return lcdOrientation
;
408 /**************************************************************************/
410 @brief Gets the width in pixels of the LCD screen (varies depending
411 on the current screen orientation)
413 /**************************************************************************/
414 uint16_t lcdGetWidth(void)
416 return ssd1331Properties
.width
;
419 /**************************************************************************/
421 @brief Gets the height in pixels of the LCD screen (varies depending
422 on the current screen orientation)
424 /**************************************************************************/
425 uint16_t lcdGetHeight(void)
427 return ssd1331Properties
.height
;
430 /**************************************************************************/
432 @brief Scrolls the contents of the LCD screen vertically the
433 specified number of pixels using a HW optimised routine
435 /**************************************************************************/
436 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
441 /**************************************************************************/
443 @brief Gets the controller's 16-bit (4 hexdigit) ID
445 /**************************************************************************/
446 uint16_t lcdGetControllerID(void)
448 return ssd1331Type();
451 /**************************************************************************/
453 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
454 generic capabilities and dimensions
456 /**************************************************************************/
457 lcdProperties_t
lcdGetProperties(void)
459 return ssd1331Properties
;