1.8 TFT SPI Display


New Member
After Christmas I ordered via ebay a list of chinese made goodies no-one thought to give me as a present. One item was this full colour pixel display from hittime priced only £2.68 inc post and arriving within a fortnight. It is sold for the Arduino and has downloadable library files but not much real info on operation.

It took a while to break into its workings but it can be interfaced easily to a Picaxe. Of course running Basic on the chip means it runs slower by maybe three orders of magnitude than operating with precompiled code. So educational mainly but there will be applications if the limitations are understood.

I used the row of 16 plated through holes for connection but the yellow terminal pins seem to replicate the TFT pins (but not the SD). Wired to a 20X2 like this:

B.4 pin 14 - TFT CS pin 10 (CE) this signal taken low during SPI sending
B.7 pin 11 - TFT SCK pin 9 (SCK) use with hspisetup
C.1 pin 9 - TFT SDA pin 8 (MOSI) use with hspiout
B.6 pin 12 - TFT RS pin 7 (Cmd/Data) take high for data, low for a command
C.2 pin 8 - TFT RST pin 6 (Reset) pulse low only if needed. Power up will leave RAM a coloured mush.
B.3 pin 15 - TFT BL pin 4 (LED) take high for the backlight LED to turn on.

The real issue is what sequence of commands to wake up the display. Google the pdf for the Sitronix ST7735R control chip because this is required reading. Begin with SLPOUT and DISPON. Then RAMWR to start sending data and any following characters should hit the screen.

The display has 160 x 180 pixels, each with 3 bytes for colour so to fill it will need around 62 thousand bytes sent via SPI. Perhaps 24 seconds to clear to one colour (no hardware instruction) and the pixel writing demo attached takes around 50 seconds.

A feature to understand is the writing window – a rectangular area which can be set with x,y start and x,y end coordinates. Within that block the RAM is written in raster fashion but the direction can be changed by the MADCTL command. Dr Sheldon Cooper may appreciate the fun you can have with the example code.

I have also coded a character display of 18 x 16 lines which I hope to post shortly.



New Member
1.8 TFT 18 x 16 lines Display

Now I’ve finally managed my first posting I see that I left a lot of old code with the flag program. In fact my first code was for this character display and I began using bit banged SPI so I could be sure of the pin states. Once the display was awoken I used hspiout etc. However, to use the MISO that the ST7735R chip refers to for data reads will probably involve setting MOSI to tri state between bytes.

Here the speed issue is such that a scrolling display is not possible in real time and even a short line is a problem because the rest of the line must be written over with blanks for clarity. The writing area is now the 7x5 pixels for each character and the raster scan is set to strobe down the 8 bits so only 5 writes (of RGB) are needed for each displayed char. Again it is a pixel display, not a character generator, so every ASCII character must be looked up. I copied the bit patterns used by the HD44789U display controller that drives the LM1602 units. And I thought using I2C sending nibbles was klunky!

If the characters are written to a clean screen the display is quite readable. If characters continue past line 16 they will write from the top again but the character colour will then change.

So to use this as a general display, for sertxd diagnostics say, it would need a front end buffer. Even at 300bps it will be swamped with a continuous stream. I measure less than 7 bytes per second so a mechanical Teletype was faster.

However, it is very pretty and it has colour so with the right application it may still be useful. A mimic diagram, status display, or arrivals board (where most information on screen is static) are possibilities.

I have been helped by forum postings for the nRF24L01P radio chip which I use in a mesh of six. I hope that others can now take this TFT display code development further.



Technical Support
Staff member
Excellent work.

It doesn't look like there is any SETFREQ in the code which would allow the PICAXE operating speed to be increased eight-fold from 8MHz to 64MHz. That could give a reasonable display update speed improvement.


New Member
Thank you, Hippy.

Setfreq m64 makes for a dramatic improvement in speed. The flag demo now paints within 7 seconds and the ASCII display writes at a respectable 50 cps. For interest I measured the battery current at 38.2 mA with no setfreq and 48.5 mA using m64.


New Member
08M2 drives scrolling TFT display

This update offers code for an 08M2 to drive a scrolling display of 16 lines of 18 blue chars on a white background.

With the TFT displays I also purchased some Arduino nanos and eventually revisited this application as a comparative learning exercise.

I translated the original code from BASIC to C+ and used ‘bit banging’ to avoid libraries. The fixed 16MHz clock nano equalled the 64MHz Picaxe 20X2 using hspi instructions. Still not fast enough, I learned a number of direct port addressing and other tricks to get the nano to write characters to screen faster than they could be read.

