PIC18F4550 driver for 1.8" TFT display (128x160 pixels)
A few weeks ago I decided to try to write a driver for my eBay 1.8" TFT display. I tried to use the SPI module of the microcontroller but didn't get it working with the display. So I browsed the internet for some example projects and I came across a nice blog about a PIC 18F2550 driving a 1.8 inch TFT LCD display of Joe Watson. This example uses bit-banging instead of the build-in SPI. I had to modify it just a little to get it working. After I had it running I made a few more changes. The differences are
  • No bootloader
  • Initialization is writing step by step in code instead of table look-up.
  • Less the initialization commands, just a bare subset.
  • Use partial screen updates
  • Use of partial area
  • Different microcontroller: PIC184550
  • Using a table lookup for drawing colorized sinus and cosinus

Below you can see the TFT display front and backside.
  • pin 1 (GND) is connected to ground (0V)
  • pin 2 (Vcc) is connected to +5V
  • The signal pins are 3.3V levelled (!)
  • pin 7 (A) is the data/command bit high=data, low=command
  • pin 8 (SDA) is the data pin high=1, low=0
  • pin 9 (SCK) is used for clocking the data into the TFT display
  • pin 10 (CS) is connected to ground: write mode
  • pin 15 (led+) and pin 16 (led-) are used for contrast level
  • The pins marked yellow (11-14) are for reading/writing to the optional sd card. They are not used in this example.

1.8" TFT display front and backside
1.8" TFT display front and backside

Below you see the sinus and cosinus table. The dispay is a 128 x 160 display and I wanted as much sinus values as possible. Therefore the x-axis has 160 pixels and the y-axis 128. To centre the sinus I added an offset of 60 (64 would have been better). As a result the sinus values must be between 0 and 120.

I used excel to calculate:
  • 160 values between 0 and 2 PI with a step size of 2 PI/160.
  • For each calculated value I applied the formula 60*sin(x)+ 60.
  • Rounded the values to integer values
  • Converted from decimal value to hexadecimal value
  • The same approach was applied for the consinus: 60*cosinus(x) + 60
  • Because of the overlap in sinus and consinus data, I merged them into a single table and added two labels: 'SinusSequence' and 'CosinusSequence'
  • use 4-4-4 colour mode. Only need 3 bytes for 2 pixels.


10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
ORG 0x1000
db 0x3A, 0x3C
SinusSequence:
db 0x3C, 0x3E, 0x41, 0x43, 0x45, 0x48, 0x4A, 0x4C, 0x4F, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5C, 0x5E, 0x5F, 0x61, 0x63, 0x65
db 0x67, 0x68, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x74, 0x74, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78
CosinusSequence:
db 0x78, 0x78, 0x78, 0x78, 0x77, 0x77, 0x76, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6D, 0x6C, 0x6B, 0x69, 0x67
db 0x66, 0x64, 0x62, 0x60, 0x5E, 0x5D, 0x5B, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4E, 0x4B, 0x49, 0x47, 0x44, 0x42, 0x40, 0x3D
db 0x3B, 0x38, 0x36, 0x34, 0x31, 0x2F, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1D, 0x1B, 0x1A, 0x18, 0x16, 0x14, 0x12
db 0x11, 0x0F, 0x0D, 0x0C, 0x0B, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x10, 0x11
db 0x13, 0x15, 0x17, 0x19, 0x1A, 0x1C, 0x1F, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2C, 0x2E, 0x30, 0x33, 0x35, 0x37, 0x3A, 0x3C
db 0x3C, 0x3E, 0x41, 0x43, 0x45, 0x48, 0x4A, 0x4C, 0x4F, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5C, 0x5E, 0x5F, 0x61, 0x63, 0x65
db 0x67, 0x68, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x74, 0x74, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78
db 0x78, 0x78, 0x78, 0x78, 0x77, 0x77, 0x76, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6D, 0x6C, 0x6B, 0x69, 0x67
db 0x66, 0x64, 0x62, 0x60, 0x5E, 0x5D, 0x5B, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4E, 0x4B, 0x49, 0x47, 0x44, 0x42, 0x40, 0x3D
db 0x3B, 0x38, 0x36, 0x34, 0x31, 0x2F, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1D, 0x1B, 0x1A, 0x18, 0x16, 0x14, 0x12
db 0x11, 0x0F, 0x0D, 0x0C, 0x0B, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x10, 0x11
db 0x13, 0x15, 0x17, 0x19, 0x1A, 0x1C, 0x1F, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2C, 0x2E, 0x30, 0x33, 0x35, 0x37, 0x3A, 0x3C
db 0x3C, 0x3E, 0x41, 0x43, 0x45, 0x48, 0x4A, 0x4C, 0x4F, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5C, 0x5E, 0x5F, 0x61, 0x63, 0x65
db 0x67, 0x68, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x74, 0x74, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78
db 0x78, 0x78, 0x78, 0x78, 0x77, 0x77, 0x76, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6D, 0x6C, 0x6B, 0x69, 0x67
db 0x66, 0x64, 0x62, 0x60, 0x5E, 0x5D, 0x5B, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4E, 0x4B, 0x49, 0x47, 0x44, 0x42, 0x40, 0x3D

The program loops through the data from 0...159 values. TBLPTR is used to lookup the data (y-position).

10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
sin_loop_init:
MOVLW Low SinusSequence ;Point Rom pointer to the init sequence
MOVWF TBLPTRL,A
MOVLW High SinusSequence
MOVWF TBLPTRH,A
CLRF TBLPTRU,A
CLRF XS, A ; clear x position
sin_loop:
TBLRD*+ ; read into TABLAT and increment
MOVF TABLAT, W ; get data
MOVWF YS ; get byte
CALL draw_pixel ;CALL fill_with_color
INCF XS, 1 ,0 ;inc xs, place result in WREG
MOVLW 0xA0
SUBWF XS, 0 ,0 ;substract 160 from YS, place result in WREG
BTFSS STATUS, Z
GOTO sin_loop

For drawing a single pixel, the ROWS COLS are set to [x,y], [x+1, y] which leaves an are of 2 pixels.
Three bytes of color are sent: RRRRGGGG BBBBRRRR GGGGBBBB => First byte contains RED and GREEN values of pixel 1, second byte contains BLUE value of pixel 1 and RED value of pixel 2, third byte contains GREEN and BLUE values of pixel 2.

10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
draw_pixel:
INCF XS, 0 ,0 ;inc XS, place result in WREG
MOVF XE, 0, 0
CALL set_cols_and_rows ;set row and columns
CALL fill_pixel_withcolor
RETURN
set_cols_and_rows:
MOVLW CASET
CALL SEND_COMMAND
MOVLW 0x00
CALL SEND_DATA
MOVF YS, 0, 0
CALL SEND_DATA
MOVLW 0x00
CALL SEND_DATA
MOVF YE, 0, 0
CALL SEND_DATA
MOVLW RASET
CALL SEND_COMMAND
MOVLW 0x00
CALL SEND_DATA
MOVF XS, 0, 0
CALL SEND_DATA
MOVLW 0x00
CALL SEND_DATA
MOVF XE, 0, 0
CALL SEND_DATA
RETURN
fill_pixel_withcolor:
MOVLW RAMWR
CALL SEND_COMMAND
MOVF COL_R1G1, 0,0
CALL SEND_DATA
MOVF COL_B1R2, 0,0
CALL SEND_DATA
MOVF COL_G2B2, 0,0
CALL SEND_DATA
RETURN

The result is shown below:
Sinus and cosinus
Sinus and cosinus

Downloads:

Back to List