Small TFT display, 5x5cm, for moving graphics, over SPI - Page 1
Forum section: electronics / projects

author: peter-h
author_rank: Super Contributor
timestamp: December 07, 2021, 08:02:36 pm
content: This came up herehttps://www.eevblog.com/forum/projects/oled-dot-matrix-display-life/msg3859394/#msg3859394but I haven't found anything suitable. What do people use?I can see there are some standard controller chips for dot matrix LCDs and maybe everybody in this business is making their own custom display. I am not after any video type graphics (obviously any picture could be drawn, given time); just stuff that moves around slowly. I can send out 2MB/sec (21mbps) over SPI which is plenty fast enough in theory for say a 256x256 display.It has to be SPI because that's all I have

author: ataradov
author_rank: Super Contributor
timestamp: December 07, 2021, 08:39:14 pm
content: https://www.buydisplay.com/would be the best source for displays with good documentation and guaranteed supply longevity. They have a number of SPI displays in that general size group.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 07, 2021, 09:30:07 pm
content: There're lots of 240x240 st7789 spi displays.

author: peter-h
author_rank: Super Contributor
timestamp: December 07, 2021, 10:04:58 pm
content: Yes; thanks very much to both of you. These looks good, and are very cheap.I see some e.g.https://www.buydisplay.com/3-5-inch-tft-lcd-color-module-in-320x240-touch-screen-lq035nc111use the HX8238 chip which specs the max SPI clock at 20MHz which is pretty good.The ST7789 controller has a much faster SPI speed of about 60MHz (16ns min clock cycle).

author: peter-h
author_rank: Super Contributor
timestamp: January 12, 2022, 01:13:43 pm
content: Well, more than a month later, three of these arrived from China. Turns out the connector is 0.7mm pitch - could not work that out from the data sheet.Now, how does one do something with it, short of reading the entire chip reference manual?

author: ajb
author_rank: Super Contributor
timestamp: January 12, 2022, 05:08:06 pm
content: Quote from: peter-h on January 12, 2022, 01:13:43 pmWeird that they didn't dimension the pitch directly, but it's indicated in the dimension from pin 1 to pin 12 in the drawing. That looks like an FPC designed for soldering, not sure if you'll be able to find a mating connector for it.QuoteYou use one of the existing libraries that supports the controller, although this is not guaranteed to avoid any reading of the datasheet at all, depending on the quality of the library and what assumptions it makes about your hardware. Of course you'll need to read the parts about the connector pinout and the electrical requirements.Buydisplay should offer some sample code for initializing the display on the product page, using pretty simple write commands, and getting that sequence right is important. The controller will need to have certain configuration options set to match the panel it's driving, and the sample code will include those. So if you're not using a library (or even if you are, since the library may assume a different panel with different configuration requirements) then that's a good place to start.I've done my own code for dealing with a couple of different displays, and you don'tquiteneed to read the whole manual for the controller, although you will need to read a lot of it to understand how the display's memory space is arranged and mapped to the display, and how the write commands interact with it. Once you have the basic functionality of setting specific pixels to specific colors it's not that hard to start building up more useful functions from there to fill rectangles, copy images from memory, write text in fonts, etc. This is really useful for converting standard fonts to a form that's easy to use in embedded systems:https://github.com/pavius/the-dot-factory

