dma_st7789.hpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #ifndef __DMA_ST7789
  2. #define __DMA_ST7789
  3. #include <Arduino.h>
  4. #include <Adafruit_GFX.h>
  5. #include <Adafruit_ST7735.h>
  6. #include <Adafruit_ST7789.h>
  7. #include <SPI.h>
  8. #include "hardware/dma.h"
  9. #include "hardware/spi.h"
  10. #include "pico/stdlib.h"
  11. class dma_st7789 : public Adafruit_ST7789 {
  12. private:
  13. volatile bool data_transfer_flag;
  14. int dma_channel;
  15. dma_channel_config c;
  16. static dma_st7789 *instance_ptr; // インスタンス
  17. // 割り込みハンドラ(動的)
  18. void dma_interrupt_handler() {
  19. // 割り込みフラグをクリア
  20. dma_hw->ints0 = 1u << dma_channel;
  21. // SPI転送の終了処理
  22. this->endWrite();
  23. // 転送中フラグをリセット
  24. data_transfer_flag = false;
  25. };
  26. public:
  27. // コンストラクタ
  28. dma_st7789(int8_t cs, int8_t dc, int8_t rst) : Adafruit_ST7789(cs, dc, rst) {
  29. data_transfer_flag = false;
  30. instance_ptr = this; // インスタンスを保存
  31. // DMAの設定
  32. dma_channel = dma_claim_unused_channel(true);
  33. c = dma_channel_get_default_config(dma_channel);
  34. channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
  35. channel_config_set_read_increment(&c, true);
  36. channel_config_set_write_increment(&c, false);
  37. channel_config_set_dreq(&c, DREQ_SPI0_TX);
  38. dma_channel_set_irq0_enabled(dma_channel, true);
  39. // 割り込みハンドラとして静的関数を登録
  40. irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler_static);
  41. irq_set_enabled(DMA_IRQ_0, true);
  42. };
  43. // 転送開始
  44. void transfer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *buffer) {
  45. // 1つ前(があればそれ)のDMAの転送完了を待つ
  46. (void)wait_for_transfer();
  47. uint size = width * height * sizeof(uint16_t);
  48. this->setAddrWindow(x, y, width, height);
  49. this->startWrite();
  50. data_transfer_flag = true;
  51. // 転送
  52. dma_channel_configure(
  53. dma_channel,
  54. &c,
  55. &spi_get_hw(spi0)->dr,
  56. buffer,
  57. size,
  58. true
  59. );
  60. };
  61. // 転送完了待機(タイムアウト付き)
  62. bool wait_for_transfer(int timeout_ms = 1000) {
  63. bool retval = true;
  64. ulong start_time = millis();
  65. while( data_transfer_flag ) {
  66. if( (millis() - start_time) > timeout_ms)
  67. break;
  68. }
  69. if(data_transfer_flag) retval = false;
  70. return retval;
  71. };
  72. // 割り込みハンドラ(静的)
  73. static void dma_irq_handler_static(void) {
  74. if(instance_ptr) {
  75. instance_ptr->dma_interrupt_handler();
  76. }
  77. };
  78. };
  79. // インスタンスを初期化
  80. dma_st7789 *dma_st7789::instance_ptr = nullptr;
  81. #endif