aboutsummaryrefslogtreecommitdiff
path: root/drivers/oled
diff options
context:
space:
mode:
authorMichael F. Lamb <mike@datagrok.org>2019-06-11 15:27:17 -0700
committerDrashna Jaelre <drashna@live.com>2019-06-11 15:27:17 -0700
commite6a81133dd3d0d4076a08be76340f905fdbf7c7f (patch)
tree41fbbc4143b915596d5bccd5bd94a3ee74d66048 /drivers/oled
parentb92387b7499e21603e241d136db92c6e716b0cba (diff)
downloadqmk_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.c31
-rw-r--r--drivers/oled/oled_driver.h14
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
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