diff --git a/.github/ISSUE_TEMPLATE/bug-report--------.md b/.github/ISSUE_TEMPLATE/bug-report--------.md index 0303e925..d877ad77 100644 --- a/.github/ISSUE_TEMPLATE/bug-report--------.md +++ b/.github/ISSUE_TEMPLATE/bug-report--------.md @@ -17,7 +17,7 @@ assignees: '' - Bus type: [SPI|I2C|Parallel8|Parallel16|other] - LovyanGFX version: [v0.4.17|latest develop|other] - FrameWork version: [ArduinoESP32 v2.0.3|ESP-IDF v4.4|other] -- Build Environment : [ArduinoIDE|PlatformIO|Eclipse|other] +- Build Environment: [ArduinoIDE|PlatformIO|Eclipse|other] - Operating System: [Windows|Linux|macOS] ## Problem Description ( 問題の内容 ) @@ -36,6 +36,9 @@ assignees: '' ### Code to reproduce this issue ( 再現させるためのコード ) +**Please submit complete source code that can reproduce your problem.** +**あなたの問題を再現できる完全なソースコードを提示してください。** + ```cpp // the code should be wrapped in the ```cpp tag so that it will be displayed better. #include "esp_log.h" diff --git a/.github/scripts/SDL.cmake b/.github/scripts/SDL.cmake index 743c2538..1117dbf3 100644 --- a/.github/scripts/SDL.cmake +++ b/.github/scripts/SDL.cmake @@ -14,6 +14,7 @@ file(GLOB Target_Files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS ${LovyanGFX_DIR}/lgfx/v1/*.cpp ${LovyanGFX_DIR}/lgfx/v1/misc/*.cpp ${LovyanGFX_DIR}/lgfx/v1/panel/Panel_Device.cpp + ${LovyanGFX_DIR}/lgfx/v1/panel/Panel_FrameBufferBase.cpp ${LovyanGFX_DIR}/lgfx/v1/platforms/sdl/*.cpp ) add_executable (${PROJECT_NAME} ${Target_Files}) diff --git a/.github/workflows/IDFBuild.yml b/.github/workflows/IDFBuild.yml index 1563e940..1bcad9df 100644 --- a/.github/workflows/IDFBuild.yml +++ b/.github/workflows/IDFBuild.yml @@ -27,7 +27,7 @@ jobs: esp-idf-fqbn: - esp32@v4.1 - - esp32@v4.2 + #- esp32@v4.2.5 # esp-idf tools broken by cython/openOCD - esp32@v4.3.1 - esp32s2@v4.4.4 - esp32s3@v4.4.4 @@ -37,20 +37,23 @@ jobs: - esp32@v5.0.1 - esp32s2@v5.0.1 - esp32s3@v5.0.1 + - esp32@v5.1 + - esp32s3@v5.1 # LGFX I2C not ready yet include: - { esp-idf-fqbn: esp32@v4.1, idf-board: esp32, idf-version: v4.1 } - - { esp-idf-fqbn: esp32@v4.2, idf-board: esp32, idf-version: v4.2 } + #- { esp-idf-fqbn: esp32@v4.2.5, idf-board: esp32, idf-version: v4.2.5 } - { esp-idf-fqbn: esp32@v4.3.1, idf-board: esp32, idf-version: v4.3.1 } - { esp-idf-fqbn: esp32s2@v4.4.4, idf-board: esp32s2, idf-version: v4.4.4 } - { esp-idf-fqbn: esp32s3@v4.4.4, idf-board: esp32s3, idf-version: v4.4.4 } - - { esp-idf-fqbn: esp32@v5.0, idf-board: esp32, idf-version: v5.0 } - - { esp-idf-fqbn: esp32s2@v5.0, idf-board: esp32s2, idf-version: v5.0 } - - { esp-idf-fqbn: esp32s3@v5.0, idf-board: esp32s3, idf-version: v5.0 } - - { esp-idf-fqbn: esp32@v5.0.1, idf-board: esp32, idf-version: v5.0.1 } - - { esp-idf-fqbn: esp32s2@v5.0.1, idf-board: esp32s2, idf-version: v5.0.1 } - - { esp-idf-fqbn: esp32s3@v5.0.1, idf-board: esp32s3, idf-version: v5.0.1 } - + - { esp-idf-fqbn: esp32@v5.0, idf-board: esp32, idf-version: v5.0 } + - { esp-idf-fqbn: esp32s2@v5.0, idf-board: esp32s2, idf-version: v5.0 } + - { esp-idf-fqbn: esp32s3@v5.0, idf-board: esp32s3, idf-version: v5.0 } + - { esp-idf-fqbn: esp32@v5.0.1, idf-board: esp32, idf-version: v5.0.1 } + - { esp-idf-fqbn: esp32s2@v5.0.1, idf-board: esp32s2, idf-version: v5.0.1 } + - { esp-idf-fqbn: esp32s3@v5.0.1, idf-board: esp32s3, idf-version: v5.0.1 } + - { esp-idf-fqbn: esp32@v5.1, idf-board: esp32, idf-version: v5.1 } + - { esp-idf-fqbn: esp32s3@v5.1, idf-board: esp32s3, idf-version: v5.1 } fail-fast: false diff --git a/README.md b/README.md index 446c7303..475bc9c1 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ This library has the following advantages. - M5Stack AtomDisplay - タッチスクリーン TouchScreens + - I2C CST816S - I2C FT5x06 (FT5206, FT5306, FT5406, FT6206, FT6236, FT6336, FT6436) - I2C GSLx680 (GSL1680) - I2C GT911 diff --git a/examples/Sprite/ClockSample/ClockSample.ino b/examples/Sprite/ClockSample/ClockSample.ino index 520b173c..659f0763 100644 --- a/examples/Sprite/ClockSample/ClockSample.ino +++ b/examples/Sprite/ClockSample/ClockSample.ino @@ -168,8 +168,8 @@ void loop(void) { static uint32_t p_milli = 0; uint32_t milli = lgfx::millis() % 1000; - if (p_milli < milli) count += (milli - p_milli); - else count += 1000 + (milli - p_milli); + if (p_milli > milli) count += 1000 + (milli - p_milli); + else count += (milli - p_milli); p_milli = milli; int32_t tmp = (count % 1000) >> 3; diff --git a/examples/Sprite/MeterSample/MeterSample.ino b/examples/Sprite/MeterSample/MeterSample.ino index 0d714d72..54bbd20a 100644 --- a/examples/Sprite/MeterSample/MeterSample.ino +++ b/examples/Sprite/MeterSample/MeterSample.ino @@ -17,8 +17,6 @@ static float zoom; // 表示倍率 void setup(void) { - Serial.begin(115200); - lcd.init(); int lw = std::min(lcd.width(), lcd.height()); diff --git a/examples_for_PC/CMake_SDL/CMakeLists.txt b/examples_for_PC/CMake_SDL/CMakeLists.txt index 1008a9f7..7b0811fb 100644 --- a/examples_for_PC/CMake_SDL/CMakeLists.txt +++ b/examples_for_PC/CMake_SDL/CMakeLists.txt @@ -39,7 +39,6 @@ ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") # SDL2を配置したパス内の.libファイルのパスを指定する; target_link_libraries(LGFX_SDL PUBLIC "C:/SDL2/lib/x64/SDL2.lib") - target_link_libraries(LGFX_SDL PUBLIC "C:/SDL2/lib/x64/SDL2main.lib") add_compile_options("$<$:/utf-8>") diff --git a/examples_for_PC/CMake_SDL/CMakeSettings.json b/examples_for_PC/CMake_SDL/CMakeSettings.json index 944b5676..04f6908d 100644 --- a/examples_for_PC/CMake_SDL/CMakeSettings.json +++ b/examples_for_PC/CMake_SDL/CMakeSettings.json @@ -1,15 +1,27 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "clang_cl_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "buildRoot": "${projectDir}\\.out\\build\\${name}", + "installRoot": "${projectDir}\\.out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "buildRoot": "${projectDir}\\.out\\build\\${name}", + "installRoot": "${projectDir}\\.out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "variables": [] + } + ] } \ No newline at end of file diff --git a/examples_for_PC/CMake_SDL/LGFX_SDL.cpp b/examples_for_PC/CMake_SDL/LGFX_SDL.cpp deleted file mode 100644 index 6f9a0fd8..00000000 --- a/examples_for_PC/CMake_SDL/LGFX_SDL.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#define LGFX_USE_V1 -#include -#include - -void setup(void); -void loop(void); - -static void loopThread(void) -{ - setup(); - for (;;) - { - std::this_thread::yield(); - loop(); - } -} - -int main(int, char**) -{ - std::thread sub_thread(loopThread); - for (;;) - { - std::this_thread::yield(); - lgfx::Panel_sdl::sdl_event_handler(); - SDL_Delay(5); - } -} diff --git a/examples_for_PC/CMake_SDL/sdl_main.cpp b/examples_for_PC/CMake_SDL/sdl_main.cpp new file mode 100644 index 00000000..94affd51 --- /dev/null +++ b/examples_for_PC/CMake_SDL/sdl_main.cpp @@ -0,0 +1,23 @@ +#include +#if defined ( SDL_h_ ) + +void setup(void); +void loop(void); + +__attribute__((weak)) +int user_func(bool* running) +{ + setup(); + do + { + loop(); + } while (*running); + return 0; +} + +int main(int, char**) +{ + return lgfx::Panel_sdl::main(user_func); +} + +#endif diff --git a/examples_for_PC/PlatformIO_SDL/README.md b/examples_for_PC/PlatformIO_SDL/README.md new file mode 100644 index 00000000..69c4dc73 --- /dev/null +++ b/examples_for_PC/PlatformIO_SDL/README.md @@ -0,0 +1,79 @@ + +## Visual Studio Code + PlatformIO + SDL2 環境で LovyanGFXを使用する手順 + +まず最初にVisual Studio Code をインストールし、PlatformIO を使用できる状態にする。 + + --- + +### PlatformIOにて、 `platform = native` のビルドができる状態にする。 + +手順は下記 URL から `Installation` の項目を読んで実施する。 +https://docs.platformio.org/en/latest/platforms/native.html#installation + +#### Linuxの場合 + +`apt` で `build-essential` をインストールする。 +``` +sudo apt update +sudo apt install build-essential +``` + +#### macOSの場合 +ターミナルから `xcode-select` をインストールする。 +``` +xcode-select --install +``` + +#### Windowsの場合 +`MSYS2` をここ https://www.msys2.org/ から入手してインストールする。 +そのあと、Windowsの`システムのプロパティ`->`環境変数` を開き、 `PATH` に以下の3つのパスを追加する。 +``` +C:\msys64\mingw64\bin +C:\msys64\ucrt64\bin +C:\msys64\usr\bin +``` + + + --- + +### PlatformIOにて、 SDL2 が使用できる状態にする。 + +手順は下記 URL から `Install SDL2` の項目を読んで実施する。 +https://docs.lvgl.io/latest/en/html/get-started/pc-simulator.html#install-sdl-2 + + +#### Linuxの場合 + +apt-getでlibsdl2をインストールする。 + +``` +sudo apt-get install libsdl2 libsdl2-dev +``` + +#### MacOS OSXの場合 + +Homebrewを使ってsdl2をインストールする。 +``` + brew install sdl2 +``` + +#### Windowsの場合 + +`platform = native` のビルドを可能にする手順において、 msys2をインストール済みのはずなので、 +githubの SDLのリポジトリにアクセスし、SDL2-devel-x.xx.x-mingw のリリースパッケージを入手する。 +https://github.com/libsdl-org/SDL/releases + +本記事作成時点のファイル名は `SDL2-devel-2.28.1-mingw.zip` +これを解凍し、出てきたフォルダの中にある `x86_64-w64-mingw32` フォルダを開き、中に以下の 4つのフォルダがあることを確認。 + - share + - bin + - include + - lib + +C:\msys64\mingw64\ を開き、上記の4つのフォルダと同名のフォルダが存在することを確認したら、C:\msys64\mingw64\ 内に上記フォルダの内容を追加する。(上書きコピー) + + --- + + + + diff --git a/examples_for_PC/PlatformIO_SDL/platformio.ini b/examples_for_PC/PlatformIO_SDL/platformio.ini new file mode 100644 index 00000000..4798caf7 --- /dev/null +++ b/examples_for_PC/PlatformIO_SDL/platformio.ini @@ -0,0 +1,34 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:native] +platform = native +build_type = debug +build_flags = -O0 -xc++ -std=c++14 -lSDL2 + -I"/usr/local/include/SDL2" ; for intel mac homebrew SDL2 + -L"/usr/local/lib" ; for intel mac homebrew SDL2 + -I"${sysenv.HOMEBREW_PREFIX}/include/SDL2" ; for arm mac homebrew SDL2 + -L"${sysenv.HOMEBREW_PREFIX}/lib" ; for arm mac homebrew SDL2 + +[esp32_base] +build_type = debug +platform = espressif32 +board = esp32dev +upload_speed = 1500000 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder + +[env:esp32_arduino] +extends = esp32_base +framework = arduino + +[env:esp32_idf] +extends = esp32_base +framework = espidf diff --git a/examples_for_PC/PlatformIO_SDL/src/sdl_main.cpp b/examples_for_PC/PlatformIO_SDL/src/sdl_main.cpp new file mode 100644 index 00000000..94affd51 --- /dev/null +++ b/examples_for_PC/PlatformIO_SDL/src/sdl_main.cpp @@ -0,0 +1,23 @@ +#include +#if defined ( SDL_h_ ) + +void setup(void); +void loop(void); + +__attribute__((weak)) +int user_func(bool* running) +{ + setup(); + do + { + loop(); + } while (*running); + return 0; +} + +int main(int, char**) +{ + return lgfx::Panel_sdl::main(user_func); +} + +#endif diff --git a/examples_for_PC/PlatformIO_SDL/src/user_code.cpp b/examples_for_PC/PlatformIO_SDL/src/user_code.cpp new file mode 100644 index 00000000..b3a4e607 --- /dev/null +++ b/examples_for_PC/PlatformIO_SDL/src/user_code.cpp @@ -0,0 +1,34 @@ +#define LGFX_AUTODETECT +#include +#include + +#if defined ( SDL_h_ ) +static LGFX lcd ( 320, 240, 2 ); +#else +static LGFX lcd; +#endif + +void setup(void) +{ + lcd.init(); +} + +void loop(void) +{ + lcd.fillCircle(rand()%lcd.width(), rand()%lcd.height(), 16, rand()); +} + + + +#if defined ( ESP_PLATFORM ) && !defined ( ARDUINO ) +extern "C" { +int app_main(int, char**) +{ + setup(); + for (;;) { + loop(); + } + return 0; +} +} +#endif diff --git a/library.json b/library.json index 139bafa0..476ffbeb 100644 --- a/library.json +++ b/library.json @@ -11,9 +11,9 @@ "type": "git", "url": "https://github.com/lovyan03/LovyanGFX.git" }, - "version": "1.1.7", - "frameworks": ["arduino", "espidf"], - "platforms": ["espressif32", "espressif8266", "atmelsam"], + "version": "1.1.8", + "frameworks": ["arduino", "espidf", "*"], + "platforms": ["espressif32", "espressif8266", "atmelsam", "native"], "headers": "LovyanGFX.hpp", "build": { "libArchive": false diff --git a/library.properties b/library.properties index 510299d8..c56b1689 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=LovyanGFX -version=1.1.7 +version=1.1.8 author=lovyan03 maintainer=lovyan03 sentence=TFT LCD Graphics driver with touch for ESP32, ESP8266, SAMD21, SAMD51, RP2040 diff --git a/src/lgfx/Fonts/IPA/lgfx_font_japan.c b/src/lgfx/Fonts/IPA/lgfx_font_japan.c index 92469cf6..b14ba7e7 100644 --- a/src/lgfx/Fonts/IPA/lgfx_font_japan.c +++ b/src/lgfx/Fonts/IPA/lgfx_font_japan.c @@ -1,4 +1,4 @@ -#include +#include "lgfx_font_japan.h" #if defined ( ARDUINO ) && !defined ( PROGMEM ) #if __has_include() #include diff --git a/src/lgfx/Fonts/efont/lgfx_efont_cn.c b/src/lgfx/Fonts/efont/lgfx_efont_cn.c index 28341f6c..8a3b509c 100644 --- a/src/lgfx/Fonts/efont/lgfx_efont_cn.c +++ b/src/lgfx/Fonts/efont/lgfx_efont_cn.c @@ -1,4 +1,4 @@ -#include +#include "lgfx_efont_cn.h" #if defined ( ARDUINO ) && !defined ( PROGMEM ) #if __has_include() #include diff --git a/src/lgfx/Fonts/efont/lgfx_efont_ja.c b/src/lgfx/Fonts/efont/lgfx_efont_ja.c index 93ba25fc..277faf15 100644 --- a/src/lgfx/Fonts/efont/lgfx_efont_ja.c +++ b/src/lgfx/Fonts/efont/lgfx_efont_ja.c @@ -1,4 +1,4 @@ -#include +#include "lgfx_efont_ja.h" #if defined ( ARDUINO ) && !defined ( PROGMEM ) #if __has_include() #include diff --git a/src/lgfx/Fonts/efont/lgfx_efont_kr.c b/src/lgfx/Fonts/efont/lgfx_efont_kr.c index 0345a6d7..c18d2b94 100644 --- a/src/lgfx/Fonts/efont/lgfx_efont_kr.c +++ b/src/lgfx/Fonts/efont/lgfx_efont_kr.c @@ -1,4 +1,4 @@ -#include +#include "lgfx_efont_kr.h" #if defined ( ARDUINO ) && !defined ( PROGMEM ) #if __has_include() #include diff --git a/src/lgfx/Fonts/efont/lgfx_efont_tw.c b/src/lgfx/Fonts/efont/lgfx_efont_tw.c index 11690427..dd296bef 100644 --- a/src/lgfx/Fonts/efont/lgfx_efont_tw.c +++ b/src/lgfx/Fonts/efont/lgfx_efont_tw.c @@ -1,4 +1,4 @@ -#include +#include "lgfx_efont_tw.h" #if defined ( ARDUINO ) && !defined ( PROGMEM ) #if __has_include() #include diff --git a/src/lgfx/boards.hpp b/src/lgfx/boards.hpp index 7fb22bf8..45cc2f3b 100644 --- a/src/lgfx/boards.hpp +++ b/src/lgfx/boards.hpp @@ -12,6 +12,7 @@ namespace lgfx , board_M5StackCore2 , board_M5StickC , board_M5StickCPlus + , board_M5StickCPlus2 , board_TTGO_TS , board_TTGO_TWatch , board_TTGO_TWristband diff --git a/src/lgfx/utility/lgfx_qoi.c b/src/lgfx/utility/lgfx_qoi.c index caee3e7e..da859b20 100644 --- a/src/lgfx/utility/lgfx_qoi.c +++ b/src/lgfx/utility/lgfx_qoi.c @@ -332,7 +332,7 @@ size_t lgfx_qoi_encode(const void *lineBuffer, const qoi_desc_t *desc, int flip, writeBuffer = (uint8_t*)malloc(writeBufferSize); if (!writeBuffer) { - debug_printf( "Can't malloc %d bytes", writeBufferSize); + debug_printf( "Can't malloc %d bytes", (int)writeBufferSize); return 0; } diff --git a/src/lgfx/utility/lgfx_qrcode.c b/src/lgfx/utility/lgfx_qrcode.c index 789ae845..f59ff3da 100644 --- a/src/lgfx/utility/lgfx_qrcode.c +++ b/src/lgfx/utility/lgfx_qrcode.c @@ -850,11 +850,11 @@ int8_t lgfx_qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, // Find the best (lowest penalty) mask uint8_t mask = 0; - int32_t minPenalty = INT32_MAX; + uint32_t minPenalty = ~0u; for (uint_fast8_t i = 0; i < 8; i++) { drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); applyMask(&modulesGrid, &isFunctionGrid, i); - int penalty = getPenaltyScore(&modulesGrid); + uint32_t penalty = getPenaltyScore(&modulesGrid); if (penalty < minPenalty) { mask = i; minPenalty = penalty; diff --git a/src/lgfx/v1/LGFXBase.cpp b/src/lgfx/v1/LGFXBase.cpp index 11cb7ab2..6e70d7c2 100644 --- a/src/lgfx/v1/LGFXBase.cpp +++ b/src/lgfx/v1/LGFXBase.cpp @@ -1497,10 +1497,24 @@ namespace lgfx _panel->copyRect(dst_x, dst_y, w, h, src_x, src_y); } - if ( dx > 0) writeFillRectPreclipped(_sx , dst_y, dx, h); - else if (dx < 0) writeFillRectPreclipped(_sx + _sw + dx, dst_y, -dx, h); - if ( dy > 0) writeFillRectPreclipped(_sx, _sy , _sw, dy); - else if (dy < 0) writeFillRectPreclipped(_sx, _sy + _sh + dy, _sw, -dy); + int_fast16_t sx = _sx; + if (dy != 0) + { + int_fast16_t sy = _sy; + if (dy < 0) { + sy += _sh + dy; + dy = -dy; + } + writeFillRectPreclipped(sx, sy, _sw, dy); + } + if (dx != 0) + { + if (dx < 0) { + sx += _sw + dx; + dx = -dx; + } + writeFillRectPreclipped(sx, dst_y, dx, h); + } endWrite(); } @@ -2242,30 +2256,37 @@ namespace lgfx y = (height() - w) >> 1; } - setColor(0xFFFFFFU); - startWrite(); - writeFillRect(x, y, w, w); for (; version <= 40; ++version) { QRCode qrcode; auto qrcodeData = (uint8_t*)alloca(lgfx_qrcode_getBufferSize(version)); if (0 != lgfx_qrcode_initText(&qrcode, qrcodeData, version, 0, string)) continue; int_fast16_t thickness = w / qrcode.size; - if (!thickness) break; int_fast16_t lineLength = qrcode.size * thickness; - int_fast16_t xOffset = x + ((w - lineLength) >> 1); - int_fast16_t yOffset = y + ((w - lineLength) >> 1); - setColor(0); - y = 0; - do { - x = 0; + int_fast16_t offset = (w - lineLength) >> 1; + startWrite(); + writeFillRect(x, y, w, offset, TFT_WHITE); + int_fast16_t dy = y + offset; + if (thickness) + { + int_fast16_t iy = 0; do { - if (lgfx_qrcode_getModule(&qrcode, x, y)) writeFillRect(x * thickness + xOffset, y * thickness + yOffset, thickness, thickness); - } while (++x < qrcode.size); - } while (++y < qrcode.size); + writeFillRect(x, dy, offset, thickness, TFT_WHITE); + int_fast16_t ix = 0; + int_fast16_t dx = x + offset; + do { + setColor(lgfx_qrcode_getModule(&qrcode, ix, iy) ? TFT_BLACK : TFT_WHITE); + writeFillRect(dx, dy, thickness, thickness); + dx += thickness; + } while (++ix < qrcode.size); + writeFillRect(dx, dy, x + w - dx, thickness, TFT_WHITE); + dy += thickness; + } while (++iy < qrcode.size); + } + writeFillRect(x, dy, w, y + w - dy, TFT_WHITE); + endWrite(); break; } - endWrite(); } //---------------------------------------------------------------------------- @@ -2935,9 +2956,24 @@ namespace lgfx } } + + static pngle_t* pngle = nullptr; + void LGFXBase::releasePngMemory(void) + { + if (pngle) { + lgfx_pngle_destroy(pngle); + pngle = nullptr; + } + } + bool LGFXBase::draw_png(DataWrapper* data, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, float zoom_x, float zoom_y, datum_t datum) { - pngle_t *pngle = lgfx_pngle_new(); + /// PNG描画を繰り返し使用した場合、pngleのメモリ確保に失敗するケースがある。 + /// そのため、pngle使用後に解放せず、再利用できる構成に変更した。 + /// メモリを明示的に解放したい場合は releasePngMemory を使用する。 + if (pngle == nullptr) { + pngle = lgfx_pngle_new(); + } if (pngle == nullptr) { return false; } prepareTmpTransaction(data); @@ -2947,7 +2983,6 @@ namespace lgfx if (lgfx_pngle_prepare(pngle, image_decoder_t::read_data, &png) < 0) { - lgfx_pngle_destroy(pngle); return false; } @@ -2963,7 +2998,6 @@ namespace lgfx , datum , lgfx_pngle_get_width(pngle), lgfx_pngle_get_height(pngle))) { - lgfx_pngle_destroy(pngle); return true; } @@ -2992,7 +3026,6 @@ namespace lgfx heap_free(png.lineBuffer); } png.end(); - lgfx_pngle_destroy(pngle); return res < 0 ? false : true; } diff --git a/src/lgfx/v1/LGFXBase.hpp b/src/lgfx/v1/LGFXBase.hpp index f33f5d2a..91a75ead 100644 --- a/src/lgfx/v1/LGFXBase.hpp +++ b/src/lgfx/v1/LGFXBase.hpp @@ -62,17 +62,64 @@ namespace lgfx LGFXBase(void) = default; virtual ~LGFXBase(void) = default; + /// @brief Converts RGB information to 8-bit color code. + /// @param r red + /// @param g green + /// @param b blue + /// @return 8-bit color code LGFX_INLINE static constexpr uint8_t color332(uint8_t r, uint8_t g, uint8_t b) { return lgfx::color332(r, g, b); } + /// @brief Converts RGB information to 16-bit color code. + /// @param r red + /// @param g green + /// @param b blue + /// @return 16-bit color code LGFX_INLINE static constexpr uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return lgfx::color565(r, g, b); } + /// @brief Converts RGB information to 24-bit color code. + /// @param r red + /// @param g green + /// @param b blue + /// @return 24-bit color code LGFX_INLINE static constexpr uint32_t color888(uint8_t r, uint8_t g, uint8_t b) { return lgfx::color888(r, g, b); } + + /// @brief Endian conversion of 16-bit RGB565 format color code. + /// @param r red + /// @param g green + /// @param b blue + /// @return 16-bit color code (endian converted) + /// @note This function is used to draw directly to the Sprite's buffer memory. LGFX_INLINE static constexpr uint16_t swap565( uint8_t r, uint8_t g, uint8_t b) { return lgfx::swap565( r, g, b); } + /// @brief Endian conversion of 24-bit RGB888 format color code. + /// @param r red + /// @param g green + /// @param b blue + /// @return 24-bit color code (endian converted) + /// @note This function is used to draw directly to the Sprite's buffer memory. LGFX_INLINE static constexpr uint32_t swap888( uint8_t r, uint8_t g, uint8_t b) { return lgfx::swap888( r, g, b); } + + /// @brief Convert 16-bit RGB565 format color code to 8-bit RGB332 format. + /// @param rgb565 16-bit color code + /// @return 8-bit color code LGFX_INLINE static uint8_t color16to8( uint32_t rgb565) { return lgfx::color_convert(rgb565); } + /// @brief Convert 8-bit RGB332 format color code to 16-bit RGB565 format. + /// @param rgb332 16-bit color code + /// @return 16-bit color code LGFX_INLINE static uint16_t color8to16( uint32_t rgb332) { return lgfx::color_convert(rgb332); } + /// @brief Convert 16-bit RGB565 format color code to 24-bit RGB888 format. + /// @param rgb565 16-bit color code + /// @return 24-bit color code LGFX_INLINE static uint32_t color16to24(uint32_t rgb565) { return lgfx::color_convert(rgb565); } + /// @brief Convert 24-bit RGB888 format color code to 16-bit RGB565 format. + /// @param rgb888 24-bit color code + /// @return 16-bit color code LGFX_INLINE static uint16_t color24to16(uint32_t rgb888) { return lgfx::color_convert(rgb888); } + /// @brief Specifies the color used to draw the screen. + /// @param r red + /// @param g green + /// @param b blue LGFX_INLINE void setColor(uint8_t r, uint8_t g, uint8_t b) { setColor(lgfx::color888(r,g,b)); } + /// @brief Specifies the color used to draw the screen. + /// @param color color code LGFX_INLINE_T void setColor(T color) { setRawColor(_write_conv.convert(color)); } LGFX_INLINE void setRawColor(uint32_t c) { *((uint32_t*)&_color) = c; } LGFX_INLINE uint32_t getRawColor(void) const { return *((uint32_t*)&_color); } @@ -81,7 +128,14 @@ namespace lgfx LGFX_INLINE color_conv_t* getColorConverter(void) { return &_write_conv; } LGFX_INLINE color_depth_t getColorDepth(void) const { return _write_conv.depth; } + /// @brief Allocate bus for screen communication. + /// @param transaction If true, transaction processing is performed. + /// @note Although bus allocation and release are automatically performed when drawing functions are called, + /// using startWrite and endWrite before and after the drawing process suppresses bus allocation + /// and release and improves drawing speed. + /// In the case of electronic paper (EPD), drawing after startWrite() is reflected on the screen by calling endWrite(). LGFX_INLINE void startWrite(bool transaction = true) { _panel->startWrite(transaction); } + /// @brief Release bus for screen communication. LGFX_INLINE void endWrite(void) { _panel->endWrite(); } LGFX_INLINE void beginTransaction(void) { _panel->beginTransaction(); } LGFX_INLINE void endTransaction(void) { _panel->endTransaction(); } @@ -100,15 +154,68 @@ namespace lgfx LGFX_INLINE void writeFillRectPreclipped( int32_t x, int32_t y, int32_t w, int32_t h) { _panel->writeFillRectPreclipped(x, y, w, h, getRawColor()); } LGFX_INLINE_T void writeColor ( const T& color, uint32_t length) { if (0 == length) return; setColor(color); _panel->writeBlock(getRawColor(), length); } LGFX_INLINE_T void pushBlock ( const T& color, uint32_t length) { if (0 == length) return; setColor(color); startWrite(); _panel->writeBlock(getRawColor(), length); endWrite(); } + + /// @brief Draw a pixel. + /// @param x X-coordinate + /// @param y Y-coordinate + /// @note Draws in the color specified by setColor(). LGFX_INLINE void drawPixel ( int32_t x, int32_t y) { if (x >= _clip_l && x <= _clip_r && y >= _clip_t && y <= _clip_b) { _panel->drawPixelPreclipped(x, y, getRawColor()); } } + /// @brief Draw a pixel. + /// @param x X-coordinate + /// @param y Y-coordinate + /// @param color Color to draw with LGFX_INLINE_T void drawPixel ( int32_t x, int32_t y , const T& color) { setColor(color); drawPixel (x, y ); } + /// @brief Draw a vertical line. + /// @param x Top-most X-coordinate + /// @param y Top-most Y-coordinate + /// @param h Height in pixels + /// @param color Color to draw with LGFX_INLINE_T void drawFastVLine ( int32_t x, int32_t y , int32_t h , const T& color) { setColor(color); drawFastVLine(x, y , h ); } + /// @brief Draw a vertical line. + /// @param x Top-most X-coordinate + /// @param y Top-most Y-coordinate + /// @param h Height in pixels + /// @note Draws in the color specified by setColor(). void drawFastVLine ( int32_t x, int32_t y , int32_t h); + /// @brief Draw a horizontal line. + /// @param x Left-most X-coordinate + /// @param y Left-most Y-coordinate + /// @param w Width in pixels + /// @param color Color to draw with LGFX_INLINE_T void drawFastHLine ( int32_t x, int32_t y, int32_t w , const T& color) { setColor(color); drawFastHLine(x, y, w ); } + /// @brief Draw a horizontal line. + /// @param x Left-most X-coordinate + /// @param y Left-most Y-coordinate + /// @param w Width in pixels + /// @note Draws in the color specified by setColor(). void drawFastHLine ( int32_t x, int32_t y, int32_t w); + /// @brief Fill a rectangle. + /// @param x Top-left-corner X-coordinate + /// @param y Top-left-corner Y-coordinate + /// @param w Width in pixels + /// @param h Height in pixels + /// @param color Color to fill with LGFX_INLINE_T void fillRect ( int32_t x, int32_t y, int32_t w, int32_t h , const T& color) { setColor(color); fillRect (x, y, w, h ); } + /// @brief Fill a rectangle. + /// @param x Top-left-corner X-coordinate + /// @param y Top-left-corner Y-coordinate + /// @param w Width in pixels + /// @param h Height in pixels + /// @note Draws in the color specified by setColor(). void fillRect ( int32_t x, int32_t y, int32_t w, int32_t h); + /// @brief Draw a rectangle outline. + /// @param x Top-left-corner X-coordinate + /// @param y Top-left-corner Y-coordinate + /// @param w Width in pixels + /// @param h Height in pixels + /// @param color Color to fill with LGFX_INLINE_T void drawRect ( int32_t x, int32_t y, int32_t w, int32_t h , const T& color) { setColor(color); drawRect (x, y, w, h ); } + /// @brief Draw a rectangle outline. + /// @param x Top-left-corner X-coordinate + /// @param y Top-left-corner Y-coordinate + /// @param w Width in pixels + /// @param h Height in pixels + /// @note Draws in the color specified by setColor(). void drawRect ( int32_t x, int32_t y, int32_t w, int32_t h); LGFX_INLINE_T void drawRoundRect ( int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, const T& color) { setColor(color); drawRoundRect(x, y, w, h, r); } void drawRoundRect ( int32_t x, int32_t y, int32_t w, int32_t h, int32_t r); @@ -747,7 +854,7 @@ namespace lgfx void* createPng( size_t* datalen, int32_t x = 0, int32_t y = 0, int32_t width = 0, int32_t height = 0); - + void releasePngMemory(void); template [[deprecated("use pushImage")]] void pushRect( int32_t x, int32_t y, int32_t w, int32_t h, const T* data) { pushImage(x, y, w, h, data); } @@ -1131,7 +1238,8 @@ namespace lgfx //---------------------------------------------------------------------------- - /// LovyanGFXクラス。ファイルシステム等、利用環境側のinclude順に依存する機能はLGFX_FILESYSTEM_Supportから継承する。; + /// @brief LovyanGFX class. + /// that depend on the include order of the environment, such as file system, are inherited from LGFX_FILESYSTEM_Support. class LovyanGFX : public #ifdef LGFX_FILESYSTEM_SUPPORT_HPP_ LGFX_FILESYSTEM_Support< diff --git a/src/lgfx/v1/LGFX_Sprite.cpp b/src/lgfx/v1/LGFX_Sprite.cpp index 990d9507..496f2832 100644 --- a/src/lgfx/v1/LGFX_Sprite.cpp +++ b/src/lgfx/v1/LGFX_Sprite.cpp @@ -179,17 +179,18 @@ namespace lgfx uint8_t* dst = &_img[(x + y * bw) * bytes]; uint8_t* src = dst; uint_fast16_t add_dst = bw * bytes; - uint_fast16_t len = w * bytes; + uint_fast32_t len = w * bytes; + uint_fast32_t w32 = w; if (_img.use_memcpy()) { - if (w != bw) + if (w32 != bw) { dst += add_dst; } else { - w *= h; + w32 *= h; h = 1; } } @@ -198,7 +199,7 @@ namespace lgfx src = (uint8_t*)alloca(len); ++h; } - memset_multi(src, rawcolor, bytes, w); + memset_multi(src, rawcolor, bytes, w32); while (--h) { memcpy(dst, src, len); diff --git a/src/lgfx/v1/LGFX_Sprite.hpp b/src/lgfx/v1/LGFX_Sprite.hpp index 8173daf1..dfc7ecfd 100644 --- a/src/lgfx/v1/LGFX_Sprite.hpp +++ b/src/lgfx/v1/LGFX_Sprite.hpp @@ -223,7 +223,7 @@ namespace lgfx #endif -#elif defined (ESP32) || defined (CONFIG_IDF_TARGET_ESP32) || defined (CONFIG_IDF_TARGET_ESP32S2) || defined (ESP_PLATFORM) +#elif defined (ESP_PLATFORM) || defined(__SAMD51_HARMONY__) || defined(stdin) // ESP-IDF, Harmony, stdio void createFromBmpFile(const char *path) { FileWrapper file; diff --git a/src/lgfx/v1/Panel.hpp b/src/lgfx/v1/Panel.hpp index 698542ae..f53172f3 100644 --- a/src/lgfx/v1/Panel.hpp +++ b/src/lgfx/v1/Panel.hpp @@ -23,8 +23,10 @@ Original Source: #include #else #include +#ifndef alloca #define alloca _alloca #endif +#endif #include "misc/enum.hpp" #include "misc/colortype.hpp" @@ -158,7 +160,13 @@ namespace lgfx auto ye = y + h; auto buf = (RGBColor*)alloca(w * sizeof(RGBColor)); #pragma GCC diagnostic push +#if defined(__has_warning) +#if __has_warning("-Wmaybe-uninitialized") #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif +#else +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif /// Not actually used uninitialized. Just grabbing a copy of the pointer before we start the loop that fills it. pixelcopy_t pc_write(buf ,_write_depth, RGBColor::depth, false); #pragma GCC diagnostic pop diff --git a/src/lgfx/v1/gitTagVersion.h b/src/lgfx/v1/gitTagVersion.h index 36d68a09..f7172599 100644 --- a/src/lgfx/v1/gitTagVersion.h +++ b/src/lgfx/v1/gitTagVersion.h @@ -1,4 +1,4 @@ #define LGFX_VERSION_MAJOR 1 #define LGFX_VERSION_MINOR 1 -#define LGFX_VERSION_PATCH 7 +#define LGFX_VERSION_PATCH 8 #define LOVYANGFX_VERSION F( LGFX_VERSION_MAJOR "." LGFX_VERSION_MINOR "." LGFX_VERSION_PATCH ) diff --git a/src/lgfx/v1/lgfx_filesystem_support.hpp b/src/lgfx/v1/lgfx_filesystem_support.hpp index bae6e0fa..4cecb417 100644 --- a/src/lgfx/v1/lgfx_filesystem_support.hpp +++ b/src/lgfx/v1/lgfx_filesystem_support.hpp @@ -31,7 +31,9 @@ Original Source: #include #else #include + #ifndef alloca #define alloca _alloca + #endif #endif namespace lgfx @@ -350,7 +352,7 @@ namespace lgfx #endif #endif -#elif defined (ESP_PLATFORM) || defined(__SAMD51_HARMONY__) || defined(_INC_STDIO) // ESP-IDF or Harmony +#elif defined (ESP_PLATFORM) || defined(__SAMD51_HARMONY__) || defined(stdin) // ESP-IDF, Harmony, stdio #define LGFX_FUNCTION_GENERATOR(drawImg) \ inline bool drawImg##File(const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ diff --git a/src/lgfx/v1/misc/colortype.hpp b/src/lgfx/v1/misc/colortype.hpp index fb35f7d4..c3d7786f 100644 --- a/src/lgfx/v1/misc/colortype.hpp +++ b/src/lgfx/v1/misc/colortype.hpp @@ -417,7 +417,7 @@ namespace lgfx static constexpr color_depth_t depth = argb8888_4Byte; constexpr bgra8888_t(void) : raw{0} {}; constexpr bgra8888_t(const bgra8888_t&) = default; - constexpr bgra8888_t(uint8_t r8, uint8_t g8, uint8_t b8) : r(r8), g(g8), b(b8) {} + constexpr bgra8888_t(uint8_t r8, uint8_t g8, uint8_t b8) : a(255), r(r8), g(g8), b(b8) {} constexpr bgra8888_t(uint8_t a8, uint8_t r8, uint8_t g8, uint8_t b8) : a(a8), r(r8), g(g8), b(b8) {} constexpr bgra8888_t(uint32_t bgra8888) : raw(bgra8888) {} inline bgra8888_t& operator=(uint32_t rhs) { *reinterpret_cast(this) = rhs; return *this; } diff --git a/src/lgfx/v1/panel/Panel_FrameBufferBase.hpp b/src/lgfx/v1/panel/Panel_FrameBufferBase.hpp index a577b0ec..b69930f0 100644 --- a/src/lgfx/v1/panel/Panel_FrameBufferBase.hpp +++ b/src/lgfx/v1/panel/Panel_FrameBufferBase.hpp @@ -59,7 +59,7 @@ namespace lgfx uint32_t readData(uint_fast8_t, uint_fast8_t) override { return 0; } void readRect(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, void* dst, pixelcopy_t* param) override; - void copyRect(uint_fast16_t dst_x, uint_fast16_t dst_y, uint_fast16_t w, uint_fast16_t h, uint_fast16_t src_x, uint_fast16_t src_y); + void copyRect(uint_fast16_t dst_x, uint_fast16_t dst_y, uint_fast16_t w, uint_fast16_t h, uint_fast16_t src_x, uint_fast16_t src_y) override; protected: uint8_t** _lines_buffer = nullptr; diff --git a/src/lgfx/v1/panel/Panel_GC9A01.hpp b/src/lgfx/v1/panel/Panel_GC9A01.hpp index 7b137ae7..3f50bf73 100644 --- a/src/lgfx/v1/panel/Panel_GC9A01.hpp +++ b/src/lgfx/v1/panel/Panel_GC9A01.hpp @@ -103,14 +103,14 @@ namespace lgfx 0x85, 1, 0xFF, 0x86, 1, 0xFF, 0x87, 1, 0xFF, + 0x8E, 1, 0xFF, + 0x8F, 1, 0xFF, 0x88, 1, 0x0A, 0x89, 1, 0x21, 0x8A, 1, 0x00, 0x8B, 1, 0x80, 0x8C, 1, 0x01, 0x8D, 1, 0x01, - 0x8E, 1, 0xFF, - 0x8F, 1, 0xFF, 0xB6, 2, 0x00, 0x20, 0x90, 4, 0x08, 0x08, 0x08, 0x08, 0xBD, 1, 0x06, @@ -136,9 +136,10 @@ namespace lgfx 0x64, 7, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07, 0x66,10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00, 0x67,10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98, - 0x74, 7, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00, + 0x74, 7, 0x10, 0x68, 0x80, 0x00, 0x00, 0x4E, 0x00, 0x98, 2, 0x3e, 0x07, -// 0x35, 0, // Tearing Effect Line ON + 0x35, 1, 0x00, // Tearing Effect Line ON + 0x21, 0, 0x11, 0+CMD_INIT_DELAY, 120, 0x29, 0+CMD_INIT_DELAY, 20, 0xFF,0xFF, // end diff --git a/src/lgfx/v1/panel/Panel_GDEW0154M09.cpp b/src/lgfx/v1/panel/Panel_GDEW0154M09.cpp index 8f34f3ef..86a69e65 100644 --- a/src/lgfx/v1/panel/Panel_GDEW0154M09.cpp +++ b/src/lgfx/v1/panel/Panel_GDEW0154M09.cpp @@ -291,7 +291,7 @@ namespace lgfx uint32_t idx = 0; do { - readbuf[idx] = _read_pixel(x + idx, y) ? ~0u : 0; + readbuf[idx] = _read_pixel(x + idx, y) ? -1 : 0; } while (++idx != w); param->src_x32 = 0; readpos = param->fp_copy(dst, readpos, readpos + w, param); diff --git a/src/lgfx/v1/panel/Panel_M5HDMI.cpp b/src/lgfx/v1/panel/Panel_M5HDMI.cpp index f06859a8..430d5178 100644 --- a/src/lgfx/v1/panel/Panel_M5HDMI.cpp +++ b/src/lgfx/v1/panel/Panel_M5HDMI.cpp @@ -109,6 +109,14 @@ namespace lgfx *_tdi_reg[0] = TDI_MASK; *_tck_reg[0] = TCK_MASK; + int retry = 128; + do + { // FPGAのロットによって待ち時間に差がある。 + // 先に進んで良いかステータスレジスタの状態をチェックする。 + if ((JTAG_ReadStatus() & 0x200) == 0) { break; } + delay(1); + } while (--retry); + JTAG_MoveTap(TAP_UNKNOWN, TAP_IDLE); ESP_LOGI(TAG, "Erase FPGA SRAM..."); @@ -440,29 +448,6 @@ namespace lgfx //---------------------------------------------------------------------------- - class _pin_backup_t - { - public: - _pin_backup_t(gpio_num_t pin_num) - : _io_mux_gpio_reg { *reinterpret_cast(GPIO_PIN_MUX_REG[pin_num]) } - , _gpio_func_out_reg { *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (pin_num * 4)) } - , _pin_num { pin_num } - {} - - void restore(void) const - { - if ((uint32_t)_pin_num < GPIO_NUM_MAX) { - *reinterpret_cast(GPIO_PIN_MUX_REG[_pin_num]) = _io_mux_gpio_reg; - *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (_pin_num * 4)) = _gpio_func_out_reg; - } - } - - private: - uint32_t _io_mux_gpio_reg; - uint32_t _gpio_func_out_reg; - gpio_num_t _pin_num; - }; - uint32_t Panel_M5HDMI::_read_fpga_id(void) { startWrite(); @@ -504,7 +489,7 @@ namespace lgfx if ((_read_fpga_id() & 0xFFFF) != ('H' | 'D' << 8)) { auto bus_cfg = reinterpret_cast(_bus)->config(); - _pin_backup_t backup_pins[] = { (gpio_num_t)bus_cfg.pin_sclk, (gpio_num_t)bus_cfg.pin_mosi, (gpio_num_t)bus_cfg.pin_miso }; + gpio::pin_backup_t backup_pins[] = { bus_cfg.pin_sclk, bus_cfg.pin_mosi, bus_cfg.pin_miso }; LOAD_FPGA fpga(bus_cfg.pin_sclk, bus_cfg.pin_mosi, bus_cfg.pin_miso, _cfg.pin_cs); for (auto &bup : backup_pins) { bup.restore(); } @@ -1042,10 +1027,7 @@ namespace lgfx buf[3] = _raw_color; bytes += 4; } - if (rect || _total_send || _last_cmd) - { - _check_busy(bytes); - } + _check_busy(bytes); _bus->writeBytes(((uint8_t*)buf)+3, bytes, false, false); } diff --git a/src/lgfx/v1/panel/Panel_RA8875.cpp b/src/lgfx/v1/panel/Panel_RA8875.cpp index 16fd2ad7..e29bc86c 100644 --- a/src/lgfx/v1/panel/Panel_RA8875.cpp +++ b/src/lgfx/v1/panel/Panel_RA8875.cpp @@ -241,7 +241,7 @@ namespace lgfx return true; } - void Panel_RA8875::_write_reg(uint8_t reg, uint8_t data) + void Panel_RA8875::_write_reg(uint_fast16_t reg, uint_fast16_t data) { _flg_memorywrite = false; if (_flg_serialbus) diff --git a/src/lgfx/v1/panel/Panel_RA8875.hpp b/src/lgfx/v1/panel/Panel_RA8875.hpp index 4ecdabe0..76ec5137 100644 --- a/src/lgfx/v1/panel/Panel_RA8875.hpp +++ b/src/lgfx/v1/panel/Panel_RA8875.hpp @@ -86,7 +86,7 @@ namespace lgfx void _set_write_pos(uint_fast16_t x, uint_fast16_t y); bool _wait_busy( uint32_t timeout = 1000); - void _write_reg(uint8_t reg, uint8_t data); + void _write_reg(uint_fast16_t reg, uint_fast16_t data); void _write_reg_0x51(uint8_t reg, uint8_t data); void _start_memorywrite(void); }; diff --git a/src/lgfx/v1/panel/Panel_SSD1306.cpp b/src/lgfx/v1/panel/Panel_SSD1306.cpp index c441d879..4b110125 100644 --- a/src/lgfx/v1/panel/Panel_SSD1306.cpp +++ b/src/lgfx/v1/panel/Panel_SSD1306.cpp @@ -33,7 +33,7 @@ namespace lgfx { //---------------------------------------------------------------------------- - static constexpr uint8_t Bayer[16] = { 8, 136, 40, 168, 200, 72, 232, 104, 56, 184, 24, 152, 248, 120, 216, 88 }; + static constexpr uint8_t Bayer[] = { 8, 136, 40, 168, 200, 72, 232, 104, 56, 184, 24, 152, 248, 120, 216, 88, 8, 136, 40, 168, 200, 72, 232, 104, 56, 184, 24, 152, 248, 120, 216, 88 }; inline static uint32_t to_gray(uint8_t r, uint8_t g, uint8_t b) { @@ -44,6 +44,11 @@ namespace lgfx ) >> 24; } + void Panel_1bitOLED::setTilePattern(uint_fast8_t i) + { + _bayer_offset = Bayer[i & 15] >> 4; + } + color_depth_t Panel_1bitOLED::setColorDepth(color_depth_t depth) { _write_depth = color_depth_t::rgb565_2Byte; @@ -131,7 +136,7 @@ namespace lgfx { x = xs; uint32_t idx = x + (y >> 3) * _cfg.panel_width; - auto btbl = &Bayer[(y & 3) << 2]; + auto btbl = &Bayer[_bayer_offset + ((y & 3) << 2)]; uint32_t mask = 1 << (y&7); do { @@ -223,7 +228,7 @@ namespace lgfx uint32_t idx = 0; do { - readbuf[idx] = _read_pixel(x + idx, y) ? ~0u : 0; + readbuf[idx] = _read_pixel(x + idx, y) ? -1 : 0; } while (++idx != w); param->src_x32 = 0; readpos = param->fp_copy(dst, readpos, readpos + w, param); @@ -235,7 +240,7 @@ namespace lgfx _rotate_pos(x, y); uint32_t idx = x + (y >> 3) * _cfg.panel_width; uint32_t mask = 1 << (y&7); - bool flg = 256 <= value + Bayer[(x & 3) | (y & 3) << 2]; + bool flg = 256 <= value + Bayer[_bayer_offset + ((x & 3) | (y & 3) << 2)]; if (flg) _buf[idx] |= mask; else _buf[idx] &= ~mask; } diff --git a/src/lgfx/v1/panel/Panel_SSD1306.hpp b/src/lgfx/v1/panel/Panel_SSD1306.hpp index 114d87e1..9a4416e0 100644 --- a/src/lgfx/v1/panel/Panel_SSD1306.hpp +++ b/src/lgfx/v1/panel/Panel_SSD1306.hpp @@ -46,6 +46,7 @@ namespace lgfx uint32_t readData(uint_fast8_t, uint_fast8_t) override { return 0; } void readRect(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, void* dst, pixelcopy_t* param) override; + void setTilePattern(uint_fast8_t); protected: @@ -60,6 +61,8 @@ namespace lgfx static constexpr uint8_t CMD_SETPRECHARGE = 0xD9; static constexpr uint8_t CMD_SETVCOMDETECT = 0xDB; + uint8_t _bayer_offset = 0; + size_t _get_buffer_length(void) const override; bool _read_pixel(uint_fast16_t x, uint_fast16_t y); void _draw_pixel(uint_fast16_t x, uint_fast16_t y, uint32_t value); diff --git a/src/lgfx/v1/platforms/common.hpp b/src/lgfx/v1/platforms/common.hpp index d0e8f331..4789dd69 100644 --- a/src/lgfx/v1/platforms/common.hpp +++ b/src/lgfx/v1/platforms/common.hpp @@ -49,14 +49,14 @@ Original Source: #include "arduino_default/common.hpp" -#elif __has_include() - -#include "opencv/common.hpp" - #elif __has_include() || __has_include() #include "sdl/common.hpp" +#elif __has_include() + +#include "opencv/common.hpp" + #elif defined (__linux__) #include "framebuffer/common.hpp" diff --git a/src/lgfx/v1/platforms/device.hpp b/src/lgfx/v1/platforms/device.hpp index aca102a3..182886f4 100644 --- a/src/lgfx/v1/platforms/device.hpp +++ b/src/lgfx/v1/platforms/device.hpp @@ -88,5 +88,10 @@ Original Source: #include "arduino_default/Bus_SPI.hpp" +#elif __has_include() || __has_include() + +#include "sdl/Bus_I2C.hpp" +#include "sdl/Panel_sdl.hpp" + #endif diff --git a/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp b/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp index eda96897..3667b39a 100644 --- a/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp +++ b/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp @@ -77,6 +77,7 @@ Original Source: #if defined (SOC_GDMA_SUPPORTED) // for C3/S3 #include #include + #include #if !defined DMA_OUT_LINK_CH0_REG #define DMA_OUT_LINK_CH0_REG GDMA_OUT_LINK_CH0_REG #define DMA_OUTFIFO_STATUS_CH0_REG GDMA_OUTFIFO_STATUS_CH0_REG @@ -159,8 +160,8 @@ namespace lgfx if (assigned_dma_ch >= 0) { // DMAチャンネルが特定できたらそれを使用する; - _spi_dma_out_link_reg = reg(DMA_OUT_LINK_CH0_REG + assigned_dma_ch * 0xC0); - _spi_dma_outstatus_reg = reg(DMA_OUTFIFO_STATUS_CH0_REG + assigned_dma_ch * 0xC0); + _spi_dma_out_link_reg = reg(DMA_OUT_LINK_CH0_REG + assigned_dma_ch * sizeof(GDMA.channel[0])); + _spi_dma_outstatus_reg = reg(DMA_OUTFIFO_STATUS_CH0_REG + assigned_dma_ch * sizeof(GDMA.channel[0])); } #elif defined ( CONFIG_IDF_TARGET_ESP32 ) || !defined ( CONFIG_IDF_TARGET ) @@ -178,7 +179,7 @@ namespace lgfx { if (pin >= GPIO_NUM_MAX) return; gpio_reset_pin( (gpio_num_t)pin); - gpio_matrix_out((gpio_num_t)pin, 0x100, 0, 0); + gpio_matrix_out((gpio_num_t)pin, SIG_GPIO_OUT_IDX, 0, 0); // gpio_matrix_in には、ArduinoESP32 v1.0.x系では重大なバグがある。(無関係なピンに対して設定変更が行われることがある) // gpio_matrix_in( (gpio_num_t)pin, 0x100, 0 ); } diff --git a/src/lgfx/v1/platforms/esp32/Bus_SPI.hpp b/src/lgfx/v1/platforms/esp32/Bus_SPI.hpp index a61e009a..3d205912 100644 --- a/src/lgfx/v1/platforms/esp32/Bus_SPI.hpp +++ b/src/lgfx/v1/platforms/esp32/Bus_SPI.hpp @@ -64,7 +64,7 @@ namespace lgfx class Bus_SPI : public IBus { -#if !defined (SPI_MOSI_DLEN_REG) +#if defined ( SPI_UPDATE ) static constexpr uint32_t SPI_EXECUTE = SPI_USR | SPI_UPDATE; #define SPI_MOSI_DLEN_REG(i) (REG_SPI_BASE(i) + 0x1C) #define SPI_MISO_DLEN_REG(i) (REG_SPI_BASE(i) + 0x1C) diff --git a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp index f2a7e406..cc2d8791 100644 --- a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp +++ b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp @@ -32,12 +32,15 @@ namespace lgfx { //---------------------------------------------------------------------------- + static constexpr const uint8_t PWM_BITS = 9; + + bool Light_PWM::init(uint8_t brightness) { #if defined ( ARDUINO ) - ledcSetup(_cfg.pwm_channel, _cfg.freq, 8); + ledcSetup(_cfg.pwm_channel, _cfg.freq, PWM_BITS); ledcAttachPin(_cfg.pin_bl, _cfg.pwm_channel); setBrightness(brightness); @@ -54,7 +57,7 @@ namespace lgfx ledc_channel.channel = (ledc_channel_t)_cfg.pwm_channel; ledc_channel.intr_type = LEDC_INTR_DISABLE; ledc_channel.timer_sel = (ledc_timer_t)((_cfg.pwm_channel >> 1) & 3); - ledc_channel.duty = _cfg.invert ? 256 : 0; + ledc_channel.duty = _cfg.invert ? (1 << PWM_BITS) : 0; ledc_channel.hpoint = 0; }; ledc_channel_config(&ledc_channel); @@ -65,7 +68,7 @@ namespace lgfx #else ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; #endif - ledc_timer.duty_resolution = (ledc_timer_bit_t)8; // resolution of PWM duty + ledc_timer.duty_resolution = (ledc_timer_bit_t)PWM_BITS; // resolution of PWM duty ledc_timer.freq_hz = _cfg.freq; // frequency of PWM signal ledc_timer.timer_num = ledc_channel.timer_sel; // timer index }; @@ -80,8 +83,17 @@ namespace lgfx void Light_PWM::setBrightness(uint8_t brightness) { - if (_cfg.invert) brightness = ~brightness; - uint32_t duty = brightness + (brightness >> 7); + uint32_t duty = 0; + if (brightness) + { + uint_fast16_t ofs = _cfg.offset; + if (ofs) { ofs = ofs * 259 >> 8; } + duty = brightness * (257 - ofs); + duty += ofs * 255; + duty += 1 << (15 - PWM_BITS); + duty >>= 16 - PWM_BITS; + } + if (_cfg.invert) duty = (1 << PWM_BITS) - duty; #if defined ( ARDUINO ) ledcWrite(_cfg.pwm_channel, duty); diff --git a/src/lgfx/v1/platforms/esp32/Light_PWM.hpp b/src/lgfx/v1/platforms/esp32/Light_PWM.hpp index 8088a767..bb2ed895 100644 --- a/src/lgfx/v1/platforms/esp32/Light_PWM.hpp +++ b/src/lgfx/v1/platforms/esp32/Light_PWM.hpp @@ -32,7 +32,7 @@ namespace lgfx { uint32_t freq = 1200; int16_t pin_bl = -1; - + uint8_t offset = 0; uint8_t pwm_channel = 7; bool invert = false; diff --git a/src/lgfx/v1/platforms/esp32/Panel_CVBS.cpp b/src/lgfx/v1/platforms/esp32/Panel_CVBS.cpp index bff093ce..c040c3b2 100644 --- a/src/lgfx/v1/platforms/esp32/Panel_CVBS.cpp +++ b/src/lgfx/v1/platforms/esp32/Panel_CVBS.cpp @@ -93,7 +93,7 @@ namespace lgfx _push_idx = 0; _using_idx = cache_num - 1; prev_index = 0; - if ((uint32_t)task_pinned_core >= portNUM_PROCESSORS) + if (task_pinned_core >= portNUM_PROCESSORS) { task_pinned_core = (xPortGetCoreID() + 1) % portNUM_PROCESSORS; } diff --git a/src/lgfx/v1/platforms/esp32/Panel_CVBS.hpp b/src/lgfx/v1/platforms/esp32/Panel_CVBS.hpp index 64778551..e1906d6b 100644 --- a/src/lgfx/v1/platforms/esp32/Panel_CVBS.hpp +++ b/src/lgfx/v1/platforms/esp32/Panel_CVBS.hpp @@ -19,8 +19,6 @@ Original Source: #include "../../panel/Panel_FrameBufferBase.hpp" -#include - namespace lgfx { inline namespace v1 @@ -61,10 +59,10 @@ namespace lgfx uint8_t use_psram = 0; /// background PSRAM read task priority - UBaseType_t task_priority = 25; + uint8_t task_priority = 25; /// background PSRAM read task pinned core. (APP_CPU_NUM or PRO_CPU_NUM) - BaseType_t task_pinned_core = -1; + uint8_t task_pinned_core = -1; }; color_depth_t setColorDepth(color_depth_t) override; diff --git a/src/lgfx/v1/platforms/esp32/common.cpp b/src/lgfx/v1/platforms/esp32/common.cpp index 9be2387a..1ed66a3f 100644 --- a/src/lgfx/v1/platforms/esp32/common.cpp +++ b/src/lgfx/v1/platforms/esp32/common.cpp @@ -37,11 +37,15 @@ Original Source: #include #include #include -#include - #include #include +#include + +#if __has_include () +#include +#endif + #if __has_include () #include #else @@ -52,7 +56,14 @@ Original Source: #include #endif +#ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT +#define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0 +#endif + #if defined (ESP_IDF_VERSION_VAL) + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + #include + #endif #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 4, 0) #if defined (ESP_ARDUINO_VERSION_VAL) @@ -87,15 +98,23 @@ Original Source: #if defined (SOC_GDMA_SUPPORTED) // for C3/S3 #include + #include // S3とC3で同じレジスタに異なる定義名がついているため、ここで統一; #if !defined (DMA_OUT_PERI_SEL_CH0_REG) #define DMA_OUT_PERI_SEL_CH0_REG GDMA_OUT_PERI_SEL_CH0_REG #endif + #if !defined (DMA_IN_PERI_SEL_CH0_REG) + #define DMA_IN_PERI_SEL_CH0_REG GDMA_IN_PERI_SEL_CH0_REG + #endif #endif #if defined ( ARDUINO ) - #include - #include + #if __has_include () + #include + #endif + #if __has_include () + #include + #endif #endif namespace lgfx @@ -194,7 +213,7 @@ namespace lgfx for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; ++i) { // ESP_LOGD("DBG","GDMA.channel:%d peri_sel:%d", i, GDMA.channel[i].out.peri_sel.sel); - if ((*reg(DMA_OUT_PERI_SEL_CH0_REG + i * 0xC0) & 0x3F) == peripheral_select) + if ((*reg(DMA_OUT_PERI_SEL_CH0_REG + i * sizeof(GDMA.channel[0])) & 0x3F) == peripheral_select) { // ESP_LOGD("DBG","GDMA.channel:%d hit", i); return i; @@ -204,46 +223,195 @@ namespace lgfx return -1; } + int32_t search_dma_in_ch(int peripheral_select) + { +#if defined ( SOC_GDMA_SUPPORTED ) // for ESP32S3 / ESP32C3 + // ESP32C3: SPI2==0 + // ESP32S3: SPI2==0 / SPI3==1 + // SOC_GDMA_TRIG_PERIPH_SPI3 + // SOC_GDMA_TRIG_PERIPH_LCD0 + // GDMAペリフェラルレジスタの配列を順に調べてペリフェラル番号が一致するDMAチャンネルを特定する; + for (int i = 0; i < SOC_GDMA_PAIRS_PER_GROUP; ++i) + { +// ESP_LOGD("DBG","GDMA.channel:%d peri_sel:%d", i, GDMA.channel[i].out.peri_sel.sel); + if ((*reg(DMA_IN_PERI_SEL_CH0_REG + i * sizeof(GDMA.channel[0])) & 0x3F) == peripheral_select) + { +// ESP_LOGD("DBG","GDMA.channel:%d hit", i); + return i; + } + } +#endif + return -1; + } + + void debug_memory_dump(const void* src, size_t len) + { + auto s = (const uint32_t*)src; + do + { + printf("0x%08x = 0x%08x\n", (int)s, (int)s[0]); + ++s; + len -= 4; + } while (len > 0); + } + //---------------------------------------------------------------------------- void pinMode(int_fast16_t pin, pin_mode_t mode) { - if (pin < 0) return; + auto gpio_num = (gpio_num_t)pin; + if ((size_t)gpio_num >= GPIO_NUM_MAX) return; - gpio_set_direction((gpio_num_t)pin, GPIO_MODE_DISABLE); -#if defined (ARDUINO) - int m; - switch (mode) + /// GPIO OUTPUT enの場合はGPIO_ENABLE_W1TS, disの場合はGPIO_ENABLE_W1TCの該当ビットを立てる。 + /// レジスタのアドレスをテーブル化しておき、演算で対象レジスタを切り替える。 + static constexpr volatile uint32_t* gpio_en_regs[] = { - case pin_mode_t::output: m = OUTPUT; break; - default: - case pin_mode_t::input: m = INPUT; break; - case pin_mode_t::input_pullup: m = INPUT_PULLUP; break; - case pin_mode_t::input_pulldown: m = INPUT_PULLDOWN; break; - } - ::pinMode(pin, m); -#else + (volatile uint32_t*)GPIO_ENABLE_W1TC_REG, + (volatile uint32_t*)GPIO_ENABLE_W1TS_REG, +#if defined ( GPIO_ENABLE1_W1TC_REG ) + (volatile uint32_t*)GPIO_ENABLE1_W1TC_REG, + (volatile uint32_t*)GPIO_ENABLE1_W1TS_REG, +#endif + }; + /// pin番号が32未満かどうかで分岐する。 bit0は OUTPUT enか否かで切替。 + auto gpio_en_reg = gpio_en_regs[((pin >> 5) << 1) + (mode == pin_mode_t::output ? 1 : 0)]; + *gpio_en_reg = 1u << (pin & 31); + + auto io_mux_reg = (volatile uint32_t*)(GPIO_PIN_MUX_REG[pin]); + auto io_mux_val = *io_mux_reg; // & ~(FUN_PU_M | FUN_PD_M | SLP_PU_M | SLP_PD_M | MCU_SEL_M); #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED - if (rtc_gpio_is_valid_gpio((gpio_num_t)pin)) rtc_gpio_deinit((gpio_num_t)pin); + if (!SOC_GPIO_SUPPORT_RTC_INDEPENDENT && rtc_gpio_is_valid_gpio(gpio_num)) { + rtc_gpio_deinit(gpio_num); + if (mode == pin_mode_t::input_pulldown) + { rtc_gpio_pulldown_en((gpio_num_t)pin); } + else + { rtc_gpio_pulldown_dis((gpio_num_t)pin); } + + if (mode == pin_mode_t::input_pullup) + { rtc_gpio_pullup_en((gpio_num_t)pin); } + else + { rtc_gpio_pullup_dis((gpio_num_t)pin); } + } + else #endif - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.pin_bit_mask = (std::uint64_t)1 << pin; - switch (mode) { - case pin_mode_t::output: - io_conf.mode = GPIO_MODE_OUTPUT; - break; - default: - io_conf.mode = GPIO_MODE_INPUT; - break; + io_mux_val &= ~(FUN_PU_M | FUN_PD_M | SLP_PU_M | SLP_PD_M); + switch (mode) { + case pin_mode_t::input_pullup: io_mux_val |= FUN_PU_M | SLP_PU_M; break; + case pin_mode_t::input_pulldown: io_mux_val |= FUN_PD_M | SLP_PD_M; break; + default: break; + } + } + io_mux_val &= ~(MCU_SEL_M); + io_mux_val |= FUN_IE_M | (PIN_FUNC_GPIO << MCU_SEL_S); + + *io_mux_reg = io_mux_val; + + GPIO.pin[pin].pad_driver = 0; // 1 = OpenDrain / 0 = normal output + GPIO.func_out_sel_cfg[pin].func_sel = SIG_GPIO_OUT_IDX; + } + +//---------------------------------------------------------------------------- + + namespace gpio + { + pin_backup_t::pin_backup_t(int pin_num) + : _pin_num { static_cast(pin_num) } + { + backup(); + } + + void pin_backup_t::backup(void) + { + auto pin_num = (size_t)_pin_num; + if (pin_num < GPIO_NUM_MAX) + { + _io_mux_gpio_reg = *reinterpret_cast(GPIO_PIN_MUX_REG[pin_num]); + _gpio_pin_reg = *reinterpret_cast(GPIO_PIN0_REG + (pin_num * 4)); + _gpio_func_out_reg = *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (pin_num * 4)); +#if defined ( GPIO_ENABLE1_REG ) + _gpio_enable = *reinterpret_cast(((_pin_num & 32) ? GPIO_ENABLE1_REG : GPIO_ENABLE_REG)) & (1 << (_pin_num & 31)); +#else + _gpio_enable = *reinterpret_cast(GPIO_ENABLE_REG) & (1 << (_pin_num & 31)); +#endif + } } - io_conf.mode = (mode == pin_mode_t::output) ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT; - io_conf.pull_down_en = (mode == pin_mode_t::input_pulldown) ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = (mode == pin_mode_t::input_pullup ) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); + + void pin_backup_t::restore(void) + { + auto pin_num = (size_t)_pin_num; + if (pin_num < GPIO_NUM_MAX) + { + // ESP_LOGD("DEBUG","restore pin:%d ", _pin_num); + // ESP_LOGD("DEBUG","restore IO_MUX_GPIO0_REG :%08x -> %08x ", *reinterpret_cast(GPIO_PIN_MUX_REG[_pin_num] ), _io_mux_gpio_reg ); + // ESP_LOGD("DEBUG","restore GPIO_PIN0_REG :%08x -> %08x ", *reinterpret_cast(GPIO_PIN0_REG + (_pin_num * 4)), _gpio_pin_reg ); + // ESP_LOGD("DEBUG","restore GPIO_FUNC0_OUT_SEL_CFG_REG:%08x -> %08x ", *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (_pin_num * 4)), _gpio_func_out_reg ); + *reinterpret_cast(GPIO_PIN_MUX_REG[_pin_num]) = _io_mux_gpio_reg; + *reinterpret_cast(GPIO_PIN0_REG + (_pin_num * 4)) = _gpio_pin_reg; + *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (_pin_num * 4)) = _gpio_func_out_reg; +#if defined ( GPIO_ENABLE1_REG ) + auto gpio_enable_reg = reinterpret_cast(((_pin_num & 32) ? GPIO_ENABLE1_REG : GPIO_ENABLE_REG)); +#else + auto gpio_enable_reg = reinterpret_cast(GPIO_ENABLE_REG); #endif + + uint32_t pin_mask = 1 << (_pin_num & 31); + uint32_t val = *gpio_enable_reg; + // ESP_LOGD("DEBUG","restore GPIO_ENABLE_REG:%08x", *gpio_enable_reg); + if (_gpio_enable) + { + val |= pin_mask; + } + else + { + val &= ~pin_mask; + } + *gpio_enable_reg = val; + // ESP_LOGD("DEBUG","restore GPIO_ENABLE_REG:%08x", *gpio_enable_reg); + } + } + + bool command(command_t cmd, uint8_t val) + { + bool res = false; + switch (cmd) + { + case command_read: res = gpio_in(val); break; + case command_write_low: gpio_lo(val); break; + case command_write_high: gpio_hi(val); break; + case command_delay: delay(val); break; + default: + if ((cmd >> 2) == (command_mode_output >> 2)) { + pin_mode_t mode = pin_mode_t::output; + switch (cmd) + { + case command_mode_input: mode = pin_mode_t::input; break; + case command_mode_input_pulldown: mode = pin_mode_t::input_pulldown; break; + case command_mode_input_pullup: mode = pin_mode_t::input_pullup; break; + default: break; + } + pinMode(val, mode); + } + break; + } + return res; + } + + uint32_t command(const uint8_t* cmd_list) + { + uint32_t result = 0; + while (cmd_list[0] != command_end) + { + auto cmd = (command_t)cmd_list[0]; + bool res = command(cmd, cmd_list[1]); + if (cmd == command_read) { + result = (result << 1) + res; + } + cmd_list += 2; + } + return result; + } } //---------------------------------------------------------------------------- @@ -286,7 +454,7 @@ namespace lgfx if (spi_sclk >= 0) { gpio_lo(spi_sclk); // ここでLOWにしておくことで、pinMode変更によるHIGHパルスが出力されるのを防止する (CSなしパネル対策); } -#if defined (ARDUINO) // Arduino ESP32 +#if defined (ARDUINO) && __has_include () // Arduino ESP32 if (spi_host == default_spi_host) { SPI.end(); @@ -311,27 +479,20 @@ namespace lgfx buscfg.max_transfer_sz = 1; buscfg.flags = SPICOMMON_BUSFLAG_MASTER; buscfg.intr_flags = 0; - +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)) + buscfg.isr_cpu_id = INTR_CPU_ID_AUTO; +#endif if (ESP_OK != spi_bus_initialize(static_cast(spi_host), &buscfg, dma_channel)) { ESP_LOGW("LGFX", "Failed to spi_bus_initialize. "); } - spi_device_interface_config_t devcfg = { - .command_bits = 0, - .address_bits = 0, - .dummy_bits = 0, - .mode = 0, - .duty_cycle_pos = 0, - .cs_ena_pretrans = 0, - .cs_ena_posttrans = 0, - .clock_speed_hz = (int)getApbFrequency()>>1, - .input_delay_ns = 0, - .spics_io_num = -1, - .flags = SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX, - .queue_size = 1, - .pre_cb = nullptr, - .post_cb = nullptr}; + spi_device_interface_config_t devcfg; + memset(&devcfg, 0, sizeof(devcfg)); + devcfg.clock_speed_hz = 10000000; + devcfg.spics_io_num = -1; + devcfg.flags = SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX; + devcfg.queue_size = 1; if (ESP_OK != spi_bus_add_device(static_cast(spi_host), &devcfg, &_spi_dev_handle[spi_host])) { ESP_LOGW("LGFX", "Failed to spi_bus_add_device. "); } @@ -352,7 +513,7 @@ namespace lgfx void release(int spi_host) { //ESP_LOGI("LGFX","spi::release"); -#if defined (ARDUINO) // Arduino ESP32 +#if defined (ARDUINO) && __has_include () // Arduino ESP32 if (_spi_handle[spi_host] != nullptr) { if (spi_host == default_spi_host) @@ -589,7 +750,7 @@ namespace lgfx { pin_sda = sda; pin_scl = scl; -#if defined ( ARDUINO ) +#if defined ( ARDUINO ) && __has_include () #if defined ( ESP_IDF_VERSION_VAL ) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) #if defined ARDUINO_ESP32_GIT_VER @@ -643,7 +804,11 @@ namespace lgfx cmd_val |= (1 << 10); // ACK_VALUE (set NACK) } #if defined (CONFIG_IDF_TARGET_ESP32S3) + #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 2) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)) + (&dev->comd[0])[index].val = cmd_val; + #else (&dev->comd0)[index].val = cmd_val; + #endif #else dev->command[index].val = cmd_val; #endif @@ -710,6 +875,7 @@ namespace lgfx auto dev = getDev(i2c_port); typeof(dev->int_raw) int_raw; static constexpr uint32_t intmask = I2C_ACK_ERR_INT_RAW_M | I2C_END_DETECT_INT_RAW_M | I2C_ARBITRATION_LOST_INT_RAW_M; + if (i2c_context[i2c_port].wait_ack_stage) { int_raw.val = dev->int_raw.val; @@ -795,7 +961,7 @@ namespace lgfx if (i2c_context[i2c_port].initialized) { i2c_context[i2c_port].initialized = false; -#if defined ( ARDUINO ) && defined ( ESP_IDF_VERSION_VAL ) +#if defined ( ARDUINO ) && __has_include () && defined ( ESP_IDF_VERSION_VAL ) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) #if defined ARDUINO_ESP32_GIT_VER #if ARDUINO_ESP32_GIT_VER != 0x44c11981 @@ -838,7 +1004,7 @@ namespace lgfx release(i2c_port).has_value(); i2c_context[i2c_port].pin_scl = (gpio_num_t)pin_scl; i2c_context[i2c_port].pin_sda = (gpio_num_t)pin_sda; -#if defined ( ARDUINO ) +#if defined ( ARDUINO ) && __has_include () #if defined ( ESP_IDF_VERSION_VAL ) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 3, 0) #define USE_TWOWIRE_SETPINS @@ -866,7 +1032,7 @@ namespace lgfx release(i2c_port); } -#if defined ( ARDUINO ) +#if defined ( ARDUINO ) && __has_include () auto twowire = ((i2c_port == 1) ? &Wire1 : &Wire); #if defined ( USE_TWOWIRE_SETPINS ) twowire->begin(); @@ -1159,6 +1325,7 @@ namespace lgfx static constexpr uint32_t intmask = I2C_ACK_ERR_INT_RAW_M | I2C_TIME_OUT_INT_RAW_M | I2C_END_DETECT_INT_RAW_M | I2C_ARBITRATION_LOST_INT_RAW_M; auto fifo_addr = getFifoAddr(i2c_port); auto dev = getDev(i2c_port); + size_t len = 0; #if defined ( CONFIG_IDF_TARGET_ESP32S3 ) uint32_t us_limit = ((dev->scl_high_period.scl_high_period + dev->scl_high_period.scl_wait_high_period + dev->scl_low_period.scl_low_period) << 1); @@ -1167,11 +1334,8 @@ namespace lgfx #else uint32_t us_limit = (dev->scl_high_period.period + dev->scl_low_period.period); #endif - us_limit += 1024; do { - len = ((length-1) & 63) + 1; - length -= len; res = i2c_wait(i2c_port); if (res.has_error()) { @@ -1179,31 +1343,33 @@ namespace lgfx break; } - int cmdidx = 0; - if (length == 0 && last_nack) { - if (len > 1) { - i2c_set_cmd(dev, cmdidx++, i2c_cmd_read, len - 1); - } - i2c_set_cmd(dev, cmdidx++, i2c_cmd_read, 1, true); - } - else - { - i2c_set_cmd(dev, cmdidx++, i2c_cmd_read, len); - } - i2c_set_cmd(dev, cmdidx, i2c_cmd_end, 0); + len = length < 64 ? length : 64; + if (length == len && last_nack && len > 1) { --len; } + length -= len; + i2c_set_cmd(dev, 0, i2c_cmd_read, len, last_nack && length == 0); + i2c_set_cmd(dev, 1, i2c_cmd_end, 0); updateDev(dev); dev->ctr.trans_start = 1; dev->int_clr.val = intmask; + + uint32_t us = lgfx::micros(); + taskYIELD(); + #if defined ( CONFIG_IDF_TARGET_ESP32S3 ) delayMicroseconds(us_limit >> 2); /// このウェイトを外すと受信失敗するケースがある; #endif + auto delayus = (us_limit + 7) >> 3; + us = lgfx::micros() - us; + if (us < delayus) { + delayMicroseconds(delayus - us); + } do { if (0 == getRxFifoCount(dev)) { uint32_t us = lgfx::micros(); - do { taskYIELD(); } while (0 == getRxFifoCount(dev) && !(dev->int_raw.val & intmask) && ((lgfx::micros() - us) <= us_limit)); + do { taskYIELD(); } while (0 == getRxFifoCount(dev) && !(dev->int_raw.val & intmask) && ((lgfx::micros() - us) <= us_limit + 1024)); if (0 == getRxFifoCount(dev)) { i2c_stop(i2c_port); diff --git a/src/lgfx/v1/platforms/esp32/common.hpp b/src/lgfx/v1/platforms/esp32/common.hpp index 5ca9789f..2e7dba51 100644 --- a/src/lgfx/v1/platforms/esp32/common.hpp +++ b/src/lgfx/v1/platforms/esp32/common.hpp @@ -126,6 +126,9 @@ namespace lgfx // Find GDMA assigned to a peripheral; int32_t search_dma_out_ch(int peripheral_select); + int32_t search_dma_in_ch(int peripheral_select); + + void debug_memory_dump(const void* src, size_t len); //---------------------------------------------------------------------------- @@ -226,6 +229,41 @@ namespace lgfx #endif +//---------------------------------------------------------------------------- + + namespace gpio + { + class pin_backup_t + { + public: + pin_backup_t(int pin_num); + void backup(void); + void restore(void); + + private: + uint32_t _io_mux_gpio_reg; + uint32_t _gpio_pin_reg; + uint32_t _gpio_func_out_reg; + gpio_num_t _pin_num; + bool _gpio_enable; + }; + + enum command_t : uint8_t + { + command_end = 0, // コマンド終了 + command_read, // [1]=GPIO番号 1bit読みとる + command_write_low, // [1]=GPIO番号 LOW出力 + command_write_high, // [1]=GPIO番号 HIGH出力 + command_mode_output, // [1]=GPIO番号 outputモードに変更する + command_mode_input, // [1]=GPIO番号 inputモードに変更する + command_mode_input_pulldown, // [1]=GPIO番号 input pulldownモードに変更する + command_mode_input_pullup, // [1]=GPIO番号 input pullupモードに変更する + command_delay, // [1]=停止する時間[ミリ秒] + }; + bool command(command_t cmd, uint8_t pin); + uint32_t command(const uint8_t* cmd_list); + } + //---------------------------------------------------------------------------- namespace spi diff --git a/src/lgfx/v1/platforms/esp32s3/Panel_RGB.cpp b/src/lgfx/v1/platforms/esp32s3/Panel_RGB.cpp index 39bbc74c..b09a0857 100644 --- a/src/lgfx/v1/platforms/esp32s3/Panel_RGB.cpp +++ b/src/lgfx/v1/platforms/esp32s3/Panel_RGB.cpp @@ -153,28 +153,6 @@ namespace lgfx } while (mask >>= 1); } - class _pin_backup_t - { - public: - _pin_backup_t(gpio_num_t pin_num) - : _io_mux_gpio_reg { *reinterpret_cast(GPIO_PIN_MUX_REG[pin_num]) } - , _gpio_func_out_reg { *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (pin_num * 4)) } - , _pin_num { pin_num } - {} - - void restore(void) const - { - if ((uint32_t)_pin_num < GPIO_NUM_MAX) { - *reinterpret_cast(GPIO_PIN_MUX_REG[_pin_num]) = _io_mux_gpio_reg; - *reinterpret_cast(GPIO_FUNC0_OUT_SEL_CFG_REG + (_pin_num * 4)) = _gpio_func_out_reg; - } - } - - private: - uint32_t _io_mux_gpio_reg; - uint32_t _gpio_func_out_reg; - gpio_num_t _pin_num; - }; void Panel_RGB::writeCommand(uint32_t data, uint_fast8_t len) { @@ -289,7 +267,8 @@ namespace lgfx int32_t pin_sclk = _config_detail.pin_sclk; if (pin_mosi >= 0 && pin_sclk >= 0) { - _pin_backup_t backup_pins[] = { (gpio_num_t)pin_mosi, (gpio_num_t)pin_sclk }; + lgfx::gpio::pin_backup_t backup_pins[] = { (gpio_num_t)pin_mosi, (gpio_num_t)pin_sclk }; + lgfx::gpio_lo(pin_mosi); lgfx::pinMode(pin_mosi, pin_mode_t::output); lgfx::gpio_lo(pin_sclk); @@ -472,7 +451,7 @@ namespace lgfx int32_t pin_sclk = _config_detail.pin_sclk; if (pin_mosi >= 0 && pin_sclk >= 0) { - _pin_backup_t backup_pins[] = { (gpio_num_t)pin_mosi, (gpio_num_t)pin_sclk }; + lgfx::gpio::pin_backup_t backup_pins[] = { (gpio_num_t)pin_mosi, (gpio_num_t)pin_sclk }; lgfx::gpio_lo(pin_mosi); lgfx::pinMode(pin_mosi, pin_mode_t::output); lgfx::gpio_lo(pin_sclk); diff --git a/src/lgfx/v1/platforms/sdl/Bus_I2C.hpp b/src/lgfx/v1/platforms/sdl/Bus_I2C.hpp new file mode 100644 index 00000000..2662b455 --- /dev/null +++ b/src/lgfx/v1/platforms/sdl/Bus_I2C.hpp @@ -0,0 +1,58 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#pragma once + +#include "../../Bus.hpp" +#include "../common.hpp" + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + class Bus_I2C : public Bus_NULL + { + public: + struct config_t + { + uint32_t freq_write = 400000; + uint32_t freq_read = 400000; + int16_t pin_scl = 22; + int16_t pin_sda = 21; + uint8_t i2c_port = 0; + uint8_t i2c_addr = 0x3C; + uint32_t prefix_cmd = 0x00; + uint32_t prefix_data = 0x40; + uint32_t prefix_len = 1; + }; + + const config_t& config(void) const { return _cfg; } + + void config(const config_t& config); + + bus_type_t busType(void) const override { return bus_type_t::bus_i2c; } + + protected: + + config_t _cfg; + }; + +//---------------------------------------------------------------------------- + } +} diff --git a/src/lgfx/v1/platforms/sdl/Panel_sdl.cpp b/src/lgfx/v1/platforms/sdl/Panel_sdl.cpp index ba0ea1ce..23142456 100644 --- a/src/lgfx/v1/platforms/sdl/Panel_sdl.cpp +++ b/src/lgfx/v1/platforms/sdl/Panel_sdl.cpp @@ -18,11 +18,12 @@ Original Source: Porting for SDL: [imliubo](https://github.com/imliubo) /----------------------------------------------------------------------------*/ -#if defined ( LGFX_SDL ) - #include "Panel_sdl.hpp" +#if defined ( SDL_h_ ) + #include "../common.hpp" +#include "../../misc/common_function.hpp" #include "../../Bus.hpp" #include @@ -31,6 +32,12 @@ namespace lgfx { inline namespace v1 { + static SDL_semaphore *_update_in_semaphore = nullptr; + static SDL_semaphore *_update_out_semaphore = nullptr; + volatile static uint32_t _in_step_exec = 0; + volatile static uint32_t _msec_step_exec = 512; + static bool _inited = false; + static bool _all_close = false; static std::list _list_monitor; @@ -43,118 +50,27 @@ namespace lgfx return nullptr; } //---------------------------------------------------------------------------- - static void memset_multi(uint8_t* buf, uint32_t c, size_t size, size_t length) - { - if (size == 1 || ((c & 0xFF) == ((c >> 8) & 0xFF) && (size == 2 || ((c & 0xFF) == ((c >> 16) & 0xFF))))) - { - memset(buf, c, size * length); - return; - } - - size_t l = length; - if (l & ~0xF) - { - while ((l >>= 1) & ~0xF); - ++l; - } - size_t len = l * size; - length = (length * size) - len; - uint8_t* dst = buf; - if (size == 2) { - do { // 2byte speed tweak - *(uint16_t*)dst = c; - dst += 2; - } while (--l); - } else { - do { - size_t i = 0; - do { - *dst++ = *(((uint8_t*)&c) + i); - } while (++i != size); - } while (--l); - } - if (!length) return; - while (length > len) { - memcpy(dst, buf, len); - dst += len; - length -= len; - len <<= 1; - } - if (length) { - memcpy(dst, buf, length); - } - } - int quit_filter(void * userdata, SDL_Event * event) + void Panel_sdl::_event_proc(void) { - Panel_sdl *sdl = (Panel_sdl *)userdata; - - if(event->type == SDL_WINDOWEVENT) { - if(event->window.event == SDL_WINDOWEVENT_CLOSE) { - sdl->sdl_quit(); - } - } - else if(event->type == SDL_QUIT) { - sdl->sdl_quit(); - } - - return 1; - } - - void Panel_sdl::sdl_update_handler(void) - { - SDL_Delay(1); - for (auto& m : _list_monitor) - { - if (m->renderer == nullptr) - { - m->panel->sdl_create(m); - } - sdl_update(m); - } - } - - void Panel_sdl::sdl_event_handler(void) - { - sdl_update_handler(); - SDL_Event event; while (SDL_PollEvent(&event)) { - if (event.type == SDL_KEYDOWN) + if ((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP)) { + int gpio = -1; switch (event.key.keysym.sym) { /// M5StackのBtnA~BtnCのエミュレート; - case SDLK_LEFT: - gpio_lo(39); - break; - case SDLK_DOWN: - gpio_lo(38); - break; - case SDLK_RIGHT: - gpio_lo(37); - break; - case SDLK_UP: - gpio_lo(36); - break; + case SDLK_LEFT: gpio = 39; break; + case SDLK_DOWN: gpio = 38; break; + case SDLK_RIGHT: gpio = 37; break; + case SDLK_UP: gpio = 36; break; + default: continue; } - } - else if (event.type == SDL_KEYUP) - { /// M5StackのBtnA~BtnCのエミュレート; - switch (event.key.keysym.sym) - { - case SDLK_LEFT: - gpio_hi(39); - break; - case SDLK_DOWN: - gpio_hi(38); - break; - case SDLK_RIGHT: - gpio_hi(37); - break; - case SDLK_UP: - gpio_hi(36); - break; + if (event.type == SDL_KEYDOWN) { + gpio_lo(gpio); + } else { + gpio_hi(gpio); } } else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEMOTION) @@ -162,7 +78,11 @@ namespace lgfx auto mon = getMonitorByWindowID(event.button.windowID); if (mon != nullptr) { - SDL_GetMouseState(&mon->touch_x, &mon->touch_y); + int x, y, w, h; + SDL_GetWindowSize(mon->window, &w, &h); + SDL_GetMouseState(&x, &y); + mon->touch_x = x * mon->panel->config().panel_width / w; + mon->touch_y = y * mon->panel->config().panel_height / h; if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT) { mon->touched = true; @@ -173,514 +93,375 @@ namespace lgfx } } } - else if (event.type == SDL_WINDOWEVENT) { - - switch((&event)->window.event) { - #if SDL_VERSION_ATLEAST(2, 0, 5) - case SDL_WINDOWEVENT_TAKE_FOCUS: - #endif - case SDL_WINDOWEVENT_EXPOSED: - break; - default: - break; + else + if (event.type == SDL_WINDOWEVENT + || event.type == SDL_QUIT) { + auto monitor = getMonitorByWindowID(event.window.windowID); + if (monitor) { + if (event.window.event == SDL_WINDOWEVENT_RESIZED) { + monitor->panel->sdl_invalidate(); + } + else + if (event.window.event == SDL_WINDOWEVENT_CLOSE) { + monitor->closing = true; + } } } } } - void Panel_sdl::setScaling(uint_fast8_t scaling_x, uint_fast8_t scaling_y) + /// デバッガでステップ実行されていることを検出するスレッド用関数。 + static int detectDebugger(bool* running) { - monitor.scaling_x = scaling_x; - monitor.scaling_y = scaling_y; + uint32_t prev_ms = SDL_GetTicks(); + do { + SDL_Delay(1); + uint32_t ms = SDL_GetTicks(); + /// 時間間隔が広すぎる場合はステップ実行中 (ブレークポイントで止まった)と判断する。 + /// また、解除されたと判断した後も1023msecほど状態を維持する。 + if (ms - prev_ms > 64) { _in_step_exec = _msec_step_exec; } + else if (_in_step_exec) { --_in_step_exec; } + prev_ms = ms; + } while (*running); + return 0; } - Panel_sdl::~Panel_sdl(void) + void Panel_sdl::_update_proc(void) { - _list_monitor.remove(&monitor); + for (auto it = _list_monitor.begin(); it != _list_monitor.end(); ) + { + if ((*it)->closing) { + SDL_DestroyTexture((*it)->texture); + SDL_DestroyRenderer((*it)->renderer); + SDL_DestroyWindow((*it)->window); + _list_monitor.erase(it++); + if (_list_monitor.empty()) { + _all_close = true; + return; + } + continue; + } + (*it)->panel->sdl_update(); + ++it; + } } - Panel_sdl::Panel_sdl(void) : Panel_Device() + int Panel_sdl::setup(void) { - monitor.panel = this; - static bool inited = false; - if (inited) { return; } - for (size_t pin = 0; pin < EMULATED_GPIO_MAX; ++pin) { gpio_hi(pin); } + if (_inited) return 1; + _inited = true; + + SDL_CreateThread((SDL_ThreadFunction)detectDebugger, "dbg", &_inited); + _update_in_semaphore = SDL_CreateSemaphore(0); + _update_out_semaphore = SDL_CreateSemaphore(0); + for (size_t pin = 0; pin < EMULATED_GPIO_MAX; ++pin) { gpio_hi(pin); } /*Initialize the SDL*/ SDL_Init(SDL_INIT_VIDEO); - - SDL_SetEventFilter(quit_filter, this); - SDL_StartTextInput(); + + // SDL_SetThreadPriority(SDL_ThreadPriority::SDL_THREAD_PRIORITY_HIGH); + return 0; } - bool Panel_sdl::init(bool use_reset) + int Panel_sdl::loop(void) { - uint32_t len = _cfg.panel_width * _cfg.panel_height * sizeof(bgr888_t) + 16; - monitor.tft_fb = (bgr888_t*)malloc(len); - memset(monitor.tft_fb, 0x44, len); + if (!_inited) return 1; - _list_monitor.push_back(&monitor); + _event_proc(); + SDL_SemWaitTimeout(_update_in_semaphore, 1); + _update_proc(); + _event_proc(); + if (SDL_SemValue(_update_out_semaphore) == 0) + { + SDL_SemPost(_update_out_semaphore); + } - return Panel_Device::init(use_reset); + return _all_close; } - color_depth_t Panel_sdl::setColorDepth(color_depth_t depth) + int Panel_sdl::close(void) { - _write_depth = color_depth_t::rgb888_3Byte; - _read_depth = color_depth_t::rgb888_3Byte; - return _write_depth; + if (!_inited) return 1; + _inited = false; + + SDL_StopTextInput(); + SDL_DestroySemaphore(_update_in_semaphore); + SDL_DestroySemaphore(_update_out_semaphore); + SDL_Quit(); + return 0; } - void Panel_sdl::setRotation(uint_fast8_t r) + int Panel_sdl::main(int(*fn)(bool*), uint32_t msec_step_exec) { - r &= 7; - _rotation = r; - _internal_rotation = ((r + _cfg.offset_rotation) & 3) | ((r & 4) ^ (_cfg.offset_rotation & 4)); + _msec_step_exec = msec_step_exec; - _width = _cfg.panel_width; - _height = _cfg.panel_height; - if (_internal_rotation & 1) std::swap(_width, _height); + /// SDLの準備 + if (0 != Panel_sdl::setup()) { return 1; } + + /// ユーザコード関数の動作・停止フラグ + bool running = true; + + /// ユーザコード関数を起動する + auto thread = SDL_CreateThread((SDL_ThreadFunction)fn, "fn", &running); + + /// 全部のウィンドウが閉じられるまでSDLのイベント・描画処理を継続 + while (0 == Panel_sdl::loop()) {}; + + /// ユーザコード関数を終了する + running = false; + SDL_WaitThread(thread, nullptr); + + /// SDLを終了する + return Panel_sdl::close(); } - void Panel_sdl::setWindow(uint_fast16_t xs, uint_fast16_t ys, uint_fast16_t xe, uint_fast16_t ye) + void Panel_sdl::setScaling(uint_fast8_t scaling_x, uint_fast8_t scaling_y) { - xs = std::max(0u, std::min(_width - 1, xs)); - xe = std::max(0u, std::min(_width - 1, xe)); - ys = std::max(0u, std::min(_height - 1, ys)); - ye = std::max(0u, std::min(_height - 1, ye)); - _xpos = xs; - _xs = xs; - _xe = xe; - _ypos = ys; - _ys = ys; - _ye = ye; + monitor.scaling_x = scaling_x; + monitor.scaling_y = scaling_y; } - void Panel_sdl::drawPixelPreclipped(uint_fast16_t x, uint_fast16_t y, uint32_t rawcolor) + Panel_sdl::~Panel_sdl(void) { - uint_fast8_t r = _internal_rotation; - if (r) - { - if ((1u << r) & 0b10010110) { y = _height - (y + 1); } - if (r & 2) { x = _width - (x + 1); } - if (r & 1) { std::swap(x, y); } - } - - size_t bw = _cfg.panel_width; - size_t index = x + y * bw; - { - auto img = &((bgr888_t*)monitor.tft_fb)[index]; - *img = rawcolor; - } + _list_monitor.remove(&monitor); + SDL_DestroyMutex(_sdl_mutex); } - void Panel_sdl::writeFillRectPreclipped(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, uint32_t rawcolor) + Panel_sdl::Panel_sdl(void) : Panel_FrameBufferBase() { - uint_fast8_t r = _internal_rotation; - if (r) - { - if ((1u << r) & 0b10010110) { y = _height - (y + h); } - if (r & 2) { x = _width - (x + w); } - if (r & 1) { std::swap(x, y); std::swap(w, h); } - } - - if (w > 1) - { - uint_fast8_t bytes = _write_bits >> 3; - uint_fast16_t bw = _cfg.panel_width; - auto* dst = &monitor.tft_fb[(x + y * bw)]; - auto* src = dst; - uint_fast16_t add_dst = bw; - uint_fast16_t len = w * bytes; - - if (w != bw) - { - dst += add_dst; - } - else - { - w *= h; - h = 1; - } - memset_multi((uint8_t*)src, rawcolor, bytes, w); - while (--h) - { - memcpy(dst, src, len); - dst += add_dst; - } - } - else - { - size_t bw = _cfg.panel_width; - size_t index = x + y * bw; - { - auto img = &((bgr888_t*)monitor.tft_fb)[index]; - do { *img = rawcolor; img += bw; } while (--h); - } - } + _sdl_mutex = SDL_CreateMutex(); + _auto_display = true; + monitor.panel = this; } - void Panel_sdl::writeBlock(uint32_t rawcolor, uint32_t length) + bool Panel_sdl::init(bool use_reset) { - do - { - uint32_t h = 1; - auto w = std::min(length, _xe + 1 - _xpos); - if (length >= (w << 1) && _xpos == _xs) - { - h = std::min(length / w, _ye + 1 - _ypos); - } - writeFillRectPreclipped(_xpos, _ypos, w, h, rawcolor); - if ((_xpos += w) <= _xe) return; - _xpos = _xs; - if (_ye < (_ypos += h)) { _ypos = _ys; } - length -= w * h; - } while (length); + initFrameBuffer(_cfg.panel_width * 4, _cfg.panel_height); + bool res = Panel_FrameBufferBase::init(use_reset); + + _list_monitor.push_back(&monitor); + + return res; } - void Panel_sdl::_rotate_pixelcopy(uint_fast16_t& x, uint_fast16_t& y, uint_fast16_t& w, uint_fast16_t& h, pixelcopy_t* param, uint32_t& nextx, uint32_t& nexty) + color_depth_t Panel_sdl::setColorDepth(color_depth_t depth) { - uint32_t addx = param->src_x32_add; - uint32_t addy = param->src_y32_add; - uint_fast8_t r = _internal_rotation; - uint_fast8_t bitr = 1u << r; - if (bitr & 0b10010110) // case 1:2:4:7: - { - param->src_y32 += nexty * (h - 1); - nexty = -(int32_t)nexty; - y = _height - (y + h); - } - if (r & 2) - { - param->src_x32 += addx * (w - 1); - param->src_y32 += addy * (w - 1); - addx = -(int32_t)addx; - addy = -(int32_t)addy; - x = _width - (x + w); - } - if (r & 1) - { - std::swap(x, y); - std::swap(w, h); - std::swap(nextx, addx); - std::swap(nexty, addy); + auto bits = depth & color_depth_t::bit_mask; + if (bits >= 16) { + depth = (bits > 16) + ? rgb888_3Byte + : rgb565_2Byte; + } else { + depth = (depth == color_depth_t::grayscale_8bit) + ? grayscale_8bit + : rgb332_1Byte; } - param->src_x32_add = addx; - param->src_y32_add = addy; + _write_depth = depth; + _read_depth = depth; + + return depth; } - void Panel_sdl::writePixels(pixelcopy_t* param, uint32_t length, bool use_dma) + Panel_sdl::lock_t::lock_t(Panel_sdl* parent) + : _parent { parent } { - uint_fast16_t xs = _xs; - uint_fast16_t xe = _xe; - uint_fast16_t ys = _ys; - uint_fast16_t ye = _ye; - uint_fast16_t x = _xpos; - uint_fast16_t y = _ypos; - const size_t bits = _write_bits; - auto k = _cfg.panel_width * bits >> 3; - - uint_fast8_t r = _internal_rotation; - if (!r) - { - uint_fast16_t linelength; - do { - linelength = std::min(xe - x + 1, length); - param->fp_copy(&monitor.tft_fb[y * k], x, x + linelength, param); - if ((x += linelength) > xe) - { - x = xs; - y = (y != ye) ? (y + 1) : ys; - } - } while (length -= linelength); - _xpos = x; - _ypos = y; - return; - } + SDL_LockMutex(parent->_sdl_mutex); + }; - int_fast16_t ax = 1; - int_fast16_t ay = 1; - if ((1u << r) & 0b10010110) { y = _height - (y + 1); ys = _height - (ys + 1); ye = _height - (ye + 1); ay = -1; } - if (r & 2) { x = _width - (x + 1); xs = _width - (xs + 1); xe = _width - (xe + 1); ax = -1; } - if (param->no_convert) - { - size_t bytes = _write_bits >> 3; - size_t xw = 1; - size_t yw = _cfg.panel_width; - if (r & 1) std::swap(xw, yw); - size_t idx = y * yw + x * xw; - auto data = (uint8_t*)param->src_data; - do - { - auto dst = &monitor.tft_fb[idx * bytes]; - size_t b = 0; - do - { - dst[b] = *data++; - } while (++b < bytes); - if (x != xe) - { - idx += xw * ax; - x += ax; - } - else - { - x = xs; - y = (y != ye) ? (y + ay) : ys; - idx = y * yw + x * xw; - } - } while (--length); - } - else + Panel_sdl::lock_t::~lock_t(void) + { + ++_parent->_modified_counter; + SDL_UnlockMutex(_parent->_sdl_mutex); + if (SDL_SemValue(_update_in_semaphore) < 2) { - if (r & 1) - { - do - { - param->fp_copy(&monitor.tft_fb[x * k], y, y + 1, param); - if (x != xe) - { - x += ax; - } - else - { - x = xs; - y = (y != ye) ? (y + ay) : ys; - } - } while (--length); - } - else - { - do - { - param->fp_copy(&monitor.tft_fb[y * k], x, x + 1, param); - if (x != xe) - { - x += ax; - } - else - { - x = xs; - y = (y != ye) ? (y + ay) : ys; - } - } while (--length); + SDL_SemPost(_update_in_semaphore); + if (!_in_step_exec) { + SDL_SemWaitTimeout(_update_out_semaphore, 1); } } - if ((1u << r) & 0b10010110) { y = _height - (y + 1); } - if (r & 2) { x = _width - (x + 1); } - _xpos = x; - _ypos = y; + }; + + void Panel_sdl::drawPixelPreclipped(uint_fast16_t x, uint_fast16_t y, uint32_t rawcolor) + { + lock_t lock(this); + Panel_FrameBufferBase::drawPixelPreclipped(x, y, rawcolor); } - void Panel_sdl::writeImage(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param, bool) + void Panel_sdl::writeFillRectPreclipped(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, uint32_t rawcolor) { - uint_fast8_t r = _internal_rotation; - if (r == 0 && param->transp == pixelcopy_t::NON_TRANSP && param->no_convert) - { - auto sx = param->src_x; - auto bits = param->src_bits; - - auto bw = _cfg.panel_width * bits >> 3; - auto dst = (uint8_t*)& monitor.tft_fb[_cfg.panel_width * y]; - auto sw = param->src_bitwidth * bits >> 3; - auto src = &((uint8_t*)param->src_data)[param->src_y * sw]; - if (sw == bw && this->_cfg.panel_width == w && sx == 0 && x == 0) - { - memcpy(dst, src, bw * h); - return; - } - y = 0; - dst += x * bits >> 3; - src += sx * bits >> 3; - w = w * bits >> 3; - do - { - memcpy(&dst[y * bw], &src[y * sw], w); - } while (++y != h); - return; - } + lock_t lock(this); + Panel_FrameBufferBase::writeFillRectPreclipped(x, y, w, h, rawcolor); + } - uint32_t nextx = 0; - uint32_t nexty = 1 << pixelcopy_t::FP_SCALE; - if (r) - { - _rotate_pixelcopy(x, y, w, h, param, nextx, nexty); - } - uint32_t sx32 = param->src_x32; - uint32_t sy32 = param->src_y32; + void Panel_sdl::writeBlock(uint32_t rawcolor, uint32_t length) + { +// lock_t lock(this); + Panel_FrameBufferBase::writeBlock(rawcolor, length); + } - y *= _cfg.panel_width; - do - { - int32_t pos = x + y; - int32_t end = pos + w; - while (end != (pos = param->fp_copy(monitor.tft_fb, pos, end, param)) - && end != (pos = param->fp_skip( pos, end, param))); - param->src_x32 = (sx32 += nextx); - param->src_y32 = (sy32 += nexty); - y += _cfg.panel_width; - } while (--h); + void Panel_sdl::writeImage(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param, bool use_dma) + { + lock_t lock(this); + Panel_FrameBufferBase::writeImage(x, y, w, h, param, use_dma); } void Panel_sdl::writeImageARGB(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param) { - uint32_t nextx = 0; - uint32_t nexty = 1 << pixelcopy_t::FP_SCALE; - if (_internal_rotation) - { - _rotate_pixelcopy(x, y, w, h, param, nextx, nexty); - } - uint32_t sx32 = param->src_x32; - uint32_t sy32 = param->src_y32; - - uint32_t pos = x + y * _cfg.panel_width; - uint32_t end = pos + w; - param->fp_copy(monitor.tft_fb, pos, end, param); - while (--h) - { - pos += _cfg.panel_width; - end = pos + w; - param->src_x32 = (sx32 += nextx); - param->src_y32 = (sy32 += nexty); - param->fp_copy(monitor.tft_fb, pos, end, param); - } + lock_t lock(this); + Panel_FrameBufferBase::writeImageARGB(x, y, w, h, param); } - void Panel_sdl::readRect(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, void* dst, pixelcopy_t* param) + void Panel_sdl::writePixels(pixelcopy_t* param, uint32_t len, bool use_dma) { - uint_fast8_t r = _internal_rotation; - if (0 == r && param->no_convert) - { - h += y; - auto bytes = _write_bits >> 3; - auto bw = _cfg.panel_width; - auto d = (uint8_t*)dst; - w *= bytes; - do { - memcpy(d, &monitor.tft_fb[(x + y * bw)], w); - d += w; - } while (++y != h); - } - else - { - param->src_bitwidth = _cfg.panel_width; - param->src_data = monitor.tft_fb; - uint32_t nextx = 0; - uint32_t nexty = 1 << pixelcopy_t::FP_SCALE; - if (r) - { - uint32_t addx = param->src_x32_add; - uint32_t addy = param->src_y32_add; - uint_fast8_t rb = 1 << r; - if (rb & 0b10010110) // case 1:2:4:7: - { - nexty = -(int32_t)nexty; - y = _height - (y + 1); - } - if (r & 2) - { - addx = -(int32_t)addx; - x = _width - (x + 1); - } - if ((r+1) & 2) - { - addy = -(int32_t)addy; - } - if (r & 1) - { - std::swap(x, y); - std::swap(addx, addy); - std::swap(nextx, nexty); - } - param->src_x32_add = addx; - param->src_y32_add = addy; - } - size_t dstindex = 0; - uint32_t x32 = x << pixelcopy_t::FP_SCALE; - uint32_t y32 = y << pixelcopy_t::FP_SCALE; - param->src_x32 = x32; - param->src_y32 = y32; - do - { - param->src_x32 = x32; - x32 += nextx; - param->src_y32 = y32; - y32 += nexty; - dstindex = param->fp_copy(dst, dstindex, dstindex + w, param); - } while (--h); - } + lock_t lock(this); + Panel_FrameBufferBase::writePixels(param, len, use_dma); } - void Panel_sdl::copyRect(uint_fast16_t dst_x, uint_fast16_t dst_y, uint_fast16_t w, uint_fast16_t h, uint_fast16_t src_x, uint_fast16_t src_y) + void Panel_sdl::display(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h) { - uint_fast8_t r = _internal_rotation; - if (r) + if (_in_step_exec) { - if ((1u << r) & 0b10010110) { src_y = _height - (src_y + h); dst_y = _height - (dst_y + h); } - if (r & 2) { src_x = _width - (src_x + w); dst_x = _width - (dst_x + w); } - if (r & 1) { std::swap(src_x, src_y); std::swap(dst_x, dst_y); std::swap(w, h); } + if (_display_counter != _modified_counter) { + do { + SDL_SemPost(_update_in_semaphore); + SDL_SemWaitTimeout(_update_out_semaphore, 1); + } while (_display_counter != _modified_counter); + SDL_Delay(1); + } } - - size_t bytes = _write_bits >> 3; - size_t len = w * bytes; - int32_t add = _cfg.panel_width * bytes; - if (src_y < dst_y) add = -add; - int32_t pos = (src_y < dst_y) ? h - 1 : 0; - uint8_t* src = (uint8_t*)&monitor.tft_fb[(src_x + (src_y + pos) * _cfg.panel_width)]; - uint8_t* dst = (uint8_t*)&monitor.tft_fb[(dst_x + (dst_y + pos) * _cfg.panel_width)]; - do - { - memmove(dst, src, len); - src += add; - dst += add; - } while (--h); } uint_fast8_t Panel_sdl::getTouchRaw(touch_point_t* tp, uint_fast8_t count) { - tp->x = monitor.touch_x / monitor.scaling_x; - tp->y = monitor.touch_y / monitor.scaling_y; + tp->x = monitor.touch_x; + tp->y = monitor.touch_y; tp->size = monitor.touched ? 1 : 0; tp->id = 0; return monitor.touched; } + void Panel_sdl::setWindowTitle(const char* title) + { + _window_title = title; + if (monitor.window) { + SDL_SetWindowTitle(monitor.window, _window_title); + } + } + void Panel_sdl::sdl_create(monitor_t * m) { - int flag = 0; + int flag = SDL_WINDOW_RESIZABLE; #if SDL_FULLSCREEN flag |= SDL_WINDOW_FULLSCREEN; #endif - m->panel = this; - m->window = SDL_CreateWindow("LGFX Simulator", + m->window = SDL_CreateWindow(_window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _cfg.panel_width * m->scaling_x, _cfg.panel_height * m->scaling_y, flag); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/ - m->renderer = SDL_CreateRenderer(m->window, -1, SDL_RENDERER_SOFTWARE); - m->texture = SDL_CreateTexture(m->renderer, - SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STATIC, _cfg.panel_width, _cfg.panel_height); + m->renderer = SDL_CreateRenderer(m->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + m->texture = SDL_CreateTexture(m->renderer, SDL_PIXELFORMAT_RGB24, + SDL_TEXTUREACCESS_STATIC, _cfg.panel_width, _cfg.panel_height); SDL_SetTextureBlendMode(m->texture, SDL_BLENDMODE_NONE); } - void Panel_sdl::sdl_update(const monitor_t* const m) + void Panel_sdl::sdl_update(void) { - SDL_UpdateTexture(m->texture, NULL, m->tft_fb, m->panel->config().panel_width * sizeof(bgr888_t)); + if (monitor.renderer == nullptr) + { + sdl_create(&monitor); + } + + bool step_exec = _in_step_exec; + + if (_texupdate_counter != _modified_counter) { + pixelcopy_t pc(nullptr, color_depth_t::rgb888_3Byte, _write_depth, false); + if (_write_depth == rgb565_2Byte) { + pc.fp_copy = pixelcopy_t::copy_rgb_fast; + } else if (_write_depth == rgb888_3Byte) { + pc.fp_copy = pixelcopy_t::copy_rgb_fast; + } else if (_write_depth == rgb332_1Byte) { + pc.fp_copy = pixelcopy_t::copy_rgb_fast; + } else if (_write_depth == grayscale_8bit) { + pc.fp_copy = pixelcopy_t::copy_rgb_fast; + } + + if (0 == SDL_LockMutex(_sdl_mutex)) + { + _texupdate_counter = _modified_counter; + for (int y = 0; y < _cfg.panel_height; ++y) + { + pc.src_x32 = 0; + pc.src_data = _lines_buffer[y]; + pc.fp_copy(&_texturebuf[y * _cfg.panel_width], 0, _cfg.panel_width, &pc); + } + SDL_UnlockMutex(_sdl_mutex); + SDL_UpdateTexture(monitor.texture, nullptr, _texturebuf, _cfg.panel_width * sizeof(rgb888_t)); + } + } - /*Update the renderer with the texture containing the rendered image*/ - SDL_RenderCopy(m->renderer, m->texture, NULL, NULL); - SDL_RenderPresent(m->renderer); + if (_invalidated || (_display_counter != _texupdate_counter)) + { + SDL_RendererInfo info; + if (0 == SDL_GetRendererInfo(monitor.renderer, &info)) { + // ステップ実行中はVSYNCを待機しない + if (((bool)(info.flags & SDL_RENDERER_PRESENTVSYNC)) == step_exec) + { + SDL_RenderSetVSync(monitor.renderer, !step_exec); + } + } + SDL_RenderCopy(monitor.renderer, monitor.texture, nullptr, nullptr); + SDL_RenderPresent(monitor.renderer); + _display_counter = _texupdate_counter; + if (_invalidated) { + _invalidated = false; + SDL_RenderCopy(monitor.renderer, monitor.texture, nullptr, nullptr); + SDL_RenderPresent(monitor.renderer); + } + } } - void Panel_sdl::sdl_quit(void) + bool Panel_sdl::initFrameBuffer(size_t width, size_t height) { - SDL_DestroyTexture(monitor.texture); - SDL_DestroyRenderer(monitor.renderer); - SDL_DestroyWindow(monitor.window); + uint8_t** lineArray = (uint8_t**)heap_alloc_dma(height * sizeof(uint8_t*)); + if ( nullptr == lineArray ) { return false; } - SDL_Quit(); - exit(0); + _texturebuf = (rgb888_t*)heap_alloc_dma(width * height * sizeof(rgb888_t)); + + /// 8byte alignment; + width = (width + 7) & ~7u; + + _lines_buffer = lineArray; + memset(lineArray, 0, height * sizeof(uint8_t*)); + + uint8_t* framebuffer = (uint8_t*)heap_alloc_dma(width * height + 16); + + auto fb = framebuffer; + { + for (int y = 0; y < height; ++y) + { + lineArray[y] = fb; + fb += width; + } + } + return true; } + + void Panel_sdl::deinitFrameBuffer(void) + { + auto lines = _lines_buffer; + _lines_buffer = nullptr; + if (lines != nullptr) + { + heap_free(lines[0]); + heap_free(lines); + } + if (_texturebuf) { + heap_free(_texturebuf); + _texturebuf = nullptr; + } + } + //---------------------------------------------------------------------------- } } diff --git a/src/lgfx/v1/platforms/sdl/Panel_sdl.hpp b/src/lgfx/v1/platforms/sdl/Panel_sdl.hpp index 9fc942ec..eb2abe4f 100644 --- a/src/lgfx/v1/platforms/sdl/Panel_sdl.hpp +++ b/src/lgfx/v1/platforms/sdl/Panel_sdl.hpp @@ -20,10 +20,11 @@ Porting for SDL: /----------------------------------------------------------------------------*/ #pragma once -#include "../../panel/Panel_Device.hpp" +#include "common.hpp" +#if defined (SDL_h_) +#include "../../panel/Panel_FrameBufferBase.hpp" #include "../../misc/range.hpp" #include "../../Touch.hpp" -#include "common.hpp" namespace lgfx { @@ -35,72 +36,88 @@ namespace lgfx SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; SDL_Texture* texture = nullptr; - volatile bool sdl_refr_qry; - bgr888_t* tft_fb = nullptr; Panel_sdl* panel = nullptr; int scaling_x = 1; int scaling_y = 1; - bool touched = false; int touch_x, touch_y; + bool touched = false; + bool closing = false; }; //---------------------------------------------------------------------------- - struct Panel_sdl : public Panel_Device + struct Touch_sdl : public ITouch { + bool init(void) override { return true; } + void wakeup(void) override {} + void sleep(void) override {} + bool isEnable(void) override { return true; }; + uint_fast8_t getTouchRaw(touch_point_t* tp, uint_fast8_t count) override { return 0; } + }; +//---------------------------------------------------------------------------- + + struct Panel_sdl : public Panel_FrameBufferBase + { public: - static void sdl_event_handler(void); - static void sdl_update_handler(void); Panel_sdl(void); virtual ~Panel_sdl(void); bool init(bool use_reset) override; - void beginTransaction(void) override {} - void endTransaction(void) override {} color_depth_t setColorDepth(color_depth_t depth) override; - void setRotation(uint_fast8_t r) override; - void setInvert(bool invert) override {} - void setSleep(bool flg) override {} - void setPowerSave(bool) override {} - void waitDisplay(void) override {} - bool displayBusy(void) override { return false; } + void display(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h) override; - void writePixels(pixelcopy_t* param, uint32_t len, bool use_dma) override; - void writeBlock(uint32_t rawcolor, uint32_t length) override; - void display(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h) override {} - void setWindow(uint_fast16_t xs, uint_fast16_t ys, uint_fast16_t xe, uint_fast16_t ye) override; + // void setInvert(bool invert) override {} void drawPixelPreclipped(uint_fast16_t x, uint_fast16_t y, uint32_t rawcolor) override; void writeFillRectPreclipped(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, uint32_t rawcolor) override; + void writeBlock(uint32_t rawcolor, uint32_t length) override; void writeImage(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param, bool use_dma) override; void writeImageARGB(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param) override; - - uint32_t readCommand(uint_fast16_t cmd, uint_fast8_t index, uint_fast8_t len) override { return 0; } - uint32_t readData(uint_fast8_t index, uint_fast8_t len) override { return 0; } - void readRect(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, void* dst, pixelcopy_t* param) override; - void copyRect(uint_fast16_t dst_x, uint_fast16_t dst_y, uint_fast16_t w, uint_fast16_t h, uint_fast16_t src_x, uint_fast16_t src_y) override; + void writePixels(pixelcopy_t* param, uint32_t len, bool use_dma) override; uint_fast8_t getTouchRaw(touch_point_t* tp, uint_fast8_t count) override; - void sdl_quit(void); - + void setWindowTitle(const char* title); void setScaling(uint_fast8_t scaling_x, uint_fast8_t scaling_y); - private: - void sdl_create(monitor_t * m); - static void sdl_update(const monitor_t* const m); + static int setup(void); + static int loop(void); + static int close(void); + + static int main(int(*fn)(bool*), uint32_t msec_step_exec = 512); protected: + const char* _window_title = "LGFX Simulator"; + SDL_mutex *_sdl_mutex = nullptr; + + void sdl_create(monitor_t * m); + void sdl_update(void); + touch_point_t _touch_point; monitor_t monitor; - int32_t _xpos = 0; - int32_t _ypos = 0; - // bool sdl_quit_qry = false; - void _rotate_pixelcopy(uint_fast16_t& x, uint_fast16_t& y, uint_fast16_t& w, uint_fast16_t& h, pixelcopy_t* param, uint32_t& nextx, uint32_t& nexty); + rgb888_t* _texturebuf = nullptr; + uint_fast16_t _modified_counter; + uint_fast16_t _texupdate_counter; + uint_fast16_t _display_counter; + bool _invalidated; + + static void _event_proc(void); + static void _update_proc(void); + void sdl_invalidate(void) { _invalidated = true; } + bool initFrameBuffer(size_t width, size_t height); + void deinitFrameBuffer(void); + + struct lock_t { + lock_t(Panel_sdl* parent); + ~lock_t(); + protected: + Panel_sdl* _parent; + }; }; //---------------------------------------------------------------------------- } } +#endif \ No newline at end of file diff --git a/src/lgfx/v1/platforms/sdl/common.cpp b/src/lgfx/v1/platforms/sdl/common.cpp index db5b10d3..c6cdbce8 100644 --- a/src/lgfx/v1/platforms/sdl/common.cpp +++ b/src/lgfx/v1/platforms/sdl/common.cpp @@ -18,10 +18,10 @@ Original Source: Porting for SDL: [imliubo](https://github.com/imliubo) /----------------------------------------------------------------------------*/ -#if defined ( LGFX_SDL ) - #include "common.hpp" +#if defined ( SDL_h_ ) + #include #include @@ -58,7 +58,7 @@ namespace lgfx } else { - std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds - 1)); + SDL_Delay(milliseconds); } } @@ -67,7 +67,7 @@ namespace lgfx auto start = micros(); if (us >= 2000) { - std::this_thread::sleep_for(std::chrono::milliseconds((us / 1000) - 1)); + SDL_Delay((us / 1000) - 1); } do { diff --git a/src/lgfx/v1/platforms/sdl/common.hpp b/src/lgfx/v1/platforms/sdl/common.hpp index 6d94da22..0b211fb2 100644 --- a/src/lgfx/v1/platforms/sdl/common.hpp +++ b/src/lgfx/v1/platforms/sdl/common.hpp @@ -27,12 +27,15 @@ Porting for SDL: #include #include +#define SDL_MAIN_HANDLED #if __has_include() +#include #include -#endif -#if __has_include() +#elif __has_include() +#include #include #endif +#if defined (SDL_h_) namespace lgfx { @@ -77,7 +80,11 @@ namespace lgfx need_transaction = false; } FILE* _fp; +#if defined (__STDC_WANT_SECURE_LIB__) + bool open(const char* path) override { return (0 == fopen_s(&_fp, path, "rb")); } +#else bool open(const char* path) override { return (_fp = fopen(path, "rb")); } +#endif int read(uint8_t *buf, uint32_t len) override { return fread((char*)buf, 1, len, _fp); } void skip(int32_t offset) override { seek(offset, SEEK_CUR); } bool seek(uint32_t offset) override { return seek(offset, SEEK_SET); } @@ -105,3 +112,5 @@ namespace lgfx //---------------------------------------------------------------------------- } } + +#endif \ No newline at end of file diff --git a/src/lgfx/v1/touch/Touch_CST816S.hpp b/src/lgfx/v1/touch/Touch_CST816S.hpp index af973a2c..4293bcd9 100644 --- a/src/lgfx/v1/touch/Touch_CST816S.hpp +++ b/src/lgfx/v1/touch/Touch_CST816S.hpp @@ -49,8 +49,8 @@ namespace lgfx bool init(void) override; - // void wakeup(void) override; - // void sleep(void) override; + void wakeup(void) override {}; + void sleep(void) override {}; uint_fast8_t getTouchRaw(touch_point_t* tp, uint_fast8_t count) override; diff --git a/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp b/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp index cc50dc1f..d02d7d21 100644 --- a/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp +++ b/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp @@ -161,29 +161,6 @@ namespace lgfx } }; - struct Light_M5AtomS3 : public lgfx::Light_PWM - { - Light_M5AtomS3(void) - { - auto cfg = config(); - /// The backlight of AtomS3 does not light up if the PWM cycle is too fast. - cfg.freq = 240; - cfg.pin_bl = GPIO_NUM_16; - cfg.pwm_channel = 7; - config(cfg); - } - - void setBrightness(uint8_t brightness) override - { - if (brightness) - { - brightness = brightness - (brightness >> 3) + 31; - } - Light_PWM::setBrightness(brightness); - } - }; - - #elif defined (CONFIG_IDF_TARGET_ESP32S2) #if defined ( ARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT ) @@ -715,13 +692,14 @@ namespace lgfx return res; } - static ILight* _create_pwm_backlight(int16_t pin, uint8_t ch, uint32_t freq = 12000, bool invert = false) + static ILight* _create_pwm_backlight(int16_t pin, uint8_t ch, uint32_t freq = 12000, bool invert = false, uint8_t offset = 0) { auto bl = new lgfx::Light_PWM(); auto cfg = bl->config(); cfg.pin_bl = pin; cfg.freq = freq; cfg.pwm_channel = ch; + cfg.offset = offset; cfg.invert = invert; bl->config(cfg); return bl; @@ -1068,7 +1046,7 @@ namespace lgfx ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5AtomS3"); auto p = new Panel_GC9107(); param->panel = p; - p->light(new Light_M5AtomS3()); + p->light(_create_pwm_backlight(GPIO_NUM_16, 7, 256, false, 48)); { auto cfg = p->config(); @@ -1842,6 +1820,35 @@ namespace lgfx } }; + struct _detector_M5StickCPlus2_t : public _detector_spi_t + { + constexpr _detector_M5StickCPlus2_t(void) : + _detector_spi_t + { board_t::board_M5StickCPlus2 + , 0x04, 0xFF, 0x85 // ST7789 + , 40000000, 15000000 + , GPIO_NUM_15 // MOSI + , (gpio_num_t)-1 // MISO + , GPIO_NUM_13 // SCLK + , GPIO_NUM_14 // DC + , GPIO_NUM_5 // CS + , GPIO_NUM_12 // RST + , (gpio_num_t)-1 // TF CARD CS + , 0 // SPI MODE + , true // SPI 3wire + , HSPI_HOST // SPI HOST + } {} + + void setup(_detector_result_t* result) const override + { + ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StickCPlus2"); + + auto p = new Panel_M5StickCPlus(); + result->panel = p; + p->light(_create_pwm_backlight(GPIO_NUM_27, 7, 256, false, 40)); + } + }; + struct _detector_M5StickC_t : public _detector_spi_t { constexpr _detector_M5StickC_t(void) : @@ -3177,8 +3184,9 @@ namespace lgfx #elif defined (CONFIG_IDF_TARGET_ESP32) || !defined (CONFIG_IDF_TARGET) - static constexpr const _detector_M5StickCPlus_t detector_M5StickCPlus; static constexpr const _detector_M5StickC_t detector_M5StickC; + static constexpr const _detector_M5StickCPlus_t detector_M5StickCPlus; + static constexpr const _detector_M5StickCPlus2_t detector_M5StickCPlus2; static constexpr const _detector_M5StackCoreInk_t detector_M5StackCoreInk; static constexpr const _detector_TTGO_TWristband_t detector_TTGO_TWristband; static constexpr const _detector_TTGO_TS_t detector_TTGO_TS; @@ -3206,6 +3214,15 @@ namespace lgfx static constexpr const _detector_DDUINO32_XS_t detector_DDUINO32_X; + static constexpr const _detector_t* detector_list_PICO_V3[] = + { + +#if defined ( LGFX_AUTODETECT ) || defined ( LGFX_M5STICK_C ) || defined ( LGFX_M5STICKC ) + &detector_M5StickCPlus2, +#endif + nullptr // terminator + }; + static constexpr const _detector_t* detector_list_PICO_D4[] = { @@ -3317,6 +3334,10 @@ namespace lgfx case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4: detectors = detector_list_PICO_D4; break; + + case 6: + detectors = detector_list_PICO_V3; + break; } #endif diff --git a/src/lgfx/v1_autodetect/common.hpp b/src/lgfx/v1_autodetect/common.hpp index 013df88d..98262e10 100644 --- a/src/lgfx/v1_autodetect/common.hpp +++ b/src/lgfx/v1_autodetect/common.hpp @@ -45,13 +45,13 @@ Original Source: #include "LGFX_AutoDetect_STM32.hpp" -#elif __has_include() +#elif __has_include() || __has_include() - #include "LGFX_AutoDetect_OpenCV.hpp" + #include "LGFX_AutoDetect_sdl.hpp" -#elif defined (LGFX_SDL) +#elif __has_include() - #include "LGFX_AutoDetect_sdl.hpp" + #include "LGFX_AutoDetect_OpenCV.hpp" #elif defined (LGFX_LINUX_FB) diff --git a/src/lgfx_user/LGFX_Makerfabs_MaTouchESP32S3ParallelTFTwithTouch7.h b/src/lgfx_user/LGFX_Makerfabs_MaTouchESP32S3ParallelTFTwithTouch7.h new file mode 100644 index 00000000..eec7f4de --- /dev/null +++ b/src/lgfx_user/LGFX_Makerfabs_MaTouchESP32S3ParallelTFTwithTouch7.h @@ -0,0 +1,122 @@ + +#define LGFX_USE_V1 +#include + +#include +#include +#include + +class LGFX : public lgfx::LGFX_Device +{ +public: + + lgfx::Bus_RGB _bus_instance; + lgfx::Panel_RGB _panel_instance; + lgfx::Light_PWM _light_instance; + lgfx::Touch_GT911 _touch_instance; + + LGFX(void) + { + { + auto cfg = _panel_instance.config(); + +#if defined ( LGFX_MAKERFABS_MATOUCH_1024X768 ) + cfg.memory_width = 1024; + cfg.panel_width = 1024; + cfg.memory_height = 600; + cfg.panel_height = 600; +#else + cfg.memory_width = 800; + cfg.panel_width = 800; + cfg.memory_height = 480; + cfg.panel_height = 480; +#endif + + cfg.offset_x = 0; + cfg.offset_y = 0; + + _panel_instance.config(cfg); + } + + { + auto cfg = _panel_instance.config_detail(); + + cfg.use_psram = 1; + + _panel_instance.config_detail(cfg); + } + + { + auto cfg = _bus_instance.config(); + cfg.panel = &_panel_instance; + cfg.pin_d0 = GPIO_NUM_8; // B0 + cfg.pin_d1 = GPIO_NUM_3; // B1 + cfg.pin_d2 = GPIO_NUM_46; // B2 + cfg.pin_d3 = GPIO_NUM_9; // B3 + cfg.pin_d4 = GPIO_NUM_1; // B4 + cfg.pin_d5 = GPIO_NUM_5; // G0 + cfg.pin_d6 = GPIO_NUM_6; // G1 + cfg.pin_d7 = GPIO_NUM_7; // G2 + cfg.pin_d8 = GPIO_NUM_15; // G3 + cfg.pin_d9 = GPIO_NUM_16; // G4 + cfg.pin_d10 = GPIO_NUM_4; // G5 + cfg.pin_d11 = GPIO_NUM_45; // R0 + cfg.pin_d12 = GPIO_NUM_48; // R1 + cfg.pin_d13 = GPIO_NUM_47; // R2 + cfg.pin_d14 = GPIO_NUM_21; // R3 + cfg.pin_d15 = GPIO_NUM_14; // R4 + + cfg.pin_henable = GPIO_NUM_40; + cfg.pin_vsync = GPIO_NUM_41; + cfg.pin_hsync = GPIO_NUM_39; + cfg.pin_pclk = GPIO_NUM_42; + cfg.freq_write = 16000000; + + cfg.hsync_polarity = 0; + cfg.hsync_front_porch = 80; + cfg.hsync_pulse_width = 4; + cfg.hsync_back_porch = 16; + cfg.vsync_polarity = 0; + cfg.vsync_front_porch = 22; + cfg.vsync_pulse_width = 4; + cfg.vsync_back_porch = 4; + cfg.pclk_idle_high = 1; + _bus_instance.config(cfg); + } + _panel_instance.setBus(&_bus_instance); + + { + auto cfg = _light_instance.config(); + cfg.pin_bl = GPIO_NUM_10; + cfg.invert = true; + _light_instance.config(cfg); + } + _panel_instance.light(&_light_instance); + + { + auto cfg = _touch_instance.config(); + cfg.x_min = 0; + cfg.y_min = 0; + cfg.bus_shared = false; + cfg.offset_rotation = 0; + // I2C接続 + cfg.i2c_port = I2C_NUM_1; + cfg.pin_sda = GPIO_NUM_17; + cfg.pin_scl = GPIO_NUM_18; + cfg.pin_int = GPIO_NUM_NC; + cfg.pin_rst = GPIO_NUM_38; +#if defined ( LGFX_MAKERFABS_MATOUCH_1024X768 ) + cfg.x_max = 1024; + cfg.y_max = 768; +#else + cfg.x_max = 800; + cfg.y_max = 480; +#endif + cfg.freq = 400000; + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } + + setPanel(&_panel_instance); + } +}; diff --git a/src/lgfx_user/LGFX_Sunton_ESP32-8048S070.h b/src/lgfx_user/LGFX_Sunton_ESP32-8048S070.h new file mode 100644 index 00000000..2f5716be --- /dev/null +++ b/src/lgfx_user/LGFX_Sunton_ESP32-8048S070.h @@ -0,0 +1,111 @@ + +#define LGFX_USE_V1 +#include + +#include +#include + +#include + +class LGFX : public lgfx::LGFX_Device +{ +public: + + lgfx::Bus_RGB _bus_instance; + lgfx::Panel_RGB _panel_instance; + lgfx::Light_PWM _light_instance; + lgfx::Touch_GT911 _touch_instance; + + LGFX(void) + { + { + auto cfg = _panel_instance.config(); + + cfg.memory_width = 800; + cfg.memory_height = 480; + cfg.panel_width = 800; + cfg.panel_height = 480; + + cfg.offset_x = 0; + cfg.offset_y = 0; + + _panel_instance.config(cfg); + } + + { + auto cfg = _panel_instance.config_detail(); + + cfg.use_psram = 1; + + _panel_instance.config_detail(cfg); + } + + { + auto cfg = _bus_instance.config(); + cfg.panel = &_panel_instance; + cfg.pin_d0 = GPIO_NUM_15; // B0 + cfg.pin_d1 = GPIO_NUM_7; // B1 + cfg.pin_d2 = GPIO_NUM_6; // B2 + cfg.pin_d3 = GPIO_NUM_5; // B3 + cfg.pin_d4 = GPIO_NUM_4; // B4 + cfg.pin_d5 = GPIO_NUM_9; // G0 + cfg.pin_d6 = GPIO_NUM_46; // G1 + cfg.pin_d7 = GPIO_NUM_3; // G2 + cfg.pin_d8 = GPIO_NUM_8; // G3 + cfg.pin_d9 = GPIO_NUM_16; // G4 + cfg.pin_d10 = GPIO_NUM_1; // G5 + cfg.pin_d11 = GPIO_NUM_14; // R0 + cfg.pin_d12 = GPIO_NUM_21; // R1 + cfg.pin_d13 = GPIO_NUM_47; // R2 + cfg.pin_d14 = GPIO_NUM_48; // R3 + cfg.pin_d15 = GPIO_NUM_45; // R4 + + cfg.pin_henable = GPIO_NUM_41; + cfg.pin_vsync = GPIO_NUM_40; + cfg.pin_hsync = GPIO_NUM_39; + cfg.pin_pclk = GPIO_NUM_42; + cfg.freq_write = 14000000; + + cfg.hsync_polarity = 0; + cfg.hsync_front_porch = 80; + cfg.hsync_pulse_width = 4; + cfg.hsync_back_porch = 16; + cfg.vsync_polarity = 0; + cfg.vsync_front_porch = 22; + cfg.vsync_pulse_width = 4; + cfg.vsync_back_porch = 4; + cfg.pclk_idle_high = 1; + _bus_instance.config(cfg); + } + _panel_instance.setBus(&_bus_instance); + + { + auto cfg = _light_instance.config(); + cfg.pin_bl = GPIO_NUM_2; + _light_instance.config(cfg); + } + _panel_instance.light(&_light_instance); + + { + auto cfg = _touch_instance.config(); + cfg.x_min = 0; + cfg.x_max = 800; + cfg.y_min = 0; + cfg.y_max = 480; + cfg.pin_int = GPIO_NUM_NC; + cfg.bus_shared = false; + cfg.offset_rotation = 0; + // I2C接続 + cfg.i2c_port = I2C_NUM_1; + cfg.pin_sda = GPIO_NUM_19; + cfg.pin_scl = GPIO_NUM_20; + cfg.pin_rst = GPIO_NUM_38; + cfg.freq = 400000; + cfg.i2c_addr = 0x14; // 0x5D , 0x14 + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } + + setPanel(&_panel_instance); + } +};