Open AntonioFromBrazil opened 5 years ago
Thanks for posting the issue here. :)
Since I stumbled on this old thread and couldn't find an answer online, I figured I'd post my solution.
In the included code, I print a larger .bmp to the screen (which crops to the screen size), then read each pixel on the screen and save it to a GFXcanvas16 (requires ~150kB RAM), then show how quickly the canvas can be copied from the screen and displayed. You could use the code from inside the for loop to read an individual pixel, noting that you need to discard the first "dummy read".
// Adafruit_ImageReader test for 2.4" TFT FeatherWing. Demonstrates loading
// images from SD card or flash memory to the screen, to RAM, and how to
// query image file dimensions. OPEN THE ARDUINO SERIAL MONITOR WINDOW TO
// START PROGRAM. Requires three BMP files in root directory of SD card or
// flash: purple.bmp, parrot.bmp and wales.bmp.
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ILI9341.h> // Hardware-specific library
#include <SdFat.h> // SD card & FAT filesystem library
#include <Adafruit_SPIFlash.h> // SPI / QSPI flash library
#include <Adafruit_ImageReader.h> // Image-reading functions
#include <SPI.h>
// Pin definitions for 2.4" TFT FeatherWing vary among boards...
#define TFT_CS 9
#define TFT_DC 10
#define SD_CS 5
SdFat SD; // SD card filesystem
Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys
Adafruit_Image image;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
void setup(void) {
Serial.begin(9600);
while(!Serial) delay(100); // Wait for Serial Monitor before continuing
tft.begin(); // Initialize screen
// The Adafruit_ImageReader constructor call (above, before setup())
// accepts an uninitialized SdFat or FatVolume object. This MUST
// BE INITIALIZED before using any of the image reader functions!
Serial.println(F("Initializing filesystem..."));
// SD card is pretty straightforward, a single call...
if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
Serial.println(F("SD begin() failed"));
for(;;); // Fatal error, do not continue
}
tft.setRotation(1);
reader.drawBMP("/LocalMapE5.bmp", tft, 0, 0);
GFXcanvas16 canvas(320, 240);
readPixelsToCanvas(&tft,&canvas,0,0,canvas.width(), canvas.height());
tft.fillScreen(0x0000);
tft.drawRGBBitmap(0, 0, canvas.getBuffer(), canvas.width(), canvas.height());
}
void loop() {
;
}
void readPixelsToCanvas(Adafruit_ILI9341* tft, GFXcanvas16* canvas, int16_t x, int16_t y, int16_t w, int16_t h) {
tft->startWrite();
tft->setAddrWindow(x,y,w,h);
tft->SPI_DC_LOW(); // Command mode
tft->spiWrite(ILI9341_RAMRD); // 0x2E
tft->SPI_DC_HIGH(); // Data mode
tft->spiRead(); // dummy read
for (int r = 0; r < h; r++) {
for (int c = 0; c < w; c++) {
// Serial.print(x+r); Serial.print(", "); Serial.println(y+c);
byte red = tft->spiRead();
red = (red >> 2) & 0b00011111; // need bits xRRRRRxx
// Serial.print("Red: "); Serial.println(red,BIN);
byte green = tft->spiRead();
green = (green >> 1) & 0b00111111; // need bits xGGGGGGx
// Serial.print("Green: "); Serial.println(green,BIN);
byte blue = tft->spiRead();
blue = (blue >> 2) & 0b00011111; // need bits xBBBBBxx
// Serial.print("Blue: "); Serial.println(blue,BIN);
int16_t RGB = 0; // need to combine to RRRRRGGGGGGBBBBB
RGB |= (uint16_t)red << 11;
RGB |= (uint16_t)green << 5;
RGB |= (uint16_t)blue;
// Serial.print("RGB: "); Serial.println((uint16_t)combined,HEX);
canvas->drawPixel(x+c,y+r,(uint16_t)RGB);
}
}
tft->endWrite();
}
Does anybody know how to implement a getPixel() or readPixel() for 9341 TFT controller ? I have an application where I need to save the pixel displayed at x,y location before write a new one at same location... I did not find in GFX library any function to do that...