SSD1306 OLED display driver  1.8.2
This library is developed to control SSD1306/SSD1331/SSD1351/IL9163/PCD8554 RGB i2c/spi LED displays
oled_ssd1331.c
1 /*
2  MIT License
3 
4  Copyright (c) 2018-2019, Alexey Dynda
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in all
14  copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  SOFTWARE.
23 */
24 
25 #include "oled_ssd1331.h"
26 #include "lcd_common.h"
27 #include "ssd1331_commands.h"
28 #include "intf/ssd1306_interface.h"
29 #include "intf/spi/ssd1306_spi.h"
30 #include "ssd1306_hal/io.h"
31 #ifdef SDL_EMULATION
32 #include "sdl_core.h"
33 #endif
34 #include "nano_gfx_types.h"
35 
36 extern uint16_t ssd1306_color;
37 
38 static const PROGMEM uint8_t s_oled96x64_initData[] =
39 {
40 #ifdef SDL_EMULATION
41  SDL_LCD_SSD1331_X8,
42  0x00,
43 #endif
44  SSD1331_DISPLAYOFF, // display off
45  SSD1331_SEGREMAP, 0x00 | 0x20 | 0x10 | 0x02 | 0x01, /* 8-bit rgb color mode */
46  SSD1331_SETSTARTLINE, 0x00, // First line to start scanning from
47  SSD1331_SETDISPLAYOFFSET, 0x00, // Set display offset
48  SSD1331_NORMALDISPLAY,
49  SSD1331_SETMULTIPLEX, 63, // Reset to default MUX. See datasheet
50  SSD1331_SETMASTER, 0x8E, // Set master mode
51  SSD1331_POWERMODE, 0x0B, // Disable power-safe mode
52  SSD1331_SETPRECHARGE, 0x31, // Phase 1 and Phase 2 periods
53  SSD1331_CLOCKDIV, 0xF0, // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
54  SSD1331_PRECHARGEA, 0x64,
55  SSD1331_PRECHARGEB, 0x78,
56  SSD1331_PRECHARGELEVEL, 0x3A,
57  SSD1331_VCOMH, 0x3E,
58  SSD1331_MASTERCURRENT, 0x09,
59  SSD1331_CONTRASTA, 0x91, // RED
60  SSD1331_CONTRASTB, 0x50, // GREEN
61  SSD1331_CONTRASTC, 0x7D, // BLUE
62  SSD1331_DISPLAYON,
63 };
64 
65 static const PROGMEM uint8_t s_oled96x64_initData16[] =
66 {
67 #ifdef SDL_EMULATION
68  SDL_LCD_SSD1331_X16,
69  0x00,
70 #endif
71  SSD1331_DISPLAYOFF, // display off
72  SSD1331_SEGREMAP, 0x40 | 0x20 | 0x10 | 0x02 | 0x01, /* 16-bit rgb color mode */
73  SSD1331_SETSTARTLINE, 0x00, // First line to start scanning from
74  SSD1331_SETDISPLAYOFFSET, 0x00, // Set display offset
75  SSD1331_NORMALDISPLAY,
76  SSD1331_SETMULTIPLEX, 63, // Reset to default MUX. See datasheet
77  SSD1331_SETMASTER, 0x8E, // Set master mode
78  SSD1331_POWERMODE, 0x0B, // Disable power-safe mode
79  SSD1331_SETPRECHARGE, 0x31, // Phase 1 and Phase 2 periods
80  SSD1331_CLOCKDIV, 0xF0, // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
81  SSD1331_PRECHARGEA, 0x64,
82  SSD1331_PRECHARGEB, 0x78,
83  SSD1331_PRECHARGELEVEL, 0x3A,
84  SSD1331_VCOMH, 0x3E,
85  SSD1331_MASTERCURRENT, 0x09,
86  SSD1331_CONTRASTA, 0x91, // RED
87  SSD1331_CONTRASTB, 0x50, // GREEN
88  SSD1331_CONTRASTC, 0x7D, // BLUE
89  SSD1331_DISPLAYON,
90 };
91 
92 static uint8_t s_rotation = 0x04;
93 
95 
97  (s_rotation & 1) ? SSD1331_ROWADDR: SSD1331_COLUMNADDR,
98  (s_rotation & 1) ? SSD1331_COLUMNADDR: SSD1331_ROWADDR );
99 
101 
103 
105 
107  (s_rotation & 1) ? SSD1331_ROWADDR: SSD1331_COLUMNADDR,
108  (s_rotation & 1) ? SSD1331_COLUMNADDR: SSD1331_ROWADDR );
109 
111 
113 {
114  if (mode == LCD_MODE_NORMAL)
115  {
116  s_rotation &= ~0x04;
117  ssd1306_lcd.set_block = set_block_native;
118  ssd1306_lcd.next_page = next_page_native;
119  }
120  else if (mode == LCD_MODE_SSD1306_COMPAT )
121  {
122  s_rotation |= 0x04;
123  ssd1306_lcd.set_block = set_block_compat;
124  ssd1306_lcd.next_page = next_page_compat;
125  }
126  ssd1331_setRotation( s_rotation );
127  return;
128 }
129 
130 void ssd1331_setRotation(uint8_t rotation)
131 {
132  uint8_t ram_mode;
133  if ((rotation^s_rotation) & 0x01)
134  {
135  uint16_t t = ssd1306_lcd.width;
137  ssd1306_lcd.height = t;
138  }
139  s_rotation = (rotation & 0x03) | (s_rotation & 0x04);
142  ssd1306_intf.send( SSD1331_SEGREMAP );
143  switch (s_rotation)
144  {
145  // NORMAL FULL COLOR MODE
146  case 0:
147  ram_mode = 0b00110010;
148  break;
149  case 1: // 90 degree CW
150  ram_mode = 0b00110001;
151  break;
152  case 2: // 180 degree CW
153  ram_mode = 0b00100000;
154  break;
155  case 3: // 270 degree CW
156  ram_mode = 0b00100011;
157  break;
158  // SSD1306_COMPATIBLE mode
159  case 4:
160  ram_mode = 0b00110011;
161  break;
162  case 5: // 90 degree CW
163  ram_mode = 0b00110000;
164  break;
165  case 6: // 180 degree CW
166  ram_mode = 0b00100001;
167  break;
168  case 7: // 270 degree CW
169  ram_mode = 0b00100010;
170  break;
171  default: // 270 degree CW
172  ram_mode = 0b00100000;
173  break;
174  }
175  ssd1306_intf.send( ram_mode );
176  ssd1306_intf.stop();
177 }
178 
179 // 16-bit color in 8-bit display mode
180 static void ssd1331_sendPixel16_8(uint16_t data)
181 {
182  uint8_t color = RGB16_TO_RGB8(data);
183  ssd1306_intf.send( color );
184 }
185 
186 // 8-bit color in 16-bit display mode
187 static void ssd1331_sendPixel8_16(uint8_t data)
188 {
189  uint16_t color = RGB8_TO_RGB16(data);
190  ssd1306_intf.send( color >> 8 );
191  ssd1306_intf.send( color & 0xFF );
192 }
193 
194 // 16-bit color in 16-bit display mode
195 static void ssd1331_sendPixel16(uint16_t color)
196 {
197  ssd1306_intf.send( color >> 8 );
198  ssd1306_intf.send( color & 0xFF );
199 }
200 
202 {
204  ssd1306_lcd.height = 64;
205  ssd1306_lcd.width = 96;
206  ssd1306_lcd.set_block = set_block_compat;
207  ssd1306_lcd.next_page = next_page_compat;
208  ssd1306_lcd.send_pixels1 = send_pixels_compat;
209  ssd1306_lcd.send_pixels_buffer1 = send_pixels_buffer_compat;
210 
212  ssd1306_lcd.send_pixels16 = ssd1331_sendPixel16_8;
214  for( uint8_t i=0; i<sizeof(s_oled96x64_initData); i++)
215  {
216  ssd1306_sendCommand(pgm_read_byte(&s_oled96x64_initData[i]));
217  }
218 }
219 
220 void ssd1331_96x64_init16()
221 {
223  ssd1306_lcd.height = 64;
224  ssd1306_lcd.width = 96;
225  ssd1306_lcd.set_block = set_block_compat;
226  ssd1306_lcd.next_page = next_page_compat;
227  ssd1306_lcd.send_pixels1 = send_pixels_compat16;
228  ssd1306_lcd.send_pixels_buffer1 = send_pixels_buffer_compat16;
229 
230  ssd1306_lcd.send_pixels8 = ssd1331_sendPixel8_16;
231  ssd1306_lcd.send_pixels16 = ssd1331_sendPixel16;
233  for( uint8_t i=0; i<sizeof(s_oled96x64_initData16); i++)
234  {
235  ssd1306_sendCommand(pgm_read_byte(&s_oled96x64_initData16[i]));
236  }
237 }
238 
239 void ssd1331_96x64_spi_init(int8_t rstPin, int8_t cesPin, int8_t dcPin)
240 {
241  if (rstPin >=0)
242  {
243  ssd1306_resetController( rstPin, 10 );
244  }
245  ssd1306_spiInit(cesPin, dcPin);
247 }
248 
249 void ssd1331_96x64_spi_init16(int8_t rstPin, int8_t cesPin, int8_t dcPin)
250 {
251  if (rstPin >=0)
252  {
253  ssd1306_resetController( rstPin, 10 );
254  }
255  ssd1306_spiInit(cesPin, dcPin);
256  ssd1331_96x64_init16();
257 }
258 
259 void ssd1331_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
260 {
263  ssd1306_intf.send(SSD1331_DRAWLINE);
264  ssd1306_intf.send(x1);
265  ssd1306_intf.send(y1);
266  ssd1306_intf.send(x2);
267  ssd1306_intf.send(y2);
268  ssd1306_intf.send( (color & 0x03) << 4 );
269  ssd1306_intf.send( (color & 0x1C) << 2 );
270  ssd1306_intf.send( (color & 0xE0) >> 2 );
271  ssd1306_intf.stop();
272 }
273 
274 void ssd1331_copyBlock(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom, uint8_t newLeft, uint8_t newTop)
275 {
278  ssd1306_intf.send(0x23);
279  ssd1306_intf.send(left);
280  ssd1306_intf.send(top);
281  ssd1306_intf.send(right);
282  ssd1306_intf.send(bottom);
283  ssd1306_intf.send(newLeft);
284  ssd1306_intf.send(newTop);
285  ssd1306_intf.stop();
286 }
287 
#define CONTROLLER_NATIVE_SPI_BLOCK_8BIT_CMDS(column_cmd, row_cmd)
Definition: lcd_common.h:366
void(* send)(uint8_t data)
#define RGB16_TO_RGB8(c)
#define SSD1306_COMPAT_SEND_PIXELS_RGB8_CMDS()
Definition: lcd_common.h:390
void ssd1331_setMode(lcd_mode_t mode)
Sets GDRAM autoincrement mode.
Definition: oled_ssd1331.c:112
void(* send_pixels16)(uint16_t data)
Sends RGB pixel encoded in 5-6-5 format to OLED driver. Sends RGB pixel encoded in 5-6-5 format to OL...
Definition: lcd_common.h:149
void(* set_block)(lcduint_t x, lcduint_t y, lcduint_t w)
Sets block in RAM of lcd display controller to write data to.
Definition: lcd_common.h:114
void(* send_pixels8)(uint8_t data)
Sends RGB pixel encoded in 3-3-2 format to OLED driver. Sends RGB pixel encoded in 3-3-2 format to OL...
Definition: lcd_common.h:142
void ssd1306_spiDataMode(uint8_t mode)
Definition: ssd1306_spi.c:50
lcd_mode_t
Definition: lcd_common.h:69
void(* send_pixels_buffer1)(const uint8_t *buffer, uint16_t len)
Definition: lcd_common.h:135
void ssd1306_resetController(int8_t rstPin, uint8_t delayMs)
Does hardware reset for oled controller.
Definition: lcd_common.c:139
void(* send_pixels1)(uint8_t data)
Definition: lcd_common.h:128
void ssd1331_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
Definition: oled_ssd1331.c:259
#define SSD1306_COMPAT_SEND_PIXELS_RGB16_CMDS()
Definition: lcd_common.h:422
void ssd1306_spiInit(int8_t cesPin, int8_t dcPin)
Definition: ssd1306_spi.c:37
ssd1306_lcd_t ssd1306_lcd
Definition: lcd_common.c:33
void ssd1331_copyBlock(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom, uint8_t newLeft, uint8_t newTop)
Definition: oled_ssd1331.c:274
ssd1306_interface_t ssd1306_intf
lcduint_t height
Definition: lcd_common.h:97
#define SSD1306_COMPAT_SPI_BLOCK_8BIT_CMDS(column_cmd, row_cmd)
Definition: lcd_common.h:330
void ssd1306_sendCommand(uint8_t command)
#define RGB8_TO_RGB16(c)
void(* next_page)(void)
Definition: lcd_common.h:122
void ssd1331_setRotation(uint8_t rotation)
Sets screen orientation (rotation)
Definition: oled_ssd1331.c:130
void ssd1331_96x64_spi_init(int8_t rstPin, int8_t cesPin, int8_t dcPin)
Inits 96x64 RGB OLED display over spi in 8-bit mode (based on SSD1331 controller).
Definition: oled_ssd1331.c:239
lcduint_t width
Definition: lcd_common.h:94
lcd_type_t type
Definition: lcd_common.h:91
void(* set_mode)(lcd_mode_t mode)
Sets library display mode for direct draw functions.
Definition: lcd_common.h:164
void ssd1331_96x64_init(void)
Inits 96x64 RGB OLED display (based on SSD1331 controller).
Definition: oled_ssd1331.c:201
void ssd1331_96x64_spi_init16(int8_t rstPin, int8_t cesPin, int8_t dcPin)
Inits 96x64 RGB OLED display over spi in 16-bit mode (based on SSD1331 controller).
Definition: oled_ssd1331.c:249