Skip to content

Commit

Permalink
Add support to Sino Wealth SH1106 OLED controller
Browse files Browse the repository at this point in the history
SH1106 is basically a SSD1306 with few changes.
SH1106 codepath is marked with `if (is_sh1106) { [...] }`.

Signed-off-by: Davide Bettio <[email protected]>
  • Loading branch information
bettio committed Mar 9, 2024
1 parent 6bd1e59 commit 58044d9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.Md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pushing updates to it. For this reason no additional NIFs are provided.
software dithering
* `sharp,memory-lcd`: Sharp Memory LCDs: 400x240 1-bit monochromatic
* `solomon-systech,ssd1306`: Solomon Systech SSD1306: 128x64 1-bit monochromatic
* `sino-wealth,sh1106`: Sino Wealth SH1106: 128x64 1-bit monochromatic

[SDL Linux display](sdl_display/) is also supported and can be built as AtomVM plugin.

Expand Down
2 changes: 2 additions & 0 deletions display_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Context *display_create_port(GlobalContext *global, term opts)
ctx = ili934x_display_create_port(global, opts);
} else if (!strcmp(compat_string, "solomon-systech,ssd1306")) {
ctx = ssd1306_display_create_port(global, opts);
} else if (!strcmp(compat_string, "sino-wealth,sh1106")) {
ctx = ssd1306_display_create_port(global, opts);
} else {
ESP_LOGE(TAG, "No matching display driver for given `comptaible`: `%s`.", compat_string);
}
Expand Down
35 changes: 35 additions & 0 deletions ssd1306_display_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
struct SPI
{
term i2c_host;
bool is_sh1106;
Context *ctx;
};

Expand Down Expand Up @@ -112,12 +113,36 @@ static void do_update(Context *ctx, term display_list)
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);

i2c_master_write_byte(cmd, CTRL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0xB0 | ypos / 8, true);
if (spi->is_sh1106) {
// set the column, otherwise the starting column will be somewhere in the middle
i2c_master_write_byte(cmd, CTRL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0x00, true);
i2c_master_write_byte(cmd, CTRL_BYTE_CMD_SINGLE, true);
i2c_master_write_byte(cmd, 0x10, true);
}
i2c_master_write_byte(cmd, CTRL_BYTE_DATA_STREAM, true);


if (spi->is_sh1106) {
// add 2 empty pages on sh1106 since it can have up to 132 pixels
// and 128 pixel screen starts at (2, 0)
i2c_master_write_byte(cmd, 0, true);
i2c_master_write_byte(cmd, 0, true);
}

for (uint8_t j = 0; j < DISPLAY_WIDTH; j++) {
i2c_master_write_byte(cmd, out_buf[j], true);
}

// no need to send the last 2 page, the position will be set on next line again
// if (spi->is_sh1106) {
// i2c_master_write_byte(cmd, 0, true);
// i2c_master_write_byte(cmd, 0, true);
// }

i2c_master_stop(cmd);
i2c_master_cmd_begin(i2c_num, cmd, 10 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
Expand Down Expand Up @@ -152,6 +177,16 @@ static void display_init(Context *ctx, term opts)

spi->ctx = ctx;

term compat_value_term = interop_kv_get_value_default(opts, ATOM_STR("\xA", "compatible"), term_nil(), ctx->global);
int str_ok;
char *compat_string = interop_term_to_string(compat_value_term, &str_ok);
if (str_ok && compat_string) {
spi->is_sh1106 = !strcmp(compat_string, "sino-wealth,sh1106");
free(compat_string);
} else {
return;
}

int reset_gpio;
if (!display_common_gpio_from_opts(opts, ATOM_STR("\x5", "reset"), &reset_gpio, glb)) {
ESP_LOGI(TAG, "Reset GPIO not configured.");
Expand Down

0 comments on commit 58044d9

Please sign in to comment.