Teensy 3.2 / Adafruit ST7735 / spitftbitmap Example - Image is off the screen?

Status
Not open for further replies.
The 80x160 LCD has the same internal buffer as the 128x160 (same ST7735 controller), but the display is offset. In my bb_spi_lcd library I have different settings for the 128x160, and 80x160 displays and the difference is a x,y offset of the upper left pixel. The 80x160 displays that I've tested start the visible display at x=26, y=1 or x=24, y=0 (depends on the display).
 
I tested using Teensy 3.2 and Adafruit's display with the ST7735_t3 library. Ran the "spitftbitmap" with a Sandisk Ultra 16GB card. I used Teensyduino 1.53-beta3 and Arduino 1.8.13. Works fine.

st7735_1.jpg

Here's a photo of the bottom side wiring, so you can see the correct connections which work with that example (no edits to the example).

st7735_2.jpg
 
Yes you are right it does not work... It reads the file.

The issue is when we added SPI.transaction support, it really did not work well with
sketches that: tft.setAddrWindow(x, y, x+w-1, y+h-1);

and then call tft.pushColor as the SPI transactions ended inbetween these calls and as such the display did not like it...

I thought we added some hacks to allow this to work on some displays...
We also had better ways of displaying the data...
 
@Paul and ... Now I am remembering some more.

Earlier I did try to put in some support for this into display code, to disable the calls to
Code:
void ST7735_t3::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
	beginSPITransaction();
	setAddr(x0, y0, x1, y1);
	writecommand(ST7735_RAMWR); // write to RAM
	// The setAddrWindow/pushColor will only work if SPI is kept active during this loop...
[COLOR="#FF0000"]	//endSPITransaction();[/COLOR]
}


void ST7735_t3::pushColor(uint16_t color, boolean last_pixel)
{
	//beginSPITransaction();
	if (last_pixel) {
		writedata16_last(color);
		endSPITransaction();
	} else {
		writedata16(color);
	}
}
Note: the line in RED is different, never checked in that change... It was/is unclear to me how this can ever work.
Maybe at times by luck.

That is logically: the draw function, here calls the setAddrWindow: will output the stuff for the start of the data, like the <2a> x x <2b> y y <2c>

And then it is expecting that user code will call the pushcolor stuff which has to do things like, make sure we are in 16 bit write mode. This is different for T4 versus T3. We have to update the state of TCR and the code sort of assumes it knows what the previous state of TCR was.

Also in both cases of T3.x and T4.x it leaves the queue with data in it... So again it may be at the mercy of what other SPI code is called during that time...

I will try some different hacks to see if that helps.
 
Thanks everyone.I am pretty sure my wiring is fine.I will try a different SD card. I am testing the speed at which different microcontrollers can send a bmp to the tft to display an image. I have an UNO, and teensy 3.2, an esp8266, and a teensy 4.0.The UNO is pretty slow , the teensy 3.2 seems quite a bit faster according to some videos I have watched.The ESP is supposedly faster, but there are issues with the SPI and the sd card and tft and I read that the teensy 4.0 works best if the images are stored in the flash memory rather than reading from an SD card reader. I am curious as to how much difference the speed of the microcontroller makes.it seems like the bottleneck is the transfer of data from the SD card into the microcontroller.I found a hack online that allows an arduino UNO to play 20 fps video.it requires some modification of the tft and some circuitry.it works by transferring data directly from the sd card to the tft and bypassing the microcontroller.This allows an image to be uploaded to the screen in aobut 50ms.I had an electronics company make a tft with an arduino NANO and the circuitry to bypass the microncontroller all mounted on to the back of the tft with a microSD card.You convert a video file into a .raw file and the software uses the USART in SPI mode to directly transfer the raw file data to the tft. It works great for playing video and I used it to make vdieo display screens for my Moebius models 2001 EVA pod. https://www.youtube.com/watch?v=R7K6FDaAGIA
 
@KurtE
Sorry was busy soldering up a couple more T4.1's.

Was the hack we put for drawing from SD Card was in the sketch itself - we used drawRect for the scanline?
 
@mjs513 (@Paul) - Yes the best fix is to rework the function.
Actually I just did a copy of the function directly out of my ili9341_t3n version into the example here,
with 1 edit in ili9341_t3n it is color565 in St7735_t3 it is Color565...

