acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Flash_Jpg_DMA.ino (4140B)

      1 // Example for library:
      2 // https://github.com/Bodmer/TJpg_Decoder
      3 
      4 // This example renders a Jpeg file that is stored in an array within Flash (program) memory
      5 // see panda.h tab.  The panda image file being ~13Kbytes.
      6 
      7 #define USE_DMA
      8 
      9 // Include the array
     10 #include "panda.h"
     11 
     12 // Include the jpeg decoder library
     13 #include <TJpg_Decoder.h>
     14 
     15 #ifdef USE_DMA
     16   uint16_t  dmaBuffer1[16*16]; // Toggle buffer for 16*16 MCU block, 512bytes
     17   uint16_t  dmaBuffer2[16*16]; // Toggle buffer for 16*16 MCU block, 512bytes
     18   uint16_t* dmaBufferPtr = dmaBuffer1;
     19   bool dmaBufferSel = 0;
     20 #endif
     21 
     22 // Include the TFT library https://github.com/Bodmer/TFT_eSPI
     23 #include "SPI.h"
     24 #include <TFT_eSPI.h>              // Hardware-specific library
     25 TFT_eSPI tft = TFT_eSPI();         // Invoke custom library
     26 
     27 // This next function will be called during decoding of the jpeg file to render each
     28 // 16x16 or 8x8 image tile (Minimum Coding Unit) to the TFT.
     29 bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
     30 {
     31    // Stop further decoding as image is running off bottom of screen
     32   if ( y >= tft.height() ) return 0;
     33 
     34   // STM32F767 processor takes 43ms just to decode (and not draw) jpeg (-Os compile option)
     35   // Total time to decode and also draw to TFT:
     36   // SPI 54MHz=71ms, with DMA 50ms, 71-43 = 28ms spent drawing, so DMA is complete before next MCU block is ready
     37   // Apparent performance benefit of DMA = 71/50 = 42%, 50 - 43 = 7ms lost elsewhere
     38   // SPI 27MHz=95ms, with DMA 52ms. 95-43 = 52ms spent drawing, so DMA is *just* complete before next MCU block is ready!
     39   // Apparent performance benefit of DMA = 95/52 = 83%, 52 - 43 = 9ms lost elsewhere
     40 #ifdef USE_DMA
     41   // Double buffering is used, the bitmap is copied to the buffer by pushImageDMA() the
     42   // bitmap can then be updated by the jpeg decoder while DMA is in progress
     43   if (dmaBufferSel) dmaBufferPtr = dmaBuffer2;
     44   else dmaBufferPtr = dmaBuffer1;
     45   dmaBufferSel = !dmaBufferSel; // Toggle buffer selection
     46   //  pushImageDMA() will clip the image block at screen boundaries before initiating DMA
     47   tft.pushImageDMA(x, y, w, h, bitmap, dmaBufferPtr); // Initiate DMA - blocking only if last DMA is not complete
     48   // The DMA transfer of image block to the TFT is now in progress...
     49 #else
     50   // Non-DMA blocking alternative
     51   tft.pushImage(x, y, w, h, bitmap);  // Blocking, so only returns when image block is drawn
     52 #endif
     53   // Return 1 to decode next block.
     54   return 1;
     55 }
     56 
     57 void setup()
     58 {
     59   Serial.begin(115200);
     60   Serial.println("\n\n Testing TJpg_Decoder library");
     61 
     62   // Initialise the TFT
     63   tft.begin();
     64   tft.setTextColor(TFT_WHITE, TFT_BLACK);
     65   tft.fillScreen(TFT_BLACK);
     66 
     67 #ifdef USE_DMA
     68   tft.initDMA(); // To use SPI DMA you must call initDMA() to setup the DMA engine
     69 #endif
     70 
     71   // The jpeg image can be scaled down by a factor of 1, 2, 4, or 8
     72   TJpgDec.setJpgScale(1);
     73 
     74   // The colour byte order can be swapped by the decoder
     75   // using TJpgDec.setSwapBytes(true); or by the TFT_eSPI library:
     76   tft.setSwapBytes(true);
     77 
     78   // The decoder must be given the exact name of the rendering function above
     79   TJpgDec.setCallback(tft_output);
     80 }
     81 
     82 void loop()
     83 {
     84   // Show a contrasting colour for demo of draw speed
     85   tft.fillScreen(TFT_RED);
     86 
     87 
     88   // Get the width and height in pixels of the jpeg if you wish:
     89   uint16_t w = 0, h = 0;
     90   TJpgDec.getJpgSize(&w, &h, panda, sizeof(panda));
     91   Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);
     92 
     93   // Time recorded for test purposes
     94   uint32_t dt = millis();
     95 
     96   // Must use startWrite first so TFT chip select stays low during DMA and SPI channel settings remain configured
     97   tft.startWrite();
     98 
     99   // Draw the image, top left at 0,0 - DMA request is handled in the call-back tft_output() in this sketch
    100   TJpgDec.drawJpg(0, 0, panda, sizeof(panda));
    101 
    102   // Must use endWrite to release the TFT chip select and release the SPI channel
    103   tft.endWrite();
    104 
    105   // How much time did rendering take (ESP8266 80MHz 262ms, 160MHz 149ms, ESP32 SPI 111ms, 8bit parallel 90ms
    106   dt = millis() - dt;
    107   Serial.print(dt); Serial.println(" ms");
    108 
    109   // Wait before drawing again
    110   delay(2000);
    111 }