16-bit parallel ILI9341/ILI9488/etc. displays with Teensies

Status
Not open for further replies.

Nominal Animal

Well-known member
Just out of technical interest, I've looked at a few different possibilities of connecting cheap 240×320/320×480 TFT display modules using 16-bit parallel connection to various Teensies.
The controllers are similar to ILI9341 and ILI9488, and can support much higher parallel data rates than via SPI. The problem is that because of the pins used on different Teensies, they really aren't that well suited for the 16-bit parallel connection (which really requires something like 19 I/O pins or more), and in many use cases a color look-up table is needed anyway, making DMA operation nontrivial.

I've looked at things like using an SRAM chip with two serial-to-parallel latching shift registers, where the SRAM output would be connected to the display in parallel, one serial would control the "palette" selection, and one would be used via SPI (MOSI/DO and SCK only) to emit the framebuffer data. For 8-bit framebuffer, one or two colors would be reserved for the 17-bit commands needed, leaving 254 or 255 colors for use. A second DMA could be used to emit just the palette selector for each pixel row, letting each row have their own palette. Alternatively, the display could be subdivided into rectangular regions with their own palettes. Chaining the two DMAs, with a few extra bytes per scan line (pixel data command parameters) would allow almost completely transparent DMA transfers.

Unfortunately, I could not find an option with the complexity and cost that would make sense to implement.

What I did find, instead, was a slew of cheap microcontrollers like ATSAMD51J20A, that could be used instead of the SRAM chips. All it needs to be a SPI slave at high clock frequencies for Teensies is a handful of jellybean capacitors, a 32768 Hz crystal, and a simple double-sided board any board fabricator like OSH Park, JLCPCB, and so on. The price for the components at Mouser in singles is on the order of 7-8€.

As I now have one (allegedly LG) 240x320 IPS panel with 16-bit parallel connection to its ILI9341 controller, and I really like designing boards in EasyEDA (noting that I am a bumblespork hobbyist only), I decided to look into how to make a carrier board for testing a SAMD51J20A, as a SPI slave for Teensy 3.0/3.1/3.2/LC/4.0 (me having all of those at hand).

Then, as usual, I got sidetracked. I found out about TPS82084, which is cheap but provides 3.3V from 3.3V-5.5V source very, very efficiently (90%+ at 1mA+ currents, 92%+ at 10mA+, according to TI Webench Power Designer), making it perfect component to provide a stable voltage from USB or single-cell LiPoly. (The linked "board" is a tiny 31mm by 11mm module that costs less than 3€ in parts from Mouser in singles.)
Unfortunately, I don't have a proper oscilloscope with the bandwidth or probes to find out how good that is in practice. (It uses a high frequency integrated shielded inductor, so it shouldn't spew EMI everywhere; I'd just prefer to check.)

I also realized that the SAMD51J20A has two 12-bit DACs, and I had those pins free, so I could add a simple headphone amplifier on it, and play with wavetable synthesis again (I was into music tracker software in late 90s, and know quite a bit of how they worked; SAMD51 would have ample power to implement a 8-bit/12-bit 8-channel tracker for music and sound effects). Capless headphone amplifiers are just a couple of euros in parts, and should work fine for this use case. Of course, I don't have any experience with analog audio and headphone amplifiers, so it'd take a bit of experimentation to see what kind of DAC voltage levels and biasing would produce the optimum audio levels and quality. Yet another sidetrack!

