#include <KeDeiRPI35_t3.h>
#include <KeDeiRPI35_t3_font_Arial.h>
#include <KeDeiRPI35_t3_font_ArialBold.h>
#define TFT_CS 10
#define TOUCH_CS 9
KEDEIRPI35_t3 tft = KEDEIRPI35_t3(&SPI, TFT_CS, TOUCH_CS);
Adafruit_GFX_Button button;
uint8_t use_fb = 0;
uint8_t use_dma = 0;
uint8_t use_clip_rect = 0;
uint8_t use_set_origin = 0;
#define ORIGIN_TEST_X 50
#define ORIGIN_TEST_Y 50
void setup() {
while (!Serial && (millis() < 4000)) ;
Serial.begin(115200);
#ifdef TFT_BL
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);
#endif
tft.begin();
tft.setRotation(3);
tft.fillScreen(KEDEIRPI35_BLACK);
Serial.println("Screen should be black");
WaitForUserInput();
tft.fillScreen(KEDEIRPI35_RED);
Serial.println("Screen should be red");
WaitForUserInput();
tft.fillScreen(KEDEIRPI35_GREEN);
Serial.println("Screen should be green");
WaitForUserInput();
tft.fillScreen(KEDEIRPI35_BLUE);
Serial.println("Screen should be blue");
WaitForUserInput();
tft.fillScreen(KEDEIRPI35_WHITE);
Serial.println("Screen should be white");
WaitForUserInput();
#ifdef DEBUG_PIN
pinMode(DEBUG_PIN, OUTPUT);
#endif
button.initButton(&tft, 200, 125, 100, 40, KEDEIRPI35_GREEN, KEDEIRPI35_YELLOW, KEDEIRPI35_RED, "UP", 1);
drawTestScreen();
}
void SetupOrClearClipRectAndOffsets() {
if (use_clip_rect) {
tft.setClipRect(); // make sure we clear the whole screen
tft.setOrigin(); // make sure none are set yet
tft.fillScreen(KEDEIRPI35_LIGHTGREY);
// Now lets set origin.
if (use_set_origin)
tft.setOrigin(ORIGIN_TEST_X, ORIGIN_TEST_Y);
int x = tft.width() / 4;
int y = tft.height() / 4;
int w = tft.width() / 2;
int h = tft.height() / 2;
tft.drawRect(x, y, w, h, KEDEIRPI35_ORANGE);
tft.updateScreen();
tft.setClipRect(x + 1, y + 1, w - 2, h - 2);
delay(250);
} else {
tft.setClipRect();
if (use_set_origin)
tft.setOrigin(ORIGIN_TEST_X, ORIGIN_TEST_Y);
else
tft.setOrigin();
}
}
uint16_t palette[16]; // Should probably be 256, but I don't use many colors...
uint16_t pixel_data[2500];
const uint8_t pict1bpp[] = {0xff, 0xff, 0xc0, 0x03, 0xa0, 0x05, 0x90, 0x9, 0x88, 0x11, 0x84, 0x21, 0x82, 0x41, 0x81, 0x81,
0x81, 0x81, 0x82, 0x41, 0x84, 0x21, 0x88, 0x11, 0x90, 0x09, 0xa0, 0x05, 0xc0, 0x03, 0xff, 0xff
};
const uint8_t pict2bpp[] = {
0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff,
0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00,
0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
0xaa, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x55, 0x55,
0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
0xff, 0xff, 0x00, 0x00, 0x55, 0x55, 0xaa, 0xaa,
};
const uint8_t pict4bpp[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x33, 0x33, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
0x00, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00,
0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
void drawTestScreen() {
Serial.printf("Use FB: %d(%d) ", use_fb, use_dma); Serial.flush();
tft.useFrameBuffer(use_fb);
SetupOrClearClipRectAndOffsets();
uint32_t start_time = millis();
elapsedMillis emAsync;
tft.fillScreen(use_fb ? KEDEIRPI35_RED : KEDEIRPI35_BLACK);
//tft.setFont(Inconsolata_60);
tft.setFont(Arial_24_Bold);
tft.setTextColor(KEDEIRPI35_WHITE);
tft.setCursor(0, 0);
tft.println("Test");
tft.setTextColor(KEDEIRPI35_WHITE, KEDEIRPI35_RED);
tft.println("text");
tft.setCursor(85, 65);
tft.print("XYZ");
tft.setFontAdafruit();
tft.setTextSize(2);
tft.setTextColor(KEDEIRPI35_WHITE);
tft.println("01234");
tft.setTextColor(KEDEIRPI35_WHITE, KEDEIRPI35_GREEN);
tft.println("56789!@#$%");
tft.drawRect(0, 150, 100, 50, KEDEIRPI35_WHITE);
tft.drawLine(0, 150, 100, 50, KEDEIRPI35_GREEN);
tft.fillRectVGradient(125, 150, 50, 50, KEDEIRPI35_GREEN, KEDEIRPI35_YELLOW);
tft.fillRectHGradient(200, 150, 50, 50, KEDEIRPI35_YELLOW, KEDEIRPI35_GREEN);
// Try a read rect and write rect
#ifdef DEBUG_PIN
digitalWrite(DEBUG_PIN, HIGH);
#endif
tft.readRect(0, 0, 50, 50, pixel_data);
#ifdef DEBUG_PIN
digitalWrite(DEBUG_PIN, LOW);
#endif
tft.writeRect(250, 0, 50, 50, pixel_data);
// Lets try to pack this rectangle of data into 8 byte
tft.readRect(85, 65, 50, 50, pixel_data);
uint16_t *ppd16 = pixel_data;
uint8_t *ppd8 = (uint8_t*)pixel_data;
uint8_t palette_cnt = 0;
int palette_index;
for (int i = 0; i < 2500; i++) {
for (palette_index = 0; palette_index < palette_cnt; palette_index++) {
if (*ppd16 == palette[palette_index])
break;
}
if (palette_index >= palette_cnt) {
palette[palette_cnt++] = *ppd16; // save away the color
}
*ppd8++ = palette_index;
ppd16++;
}
tft.writeRect8BPP(200, 50, 50, 50, (uint8_t*)pixel_data, palette);
palette[0] = KEDEIRPI35_CYAN;
palette[1] = KEDEIRPI35_OLIVE;
tft.writeRect1BPP(75, 100, 16, 16, pict1bpp, palette);
tft.writeRect1BPP(320 - 90, 75, 16, 16, pict1bpp, palette);
palette[2] = KEDEIRPI35_MAROON;
palette[3] = KEDEIRPI35_PINK;
tft.writeRect2BPP(75, 125, 32, 16, pict2bpp, palette);
tft.writeRectNBPP(15, 125, 32, 16, 2, pict2bpp, palette);
tft.writeRectNBPP(75, 150, 16, 16, 4, pict4bpp, palette);
// Try drawing button
tft.setFontAdafruit();
button.drawButton();
if (use_dma) {
emAsync = 0;
tft.updateScreenAsync();
} else {
tft.updateScreen();
}
Serial.println(millis() - start_time, DEC);
if (use_dma && use_fb) {
while (tft.asyncUpdateActive() && emAsync < 500) ;
// delay(500);
Serial.printf("Async Update Time: %d DMA error status: %x\n",
(uint32_t)emAsync, DMA_ES);
}
use_fb = !use_fb;
}
void drawTextScreen(bool fOpaque) {
SetupOrClearClipRectAndOffsets();
uint32_t start_time = millis();
tft.useFrameBuffer(use_fb);
tft.fillScreen(use_fb ? KEDEIRPI35_RED : KEDEIRPI35_BLACK);
tft.setFont(Arial_40_Bold);
if (fOpaque)
tft.setTextColor(KEDEIRPI35_WHITE, use_fb ? KEDEIRPI35_BLACK : KEDEIRPI35_RED);
else
tft.setTextColor(KEDEIRPI35_WHITE);
tft.setCursor(0, 5);
tft.println("AbCdEfGhIj");
tft.setFont(Arial_28_Bold);
tft.println("0123456789!@#$");
#if 1
tft.setFont(Arial_20_Bold);
tft.println("abcdefghijklmnopq");
tft.setFont(Arial_14_Bold);
tft.println("ABCDEFGHIJKLMNOPQRST");
tft.setFont(Arial_10_Bold);
tft.println("0123456789zyxwvutu");
#endif
tft.updateScreen();
Serial.printf("Use FB: %d OP: %d, DT: %d OR: %d\n", use_fb, fOpaque, use_set_origin, millis() - start_time);
}
//=============================================================================
// Wait for user input
//=============================================================================
void WaitForUserInput() {
Serial.println("Hit Enter to continue");
Serial.flush();
while (Serial.read() == -1) ;
while (Serial.read() != -1) ;
}
//=============================================================================
// Try continuous update
//=============================================================================
void WaitForFrame(bool fCont, uint32_t wait_frame_count) {
if (fCont) {
while (tft.frameCount() < wait_frame_count) yield();
} else {
tft.updateScreenAsync();
WaitForUserInput();
}
}
void testDMAContUpdate(bool fCont) {
// Force frame buffer on
Serial.printf("continuous DMA udpate test - Frame mode on\n"); Serial.flush();
if (!fCont) {
Serial.println("Step Mode");
Serial.flush();
}
use_fb = 1; //
tft.useFrameBuffer(use_fb);
tft.fillScreen(KEDEIRPI35_GREEN);
// check to see if screen memory actually turned green.
if (use_fb) {
uint8_t *pw = tft.getFrameBuffer();
uint16_t *pallet = tft.getPallet();
int error_count = 0;
for (int i = 0; i < (KEDEIRPI35_TFTWIDTH * KEDEIRPI35_TFTHEIGHT); i++)
{
if (pallet[*pw] != KEDEIRPI35_GREEN) {
Serial.printf("tft.fillScreen(KEDEIRPI35_GREEN) not green? %d != %x %x\n", i, *pw, pallet[*pw]);
error_count++;
}
pw++;
}
Serial.printf("tft.fillScreen(KEDEIRPI35_GREEN(%x)) error count = %d\n", KEDEIRPI35_GREEN, error_count);
}
if (fCont)
tft.updateScreenAsync(fCont);
// Start the update
WaitForFrame(fCont, 10);
tft.fillScreen(KEDEIRPI35_YELLOW);
tft.drawRect(5, 5, 310, 230, KEDEIRPI35_GREEN);
tft.fillRect(140, 100, 40, 40, KEDEIRPI35_BLUE);
WaitForFrame(fCont, 20);
tft.fillScreen(KEDEIRPI35_RED);
tft.drawRect(5, 5, 310, 230, KEDEIRPI35_WHITE);
WaitForFrame(fCont, 30);
tft.fillScreen(KEDEIRPI35_BLACK);
tft.drawRect(5, 5, 310, 230, KEDEIRPI35_GREEN);
tft.drawRect(25, 25, 270, 190, KEDEIRPI35_RED);
WaitForFrame(fCont, 40);
digitalWrite(0, HIGH);
tft.drawRect(5, 5, 310, 230, KEDEIRPI35_GREEN);
tft.setCursor(10, 100);
tft.setTextColor(KEDEIRPI35_RED, KEDEIRPI35_BLACK);
tft.setFont(Arial_20_Bold);
tft.println("DONE");
tft.setFontAdafruit();
tft.setCursor(10, 200);
tft.setTextColor(KEDEIRPI35_GREEN);
tft.print("Done");
tft.setTextSize(2);
tft.setCursor(10, 50);
tft.setTextColor(KEDEIRPI35_WHITE, KEDEIRPI35_RED);
tft.print("Done");
digitalWrite(0, LOW);
WaitForFrame(fCont, 45);
tft.fillRect(0, 0, 2, 2, KEDEIRPI35_PURPLE);
if (!fCont) {
Serial.println("Lets now try doing Continue for a few iterations to see if it changes");
tft.updateScreenAsync(true);
while (tft.frameCount() < 10) yield();
}
tft.endUpdateAsync();
Serial.println("after endUpdateAsync");
tft.waitUpdateAsyncComplete();
Serial.println("after waitUpdateAsyncComplete");
Serial.println("Finished test");
delay(2000);
Serial.println("Do normal update to see if data is there");
tft.updateScreen();
}
void loop(void) {
// See if any text entered
int ich;
if ((ich = Serial.read()) != -1) {
while (Serial.read() != -1) ;
if (ich == 'c') {
use_clip_rect = !use_clip_rect;
if (use_clip_rect) Serial.println("Clip Rectangle Turned on");
else Serial.println("Clip Rectangle turned off");
return;
}
if (ich == 'd') {
use_dma = !use_dma;
if (use_dma) Serial.println("DMA Turned on");
else Serial.println("DMA turned off");
return;
}
if (ich == 's') {
use_set_origin = !use_set_origin;
if (use_set_origin) Serial.printf("Set origin to %d, %d\n", ORIGIN_TEST_X, ORIGIN_TEST_Y);
else Serial.println("Clear origin");
return;
}
if (ich == 'o')
drawTextScreen(1);
else if (ich == 't')
drawTextScreen(0);
else if (ich == 'r') {
testDMAContUpdate(true);
Serial.println("Returned from testDMAContUpdate");
}
else if (ich == 'a') {
testDMAContUpdate(false);
Serial.println("Returned from testDMAContUpdate");
}
else
drawTestScreen();
}
}