author: peter-h
author_rank: Super Contributor
timestamp: January 27, 2022, 04:25:07 pm
content: I got this onehttps://www.buydisplay.com/1-54-inch-tft-lcd-display-ips-panel-screen-240x240-for-smart-watchand mounted it on one of the adaptor PCBs off Ebay.It's gonna be amazing if I manage to get some pixels set... 1 pixel is sufficient to prove the conceptBut just how much code will be needed to set 1 pixel?The chip is an ST7789. Read through the whole 317 page data sheet. Curiously 3.3V is at the top of their max supply - but well below absolute max.Not found any straightforward code for it; most of the stuff online is for arduino and similar projects where it's all been done for you. I am looking for some straight C code for init of the chip and then drawing some vectors. One surprising thing is that this chip is no more than a "memory map for an LCD". There are no commands for drawing even the simplest things, not even filled rectangles. And no text. This is OK; in most cases those commands aren't particularly useful, and I will have a 21mbps SPI available, fed via DMA, so genuine 2MB/sec.This looks like worth a closer lookhttps://www.ramtex.dk/display-controller-driver/rgb/st7789.htmIt is around £500.The algorithms for drawing vectors, circles, etc, are a well worn thing; I was doing that in the 1980s on a Z80. In practice one normally prefers to not set or clear individual pixels because usually that is just too slow even at 21mbps. So one copies chunks of RAM.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: January 27, 2022, 05:17:14 pm
content: I forget how different that one is, compared to the ST7735. I think I remember seeing it in Adafruit's drivers too? Anyway, that's what I used as a starting point, put it into C and tightened up for my purposes.https://github.com/T3sl4co1l/st7735_gfxAlso, the image routine uses the encoder in the same repo; it's a slightly richer RLE format (without much optimization spent on minimizing file size, alas..). It works well enough for flat-shaded images, and runs pretty fast on the hardware.Animation is possible on such a thing, but you'll need either full speed SPI (and an MCU to drive it; most any ARM should do) or only limited update regions.Tim

author: peter-h
author_rank: Super Contributor
timestamp: January 27, 2022, 06:10:13 pm
content: Yours looks like a handy set of basic functions. I will probably try that first.It doesn't look like you are using any significant buffer RAM, which is good.

author: ajb
author_rank: Super Contributor
timestamp: January 27, 2022, 09:47:05 pm
content: Quote from: peter-h on January 27, 2022, 04:25:07 pmDid you look at the "8051 Interfacing and Demo Code" download from the product page? ST7789V.h in that zip file has what you need. There's even a bitmapped font in there. Annoyingly they use hex values for all of the commands rather than defining or enuming meaningful names for them, but you can cross reference to the datasheet to figure out what's going on and replace them. They also use very basic blocking write functions which you can replace with your own method using DMA or whatever if you want.

author: peter-h
author_rank: Super Contributor
timestamp: January 27, 2022, 11:13:24 pm
content: Yes I saw. They even seem to do a software SPI.Interesting also there is noreadof the frame buffer via SPI. That's OK.I am trying to work out just how much abstraction is involved. The chip data sheet is massively complex. The RAMTEX package is very powerful but I can't see the code until I buy itAt a basic level the API should be simple: draw an object at x,y.

