SH1106 OLED Display driver for libDaisy Nim wrapper
The SH1106 is a popular and cost-effective alternative to the SSD1306 OLED controller. It is nearly identical to the SSD130x series, with the primary difference being the column addressing scheme used in the Update() method. This driver extends the SSD130x driver and only overrides the Update() implementation.
Features:
- 128x64 monochrome display support
- I2C and 4-wire SPI transport options
- Compatible with SSD130x API (drop-in replacement)
- Same drawing functions as SSD130x (pixel, line, rect, circle, etc.)
Hardware Notes:
- Common in cheap OLED modules (often labeled "SSD1306 compatible")
- Column addressing differs: uses 0x02 base instead of 0x00
- Uses same transports (SSD130xI2CTransport, SSD130x4WireSpiTransport)
Example - I2C display:
import nimphea import nimphea/dev/oled_sh1106 var display = initSH1106I2c(128, 64) display.fill(false) display.drawPixel(64, 32, true) display.drawCircle(64, 32, 10, true) display.update()
Example - SPI display (faster updates):
import nimphea import nimphea/dev/oled_sh1106 var display = initSH1106Spi(128, 64) while true: display.fill(false) display.drawRect(10, 10, 108, 44, true) display.update() hw.delay(50)
Differences from SSD130x:
- Update() uses different column start address (0x02 vs 0x00)
- Same initialization sequence
- Same framebuffer format
- Same drawing API
Types
SH1106I2c128x64 {.importcpp: "SH1106I2c128x64".} = object
- Source Edit
SH1106I2cConfig {.importcpp: "SH1106I2c128x64::Config", bycopy.} = object transport_config* {.importc: "transport_config".}: SSD130xI2CTransportConfig
- Source Edit
SH1106Spi128x64 {.importcpp: "SH1106Spi128x64".} = object
- Source Edit
SH1106SpiConfig {.importcpp: "SH1106Spi128x64::Config", bycopy.} = object transport_config* {.importc: "transport_config".}: SSD130x4WireSpiTransportConfig
- Source Edit
SSD130x4WireSpiTransportConfig {.importcpp: "daisy::SSD130x4WireSpiTransport::Config", bycopy.} = object spi_config* {.importc: "spi_config".}: SpiConfig pin_config* {.importc: "pin_config".}: SSD130xSpiPinConfig useDma* {.importc: "useDma".}: bool
- Source Edit
SSD130xI2CTransportConfig {.importcpp: "daisy::SSD130xI2CTransport::Config", bycopy.} = object i2c_config* {.importc: "i2c_config".}: I2CConfig i2c_address* {.importc: "i2c_address".}: uint8
- Source Edit
SSD130xSpiPinConfig {.importcpp: "daisy::SSD130x4WireSpiTransport::Config::pin_config", bycopy.} = object dc* {.importc: "dc".}: Pin reset* {.importc: "reset".}: Pin
- Source Edit
Consts
SH1106_I2C_ADDRESS_ALT = 0x0000003D
- Alternate I2C address (set via jumper on some modules) Source Edit
SH1106_I2C_ADDRESS_DEFAULT = 0x0000003C
- Default I2C address for SH1106 displays Source Edit
Procs
proc Defaults(config: var SSD130x4WireSpiTransportConfig) {. importcpp: "#.Defaults()", header: "daisy_seed.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc Defaults(config: var SSD130xI2CTransportConfig) {. importcpp: "#.Defaults()", header: "daisy_seed.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc drawCircle(display: var OledSH1106; x0, y0, radius: int; on: bool = true)
-
Draw a circle outline using midpoint circle algorithm
Parameters:
- x0, y0 - Center point
- radius - Circle radius in pixels
- on - true for white, false for black
proc drawLine(display: var OledSH1106; x0, y0, x1, y1: int; on: bool = true)
-
Draw a line using Bresenham's algorithm
Parameters:
- x0, y0 - Start point
- x1, y1 - End point
- on - true for white, false for black
proc drawPixel(display: var OledSH1106; x, y: int; on: bool = true)
-
Draw a single pixel
Parameters:
- x, y - Pixel coordinates (0-based)
- on - true for white, false for black
proc drawRect(display: var OledSH1106; x, y, w, h: int; on: bool = true)
-
Draw a rectangle outline
Parameters:
- x, y - Top-left corner
- w, h - Width and height
- on - true for white, false for black
proc fill(display: var OledSH1106; on: bool = true)
-
Fill entire display with a color
Parameters:
- on - true for white, false for black
proc fillRect(display: var OledSH1106; x, y, w, h: int; on: bool = true)
-
Draw a filled rectangle
Parameters:
- x, y - Top-left corner
- w, h - Width and height
- on - true for white, false for black
proc height(display: OledSH1106): int {.inline.}
- Get display height in pixels Source Edit
proc update(display: var OledSH1106)
- Send framebuffer to display hardware Call this after drawing to make changes visible Source Edit
proc width(display: OledSH1106): int {.inline.}
- Get display width in pixels Source Edit
Templates
template initSH1106I2c(width, height: static[int]; sclPin: Pin = newPin(PORTB, 8); sdaPin: Pin = newPin(PORTB, 9); address: uint8 = 0x0000003C): untyped
-
Initialize SH1106 OLED via I2C
Parameters:
- width, height - Display dimensions (only 128x64 supported)
- sclPin - I2C clock pin (default: PB8)
- sdaPin - I2C data pin (default: PB9)
- address - I2C address (default: 0x3C, alt: 0x3D)
Returns: Initialized display instance
Example:
var oled = initSH1106I2c(128, 64) oled.fill(false) oled.drawPixel(64, 32, true) oled.update()
Source Edit template initSH1106Spi(width, height: static[int]; dcPin: Pin = newPin(PORTB, 4); resetPin: Pin = newPin(PORTB, 15); sclkPin: Pin = newPin(PORTG, 11); mosiPin: Pin = newPin(PORTB, 5); nssPin: Pin = newPin(PORTG, 10)): untyped
-
Initialize SH1106 OLED via SPI (faster than I2C)
Parameters:
- width, height - Display dimensions (only 128x64 supported)
- dcPin - Data/Command pin (default: PB4)
- resetPin - Reset pin (default: PB15)
- sclkPin - SPI clock pin (default: PG11)
- mosiPin - SPI MOSI pin (default: PB5)
- nssPin - SPI chip select pin (default: PG10)
Returns: Initialized display instance
Example:
var oled = initSH1106Spi(128, 64) while true: oled.fill(false) oled.drawCircle(64, 32, 20, true) oled.update() hw.delay(50)
Source Edit