ESP32-WROOM-32 で ILI9341 に SDから読みだした PNG画像を連続描画【マルチコア使用】
戦略
描画とSDからの読み出しを別々のコアでやることで並列に動作させてできるだけアイドルを減らす。
画像の前半を読んだらセマフォを開放。前半の描画を行っている間に次の後半の描画部分を読みだす。 描画のほうが早いので読み出しの速度分のFPSがでるはず。
コード
#include "FS.h" #include "SD.h" #include "SPI.h" #include "TFT_eSPI.h" TFT_eSPI tft = TFT_eSPI(); // Invoke custom library SPIClass sd_HSPI(HSPI); #define HSPI_SCK 14 #define HSPI_MISO 35 #define HSPI_MOSI 13 #define HSPI_SS 15 #define SDSPEED 16000000 boolean sdHasError; SemaphoreHandle_t xSemaphore1; SemaphoreHandle_t xSemaphore2; SemaphoreHandle_t xSemaphore3; static uint8_t data1[120 * 320]; static uint8_t data2[120 * 320]; void testOriginalData() { xSemaphoreTake(xSemaphore1, portMAX_DELAY); tft.pushImage(0, 0, 320, 120, data1); xSemaphoreGive(xSemaphore1); xSemaphoreTake(xSemaphore2, portMAX_DELAY); tft.pushImage(0, 120, 320, 120, data2); xSemaphoreGive(xSemaphore2); } bool readFile(fs::FS &fs, const char * path){ if(sdHasError) { return false; } File file = fs.open(path); if(!file){ Serial.println("Failed to open file for reading"); return false; } xSemaphoreTake(xSemaphore1, portMAX_DELAY); xSemaphoreGive(xSemaphore3); file.read(data1, 120 * 320); xSemaphoreGive(xSemaphore1); xSemaphoreTake(xSemaphore2, portMAX_DELAY); file.read(data2, 120 * 320); xSemaphoreTake(xSemaphore3, portMAX_DELAY); xSemaphoreGive(xSemaphore2); file.close(); return true; } void task0(void* arg) { char buf[255]; while(1) { for(int i = 1; i <= 100; i++) { sprintf(buf, "/output/%04d.dat", i); readFile(SD, buf); delay(1); } } } void setup() { // Setup the LCD tft.init(); tft.setRotation(1); sd_HSPI.begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, HSPI_SS); Serial.begin(115200); delay(100); if(!SD.begin(HSPI_SS, sd_HSPI, 12000000L)){ Serial.println("Card Mount Failed"); sdHasError = true; } else { Serial.println("Card Mount Succeeded"); } xSemaphore1 = xSemaphoreCreateMutex(); xSemaphore2 = xSemaphoreCreateMutex(); xSemaphore3 = xSemaphoreCreateBinary(); xTaskCreatePinnedToCore(task0, "Task0", 4096, NULL, 1, NULL, 0); tft.fillScreen(TFT_BLACK); } void loop() { xSemaphoreTake(xSemaphore3, portMAX_DELAY); xSemaphoreGive(xSemaphore3); if (sdHasError) { if(!SD.begin(HSPI_SS, sd_HSPI, SDSPEED)){ Serial.println("Card Mount Failed"); delay(1000); return; } else { Serial.println("Card Mount Succeeded"); sdHasError = false; } } //randomSeed(1234); // This ensure test is repeatable with exact same draws each loop char buf[255]; int x, x2; int y, y2; int r; // Clear the screen and draw the frame static unsigned long old_time; old_time = millis(); testOriginalData(); Serial.print((float)1/(millis()-old_time)*1000); Serial.println(" fps"); }
結果
6.80 ~ 7.50 fps になった。