From 84366f168c6570a0e778d5638b2f3f8c8ae6b04b Mon Sep 17 00:00:00 2001 From: Wouter van Ooijen Date: Thu, 3 Sep 2020 22:45:21 +0200 Subject: [PATCH] update --- .gitignore | 2 +- .../due-#0050-uart-hello/_cpp_flags | 2 +- .../due-#0050-uart-hello/_linker_flags | 2 +- demo/arduino-due/due-#0500-st7789/main.cpp | 29 + demo/arduino-due/due-#0500-st7789/makefile | 25 + library/hwlib-all.hpp | 1 + library/peripherals/hwlib-glcd-st7789.hpp | 668 ++++-------------- makefile.inc | 1 + 8 files changed, 187 insertions(+), 543 deletions(-) create mode 100644 demo/arduino-due/due-#0500-st7789/main.cpp create mode 100644 demo/arduino-due/due-#0500-st7789/makefile diff --git a/.gitignore b/.gitignore index d7429ee..16facb2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ __codelite.workspace __codelite.session __codelite.tags _cpp_flags -_link_flags +_linker_flags refactoring.db ~$*.docx .project diff --git a/demo/arduino-due/due-#0050-uart-hello/_cpp_flags b/demo/arduino-due/due-#0050-uart-hello/_cpp_flags index b5cc793..f70f42e 100644 --- a/demo/arduino-due/due-#0050-uart-hello/_cpp_flags +++ b/demo/arduino-due/due-#0050-uart-hello/_cpp_flags @@ -1 +1 @@ --mcpu=cortex-m3 -mthumb -fomit-frame-pointer -march=armv7-m -Wall -Werror -Wno-maybe-uninitialized -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-unused-local-typedefs -Wno-unused-function -Wno-attributes -Os -fdata-sections -ffunction-sections -I../../../../bmptk/targets/cortex/atmel -I../../../../bmptk/targets/cortex/atmel/sam3xa/include -I../../../library -I../../../../Catch2/single_include -I../../../../Catch2/single_include/catch2 -I../../../../boost_1_69_0 -I../../../../bmptk -I../../../../bmptk/targets -I../../../../bmptk/targets/cortex -I../../../../bmptk/targets/cortex/cmsis -DHWCPP_FAKE_OSTREAM -DDONT_USE_CMSIS_INIT -DBMPTK_INCLUDE_CHIP=sam.h -D__SAM3X8E__ -DBMPTK_TARGET=arduino_due -DBMPTK_TARGET_arduino_due -DHWLIB_TARGET_arduino_due -DHWCPP_TARGET_arduino_due -DGF_TARGET_arduino_due -DBMPTK_CHIP=sam3x8e -DBMPTK_CHIP_sam3x8e -DBMPTK_XTAL=12000 -DBMPTK_BAUDRATE=2400 -DHWLIB_BAUDRATE=2400 -DGODAFOSS_BAUDRATE=2400 -DGF_BAUDRATE=2400 -DBMPTK_VERSION=V04_00_work_in_progress_2020_05_23 -DBMPTK_EMBEDDED -std=c++17 -fconcepts -fno-rtti -fno-exceptions -fno-asynchronous-unwind-tables -fno-threadsafe-statics -fno-use-cxa-get-exception-ptr -fno-use-cxa-atexit -nostdlib -nodefaultlibs + -mcpu=cortex-m3 -mthumb -fomit-frame-pointer -march=armv7-m -Wall -Werror -Wno-maybe-uninitialized -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-unused-local-typedefs -Wno-unused-function -Wno-attributes -Os -fdata-sections -ffunction-sections -IC:\Python36\include -I../../../../bmptk/targets/cortex/atmel -I../../../../bmptk/targets/cortex/atmel/sam3xa/include -I../../../library -I../../../../Catch2/single_include -I../../../../Catch2/single_include/catch2 -I../../../../boost_1_69_0 -I../../../../bmptk -I../../../../bmptk/targets -I../../../../bmptk/targets/cortex -I../../../../bmptk/targets/cortex/cmsis -DHWCPP_FAKE_OSTREAM -DDONT_USE_CMSIS_INIT -DBMPTK_INCLUDE_CHIP=sam.h -D__SAM3X8E__ -DBMPTK_TARGET=arduino_due -DBMPTK_TARGET_arduino_due -DHWLIB_TARGET_arduino_due -DHWCPP_TARGET_arduino_due -DGF_TARGET_arduino_due -DBMPTK_CHIP=sam3x8e -DBMPTK_CHIP_sam3x8e -DBMPTK_XTAL=12000 -DBMPTK_BAUDRATE=2400 -DHWLIB_BAUDRATE=2400 -DGODAFOSS_BAUDRATE=2400 -DGF_BAUDRATE=2400 -DBMPTK_VERSION=V04_00_work_in_progress_2020_05_23 -DBMPTK_EMBEDDED -std=c++17 -fconcepts -fno-rtti -fno-exceptions -fno-asynchronous-unwind-tables -fno-threadsafe-statics -fno-use-cxa-get-exception-ptr -fno-use-cxa-atexit -nostdlib -nodefaultlibs diff --git a/demo/arduino-due/due-#0050-uart-hello/_linker_flags b/demo/arduino-due/due-#0050-uart-hello/_linker_flags index 029aadd..3fa8ca0 100644 --- a/demo/arduino-due/due-#0050-uart-hello/_linker_flags +++ b/demo/arduino-due/due-#0050-uart-hello/_linker_flags @@ -1 +1 @@ --mcpu=cortex-m3 -mthumb -fomit-frame-pointer -march=armv7-m -Wall -Werror -Wno-maybe-uninitialized -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-unused-local-typedefs -Wno-unused-function -Wno-attributes -Os -fdata-sections -ffunction-sections -I../../../../bmptk/targets/cortex/atmel -I../../../../bmptk/targets/cortex/atmel/sam3xa/include -I../../../library -I../../../../Catch2/single_include -I../../../../Catch2/single_include/catch2 -I../../../../boost_1_69_0 -I../../../../bmptk -I../../../../bmptk/targets -I../../../../bmptk/targets/cortex -I../../../../bmptk/targets/cortex/cmsis -DHWCPP_FAKE_OSTREAM -DDONT_USE_CMSIS_INIT -DBMPTK_INCLUDE_CHIP=sam.h -D__SAM3X8E__ -DBMPTK_TARGET=arduino_due -DBMPTK_TARGET_arduino_due -DHWLIB_TARGET_arduino_due -DHWCPP_TARGET_arduino_due -DGF_TARGET_arduino_due -DBMPTK_CHIP=sam3x8e -DBMPTK_CHIP_sam3x8e -DBMPTK_XTAL=12000 -DBMPTK_BAUDRATE=2400 -DHWLIB_BAUDRATE=2400 -DGODAFOSS_BAUDRATE=2400 -DGF_BAUDRATE=2400 -DBMPTK_VERSION=V04_00_work_in_progress_2020_05_23 -DBMPTK_EMBEDDED -lgcc -Wl,-Map,main.map -Wl,--gc-sections -Wl,-fatal-warnings + -mcpu=cortex-m3 -mthumb -fomit-frame-pointer -march=armv7-m -Wall -Werror -Wno-maybe-uninitialized -Wno-unused-local-typedefs -Wno-unused-but-set-variable -Wno-unused-local-typedefs -Wno-unused-function -Wno-attributes -Os -fdata-sections -ffunction-sections -IC:\Python36\include -I../../../../bmptk/targets/cortex/atmel -I../../../../bmptk/targets/cortex/atmel/sam3xa/include -I../../../library -I../../../../Catch2/single_include -I../../../../Catch2/single_include/catch2 -I../../../../boost_1_69_0 -I../../../../bmptk -I../../../../bmptk/targets -I../../../../bmptk/targets/cortex -I../../../../bmptk/targets/cortex/cmsis -DHWCPP_FAKE_OSTREAM -DDONT_USE_CMSIS_INIT -DBMPTK_INCLUDE_CHIP=sam.h -D__SAM3X8E__ -DBMPTK_TARGET=arduino_due -DBMPTK_TARGET_arduino_due -DHWLIB_TARGET_arduino_due -DHWCPP_TARGET_arduino_due -DGF_TARGET_arduino_due -DBMPTK_CHIP=sam3x8e -DBMPTK_CHIP_sam3x8e -DBMPTK_XTAL=12000 -DBMPTK_BAUDRATE=2400 -DHWLIB_BAUDRATE=2400 -DGODAFOSS_BAUDRATE=2400 -DGF_BAUDRATE=2400 -DBMPTK_VERSION=V04_00_work_in_progress_2020_05_23 -DBMPTK_EMBEDDED -lgcc -Wl,-Map,main.map -Wl,--gc-sections -Wl,-fatal-warnings diff --git a/demo/arduino-due/due-#0500-st7789/main.cpp b/demo/arduino-due/due-#0500-st7789/main.cpp new file mode 100644 index 0000000..87b37e5 --- /dev/null +++ b/demo/arduino-due/due-#0500-st7789/main.cpp @@ -0,0 +1,29 @@ +#include "hwlib.hpp" + +namespace target = hwlib::target; + +int main( void ){ + + // wait for the terminal emulator to start up + hwlib::wait_ms( 2'000 ); + hwlib::cout << "ST7789 demo\n" << hwlib::flush; + + auto sclk = hwlib::target::pin_out{ hwlib::target::pins::d2 }; + auto mosi = hwlib::target::pin_out{ hwlib::target::pins::d3 };; + + auto spi = hwlib::spi_bus_bit_banged_sclk_mosi_miso{ + sclk, mosi, hwlib::pin_in_dummy }; + + auto dc = hwlib::target::pin_out{ hwlib::target::pins::d4 }; + auto & cs = hwlib::pin_out_dummy; + auto rst = hwlib::target::pin_out{ hwlib::target::pins::d5 }; + + auto display = hwlib::st7789_spi_dc_cs_rst( spi, dc, cs, rst ); + + for(;;){ + hwlib::cout << __LINE__ << "\n"; + display.flush(); + hwlib::wait_ms( 1'000 ); + } + +} diff --git a/demo/arduino-due/due-#0500-st7789/makefile b/demo/arduino-due/due-#0500-st7789/makefile new file mode 100644 index 0000000..b5e55d1 --- /dev/null +++ b/demo/arduino-due/due-#0500-st7789/makefile @@ -0,0 +1,25 @@ +#============================================================================ +# +# simple project makefile (just a main file) +# +# (c) Wouter van Ooijen (wouter@voti.nl) 2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +#============================================================================ + +# source files in this project (main.* is automatically assumed) +SOURCES := + +# header files in this project +HEADERS := + +# other places to look for files for this project +SEARCH := + +# set RELATIVE to the next higher directory +# and defer to the appropriate Makefile.* there +RELATIVE := .. +include $(RELATIVE)/makefile.link \ No newline at end of file diff --git a/library/hwlib-all.hpp b/library/hwlib-all.hpp index bcfbd35..da3603b 100644 --- a/library/hwlib-all.hpp +++ b/library/hwlib-all.hpp @@ -95,6 +95,7 @@ #include HWLIB_INCLUDE( peripherals/hwlib-hd44780.hpp ) #include HWLIB_INCLUDE( peripherals/hwlib-glcd-5510.hpp ) #include HWLIB_INCLUDE( peripherals/hwlib-glcd-oled.hpp ) +#include HWLIB_INCLUDE( peripherals/hwlib-glcd-st7789.hpp ) #include HWLIB_INCLUDE( peripherals/hwlib-matrix-keypad.hpp ) #include HWLIB_INCLUDE( peripherals/hwlib-servo-background.hpp ) diff --git a/library/peripherals/hwlib-glcd-st7789.hpp b/library/peripherals/hwlib-glcd-st7789.hpp index 85b9959..8fa230c 100644 --- a/library/peripherals/hwlib-glcd-st7789.hpp +++ b/library/peripherals/hwlib-glcd-st7789.hpp @@ -40,568 +40,156 @@ namespace hwlib { /// and available from lots of sources. /// /// \image html oled.jpg -// - -#define ST77XX_NOP 0x00 -#define ST77XX_SWRESET 0x01 -#define ST77XX_RDDID 0x04 -#define ST77XX_RDDST 0x09 - -#define ST77XX_SLPIN 0x10 -#define ST77XX_SLPOUT 0x11 -#define ST77XX_PTLON 0x12 -#define ST77XX_NORON 0x13 - -#define ST77XX_INVOFF 0x20 -#define ST77XX_INVON 0x21 -#define ST77XX_DISPOFF 0x28 -#define ST77XX_DISPON 0x29 -#define ST77XX_CASET 0x2A -#define ST77XX_RASET 0x2B -#define ST77XX_RAMWR 0x2C -#define ST77XX_RAMRD 0x2E - -#define ST77XX_PTLAR 0x30 -#define ST77XX_TEOFF 0x34 -#define ST77XX_TEON 0x35 -#define ST77XX_MADCTL 0x36 -#define ST77XX_COLMOD 0x3A - -#define ST77XX_MADCTL_MY 0x80 -#define ST77XX_MADCTL_MX 0x40 -#define ST77XX_MADCTL_MV 0x20 -#define ST77XX_MADCTL_ML 0x10 -#define ST77XX_MADCTL_RGB 0x00 - -#define ST77XX_RDID1 0xDA -#define ST77XX_RDID2 0xDB -#define ST77XX_RDID3 0xDC -#define ST77XX_RDID4 0xDD - -/// SSD1306 chip commands -enum class st77xx_commands : uint8_t { - NOP = 0x00, - SWRESET = 0x01, - RDDID = 0x04, - RDDST = 0x09, - - SLPIN = 0x10, - SLPOUT = 0x11, - PTLON = 0x12, - NORON = 0x13, - - INVOFF = 0x20, - INVON = 0x21, - DISPOFF = 0x28, - DISPON = 0x29, - CASET = 0x2A, - RASET = 0x2B, - RAMWR = 0x2C, - RAMRD = 0x2E, - - PTLAR = 0x30, - TEOFF = 0x34, - TEON = 0x35, - MADCTL = 0x36, - COLMOD = 0x3A -}; - -/// value to send over i2c before a command -constexpr uint8_t ssd1306_cmd_prefix = 0x80; - -/// value to send over i2c before a command -constexpr uint8_t ssd1306_data_prefix = 0x40; +/// -/// SSD1306 chip initialization -constexpr const uint8_t ssd1306_initialization[] = { - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::display_off, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_display_clock_div, 0x80, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_multiplex, 0x3f, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_display_offset, 0x00, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_start_line | 0x00, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::charge_pump, 0x14, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::memory_mode, 0x00, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::seg_remap | 0x01, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::com_scan_dec, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_compins, 0x12, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_contrast, 0xcf, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_precharge, 0xf1, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::set_vcom_detect, 0x40, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::display_all_on_resume, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::normal_display, - ssd1306_cmd_prefix, (uint8_t) ssd1306_commands::display_on +class st7789 { +public: + enum class commands : uint8_t { + NOP = 0x00, + SWRESET = 0x01, + RDDID = 0x04, + RDDST = 0x09, + RDDPM = 0x0A, + RDDMADCTL = 0x0B, + RDDIM = 0x0D, + RDDSEM = 0x0E, + RDDSDR = 0x0F, + + SLPIN = 0x10, + SLPOUT = 0x11, + PTLON = 0x12, + NORON = 0x13, + + INVOFF = 0x20, + INVON = 0x21, + GAMSET = 0x26, + DISPOFF = 0x28, + DISPON = 0x29, + CASET = 0x2A, + RASET = 0x2B, + RAMWR = 0x2C, + RAMRD = 0x2E, + + PTLAR = 0x30, + VSCRDEF = 0x30, + TEOFF = 0x34, + TEON = 0x35, + MADCTL = 0x36, + COLMOD = 0x3A + }; }; +class st7789_spi_dc_cs_rst : public st7789, window { +private: -// ========================================================================== -// -// ssd1306, accessed by i2c -// -// ========================================================================== - -class ssd1306_i2c { -protected: - - /// the i2c channel - i2c_bus & bus; - uint_fast8_t address; + static auto constexpr wsize = xy( 240, 240 ); - /// current cursor location in the controller - xy cursor; - -public: - - /// construct by providing the i2c channel - ssd1306_i2c( i2c_bus & bus, uint_fast8_t address = 0x3C ): - bus( bus ), - address( address ), - cursor( 255, 255 ) - { - // wait for the controller to be ready for the initialization - wait_ms( 20 ); + uint8_t buffer[ wsize.x * wsize.y ]; + + void write_implementation( + xy pos, + color col + ) override { + buffer[ pos.x + wsize.x * pos.y ] = + ( ( col.red & 0xC0 ) >> 2 ) + + ( ( col.green & 0xC0 ) >> 4 ) + + ( ( col.blue & 0xC0 ) >> 6 ); } - - /// send a command without data - void command( ssd1306_commands c ){ - uint8_t data[] = { - ssd1306_cmd_prefix, (uint8_t) c - }; - bus.write( address ).write( - data, - sizeof( data ) / sizeof( uint8_t ) - ); - } - - /// send a command with one data byte - void command( ssd1306_commands c, uint8_t d0 ){ - uint8_t data[] = { - ssd1306_cmd_prefix, (uint8_t) c, - ssd1306_cmd_prefix, d0 - }; - bus.write( address ).write( - data, - sizeof( data ) / sizeof( uint8_t ) - ); - } - - /// send a command with two data bytes - void command( ssd1306_commands c , uint8_t d0, uint8_t d1 ){ - uint8_t data[] = { - ssd1306_cmd_prefix, (uint8_t) c, - ssd1306_cmd_prefix, d0, - ssd1306_cmd_prefix, d1 - }; - bus.write( address ).write( - data, - sizeof( data ) / sizeof( uint8_t ) - ); - } - - /// write the pixel byte d at column x page y - void pixels_byte_write( - xy location, - uint8_t d - ){ - - if( location != cursor ){ - command( ssd1306_commands::column_addr, location.x, 127 ); - command( ssd1306_commands::page_addr, location.y, 7 ); - cursor = location; - } - uint8_t data[] = { ssd1306_data_prefix, d }; - bus.write( address ).write( - data, - sizeof( data ) / sizeof( uint8_t ) - ); - cursor.x++; - - } - -}; // class ssd1306_i2c - - -// ========================================================================== -// -// ssd1306, accessed by spi -// -// ========================================================================== - -class ssd1306_spi_res_dc_cs { -protected: - - // the spi bus & pins spi_bus & bus; - pin_out & res; pin_out & dc; pin_out & cs; + pin_out & rst; - // current cursor location in the controller - xy cursor; - -public: - - /// construct by providing the spi bus and the res, dc and cs pins - ssd1306_spi_res_dc_cs( spi_bus & bus, pin_out & res, pin_out & dc, pin_out & cs ): - bus( bus ), - res( res ), - dc( dc ), - cs( cs ), - cursor( 255, 255 ) - { - res.write( 0 ); - wait_ms( 1 ); - res.write( 1 ); - - // wait for the controller to be ready for the initialization - wait_ms( 20 ); - } - - /// send a command without data - void command( ssd1306_commands c ){ - dc.write( 0 ); - auto t = bus.transaction( cs ); - t.write( static_cast< uint8_t >( c ) ); +public: + + void command( + commands c + ){ + dc.write( 0 ); dc.flush(); + auto transaction = bus.transaction( cs ); + transaction.write( static_cast< uint8_t >( c ) ); + dc.write( 1 ); dc.flush(); + } + + void command( + commands c, + uint8_t d0 + ){ + dc.write( 0 ); dc.flush(); + auto transaction = bus.transaction( cs ); + transaction.write( static_cast< uint8_t >( c ) ); + dc.write( 1 ); dc.flush(); + transaction.write( d0 ); } - /// send a command with one data byte - void command( ssd1306_commands c, uint8_t d0 ){ - dc.write( 0 ); - auto t = bus.transaction( cs ); - t.write( static_cast< uint8_t >( c ) ); - t.write( d0 ); - } - - /// send a command with two data bytes - void command( ssd1306_commands c , uint8_t d0, uint8_t d1 ){ - dc.write( 0 ); - auto t = bus.transaction( cs ); - t.write( static_cast< uint8_t >( c ) ); - t.write( d0 ); - t.write( d1 ); + void command( + commands c, + uint8_t d0, + uint8_t d1, + uint8_t d2, + uint8_t d3 + ){ + dc.write( 0 ); dc.flush(); + auto transaction = bus.transaction( cs ); + transaction.write( static_cast< uint8_t >( c ) ); + dc.write( 1 ); dc.flush(); + transaction.write( d0 ); + transaction.write( d1 ); + transaction.write( d2 ); + transaction.write( d3 ); } - /// write the pixel byte d at column x page y - void pixels_byte_write( - xy location, - uint8_t d - ){ - - if( location != cursor ){ - command( ssd1306_commands::column_addr, location.x, 127 ); - command( ssd1306_commands::page_addr, location.y, 7 ); - cursor = location; - } - - dc.write( 1 ); - auto t = bus.transaction( cs ); - t.write( d ); - cursor.x++; - - } + st7789_spi_dc_cs_rst( + spi_bus & bus, + pin_out & dc, + pin_out & cs, + pin_out & rst + ): + window( wsize, white, black ), + bus( bus ), + dc( dc ), + cs( cs ), + rst( rst ) + { + rst.write( 0 );rst.flush(); + wait_ms( 200 ); + rst.write( 1 );rst.flush(); + wait_ms( 200 ); -}; // class ssd1306_spi - - -// ========================================================================== -// -// direct i2c -// -// ========================================================================== - -/// buffered oled window -class glcd_oled_i2c_128x64_direct : public ssd1306_i2c, public window { -private: - - static auto constexpr wsize = xy( 128, 64 ); - - uint8_t buffer[ wsize.x * wsize.y / 8 ]; + command( commands::SWRESET ); + wait_ms( 150 ); - void write_implementation( - xy pos, - color col - ) override { - - int a = pos.x + ( pos.y / 8 ) * size.x; - - if( col == white ){ - buffer[ a ] |= ( 0x01 << ( pos.y % 8 )); - } else { - buffer[ a ] &= ~( 0x01 << ( pos.y % 8 )); - } - - pixels_byte_write( xy( pos.x, pos.y / 8 ), buffer[ a ] ); - - } - - void clear_implementation( color c ) override { - const uint8_t d = ( c == white ) ? 0xFF : 0x00; - command( ssd1306_commands::column_addr, 0, 127 ); - command( ssd1306_commands::page_addr, 0, 7 ); - auto t = bus.write( address ); - t.write( ssd1306_data_prefix ); - for( uint_fast16_t x = 0; x < sizeof( buffer ); ++x ){ - buffer[ x ] = d; - t.write( d ); - } - cursor = xy( 255, 255 ); - } - -public: - - /// construct by providing the i2c channel - glcd_oled_i2c_128x64_direct( i2c_bus & bus, uint_fast8_t address = 0x3C ): - ssd1306_i2c( bus, address ), - window( wsize, white, black ) - { - bus.write( address ).write( - ssd1306_initialization, - sizeof( ssd1306_initialization ) / sizeof( uint8_t ) - ); - } - - void flush() override {} - -}; // class glcd_oled_i2c_128x64_direct - - -// ========================================================================== -// -// direct spi -// -// ========================================================================== - -/// buffered oled window -class glcd_oled_spi_128x64_direct_res_dc_cs : - public ssd1306_spi_res_dc_cs, - public window -{ -private: - - static auto constexpr wsize = xy( 128, 64 ); - - uint8_t buffer[ wsize.x * wsize.y / 8 ]; + command( commands::SLPOUT ); + wait_ms( 10 ); - void write_implementation( - xy pos, - color col - ) override { - - int a = pos.x + ( pos.y / 8 ) * size.x; + command( commands::COLMOD, 0x66 ); + wait_ms( 10 ); - if( col == white ){ - buffer[ a ] |= ( 0x01 << ( pos.y % 8 )); - } else { - buffer[ a ] &= ~( 0x01 << ( pos.y % 8 )); - } - - pixels_byte_write( xy( pos.x, pos.y / 8 ), buffer[ a ] ); - - } - -public: - - /// construct by providing the i2c channel - glcd_oled_spi_128x64_direct_res_dc_cs( spi_bus & bus, pin_out & res, pin_out & dc, pin_out & cs ): - ssd1306_spi_res_dc_cs( bus, res, dc, cs ), - window( wsize, white, black ) - { - command( ssd1306_commands::display_off ); - command( ssd1306_commands::set_display_clock_div, 0x80 ); - command( ssd1306_commands::set_multiplex, 0x3f ); - command( ssd1306_commands::set_display_offset, 0x00 ); - command( (ssd1306_commands) (((int) ssd1306_commands::set_start_line ) | 0x00 )); - command( ssd1306_commands::charge_pump, 0x14 ); - command( ssd1306_commands::memory_mode, 0x00 ); - command( (ssd1306_commands) (((int) ssd1306_commands::seg_remap ) | 0x01 )); - command( ssd1306_commands::com_scan_dec ); - command( ssd1306_commands::set_compins, 0x12 ); - command( ssd1306_commands::set_contrast, 0xcf ); - command( ssd1306_commands::set_precharge, 0xf1 ); - command( ssd1306_commands::set_vcom_detect, 0x40 ); - command( ssd1306_commands::display_all_on_resume ); - command( ssd1306_commands::normal_display ); - command( ssd1306_commands::display_on ); + command( commands::MADCTL, 0x00 ); + command( commands::CASET, 0, 0, wsize.x >> 8, wsize.x & 0xFF ); + command( commands::RASET, 0, 0, wsize.y >> 8, wsize.y & 0xFF ); - } - - void clear_implementation( color c ) override { - const uint8_t d = ( c == white ) ? 0xFF : 0x00; - command( ssd1306_commands::column_addr, 0, 127 ); - command( ssd1306_commands::page_addr, 0, 7 ); - auto t = bus.transaction( cs ); - t.write( ssd1306_data_prefix ); - for( uint_fast16_t x = 0; x < sizeof( buffer ); ++x ){ - buffer[ x ] = d; - t.write( d ); - } - cursor = xy( 255, 255 ); - } - - void flush() override {} - - -}; // class glcd_oled_i2c_128x64_direct - - -// ========================================================================== -// -// buffered -// -// ========================================================================== - -/// buffered oled window -class glcd_oled_i2c_128x64_buffered : public ssd1306_i2c, public window { -private: - - static auto constexpr wsize = xy( 128, 64 ); - - uint8_t buffer[ wsize.x * wsize.y / 8 ]; - - void write_implementation( - xy pos, - color col - ) override { - int a = pos.x + ( pos.y / 8 ) * size.x; - - if( col == white ){ - buffer[ a ] |= ( 0x01 << (pos.y % 8 )); - } else { - buffer[ a ] &= ~( 0x01 << ( pos.y % 8 )); - } - } - -public: - - /// construct by providing the i2c channel - glcd_oled_i2c_128x64_buffered( i2c_bus & bus, int address = 0x3C ): - ssd1306_i2c( bus, address ), - window( wsize, white, black ) - { - bus.write( address ).write( - ssd1306_initialization, - sizeof( ssd1306_initialization ) / sizeof( uint8_t ) - ); - } - - void flush() override { - command( ssd1306_commands::column_addr, 0, 127 ); - command( ssd1306_commands::page_addr, 0, 7 ); - if(0) for( int y = 0; y < 64 / 8; y++ ){ - for( int x = 0; x < 128; x++ ){ - uint8_t d = buffer[ x + 128 * y ]; - uint8_t data[] = { 0x40, d }; - bus.write( address ).write( - data, - sizeof( data ) / sizeof( uint8_t ) - ); - } - - // yield the CPU when this is run with an I2C implementation - // that doesn't ever wait, to - // - prevent polling timing from missing an overflow - // - keep other threads in a in a multi-threading context alive - wait_us( 0 ); - } - //for( int y = 0; y < 64 / 8; y++ ){ - auto t = bus.write( address ); - t.write( ssd1306_data_prefix ); - t.write( buffer, sizeof( buffer ) / sizeof( uint8_t ) ); - //} + command( commands::INVON ); + wait_ms( 10 ); + command( commands::NORON ); + wait_ms( 10 ); + command( commands::DISPON ); + wait_ms( 10 ); } - -}; // class glcd_oled_i2c_128x64_buffered -// ========================================================================== -// -// fast buffered -// -// ========================================================================== - -/// buffered oled window -class glcd_oled_i2c_128x64_fast_buffered : public ssd1306_i2c, public window { -private: - - static auto constexpr wsize = xy( 128, 64 ); - - static auto constexpr buf_size = wsize.x * wsize.y / 8; - - uint8_t buffer[ buf_size ]; - bool dirty[ buf_size ]; - - void write_implementation( - xy pos, - color col - ) override { - int a = pos.x + ( pos.y / 8 ) * size.x; - - if( col == white ){ - buffer[ a ] |= ( 0x01 << (pos.y % 8 )); - } else { - buffer[ a ] &= ~( 0x01 << ( pos.y % 8 )); - } - - dirty[ a ] = true; - } - -public: - - /// construct by providing the i2c channel - glcd_oled_i2c_128x64_fast_buffered( i2c_bus & bus, int address = 0x3C ): - ssd1306_i2c( bus, address ), - window( wsize, white, black ) - { - bus.write( address ).write( - ssd1306_initialization, - sizeof( ssd1306_initialization ) / sizeof( uint8_t ) - ); - } - void flush() override { - unsigned int start = 0; - while( start < buf_size ){ - - // find first/next dirty pixel - while( !dirty[ start ] ){ - ++start; - if( start == buf_size ){ - // no dirty pixels: nothing to do - return; - } - } - - // find the extent of the next message - unsigned int tail = start; - unsigned int cursor = start; - unsigned int gap = 0; - for(;;){ - if( dirty[ cursor ] ){ - gap = 0; - tail = cursor; - dirty[ cursor ] = false; - } else { - // if gap larger than 10: flush upto last visited dirty pixel - if( ++gap > 10 ){ - break; - } - } - ++cursor; - // if end of buffer: flush - if( cursor == buf_size ){ - break; - } - } - - command( ssd1306_commands::column_addr, start % wsize.x, 127 ); - command( ssd1306_commands::page_addr, start / wsize.x, 7 ); - auto t = bus.write( address ); - t.write( ssd1306_data_prefix ); - t.write( & buffer[ start ], 1 + ( tail - start ) ); - } + dc.write( 0 ); dc.flush(); + auto transaction = bus.transaction( cs ); + transaction.write( static_cast< uint8_t >( commands::RAMWR ) ); + dc.write( 1 ); dc.flush(); + for( int i = 0; i < 240 * 240; ++i ){ + transaction.write( 0xFF ); + transaction.write( 0x00 ); + transaction.write( 0x00 ); + } } - -}; // class glcd_oled_i2c_128x64_fast_buffered - -using glcd_oled = glcd_oled_i2c_128x64_buffered; + +}; // class st7789_spi_dc_cs_rst -}; // namespace hwlib +}; // namespace hwlib \ No newline at end of file diff --git a/makefile.inc b/makefile.inc index 19901c7..0e66ccc 100644 --- a/makefile.inc +++ b/makefile.inc @@ -84,6 +84,7 @@ HEADERS += peripherals/hwlib-hc595.hpp HEADERS += peripherals/hwlib-hd44780.hpp HEADERS += peripherals/hwlib-glcd-5510.hpp HEADERS += peripherals/hwlib-glcd-oled.hpp +HEADERS += peripherals/hwlib-glcd-st7789.hpp HEADERS += peripherals/hwlib-matrix-keypad.hpp HEADERS += peripherals/hwlib-servo-background.hpp