diff options
| author | Michael F. Lamb <mike@datagrok.org> | 2019-06-11 15:27:17 -0700 |
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2019-06-11 15:27:17 -0700 |
| commit | e6a81133dd3d0d4076a08be76340f905fdbf7c7f (patch) | |
| tree | 41fbbc4143b915596d5bccd5bd94a3ee74d66048 /drivers/oled | |
| parent | b92387b7499e21603e241d136db92c6e716b0cba (diff) | |
| download | qmk_firmware-e6a81133dd3d0d4076a08be76340f905fdbf7c7f.tar.gz qmk_firmware-e6a81133dd3d0d4076a08be76340f905fdbf7c7f.zip | |
Add SH1106 OLED support (#5787)
* modify oled_driver to support SH1106
also:
- improve mechanism to specify which OLED IC we use
- comment calc_bounds()
- give OLED_COLUMN_OFFSET a default value
- inline comment re: OLED MEMORY_MODE and SH1106
- update docs/feature_oled_driver.h for SH1106 support and related changes
- docs: OLED: note we have tested SSD1306 on ARM boards (per @XScorpion2)
- define out MEMORY_MODE when using SH1106 OLED driver
* document that SSD1306 128x64 on AVR works
Per @XScorpion2: https://github.com/qmk/qmk_firmware/pull/5787#discussion_r291837842
Diffstat (limited to 'drivers/oled')
| -rw-r--r-- | drivers/oled/oled_driver.c | 31 | ||||
| -rw-r--r-- | drivers/oled/oled_driver.h | 14 |
2 files changed, 41 insertions, 4 deletions
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 | ||
| 220 | static void calc_bounds(uint8_t update_start, uint8_t* cmd_array) | 230 | static 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 | ||
| 228 | static void calc_bounds_90(uint8_t update_start, uint8_t* cmd_array) | 253 | static 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 |
