new showBMP, TouchScreen_Calibr

This commit is contained in:
prenticedavid
2017-05-24 15:57:56 +01:00
parent b0f90efd2f
commit 6143cc7179
6 changed files with 387 additions and 52 deletions

View File

@@ -1,3 +1,7 @@
// https://forum.arduino.cc/index.php?topic=473885.msg3245748#msg3245748
// file attached 03 May 2017 21:15 BST
// TouchScreen_Calibr_kbv for MCUFRIEND UNO Display Shields
// adapted by David Prentice
// for Adafruit's <TouchScreen.h> Resistive Touch Screen Library
@@ -15,6 +19,7 @@
//
// Instructions will be given on the display.
//#define TOUCH_ORIENTATION LANDSCAPE
#define TOUCH_ORIENTATION PORTRAIT
#define TITLE "TouchScreen.h Calibration"
@@ -25,10 +30,8 @@ UTFTGLUE myGLCD(0x9341, A2, A1, A3, A4, A0);
#include <TouchScreen.h> //Adafruit Library
// MCUFRIEND UNO shield shares pins with the TFT. Due does NOT work
#define YP A1 //[A1], A3 for ILI9320, A2 for ST7789V
#define YM 7 //[ 7], 9 , 7
#define XM A2 //[A2], A2 for ILI9320, A1 for ST7789V
#define XP 6 //[ 6], 8 , 6
int YP = A1, YM = 7, XM = A2, XP = 7; //most comon configuration
TouchScreen myTouch(XP, YP, XM, YM, 300);
TSPoint tp; //Touchscreen_due branch uses Point
@@ -86,10 +89,63 @@ int dispx, dispy, text_y_center, swapxy;
uint32_t calx, caly, cals;
char buf[13];
void showpins(int A, int D, int value, const char *msg)
{
char buf[40];
sprintf(buf, "%s (A%d, D%d) = %d", msg, A - A0, D, value);
Serial.println(buf);
}
boolean diagnose_pins()
{
int i, j, value, Apins[2], Dpins[2], Values[2], found = 0;
// Serial.begin(9600);
Serial.println("Making all control and bus pins INPUT_PULLUP");
Serial.println("Typical 30k Analog pullup with corresponding pin");
Serial.println("would read low when digital is written LOW");
Serial.println("e.g. reads ~25 for 300R X direction");
Serial.println("e.g. reads ~30 for 500R Y direction");
Serial.println("");
for (i = A0; i < A5; i++) pinMode(i, INPUT_PULLUP);
for (i = 2; i < 10; i++) pinMode(i, INPUT_PULLUP);
for (i = A0; i < A4; i++) {
for (j = 5; j < 10; j++) {
pinMode(j, OUTPUT);
digitalWrite(j, LOW);
value = analogRead(i); // ignore first reading
value = analogRead(i);
if (value < 100) {
showpins(i, j, value, "Testing :");
if (found < 2) {
Apins[found] = i;
Dpins[found] = j;
Values[found] = value;
found++;
}
}
pinMode(j, INPUT_PULLUP);
}
}
if (found == 2) {
Serial.println("Diagnosing as:-");
int idx = Values[0] < Values[1];
for (i = 0; i < 2; i++) {
showpins(Apins[i], Dpins[i], Values[i],
(Values[i] < Values[!i]) ? "XM,XP: " : "YP,YM: ");
}
XM = Apins[!idx]; XP = Dpins[!idx]; YP = Apins[idx]; YM = Dpins[idx];
myTouch = TouchScreen(XP, YP, XM, YM, 300);
return true;
}
Serial.println("BROKEN TOUCHSCREEN");
return false;
}
void setup()
{
Serial.begin(9600);
Serial.println(TITLE);
bool ret = diagnose_pins();
digitalWrite(A0, HIGH);
pinMode(A0, OUTPUT);
myGLCD.InitLCD(TOUCH_ORIENTATION);
@@ -98,6 +154,10 @@ void setup()
dispx = myGLCD.getDisplayXSize();
dispy = myGLCD.getDisplayYSize();
text_y_center = (dispy / 2) - 6;
if (ret == false) {
myGLCD.print("BROKEN TOUCHSCREEN", CENTER, dispy / 2);
while (1);
}
}
void drawCrossHair(int x, int y)
@@ -232,6 +292,7 @@ void done()
{
uint16_t TS_LEFT, TS_RT, TS_TOP, TS_BOT, TS_WID, TS_HT, TS_SWAP;
int16_t tmp;
char buf[60];
myGLCD.clrScr();
myGLCD.setColor(255, 0, 0);
myGLCD.fillRect(0, 0, dispx - 1, 13);
@@ -255,35 +316,42 @@ void done()
TS_WID = ((cals >> 12) & 0x0FFF) + 1;
TS_HT = ((cals >> 0) & 0x0FFF) + 1;
TS_SWAP = (cals >> 31);
if (TOUCH_ORIENTATION != 0) {
myGLCD.print("Sketch is LANDSCAPE", 0, 126);
myGLCD.printNumI(TS_WID, 150, 126);
myGLCD.print("x", 174, 126);
myGLCD.printNumI(TS_HT, 186, 126);
showNumI("LEFT ", TS_LEFT, 0, 138);
showNumI("RT ", TS_RT, 100, 138);
showNumI("TOP ", TS_TOP, 0, 150);
showNumI("BOT ", TS_BOT, 100, 150);
switch (TOUCH_ORIENTATION) {
case 1:
tmp = TS_LEFT, TS_LEFT = TS_TOP, TS_TOP = TS_RT, TS_RT = TS_BOT, TS_BOT = tmp;
tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
break;
}
int y = 120;
Serial.println("");
sprintf(buf, "Sketch is %s %d x %d",
TOUCH_ORIENTATION ? "LANDSCAPE" : "PORTRAIT", TS_WID, TS_HT);
myGLCD.print(buf, 0, y);
Serial.println(buf);
if (TOUCH_ORIENTATION == LANDSCAPE) { //always show PORTRAIT first
tmp = TS_LEFT, TS_LEFT = TS_BOT, TS_BOT = TS_RT, TS_RT = TS_TOP, TS_TOP = tmp;
tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
}
myGLCD.print("PORTRAIT CALIBRATION", 0, 174);
myGLCD.printNumI(TS_WID, 150, 174);
myGLCD.print("x", 174, 174);
myGLCD.printNumI(TS_HT, 186, 174);
showNumI("LEFT ", TS_LEFT, 0, 186);
showNumI("RT ", TS_RT, 100, 186);
myGLCD.printNumF(((float)TS_RT - TS_LEFT) / TS_WID, 2, 200, 186);
showNumI("TOP ", TS_TOP, 0, 198);
showNumI("BOT ", TS_BOT, 100, 198);
myGLCD.printNumF(((float)TS_BOT - TS_TOP) / TS_HT, 2, 200, 198);
myGLCD.print("Touch Pin Wiring is ", 0, 222);
myGLCD.print((cals >> 31) ? "SWAPXY" : "PORTRAIT", 170, 222);
sprintf(buf, "PORTRAIT CALIBRATION %d x %d", TS_WID, TS_HT);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
sprintf(buf, "x = map(p.x, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "y = map(p.y, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "Touch Pin Wiring XP=%d XM=A%d YP=A%d YM=%d",
XP, XM - A0, YP - A0, YM);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
tmp = TS_LEFT, TS_LEFT = TS_TOP, TS_TOP = TS_RT, TS_RT = TS_BOT, TS_BOT = tmp;
tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
sprintf(buf, "LANDSCAPE CALIBRATION %d x %d", TS_WID, TS_HT);
myGLCD.print(buf, 0, y += 24);
Serial.println(buf);
sprintf(buf, "x = map(p.y, LEFT=%d, RT=%d, 0, %d)", TS_LEFT, TS_RT, TS_WID);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
sprintf(buf, "y = map(p.x, TOP=%d, BOT=%d, 0, %d)", TS_TOP, TS_BOT, TS_HT);
myGLCD.print(buf, 0, y += 12);
Serial.println(buf);
}
void fail()

View File

@@ -1,27 +1,28 @@
// Simple BMP display on Uno
// library: 320x240x24 180x180x24 320x240x16
// SDfat (SPI) 2146ms 845ms 1735ms
// SDfat (soft) 4095ms 1730ms 3241ms
// SD (SPI) 3046ms 1263ms 2441ms (7)
// SD (AS7) 16398ms 7384ms 12491ms (7)
// MCUFRIEND UNO shields have microSD on pins 10, 11, 12, 13
// The official <SD.h> library only works on the hardware SPI pins
// e.g. 11, 12, 13 on a Uno (or STM32 Nucleo)
//
//
// copy all your BMP files to the root directory on the microSD with your PC
// (or another directory)
#include <SPI.h> // f.k. for Arduino-1.5.2
#define USE_SDFAT
//#include <SD.h>
#include <SdFat.h> // Use the SdFat library
SdFat SD; // Use hardware SPI (or UNO with SD_SPI_CONFIGURATION==2)
//SdFatSoftSpi<12, 11, 13> SD; //Bit-Bang SD_SPI_CONFIGURATION==3
#include <Adafruit_GFX.h> // Hardware-specific library
#include <SPI.h> // f.k. for Arduino-1.5.2
//#define USE_SDFAT
#include <SD.h> // Use the official SD library on hardware pins
#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#define SD_CS 10
#define SD_CS 10
//#define NAMEMATCH "" // "" matches any name
#define NAMEMATCH "tiger" // *tiger*.bmp
#define PALETTEDEPTH 0 // do not support Palette modes
//#define PALETTEDEPTH 8 // support 256-colour Palette
//char namebuf[32] = "/"; //BMP files in root directory
char namebuf[32] = "/bitmaps/"; //BMP directory e.g. files in /bitmaps/*.bmp
File root;
char namebuf[32] = "/bitmaps/";
int pathlen;
void setup()
@@ -34,7 +35,6 @@ void setup()
if (ID == 0x0D3D3) ID = 0x9481;
tft.begin(ID);
tft.fillScreen(0x001F);
if (tft.height() > tft.width()) tft.setRotation(1); //LANDSCAPE
tft.setTextColor(0xFFFF, 0x0000);
bool good = SD.begin(SD_CS);
if (!good) {
@@ -59,7 +59,7 @@ void loop()
#endif
f.close();
strlwr(nm);
if (strstr(nm, ".bmp") != NULL && strstr(nm, "tiger") != NULL) {
if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH) != NULL) {
Serial.print(namebuf);
Serial.print(F(" - "));
tft.fillScreen(0);
@@ -83,6 +83,9 @@ void loop()
case 4:
Serial.println(F("unsupported BMP format"));
break;
case 5:
Serial.println(F("unsupported palette"));
break;
default:
Serial.println(F("unknown"));
break;
@@ -94,8 +97,7 @@ void loop()
#define BMPIMAGEOFFSET 54
#define PALETTEDEPTH 8
#define BUFFPIXEL 20
#define BUFFPIXEL 20
uint16_t read16(File& f) {
uint16_t result; // read little-endian
@@ -149,6 +151,7 @@ uint8_t showBMP(char *nm, int x, int y)
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (n != 1) ret = 3; // too many planes
else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
else {
bool first = true;
is565 = (pos == 3); // ?already in 16-bit format

View File

@@ -0,0 +1,264 @@
// MCUFRIEND UNO shields have microSD on pins 10, 11, 12, 13
// The official <SD.h> library only works on the hardware SPI pins
// e.g. 11, 12, 13 on a Uno
// e.g. 50, 51, 52 on a Mega2560
// e.g. 74, 75, 76 on a Due
//
// if you are not using a UNO, you must use Software SPI:
//
// install v1.0.1 of the <SdFat.h> library with the Arduino Library Manager.
// edit the src/SdFatConfig.h file to #define ENABLE_SOFTWARE_SPI_CLASS 1
//
// copy all your BMP files to the root directory on the microSD with your PC
// (or another directory)
#include <SPI.h> // f.k. for Arduino-1.5.2
#define USE_SDFAT
#include <SdFat.h> // Use the SdFat library
SdFatSoftSpi<12, 11, 13> SD; //Bit-Bang on the Shield pins
#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#define SD_CS 10
#define NAMEMATCH "" // "" matches any name
//#define NAMEMATCH "tiger" // *tiger*.bmp
#define PALETTEDEPTH 8 // support 256-colour Palette
char namebuf[32] = "/"; //BMP files in root directory
//char namebuf[32] = "/bitmaps/"; //BMP directory e.g. files in /bitmaps/*.bmp
File root;
int pathlen;
void setup()
{
uint16_t ID;
Serial.begin(9600);
Serial.print("Show BMP files on TFT with ID:0x");
ID = tft.readID();
Serial.println(ID, HEX);
if (ID == 0x0D3D3) ID = 0x9481;
tft.begin(ID);
tft.fillScreen(0x001F);
tft.setTextColor(0xFFFF, 0x0000);
bool good = SD.begin(SD_CS);
if (!good) {
Serial.print(F("cannot start SD"));
while (1);
}
root = SD.open(namebuf);
pathlen = strlen(namebuf);
}
void loop()
{
char *nm = namebuf + pathlen;
File f = root.openNextFile();
uint8_t ret;
uint32_t start;
if (f != NULL) {
#ifdef USE_SDFAT
f.getName(nm, 32 - pathlen);
#else
strcpy(nm, (char *)f.name());
#endif
f.close();
strlwr(nm);
if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH) != NULL) {
Serial.print(namebuf);
Serial.print(F(" - "));
tft.fillScreen(0);
start = millis();
ret = showBMP(namebuf, 5, 5);
switch (ret) {
case 0:
Serial.print(millis() - start);
Serial.println(F("ms"));
delay(5000);
break;
case 1:
Serial.println(F("bad position"));
break;
case 2:
Serial.println(F("bad BMP ID"));
break;
case 3:
Serial.println(F("wrong number of planes"));
break;
case 4:
Serial.println(F("unsupported BMP format"));
break;
case 5:
Serial.println(F("unsupported palette"));
break;
default:
Serial.println(F("unknown"));
break;
}
}
}
else root.rewindDirectory();
}
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20
uint16_t read16(File& f) {
uint16_t result; // read little-endian
result = f.read(); // LSB
result |= f.read() << 8; // MSB
return result;
}
uint32_t read32(File& f) {
uint32_t result;
result = f.read(); // LSB
result |= f.read() << 8;
result |= f.read() << 16;
result |= f.read() << 24; // MSB
return result;
}
uint8_t showBMP(char *nm, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24, 16, 8, 4, 1)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos; // seek position
boolean is565 = false; //
uint16_t bmpID;
uint16_t n; // blocks read
uint8_t ret;
if ((x >= tft.width()) || (y >= tft.height()))
return 1; // off screen
bmpFile = SD.open(nm); // Parse BMP header
bmpID = read16(bmpFile); // BMP signature
(void) read32(bmpFile); // Read & ignore file size
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
(void) read32(bmpFile); // Read & ignore DIB header size
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
n = read16(bmpFile); // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
pos = read32(bmpFile); // format
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (n != 1) ret = 3; // too many planes
else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
else {
bool first = true;
is565 = (pos == 3); // ?already in 16-bit format
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
if (bmpHeight < 0) { // If negative, image is in top-down order.
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
if ((x + w) >= tft.width()) // Crop area to be loaded
w = tft.width() - x;
if ((y + h) >= tft.height()) //
h = tft.height() - y;
if (bmpDepth <= PALETTEDEPTH) { // these modes have separate palette
bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
bitmask = 0xFF;
if (bmpDepth < 8)
bitmask >>= bmpDepth;
bitshift = 8 - bmpDepth;
n = 1 << bmpDepth;
lcdbufsiz -= n;
palette = lcdbuffer + lcdbufsiz;
for (col = 0; col < n; col++) {
pos = read32(bmpFile); //map palette to 5-6-5
palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
}
}
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
uint8_t r, g, b, *sdptr;
int lcdidx, lcdleft;
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; ) { //pixels in row
lcdleft = w - col;
if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
uint16_t color;
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
r = 0;
}
switch (bmpDepth) { // Convert pixel from BMP to TFT format
case 24:
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
color = tft.color565(r, g, b);
break;
case 16:
b = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
if (is565)
color = (r << 8) | (b);
else
color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
break;
case 1:
case 4:
case 8:
if (r == 0)
b = sdbuffer[buffidx++], r = 8;
color = palette[(b >> bitshift) & bitmask];
r -= bmpDepth;
b <<= bmpDepth;
break;
}
lcdbuffer[lcdidx] = color;
}
tft.pushColors(lcdbuffer, lcdidx, first);
first = false;
col += lcdidx;
} // end cols
} // end rows
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
ret = 0; // good render
}
bmpFile.close();
return (ret);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB