112 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
// Example for library:
 | 
						|
// https://github.com/Bodmer/TJpg_Decoder
 | 
						|
 | 
						|
// This example renders a Jpeg file that is stored in an array within Flash (program) memory
 | 
						|
// see panda.h tab.  The panda image file being ~13Kbytes.
 | 
						|
 | 
						|
#define USE_DMA
 | 
						|
 | 
						|
// Include the array
 | 
						|
#include "panda.h"
 | 
						|
 | 
						|
// Include the jpeg decoder library
 | 
						|
#include <TJpg_Decoder.h>
 | 
						|
 | 
						|
#ifdef USE_DMA
 | 
						|
  uint16_t  dmaBuffer1[16*16]; // Toggle buffer for 16*16 MCU block, 512bytes
 | 
						|
  uint16_t  dmaBuffer2[16*16]; // Toggle buffer for 16*16 MCU block, 512bytes
 | 
						|
  uint16_t* dmaBufferPtr = dmaBuffer1;
 | 
						|
  bool dmaBufferSel = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
// Include the TFT library https://github.com/Bodmer/TFT_eSPI
 | 
						|
#include "SPI.h"
 | 
						|
#include <TFT_eSPI.h>              // Hardware-specific library
 | 
						|
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library
 | 
						|
 | 
						|
// This next function will be called during decoding of the jpeg file to render each
 | 
						|
// 16x16 or 8x8 image tile (Minimum Coding Unit) to the TFT.
 | 
						|
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
 | 
						|
{
 | 
						|
   // Stop further decoding as image is running off bottom of screen
 | 
						|
  if ( y >= tft.height() ) return 0;
 | 
						|
 | 
						|
  // STM32F767 processor takes 43ms just to decode (and not draw) jpeg (-Os compile option)
 | 
						|
  // Total time to decode and also draw to TFT:
 | 
						|
  // SPI 54MHz=71ms, with DMA 50ms, 71-43 = 28ms spent drawing, so DMA is complete before next MCU block is ready
 | 
						|
  // Apparent performance benefit of DMA = 71/50 = 42%, 50 - 43 = 7ms lost elsewhere
 | 
						|
  // SPI 27MHz=95ms, with DMA 52ms. 95-43 = 52ms spent drawing, so DMA is *just* complete before next MCU block is ready!
 | 
						|
  // Apparent performance benefit of DMA = 95/52 = 83%, 52 - 43 = 9ms lost elsewhere
 | 
						|
#ifdef USE_DMA
 | 
						|
  // Double buffering is used, the bitmap is copied to the buffer by pushImageDMA() the
 | 
						|
  // bitmap can then be updated by the jpeg decoder while DMA is in progress
 | 
						|
  if (dmaBufferSel) dmaBufferPtr = dmaBuffer2;
 | 
						|
  else dmaBufferPtr = dmaBuffer1;
 | 
						|
  dmaBufferSel != dmaBufferSel; // Toggle buffer selection
 | 
						|
  //  pushImageDMA() will clip the image block at screen boundaries before initiating DMA
 | 
						|
  tft.pushImageDMA(x, y, w, h, bitmap, dmaBufferPtr); // Initiate DMA - blocking only if last DMA is not complete
 | 
						|
  // The DMA transfer of image block to the TFT is now in progress...
 | 
						|
#else
 | 
						|
  // Non-DMA blocking alternative
 | 
						|
  tft.pushImage(x, y, w, h, bitmap);  // Blocking, so only returns when image block is drawn
 | 
						|
#endif
 | 
						|
  // Return 1 to decode next block.
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
void setup()
 | 
						|
{
 | 
						|
  Serial.begin(115200);
 | 
						|
  Serial.println("\n\n Testing TJpg_Decoder library");
 | 
						|
 | 
						|
  // Initialise the TFT
 | 
						|
  tft.begin();
 | 
						|
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
 | 
						|
  tft.fillScreen(TFT_BLACK);
 | 
						|
 | 
						|
#ifdef USE_DMA
 | 
						|
  tft.initDMA(); // To use SPI DMA you must call initDMA() to setup the DMA engine
 | 
						|
#endif
 | 
						|
 | 
						|
  // The jpeg image can be scaled down by a factor of 1, 2, 4, or 8
 | 
						|
  TJpgDec.setJpgScale(1);
 | 
						|
 | 
						|
  // The colour byte order can be swapped by the decoder
 | 
						|
  // using TJpgDec.setSwapBytes(true); or by the TFT_eSPI library:
 | 
						|
  tft.setSwapBytes(true);
 | 
						|
 | 
						|
  // The decoder must be given the exact name of the rendering function above
 | 
						|
  TJpgDec.setCallback(tft_output);
 | 
						|
}
 | 
						|
 | 
						|
void loop()
 | 
						|
{
 | 
						|
  // Show a contrasting colour for demo of draw speed
 | 
						|
  tft.fillScreen(TFT_RED);
 | 
						|
 | 
						|
 | 
						|
  // Get the width and height in pixels of the jpeg if you wish:
 | 
						|
  uint16_t w = 0, h = 0;
 | 
						|
  TJpgDec.getJpgSize(&w, &h, panda, sizeof(panda));
 | 
						|
  Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);
 | 
						|
 | 
						|
  // Time recorded for test purposes
 | 
						|
  uint32_t dt = millis();
 | 
						|
 | 
						|
  // Must use startWrite first so TFT chip select stays low during DMA and SPI channel settings remain configured
 | 
						|
  tft.startWrite();
 | 
						|
 | 
						|
  // Draw the image, top left at 0,0 - DMA request is handled in the call-back tft_output() in this sketch
 | 
						|
  TJpgDec.drawJpg(0, 0, panda, sizeof(panda));
 | 
						|
 | 
						|
  // Must use endWrite to release the TFT chip select and release the SPI channel
 | 
						|
  tft.endWrite();
 | 
						|
 | 
						|
  // How much time did rendering take (ESP8266 80MHz 262ms, 160MHz 149ms, ESP32 SPI 111ms, 8bit parallel 90ms
 | 
						|
  dt = millis() - dt;
 | 
						|
  Serial.print(dt); Serial.println(" ms");
 | 
						|
 | 
						|
  // Wait before drawing again
 | 
						|
  delay(2000);
 | 
						|
}
 |