diff --git a/display_driver.c b/display_driver.c index ca280ac..d229984 100644 --- a/display_driver.c +++ b/display_driver.c @@ -67,6 +67,8 @@ Context *display_create_port(GlobalContext *global, term opts) ctx = ili948x_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, "solomon-systech,ssd1315")) { + ctx = ssd1306_display_create_port(global, opts); } else if (!strcmp(compat_string, "sino-wealth,sh1106")) { ctx = ssd1306_display_create_port(global, opts); } else if (!strcmp(compat_string, "sitronix,st7789") diff --git a/ssd1306_display_driver.c b/ssd1306_display_driver.c index d914a17..1e88894 100644 --- a/ssd1306_display_driver.c +++ b/ssd1306_display_driver.c @@ -53,11 +53,17 @@ #define CMD_SET_COM_SCAN_MODE 0xC8 #define CMD_SET_CHARGE_PUMP 0x8D +typedef enum { + DISPLAY_SSD1306, + DISPLAY_SSD1315, + DISPLAY_SH1106, +} display_type_t; + // TODO: let's change name, since also non SPI display are supported now struct SPI { term i2c_host; - bool is_sh1106; + display_type_t type; Context *ctx; }; @@ -116,7 +122,7 @@ static void do_update(Context *ctx, term display_list) i2c_master_write_byte(cmd, CTRL_BYTE_CMD_SINGLE, true); i2c_master_write_byte(cmd, 0xB0 | ypos / 8, true); - if (spi->is_sh1106) { + if (spi->type == DISPLAY_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); @@ -126,7 +132,7 @@ static void do_update(Context *ctx, term display_list) i2c_master_write_byte(cmd, CTRL_BYTE_DATA_STREAM, true); - if (spi->is_sh1106) { + if (spi->type == DISPLAY_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); @@ -137,12 +143,6 @@ static void do_update(Context *ctx, term display_list) 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); @@ -180,13 +180,26 @@ static void display_init(Context *ctx, term opts) 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); + + if (!(str_ok && compat_string)) { + ESP_LOGE(TAG, "Compatible display not found."); + return; + } + + if(!strcmp(compat_string, "solomon-systech,ssd1306")) { + spi->type = DISPLAY_SSD1306; + } else if(!strcmp(compat_string, "solomon-systech,ssd1315")) { + spi->type = DISPLAY_SSD1315; + } else if(!strcmp(compat_string, "sino-wealth,sh1106")) { + spi->type = DISPLAY_SH1106; } else { + ESP_LOGE(TAG, "Unsupported display: %s", compat_string); + free(compat_string); return; } + free(compat_string); + int reset_gpio; if (!display_common_gpio_from_opts(opts, ATOM_STR("\x5", "reset"), &reset_gpio, glb)) { ESP_LOGI(TAG, "Reset GPIO not configured."); @@ -209,8 +222,26 @@ static void display_init(Context *ctx, term opts) i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, CTRL_BYTE_CMD_STREAM, true); - i2c_master_write_byte(cmd, CMD_SET_CHARGE_PUMP, true); - i2c_master_write_byte(cmd, 0x14, true); + if(spi->type == DISPLAY_SSD1306) { + i2c_master_write_byte(cmd, CMD_SET_CHARGE_PUMP, true); + i2c_master_write_byte(cmd, 0x14, true); + } else if(spi->type == DISPLAY_SSD1315) { + i2c_master_write_byte(cmd, CMD_SET_CHARGE_PUMP, true); + i2c_master_write_byte(cmd, 0x10, true); + + i2c_master_write_byte(cmd, 0xD5, true); // Display clock + i2c_master_write_byte(cmd, 0x80, true); + + i2c_master_write_byte(cmd, 0xA8, true); // Multiplex + i2c_master_write_byte(cmd, 0x3F, true); + + i2c_master_write_byte(cmd, 0xD9, true); // Pre-charge + i2c_master_write_byte(cmd, 0x22, true); + + i2c_master_write_byte(cmd, 0xDB, true); // VCOMH + i2c_master_write_byte(cmd, 0x20, true); + } + // SH1106 Do not need CMD_SET_CHARGE_PUMP setting i2c_master_write_byte(cmd, CMD_SET_SEGMENT_REMAP, true); i2c_master_write_byte(cmd, CMD_SET_COM_SCAN_MODE, true);