From 6ba90554449cb74b19967a88d4c6e154ca3a752d Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Sat, 4 Dec 2021 01:13:05 +0300 Subject: [PATCH 1/2] first approach to ssd1681 driver support --- src/U8g2lib.h | 90 +++++++++ src/U8x8lib.h | 30 +++ src/clib/u8g2.h | 3 + src/clib/u8g2_d_setup.c | 28 +++ src/clib/u8x8.h | 1 + src/clib/u8x8_d_ssd1681_200x200.c | 297 ++++++++++++++++++++++++++++++ 6 files changed, 449 insertions(+) create mode 100644 src/clib/u8x8_d_ssd1681_200x200.c diff --git a/src/U8g2lib.h b/src/U8g2lib.h index cdbe19bf..23cdad17 100644 --- a/src/U8g2lib.h +++ b/src/U8g2lib.h @@ -19571,6 +19571,96 @@ class U8G2_SSD1607_WS_200X200_F_3W_HW_SPI : public U8G2 { u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); } }; +class U8G2_SSD1681_200X200_1_4W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_1_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_ssd1681_200x200_1(&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_SSD1681_200X200_1_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_1_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_1_2ND_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_1_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_1_3W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_1_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + } +}; +class U8G2_SSD1681_200X200_1_3W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_1_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); + } +}; +class U8G2_SSD1681_200X200_2_4W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_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_ssd1681_200x200_2(&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_SSD1681_200X200_2_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_2_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_2_2ND_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_2_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_2_3W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_2_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + } +}; +class U8G2_SSD1681_200X200_2_3W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_2_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); + } +}; +class U8G2_SSD1681_200X200_F_4W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_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_ssd1681_200x200_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_SSD1681_200X200_F_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_F_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_F_2ND_4W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_F_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8G2_SSD1681_200X200_F_3W_SW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_F_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + } +}; +class U8G2_SSD1681_200X200_F_3W_HW_SPI : public U8G2 { + public: U8G2_SSD1681_200X200_F_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); + } +}; class U8G2_IL3820_296X128_1_4W_SW_SPI : public U8G2 { public: U8G2_IL3820_296X128_1_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_il3820_296x128_1(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); diff --git a/src/U8x8lib.h b/src/U8x8lib.h index 4f57b8c1..0c6e9226 100644 --- a/src/U8x8lib.h +++ b/src/U8x8lib.h @@ -6774,6 +6774,36 @@ class U8X8_SSD1607_WS_200X200_3W_HW_SPI : public U8X8 { u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); } }; +class U8X8_SSD1681_200X200_4W_SW_SPI : public U8X8 { + public: U8X8_SSD1681_200X200_4W_SW_SPI(uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8X8() { + u8x8_Setup(getU8x8(), u8x8_d_ssd1681_200x200, u8x8_cad_011, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_SW_SPI(getU8x8(), clock, data, cs, dc, reset); + } +}; +class U8X8_SSD1681_200X200_4W_HW_SPI : public U8X8 { + public: U8X8_SSD1681_200X200_4W_HW_SPI(uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8X8() { + u8x8_Setup(getU8x8(), u8x8_d_ssd1681_200x200, u8x8_cad_011, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8X8_SSD1681_200X200_2ND_4W_HW_SPI : public U8X8 { + public: U8X8_SSD1681_200X200_2ND_4W_HW_SPI(uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8X8() { + u8x8_Setup(getU8x8(), u8x8_d_ssd1681_200x200, u8x8_cad_011, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); + } +}; +class U8X8_SSD1681_200X200_3W_SW_SPI : public U8X8 { + public: U8X8_SSD1681_200X200_3W_SW_SPI(uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8X8() { + u8x8_Setup(getU8x8(), u8x8_d_ssd1681_200x200, u8x8_cad_011, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + } +}; +class U8X8_SSD1681_200X200_3W_HW_SPI : public U8X8 { + public: U8X8_SSD1681_200X200_3W_HW_SPI(uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8X8() { + u8x8_Setup(getU8x8(), u8x8_d_ssd1681_200x200, u8x8_cad_011, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); + u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); + } +}; class U8X8_IL3820_296X128_4W_SW_SPI : public U8X8 { public: U8X8_IL3820_296X128_4W_SW_SPI(uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8X8() { u8x8_Setup(getU8x8(), u8x8_d_il3820_296x128, u8x8_cad_011, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); diff --git a/src/clib/u8g2.h b/src/clib/u8g2.h index 65727fc6..50d9d4eb 100644 --- a/src/clib/u8g2.h +++ b/src/clib/u8g2.h @@ -1317,6 +1317,9 @@ void u8g2_Setup_ssd1607_ws_200x200_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8 void u8g2_Setup_ssd1607_200x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1607_gd_200x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_ssd1607_ws_200x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); +void u8g2_Setup_ssd1681_200x200_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); +void u8g2_Setup_ssd1681_200x200_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); +void u8g2_Setup_ssd1681_200x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_il3820_296x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_il3820_v2_296x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); void u8g2_Setup_il3820_296x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); diff --git a/src/clib/u8g2_d_setup.c b/src/clib/u8g2_d_setup.c index 902c2b8c..20ea39a8 100644 --- a/src/clib/u8g2_d_setup.c +++ b/src/clib/u8g2_d_setup.c @@ -6247,6 +6247,34 @@ void u8g2_Setup_ssd1607_ws_200x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8 buf = u8g2_m_25_25_f(&tile_buf_height); u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); } +/* ssd1681 */ +/* ssd1681 1 */ +void u8g2_Setup_ssd1681_200x200_1(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_ssd1681_200x200, u8x8_cad_011, byte_cb, gpio_and_delay_cb); + buf = u8g2_m_25_25_1(&tile_buf_height); + u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); +} +/* ssd1681 2 */ +void u8g2_Setup_ssd1681_200x200_2(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_ssd1681_200x200, u8x8_cad_011, byte_cb, gpio_and_delay_cb); + buf = u8g2_m_25_25_2(&tile_buf_height); + u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); +} +/* ssd1681 f */ +void u8g2_Setup_ssd1681_200x200_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_ssd1681_200x200, u8x8_cad_011, byte_cb, gpio_and_delay_cb); + buf = u8g2_m_25_25_f(&tile_buf_height); + u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); +} /* il3820 */ /* il3820 1 */ void u8g2_Setup_il3820_296x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb) diff --git a/src/clib/u8x8.h b/src/clib/u8x8.h index dd2af91a..5e2f463b 100644 --- a/src/clib/u8x8.h +++ b/src/clib/u8x8.h @@ -960,6 +960,7 @@ uint8_t u8x8_d_ssd1607_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void uint8_t u8x8_d_ssd1607_v2_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1607_gd_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_ssd1607_ws_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* issue 637 */ +uint8_t u8x8_d_ssd1681_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_il3820_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_il3820_v2_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8x8_d_lc7981_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); diff --git a/src/clib/u8x8_d_ssd1681_200x200.c b/src/clib/u8x8_d_ssd1681_200x200.c new file mode 100644 index 00000000..8add235a --- /dev/null +++ b/src/clib/u8x8_d_ssd1681_200x200.c @@ -0,0 +1,297 @@ +/* + + u8x8_d_ssd1681_200x200.c + + Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) + + Copyright (c) 2016, olikraus@gmail.com + Copyright (c) 2021, Ivanov Ivan, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + SSD1681: 200x200x1 + + command + 0x22: assign actions + 0x20: execute actions + + action for command 0x022 are (more or less guessed) + bit 7: Enable Clock + bit 6: Enable Charge Pump + bit 5: Load Temparture Value (???) + bit 4: Load LUT (???) + bit 3: Initial Display (???) + bit 2: Pattern Display --> Requires about 945ms with the LUT from below + bit 1: Disable Charge Pump + bit 0: Disable Clock + + Disable Charge Pump and Clock require about 267ms + Enable Charge Pump and Clock require about 10ms + + Notes: + - Introduced a refresh display message, which copies RAM to display + - Charge pump and clock are only enabled for the transfer RAM to display + (copy from ssd1606 file) - U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok. +*/ + + +#include "u8x8.h" + +/*=================================================*/ + +static const u8x8_display_info_t u8x8_ssd1681_200x200_display_info = +{ + /* chip_enable_level = */ 0, + /* chip_disable_level = */ 1, + + /* values from SSD1606 */ + /* post_chip_enable_wait_ns = */ 120, + /* pre_chip_disable_wait_ns = */ 60, + /* reset_pulse_width_ms = */ 100, + /* post_reset_wait_ms = */ 100, + /* sda_setup_time_ns = */ 50, /* SSD1606: */ + /* sck_pulse_width_ns = */ 100, /* SSD1606: 100ns */ + /* 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, + /* tile_width = */ 25, /* 25*8 = 200 */ + /* tile_hight = */ 25, + /* default_x_offset = */ 0, + /* flipmode_x_offset = */ 0, + /* pixel_width = */ 200, + /* pixel_height = */ 200 +}; + + +// GDEH0154D67 +static const uint8_t u8x8_d_ssd1681_D67_200x200_powersave0_seq[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start + U8X8_CA(0x22, 0xc0), // enable clock and charge pump + U8X8_C(0x20), // execute sequence + U8X8_DLY(250), // according to my measures it may take up to 150ms + U8X8_DLY(250), // but it might take longer + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence +}; + +static const uint8_t u8x8_d_ssd1681_D67_200x200_powersave1_seq[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start + // disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content + U8X8_CA(0x22, 0xc3), // only disable charge pump, HW reset seems to be required if the clock is disabled + U8X8_C(0x20), // execute sequence + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence +}; + +static const uint8_t u8x8_d_ssd1681_D67_refresh_seq[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start + + U8X8_CA(0x22, 0xf7), // display update seq. option: clk -> CP -> LUT -> initial display -> pattern display + U8X8_C(0x20), // execute sequence + + U8X8_DLY(250), // delay for 1500ms. The current sequence takes 1300ms + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_DLY(250), + + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence +}; + +static void u8x8_d_ssd1681_D67_200x200_first_init(u8x8_t *u8x8) +{ + + static const uint8_t u8x8_d_ssd1681_D67_load_lut_from_opt[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start + U8X8_CAA(0x1a, 0x19, 0x0 ), + U8X8_DLY(250), + U8X8_DLY(250), + + U8X8_CA(0x22, 0xb1), + U8X8_C(0x20), + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_DLY(250), + U8X8_DLY(250), + + + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence + }; + + u8x8_cad_SendSequence( u8x8 , u8x8_d_ssd1681_D67_load_lut_from_opt); + + u8x8_FillDisplay(u8x8); + u8x8_RefreshDisplay(u8x8); + u8x8_FillDisplay(u8x8); + u8x8_RefreshDisplay(u8x8); + u8x8_ClearDisplay(u8x8); + u8x8_RefreshDisplay(u8x8); + + u8x8_ClearDisplay(u8x8); + u8x8_RefreshDisplay(u8x8); +} + +static uint8_t *u8x8_convert_tile_for_ssd1681(uint8_t *t) +{ + uint8_t i; + static uint8_t buf[8]; + uint8_t *pbuf = buf; + + for (i = 0; i < 8; i++) + { + *pbuf++ = ~(*t++); + } + return buf; +} + +static void u8x8_d_ssd1681_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE; +static void u8x8_d_ssd1681_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) +{ + uint16_t x; + uint8_t c, page; + uint8_t *ptr; + u8x8_cad_StartTransfer(u8x8); + + page = u8x8->display_info->tile_height; + page --; + page -= (((u8x8_tile_t *)arg_ptr)->y_pos); + + x = ((u8x8_tile_t *)arg_ptr)->x_pos; + x *= 8; + x += u8x8->x_offset; + + u8x8_cad_SendCmd(u8x8, 0x045 ); // window start column + u8x8_cad_SendArg(u8x8, x&255); + u8x8_cad_SendArg(u8x8, x>>8); + u8x8_cad_SendArg(u8x8, 199); // end of display + u8x8_cad_SendArg(u8x8, 0); + + u8x8_cad_SendCmd(u8x8, 0x044); // window end page + u8x8_cad_SendArg(u8x8, page); + u8x8_cad_SendArg(u8x8, page); + + u8x8_cad_SendCmd(u8x8, 0x04f); // window column + u8x8_cad_SendArg(u8x8, x&255); + u8x8_cad_SendArg(u8x8, x>>8); + + u8x8_cad_SendCmd(u8x8, 0x04e); // window row + u8x8_cad_SendArg(u8x8, page); + + u8x8_cad_SendCmd(u8x8, 0x024); + + do + { + c = ((u8x8_tile_t *)arg_ptr)->cnt; + ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; + do + { + u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_ssd1681(ptr)); + ptr += 8; + x += 8; + c--; + } while( c > 0 ); + + arg_int--; + } while( arg_int > 0 ); + + u8x8_cad_EndTransfer(u8x8); +} + + +static const uint8_t u8x8_d_ssd1681_D67_200x200_init_seq[] = { + U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */ + + U8X8_DLY(11), + U8X8_C(0x12), + U8X8_DLY(20), + // 3. Send Initialization Code + // Set gate driver output by Command 0x01 + U8X8_C(0x01), /* DRIVER_OUTPUT_CONTROL: LO(EPD_HEIGHT-1), HI(EPD_HEIGHT-1). GD = 0; SM = 0; TB = 0; */ + U8X8_A(199), U8X8_A(0), U8X8_A(0), + + U8X8_CA(0x3c, 0x05), /* select boarder waveform */ + U8X8_CA(0x18, 0x80), + + // _setPartialRamArea; + // Set display RAM size by Command 0x11, 0x44, 0x45 + U8X8_CA(0x11, 0x03), /* DATA_ENTRY_MODE_SETTING: X increment; Y increment */ + U8X8_CAA(0x44, 0, 24), /* SET_RAM_X_ADDRESS_START_END_POSITION: LO(x >> 3), LO((w-1) >> 3) */ + U8X8_CAAAA(0x45, 0, 0, 199&255, 199>>8), /* SET_RAM_Y_ADDRESS_START_END_POSITION: LO(y), HI(y), LO(h - 1), HI(h - 1) */ + + U8X8_CA(0x4e, 0), /* LO(x >> 3) */ + U8X8_CAA(0x4f, 0, 0), /* LO(y), HI(y >> 8) */ + + U8X8_END_TRANSFER(), /* disable chip */ + U8X8_END() /* end of sequence */ + +}; + + +/* GDEH0154D67 200x200 BW only ssd1681 */ +uint8_t u8x8_d_ssd1681_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_DISPLAY_SETUP_MEMORY: + u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1681_200x200_display_info); + break; + case U8X8_MSG_DISPLAY_INIT: + u8x8_d_helper_display_init(u8x8); + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_init_seq); + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave0_seq); + u8x8_d_ssd1681_D67_200x200_first_init(u8x8); + //u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_D67_to_display_seq); + break; + case U8X8_MSG_DISPLAY_SET_POWER_SAVE: + if ( arg_int == 0 ) + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave0_seq); + else + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave1_seq); + break; + case U8X8_MSG_DISPLAY_SET_FLIP_MODE: + break; + case U8X8_MSG_DISPLAY_DRAW_TILE: + u8x8_d_ssd1681_draw_tile(u8x8, arg_int, arg_ptr); + break; + case U8X8_MSG_DISPLAY_REFRESH: + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_refresh_seq); + break; + default: + return 0; + } + return 1; +} + + + From 07736f17f899a721548cd04a2696dd22316d9c58 Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Sun, 16 Jan 2022 21:45:38 +0300 Subject: [PATCH 2/2] ssd1681 and partial update --- src/U8g2lib.h | 48 ++++++++-------- src/U8x8lib.cpp | 58 +++++++++++++++++++- src/U8x8lib.h | 12 ++++ src/clib/u8x8.h | 6 +- src/clib/u8x8_d_ssd1681_200x200.c | 91 ++++++++++++++++++------------- 5 files changed, 151 insertions(+), 64 deletions(-) diff --git a/src/U8g2lib.h b/src/U8g2lib.h index 23cdad17..e1b3ff70 100644 --- a/src/U8g2lib.h +++ b/src/U8g2lib.h @@ -108,7 +108,11 @@ class U8G2 : public Print /* U8X8_MSG_GPIO_MENU_NEXT, U8X8_MSG_GPIO_MENU_PREV, */ /* U8X8_MSG_GPIO_MENU_HOME */ uint8_t getMenuEvent(void) { return u8x8_GetMenuEvent(u8g2_GetU8x8(&u8g2)); } - + + void initPartialDisplay(void) { + u8g2.u8x8.partial_init = 1; + u8g2_InitDisplay(&u8g2); } + void initDisplay(void) { u8g2_InitDisplay(&u8g2); } @@ -19572,91 +19576,91 @@ class U8G2_SSD1607_WS_200X200_F_3W_HW_SPI : public U8G2 { } }; class U8G2_SSD1681_200X200_1_4W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_1_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() { + public: U8G2_SSD1681_200X200_1_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, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); - u8x8_SetPin_4Wire_SW_SPI(getU8x8(), clock, data, cs, dc, reset); + u8x8_SetPin_4Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, dc, reset, busy); } }; class U8G2_SSD1681_200X200_1_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_1_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_1_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_1_2ND_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_1_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_1_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_1_3W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_1_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_1_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); - u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + u8x8_SetPin_3Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, reset, busy); } }; class U8G2_SSD1681_200X200_1_3W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_1_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_1_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_1(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); } }; class U8G2_SSD1681_200X200_2_4W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_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() { + public: U8G2_SSD1681_200X200_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, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); - u8x8_SetPin_4Wire_SW_SPI(getU8x8(), clock, data, cs, dc, reset); + u8x8_SetPin_4Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, dc, reset, busy); } }; class U8G2_SSD1681_200X200_2_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_2_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_2_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_2_2ND_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_2_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_2_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_2_3W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_2_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_2_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); - u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + u8x8_SetPin_3Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, reset, busy); } }; class U8G2_SSD1681_200X200_2_3W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_2_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_2_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_2(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); } }; class U8G2_SSD1681_200X200_F_4W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_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() { + public: U8G2_SSD1681_200X200_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, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_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); + u8x8_SetPin_4Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, dc, reset, busy); } }; class U8G2_SSD1681_200X200_F_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_F_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_F_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_F_2ND_4W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_F_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_F_2ND_4W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_2nd_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_4Wire_HW_SPI(getU8x8(), cs, dc, reset); } }; class U8G2_SSD1681_200X200_F_3W_SW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_F_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_F_3W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_3wire_sw_spi, u8x8_gpio_and_delay_arduino); - u8x8_SetPin_3Wire_SW_SPI(getU8x8(), clock, data, cs, reset); + u8x8_SetPin_3Wire_Busy_SW_SPI(getU8x8(), clock, data, cs, reset, busy); } }; class U8G2_SSD1681_200X200_F_3W_HW_SPI : public U8G2 { - public: U8G2_SSD1681_200X200_F_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE) : U8G2() { + public: U8G2_SSD1681_200X200_F_3W_HW_SPI(const u8g2_cb_t *rotation, uint8_t cs, uint8_t reset = U8X8_PIN_NONE, uint8_t busy = U8X8_PIN_NONE) : U8G2() { u8g2_Setup_ssd1681_200x200_f(&u8g2, rotation, u8x8_byte_arduino_3wire_hw_spi, u8x8_gpio_and_delay_arduino); u8x8_SetPin_3Wire_HW_SPI(getU8x8(), cs, reset); } diff --git a/src/U8x8lib.cpp b/src/U8x8lib.cpp index b6bf1fa6..885d2ca0 100644 --- a/src/U8x8lib.cpp +++ b/src/U8x8lib.cpp @@ -79,7 +79,6 @@ extern "C" uint8_t u8x8_gpio_and_delay_arduino(u8x8_t *u8x8, uint8_t msg, uint8_ switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: - for( i = 0; i < U8X8_PIN_CNT; i++ ) if ( u8x8->pins[i] != U8X8_PIN_NONE ) { @@ -117,7 +116,35 @@ extern "C" uint8_t u8x8_gpio_and_delay_arduino(u8x8_t *u8x8, uint8_t msg, uint8_ break; case U8X8_MSG_DELAY_MILLI: - delay(arg_int); + if (u8x8->pins[U8X8_PIN_BUSY] != U8X8_PIN_NONE) { + uint16_t _busy_level = 1; + delay(3); // add some margin to become active + unsigned long start = micros(); + unsigned long delay_time = arg_int; + delay_time *= 1000; + while (1) + { + uint16_t level = digitalRead( u8x8->pins[U8X8_PIN_BUSY]); + + if ( level != _busy_level) break; + delay(1); + if (micros() - start > delay_time ) + { + // Serial.println("Busy Timeout!"); + break; + } + } +/* + unsigned long elapsed = micros() - start; + Serial.print("delay -- "); + Serial.print(delay_time); + Serial.print(", elapsed : "); + Serial.println(elapsed); +*/ + } + else + delay(arg_int); + break; case U8X8_MSG_DELAY_I2C: /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */ @@ -1652,6 +1679,17 @@ extern "C" uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t a use U8X8_PIN_NONE as value for "reset", if there is no reset line */ +void u8x8_SetPin_4Wire_Busy_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t busy) +{ + u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock); + u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data); + u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); + u8x8_SetPin(u8x8, U8X8_PIN_DC, dc); + u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, busy); +} + + void u8x8_SetPin_4Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset) { u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock); @@ -1672,6 +1710,7 @@ void u8x8_Setup_4Wire_SW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_DC, dc); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } #endif /* obsolete com specific setup */ @@ -1681,8 +1720,19 @@ void u8x8_SetPin_3Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data); u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } +void u8x8_SetPin_3Wire_Busy_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset, uint8_t busy) +{ + u8x8_SetPin(u8x8, U8X8_PIN_SPI_CLOCK, clock); + u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data); + u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); + u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, busy); +} + + #ifdef _obsolete_com_specific_setup void u8x8_Setup_3Wire_SW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset) { @@ -1693,6 +1743,7 @@ void u8x8_Setup_3Wire_SW_SPI(u8x8_t *u8x8, u8x8_msg_cb display_cb, uint8_t clock u8x8_SetPin(u8x8, U8X8_PIN_SPI_DATA, data); u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } #endif /* obsolete com specific setup */ @@ -1703,6 +1754,7 @@ void u8x8_SetPin_3Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset) { u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } /* @@ -1713,12 +1765,14 @@ void u8x8_SetPin_4Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t dc, uint8_t rese u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_DC, dc); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } void u8x8_SetPin_ST7920_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset) { u8x8_SetPin(u8x8, U8X8_PIN_CS, cs); u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_BUSY, U8X8_PIN_NONE); } diff --git a/src/U8x8lib.h b/src/U8x8lib.h index 0c6e9226..29362d2e 100644 --- a/src/U8x8lib.h +++ b/src/U8x8lib.h @@ -146,8 +146,10 @@ extern "C" uint8_t u8x8_byte_arduino_2nd_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8 extern "C" uint8_t u8x8_byte_arduino_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); #ifdef U8X8_USE_PINS +void u8x8_SetPin_4Wire_Busy_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t busy); void u8x8_SetPin_4Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset); void u8x8_SetPin_3Wire_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset); +void u8x8_SetPin_3Wire_Busy_SW_SPI(u8x8_t *u8x8, uint8_t clock, uint8_t data, uint8_t cs, uint8_t reset, uint8_t busy); void u8x8_SetPin_3Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset); void u8x8_SetPin_4Wire_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t dc, uint8_t reset); void u8x8_SetPin_ST7920_HW_SPI(u8x8_t *u8x8, uint8_t cs, uint8_t reset); @@ -215,6 +217,11 @@ class U8X8 : public Print void initDisplay(void) { u8x8_InitDisplay(&u8x8); } + + void initDisplay(bool partial_init) { // to eink, we should call init anyway but with different arguments + u8x8.partial_init = partial_init ? 1 : 0; + u8x8_InitDisplay(&u8x8); } + /* call initInterface if the uC comes out of deep sleep mode and display is already running */ /* initInterface is part if initDisplay, do not call both use either initDisplay OR initInterface */ void initInterface(void) { @@ -232,6 +239,11 @@ class U8X8 : public Print bool begin(void) { initDisplay(); clearDisplay(); setPowerSave(0); return 1; } + + bool begin(bool partial_init) { // eink implementation + initDisplay(partial_init); clearDisplay(); setPowerSave(0); return 1; } + + #ifdef U8X8_USE_PINS /* use U8X8_PIN_NONE if a pin is not required */ bool begin(uint8_t menu_select_pin, uint8_t menu_next_pin, uint8_t menu_prev_pin, uint8_t menu_up_pin = U8X8_PIN_NONE, uint8_t menu_down_pin = U8X8_PIN_NONE, uint8_t menu_home_pin = U8X8_PIN_NONE) { diff --git a/src/clib/u8x8.h b/src/clib/u8x8.h index 5e2f463b..8fb72853 100644 --- a/src/clib/u8x8.h +++ b/src/clib/u8x8.h @@ -302,11 +302,13 @@ struct u8x8_display_info_struct #define U8X8_PIN_D6 6 #define U8X8_PIN_D7 7 + #define U8X8_PIN_E 8 #define U8X8_PIN_CS 9 /* parallel, SPI */ #define U8X8_PIN_DC 10 /* parallel, SPI */ #define U8X8_PIN_RESET 11 /* parallel, SPI, I2C */ + #define U8X8_PIN_I2C_CLOCK 12 /* 1 = Input/high impedance, 0 = drive low */ #define U8X8_PIN_I2C_DATA 13 /* 1 = Input/high impedance, 0 = drive low */ @@ -321,8 +323,9 @@ struct u8x8_display_info_struct #define U8X8_PIN_MENU_HOME 19 #define U8X8_PIN_MENU_UP 20 #define U8X8_PIN_MENU_DOWN 21 +#define U8X8_PIN_BUSY 22 /* parallel, SPI, for E-INK */ -#define U8X8_PIN_INPUT_CNT 6 +#define U8X8_PIN_INPUT_CNT 7 #ifdef U8X8_USE_PINS #define U8X8_PIN_CNT (U8X8_PIN_OUTPUT_CNT+U8X8_PIN_INPUT_CNT) @@ -359,6 +362,7 @@ struct u8x8_struct #ifdef U8X8_USE_PINS uint8_t pins[U8X8_PIN_CNT]; /* defines a pinlist: Mainly a list of pins for the Arduino Envionment, use U8X8_PIN_xxx to access */ #endif + uint8_t partial_init; // eink }; #ifdef U8X8_WITH_USER_PTR diff --git a/src/clib/u8x8_d_ssd1681_200x200.c b/src/clib/u8x8_d_ssd1681_200x200.c index 8add235a..cf4804ec 100644 --- a/src/clib/u8x8_d_ssd1681_200x200.c +++ b/src/clib/u8x8_d_ssd1681_200x200.c @@ -94,19 +94,28 @@ static const uint8_t u8x8_d_ssd1681_D67_200x200_powersave0_seq[] = { U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start U8X8_CA(0x22, 0xc0), // enable clock and charge pump U8X8_C(0x20), // execute sequence - U8X8_DLY(250), // according to my measures it may take up to 150ms - U8X8_DLY(250), // but it might take longer + U8X8_DLY(238), // according to my measures it may take up to 150ms + U8X8_DLY(237), // but it might take longer U8X8_END_TRANSFER(), // disable chip U8X8_END() // end of sequence }; + +static const uint8_t u8x8_d_ssd1681_D67_200x200_powersaveDeepSleep_seq[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start + U8X8_CA(0x10, 0x01), + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence +}; + + static const uint8_t u8x8_d_ssd1681_D67_200x200_powersave1_seq[] = { U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start // disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content U8X8_CA(0x22, 0xc3), // only disable charge pump, HW reset seems to be required if the clock is disabled U8X8_C(0x20), // execute sequence - U8X8_DLY(250), - U8X8_DLY(250), + U8X8_DLY(240), + U8X8_DLY(239), U8X8_END_TRANSFER(), // disable chip U8X8_END() // end of sequence }; @@ -117,49 +126,44 @@ static const uint8_t u8x8_d_ssd1681_D67_refresh_seq[] = { U8X8_CA(0x22, 0xf7), // display update seq. option: clk -> CP -> LUT -> initial display -> pattern display U8X8_C(0x20), // execute sequence - U8X8_DLY(250), // delay for 1500ms. The current sequence takes 1300ms - U8X8_DLY(250), - U8X8_DLY(250), - U8X8_DLY(250), - U8X8_DLY(250), - U8X8_DLY(250), + U8X8_DLY(246), // delay for 1500ms. The current sequence takes 1300ms + U8X8_DLY(245), + U8X8_DLY(244), + U8X8_DLY(243), + U8X8_DLY(242), + U8X8_DLY(241), U8X8_END_TRANSFER(), // disable chip U8X8_END() // end of sequence }; -static void u8x8_d_ssd1681_D67_200x200_first_init(u8x8_t *u8x8) -{ - static const uint8_t u8x8_d_ssd1681_D67_load_lut_from_opt[] = { - U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start - U8X8_CAA(0x1a, 0x19, 0x0 ), - U8X8_DLY(250), - U8X8_DLY(250), +static const uint8_t u8x8_d_ssd1681_D67_part_refresh_seq[] = { + U8X8_START_TRANSFER(), // enable chip, delay is part of the transfer start - U8X8_CA(0x22, 0xb1), - U8X8_C(0x20), - U8X8_DLY(250), - U8X8_DLY(250), - U8X8_DLY(250), - U8X8_DLY(250), + U8X8_CA(0x22, 0xff), + U8X8_C(0x20), // execute sequence + U8X8_DLY(246), // delay + U8X8_DLY(245), + U8X8_DLY(244), + U8X8_DLY(243), + U8X8_DLY(242), + U8X8_DLY(241), - U8X8_END_TRANSFER(), // disable chip - U8X8_END() // end of sequence - }; + U8X8_END_TRANSFER(), // disable chip + U8X8_END() // end of sequence +}; - u8x8_cad_SendSequence( u8x8 , u8x8_d_ssd1681_D67_load_lut_from_opt); +static void u8x8_d_ssd1681_D67_200x200_first_init(u8x8_t *u8x8) +{ +/* u8x8_FillDisplay(u8x8); u8x8_RefreshDisplay(u8x8); - u8x8_FillDisplay(u8x8); - u8x8_RefreshDisplay(u8x8); - u8x8_ClearDisplay(u8x8); - u8x8_RefreshDisplay(u8x8); - u8x8_ClearDisplay(u8x8); u8x8_RefreshDisplay(u8x8); +*/ } static uint8_t *u8x8_convert_tile_for_ssd1681(uint8_t *t) @@ -229,6 +233,8 @@ static void u8x8_d_ssd1681_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_pt } + + static const uint8_t u8x8_d_ssd1681_D67_200x200_init_seq[] = { U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */ @@ -240,8 +246,8 @@ static const uint8_t u8x8_d_ssd1681_D67_200x200_init_seq[] = { U8X8_C(0x01), /* DRIVER_OUTPUT_CONTROL: LO(EPD_HEIGHT-1), HI(EPD_HEIGHT-1). GD = 0; SM = 0; TB = 0; */ U8X8_A(199), U8X8_A(0), U8X8_A(0), - U8X8_CA(0x3c, 0x05), /* select boarder waveform */ - U8X8_CA(0x18, 0x80), + U8X8_CA(0x3c, 0x05), // select boarder waveform + U8X8_CA(0x18, 0x80), // internal termo // _setPartialRamArea; // Set display RAM size by Command 0x11, 0x44, 0x45 @@ -270,23 +276,30 @@ uint8_t u8x8_d_ssd1681_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void u8x8_d_helper_display_init(u8x8); u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_init_seq); u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave0_seq); - u8x8_d_ssd1681_D67_200x200_first_init(u8x8); - //u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_D67_to_display_seq); + // u8x8_d_ssd1681_D67_200x200_first_init(u8x8); break; case U8X8_MSG_DISPLAY_SET_POWER_SAVE: if ( arg_int == 0 ) u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave0_seq); else - u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersave1_seq); + u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_200x200_powersaveDeepSleep_seq);//u8x8_d_ssd1681_D67_200x200_powersave1_seq); break; case U8X8_MSG_DISPLAY_SET_FLIP_MODE: break; case U8X8_MSG_DISPLAY_DRAW_TILE: u8x8_d_ssd1681_draw_tile(u8x8, arg_int, arg_ptr); break; - case U8X8_MSG_DISPLAY_REFRESH: - u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1681_D67_refresh_seq); + case U8X8_MSG_DISPLAY_REFRESH:{ + const uint8_t *refresh_seq = u8x8_d_ssd1681_D67_refresh_seq; +/* + if ( u8x8->partial_init ) { + refresh_seq = u8x8_d_ssd1681_D67_part_refresh_seq; + } +*/ + u8x8_cad_SendSequence(u8x8, refresh_seq); + break; + } default: return 0; }