Cornell University ECE4760
Adafruit TFT LCD Display Model 1480


Adafruit TFT on PIC32
The library written for Arduino was ported to PIC32 by Syed Tahmid Mahbub, as explained on his excellent blog.
I hacked the demo program to be a little more focused on this course and to use Protothreads for multitasking.
The thread library was changed for this application to remove UART communication and debugging pin support.
More Protothread documentation is available.

Connect the TFT display as shown below.Or as described in Tahmid's blog.
You can get Vdd from the via near the center of the MicrostickII as shown in the keypad section images.
The third image shows the orientation of a properly soldered TFT header.
connect 1connect 2soldering pins

Download the TFT project ZIP file, refered to on the protothreads page.

A short video of the application generated by TFT_test_BRL4.c. This code can be substituted into the project.

There are spearate tft_master.c files for SPI channel one and SPI channel 2. An example which reads the AN11 analog input and draws the voltage on the TFT using the SPI2 master and Protothreads 1.2 is ZIPPED here.

Graphics Details

The Adafruit TFT color format is 16 bit:

Color examples:

A list of the available graphics routines is in tft_gfx.h with more explanation of parameters in tft_gfx.c

void tft_drawLine(short x0, short y0, short x1, short y1, unsigned short color);
void tft_drawRect(short x, short y, short w, short h, unsigned short color);
void tft_drawCircle(short x0, short y0, short r, unsigned short color);
void tft_drawCircleHelper(short x0, short y0, short r, unsigned char cornername,
      unsigned short color);
void tft_fillCircle(short x0, short y0, short r, unsigned short color);
void tft_fillCircleHelper(short x0, short y0, short r, unsigned char cornername,
      short delta, unsigned short color);
void tft_drawTriangle(short x0, short y0, short x1, short y1,
      short x2, short y2, unsigned short color);
void tft_fillTriangle(short x0, short y0, short x1, short y1,
      short x2, short y2, unsigned short color);
void tft_drawRoundRect(short x0, short y0, short w, short h,
      short radius, unsigned short color);
void tft_fillRoundRect(short x0, short y0, short w, short h, short radius, unsigned short color);
void tft_drawBitmap(short x, short y, const unsigned char *bitmap, short w, short h, unsigned short color);
void tft_drawChar(short x, short y, unsigned char c, unsigned short color, unsigned short bg, unsigned char size);
void tft_setCursor(short x, short y);
void tft_setTextColor(unsigned short c);
void tft_setTextColor2(unsigned short c, unsigned short bg);
void tft_setTextSize(unsigned char s);
void tft_setTextWrap(char w);
void tft_gfx_setRotation(unsigned char r);
void tft_write(unsigned char c);
void tft_writeString(char* str);    // This is the function to use to write a string 

Drawing text
To make is easier to format debugging messages, I wrote a short routine:
void printLine(int line_number, char* print_buffer, short text_color, short back_color)
that takes as input:
-- a line number: 0 to 31
-- a string of length 1 to 35 characters
-- text color
-- background color
The routine renders one text line of size=1 text on a vertically oriented screen.
The amazingly ugly display to the left shows five background colors
with the demo code cycling through five different text colors. A small change in the
code generates text of size 2 for those of us who have trouble seeing the smallest font.

For capacitance measurement lab:

Animation examples:

Example using fixed point arithmetic to bounce a ball with gravity and air drag.

This random diffusion example animates 3000 point particles, while profiling the execution time, and maintaining a elapsed time clock. The example uses an optimized point drawing routine which takes about 10 microseconds/point to draw/erase. Most of that time is spent in SPI communication with the TFT display. For comparision, the NTSC TV code wirites a point in about 4 microseconds. Execution time for 3000 particles is about 60 milliseconds/frame, dominated by a draw and an erase for each particle. Zipped project (including the optimized point draw). CPU speed is 40 MHz.

However, cranking the CPU clock to 64 MHz, peripherial clock divider to unity, and the SPI divider to 2 enables drawing of 3000 particles in 37 milliseconds. It seems to work, but I suspect is of marginal stability because of white board bandwidth, and perhaps SPI maximum rate on the TFT display (Zipped project).


Adding a 12 key keypad (0 to 9 with * and #) requires seven i/o pins. Each switch connects one row wire to one column wire. Connection scheme used in the test code is shown below. 300 ohm resistors protect the outputs from short circuits when multiple switches are closed. The 10K pulldown resistors provide an input source when the switches are open. The code displays the button label when a button is pressed, and -1 when no button is pressed. If you add one line of code, you can eliminate the three 10k pulldown resistors by turning on internal pulldowns. The poorly documented CNPDB register (Change Notice Pull-down Enable B) selects input bits to pull down. Setting
CNPDB = BIT_7 | BIT_8 | BIT_9

in the keypad thread pulls down B7, B8, and B9. To be safe, you should probably clear the CNPUB register to turn off pull up resistors.
If you include the following macros:
#define EnablePullDownB(bits) CNPUBCLR=bits; CNPDBSET=bits;
#define DisablePullDownB(bits) CNPDBCLR=bits;
#define EnablePullUpB(bits) CNPDBCLR=bits; CNPUBSET=bits;
#define DisablePullUpB(bits) CNPUBCLR=bits;
#define EnablePullDownA(bits) CNPUACLR=bits; CNPDASET=bits;
#define DisablePullDownA(bits) CNPDACLR=bits;
#define EnablePullUpA(bits) CNPDACLR=bits; CNPUASET=bits;
#define DisablePullUpA(bits) CNPUACLR=bits;

Then you can just write
EnablePullDownB( BIT_7 | BIT_8 | BIT_9);

ZIP of project

The physical connections for servral styles of keypad are shown below. You probably will want to use the
12-key models.

Connector:  top:8-pin      top:9-pin   bottom  12-key
Pin 1  ---- row 1 2 3 A    col 1       col 1    row 1 (pin A0)
Pin 2  ---- row 4 5 6 B    col 2       col 2    row 2 (pin A1)
Pin 3  ---- row 7 8 9 C    col 3       col 3    row 3 (pin A2)
Pin 4  ---- row * 0 # D    col 4       col 4    row 4 (pin A3)

Pin 5  ---- col 1 4 7 *    row 1       row 1    col 1 (pin B7)
Pin 6  ---- col 2 5 8 0    row 2       row 2    col 2 (pin B8)
Pin 7  ---- col 3 6 9 #    row 3       row 3    col 3 (pin B9)
Pin 8  ---- col A B C D    row 4       row 4    ----
Pin 9  ----              (NO CONNECT--common)

(a) Each switch shorts one row to one column. When in doubt, get the ohmmeter!
(b) On the 9-pin models, do not connect the common lead.

tft and keytft and key

For DDS lab:

Copyright Cornell University July 25, 2017