123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /*
- The MIT License (MIT)
- Copyright (c) 2025, Satoshi Yoneda (GADGET LTD.)
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #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
|