This sketch demo uses the NHD-FT81x-Shield paired with the NHD-ST1-BT817 Controller board. Display SPI initialization is done through the BT817 EVE IC.
//---------------------------------------------------------
/*
(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.
*/
//---------------------------------------------------------
#include <SPI.h>
#include <GD2.h>
// Include new BT817 registers
#define REG_GPIOX 3154076UL
#define REG_GPIOX_DIR 3154072UL
// Resolution for the display
int _hsize = 480;
int _vsize = 480;
int _screen = 0;
// Initialize Embedded Video Controller
void init_480X480() {
GD.wr16(REG_PWM_DUTY, 128);
GD.wr16(REG_PWM_HZ, 5000);
GD.wr16(REG_GPIOX_DIR, 0x800F);
GD.wr16(REG_GPIOX, 0x8000);
delay(20);
GD.wr16(REG_GPIOX, 0x0000);
delay(20);
GD.wr16(REG_GPIOX, 0x8000 | 0b1111);
delay(2000); // NECESSARRY 2s DELAY BEFORE TFT INITIALIZATION
_lcd_init();
delay(100);
// Horizontal timing (pixels)
GD.wr16(REG_HSIZE, _hsize); // Active pixels
GD.wr16(REG_HCYCLE, 790); // 10 + 150 + 480 + 150
GD.wr16(REG_HSYNC0, 0); // HSYNC start
GD.wr16(REG_HSYNC1, 10); // HSYNC end (width = 10)
GD.wr16(REG_HOFFSET, 160); // HSYNC(10) + HBP(150)
// Vertical timing (lines)
GD.wr16(REG_VSIZE, _vsize); // Active lines
GD.wr16(REG_VCYCLE, 530); // 10 + 20 + 480 + 20
GD.wr16(REG_VSYNC0, 0); // VSYNC start
GD.wr16(REG_VSYNC1, 10); // VSYNC end (width = 10)
GD.wr16(REG_VOFFSET, 30); // VSYNC(10) + VBP(20)
// Pixel clock and signal polarity
GD.wr16(REG_PCLK, 2);
GD.wr16(REG_SWIZZLE, 0);
GD.wr16(REG_PCLK_POL, 0);
GD.wr16(REG_CSPREAD, 0);
GD.wr16(REG_DITHER, 1);
GD.wr16(REG_ROTATE, 0);
GD.wr16(REG_PWM_HZ, 5000);
GD.swap();
}
// Initialization Command through BT817 GPIO SPI
void _lcd_com(unsigned char c) {
GD.wr16(REG_GPIOX, 0x8000 | 0b0011);
for (int i = 0; i < 8; i++) {
if ((c & 0x80) == 0x80) {
GD.wr16(REG_GPIOX, 0x8000 | 0b0011);
GD.wr16(REG_GPIOX, 0x8000 | 0b0010);
GD.wr16(REG_GPIOX, 0x8000 | 0b0011);
} else {
GD.wr16(REG_GPIOX, 0x8000 | 0b0001);
GD.wr16(REG_GPIOX, 0x8000 | 0b0000);
GD.wr16(REG_GPIOX, 0x8000 | 0b0001);
}
c = (c << 1); // Shift byte
}
GD.wr16(REG_GPIOX, 0x8000 | 0b0100);
}
// Initialization Data through BT817 GPIO SPI
void _lcd_dat(unsigned char d) {
GD.wr16(REG_GPIOX, 0x8000 | 0b1011);
for (int i = 0; i < 8; i++) {
if ((d & 0x80) == 0x80) {
GD.wr16(REG_GPIOX, 0x8000 | 0b1011);
GD.wr16(REG_GPIOX, 0x8000 | 0b1010);
GD.wr16(REG_GPIOX, 0x8000 | 0b1011);
} else {
GD.wr16(REG_GPIOX, 0x8000 | 0b1001);
GD.wr16(REG_GPIOX, 0x8000 | 0b1000);
GD.wr16(REG_GPIOX, 0x8000 | 0b1001);
}
d = (d << 1); // Shift byte
}
GD.wr16(REG_GPIOX, 0x8000 | 0b0100);
}
// Initializate LCD TFT
void _lcd_init() {
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x13);
_lcd_com(0xEF);
_lcd_dat(0x08);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x10);
_lcd_com(0xC0);
_lcd_dat(0x3B);
_lcd_dat(0x00);
_lcd_com(0xC1);
_lcd_dat(0x0D);
_lcd_dat(0x02);
_lcd_com(0xC2);
_lcd_dat(0x21);
_lcd_dat(0x08);
_lcd_com(0xC7);
_lcd_dat(0x00);
_lcd_com(0xCC);
_lcd_dat(0x18);
_lcd_com(0xB0);
_lcd_dat(0x00);
_lcd_dat(0x13);
_lcd_dat(0x1E);
_lcd_dat(0x0E);
_lcd_dat(0x11);
_lcd_dat(0x05);
_lcd_dat(0x09);
_lcd_dat(0x07);
_lcd_dat(0x07);
_lcd_dat(0x23);
_lcd_dat(0x04);
_lcd_dat(0x12);
_lcd_dat(0x0F);
_lcd_dat(0xA7);
_lcd_dat(0x2C);
_lcd_dat(0x18);
_lcd_com(0xB1);
_lcd_dat(0x00);
_lcd_dat(0x14);
_lcd_dat(0x1B);
_lcd_dat(0x0E);
_lcd_dat(0x11);
_lcd_dat(0x06);
_lcd_dat(0x06);
_lcd_dat(0x08);
_lcd_dat(0x07);
_lcd_dat(0x20);
_lcd_dat(0x04);
_lcd_dat(0x12);
_lcd_dat(0x11);
_lcd_dat(0xA5);
_lcd_dat(0x2F);
_lcd_dat(0x18);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x11);
_lcd_com(0xB0);
_lcd_dat(0x60);
_lcd_com(0xB1);
_lcd_dat(0x31);
_lcd_com(0xB2);
_lcd_dat(0x8A);
_lcd_com(0xB3);
_lcd_dat(0x80);
_lcd_com(0xB5);
_lcd_dat(0x4B);
_lcd_com(0xB7);
_lcd_dat(0x85);
_lcd_com(0xB8);
_lcd_dat(0x21);
_lcd_com(0xC0);
_lcd_dat(0x07);
_lcd_com(0xC1);
_lcd_dat(0x78);
_lcd_com(0xC2);
_lcd_dat(0x78);
_lcd_com(0xE0);
_lcd_dat(0x00);
_lcd_dat(0x1B);
_lcd_dat(0x02);
_lcd_com(0xE1);
_lcd_dat(0x08);
_lcd_dat(0xA0);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x07);
_lcd_dat(0xA0);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x44);
_lcd_dat(0x44);
_lcd_com(0xE2);
_lcd_dat(0x11);
_lcd_dat(0x11);
_lcd_dat(0x44);
_lcd_dat(0x44);
_lcd_dat(0xED);
_lcd_dat(0xA0);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0xEC);
_lcd_dat(0xA0);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_com(0xE3);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x11);
_lcd_dat(0x11);
_lcd_com(0xE4);
_lcd_dat(0x44);
_lcd_dat(0x44);
_lcd_com(0xE5);
_lcd_dat(0x0A);
_lcd_dat(0xE9);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x0C);
_lcd_dat(0xEB);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x0E);
_lcd_dat(0xED);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x10);
_lcd_dat(0xEF);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_com(0xE6);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x11);
_lcd_dat(0x11);
_lcd_com(0xE7);
_lcd_dat(0x44);
_lcd_dat(0x44);
_lcd_com(0xE8);
_lcd_dat(0x09);
_lcd_dat(0xE8);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x0B);
_lcd_dat(0xEA);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x0D);
_lcd_dat(0xEC);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_dat(0x0F);
_lcd_dat(0xEE);
_lcd_dat(0xD8);
_lcd_dat(0xA0);
_lcd_com(0xEB);
_lcd_dat(0x02);
_lcd_dat(0x00);
_lcd_dat(0xE4);
_lcd_dat(0xE4);
_lcd_dat(0x88);
_lcd_dat(0x00);
_lcd_dat(0x40);
_lcd_com(0xEC);
_lcd_dat(0x3C);
_lcd_dat(0x00);
_lcd_com(0xED);
_lcd_dat(0xAB);
_lcd_dat(0x89);
_lcd_dat(0x76);
_lcd_dat(0x54);
_lcd_dat(0x02);
_lcd_dat(0xFF);
_lcd_dat(0xFF);
_lcd_dat(0xFF);
_lcd_dat(0xFF);
_lcd_dat(0xFF);
_lcd_dat(0xFF);
_lcd_dat(0x20);
_lcd_dat(0x45);
_lcd_dat(0x67);
_lcd_dat(0x98);
_lcd_dat(0xBA);
_lcd_com(0xEF);
_lcd_dat(0x08);
_lcd_dat(0x08);
_lcd_dat(0x08);
_lcd_dat(0x45);
_lcd_dat(0x3F);
_lcd_dat(0x54);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x13);
_lcd_com(0xE8);
_lcd_dat(0x00);
_lcd_dat(0x0E);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_com(0x11);
delay(120);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x13);
_lcd_com(0xE8);
_lcd_dat(0x00);
_lcd_dat(0x0C);
delay(10);
_lcd_com(0xE8);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_com(0xFF);
_lcd_dat(0x77);
_lcd_dat(0x01);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_dat(0x00);
_lcd_com(0x3A); // 565RGB 55 16bit,666RGB 66 18bit,24bit 77
_lcd_dat(0x77);
_lcd_com(0x29);
_lcd_com(0x36);
_lcd_dat(0x00);
}
void setup() {
GD.begin(0, 10, 5);
delay(100);
init_480X480();
GD.ClearColorRGB(0x808080);
GD.cmd_sketch(0, 0, 480, 480, 0, L8); // start sketching
GD.cmd_memset(0, 0, 480UL * 480UL); // clear the bitmap
GD.Clear();
GD.ColorRGB(255, 255, 255);
GD.PointSize(16 * 230);
GD.Begin(POINTS);
GD.Vertex2ii(240, 240);
GD.BitmapLayout(L8, 480, 480);
GD.BitmapSize(NEAREST, BORDER, BORDER, 480, 480);
GD.ColorRGB(255, 0, 0);
GD.Begin(BITMAPS);
GD.Vertex2ii(0, 0);
GD.finish();
GD.swap();
}
void loop() {
}