//---------------------------------------------------------
/*
Program for writing to Newhaven Display NHD-2.1-480480AF-ASXP with NHD-4.3-480272MF-20 Controller Board (SSD1963, 8-bit)
R45 on controller board has been replaced with 2Ω to provide 100mA backlight current
This program is written for Arduino Due.
The program will fill the screen with red, green, and blue colors. Then it will display 4 images from an SD card.
(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.
*/
//---------------------------------------------------------
/* Wiring Instructions
----------------------------------------------------
Display side Controller board side
1 1
2 2
3 4
4 3
5 NC
6 NC
7 5
8 NC
9 NC
10 6
11 33
12 32
13 30
14 34
15-20 23-28
21-26 15-20
27-32 7-12
33 Arduino Due D24
34 Arduino Due D25
35 Arduino Due D26
36 Arduino Due D29
37 Arduino Due D27
38 Arduino Due D47 or GND
39 Arduino Due D49 or 3V3
40 Arduino Due D51 or GND
-----------------------------------------------------
Controller Board J2 Arduino Due
1 GND
2 3V3
3 D28
4 D29
5 D30
6 3V3
7-14 D2-D9
15 D32
16 D33
17 NC
18 NC
19 3V3
20 NC
------------------------------------------------------
SD Card PCB wired to DUE SPI pin header
SD Card CS -> Arduino Due D10
*/
//Display Init Pins
#define RESX 24
#define CSX 25
#define SCL 26
#define SDA 27
//SSD1963 Controller Pins
#define BLE 28
#define RD 31
#define CS 32
#define RST 33
//Interface selction Pins for init TFT
#define IM0 47
#define IM1 49
#define IM2 51
// Arduino DUE Port manipulation setup
#define PIN2_MASK (1u << 25)
#define PIN3_MASK (1u << 28)
#define PIN4_MASK (1u << 26)
#define PIN5_MASK (1u << 25)
#define PIN6_MASK (1u << 24)
#define PIN7_MASK (1u << 23)
#define PIN8_MASK (1u << 22)
#define PIN9_MASK (1u << 21)
#define DC_MASK (1u << 6) //DC = D29
#define WR_MASK (1u << 9) //WR = D30
#define ALL_PINS_MASK_PIOB (PIN2_MASK)
#define ALL_PINS_MASK_PIOC (PIN3_MASK | PIN4_MASK | PIN5_MASK | PIN6_MASK | PIN7_MASK | PIN8_MASK | PIN9_MASK)
/////////////SD Card /////////////
const int ChipSelect = 10;
#include <SD.h>
#include <SPI.h>
File myFile;
/////////////////////////////
void SPI_CMD(unsigned char c) {
digitalWrite(CSX, LOW);
digitalWrite(SDA, LOW);
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SCL, HIGH);
for (int i = 0; i < 8; i++) {
if ((c & 0x80) == 0x80) {
digitalWrite(SDA, HIGH);
} else {
digitalWrite(SDA, LOW);
}
c = (c << 1); //Shift byte
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SCL, HIGH);
}
digitalWrite(CSX, HIGH);
}
void SPI_DAT(unsigned char c) {
digitalWrite(CSX, LOW);
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SCL, HIGH);
for (int i = 0; i < 8; i++) {
if ((c & 0x80) == 0x80) {
digitalWrite(SDA, HIGH);
} else {
digitalWrite(SDA, LOW);
}
c = (c << 1); //Shift byte
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SCL, HIGH);
}
digitalWrite(CSX, HIGH);
}
void data(unsigned char d) { //Function that sends data
REG_PIOD_SODR = DC_MASK;
uint32_t setMaskPIOB =((d & 0x01) ? PIN2_MASK : 0);
uint32_t setMaskPIOC =
((d & 0x02) ? PIN3_MASK : 0) |
((d & 0x04) ? PIN4_MASK : 0) |
((d & 0x08) ? PIN5_MASK : 0) |
((d & 0x10) ? PIN6_MASK : 0) |
((d & 0x20) ? PIN7_MASK : 0) |
((d & 0x40) ? PIN8_MASK : 0) |
((d & 0x80) ? PIN9_MASK : 0);
REG_PIOB_CODR = ALL_PINS_MASK_PIOB;
REG_PIOC_CODR = ALL_PINS_MASK_PIOC;
REG_PIOB_SODR = setMaskPIOB;
REG_PIOC_SODR = setMaskPIOC;
REG_PIOD_CODR = WR_MASK; // Set WR LOW (start write)
REG_PIOD_SODR = WR_MASK; // Set WR HIGH (end write)
}
void command(unsigned char d) { //Function that sends commands
REG_PIOD_CODR = DC_MASK;
uint32_t setMaskPIOB = ((d & 0x01) ? PIN2_MASK : 0);
uint32_t setMaskPIOC =
((d & 0x02) ? PIN3_MASK : 0) |
((d & 0x04) ? PIN4_MASK : 0) |
((d & 0x08) ? PIN5_MASK : 0) |
((d & 0x10) ? PIN6_MASK : 0) |
((d & 0x20) ? PIN7_MASK : 0) |
((d & 0x40) ? PIN8_MASK : 0) |
((d & 0x80) ? PIN9_MASK : 0);
REG_PIOB_CODR = ALL_PINS_MASK_PIOB;
REG_PIOC_CODR = ALL_PINS_MASK_PIOC;
REG_PIOB_SODR = setMaskPIOB;
REG_PIOC_SODR = setMaskPIOC;
REG_PIOD_CODR = WR_MASK; // Set WR LOW (start write)
REG_PIOD_SODR = WR_MASK; // Set WR HIGH (end write)
}
void SetPins() {
pinMode(RESX, OUTPUT);
pinMode(CSX, OUTPUT);
pinMode(SCL, OUTPUT);
pinMode(SDA, OUTPUT);
pinMode(BLE, OUTPUT);
pinMode(RD, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(RST, OUTPUT);
pinMode(IM0, OUTPUT);
pinMode(IM1, OUTPUT);
pinMode(IM2, OUTPUT);
digitalWrite(RESX, HIGH);
digitalWrite(CSX, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SDA, HIGH);
digitalWrite(BLE, HIGH);
digitalWrite(RD, HIGH);
digitalWrite(CS, LOW);
digitalWrite(RST, HIGH);
digitalWrite(IM0, LOW);
digitalWrite(IM1, HIGH);
digitalWrite(IM2, LOW);
REG_PIOB_PER = PIN2_MASK;
REG_PIOC_PER = PIN3_MASK;
REG_PIOC_PER = PIN4_MASK;
REG_PIOC_PER = PIN5_MASK;
REG_PIOC_PER = PIN6_MASK;
REG_PIOC_PER = PIN7_MASK;
REG_PIOC_PER = PIN8_MASK;
REG_PIOC_PER = PIN9_MASK;
REG_PIOD_PER = DC_MASK;
REG_PIOD_PER = WR_MASK;
//set as output
REG_PIOB_OER = PIN2_MASK;
REG_PIOC_OER = PIN3_MASK;
REG_PIOC_OER = PIN4_MASK;
REG_PIOC_OER = PIN5_MASK;
REG_PIOC_OER = PIN6_MASK;
REG_PIOC_OER = PIN7_MASK;
REG_PIOC_OER = PIN8_MASK;
REG_PIOC_OER = PIN9_MASK;
REG_PIOD_OER = DC_MASK;
REG_PIOD_OER = WR_MASK;
}
void TFT_SDbmp(unsigned char image) // function to show bmp from SD card
{
unsigned char dummy;
switch (image) {
case 1:
myFile = SD.open("image1.bmp");
break;
case 2:
myFile = SD.open("image2.bmp");
break;
case 3:
myFile = SD.open("image3.bmp");
break;
case 4:
myFile = SD.open("image4.bmp");
break;
default:
break;
}
WindowSet(0, 479, 0, 479);
command(0x2C);
if (myFile) {
for (unsigned int i = 0; i < 54; i++) {
dummy = myFile.read();
}
//for(unsigned int i=0;i<20480;i++)
while (myFile.available()) {
data(myFile.read());
}
myFile.close();
}
}
void WindowSet(unsigned int s_x, unsigned int e_x, unsigned int s_y, unsigned int e_y) {
command(0x2a); //SET column address
data((s_x) >> 8); //SET start column address
data(s_x);
data((e_x) >> 8); //SET end column address
data(e_x);
command(0x2b); //SET page address
data((s_y) >> 8); //SET start page address
data(s_y);
data((e_y) >> 8); //SET end page address
data(e_y);
}
void disp() {
WindowSet(0, 479, 0, 479);
command(0x2C);
unsigned int i, j;
for (i = 0; i < 480; i++) //Fill screen with Red pixels
{
for (j = 0; j < 480; j++) {
data(0x00);
data(0x00);
data(0xFF);
}
}
WindowSet(0, 479, 0, 479);
command(0x2C);
for (i = 0; i < 480; i++) //Fill screen with Green pixels
{
for (j = 0; j < 480; j++) {
data(0x00);
data(0xFF);
data(0x00);
}
}
WindowSet(0, 479, 0, 479);
command(0x2C);
for (i = 0; i < 480; i++) //Fill screen with Blue pixels
{
for (j = 0; j < 480; j++) {
data(0xFF);
data(0x00);
data(0x00);
}
}
}
void Controller_Init(){
command(0x01); //Software reset
delay(120);
command(0xe2); //set multiplier and divider of PLL
data(0x1d);
data(0x02);
data(0x04);
command(0xe0); //Enable PLL
data(0x01);
delay(1);
command(0xe0);
data(0x03); //Lock PLL
command(0x01); //Software reset
delay(120);
command(0xb0); //SET LCD MODE SET TFT 18Bits MODE
data(0x0c); //SET TFT MODE & hsync+Vsync+DEN MODE
data(0x00); //SET TFT MODE & hsync+Vsync+DEN MODE
data(0x01); //SET horizontal size=480-1 HightByte
data(0xDF); //SET horizontal size=480-1 LowByte
data(0x01); //SET vertical size=480-1 HightByte
data(0xDF); //SET vertical size=480-1 LowByte
data(0x00); //SET even/odd line RGB seq.=RGB
command(0xf0);
data(0x00); //SET pixel data I/F format=8bit
command(0x36);
data(0x88); //SET address mode
command(0xe6); //SET PCLK freq
data(0x0E);
data(0xFF);
data(0xFF);
command(0xb4); //SET HBP
data(0x03); //SET HSYNC Total=1056
data(0xA0);
data(0x00); //SET HBP 88
data(0x58);
data(0x80); //SET HSYNC Pulse Width=128=127pixels+1
data(0x00); //SET Hsync pulse start position
data(0x00);
data(0x00); //SET Hsync pulse subpixel start position
command(0xb6); //SET VBP
data(0x02); //SET Vsync total 525
data(0x0d);
data(0x00); //SET VBP=32
data(0x1F);
data(0x01); //SET VSYNC Pulse Width= 0=0lines+1
data(0x00); //SET Vsync pulse start position
data(0x00);
command(0x13); //SET display on
command(0x38); //SET display on
command(0x29); //SET display on
delay(10);
}
void display_Init(){
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x13);
SPI_CMD(0xEF);
SPI_DAT(0x08);
SPI_CMD(0x3A);
SPI_DAT(0x6f);
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x10);
SPI_CMD(0xC0);
SPI_DAT(0x3B);
SPI_DAT(0x00);
SPI_CMD(0xC1);
SPI_DAT(0x09);
SPI_DAT(0x05);
SPI_CMD(0xC2);
SPI_DAT(0x07);
SPI_DAT(0x02);
SPI_CMD(0xC6);
SPI_DAT(0x21);
SPI_CMD(0xCC);
SPI_DAT(0x30);
SPI_CMD(0xB0);
SPI_DAT(0xC0);
SPI_DAT(0x54);
SPI_DAT(0x5C);
SPI_DAT(0x0D);
SPI_DAT(0x51);
SPI_DAT(0x06);
SPI_DAT(0x09);
SPI_DAT(0x08);
SPI_DAT(0x07);
SPI_DAT(0x24);
SPI_DAT(0x03);
SPI_DAT(0x11);
SPI_DAT(0x0F);
SPI_DAT(0xAC);
SPI_DAT(0xB5);
SPI_DAT(0x7F);
SPI_CMD(0xB1);
SPI_DAT(0xC0);
SPI_DAT(0x54);
SPI_DAT(0x5C);
SPI_DAT(0x0E);
SPI_DAT(0x11);
SPI_DAT(0x07);
SPI_DAT(0x0A);
SPI_DAT(0x09);
SPI_DAT(0x08);
SPI_DAT(0x24);
SPI_DAT(0x04);
SPI_DAT(0x51);
SPI_DAT(0x10);
SPI_DAT(0xAD);
SPI_DAT(0x75);
SPI_DAT(0x7F);
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x11);
SPI_CMD(0xB0);
SPI_DAT(0x7D);
SPI_CMD(0xB1);
SPI_DAT(0x33);
SPI_CMD(0xB2);
SPI_DAT(0x87);
SPI_CMD(0xB3);
SPI_DAT(0x80);
SPI_CMD(0xB5);
SPI_DAT(0x45);
SPI_CMD(0xB7);
SPI_DAT(0x87);
SPI_CMD(0xB8);
SPI_DAT(0x33);
SPI_CMD(0xB9);
SPI_DAT(0x10);
SPI_CMD(0xBB);
SPI_DAT(0x03);
SPI_CMD(0xC0);
SPI_DAT(0x03);
SPI_CMD(0xC1);
SPI_DAT(0x78);
SPI_CMD(0xC2);
SPI_DAT(0x78);
SPI_CMD(0xD0);
SPI_DAT(0x88);
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x11);
SPI_CMD(0xE0);
SPI_DAT(0x00);
SPI_DAT(0x18);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x20);
SPI_CMD(0xE1);
SPI_DAT(0x05);
SPI_DAT(0xA0);
SPI_DAT(0x00);
SPI_DAT(0xA0);
SPI_DAT(0x04);
SPI_DAT(0x0A);
SPI_DAT(0x00);
SPI_DAT(0xA0);
SPI_DAT(0x00);
SPI_DAT(0x44);
SPI_DAT(0x44);
SPI_CMD(0xE2);
SPI_DAT(0x11);
SPI_DAT(0x11);
SPI_DAT(0x44);
SPI_DAT(0x44);
SPI_DAT(0xEA);
SPI_DAT(0xA0);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0xE9);
SPI_DAT(0xA0);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_CMD(0xE3);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x11);
SPI_DAT(0x11);
SPI_CMD(0xE4);
SPI_DAT(0x44);
SPI_DAT(0x44);
SPI_CMD(0xE5);
SPI_DAT(0x06);
SPI_DAT(0xE5);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x08);
SPI_DAT(0xE7);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x0A);
SPI_DAT(0xE9);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x0C);
SPI_DAT(0xEB);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_CMD(0xE6);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x11);
SPI_DAT(0x11);
SPI_CMD(0xE7);
SPI_DAT(0x44);
SPI_DAT(0x44);
SPI_CMD(0xE8);
SPI_DAT(0x05);
SPI_DAT(0xE4);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x07);
SPI_DAT(0xE6);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x09);
SPI_DAT(0xE8);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_DAT(0x0B);
SPI_DAT(0xEA);
SPI_DAT(0xD8);
SPI_DAT(0xA0);
SPI_CMD(0xEB);
SPI_DAT(0x02);
SPI_DAT(0x00);
SPI_DAT(0xE4);
SPI_DAT(0xE4);
SPI_DAT(0x88);
SPI_DAT(0x00);
SPI_DAT(0x10);
SPI_CMD(0xEC);
SPI_DAT(0x3D);
SPI_DAT(0x02);
SPI_DAT(0x00);
SPI_CMD(0xED);
SPI_DAT(0x20);
SPI_DAT(0x76);
SPI_DAT(0x54);
SPI_DAT(0x98);
SPI_DAT(0xBA);
SPI_DAT(0xFF);
SPI_DAT(0xFF);
SPI_DAT(0xFF);
SPI_DAT(0xFF);
SPI_DAT(0xFF);
SPI_DAT(0xFF);
SPI_DAT(0xAB);
SPI_DAT(0x89);
SPI_DAT(0x45);
SPI_DAT(0x67);
SPI_DAT(0x02);
SPI_CMD(0xEF);
SPI_DAT(0x08);
SPI_DAT(0x08);
SPI_DAT(0x08);
SPI_DAT(0x45);
SPI_DAT(0x3F);
SPI_DAT(0x54);
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x13);
SPI_CMD(0xE8);
SPI_DAT(0x00);
SPI_DAT(0x0E);
SPI_CMD(0x11);
delay(120);
SPI_CMD(0xE8);
SPI_DAT(0x00);
SPI_DAT(0x0C);
delay(10);
SPI_CMD(0xE8);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_CMD(0xE6);
SPI_DAT(0x16);
SPI_DAT(0x7C);
SPI_CMD(0xFF);
SPI_DAT(0x77);
SPI_DAT(0x01);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_DAT(0x00);
SPI_CMD(0x29);
delay(120);
SPI_CMD(0x36);
SPI_DAT(0x00);
}
void setup() {
SetPins();
delay(1000);
digitalWrite(RST, LOW);
digitalWrite(RESX, LOW);
delay(5);
digitalWrite(RST, HIGH);
digitalWrite(RESX, HIGH);
display_Init();
Controller_Init();
SD.begin(ChipSelect);
}
void loop() {
disp();
TFT_SDbmp(1);
delay(200);
TFT_SDbmp(2);
delay(200);
TFT_SDbmp(3);
delay(200);
TFT_SDbmp(4);
delay(200);
}