At this point, I am torn between whether to try and investigate the idea of SAMD51J20A as a pure cheap blitter/LUT/slave graphics processor for Teensies (connected via one or more SPI, I2C, and/or UART; with the framebuffer on Teensy, and the SAMD51 as just an accelerator/translator/blitter/helper), or instead see if I could make the SAMD51J into a really cheap handheld retro "console" instead. I'm not particularly interested in games, and don't intend to create any. It is this low-level tech that really interests me, and the design and testing as an investigation or exercise! My designs will be in public domain, and software libraries free/open source software (or CC0, I'm not fanatic although I prefer GPL in general).

So, my question is, is there anybody here interested in using a separate cheap -- complete cost including PCB in singles < 10€ -- microcontroller as an accelerator/blitter/translator between a Teensy and these 16-bit parallel displays, connected via SPI/I2C/UART? The same pinout can support 8, 9, 16, and 18-bit parallel. You'd have to buy the parts, order the boards, and put them together yourself; I won't be making any to sell.
 
I'll start with admitting that my knowledge is very limited on this topic, but being that I've been searching for a decent display for a project recently, we are fairly limited to SPI wiring with 16bit color scheme.
There are quite a few displays out there that support 16 bit data bus with SPI control or some other for of control that would be perfect for the size and visual capabilities - defiantly something I would be interested in testing out if it becomes available.
I think the bigger challenge is writing an optimised library that performs just as well as the current SPI displays, or even better.

Something that looks really cool is the Sony PSP display (480x272) @ 4.3". Although its 24bit RGB interface, something equivalent would be kick ass IMO if we can get it at a decent price.
 
Sorry I am probably missing something here?

If the main thing the board does is to do a parallel IO to the display, and talk back to the Teensy over SPI, I am not sure where the improvements are.

Now of course I can imagine if you are saying that you are going after something like an RA8875, where you have a set of primitives/macros you can send across, like draw a rectangle (x, y, w, h, color) and can simply send this off to the screen with a small number of bytes transferred over SPI, yes you can speed up these operations.

However the performance of the RA8875 is not great when you are doing things like sending images where you individually set each pixel.

So again it may really depend on what you are after.
 
If the main thing the board does is to do a parallel IO to the display, and talk back to the Teensy over SPI, I am not sure where the improvements are.
The helper SAMD51J20A does have 256k of RAM, which is enough for tiles, sprites and fonts, or for a 320×240 framebuffer. Since it is Arduino-programmable -- basically the same as Adafruit Feather M4 Express, except with a completely different pinout --, there are three main use cases:

  • Pixel format expander, color LUT controller
    For example, an 16×16-pixel 2-bit color tile, four colors per tile, takes 64 bytes. The helper can expand this transparently to the display 15/16/18-bit color.
    The comms format between a Teensy and the helper does not need to have anything in common with the display commands, so tiles can be sent with the color information, or the helper can store and use palettes. 1, 2, 4, and 8 bits per pixel color formats are all useful, and quite straightforward to implement.
    The limitation is that without a framebuffer on the helper, it is not feasible to support transparency.

    The intent is that a limited bit depth framebuffer on the Teensy is rapidly transferred to the helper, which expands it to full 15/16/18-bit color, and forwards to the display module.
  • Blitter for games
    Most of the 262,144 bytes of the RAM on the helper is used by tiles and palettes, and a couple of limited size tile maps. Teensy provides changes to tiles, tile maps, and the palettes, and the helper reconstructs entire frame data for each frame. This is similar to for example the video subsystem on Super Nintendo Entertainment System.

    The exact format (number of tile layers, bit depth, et cetera) is up to the user, and is really only limited by the available memory. Each pixel row is reconstructed from scratch in full 16/24-bit color, which allows for full transparency/opacity controls. The helper does have a single-cycle 32×32=32-bit multiplier, which allows for very fast RGB blending.
  • Interactive user interfaces
    User interface screens can be generated or loaded from an microSD card (SPI mode; although SDHC is supported by the hardware, the pinout interferes with the parallel connection to the display, so only "slow" SPI mode can be supported), with gauges, buttons (if touchscreen is used) et cetera, and event information transferred via SPI, I2C, or UART. (It is possible to use more than one; one for events for example, and another for other control or graphics information.)

    This type of display already exists, and has been discussed on this forum, too; the Digole displays for example.
I also like how the helper MCU approach can abstract away the display details, or be used to optimize a specific use case for a very specific display. Because of that, I think it is paramount for the helper MCU to be easily reprogrammable, and have as open/free license as possible. I really am only interested in creating a building block, and seeing what others can make of it.

I think the bigger challenge is writing an optimised library that performs just as well as the current SPI displays, or even better.
I probably should have mentioned that the software side is not a problem for me. Although, I do slightly prefer C over C++ for purely personal reasons, so my code tends to have plain-C interfaces instead of C++ interfaces (as is recommended/required for Arduino libraries, AFAICT).

a set of primitives/macros you can send across, like draw a rectangle (x, y, w, h, color)
Yes, except I am concentrating more on pixmaps and tiles and font rendering.

2D primitives only really make sense when there is a full framebuffer on the helper, and with 256k of RAM, that is only possible for 320×240, really. You can do an 8-bit framebuffer for 480×320, or maybe a 12-bit one (each set of 8 pixels taking 12 bytes), and I'd really like to implement an antialiased flat-color triangle, and maybe antialiased single-pixel wide lines, because those could really up the visual quality of typical gauges.. so I am most interested in pixmaps/tiles on one hand, and full-color framebuffers with opacity and antialiased primitives, on the other. (In the middle, or third vertex of the triangle, stands the graphics blitter stuff, i.e. reconstructing the entire display from tiles, scan line by scan line, at full color, but from paletted source data. Analysis paralysis!)

Something that looks really cool is the Sony PSP display (480x272) @ 4.3".
That is on the very upper end of what can be supported with just 256k of RAM. It might be possible to get a 15/16-bit (5 bits per color) full-color framebuffer; probably a 12-bit (4 bits per color, or 16 shades, or 4096 colors); or perhaps one could use only a part of the screen for the full-color framebuffer stuff... However, I haven't seen any with a parallel interface, only with RGB interfaces.

I'm pretty keen on image quality, too, so I'm concentrating on easily obtainable display modules with IPS panels.

The reason I picked SAMD51J20A as the helper MCU was because it is the cheapest one with 256k of RAM of the non-PIC variety, in a hobbyist-solderable QFP-64 package; that also happens to already be used in other dev boards (Adafruit Feather M4 Express) making the initial bring-to-function stage easier. I don't see any easy way to get more RAM, either. Something like a Teensy 4 variant with just a completely different pinout would be lovely, but BGA stuff is completely outside feasibility for me: I don't have a reflow oven, only a temperature controlled iron and a cheap hot air rework station. Heck, I'm even using free EasyEDA because of its ease of use and integration to JLCPCB!

So again it may really depend on what you are after.
And that is exactly why I posted this question. I don't have a particular use case in mind, as I am really just interested in implementing the nitty-gritty details (hardware and library support), and would simply love to see what nifty things others can build on top. Consider me the janitorial type inventor: I like to make reliable, robust tools and modules, not finished products. It is the technical challenge and problems to be solved that interest me, not any finished product.
 
FWIW, here is the EasyEDA project for the SAMD51 blitter board. While it can be used standalone, I really am envisioning it more like the boards used on most display modules their flat flex cable is soldered to, especially for use as a slave microcontroller to Teensies.
 
Status
Not open for further replies.
Back
Top