From 4c91ba130ae8af3eab8fca196000806a0a7da909 Mon Sep 17 00:00:00 2001 From: FrankX0 Date: Wed, 19 May 2021 21:25:15 +0200 Subject: [PATCH] Support for EA OLEDS102-6 Added support for a 102x64 OLED display from EA --- cppsrc/U8g2lib.h | 12 +++++ csrc/u8g2.h | 1 + csrc/u8g2_d_setup.c | 9 ++++ csrc/u8x8.h | 1 + csrc/u8x8_d_ssd1309.c | 112 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+) diff --git a/cppsrc/U8g2lib.h b/cppsrc/U8g2lib.h index 0deb0330d..60e65b78f 100644 --- a/cppsrc/U8g2lib.h +++ b/cppsrc/U8g2lib.h @@ -5660,6 +5660,18 @@ class U8G2_SSD1309_128X64_NONAME0_1_8080 : public U8G2 { u8x8_SetPin_8Bit_8080(getU8x8(), d0, d1, d2, d3, d4, d5, d6, d7, enable, cs, dc, reset); } }; +class U8G2_SSD1309_102X64_EA_OLEDS102_F_4W_SW_SPI : public U8G2 { + public: U8G2_SSD1309_102X64_EA_OLEDS102_F_4W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1309_102x64_ea_oleds102_f(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_SW_SPI(getU8x8(), clock, data, cs, dc, reset); + } +}; +class U8G2_SSD1309_102X64_EA_OLEDS102_F_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1309_102X64_EA_OLEDS102_F_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1309_102x64_ea_oleds102_f(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; class U8G2_SSD1309_128X64_NONAME0_2_4W_SW_SPI : public U8G2 { public: U8G2_SSD1309_128X64_NONAME0_2_4W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1309_128x64_noname0_2(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); diff --git a/csrc/u8g2.h b/csrc/u8g2.h index 3a4531ba2..6179cab77 100644 --- a/csrc/u8g2.h +++ b/csrc/u8g2.h @@ -772,6 +772,7 @@ void u8g2_Setup_ssd1309_i2c_128x64_noname2_f(u8g2_t *u8g2, const u8g2_cb_t *rota void u8g2_Setup_ssd1309_128x64_noname0_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1309_128x64_noname0_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1309_128x64_noname0_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); +void u8g2_Setup_ssd1309_102x64_ea_oleds102_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1309_i2c_128x64_noname0_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1309_i2c_128x64_noname0_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1309_i2c_128x64_noname0_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); diff --git a/csrc/u8g2_d_setup.c b/csrc/u8g2_d_setup.c index 1c153c63a..65b53e793 100644 --- a/csrc/u8g2_d_setup.c +++ b/csrc/u8g2_d_setup.c @@ -1519,6 +1519,15 @@ void u8g2_Setup_ssd1306_i2c_96x16_er_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, buf = u8g2_m_12_2_f(&tile_buf_height); u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); } +/* ssd1309 f */ +void u8g2_Setup_ssd1309_102x64_ea_oleds102_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb) +{ + uint8_t tile_buf_height; + uint8_t *buf; + u8g2_SetupDisplay(u8g2, u8x8_d_ssd1309_102x64_ea_oleds102, u8x8_cad_001, byte_cb, gpio_and_delay_cb); + buf = u8g2_m_13_8_f(&tile_buf_height); + u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); +} /* ssd1309 */ /* ssd1309 1 */ void u8g2_Setup_ssd1309_128x64_noname2_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb) diff --git a/csrc/u8x8.h b/csrc/u8x8.h index 3b7d653e0..272ca95f5 100644 --- a/csrc/u8x8.h +++ b/csrc/u8x8.h @@ -809,6 +809,7 @@ uint8_t u8x8_d_ssd1305_128x64_raystar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1306_128x64_alt0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); +uint8_t u8x8_d_ssd1309_102x64_ea_oleds102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1309_128x64_noname2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_sh1106_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); diff --git a/csrc/u8x8_d_ssd1309.c b/csrc/u8x8_d_ssd1309.c index a75b7faf5..01f9ebe35 100644 --- a/csrc/u8x8_d_ssd1309.c +++ b/csrc/u8x8_d_ssd1309.c @@ -286,3 +286,115 @@ uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int } return 1; } + +static const uint8_t u8x8_d_ssd1309_102x64_ea_oleds102_init_seq[] = { + + U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */ + + U8X8_C(0x40), //Set Display start line + U8X8_C(0xA0), //Bottom View no Segment remap + U8X8_C(0xC0), //Bottom View COM scan direction normal + U8X8_C(0x2E), //StartColumnAddress + U8X8_CA(0x8D, 0x95), //Switch Charge Pump (9V) + U8X8_CA(0x20, 0x02), //Set Memory AddressMode + U8X8_CA(0x81, 0xFF), //Set Brightness + U8X8_CA(0xD5, 0x40), //Set Display Clock Divide + U8X8_CA(0xD9, 0xF1), //Set Precharge Periode + U8X8_CA(0xAD, 0x30), //Set Internal Ref + U8X8_CAA(0x21, 0x0D, 0x72), //Set ColumnAddress to 13x8 + 10 = 114/0x72 + U8X8_CAA(0x22, 0x00, 0x3F), //Set PageAddress + U8X8_C(0xAF), //Display on + + U8X8_END_TRANSFER(), /* disable chip */ + U8X8_END() /* end of sequence */ +}; + +/* timing from SSD1306 */ +static const u8x8_display_info_t u8x8_ssd1309_102x64_ea_oleds102_display_info = +{ + /* chip_enable_level = */ 0, + /* chip_disable_level = */ 1, + + /* post_chip_enable_wait_ns = */ 20, + /* pre_chip_disable_wait_ns = */ 10, + /* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */ + /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */ + /* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */ + /* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */ + /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */ + /* spi_mode = */ 0, /* active high, rising edge */ + /* i2c_bus_clock_100kHz = */ 4, + /* data_setup_time_ns = */ 40, + /* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */ + /* tile_width = */ 13, /* width of 13*8=104 pixel */ + /* tile_hight = */ 8, + /* default_x_offset = */ 13, + /* flipmode_x_offset = */ 13, + /* pixel_width = */ 102, + /* pixel_height = */ 64 +}; + +uint8_t u8x8_d_ssd1309_102x64_ea_oleds102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t x, c; + uint8_t *ptr; + + switch(msg) + { + case U8X8_MSG_DISPLAY_SET_FLIP_MODE: + if ( arg_int == 0 ) + { + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip0_seq); + u8x8->x_offset = u8x8->display_info->default_x_offset; + } + else + { + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip1_seq); + u8x8->x_offset = u8x8->display_info->flipmode_x_offset; + } + break; + case U8X8_MSG_DISPLAY_INIT: + u8x8_d_helper_display_init(u8x8); + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_102x64_ea_oleds102_init_seq); + break; + case U8X8_MSG_DISPLAY_SETUP_MEMORY: + u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1309_102x64_ea_oleds102_display_info); + break; + case U8X8_MSG_DISPLAY_SET_CONTRAST: + u8x8_cad_StartTransfer(u8x8); + u8x8_cad_SendCmd(u8x8, 0x081 ); + u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1309 has range from 0 to 255 */ + u8x8_cad_EndTransfer(u8x8); + break; + case U8X8_MSG_DISPLAY_DRAW_TILE: + u8x8_cad_StartTransfer(u8x8); + + x = ((u8x8_tile_t *)arg_ptr)->x_pos; + x *= 8; + x += u8x8->x_offset; + u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) ); + u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15))); + u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); + + c = ((u8x8_tile_t *)arg_ptr)->cnt; + c *= 8; + ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; + + if ( c + x > 115u ) + { + c = 115u; + c -= x; + } + do + { + u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */ + arg_int--; + } while( arg_int > 0 ); + + u8x8_cad_EndTransfer(u8x8); + break; + default: + return 0; + } + return 1; +} \ No newline at end of file