Satoshi Yoneda 3 долоо хоног өмнө
commit
2e2338f72e

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch

+ 10 - 0
.vscode/extensions.json

@@ -0,0 +1,10 @@
+{
+    // See http://go.microsoft.com/fwlink/?LinkId=827846
+    // for the documentation about the extensions.json format
+    "recommendations": [
+        "platformio.platformio-ide"
+    ],
+    "unwantedRecommendations": [
+        "ms-vscode.cpptools-extension-pack"
+    ]
+}

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+    "C_Cpp.vcFormat.wrap.preserveBlocks": "oneLiners"
+}

+ 39 - 0
include/README

@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

BIN
include/constructor.jpg


+ 97 - 0
include/dma_st7789.hpp

@@ -0,0 +1,97 @@
+#ifndef __DMA_ST7789
+#define __DMA_ST7789
+
+#include <Arduino.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_ST7735.h>
+#include <Adafruit_ST7789.h>
+#include <SPI.h>
+
+#include "hardware/dma.h"
+#include "hardware/spi.h"
+#include "pico/stdlib.h"
+
+class dma_st7789 : public Adafruit_ST7789 {
+
+    private:
+        volatile bool data_transfer_flag;
+        int dma_channel;
+        dma_channel_config c;
+        static dma_st7789   *instance_ptr;  // インスタンス
+    
+        // 割り込みハンドラ(動的)
+        void dma_interrupt_handler() {
+            // 割り込みフラグをクリア
+            dma_hw->ints0 = 1u << dma_channel;
+            // SPI転送の終了処理
+            this->endWrite();
+            // 転送中フラグをリセット
+            data_transfer_flag = false;
+        };
+    
+    public:
+        // コンストラクタ
+        dma_st7789(int8_t cs, int8_t dc, int8_t rst) : Adafruit_ST7789(cs, dc, rst) {
+            data_transfer_flag = false;
+            instance_ptr = this;    // インスタンスを保存
+
+            // DMAの設定
+            dma_channel = dma_claim_unused_channel(true);
+            c = dma_channel_get_default_config(dma_channel);
+            channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
+            channel_config_set_read_increment(&c, true);
+            channel_config_set_write_increment(&c, false);
+            channel_config_set_dreq(&c, DREQ_SPI0_TX);
+            dma_channel_set_irq0_enabled(dma_channel, true);
+    
+            // 割り込みハンドラとして静的関数を登録
+            irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler_static);
+            irq_set_enabled(DMA_IRQ_0, true);
+        };
+    
+        // 転送開始
+        void transfer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *buffer) {
+            // 1つ前(があればそれ)のDMAの転送完了を待つ
+            (void)wait_for_transfer();
+    
+            uint size = width * height * sizeof(uint16_t);
+            this->setAddrWindow(x, y, width, height);
+            this->startWrite();
+            data_transfer_flag = true;
+            // 転送
+            dma_channel_configure(
+                dma_channel,
+                &c,
+                &spi_get_hw(spi0)->dr,
+                buffer,
+                size,
+                true
+            );
+        };
+    
+        // 転送完了待機(タイムアウト付き)
+        bool wait_for_transfer(int timeout_ms = 1000) {
+            bool retval = true;
+    
+            ulong start_time = millis();
+            while( data_transfer_flag ) {
+                if( (millis() - start_time) > timeout_ms)
+                 break;
+            }
+            if(data_transfer_flag) retval = false;
+    
+            return retval;
+        };
+    
+        // 割り込みハンドラ(静的)
+        static void dma_irq_handler_static(void) {
+            if(instance_ptr) {
+                instance_ptr->dma_interrupt_handler();
+            }
+        };
+};
+
+// インスタンスを初期化
+dma_st7789  *dma_st7789::instance_ptr = nullptr;
+
+#endif

+ 46 - 0
lib/README

@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+|  |
+|  |--Bar
+|  |  |--docs
+|  |  |--examples
+|  |  |--src
+|  |     |- Bar.c
+|  |     |- Bar.h
+|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+|  |
+|  |--Foo
+|  |  |- Foo.c
+|  |  |- Foo.h
+|  |
+|  |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+   |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+  ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html

+ 19 - 0
platformio.ini

@@ -0,0 +1,19 @@
+; 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:rpipico2]
+platform = raspberrypi
+board = rpipico2
+framework = arduino
+lib_deps = 
+	adafruit/Adafruit ST7735 and ST7789 Library@^1.11.0
+	bitbank2/JPEGDEC@^1.7.0
+upload_protocol = cmsis-dap
+debug_tool = cmsis-dap

+ 66 - 0
src/main.cpp

@@ -0,0 +1,66 @@
+#include <Arduino.h>
+#include "dma_st7789.hpp"
+#include <JPEGDEC.h>
+
+#define TFT_CS         17
+#define TFT_RST        21
+#define TFT_DC         20
+
+// サンプル画像を埋め込む
+__asm(\
+  ".section \".rodata\" \n"\
+  ".balign 4\n"\
+
+  ".global _sample_picture\n"\
+  ".global _picture_size\n"\
+
+  "_sample_picture:\n"\
+  ".incbin \"include/constructor.jpg\"\n"\
+  ".set _picture_size, . - _sample_picture\n"\
+  ".section \".text\"\n"\
+);
+
+extern const uint16_t _sample_picture[];
+extern uint32_t _picture_size[];
+
+
+// ST7789LCD(DMA付き)
+dma_st7789 st7789_lcd = dma_st7789(TFT_CS, TFT_DC, TFT_RST);
+
+// JPEGデコーダー
+JPEGDEC jpeg;
+
+// MCUを描画するコールバック関数
+int mcu_draw(JPEGDRAW *draw)
+{
+  if( draw->iBpp == 16 ){
+    st7789_lcd.transfer(draw->x, draw->y, draw->iWidth, draw->iHeight, (uint8_t *)(draw->pPixels) );
+  }
+
+  return 1;
+}
+
+void setup() {
+  Serial1.begin(115200);
+  // SPIクロック100MHz
+  st7789_lcd.setSPISpeed(100*000*000);
+  // 解像度240×240、SPIモード3
+  st7789_lcd.init(240, 240, SPI_MODE3);
+}
+
+
+void loop() {
+  st7789_lcd.fillScreen(ST77XX_BLACK);
+
+  jpeg.openFLASH((uint8_t *)_sample_picture, (int)_picture_size, mcu_draw);
+  jpeg.setPixelType(RGB565_BIG_ENDIAN);
+  // 開始時間
+  ulong start_time = micros();
+  jpeg.decode(0,0,JPEG_USES_DMA);
+  // 経過時間測定
+  ulong elapsed = micros() - start_time;
+  Serial1.printf("elapsed time %u usec.\n", elapsed);
+  jpeg.close();
+  sleep_ms(2000);
+}
+

+ 11 - 0
test/README

@@ -0,0 +1,11 @@
+
+This directory is intended for PlatformIO Test Runner and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PlatformIO Unit Testing:
+- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html