~ruther/qmk_firmware

09968ba035f3bfa4df5b1d142dddfa669aefb2d7 — XScorpion2 6 years ago 54ac80d
Fixing OLED Driver for 128x64 displays (#6085)

3 files changed, 54 insertions(+), 8 deletions(-)

M docs/feature_oled_driver.md
M drivers/oled/oled_driver.c
M drivers/oled/oled_driver.h
M docs/feature_oled_driver.md => docs/feature_oled_driver.md +5 -4
@@ 108,10 108,11 @@ void oled_task_user(void) {
|`OLED_DISPLAY_CUSTOM`  |*Not defined*  |Changes the display defines for use with custom displays.<br />Requires user to implement the below defines. |
|`OLED_DISPLAY_WIDTH`   |`128`          |The width of the OLED display.                                   |
|`OLED_DISPLAY_HEIGHT`  |`32`           |The height of the OLED display.                                  |
|`OLED_MATRIX_SIZE`     |`512`          |The local buffer size to allocate.<br />`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`|
|`OLED_BLOCK_TYPE`      |`uint16_t`     |The unsigned integer type to use for dirty rendering.|
|`OLED_BLOCK_COUNT`     |`16`           |The number of blocks the display is divided into for dirty rendering.<br />`(sizeof(OLED_BLOCK_TYPE) * 8)`|
|`OLED_BLOCK_SIZE`      |`32`           |The size of each block for dirty rendering<br />`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`|
|`OLED_MATRIX_SIZE`     |`512`          |The local buffer size to allocate.<br />`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`. |
|`OLED_BLOCK_TYPE`      |`uint16_t`     |The unsigned integer type to use for dirty rendering. |
|`OLED_BLOCK_COUNT`     |`16`           |The number of blocks the display is divided into for dirty rendering.<br />`(sizeof(OLED_BLOCK_TYPE) * 8)`. |
|`OLED_BLOCK_SIZE`      |`32`           |The size of each block for dirty rendering<br />`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`. |
|`OLED_COM_PINS`        |`COM_PINS_SEQ` |How the SSD1306 chip maps it's memory to display.<br />Options are `COM_PINS_SEQ`, `COM_PINS_ALT`, `COM_PINS_SEQ_LR`, & `COM_PINS_ALT_LR`. |
|`OLED_SOURCE_MAP`      |`{ 0, ... N }` |Precalculated source array to use for mapping source buffer to target OLED memory in 90 degree rendering.         |
|`OLED_TARGET_MAP`      |`{ 24, ... N }`|Precalculated target array to use for mapping source buffer to target OLED memory in 90 degree rendering.         |


M drivers/oled/oled_driver.c => drivers/oled/oled_driver.c +5 -1
@@ 63,6 63,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#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,

M drivers/oled/oled_driver.h => drivers/oled/oled_driver.h +44 -3
@@ 24,17 24,39 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  // 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 <http://www.gnu.org/licenses/>.
  // #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 }