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.


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).

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.

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

All form fields are required.
A confirmation mail for the comments will be send to you.