//---------------------------------------------------------
/*
Program for writing to Newhaven Display 2.8" TFT with ILI9341 controller.
This program is written for Arduino Uno or Seeeduino V4.2 set to 3.3V IO.
For Arduino Uno, logic level shifters are required to convert 5V logic to 3.3V.
This code will cycle through images on an SD card when a pushbutton is pressed.
(c)2025 Newhaven Display International, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
//---------------------------------------------------------
// The 8 bit data bus is connected to PORTD of the Arduino/Seeeduino (Pins DB17 -> D7, DB10 -> D0)
// SD card PCB wired to SPI pin header
// Pushbutton wired to analog pin A2
int RS = 8; //
int WR = 9; //
int RD = 10; //
int RES = A0; //
int button = A2;
// /CS signal tied to GND
/////////////SD Card /////////////
const int ChipSelect = A1;
#include <SD.h>
#include <SPI.h>
File myFile;
/////////////////////////////
unsigned int i;
void comm_out(unsigned char c)
{
digitalWrite(RS, LOW);
PORTD = c;
digitalWrite(WR, LOW);
digitalWrite(WR, HIGH);
}
void data_out(unsigned char d)
{
digitalWrite(RS, HIGH);
PORTD = d;
digitalWrite(WR, LOW);
digitalWrite(WR, HIGH);
}
void dispWhite()
{
comm_out(0x2C); //command to begin writing to frame memory
for(i=0;i<38400;i++) //fill screen with white pixels
{
data_out(0xFF);
data_out(0xFF);
data_out(0xFF);
data_out(0xFF);
}
}
void dispRed(){
comm_out(0x2C);
for(i=0;i<38400;i++) //fill screen with red pixels
{
data_out(0xF8);
data_out(0x00);
data_out(0xF8);
data_out(0x00);
}
}
void dispGreen(){
comm_out(0x2C);
for(i=0;i<38400;i++) //fill screen with green pixels
{
data_out(0x07);
data_out(0xE0);
data_out(0x07);
data_out(0xE0);
}
}
void dispBlue(){
comm_out(0x2C);
for(i=0;i<38400;i++) //fill screen with blue pixels
{
data_out(0x00);
data_out(0x1F);
data_out(0x00);
data_out(0x1F);
}
}
void dispBlack(){
comm_out(0x2C);
for(i=0;i<38400;i++) //fill screen with black pixels
{
data_out(0x00);
data_out(0x00);
data_out(0x00);
data_out(0x00);
}
}
void TFT_SDbmp(unsigned char image) {
unsigned char dummy;
unsigned int width = 240;
unsigned int height = 320;
switch (image) {
case 1: myFile = SD.open("img1.bmp"); break;
case 2: myFile = SD.open("img2.bmp"); break;
case 3: myFile = SD.open("img3.bmp"); break;
case 4: myFile = SD.open("img4.bmp"); break;
case 5: myFile = SD.open("img5.bmp"); break;
default: return;
}
if (myFile) {
// Skip BMP header
for (unsigned int i = 0; i < 66; i++) {
dummy = myFile.read();
}
comm_out(0x2C); // Begin writing to display
delay(100);
for (unsigned int y = 0; y < height; y++) {
for (unsigned int x = 0; x < width; x++) {
uint8_t lowByte = myFile.read();
uint8_t highByte = myFile.read();
data_out(highByte);
data_out(lowByte);
}
}
myFile.close();
}
}
void waitForButtonPress() {
while (digitalRead(button) == LOW) {
// Wait for button press
}
delay(50); // Debounce delay
while (digitalRead(button) == HIGH) {
// Wait for button release
}
delay(50); // Debounce delay
}
void setup()
{
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, INPUT);
pinMode(RES, OUTPUT);
pinMode(ChipSelect, OUTPUT);
digitalWrite(ChipSelect, HIGH);
digitalWrite(RS, LOW);
DDRD = 0xFF;
PORTD = 0x00;
digitalWrite(RD, HIGH);
digitalWrite(WR, LOW);
digitalWrite(RES, LOW);
delay(250);
digitalWrite(RES, HIGH);
delay(250);
comm_out(0x28); //display off
comm_out(0x11); //exit SLEEP mode
comm_out(0xCB); //power control A
data_out(0x39);
data_out(0x2C);
data_out(0x00);
data_out(0x34);
data_out(0x02);
comm_out(0xCF); //power control B
data_out(0x00);
data_out(0x81);
data_out(0x30);
comm_out(0xC0);
data_out(0x26); //power control 1
data_out(0x04); //second parameter for ILI9340 (ignored by ILI9341)
comm_out(0xC1);
data_out(0x11); //power control 2
comm_out(0xC5);
data_out(0x35);
data_out(0x3E); //VCOM control 1
comm_out(0x36);
data_out(0x88); //memory access control = BGR
comm_out(0xB1);
data_out(0x00);
data_out(0x18); //frame rate control
comm_out(0xB6);
data_out(0x0A);
data_out(0xA2); //display function control
comm_out(0xC7);
data_out(0xBE); //VCOM control 2
comm_out(0x3A);
data_out(0x55); //pixel format = 16 bit per pixel
comm_out(0xF2); //3g damma control
data_out(0x02); //off
comm_out(0x26); //gamma curve 3
data_out(0x01);
comm_out(0x2A);
data_out(0x00); //column address set
data_out(0x00); //start 0x0000
data_out(0x00);
data_out(0xEF); //end 0x00EF
comm_out(0x2B);
data_out(0x00); //page address set
data_out(0x00); //start 0x0000
data_out(0x01);
data_out(0x3F); //end 0x003F
comm_out(0x29); //display ON
delay(10);
SD.begin(ChipSelect);
dispWhite();
}
void loop() {
waitForButtonPress();
TFT_SDbmp(1);
waitForButtonPress();
TFT_SDbmp(2);
waitForButtonPress();
TFT_SDbmp(3);
waitForButtonPress();
TFT_SDbmp(4);
waitForButtonPress();
TFT_SDbmp(5);
waitForButtonPress();
dispBlack();
waitForButtonPress();
dispWhite();
}