aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_oled_driver.md38
-rw-r--r--drivers/oled/oled_driver.c31
-rw-r--r--drivers/oled/oled_driver.h14
3 files changed, 67 insertions, 16 deletions
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index 144b695b7..155dfa9d2 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -2,7 +2,17 @@
2 2
3## OLED Supported Hardware 3## OLED Supported Hardware
4 4
5128x32 OLED modules using SSD1306 driver IC over I2C. Supported on AVR based keyboards. Possible but untested hardware includes ARM based keyboards and other sized OLED modules using SSD1306 over I2C, such as 128x64. 5OLED modules using SSD1306 or SH1106 driver ICs, communicating over I2C.
6Tested combinations:
7
8| IC driver | Size | Keyboard Platform | Notes |
9|-----------|--------|-------------------|--------------------------|
10| SSD1306 | 128x32 | AVR | Primary support |
11| SSD1306 | 128x64 | AVR | Verified working |
12| SSD1306 | 128x32 | ARM | |
13| SH1106 | 128x64 | AVR | No rotation or scrolling |
14
15Hardware configurations using ARM-based microcontrollers or different sizes of OLED modules may be compatible, but are untested.
6 16
7!> Warning: This OLED Driver currently uses the new i2c_master driver from split common code. If your split keyboard uses i2c to communication between sides this driver could cause an address conflict (serial is fine). Please contact your keyboard vendor and ask them to migrate to the latest split common code to fix this. 17!> Warning: This OLED Driver currently uses the new i2c_master driver from split common code. If your split keyboard uses i2c to communication between sides this driver could cause an address conflict (serial is fine). Please contact your keyboard vendor and ask them to migrate to the latest split common code to fix this.
8 18
@@ -86,17 +96,17 @@ void oled_task_user(void) {
86 96
87 ## Basic Configuration 97 ## Basic Configuration
88 98
89|Define |Default |Description | 99| Define | Default | Description |
90|-----------------------|---------------|------------------------------------------------| 100|------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------|
91|`OLED_DISPLAY_ADDRESS` |`0x3C` |The i2c address of the OLED Display | 101| `OLED_DISPLAY_ADDRESS` | `0x3C` | The i2c address of the OLED Display |
92|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts | 102| `OLED_FONT_H` | `"glcdfont.c"` | The font code file to use for custom fonts |
93|`OLED_FONT_START` |`0` |The starting characer index for custom fonts | 103| `OLED_FONT_START` | `0` | The starting characer index for custom fonts |
94|`OLED_FONT_END` |`224` |The ending characer index for custom fonts | 104| `OLED_FONT_END` | `224` | The ending characer index for custom fonts |
95|`OLED_FONT_WIDTH` |`6` |The font width | 105| `OLED_FONT_WIDTH` | `6` | The font width |
96|`OLED_FONT_HEIGHT` |`8` |The font height (untested) | 106| `OLED_FONT_HEIGHT` | `8` | The font height (untested) |
97|`OLED_DISABLE_TIMEOUT` |*Not defined* |Disables the built in OLED timeout feature. Useful when implementing custom timeout rules.| 107| `OLED_DISABLE_TIMEOUT` | *Not defined* | Disables the built in OLED timeout feature. Useful when implementing custom timeout rules. |
98 108| `OLED_IC` | `OLED_IC_SSD1306` | Set to `OLED_IC_SH1106` if you're using the SH1106 OLED controller. |
99 109| `OLED_COLUMN_OFFSET` | `0` | (SH1106 only.) Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC. |
100 110
101 ## 128x64 & Custom sized OLED Displays 111 ## 128x64 & Custom sized OLED Displays
102 112
@@ -119,6 +129,8 @@ void oled_task_user(void) {
119 129
120### 90 Degree Rotation - Technical Mumbo Jumbo 130### 90 Degree Rotation - Technical Mumbo Jumbo
121 131
132!> Rotation is unsupported on the SH1106.
133
122```C 134```C
123// OLED Rotation enum values are flags 135// OLED Rotation enum values are flags
124typedef enum { 136typedef enum {
@@ -250,6 +262,8 @@ uint8_t oled_max_chars(void);
250uint8_t oled_max_lines(void); 262uint8_t oled_max_lines(void);
251``` 263```
252 264
265!> Scrolling and rotation are unsupported on the SH1106.
266
253## SSD1306.h driver conversion guide 267## SSD1306.h driver conversion guide
254 268
255|Old API |Recommended New API | 269|Old API |Recommended New API |
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c
index 643e52894..a54f5fadc 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/oled_driver.c
@@ -33,6 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
33#endif // defined(__AVR__) 33#endif // defined(__AVR__)
34 34
35// Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf 35// Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
36// for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf
37
36// Fundamental Commands 38// Fundamental Commands
37#define CONTRAST 0x81 39#define CONTRAST 0x81
38#define DISPLAY_ALL_ON 0xA5 40#define DISPLAY_ALL_ON 0xA5
@@ -40,6 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
40#define NORMAL_DISPLAY 0xA6 42#define NORMAL_DISPLAY 0xA6
41#define DISPLAY_ON 0xAF 43#define DISPLAY_ON 0xAF
42#define DISPLAY_OFF 0xAE 44#define DISPLAY_OFF 0xAE
45#define NOP 0xE3
43 46
44// Scrolling Commands 47// Scrolling Commands
45#define ACTIVATE_SCROLL 0x2F 48#define ACTIVATE_SCROLL 0x2F
@@ -53,6 +56,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
53#define MEMORY_MODE 0x20 56#define MEMORY_MODE 0x20
54#define COLUMN_ADDR 0x21 57#define COLUMN_ADDR 0x21
55#define PAGE_ADDR 0x22 58#define PAGE_ADDR 0x22
59#define PAM_SETCOLUMN_LSB 0x00
60#define PAM_SETCOLUMN_MSB 0x10
61#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
56 62
57// Hardware Configuration Commands 63// Hardware Configuration Commands
58#define DISPLAY_START_LINE 0x40 64#define DISPLAY_START_LINE 0x40
@@ -158,7 +164,11 @@ bool oled_init(uint8_t rotation) {
158 DISPLAY_OFFSET, 0x00, 164 DISPLAY_OFFSET, 0x00,
159 DISPLAY_START_LINE | 0x00, 165 DISPLAY_START_LINE | 0x00,
160 CHARGE_PUMP, 0x14, 166 CHARGE_PUMP, 0x14,
161 MEMORY_MODE, 0x00, }; // Horizontal addressing mode 167#if (OLED_IC != OLED_IC_SH1106)
168 // MEMORY_MODE is unsupported on SH1106 (Page Addressing only)
169 MEMORY_MODE, 0x00, // Horizontal addressing mode
170#endif
171 };
162 if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { 172 if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) {
163 print("oled_init cmd set 1 failed\n"); 173 print("oled_init cmd set 1 failed\n");
164 return false; 174 return false;
@@ -219,10 +229,25 @@ void oled_clear(void) {
219 229
220static void calc_bounds(uint8_t update_start, uint8_t* cmd_array) 230static void calc_bounds(uint8_t update_start, uint8_t* cmd_array)
221{ 231{
222 cmd_array[1] = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; 232 // Calculate commands to set memory addressing bounds.
223 cmd_array[4] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; 233 uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH;
234 uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH;
235#if (OLED_IC == OLED_IC_SH1106)
236 // Commands for Page Addressing Mode. Sets starting page and column; has no end bound.
237 // Column value must be split into high and low nybble and sent as two commands.
238 cmd_array[0] = PAM_PAGE_ADDR | start_page;
239 cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f);
240 cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f);
241 cmd_array[3] = NOP;
242 cmd_array[4] = NOP;
243 cmd_array[5] = NOP;
244#else
245 // Commands for use in Horizontal Addressing mode.
246 cmd_array[1] = start_column;
247 cmd_array[4] = start_page;
224 cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; 248 cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1];
225 cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1; 249 cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1;
250#endif
226} 251}
227 252
228static void calc_bounds_90(uint8_t update_start, uint8_t* cmd_array) 253static void calc_bounds_90(uint8_t update_start, uint8_t* cmd_array)
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index abbdde57e..03dda2e64 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -19,6 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19#include <stdint.h> 19#include <stdint.h>
20#include <stdbool.h> 20#include <stdbool.h>
21 21
22// an enumeration of the chips this driver supports
23#define OLED_IC_SSD1306 0
24#define OLED_IC_SH1106 1
22 25
23#if defined(OLED_DISPLAY_CUSTOM) 26#if defined(OLED_DISPLAY_CUSTOM)
24 // Expected user to implement the necessary defines 27 // Expected user to implement the necessary defines
@@ -100,7 +103,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
100 // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } 103 // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 }
101#endif // defined(OLED_DISPLAY_CUSTOM) 104#endif // defined(OLED_DISPLAY_CUSTOM)
102 105
103// Address to use for tthe i2d oled communication 106#if !defined(OLED_IC)
107 #define OLED_IC OLED_IC_SSD1306
108#endif
109
110// the column address corresponding to the first column in the display hardware
111#if !defined(OLED_COLUMN_OFFSET)
112 #define OLED_COLUMN_OFFSET 0
113#endif
114
115// Address to use for the i2c oled communication
104#if !defined(OLED_DISPLAY_ADDRESS) 116#if !defined(OLED_DISPLAY_ADDRESS)
105 #define OLED_DISPLAY_ADDRESS 0x3C 117 #define OLED_DISPLAY_ADDRESS 0x3C
106#endif 118#endif