Code:
// Try Draw using writeRect
void bmpDraw(const char *filename, uint8_t x, uint16_t y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint16_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();

  uint16_t awColors[320];  // hold colors for one row at a time...

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print(F("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if (!(bmpFile = SD.open(filename))) {
    Serial.print(F("File not found"));
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        for (row=0; row<h; row++) { // For each scanline...

          // Seek to start of scan line.  It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding.  Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            awColors[col] = tft.Color565(r,g,b);
          } // end pixel
          tft.writeRect(0, row, w, 1, awColors);
        } // end scanline
        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println(F("BMP format not recognized."));
}
And it draws correctly
 
Paul I create a Pull Request with it using the drawRect code to output one scan line at a time...
https://github.com/PaulStoffregen/ST7735_t3/pull/18

Could do this just for T4.x - But I believe it is problematic on T3.x as well, especially if the CS pin is NOT a hardware CS pin, as who controls the assertion and deassertion of CS on for the display when the code decides to go and read something from SD card which asserts it's own CS... You could get away with it on T3.x as it was encoded in the PUSHR instruction, assuming that whatever other SPI stuff you might do, does not much with the CTARS, or decide to clear the FIFOS or ...
 
Still not working.The wiring is fine.The bmp is fine.I used a new 16bg microSD card and the .bmp loads up onto my pc and the serial monitor shows the teensy is reading the card.I did put a 10K resistor on the Card_CS wire as someone suggested.Here are pictures of the serial monitor and the image that is displayed.The same display works fine with an Arduino UNO.Not sure what is going on.I tried a different teensy 3.2 and got the same result.serial monitor.jpgparrot.jpg
 
Those look like some pretty long wires! And that display... which one is it? Doesn't look like Adafruit.

For Teensy, try reducing the speed with Tools > CPU Speed. 24 MHz is the slowest where USB still works. Give that a try, as it will limit the maximum SPI speed to only 12 MHz. Maybe this could be just a case of hardware that isn't able to run at the normal (fast) SPI speed Teensy uses?
 
Works for me:
IMG_0266.jpg

Probably the next real question is what is your display? What are you actually running on the UNO? Could you list or include your actual sketch that you ran on the UNO... Might give hints like what you are actually configured for.

That does not appear to be an Adafruit display. Is it an ST7735 or an ST7789? As it does not appear to be Adafruit, and I don't see any obvious markings on the top of what each pin is, can not tell again which wire is which and for example if it has a CS pin for the display. There are some cheap ST7789s that don't have a CS.

Also one of these days we should maybe extend this example, like we did for some of the others to show some of the other configurations, like for ST7789.

So if I see what your UNO is setup for, I can try to make it work for you on the Teensy...
 
Actually now I think it is the BLACKTAB that should be used.

I don't have the Adafruit 1.8" version but I do have one by HiLetGo...
https://smile.amazon.com/gp/product/B00LSG51MM/

Took me a bit to hook it up again as their wiring labeling is a bit screwy
6108TFNRXkL._AC_SL1010_.jpg

But here it is running on T3.2 with the SDCard...
IMG_0267.jpg

Debug output:
Code:
nitializing SD card...OK!



Loading image 'parrot.bmp'
File size: 61496
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x160
Loaded in 167 ms
 
I got it to wrk.All I did was go to github and copy the spitftbitmap sketch there and paste it into Arduino IDE.Now I get the parrot image to upload.The upload spped I am getting is aobut 530ms.I noticed you got 167 ms, but that was a different tft.My tft is an adafruit one.It has their logo on the back.
 
@Kurte I also have the same tft as you used in your last example.Can you list the pinouts.This screen has some weird pins like SDA.Thanks
Carl
 
@Kurte I also have the same tft as you used in your last example.Can you list the pinouts.This screen has some weird pins like SDA.Thanks
Carl

As mentioned the labels on the back of these displays are confusing at best.
What I hooked up:

Just Display:

VCC=VUSB, GND=GND,
RESET=8
A0 is DC = 9
SDA (DATA = MOSI) = 11
SCL (CLOCK = SCK) = 13
CS = 10
LED+ = 3.3v (backlight)

And that was enough for running graphics test.

But for this test, needed SDCARD, which I believe are not connected to the display with the pins so:
SCK = 13
MISO = 12
MOSI = 11
SD_CS = 4 (SD Select can be any digital pin)
 
@KurtE Thank you for all of your help got the tft working great. I really appreciate the time you guys took to help.

Carl
 
So I am looking at the imnge and for some reason the red pixels are not beign displayed properly.I tried this with 2 different Adafruit boards.I am using the spitbitmap sketch from github, but the st7735_t3 library has disappeared from Github now and when I use the file on the examples already installed in my library I get the vertical lines I posted previously.
 
If you went off of my fix branch it was merged into Paul’s master branch and released with the latest release of teensyduino
 
There is an error in the coding for spitftfbitmap when the colors are decoded. I changed the r g b order in the following lines. It originally had it as b g r .Switching it to r g b fixed the colors

// Convert pixel from BMP to TFT format, push to display
r = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
b = sdbuffer[buffidx++];
awColors[col] = tft.Color565(r,g,b);
 
There is an error in the coding for spitftfbitmap when the colors are decoded. I changed the r g b order in the following lines. It originally had it as b g r .Switching it to r g b fixed the colors

// Convert pixel from BMP to TFT format, push to display
r = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
b = sdbuffer[buffidx++];
awColors[col] = tft.Color565(r,g,b);

On linux/windows the parrot has red shoulders in parrot.bmp, and the fix to example spitftbitmap.ino in post #48 gives the parrot the desired red shoulders. There may be other bmp examples in the lib that need fixing. Curiously, parrot has red shoulders in Paul's photo in post #27 ?? Kurt's photos do not have red shoulder.
 
On linux/windows the parrot has red shoulders in parrot.bmp, and the fix to example spitftbitmap.ino in post #48 gives the parrot the desired red shoulders. There may be other bmp examples in the lib that need fixing. Curiously, parrot has red shoulders in Paul's photo in post #27 ?? Kurt's photos do not have red shoulder.

I think I figured it out...
My guess is Paul used the example sketch without modifying it. So it is configured:
Code:
  // Use this initializer if you're using a 1.8" TFT
  tft.initR(INITR_BLACKTAB);
  // Use this initializer (uncomment) if you're using a 1.44" TFT
  //tft.initR(INITR_144GREENTAB);
Which on my 128x128 ST7735 display shows up with RED as you mentioned... HOWEVER I am using the smaller display so I modified sketch to use: GREENTAB...

So I am fixing the example sketch to update the color order as mentioned. In addition I put in ST7789 init stuff, plus have it cycle through fillScreen, with RED, GREEN, BLUE with the color of the screen printed in black centered with half second delay between each to show that we have the right colors... On the one that I believe Paul ran those colors will show up wrong.
 
Status
Not open for further replies.
Back
Top