author: ajb
author_rank: Super Contributor
timestamp: January 28, 2022, 06:34:47 am
content: I'm not sure what you're looking for then. The example code from Buydisplay gives you what you need to initialize the display, command by command (including, usually, some panel-specific setup values that you'll need), and set individual pixels, and you can build up from there. Or you can use the arduino style libraries where everything's done for you.There is really no abstraction within these display controllers. Generally you set the area you want to write to (usually defining a rectangle of pixels within the display area) and then you throw color values at it and it stuffs them into the write area one pixel at a time. Anything above that is up the user. The example code for this display in particular looks to be more comprehensive and better organized than some others I've seen from them, with line drawing and even text functions included.

author: peter-h
author_rank: Super Contributor
timestamp: January 28, 2022, 06:59:45 am
content: The 8051 code is going to be great for getting this going - many thanks. I might have a go at T3sl4co1l's code first though - a bit more readable.The driver chip needs two GPIO lines: CS and D/C (data/command), otherwise you need a 9 bit SPI mode which the 32F4 doesn't have.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: January 28, 2022, 10:21:35 am
content: Reading requires hardware, so it's not the most trivial thing to set up. Most MCUs have MOSI/MISO not SDA. Some support the bidirectional mode directly, or by swapping RX/TX pins perhaps. Others it's fixed and you have to wire a resistor between them, so that MISO receives loopback from MOSI (discarded) or SDA (save data) when the panel is outputting. (Not much hardware at all, indeed, but it is more than zero I mean.)MCUs also don't have much RAM for the most part, so a function like read-into-buffer can be dangerous / tricky to use. And when they do, you're better off just making a frame buffer in software, and always doing writes from that (with whatever partial/full updating you care to do).Tim

author: peter-h
author_rank: Super Contributor
timestamp: January 28, 2022, 01:45:37 pm
content: ISTM that these displays are intended to run with standard SPI controllers, which can do either direction.One advantage of reading back the display's frame buffer is that you don't need to keep track of what was in that area (probably a rectangle) before; you can just read it back (always using the same single local buffer), modify it, and write it back to the display.That Ramtex £500 library fairly obviously uses a complicated scheme to manage an "object oriented" model without needing lots of local RAM. I have obviously not seen the sources so don't know how much work it is to get started with it, but as you would expect at the price it does have lots of clever features.There was a thread on this elsewhere here on how to do this without a local full-frame buffer; I think it basically involves managing objects and a clever strategy on redrawing the background in that area when you want to move the object along.Or, of course, just redrawing the entire image each timeDoes anyone know what is the purpose of the various time slots like front or back porch? I know what they are but why are they relevant to an LCD? Is the purpose to do video memory update during a gap when the display is not being updated?

author: T3sl4co1l
author_rank: Super Contributor
timestamp: January 28, 2022, 03:47:53 pm
content: Porches are the archaic term for timing around retrace, on a raster scanned display. LCDs often run wide open (pixel 239 on line N immediately followed by pixel 0 on line N+1, etc.) and that's mostly fine on account of being little more than counters into row/column selectors. Timings may still be enforced (or expected, anyway) for compatibility with CRT controllers, VGA interfaces, that sort of thing.So, only relevant for live video types -- usually 24 bit parallel RGB plus sync. On the SPI side, you can safely ignore it.At worst, you should wait for vertical retrace before redraws, to avoid frame tearing -- but it's not a big deal for a lot of applications. (Often a "frame tear" signal is provided, whether on the interface, or as a register somewhere.)Tim

author: peter-h
author_rank: Super Contributor
timestamp: January 28, 2022, 04:00:21 pm
content: The other thread is this one:https://www.eevblog.com/forum/projects/graphics-on-an-embedded-system-tft-display-need-help-with-some-pointers/msg3861806/#msg3861806OK; I can imagine one can get weird effects, via inadvertent synchronicity. I had this the other day with a waveform generator where DMA is copying a circular buffer into a DAC, and the two buffers get auto toggled at 50Hz. I found that if I was updating the "currently unused" buffer, at 50Hz also, the updates never showed upThis chip has onlyoneframe buffer, AFAICT, so one cannot avoid this other than by finding a time slot during which the display is not being updated, by delaying an update, etc. But isn't the LCD always multiplexed? At 240x240 it must be, so the frame buffer must be continuously cycled, so if you block this, it will go blank.These "porches" imply that there are time gaps when writing to the frame buffer doesnotshow up on the LCD. Like the vertical flyback on a CRT (I used to design CRT drive boards, and one had the vertical flyback, plus, if you were quick, the horizontal flyback).

author: T3sl4co1l
author_rank: Super Contributor
timestamp: January 28, 2022, 06:06:07 pm
content: Right, best you can do is, say: wait a little bit after it's started drawing the top row; start dumping data, slightly slower than the scan rate; finish after 1 < t < 2 frames, so that scanning out the next frame doesn't catch up to where you are currently. Wait until next frame for sync, and you'll be updating at Vsync/N FPS (N=1, 2, ...).Actually achieving FPS = Vsync is probably a bit tricky? In practice, you'll just dump it out and hope it works, maybe adding some delays to make it line up better.What actually matters is: delay the write, such that, by the time it's done, the scan will have looped around, plus some margin. That way your writes don't leapfrog the scan address, which would update the frame being currently scanned, partway through -- tearing it.If you have extremely fast writes, then wait e.g. 1/2 frame after retrace, then copy over the first half of the buffer; wait another half (in which time the scan will have wrapped around), and finish the write. Repeat ad infinitum, and you don't tear frames.If your writes are comparable to but just faster than the scan rate, start after a small delay, then by the time the write is finished, it will still be lagging just behind the current scan address.If your write is a bit slow, you can take up to two frames to write it: begin immediately after retrace, "racing" behind the scan address, but always falling behind it; eventually it loops around, but as long as it doesn't lap you (you finish writing before the scan catches up), you're good.Still slower writes, over multiple frames (> 2), are impossible to avoid tearing on full-screen updates. Partial updates can still be done, or since the framerate is relatively low anyway (<= 20 FPS say?), it doesn't really matter, it's going to be a bit choppy and who minds if a frame is shown for 2 or 3 scans.Tim

author: peter-h
author_rank: Super Contributor
timestamp: January 28, 2022, 06:50:51 pm
content: I looked up "tearing" in the controller data sheet, and the signal comes out only on a pin, and isn't accessible on the SPI versionThe frame rate is approx 60Hz and if one did use that signal, one would get a ~1ms slot during "vertical flyback" for writing data. The frame buffer is around 130kbytes and at even 21mbps SPI, and assuming no host delays, it would take 50ms to write the display via SPI. No matter how one looks at it, it is impossible to update the whole display during these slots, within 1 frame time.Making use of the horizontal slots doesn't make much difference (they are very brief).So it seems that in most applications it can't be that important.I reckon the way people implement the anti-tearing is by checking that signal before each call to SPI, or each byte/word load. This is easy and very fast and makes best use of the short horizontal gaps. But I think you could still get funny effects. The only sure way is to have two video buffersandsomehow make sure you never get inadvertent synchronicity.

author: peter-h
author_rank: Super Contributor
timestamp: January 30, 2022, 07:52:11 pm
content: Just a quick update which may be useful to someone.I've been digging around to see which TFT displays have a controller chip which can run SPI at a decent speed. I found these twohttps://www.buydisplay.com/1-54-inch-tft-lcd-display-ips-panel-screen-240x240-for-smart-watchThat uses ST7789 which can be written at 60MHzhttps://www.buydisplay.com/serial-spi-3-5-inch-tft-lcd-module-in-320x480-optl-touchscreen-ili9488That uses ILI9488 which can be written at 20MHzMost of the others I found herehttps://www.buydisplay.com/tft-display/tft-display-panelare a lot slower, with some not going much above 5MHz, and curiously some of the large panels (say 640x480) are in that category, which is obviously not what you want. It looks like they are supposed to be fed via the parallel interface, but that uses a large number of pins.This is also relevant to anyone who buys the 500 quid library fromhttps://www.ramtex.dk/gclcd/glcd0129.htmwhich supports a range of chips. I went through the whole list they support and checked it against all the displays on the above site, and found basically just the above two displays (plus others of similar small sizes).

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 30, 2022, 09:50:55 pm
content: My favourite display module is2.8" IPS 240x320 from BuyDisplay/EastRising, using a common ILI9341 controller. The connector is 50-pin at 0.5mm pitch, and exposes all 18 data pins, the four interface mode select pins (IM0..IM3), serial I/O pins, and even the Tear Effect (TE) pin. ILI9341 can also be directly driven with RGB data and HSYNC, VSYNC, and max. 10 MHz dot clock, effectively bypassing the internal framebuffer, because all the necessary pins are exposed on the connector.Although the ILI9341 is only specced at max. 10 MHz serial clock (100ns serial clock write cycle period –– note thatparallelwrite cycle max is just 66ns or 15 MHz), theseoftenwork at much higher serial clock rates; 24 MHz should not be an issue. Then again, I'm a hobbyist with sample size of fewer than I have fingers, so what do I know.One of the approaches I've been wondering at, is using a small FPGA to "translate" the incoming serial (SPI/I2C) command stream into parallel, but with a color table lookup. Essentially, say the incoming stream is <draw_8x8><4bpp><palette0><x><y><data0><data1>...<data31>, with <value> denoting each byte. Each data byte defines the color for two pixels, using a palette lookup with 16 entries of 18-bit colors. If the input clock is max. 40 MHz, then the parallel data would be at the maximum specified parallel rate. (The reason the command is so long is to ensure the FPGA has enough time to set up the rectangular update area for the particular display controller.) Better yet, if it had more RAM, or used a proper MCU (I'dloveusing an NXP i.MX RT106x for this with lots of PSRAM), it could contain the framebuffer, and do blending and proper blitting. No more sending the same glyph data over and over again, just "save" the nice, antialiased glyph data, then blit it whenever and wherever needed.It's a pity I'm such a bumblefuck in electronics (and FPGA design). The software and comms design I can handle easily.. but I don't even have the test equipment to measure a 40 MHz clock signal, not even a proper oscilloscope.

author: peter-h
author_rank: Super Contributor
timestamp: January 30, 2022, 10:14:57 pm
content: Yes; an FPGA can do clever stuff, especially with SPI where one gets all kinds of hassles like having to make the operation blocking (even if feeding SPI with DMA!) all the way to the end, because you can't raise CS until after the last clock pulse (plus a hold time). With an FPGA you could trivially implement a pulse counter so for e.g. a 512 byte transfer you could count off 4096 pulses and then the FPGA can raise CS, while the CPU could have gone off and done something useful.I know you can do that with interrupts, but... at 21mbps SPI?I used to do FPGA design (for both FPGA and using FPGAs for ASIC prototyping) but got out of it due to the then crappy tools (Xilinx XACT, etc). They have their uses...They also aren't cheap. And today's micros are very fast.For hobby use, or low volume, they can be fun because the cost doesn't matter so you can just use a large device and use the same one in every project. For example I used an XC3064https://www.xilinx.com/support/documentation/data_sheets/3000.pdffor most things.QuoteI plan to run the 20MHz one at 21MHz.

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 30, 2022, 11:12:37 pm
content: Quote from: peter-h on January 30, 2022, 10:14:57 pmA lot of people on the Teensy forums run ILI9341 w/4-wire SPI (CS+CLK+DO+D/C) at 30 MHz (4.x) or 24 MHz (3.x) SPI clock rate (using theILI9341_t3library, which defaults to 30 MHz on Teensy 4.x and overclocked 3.x, and 24 MHz on normally-clocked Teensy 3.x's).Note that whenreadingfrom the ILI9341 chip, the maximum clock is just 6.7 MHz. This means that when initializing the controller chip (including reading the display indentification), it is better to use a slow SPI clock, say 4-6.667 MHz, and use a faster clock for data writes. The aforementioned library uses 6.5 MHz for read operations.

author: peter-h
author_rank: Super Contributor
timestamp: January 31, 2022, 07:51:16 am
content: I spotted that much reduced SPI clock requirement in the other threadhttps://www.eevblog.com/forum/projects/graphics-on-an-embedded-system-tft-display-need-help-with-some-pointers/msg3863324/#msg3863324I wonder how many libraries actually implement that... But one could argue you don't need to do any reading, if you have a #define for every controller chip. That 500 quid lib says it is write-only if SPI is used, anyway.Any library needs to have a user-customised empty function for "SPI write a byte", a function for wait_microseconds(), etc. I have not seen this in any of the open source libs.Interesting lib, that one, but C++.What is needed most of all, for general "graphics", is a fast polygon fill. A set-pixel is likely to be too slow for most things.

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 31, 2022, 08:53:28 am
content: Polygon fill is actually simple to implement: you just find thexcoordinates where the polygon edges intersect eachycoordinate (assuming your data is continuous in increasingxon the samey). Then, you fill the polygon by sending each suchycoordinate one or more horizontal lines.You can find more information about this at e.g. Wikipediascanline renderingpage.If each intersection point also records a color, or a "blend" value, you can linearly interpolate the pixels on the scanline fill.If you use 15-bit color, you can expand each blend endpoint color from 15-bit 0bRRRRRGGGGGBBBBBto 30-bit 0b00000RRRRR00000GGGGG00000BBBBB. If the two endpoints 30-bit colors areC0andC1, andpis the phase from 0 to 33, inclusive, the blended 30-bit color is (33-p)*C0+p*C1= 0bRRRRRrrrrrGGGGGgggggBBBBBbbbbb, where the lower-case letter correspond to fractional bits you need to discard. Of course, in addition to the two multiplications, addition, and subtraction, you do need three ANDs, two bit shifts, and two ORs, per pixel, to reconstruct the 15-bit target color.Antialiasing the outer edge can be done by using fixed point intersection coordinate values, and examining the intersectionxfor the same edge both "above" and "below" the current "pixel", and then blending between the background color and the fill color as above.I'd really want to use an NXP i.MX RT106x with a few megabytes of PSRAM to control these small displays. You could e.g. store 4-bit glyphs (with a palette that contains say 8 opacities of glyph outline, and 7 shades of fully opaque color from outline to fill, with one entry reserved for background) and very rapidly blit them anywhere in a full framebuffer, and only when all changes are done, sync the changes to the display controller... Such glyphs would be perfectly antialiased, and by changing the palette, you could do antialiased font with selectable outline and fill color (dark outline avoiding the light-font-on-light-background problem, for example). My electronics design skills just don't reach to that MAPBGA-196 footprint yet.

author: peter-h
author_rank: Super Contributor
timestamp: January 31, 2022, 09:31:17 am
content: That algorithm will fail for polygons which have a notch. A simple case is an arrowhead. This will workbut this will breakObviously code for all this has been developed, including polygons with holes, etc.Yes; RAM is powerSuch a pity these fast ARM uCs have just 128k etc. Even SPI-attached RAM would be great.

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 31, 2022, 09:57:53 am
content: Quote from: peter-h on January 31, 2022, 09:31:17 amNo, you just need to handle pairs of intersections on eachy; and correctly handle polygon vertices as an intersection. That then also handles self-intersecting polygons naturally usingeven-odd rule. For eachy, you get an even number of intersections. Sort them in increasing order, and each consecutive pair forms a span (a horizontal line segment) that you need to fill on thaty.

author: peter-h
author_rank: Super Contributor
timestamp: February 03, 2022, 07:23:20 am
content: I've decided to buy that 500 quid library mentioned earlierhttps://www.eevblog.com/forum/projects/small-tft-display-5x5cm-for-moving-graphics-over-spi/msg3976907/#msg3976907It will save a huge amount of time. It is apparent that it is fairly easy, with the free code examples, to set a pixel, but not much more.I've spent some time getting DMA to work on 32F417 SPI3 because that will be neededhttps://www.eevblog.com/forum/microcontrollers/32f417-spi-running-at-one-third-the-speed-it-should/msg3940687/#msg3940687

author: ve7xen
author_rank: Super Contributor
timestamp: February 03, 2022, 08:03:07 am
content: Rather than buying a library to drive a framebuffer LCD, have you considered a Nextion module that includes a display controller? You use a Windows app to design the UI pages and then just send basic commands over UART to update the UI elements. There are other companies doing this too, maybe some cheap ones, but mostly they seem to target the industrial market and are kind of expensive.Nextion have modules likeNX3224T0242.4" 320x240 for about $25. If you're not planning to build in quantity it makes a lot of sense.

author: peter-h
author_rank: Super Contributor
timestamp: February 03, 2022, 10:58:57 am
content: That's probably good for hobby / low volume / non-industrial but it ties you to a device which, if it goes out of production, lands you with a massive job. Whereas all the time you are using these "dumb" LCDs, you should be able to find an alternative.The real issue is likely to be TFT panel availability. Normally you are stuck with a given size, to fit your box.BTW what happened to the low temp issue? In say aviation one sometimes had a heater on the back of it. Hence OLEDs but they have a crap life. Wide temp range products tended to use vacuum fluorescent displays, which have lots of reliability issues too.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: February 03, 2022, 07:09:34 pm
content: OTOH, it saves you a lot of upfront work, integrating that display. Good not just for industrial and low-quantity but also quick-turn / short-TTM projects. Get it out there earning money, cost reduce it later. Some projects it's worth spending that up front, others more like this; just another option for doing business.Tim

author: Bud
author_rank: Super Contributor
timestamp: February 03, 2022, 09:17:13 pm
content: Quote from: ve7xen on February 03, 2022, 08:03:07 amThanks for the tip! Makes it a lot easier for a variety of hobby projects.