// scope
// https://wokwi.com/projects/391512377779447809
//#include <SPI.h>
#include <stdio.h>
#include <hardware/pio.h>
#include <hardware/dma.h>
//#include "hardware/spi.h"
#include "pio.h"
// PIO定義
#define PIO_ID pio0
#define PIO_TX_SM 0
// 解像度
#define WIDTH 240
#define HEIGHT 320
//SPISettings spisettings(10000, MSBFIRST, SPI_MODE0);
//#define SPI_PORT spi0
#define TFT_MOSI 20
#define TFT_CLK 21
#define TFT_DC 22
#define TFT_RST 26
#define TFT_CS 27
uint8_t send_buffer[2] = {0x00, 0x00};
// DMA
#define DMA_DATA_COUNT WIDTH*HEIGHT
uint16_t image_buffer[WIDTH*HEIGHT] = {};
int dma_chan; // DMAチャンネル
int loop_cnt = 0;
//
void dma_handler() {
// 色変更
for(int i = 0; i < WIDTH*HEIGHT; i++){
if(loop_cnt % 2 == 0) image_buffer[i] = 0xAAAA;
else image_buffer[i] = 0x0000;
}
//
dma_channel_set_read_addr(dma_chan, image_buffer, true); // 転送を即時実行
dma_hw->ints0 = 1u << dma_chan; // 割り込み要求をクリアします
loop_cnt++;
Serial1.println(loop_cnt);
}
// PIOのSPIだと同期がとれないので信号切り替え待ちを行う
void digitalWrite_with_sleep(uint8_t pin, bool mode, int16_t ms=100){
delay(ms);
digitalWrite(pin, mode);
delay(ms);
}
void setup() {
// シリアル通信
Serial1.begin(115200);
Serial1.println("Open");
// ピン設定
pinMode(25, OUTPUT);
pinMode(TFT_DC, OUTPUT); // 22
pinMode(TFT_RST, OUTPUT); // 26
pinMode(TFT_CS, OUTPUT); // 27
// CS設定
digitalWrite(TFT_CS, LOW);
// PIOにプログラム転送
uint8_t addr = pio_add_program(PIO_ID, &spi_tx_program);
// PIO初期化
spi_tx_init(
PIO_ID,
PIO_TX_SM, // ステートマシン(0~3)
addr, // プログラム位置
TFT_MOSI,
TFT_CLK,
2.0
);
//-------------------------------------------------------
// ILI9341初期化
// HARDWARE Reset
digitalWrite(TFT_RST, LOW);
delay(20);
digitalWrite(TFT_RST, HIGH);
digitalWrite_with_sleep(TFT_DC, LOW);
pio_putc(PIO_ID, PIO_TX_SM, 0x01); // SOFTWARE RESET
pio_putc(PIO_ID, PIO_TX_SM, 0x13); // Normal Display Mode ON
pio_putc(PIO_ID, PIO_TX_SM, 0x36); // Memory Access Control
digitalWrite_with_sleep(TFT_DC, HIGH); // Data mode
pio_putc(PIO_ID, PIO_TX_SM, 0x48); // MX = ON , GBR = ON (縦画面,左から右に表示)
digitalWrite_with_sleep(TFT_DC, LOW); // Command mode
pio_putc(PIO_ID, PIO_TX_SM, 0x3a); // COLMOD: Pixel Format Set
digitalWrite_with_sleep(TFT_DC, HIGH); // Data mode
pio_putc(PIO_ID, PIO_TX_SM, 0x55); // 16Bits / 1Pixcel
digitalWrite_with_sleep(TFT_DC, LOW); // Command mode
pio_putc(PIO_ID, PIO_TX_SM, 0x11); // Sleep Out
pio_putc(PIO_ID, PIO_TX_SM, 0x29); // Display ON
// COL方向の描画範囲
digitalWrite_with_sleep(TFT_DC, LOW); // Command mode
pio_putc(PIO_ID, PIO_TX_SM, 0x2a);
digitalWrite_with_sleep(TFT_DC, HIGH); // Data mode
pio_putc(PIO_ID, PIO_TX_SM, 0x00);
pio_putc(PIO_ID, PIO_TX_SM, 0x00);
pio_putc(PIO_ID, PIO_TX_SM, 0x00);
pio_putc(PIO_ID, PIO_TX_SM, 0xef);
// ROW方向の描画範囲
digitalWrite_with_sleep(TFT_DC, LOW); // Command mode
pio_putc(PIO_ID, PIO_TX_SM, 0x2b);
digitalWrite_with_sleep(TFT_DC, HIGH); // Data mode
pio_putc(PIO_ID, PIO_TX_SM, 0x00);
pio_putc(PIO_ID, PIO_TX_SM, 0x00);
pio_putc(PIO_ID, PIO_TX_SM, 0x01);
pio_putc(PIO_ID, PIO_TX_SM, 0x3f);
digitalWrite_with_sleep(TFT_DC, LOW); // Command mode
pio_putc(PIO_ID, PIO_TX_SM, 0x2c); // Memory Write
digitalWrite_with_sleep(TFT_DC, HIGH); // Data mode
delay(100);
//-------------------------------------------------------
// PIOにプログラム転送
addr = pio_add_program(PIO_ID, &spi_tx_16bit_program);
// PIO初期化
spi_tx_init(
PIO_ID,
PIO_TX_SM, // ステートマシン(0~3)
addr, // プログラム位置
TFT_MOSI,
TFT_CLK,
1.0
);
// DMA設定
dma_chan = dma_claim_unused_channel(true); // 未使用のDMAチャンネルを取得
dma_channel_config c = dma_channel_get_default_config(dma_chan);
channel_config_set_transfer_data_size(&c, DMA_SIZE_16); // Nbit単位で転送
channel_config_set_read_increment(&c, true); // データ元の自動インクリメントを有効
channel_config_set_dreq(&c, DREQ_PIO0_TX0); // TX FIFOが空になったらDMA実行
dma_channel_configure(
dma_chan,
&c,
&pio0_hw->txf[PIO_TX_SM], // PIOのTX FIFO
image_buffer, // 送信元データ
DMA_DATA_COUNT, // このカウント分転送すると割り込みを発生させる
false // まだ開始しない
);
dma_channel_set_irq0_enabled(dma_chan, true); // IRQ0の割り込みを有効化
irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); // IRQハンドラーとしてdma_handlerを設定
irq_set_enabled(DMA_IRQ_0, true);
dma_handler(); // 初回のDMA実行
/*
// SPI
_spi_init(SPI_PORT, 1 * 1000 * 1000);
gpio_set_function(19, GPIO_FUNC_SPI);
gpio_set_function(18, GPIO_FUNC_SPI);
spi_set_format(SPI_PORT, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
*/
}
void loop() {
//digitalWrite(TFT_CS, LOW);
//pio_putc(PIO_ID, PIO_TX_SM, 0xAA);
//spi_write_blocking(SPI_PORT, send_buffer, 1);
//digitalWrite(TFT_CS, HIGH);
//spi_write_read_blocking(SPI_PORT, nullptr, send_buffer, 3);
//int n = spi_write16_read16_blocking(SPI_PORT, wBuff, rBuff, 1);
//delay(10);
// 動作確認のLED点滅
//digitalWrite(25, HIGH);
//delay(500);
//digitalWrite(25, LOW);
//delay(500);
}