1.8" LCD SD SPI blitting

EL Wire/Tape/Panels, LEDs, pixels and strips, LCDs and TFTs, etc products from Adafruit

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

1.8" LCD SD SPI blitting

Post by xenoc »

Hello,

I've been working on a project (https://github.com/lewisd32/ArduinoSlideShow) using Adafruit's 1.8" TFT LCD breakout with the SD card slot. The idea is to turn an old film slide viewer into an LCD slide show. The project's working pretty well, I have a button under the slide slot, and I cut the film out of a slide and mounted the LCD to it. When you push the "slide" down into the slide viewer, the button is depressed, and the screen comes on. When you release it, I turn the backlight off, and update the photo on the screen, so that it's ready to show when the "slide" is pushed down again.

My problem is this: It takes about a second to draw the image on the screen. If I check the button while I'm drawing the image, then releasing the slide and quickly (less than a second) press it again, the backlight comes on immediately, and you can see the image being drawn. If I don't check the button, then pushing it down again quickly doesn't respond for 1/2 a second or so, which is arguable worse.

I think the code I'm using is already close to optimal, and is simply being limited by the Arduino's limits on how fast it can operate the SPI bus.

Code: Select all

  for (uint8_t x = 0; x < w; ++x) {
    for (uint8_t y = 0; y < h; ++y) {
      file.read(buf, 3);
      r = buf[0];
      g = buf[1];
      b = buf[2];
      tft.pushColor(tft.Color565(r,g,b));
    }
  }
I've thought of doing some old 80's coding tricks like reading more than 1 pixel at a time from the SD card, and loop unrolling, but I'm not sure they'll provide much benefit, given how simple the AVR architecture is.

I can't help but wonder, since both the LCD and the SD card are on the SPI bus, and it seems to be the Arduino itself that's limited in the speed it can operate the SPI bus, is there some way to pass chunks of data directly from the SD card to the LCD? I already write the images to the SD card (from my PC) in a raw format that makes blitting them easier and faster, so changing the file format isn't an issue. I wonder if there's some way to tell the screen that it's about to receive 128 pixels, and then tell the SD card to read the next 128*3 bytes of the file, and have them go straight from the SD card to the LCD, rather than having to go via registers in the Arduino.

Has anyone experimented with anything like this?

User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

Re: 1.8" LCD SD SPI blitting

Post by xenoc »

Update:
I've changed things so the files are stored in the SD card as RGB565, so now I can just read 2 bytes from the file, and send them unmodified to the LCD. It does speed things up a bit, but it's still not fast enough. I've also done some unrolling, so it's reading 8 bytes, and sending 4 pixels, each iteration. Doing that didn't seem to make much difference though.

I'd still like to try and see if there's some way to read chunks (8 bytes or more) from the SD card directly to the LCD controller, but I don't know where to start attempting that sort of thing.

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: 1.8" LCD SD SPI blitting

Post by adafruit_support_mike »

Take a look at the 'spitftbitmap' sketch included with the library. That uses 'tft.pushColor()' to send pixels to the display.

You should be able to use that to interleave reading data and writing to the display.

User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

Re: 1.8" LCD SD SPI blitting

Post by xenoc »

Yeah, I started with that example sketch, but I'm trying to make it faster. Much faster.

I do have a few less crazy ideas to make reading an image from the SD card and writing to the screen faster (I'm going to try it and submit a PR on the library for a putPixels [note the plural]), but all of them still involve the same fundamental pattern, shaken or stirred in various ways: Read data from the SD card into the memory on the Arduino, then write that data from memory to the LCD controller.

What I'm wondering about is if there's some way to leverage the fact that they're both SPI devices, and (maybe with some additional parts) send the bits directly from the SD card to the LCD controller, with the Arduino just supplying the clock signal. Something along these lines: (ignoring the complexities of the FAT library for the moment, because this might work better using the SD card as raw storage instead)
0. Call tft.setAddrWindow to set up the area of the screen to receive an image
1. Prepare to read some data from the SD card, but don't actually tell it to send the data yet.
2. Tell the LCD that it's about to receive pixels
3. Set up any supporting hardware so that the data-out line on the SD card is connected to the data-in line on the LCD controller.
4. Tell the SD card to send the data.

If the data is stored on the card in RGB565 format, which is what the LCD controller expects, then I would expect this to be approximately twice as fast as reading it into the Arduino's memory, and then sending it to the LCD controller. For drawing a full screen image, or even for blitting many small sprites, this could make a huge difference.

I think doing this would involve connecting the MISO pin from the SD card to the MOSI pin on the LCD controller. That can't normally be connected though, or the Arduino would be unable to communicate with anything, since that would short the MISO/MOSI pins, so I think there would need to be some additional hardware, a buffer or muxer or something, to toggle between two modes: normal and SD->LCD mode.

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: 1.8" LCD SD SPI blitting

Post by adafruit_support_mike »

In theory you could connect the SD card's MISO to the TFT's MOSI and clock data from the card to the display. You'd need to multiplex both MOSI and MISO so the Arduino could send the display commands between data bursts though.

The logical extension of that idea would be to use an SPI SRAM chip as a buffer. Write the entire control-bit sequence to that while one image is on screen, then clock it all through to the TFT when it's time to display a new image.

User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

Re: 1.8" LCD SD SPI blitting

Post by xenoc »

That's quite the logical extension. :) I guess to be as fast as possible, you'd probably also want an external clock to handle the clocking of the data from the SD card to the LCD. ;) I have no idea what speed SPI bus the LCD controller supports.

As far as eeking out some extra speed with minimal extra hardware though... do both need to be multiplexed? I could be misunderstanding something here, but I *think* that if the MOSI on the LCD was multiplexed between the MOSI on the Arduino, and the MISO on the SD card, that would be sufficient.

There's three flows that need to happen:
1. Arduino read/write from SD - nothing's multiplexed there, just regular wiring.
2. Arduino read/write from LCD - multiplexer set to connect Arduino MOSI to LCD MOSI, as per standard wiring.
3. SD write to LCD - multiplexer set to connect SD MISO to LCD MOSI (and also disconnect the LCD MOSI from the Arduino MOSI)

I drew a little diagram of how I think it might look:
http://imgur.com/jEaT4A3
The bottom one is the SD card, the label got cut off in the photo.

I think it's actually a 2:1 demux that's needed, not a multiplexor? I always get the two backwards. If that's the case, I wonder if it could be done with two output pins, two transistors, and a handful of resistors. Whatever it's done with, I guess it'll need to run at 4MHz to handle the SPI bus speed?

User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

Re: 1.8" LCD SD SPI blitting

Post by xenoc »

Well, adafruit_support_mike, you were right. :) I do need to multiplex both. I wired up that previous diagram, and it didn't do much of anything. I think the problem was that when trying to clock data from the SD to the LCD, the LCD is receiving data, and, I think trying to respond on it's MISO pin, which is connected to the SD's MISO pin, which is sending the data to the LCD.

I grabbed a 74LS241 yesterday, which seems almost perfect for this. It's an octal line driver with tri-state outputs, which is the real key. It's set up so there are to banks of 4 input/output pairs each. The thing that's great about the 241 in comparison to it's siblings is that the enable pins for the two banks are the reverse of each other, one is active high, the other is active low. That means I can just wire a single Arduino output pin directly to both enable pins, to toggle between bank 1 and 2 being active. Whichever bank is inactive has high impedance outputs, so they won't interfere with the rest of the circuit.

So, with that in mind, I drew up a new circuit:
http://imgur.com/tpRqgLC

And what do you know, it works! Without (or with, but they're not required) the dotted lines, and D6 set low, it functions like a normally wired SPI bus with the Arduino, LCD, and SD. With the dotted lines wired in, setting D6 high, the Arduino can still send and receive data from the SD card, but any data it receives from the SD card also goes to the LCD screen. Since my test program is still naively using FAT on the SD card, what shows up on the LCD is pretty scrambled, but it does show something, so I'm pretty excited that this is actually working. And, as expected, it's about 2x as fast as my previous fastest image blitting code. Down to 187ms from 351ms.

Here's the mess of breadboarded wired, and the type of scrambled image I'm getting, which I believe is due to FAT data being transferred to the LCD screen:
http://imgur.com/K0KbPW2

Someone on another thread viewtopic.php?f=47&t=52066#wrap showed me a way of storing files in contiguous blocks on FAT, so I'm going to try that, and see if it eliminates the scrambled display.

User avatar
xenoc
 
Posts: 30
Joined: Thu Sep 15, 2011 2:26 pm

Re: 1.8" LCD SD SPI blitting

Post by xenoc »

Success! I have it working with the last circuit diagram I posted, and some custom SD reading code. It'll draw the image in 99ms now. I need to rewrite a bit of incredibly messy code, but I'll post it when I'm done that. The circuit itself is exactly as described in my previous post.

Locked
Please be positive and constructive with your questions and comments.

Return to “Glowy things (LCD, LED, TFT, EL) purchased at Adafruit”