SSD1306 OLED display driver  1.7.1
This library is developed to control SSD1306/SSD1331/SSD1351/IL9163/PCD8554 RGB i2c/spi LED displays
oled_ssd1351.c
1 /*
2  MIT License
3 
4  Copyright (c) 2018, 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_ssd1351.h"
26 #include "lcd_common.h"
27 #include "ssd1351_commands.h"
28 #include "intf/ssd1306_interface.h"
29 #include "intf/spi/ssd1306_spi.h"
30 #include "ssd1306_hal/io.h"
31 #include "nano_gfx_types.h"
32 
33 #define CMD_ARG 0xFF
34 
35 extern uint16_t ssd1306_color;
36 extern uint32_t s_ssd1306_spi_clock;
37 
38 static const PROGMEM uint8_t s_oled128x128_initData[] =
39 {
40  SSD1351_UNLOCK, CMD_ARG, 0x12,
41  SSD1351_UNLOCK, CMD_ARG, 0xB1,
42  SSD1351_SLEEP_ON,
43  SSD1351_CLOCKDIV, CMD_ARG, 0xF1, // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
44  SSD1351_SETMULTIPLEX, CMD_ARG, 127, // Reset to default MUX. See datasheet
45  SSD1351_SEGREMAP, CMD_ARG, 0B00110101, // 16-bit rgb color mode
46  SSD1351_SETSTARTLINE, CMD_ARG, 0x00, // First line to start scanning from
47  SSD1351_SETDISPLAYOFFSET, CMD_ARG, 0x00, // Set display offset
48  SSD1351_SETGPIO, CMD_ARG, 0x00, // GPIO OFF
49  SSD1351_SETFUNCTION, CMD_ARG, 0x01,
50  SSD1351_SETPRECHARGE, CMD_ARG, 0x32, // Phase 1 and Phase 2 periods
51  SSD1351_VCOMH, CMD_ARG, 0x05, //
52  SSD1351_PRECHARGELEVEL, CMD_ARG, 0x17,
53  SSD1351_NORMALDISPLAY,
54  SSD1351_CONTRAST, CMD_ARG, 0xC8, // RED
55  CMD_ARG, 0x80, // GREEN
56  CMD_ARG, 0xC8, // BLUE
57  SSD1351_MASTERCURRENT, CMD_ARG, 0x0F, //
58  SSD1351_EXTVSL, CMD_ARG, 0xA0, CMD_ARG, 0xB5, CMD_ARG, 0x55,
59  SSD1351_PRECHARGESECOND, CMD_ARG, 0x01, //
60  SSD1351_SLEEP_OFF, // Disable power-safe mode
61  SSD1351_NORMALDISPLAY,
62 };
63 
64 static uint8_t s_column;
65 static uint8_t s_page;
66 
67 static void ssd1351_setBlock(lcduint_t x, lcduint_t y, lcduint_t w)
68 {
69  uint8_t rx = w ? (x + w - 1) : (ssd1306_lcd.width - 1);
70  s_column = x;
71  s_page = y;
74  ssd1306_intf.send(SSD1351_COLUMNADDR);
75  ssd1306_spiDataMode(1); // According to datasheet all args must be passed in data mode
76  ssd1306_intf.send(x);
79  ssd1306_intf.send(SSD1351_ROWADDR);
80  ssd1306_spiDataMode(1); // According to datasheet all args must be passed in data mode
81  ssd1306_intf.send(y<<3);
82  ssd1306_intf.send(((y<<3) + 7) < ssd1306_lcd.height ? ((y<<3) + 7) : (ssd1306_lcd.height - 1));
84  ssd1306_intf.send(SSD1331_WRITEDATA);
86 }
87 
88 static void ssd1351_setBlock2(lcduint_t x, lcduint_t y, lcduint_t w)
89 {
90  uint8_t rx = w ? (x + w - 1) : (ssd1306_lcd.width - 1);
93  ssd1306_intf.send(SSD1351_COLUMNADDR);
94  ssd1306_spiDataMode(1); // According to datasheet all args must be passed in data mode
95  ssd1306_intf.send(x);
98  ssd1306_intf.send(SSD1351_ROWADDR);
99  ssd1306_spiDataMode(1); // According to datasheet all args must be passed in data mode
100  ssd1306_intf.send(y);
103  ssd1306_intf.send(SSD1331_WRITEDATA);
105 }
106 
107 static void ssd1351_nextPage(void)
108 {
109  ssd1306_intf.stop();
110  ssd1351_setBlock(s_column,s_page+1,0);
111 }
112 
113 static void ssd1351_nextPage2(void)
114 {
115 }
116 
118 {
121  ssd1306_intf.send( SSD1351_SEGREMAP );
123  ssd1306_intf.send( 0B00110100 | mode );
124  ssd1306_intf.stop();
125  if (mode)
126  {
127  ssd1306_lcd.set_block = ssd1351_setBlock;
128  ssd1306_lcd.next_page = ssd1351_nextPage;
129  }
130  else
131  {
132  ssd1306_lcd.set_block = ssd1351_setBlock2;
133  ssd1306_lcd.next_page = ssd1351_nextPage2;
134  }
135 }
136 
137 static void ssd1351_sendPixels(uint8_t data)
138 {
139  for (uint8_t i=8; i>0; i--)
140  {
141  if ( data & 0x01 )
142  {
143  ssd1306_intf.send( (uint8_t)(ssd1306_color>>8) );
144  ssd1306_intf.send( (uint8_t)(ssd1306_color) );
145  }
146  else
147  {
148  ssd1306_intf.send( 0B00000000 );
149  ssd1306_intf.send( 0B00000000 );
150  }
151  data >>= 1;
152  }
153 }
154 
155 static void ssd1351_sendPixelsBuffer(const uint8_t *buffer, uint16_t len)
156 {
157  while(len--)
158  {
159  ssd1351_sendPixels(*buffer);
160  buffer++;
161  }
162 }
163 
164 static void ssd1351_sendPixel8(uint8_t data)
165 {
166  uint16_t color = RGB8_TO_RGB16(data);
167  ssd1306_intf.send( color >> 8 );
168  ssd1306_intf.send( color & 0xFF );
169 }
170 
172 {
174  ssd1306_lcd.height = 128;
175  ssd1306_lcd.width = 128;
176  ssd1306_lcd.set_block = ssd1351_setBlock;
177  ssd1306_lcd.next_page = ssd1351_nextPage;
178  ssd1306_lcd.send_pixels1 = ssd1351_sendPixels;
179  ssd1306_lcd.send_pixels_buffer1 = ssd1351_sendPixelsBuffer;
180  ssd1306_lcd.send_pixels8 = ssd1351_sendPixel8;
184  for( uint8_t i=0; i<sizeof(s_oled128x128_initData); i++)
185  {
186  uint8_t data = pgm_read_byte(&s_oled128x128_initData[i]);
187  if (data == CMD_ARG)
188  {
189  data = pgm_read_byte(&s_oled128x128_initData[++i]);
191  ssd1306_intf.send(data);
193  }
194  else
195  {
196  ssd1306_intf.send(data);
197  }
198  }
199  ssd1306_intf.stop();
200 }
201 
202 void ssd1351_128x128_spi_init(int8_t rstPin, int8_t cesPin, int8_t dcPin)
203 {
204  if (rstPin >=0)
205  {
206  pinMode(rstPin, OUTPUT);
207  digitalWrite(rstPin, HIGH);
208  /* Wait at least 1ms after VCC is up for LCD */
209  delay(1);
210  /* Perform reset operation of LCD display */
211  digitalWrite(rstPin, LOW);
212  delay(20);
213  digitalWrite(rstPin, HIGH);
214  }
215  /* ssd1351 cannot work faster than at 4MHz per datasheet */
216  s_ssd1306_spi_clock = 4000000;
217  ssd1306_spiInit(cesPin, dcPin);
219 }
void ssd1351_setMode(lcd_mode_t mode)
Sets GDRAM autoincrement mode.
Definition: oled_ssd1351.c:117
void(* send)(uint8_t data)
uint32_t s_ssd1306_spi_clock
Definition: ssd1306_spi.c:35
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 ssd1351_128x128_init(void)
Inits 128x128 RGB OLED display (based on SSD1351 controller).
Definition: oled_ssd1351.c:171
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(* send_pixels1)(uint8_t data)
Definition: lcd_common.h:128
void ssd1306_spiInit(int8_t cesPin, int8_t dcPin)
Definition: ssd1306_spi.c:37
ssd1306_lcd_t ssd1306_lcd
Definition: lcd_common.c:32
void ssd1351_128x128_spi_init(int8_t rstPin, int8_t cesPin, int8_t dcPin)
Inits 128x128 RGB OLED display over spi (based on SSD1351 controller).
Definition: oled_ssd1351.c:202
ssd1306_interface_t ssd1306_intf
lcduint_t height
Definition: lcd_common.h:97
#define RGB8_TO_RGB16(c)
void(* next_page)(void)
Definition: lcd_common.h:122
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:157