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 // You can speed all of these slow GPIO calls up by using the SET/CLR macros!
54 #define CMD(c) do { gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
55 gpioSetValue( SSD1331_DC_PORT, SSD1331_DC_PIN, 0 ); \
56 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 0 ); \
57 ssd1331SendByte( c ); \
58 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
60 #define DATA(c) do { gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
61 gpioSetValue( SSD1331_DC_PORT, SSD1331_DC_PIN, 1 ); \
62 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 0 ); \
63 ssd1331SendByte( c ); \
64 gpioSetValue( SSD1331_CS_PORT, SSD1331_CS_PIN, 1 ); \
66 #define DELAY(mS) do { systickDelay( mS / CFG_SYSTICK_DELAY_IN_MS ); } while(0);
68 /**************************************************************************/
70 @brief Simulates an SPI write using GPIO
75 /**************************************************************************/
76 void ssd1331SendByte(uint8_t byte
)
80 // Make sure clock pin starts high
81 gpioSetValue(SSD1331_SCK_PORT
, SSD1331_SCK_PIN
, 1);
83 // Write from MSB to LSB
87 gpioSetValue(SSD1331_SCK_PORT
, SSD1331_SCK_PIN
, 0);
88 // Set data pin high or low depending on the value of the current bit
89 gpioSetValue(SSD1331_SID_PORT
, SSD1331_SID_PIN
, byte
& (1 << i
) ? 1 : 0);
91 gpioSetValue(SSD1331_SCK_PORT
, SSD1331_SCK_PIN
, 1);
95 /**************************************************************************/
97 @brief Reads a 16-bit value from the 8-bit data bus
99 /**************************************************************************/
100 uint16_t ssd1331ReadData(void)
106 /**************************************************************************/
108 @brief Reads a 16-bit value
110 /**************************************************************************/
111 uint16_t ssd1331Read(uint16_t addr
)
117 /**************************************************************************/
119 @brief Returns the 16-bit (4-hexdigit) controller code
121 /**************************************************************************/
122 uint16_t ssd1331Type(void)
128 /**************************************************************************/
130 @brief Sets the cursor to the specified X/Y position
132 /**************************************************************************/
133 void ssd1331SetCursor(uint8_t x
, uint8_t y
)
135 if ((x
>= ssd1331Properties
.width
) || (y
>= ssd1331Properties
.height
))
137 // set x and y coordinate
138 CMD(SSD1331_CMD_SETCOLUMN
);
140 CMD(ssd1331Properties
.width
-1);
142 CMD(SSD1331_CMD_SETROW
);
144 CMD(ssd1331Properties
.height
-1);
147 /**************************************************************************/
149 @brief Draws a solid line using HW acceleration
151 /**************************************************************************/
152 void ssd1331DrawLine(uint8_t x1
, uint8_t y1
, uint8_t x2
, uint8_t y2
, uint16_t color
)
154 if ((x1
>= ssd1331Properties
.width
) || (x2
>= ssd1331Properties
.width
) ||
155 (y1
>= ssd1331Properties
.height
) || (y2
>= ssd1331Properties
.height
)) {
159 CMD(SSD1331_CMD_DRAWLINE
);
164 CMD((color
>> 11) << 1);
165 CMD((color
>> 5) & 0x3F);
166 CMD((color
<< 1)& 0x3F);
169 /**************************************************************************/
171 @brief Draws a filled rectangle using HW acceleration
173 /**************************************************************************/
174 void ssd1331FillRect(uint8_t x1
, uint8_t y1
, uint8_t x2
, uint8_t y2
, uint16_t pencolor
, uint16_t fillcolor
)
176 if ((x1
>= ssd1331Properties
.width
) || (x2
>= ssd1331Properties
.width
) ||
177 (y1
>= ssd1331Properties
.height
) || (y2
>= ssd1331Properties
.height
)) {
182 CMD(SSD1331_CMD_FILL
);
185 CMD(SSD1331_CMD_DRAWRECT
);
190 CMD((pencolor
>> 11) << 1);
191 CMD((pencolor
>> 5) & 0x3F);
192 CMD((pencolor
<< 1)& 0x3F);
194 CMD((fillcolor
>> 11) << 1);
195 CMD((fillcolor
>> 5) & 0x3F);
196 CMD((fillcolor
<< 1)& 0x3F);
199 /**************************************************************************/
201 @brief Inverts the R and B in an RGB565 color
203 /**************************************************************************/
204 uint16_t invert565Color(uint16_t color
)
208 b
= (color
>>0) & 0x1f;
209 g
= (color
>>5) & 0x3f;
210 r
= (color
>>11) & 0x1f;
212 return( (b
<<11) + (g
<<5) + (r
<<0) );
215 /*************************************************/
217 /*************************************************/
219 /**************************************************************************/
221 @brief Configures any pins or HW and initialises the LCD controller
223 /**************************************************************************/
226 // Set all pins to output
227 gpioSetDir(SSD1331_SCK_PORT
, SSD1331_SCK_PIN
, gpioDirection_Output
);
228 gpioSetDir(SSD1331_SID_PORT
, SSD1331_SID_PIN
, gpioDirection_Output
);
229 gpioSetDir(SSD1331_DC_PORT
, SSD1331_DC_PIN
, gpioDirection_Output
);
230 gpioSetDir(SSD1331_RST_PORT
, SSD1331_RST_PIN
, gpioDirection_Output
);
231 gpioSetDir(SSD1331_CS_PORT
, SSD1331_CS_PIN
, gpioDirection_Output
);
241 SSD1331_DISABLEPULLUPS();
243 CMD(SSD1331_CMD_DISPLAYOFF
); // 0xAE
244 CMD(SSD1331_CMD_SETREMAP
); // 0xA0
246 CMD(SSD1331_CMD_STARTLINE
); // 0xA1
248 CMD(SSD1331_CMD_DISPLAYOFFSET
); // 0xA2
250 CMD(SSD1331_CMD_NORMALDISPLAY
); // 0xA4
251 CMD(SSD1331_CMD_SETMULTIPLEX
); // 0xA8
252 CMD(0x3F); // 0x3F 1/64 duty
253 CMD(SSD1331_CMD_SETMASTER
); // 0xAD
255 CMD(SSD1331_CMD_POWERMODE
); // 0xB0
257 CMD(SSD1331_CMD_PRECHARGE
); // 0xB1
259 CMD(SSD1331_CMD_CLOCKDIV
); // 0xB3
260 CMD(0xF0); // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
261 CMD(SSD1331_CMD_PRECHARGEA
); // 0x8A
263 CMD(SSD1331_CMD_PRECHARGEB
); // 0x8B
265 CMD(SSD1331_CMD_PRECHARGEA
); // 0x8C
267 CMD(SSD1331_CMD_PRECHARGELEVEL
); // 0xBB
269 CMD(SSD1331_CMD_VCOMH
); // 0xBE
271 CMD(SSD1331_CMD_MASTERCURRENT
); // 0x87
273 CMD(SSD1331_CMD_CONTRASTA
); // 0x81
275 CMD(SSD1331_CMD_CONTRASTB
); // 0x82
277 CMD(SSD1331_CMD_CONTRASTC
); // 0x83
279 CMD(SSD1331_CMD_DISPLAYON
);//--turn on oled panel
282 lcdFillRGB(COLOR_BLACK
);
285 /**************************************************************************/
287 @brief Enables or disables the LCD backlight
289 /**************************************************************************/
290 void lcdBacklight(bool state
)
292 // No backlight ... do nothing
295 /**************************************************************************/
297 @brief Renders a simple test pattern on the LCD
299 /**************************************************************************/
303 ssd1331SetCursor(0, 0);
309 if(i
>55){DATA(invert565Color(COLOR_WHITE
)>>8);DATA(invert565Color(COLOR_WHITE
));}
310 else if(i
>47){DATA(invert565Color(COLOR_BLUE
)>>8);DATA(invert565Color(COLOR_BLUE
));}
311 else if(i
>39){DATA(invert565Color(COLOR_GREEN
)>>8);DATA(invert565Color(COLOR_GREEN
));}
312 else if(i
>31){DATA(invert565Color(COLOR_CYAN
)>>8);DATA(invert565Color(COLOR_CYAN
));}
313 else if(i
>23){DATA(invert565Color(COLOR_RED
)>>8);DATA(invert565Color(COLOR_RED
));}
314 else if(i
>15){DATA(invert565Color(COLOR_MAGENTA
)>>8);DATA(invert565Color(COLOR_MAGENTA
));}
315 else if(i
>7){DATA(invert565Color(COLOR_YELLOW
)>>8);DATA(invert565Color(COLOR_YELLOW
));}
316 else {DATA(invert565Color(COLOR_BLACK
)>>8);DATA(invert565Color(COLOR_BLACK
));}
321 /**************************************************************************/
323 @brief Fills the LCD with the specified 16-bit color
325 /**************************************************************************/
326 void lcdFillRGB(uint16_t data
)
328 data
= invert565Color(data
);
329 ssd1331FillRect(0,0,ssd1331Properties
.width
-1,ssd1331Properties
.height
-1, data
, data
);
332 /**************************************************************************/
334 @brief Draws a single pixel at the specified X/Y location
336 /**************************************************************************/
337 void lcdDrawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
339 if ((x
>= ssd1331Properties
.width
) || (y
>= ssd1331Properties
.height
))
342 ssd1331SetCursor((uint8_t)x
, (uint8_t)y
);
343 color
= invert565Color(color
);
348 /**************************************************************************/
350 @brief Draws an array of consecutive RGB565 pixels (much
351 faster than addressing each pixel individually)
353 /**************************************************************************/
354 void lcdDrawPixels(uint16_t x
, uint16_t y
, uint16_t *data
, uint32_t len
)
359 /**************************************************************************/
361 @brief Optimised routine to draw a horizontal line faster than
362 setting individual pixels
364 /**************************************************************************/
365 void lcdDrawHLine(uint16_t x0
, uint16_t x1
, uint16_t y
, uint16_t color
)
367 color
= invert565Color(color
);
368 ssd1331DrawLine((uint8_t)x0
, (uint8_t)y
, (uint8_t)x1
, (uint8_t)y
, color
);
371 /**************************************************************************/
373 @brief Optimised routine to draw a vertical line faster than
374 setting individual pixels
376 /**************************************************************************/
377 void lcdDrawVLine(uint16_t x
, uint16_t y0
, uint16_t y1
, uint16_t color
)
379 color
= invert565Color(color
);
380 ssd1331DrawLine((uint8_t)x
, (uint8_t)y0
, (uint8_t)x
, (uint8_t)y1
, color
);
383 /**************************************************************************/
385 @brief Gets the 16-bit color of the pixel at the specified location
387 /**************************************************************************/
388 uint16_t lcdGetPixel(uint16_t x
, uint16_t y
)
394 /**************************************************************************/
396 @brief Sets the LCD orientation to horizontal and vertical
398 /**************************************************************************/
399 void lcdSetOrientation(lcdOrientation_t orientation
)
404 /**************************************************************************/
406 @brief Gets the current screen orientation (horizontal or vertical)
408 /**************************************************************************/
409 lcdOrientation_t
lcdGetOrientation(void)
411 return lcdOrientation
;
414 /**************************************************************************/
416 @brief Gets the width in pixels of the LCD screen (varies depending
417 on the current screen orientation)
419 /**************************************************************************/
420 uint16_t lcdGetWidth(void)
422 return ssd1331Properties
.width
;
425 /**************************************************************************/
427 @brief Gets the height in pixels of the LCD screen (varies depending
428 on the current screen orientation)
430 /**************************************************************************/
431 uint16_t lcdGetHeight(void)
433 return ssd1331Properties
.height
;
436 /**************************************************************************/
438 @brief Scrolls the contents of the LCD screen vertically the
439 specified number of pixels using a HW optimised routine
441 /**************************************************************************/
442 void lcdScroll(int16_t pixels
, uint16_t fillColor
)
447 /**************************************************************************/
449 @brief Gets the controller's 16-bit (4 hexdigit) ID
451 /**************************************************************************/
452 uint16_t lcdGetControllerID(void)
454 return ssd1331Type();
457 /**************************************************************************/
459 @brief Returns the LCDs 'lcdProperties_t' that describes the LCDs
460 generic capabilities and dimensions
462 /**************************************************************************/
463 lcdProperties_t
lcdGetProperties(void)
465 return ssd1331Properties
;