Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

White spaces whilst reading from SD card #43

Closed
el-samiyel opened this issue Aug 29, 2022 · 9 comments
Closed

White spaces whilst reading from SD card #43

el-samiyel opened this issue Aug 29, 2022 · 9 comments

Comments

@el-samiyel
Copy link

Hi Larry,

After some support with an issue I am having, probably something I am doing wrong. When drawing from the SD card, I am getting horizontal white bars across the screen.

I have checked that I am drawing baseline jpgs and checked the return codes but cant see any immediate errors.

`#include "Adafruit_GFX.h"
#include <Adafruit_ST7789.h>
#include <JPEGDEC.h>
#include <SD.h>

#define TFT_CS 13
#define TFT_DC 5
#define TFT_RST 12

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
JPEGDEC jpeg;

void setup() {

Serial.begin(115200);
tft.init(240, 240);
tft.setRotation(3);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.println("Waiting for Arduino Serial Monitor...");

while (!Serial && millis() < 3000)
; // wait up to 3 seconds for Arduino Serial Monitor
Serial.println("ILI9341 Slideshow");
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(0, 0);

while (!SD.begin(2)) {
Serial.println("Unable to access SD Card");
tft.println("Unable to access SD Card");
delay(1000);
}
tft.startWrite();
}

// Functions to access a file on the SD card
File myfile;

void *myOpen(const char *filename, int32_t *size) {
myfile = SD.open(filename);
*size = myfile.size();
return &myfile;
}
void myClose(void *handle) {
if (myfile) myfile.close();
}
int32_t myRead(JPEGFILE *handle, uint8_t *buffer, int32_t length) {
if (!myfile) return 0;
return myfile.read(buffer, length);
}
int32_t mySeek(JPEGFILE *handle, int32_t position) {
if (!myfile) return 0;
return myfile.seek(position);
}

// Function to draw pixels to the display
int JPEGDraw(JPEGDRAW *pDraw) {
Serial.printf("jpeg draw: x,y=%d,%d, cx,cy = %d,%d\n",
pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight);
tft.startWrite();
tft.setAddrWindow(pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight);
tft.writePixels(pDraw->pPixels, pDraw->iWidth * pDraw->iHeight, true, false); // Use DMA, big-endian
return 1;
}

// Main loop, scan for all .JPG files on the card and display them
void loop() {
int filecount = 0;
tft.setCursor(0, 0);
File dir = SD.open("/");
while (true) {
File entry = dir.openNextFile();
if (!entry) break;
if (entry.isDirectory() == false) {
const char *name = entry.name();
const int len = strlen(name);
if (len > 3 && strcasecmp(name + len - 3, "JPG") == 0) {
Serial.print("File: ");
Serial.println(name);
tft.print("File: ");
tft.println(name);
jpeg.open((const char *)name, myOpen, myClose, myRead, mySeek, JPEGDraw);
jpeg.decode(0, 0, 0);
jpeg.close();
filecount = filecount + 1;
}
}
entry.close();
}
if (filecount == 0) {
Serial.println("No .JPG files found");
tft.println("No .JPG files found");
delay(2000);
}
}`

I modified your t3 example to work with that adafruit ST7789. A point in the right direction will be most appreciated.

Hardware: [Adafruit Feather M4 Express) SAMD51 120mhz.

Many Thanks

@bitbank2
Copy link
Owner

If your LCD and SD card are sharing the same SPI bus, then using DMA could potentially have both devices trying to access the bus at the same time. Try it without DMA (change the tft.writePixels parameters)

@el-samiyel
Copy link
Author

I see, yes they are sharing the same SPI bus, I have changed the DMA settings to false but still no luck: tft.writePixels(pDraw->pPixels, pDraw->iWidth * pDraw->iHeight, false, false); // Use DMA, big-endian

Are there any other areas I could explore in order to rectify?

Many Thanks

@bitbank2
Copy link
Owner

Do the white bars mean that the image is corrupt from that point down? Any data corruption in reading JPEG data usually means the rest of the image is garbage from that point onward. If you see white bars, but the rest of the image decodes properly, it probably means something is interfering with writing pixels to the LCD or the memory used for storing the pixels is being overwritten. Does it only happen on certain images, or on every image?

@el-samiyel
Copy link
Author

Its actually the latter, so I get: Good decoding for about an eighth of the image > white bar full width > good decode > 2 x white bar > good decode half the width of the image.

The white bars appear to be random in nature. I also tested with a T4 on an ILI9341 and get the same results, but the bars are in a different position.

This happens on very image, I also downloaded a fresh set of images ensuring they were baseline but got the same result.

What's interesting is that if I run the examples with images created out of C code, they load up just fine.

@bitbank2
Copy link
Owner

I can test this on the same hardware. I'll let you know what I find.

@countrysideboy
Copy link

IMG_4743
10
@bitbank2 I met same problem...

@bitbank2
Copy link
Owner

Can you send me the full code you're using to decode the image? It looks like an internal memory corruption problem.

@countrysideboy
Copy link

countrysideboy commented Nov 23, 2023

It is the callback function.
I use the default SD.h lib from the arduino of rp2040, and two independent SPI for screen and sdcard.
The e-ink screen driver is the GxEPD2.
Thank you for your reply, I will try to split the bloated code and post a complete example.
@bitbank2

void convert_rgb_565_to_rgb(uint16_t rgb565, uint16_t *r, uint16_t *g, uint16_t *b) {
  *r = (rgb565 & 0xF800) >> 8;
  *g = (rgb565 & 0x07E0) >> 3;
  *b = (rgb565 & 0x001F) << 3;
}

int JPEGDraw_callback(JPEGDRAW *pDraw) {
  yield();
  bool _with_color = true;
  uint16_t red, green, blue;
  bool whitish = false;
  bool colored = false;
  uint16_t color = GxEPD_WHITE;
  int x = pDraw->x;
  int y = pDraw->y;
  int w = pDraw->iWidth;
  int h = pDraw->iHeight;

  for (int16_t i = 0; i < w; i++) {
    for (int16_t j = 0; j < h; j++) {
      no_block_thread();
      convert_rgb_565_to_rgb(pDraw->pPixels[i + j * w], &red, &green, &blue);
      whitish = _with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80);  // whitish
      colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0));
      color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
      if (_with_color) {
        // keep color
      } else if (whitish) {
        color = GxEPD_WHITE;
      } else if (colored && _with_color) {
        color = GxEPD_COLORED;
      } else {
        color = GxEPD_BLACK;
      }
      display.drawPixel((x + i), (y + j) , color);
    }  // for j
  }    // for i
  return 1;
} /* JPEGDraw() */

@bitbank2
Copy link
Owner

The above code is extremely inefficient, but not necessarily wrong. I would like to see the rest of the app before I make any conclusions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants