ST7735 with a parallel port

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using a ST7735 SPI display with an Arduino board. I'm using the code from the Adafruit library and it's too slow to render video game graphics at a framerate at least 50fps. The datasheet said that there's a version of ST7735 with a parallel port and I think that might be faster.

Does someone know if there's a ST7735 display with a parallel port?

If not that, is there another display with the 128x160 resolution and parallel port?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do the maths.
160x128x2x50 bytes per second. I make that 7.8 cycles allowed per byte @ 16MHz.
USART_MSPI is going to take 16 cycles per byte.
8-bit parallel would require some loop unrolling to transfer at that speed.
16-bit parallel would still be tight.

You could probably just manage with an Xmega that is reading an SPI flash memory with DMA and writing to the display on another bus.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What do you mean reading SPI flash memory?

For sending two bytes of one pixel to the 16-bit port:

out LCDPortHi, ColorHiCPUReg // 1 cycle
out LCDPortLo, ColorLoCPUReg // 1 cycle
sbi AnotherPort, LCDEnablePin // 1 cycle
// Do something like getting the next pixel
cbi AnotherPort, LCDEnablePin // 1 cycle

The picture will be rendered as tiles like on NES/SNES with sprites on top of that. I've seen Uzebox doing the same thing. However, Uzebox is timely challenged by NTSC while my game system won't be. It will be a handheld console like Gamebuino, but in color and higher resolution.

 

Also, just that you know, I'll be using Atmega2560 because it's supported by Arduino unlike XMEGAs with their 24-bit pointers and slow EBIs (yes, I quit from XMEGA (except if I'll need XMEGA for extra frequency) ).

Atmega2560 has 100 pins and that will be enough for a screen and much more hardware.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your maths is wrong.   SBI is 2 cycles.   You could use OUT PINx,WrReg which is 1 cycle.

 

For a word through 8-bit i/f:  OUT Port,HiReg / OUT WrPin,WrReg / OUT WrPin,WrReg /  OUT Port,LoReg / OUT WrPin,WrReg / OUT WrPin,WrReg

For a word through 16-bit i/f:  OUT HiPort,HiReg /  OUT LoPort,LoReg / OUT WrPin,WrReg / OUT WrPin,WrReg

 

Since you have 15.6 cycles available for a 16-bit color word,   it is quite possible.   e.g. 8-bit i/f needs 6 cycles and the 16-bit i/f needs 4 cycles.

 

This gives you 9 cycles or 11 cycles to load HiReg and LoReg from external memory and have some loop control.

 

LPM (with increment) instructions are 2 cycles each.   A SBIW / BRNE loop control is 4 cycles.   i.e. 8 cycles.

 

As you might have noticed,   4 cycles for loop control is very significant.    So you unroll the loop for say 16 pixels.   This is a worthwhile saving.

 

I still reckon that it is your job to do this maths.    You will soon see what is theoretically possible.    I guess that your "game" will actually require some intelligence.    Where do you have any spare cycles for your CPU to do any computation?

 

Be realistic.   Do you really need 50 FPS?   Do you need to re-draw a complete Frame every time?    Animating small sprites is a lot quicker.

 

David.

Last Edited: Thu. Jul 9, 2015 - 09:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The ST7735 is the 'chip-on-glass' TFT controller that is pressed against the TFT display inside the module.  Because the construction of the module is so precise and requires advanced manufacturing equipment, you are limited to the SPI interface of the module.  The easiest way to get faster on-screen results is to switch to a TFT module that uses a parallel interface. 

 

   The most common one is the 320x240 2.4" Arduino shield.  However due to the 'One-Hung-Low' factory copy of the original Adafruit design of this 2.4" module, the ones that you get delivered have a high possibility of being real kluuges.  I've bought three of these shields with the eBay description and cover photo of each being identical.  However on one the controller is the original ILI9325 and the other two have ST7781 controllers.  They have different [AFAIK] internal register structures because the ILI9325 library doesn't work on the ST7781.  Plus the 'One-Hung-Low' factory shields have the AVR reset line connected internally to the TWI SDA line (A4).  You have to cut the pin off the A4 line to get any I2C interfacing operational. 

 

    The OHL shield's eBay descriptions sometimes say that the TFT controller is SPDF5408, which is a Chinese factory model number for the assembled 2.4" TFT module and has nothing to do with the type of TFT controller installed in that module.  However, when you finally get them working, the 2.4" 320x240 TFTs look great and they all have a precision touch-screen included.  However even though they have parallel interfacing, they are not much faster than full-rate SPI, because the parallel port is split between two AVR parallel ports on the Mega328P-based Arduino UNO.  Instead of using Arduino Data0:Data7 with the full PORTD, they split the parallel interface to have six bits in PORTD and two bits in PORTB.  Still, a few assembler instructions embedded into the code both in the parallel linkage and into the Adafruit library makes them run very fast.  Or, use a 480x320 TFT connected to an Arduino MEGA2650.  They cost about $12 as opposed to $6 for the ST7735, but the speed and resolution is worth the cost.  Some of them use true 16-bit parallel interfacing so you can write data to the TFT at rates approaching one fully updated pixel per microsecond.

 

  I agree that 50 full frames/sec consumes too much bandwidth.  Cinema is about 24 frames/sec and television is 29 frames/sec. TFT controllers run fast when the area being updated is a specifically-defined screen rectangle.  So only change the areas of the image's frame that require immediate change.

 

Good luck, and keep us updated on your progress.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I won't use external memory if I'll be using Atmega2560. All tiles will be in progmem and they will be rendered. And why do I have to have 15.6 cycles? What if I go over that? I need to calculate when a sprite is incoming or when multiple sprites are overlapping each other. Maybe if I use less than 50 fps, I'll be able to have more time for the game engine. If the time will be too bad, I'll have to use XMEGA which opens the option for external RAM, but at 64kB or less because anything above will require extra pins, multiplexers and more latency.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't see Simonetta's post. If the refresh rate is above 24 or 29 fps, then I'll be forced to render at the refresh rate speed or at half that speed. So if it's 40Hz, then I'll have 20fps which is kinda low and I don't know will it even look nice. When I was programming video games at 30fps in Game Maker, the movement looked kinda weird because of that framerate. Oh well, I might use "it's retro" as an excuse for that. After all, it's an 8-bit processor there.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After all, it's an 8-bit processor there.

Which once again raises the question "why?". You customers playing games aren't interested whether it runs on a coiled spring, steam or elastic bands - just that the "user experience" is smooth and professional. You seem to be deliberately wanting to shoot yourself in the foot by the inappropriate choice of CPU. If it has to be 8bit AVR then why not 32MHz Xmega at least rather than 20MHz 2560?

 

Oh and your comparison to consoles is not really valid. Most of those had display processors that took a lot of the workload off the main CPU so it just had to run the "logic". Even a Commode 64 had "SID" and "VIC-II". In the home computers I worked on (Amstrad CPC) there was at least a 6845 doing the video generation and effectively dual-porting the video buffer RAM (the 6845 "stole" every 4th Z80 T cycle). When we made the CPC 464/6128+ and GX4000 consoles we then developed an ASIC to do things like sprites.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Which once again raises the question "why?". You customers playing games aren't interested whether it runs on a coiled spring, steam or elastic bands - just that the "user experience" is smooth and professional. You seem to be deliberately wanting to shoot yourself in the foot by the inappropriate choice of CPU. If it has to be 8bit AVR then why not 32MHz Xmega at least rather than 20MHz 2560?

Because that's what the creator of Gamebuino did. His customers really like it when something little does something big. He did well on Kickstarter. That was because his stuff was supported by Arduino IDE which was popular. For me it's a bad IDE, but for others, they like it so much. XMEGA isn't really supported and it needs some special tweaks to make it work. If an XMEGA project can get popular without Arduino, I'd like to see that happening.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gamebuino has got a 84x48 mono screen implemented in STN LCD.

 

SuperTwist Nematic LCDs generally have a pixel switching time of about 100ms..200ms so if you try to run faster than about 5..10fps the display just blurs.

 

In fact you can already see that happening in their videos:

 

 

But give them the benefit of the doubt and assume they want to drive it at 10fps. Because it's mono it's going to be 8 pixels per byte so a frame is 84*48/8 bytes. That is 504 bytes. They are updating at 10 frames per second (say) then that is 5040 bytes/sec.

 

Now, your opening post here said 128x160 using ST7735 at 50-fps. I presume you are talking about a display like this:

 

http://www.amazon.co.uk/Adafruit...

Adafruit 1.8 inch TFT LCD Display with MicroSD Card Breakout (128x160, 18 Bit)

 

That is an 18bit display. In theory that would be 3 BYTES per pixel, though to speed things up you could run it in an almost indistinguishable 5-6-5 mode using 16 bits (2 bytes) per pixel. 

 

So now look at your stats:

 

128 x 160 x 2 x 50 = 2,048,000 bytes per second.

 

As I say the Gamebuino seems to be shuffling about 5,040 bytes per second. So you are talking about 406 times as much data per second.

 

AVRs are quick but I think you'll find there's a reason why the Gamebuino lads picked a mono 84x48 LCD with 100..200ms LCD !

 

If you want to use a screen like this AND an 8 bit CPU then do what the early consoles and hand-helds did and hand off some of the display driving overhead to a "display processor" and keep the central CPU for running the actual game logic.

 

BTW here's a spec of the original Gameboy:

 

http://marc.rawer.de/Gameboy/Doc...

 

The display area was 160x144 window onto a 256x256 background plane. The pixels were 4 grey level (so 2 bits each). If one considers only the display area then a frame is 160x144 / 4 = 5,760 bytes. It says the Vsync was ~60Hz so even assuming an update per Vsync that is still just 345,600 bytes per second and clearly all the tiling and sprite support is being done by some kind of hardware assist so it's not relying on the main CPU to render the entire display for every frame anyway.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would get a display processor or something like the NES PPU if there was something without copyright/patent restrictions like the old console hardware which is expensive because of its rarity for AVR to communicate with and at a good speed. Let's say that it has a tile based independent rendering with background and sprites and has a VRAM with pattern table, name table, attribute table and OAM just like the NES PPU and the GameBoy's LCD chip. If that chip could communicate with AVR and a TFT screen, I'd be happy with that. I just can't find those things no matter how hard I try Googling. Maybe I'm using wrong terminology. I'm getting some graphics cards instead of integrated circuits.

 

If the display processor will be another Atmega, it won't make it with 16MHz. Uzebox used Atmega664 overclocked to 28.6MHz and with 8x8 tiles and 240x224 resolution, it has only 20 sprites on screen. If I use XMEGA for more speed, it will raise the price of the console and it's stupid to leave a lot of pins unused on it. I could use it for sharing VRAM with another XMEGA that runs the game for loading the sprites. Now that's 2 XMEGAs and 1 dual port SRAM that hopefully will be compatible with both EBIs and that EBIs won't generate too much lag. I might overclock the XMEGA, but I'm not an expert at that and I think it might overheat or something might "break" inside. I don't want to do that unless I get explicit instructions.

 

If GameBoy LCD was on Adafruit along with a dual-port SRAM (as its VRAM), my problems would be solved. Then I could focus more on the game engine itself like using the VLSI1053 chip, SD card, Flash storage chip, accellerometer, multiplayer over TWI and so much more with the rich library of Arduino. Except if the library for the Atmegas isn't compatible with Xmegaduino boards. Then I'll have to write from the ground up, but that wouldn't be too bad, just some extra time spent with reading the datasheet and writing SPI.h, USART.h, TWI.h, etc. functions. Or I could use Atmel Studio's libraries, but they wouldn't be compatible with the Arduino's pin definition mechanism like #define MISO 69 or #define SOME_ENABLE_PIN 34.

 

Please correct me if there's something wrong with what I wrote and tell me if there's a better idea.