From 09968ba035f3bfa4df5b1d142dddfa669aefb2d7 Mon Sep 17 00:00:00 2001 From: XScorpion2 Date: Fri, 7 Jun 2019 19:02:05 -0500 Subject: Fixing OLED Driver for 128x64 displays (#6085) --- drivers/oled/oled_driver.c | 6 +++++- drivers/oled/oled_driver.h | 47 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) (limited to 'drivers/oled') diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 96ea58ccb2..643e528946 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -63,6 +63,10 @@ along with this program. If not, see . #define COM_SCAN_DEC 0xC8 #define DISPLAY_OFFSET 0xD3 #define COM_PINS 0xDA +#define COM_PINS_SEQ 0x02 +#define COM_PINS_ALT 0x12 +#define COM_PINS_SEQ_LR 0x22 +#define COM_PINS_ALT_LR 0x32 // Timing & Driving Commands #define DISPLAY_CLOCK 0xD5 @@ -182,7 +186,7 @@ bool oled_init(uint8_t rotation) { static const uint8_t PROGMEM display_setup2[] = { I2C_CMD, - COM_PINS, 0x02, + COM_PINS, OLED_COM_PINS, CONTRAST, 0x8F, PRE_CHARGE_PERIOD, 0xF1, VCOM_DETECT, 0x40, diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index ec07f1d9b8..abbdde57ed 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -24,17 +24,39 @@ along with this program. If not, see . // Expected user to implement the necessary defines #elif defined(OLED_DISPLAY_128X64) // Double height 128x64 +#ifndef OLED_DISPLAY_WIDTH #define OLED_DISPLAY_WIDTH 128 +#endif +#ifndef OLED_DISPLAY_HEIGHT #define OLED_DISPLAY_HEIGHT 64 +#endif +#ifndef OLED_MATRIX_SIZE #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed) - #define OLED_BLOCK_TYPE uint32_t +#endif +#ifndef OLED_BLOCK_TYPE + #define OLED_BLOCK_TYPE uint16_t +#endif +#ifndef OLED_BLOCK_COUNT #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed) +#endif +#ifndef OLED_BLOCK_SIZE #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) +#endif +#ifndef OLED_COM_PINS + #define OLED_COM_PINS COM_PINS_ALT +#endif // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode - #define OLED_SOURCE_MAP { 32, 40, 48, 56 } - #define OLED_TARGET_MAP { 24, 16, 8, 0 } +#ifndef OLED_SOURCE_MAP + #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } +#endif +#ifndef OLED_TARGET_MAP + #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } +#endif + // If OLED_BLOCK_TYPE is uint32_t, these tables would look like: + // #define OLED_SOURCE_MAP { 32, 40, 48, 56 } + // #define OLED_TARGET_MAP { 24, 16, 8, 0 } // If OLED_BLOCK_TYPE is uint16_t, these tables would look like: // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } // #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } @@ -43,17 +65,36 @@ along with this program. If not, see . // #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 } #else // defined(OLED_DISPLAY_128X64) // Default 128x32 +#ifndef OLED_DISPLAY_WIDTH #define OLED_DISPLAY_WIDTH 128 +#endif +#ifndef OLED_DISPLAY_HEIGHT #define OLED_DISPLAY_HEIGHT 32 +#endif +#ifndef OLED_MATRIX_SIZE #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed) +#endif +#ifndef OLED_BLOCK_TYPE #define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only +#endif +#ifndef OLED_BLOCK_COUNT #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed) +#endif +#ifndef OLED_BLOCK_SIZE #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) +#endif +#ifndef OLED_COM_PINS + #define OLED_COM_PINS COM_PINS_SEQ +#endif // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode +#ifndef OLED_SOURCE_MAP #define OLED_SOURCE_MAP { 0, 8, 16, 24 } +#endif +#ifndef OLED_TARGET_MAP #define OLED_TARGET_MAP { 24, 16, 8, 0 } +#endif // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } -- cgit v1.2.3 From e6a81133dd3d0d4076a08be76340f905fdbf7c7f Mon Sep 17 00:00:00 2001 From: "Michael F. Lamb" Date: Tue, 11 Jun 2019 15:27:17 -0700 Subject: 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 --- drivers/oled/oled_driver.c | 31 ++++++++++++++++++++++++++++--- drivers/oled/oled_driver.h | 14 +++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers/oled') diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 643e528946..a54f5fadc3 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -33,6 +33,8 @@ along with this program. If not, see . #endif // defined(__AVR__) // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf +// for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf + // Fundamental Commands #define CONTRAST 0x81 #define DISPLAY_ALL_ON 0xA5 @@ -40,6 +42,7 @@ along with this program. If not, see . #define NORMAL_DISPLAY 0xA6 #define DISPLAY_ON 0xAF #define DISPLAY_OFF 0xAE +#define NOP 0xE3 // Scrolling Commands #define ACTIVATE_SCROLL 0x2F @@ -53,6 +56,9 @@ along with this program. If not, see . #define MEMORY_MODE 0x20 #define COLUMN_ADDR 0x21 #define PAGE_ADDR 0x22 +#define PAM_SETCOLUMN_LSB 0x00 +#define PAM_SETCOLUMN_MSB 0x10 +#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 // Hardware Configuration Commands #define DISPLAY_START_LINE 0x40 @@ -158,7 +164,11 @@ bool oled_init(uint8_t rotation) { DISPLAY_OFFSET, 0x00, DISPLAY_START_LINE | 0x00, CHARGE_PUMP, 0x14, - MEMORY_MODE, 0x00, }; // Horizontal addressing mode +#if (OLED_IC != OLED_IC_SH1106) + // MEMORY_MODE is unsupported on SH1106 (Page Addressing only) + MEMORY_MODE, 0x00, // Horizontal addressing mode +#endif + }; if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { print("oled_init cmd set 1 failed\n"); return false; @@ -219,10 +229,25 @@ void oled_clear(void) { static void calc_bounds(uint8_t update_start, uint8_t* cmd_array) { - cmd_array[1] = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; - cmd_array[4] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; + // Calculate commands to set memory addressing bounds. + uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; + uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; +#if (OLED_IC == OLED_IC_SH1106) + // Commands for Page Addressing Mode. Sets starting page and column; has no end bound. + // Column value must be split into high and low nybble and sent as two commands. + cmd_array[0] = PAM_PAGE_ADDR | start_page; + cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); + cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); + cmd_array[3] = NOP; + cmd_array[4] = NOP; + cmd_array[5] = NOP; +#else + // Commands for use in Horizontal Addressing mode. + cmd_array[1] = start_column; + cmd_array[4] = start_page; cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1; +#endif } 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 abbdde57ed..03dda2e64a 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -19,6 +19,9 @@ along with this program. If not, see . #include #include +// an enumeration of the chips this driver supports +#define OLED_IC_SSD1306 0 +#define OLED_IC_SH1106 1 #if defined(OLED_DISPLAY_CUSTOM) // Expected user to implement the necessary defines @@ -100,7 +103,16 @@ along with this program. If not, see . // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } #endif // defined(OLED_DISPLAY_CUSTOM) -// Address to use for tthe i2d oled communication +#if !defined(OLED_IC) + #define OLED_IC OLED_IC_SSD1306 +#endif + +// the column address corresponding to the first column in the display hardware +#if !defined(OLED_COLUMN_OFFSET) + #define OLED_COLUMN_OFFSET 0 +#endif + +// Address to use for the i2c oled communication #if !defined(OLED_DISPLAY_ADDRESS) #define OLED_DISPLAY_ADDRESS 0x3C #endif -- cgit v1.2.3