There is a better manual (Samsung S6D02A1A01) and it describes hardware scrolling commands. There can be a top and/or bottom fixed area as well as the scrolling area; here the whole screen scrolls. Once configured, the scroll command includes a number of pixel lines on screen; here it is 10 lines. When first issued the screen will scroll up such that the top 10 lines appear at the bottom. Issue the same command again and nothing happens...

The TFT memory does not move, it is only its relationship to the screen that has changed. To scroll up again requires a parameter of 20 lines, then 30 and so on. This display will write from the top till it reaches the bottom then it will scroll up – just like the serial terminal.

Translating back from C+ to BASIC is not so easy but, as an exercise, I used the popular 08M2. It has only just enough pins, no hspi instructions and only clocks up to 32MHz. The TFT reset function uses a 1uF capacitor pulled up via a 2k2 resistor. The back light is permanently enabled via a 2k2 pullup. This leaves MOSI, SCK, CE and RE (for command or data) to be connected to the four Picaxe output pins.

SPI moves bits out serially starting with the MSB at the left. When the data output MOSI is stable, the clock is pulsed high. CE and RE are used to inform the slave of the transaction process and whether the byte is data or to be taken as a command. Using hspi instructions will be much faster than bit banging because each line of BASIC code will take time in the order of milliseconds.

To speed up the data rate we must lose as many code lines as possible so the interval between clocks is minimum. This code will not be elegant so out will go for loops and if tests. This has to be code with its sleeves rolled up.

The general routine SpiSnd first divides the byte by 128, effectively masking the MSB and testing it to be 0 or 1. This value is moved directly into the output pin for MOSI. As we will need the sent byte again, a temporary accumulator is used for the intermediate result. Then multiplying the byte by two shifts all bits to the left ready for the next step.

Pulsout is the clock instruction; 1uS won’t happen but extending the pulse in the code will lengthen the cycle time.

There is no screen clear instruction so all pixels must be cleared the hard way. Three bytes of colour data must be sent for each pixel. Use SpiSnd and it can take half a minute! White is the background colour here so MOSI is 1 for all 24 bits per pixel. All we need then is to set MOSI and waggle the clock pin half a million times – job done.

I tried many ways to trick the 08M2 but the only reliable technique uses PWM. Fortunately the pause and pwmout instructions seem related and not in conflict so we can count out the pulses approximately. If too many white dots are sent it is not a problem as the screen will wrap and the next command will reset the cursors. The PWM Wizard will give a result for up to 4MHz but it won’t work above 2MHz. More than enough to clear the screen in a quarter of a second. The same technique is used to clear the bottom line following a scroll up.

Finding no reliable way to send 8 (and only 8) clock pulses quickly, the rest of the colour data is pretty slow to output. Using only the solid colours - black, white, red, blue etc – the data pin can be set and 8 pulsouts issued per byte. The routine ScrW8 uses this approach to put blue dots on the white background.

Unable to use interrupts meaningfully with the serin or serrxd instructions there is no input character buffer. The baud rate is set at 4800 but the incoming data rate has to be kept below 10 characters per second.

The attached code will display test characters scrolling continuously. To use the serial input routine, comment out the test and uncomment the input. This will also free up memory which is on the limit.



Some excellent work. Thanks for sharing.
I've been toying with the idea of using such a display with an Arduiny doing the hard work and then feeding PICAXE serout into it.
Looks like your efforts might be able to eliminate the Arduiny as long as speed is not important.


New Member
Thanks, BeanieBots, it will depend on your application needs. I fell at the last hurdle with the 08M2 front end buffer. If you set interrupts on the data pin going high then call serin it is too late as the start bit has already begun and serin won't find it. A buffer would take a burst of input and write to screen when it could. I tried to use both input pins together - one slugged with a capacitor so the raw pin would interrupt and the slow one could feed serin. You can't set interrupts on the serrxd pin and with a fast clock serrxd can't be 2400!

The original code for the 20X2 at 64 MHz would take 50 cps but had no clear or scroll. If the PWM trick works with the 20X2 and using the new found scroll commands that should now be quite fast. A front end buffer using hserin and interrupts would be ideal.

One comment on the Arduino nano that I have. The chip wars between FTDI and the Chinese competitor are unfortunate but these chips interface the USB pins directly on the board. There are console instructions for debugging but no signal that a UART would understand. Picaxes use the AXE027 cable which converts the USB in the header and provides UART type signalling at the audio jack.