Components and supplies
Arduino UNO
Project description
Code
TFT_Shield_SD_2.ino
arduino
1/*This code is meant for the 2.4" TFT LCD touch screen shield with UNO board 2 * It creates a little slide show of images that changes depending on where you pressed on the screen 3 * The images are read from SD card 4 * Refer to SurtrTech.com for more details 5 */ 6 7#include <SPFD5408_Adafruit_GFX.h> // Core graphics library 8#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library 9#include <SPI.h> 10#include <SD.h> 11#include <SPFD5408_TouchScreen.h> //Touch screen functions library 12 13 14#if defined(__SAM3X8E__) 15 #undef __FlashStringHelper::F(string_literal) 16 #define F(string_literal) string_literal 17#endif 18 19 20//The parameters bellow depends on your shield so make sure the pins are correct 21#define YP A3 // must be an analog pin, use "An" notation! 22#define XM A2 // must be an analog pin, use "An" notation! 23#define YM 9 // can be a digital pin 24#define XP 8 // can be a digital pin 25 26//Don't forget if your touch function doesn't work check the values above it may be (A1 A2 7 6) resp 27 28// Calibrate values you may want to run the calibration code first and set those points 29#define TS_MINX 176 30#define TS_MINY 159 31#define TS_MAXX 921 32#define TS_MAXY 884 33#define MINPRESSURE 10 34#define MAXPRESSURE 1000 35 36 37TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 38 39#define LCD_CS A3 // Chip Select goes to Analog 3 40#define LCD_CD A2 // Command/Data goes to Analog 2 41#define LCD_WR A1 // LCD Write goes to Analog 1 42#define LCD_RD A0 // LCD Read goes to Analog 0 43 44#define SD_CS 10 // Set the chip select line to whatever you use 45 46Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4); 47 48char x[]="x1.bmp"; 49/*Here in this code I declared the names as an Array 50 * So I can do modifications if I want to scroll through 51 * Make sure you images have a number like "1" so you can increase it or decrease 52 * to go to the next image 53 */ 54 55void setup() 56{ 57 58 Serial.begin(9600); 59 tft.reset(); 60 uint16_t identifier = tft.readID(); 61 pinMode(10, OUTPUT); 62 digitalWrite(10, HIGH); 63 tft.begin(identifier); 64 if (!SD.begin(SD_CS)) { 65 progmemPrintln(PSTR("failed!")); 66 return; 67 } 68 tft.setRotation(1); //To do a 90 rotation of the screen 69 bmpDraw(x, 0, 0); //we draw the first image which is x -> "x1.bmp" as we declared 70} 71 72void loop() 73{ 74if(x[1]<49) //So we don't go to some strange values I add here a reset of the values 75x[1]=49; //If we're already in the first picture we stay there, same for the last 76if(x[1]>52) //"1" in char is "49" and "4" is "52" I wrote them in this format so I can manipulate them 77x[1]=52; 78 79 80 TSPoint p = ts.getPoint(); //checking if the user touched the screen 81 82 pinMode(XM, OUTPUT); 83 pinMode(YP, OUTPUT); 84 85 if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { //p.z means the pressure value so if the touch wants to be detected 86 // it pressure should be in this range (it's enough) 87 88 p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); //x and y positions of the touch so the program know the postion where the user has pressed 89 90 p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());; 91 92//The screen is rotated like in setRotation(1) so now I'm playing on Y axis only 93//And here I got like two big rectangles on the sides of the screen that are considered as buttons 94//You can add conditions on x to make small buttons 95 96 if(p.y > 0 && p.y < 100 ){ 97 Serial.println("Left"); //I did this to show on serial monitor that I pressed left 98 x[1]=x[1]-1; //here we change the name of the file we want to read x[]="x1.bmp" and x[1] is the 1 in the name and x[0] is x 99 bmpDraw(x, 0, 0); //So what I do is just increase it to make it 2 or decrease it to make it 0 (refer to the first "if" to see the solution for this case as 0 doesn't exist) 100 delay(300); //Then I draw the image which now has a different name depending on which side I pressed 101 } //Adding a little delay so the touch detection wont bounce 102 103 else if(p.y >200 && p.y <320){ 104 Serial.println("Right"); 105 x[1]=x[1]+1; 106 bmpDraw(x, 0, 0); 107 delay(300); 108 } 109 } 110 111 112} 113 114 115#define BUFFPIXEL 20 //Printing speed 20 is meant to be the best, you can go to 60 but using too much RAM 116 117//drawing function no touchy :D 118void bmpDraw(char *filename, int x, int y) { 119 120 File bmpFile; 121 int bmpWidth, bmpHeight; // W+H in pixels 122 uint8_t bmpDepth; // Bit depth (currently must be 24) 123 uint32_t bmpImageoffset; // Start of image data in file 124 uint32_t rowSize; // Not always = bmpWidth; may have padding 125 uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel) 126 uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel) 127 uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer 128 boolean goodBmp = false; // Set to true on valid header parse 129 boolean flip = true; // BMP is stored bottom-to-top 130 int w, h, row, col; 131 uint8_t r, g, b; 132 uint32_t pos = 0, startTime = millis(); 133 uint8_t lcdidx = 0; 134 boolean first = true; 135 136 if((x >= tft.width()) || (y >= tft.height())) return; 137 138 Serial.println(); 139 progmemPrint(PSTR("Loading image '")); 140 Serial.print(filename); 141 Serial.println('\\''); 142 // Open requested file on SD card 143 if ((bmpFile = SD.open(filename)) == NULL) { 144 progmemPrintln(PSTR("File not found")); 145 return; 146 } 147 148 // Parse BMP header 149 if(read16(bmpFile) == 0x4D42) { // BMP signature 150 progmemPrint(PSTR("File size: ")); Serial.println(read32(bmpFile)); 151 (void)read32(bmpFile); // Read & ignore creator bytes 152 bmpImageoffset = read32(bmpFile); // Start of image data 153 progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, DEC); 154 // Read DIB header 155 progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile)); 156 bmpWidth = read32(bmpFile); 157 bmpHeight = read32(bmpFile); 158 if(read16(bmpFile) == 1) { // # planes -- must be '1' 159 bmpDepth = read16(bmpFile); // bits per pixel 160 progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth); 161 if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 162 163 goodBmp = true; // Supported BMP format -- proceed! 164 progmemPrint(PSTR("Image size: ")); 165 Serial.print(bmpWidth); 166 Serial.print('x'); 167 Serial.println(bmpHeight); 168 169 // BMP rows are padded (if needed) to 4-byte boundary 170 rowSize = (bmpWidth * 3 + 3) & ~3; 171 172 // If bmpHeight is negative, image is in top-down order. 173 // This is not canon but has been observed in the wild. 174 if(bmpHeight < 0) { 175 bmpHeight = -bmpHeight; 176 flip = false; 177 } 178 179 // Crop area to be loaded 180 w = bmpWidth; 181 h = bmpHeight; 182 if((x+w-1) >= tft.width()) w = tft.width() - x; 183 if((y+h-1) >= tft.height()) h = tft.height() - y; 184 185 // Set TFT address window to clipped image bounds 186 tft.setAddrWindow(x, y, x+w-1, y+h-1); 187 188 for (row=0; row<h; row++) { // For each scanline... 189 // Seek to start of scan line. It might seem labor- 190 // intensive to be doing this on every line, but this 191 // method covers a lot of gritty details like cropping 192 // and scanline padding. Also, the seek only takes 193 // place if the file position actually needs to change 194 // (avoids a lot of cluster math in SD library). 195 if(flip) // Bitmap is stored bottom-to-top order (normal BMP) 196 pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; 197 else // Bitmap is stored top-to-bottom 198 pos = bmpImageoffset + row * rowSize; 199 if(bmpFile.position() != pos) { // Need seek? 200 bmpFile.seek(pos); 201 buffidx = sizeof(sdbuffer); // Force buffer reload 202 } 203 204 for (col=0; col<w; col++) { // For each column... 205 // Time to read more pixel data? 206 if (buffidx >= sizeof(sdbuffer)) { // Indeed 207 // Push LCD buffer to the display first 208 if(lcdidx > 0) { 209 tft.pushColors(lcdbuffer, lcdidx, first); 210 lcdidx = 0; 211 first = false; 212 } 213 bmpFile.read(sdbuffer, sizeof(sdbuffer)); 214 buffidx = 0; // Set index to beginning 215 } 216 217 // Convert pixel from BMP to TFT format 218 b = sdbuffer[buffidx++]; 219 g = sdbuffer[buffidx++]; 220 r = sdbuffer[buffidx++]; 221 lcdbuffer[lcdidx++] = tft.color565(r,g,b); 222 } // end pixel 223 } // end scanline 224 // Write any remaining data to LCD 225 if(lcdidx > 0) { 226 tft.pushColors(lcdbuffer, lcdidx, first); 227 } 228 progmemPrint(PSTR("Loaded in ")); 229 Serial.print(millis() - startTime); 230 Serial.println(" ms"); 231 } // end goodBmp 232 } 233 } 234 235 bmpFile.close(); 236 if(!goodBmp) progmemPrintln(PSTR("BMP format not recognized.")); 237} 238 239// These read 16- and 32-bit types from the SD card file. 240// BMP data is stored little-endian, Arduino is little-endian too. 241// May need to reverse subscript order if porting elsewhere. 242 243uint16_t read16(File f) { 244 uint16_t result; 245 ((uint8_t *)&result)[0] = f.read(); // LSB 246 ((uint8_t *)&result)[1] = f.read(); // MSB 247 return result; 248} 249 250uint32_t read32(File f) { 251 uint32_t result; 252 ((uint8_t *)&result)[0] = f.read(); // LSB 253 ((uint8_t *)&result)[1] = f.read(); 254 ((uint8_t *)&result)[2] = f.read(); 255 ((uint8_t *)&result)[3] = f.read(); // MSB 256 return result; 257} 258 259// Copy string from flash to serial port 260// Source string MUST be inside a PSTR() declaration! 261void progmemPrint(const char *str) { 262 char c; 263 while(c = pgm_read_byte(str++)) Serial.print(c); 264} 265 266// Same as above, with trailing newline 267void progmemPrintln(const char *str) { 268 progmemPrint(str); 269 Serial.println(); 270} 271 272
TFT_Shield_SD_2.ino
arduino
1/*This code is meant for the 2.4" TFT LCD touch screen shield with UNO 2 board 3 * It creates a little slide show of images that changes depending on where 4 you pressed on the screen 5 * The images are read from SD card 6 * Refer to 7 SurtrTech.com for more details 8 */ 9 10#include <SPFD5408_Adafruit_GFX.h> 11 // Core graphics library 12#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific 13 library 14#include <SPI.h> 15#include <SD.h> 16#include 17 <SPFD5408_TouchScreen.h> //Touch screen functions library 18 19 20#if defined(__SAM3X8E__) 21 22 #undef __FlashStringHelper::F(string_literal) 23 #define F(string_literal) 24 string_literal 25#endif 26 27 28//The parameters bellow depends on your shield 29 so make sure the pins are correct 30#define YP A3 // must be an analog pin, use 31 "An" notation! 32#define XM A2 // must be an analog pin, use "An" notation! 33#define 34 YM 9 // can be a digital pin 35#define XP 8 // can be a digital pin 36 37//Don't 38 forget if your touch function doesn't work check the values above it may be (A1 39 A2 7 6) resp 40 41// Calibrate values you may want to run the calibration code 42 first and set those points 43#define TS_MINX 176 44#define TS_MINY 159 45#define 46 TS_MAXX 921 47#define TS_MAXY 884 48#define MINPRESSURE 10 49#define MAXPRESSURE 50 1000 51 52 53TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 54 55#define 56 LCD_CS A3 // Chip Select goes to Analog 3 57#define LCD_CD A2 // Command/Data goes 58 to Analog 2 59#define LCD_WR A1 // LCD Write goes to Analog 1 60#define LCD_RD 61 A0 // LCD Read goes to Analog 0 62 63#define SD_CS 10 // Set the chip select 64 line to whatever you use 65 66Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, 67 A4); 68 69char x[]="x1.bmp"; 70/*Here in this code I declared the names as 71 an Array 72 * So I can do modifications if I want to scroll through 73 * Make 74 sure you images have a number like "1" so you can increase it or decrease 75 76 * to go to the next image 77 */ 78 79void setup() 80{ 81 82 Serial.begin(9600); 83 84 tft.reset(); 85 uint16_t identifier = tft.readID(); 86 pinMode(10, OUTPUT); 87 88 digitalWrite(10, HIGH); 89 tft.begin(identifier); 90 if (!SD.begin(SD_CS)) 91 { 92 progmemPrintln(PSTR("failed!")); 93 return; 94 } 95 tft.setRotation(1); 96 //To do a 90 rotation of the screen 97 bmpDraw(x, 0, 0); //we draw the first 98 image which is x -> "x1.bmp" as we declared 99} 100 101void loop() 102{ 103if(x[1]<49) 104 //So we don't go to some strange values I add here a reset of the values 105x[1]=49; 106 //If we're already in the first picture we stay there, same for the last 107if(x[1]>52) 108 //"1" in char is "49" and "4" is "52" I wrote them in this format so 109 I can manipulate them 110x[1]=52; 111 112 113 TSPoint p = ts.getPoint(); //checking 114 if the user touched the screen 115 116 pinMode(XM, OUTPUT); 117 pinMode(YP, OUTPUT); 118 119 120 if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { //p.z means the pressure value so 121 if the touch wants to be detected 122 // 123 it pressure should be in this range (it's enough) 124 125 p.x = map(p.x, TS_MINX, 126 TS_MAXX, 0, tft.width()); //x and y positions of the touch so the program know 127 the postion where the user has pressed 128 129 p.y = map(p.y, TS_MINY, TS_MAXY, 130 0, tft.height());; 131 132//The screen is rotated like in setRotation(1) so now 133 I'm playing on Y axis only 134//And here I got like two big rectangles on the sides 135 of the screen that are considered as buttons 136//You can add conditions on x to 137 make small buttons 138 139 if(p.y > 0 && p.y < 100 ){ 140 Serial.println("Left"); 141 //I did this to show on serial monitor that I pressed left 142 x[1]=x[1]-1; 143 //here we change the name of the file we want to read x[]="x1.bmp" 144 and x[1] is the 1 in the name and x[0] is x 145 bmpDraw(x, 0, 0); //So 146 what I do is just increase it to make it 2 or decrease it to make it 0 (refer to 147 the first "if" to see the solution for this case as 0 doesn't exist) 148 delay(300); 149 //Then I draw the image which now has a different name depending 150 on which side I pressed 151 } //Adding a little delay 152 so the touch detection wont bounce 153 154 else if(p.y >200 && p.y <320){ 155 156 Serial.println("Right"); 157 x[1]=x[1]+1; 158 bmpDraw(x, 0, 0); 159 160 delay(300); 161 } 162 } 163 164 165} 166 167 168#define BUFFPIXEL 20 169 //Printing speed 20 is meant to be the best, you can go to 60 but using 170 too much RAM 171 172//drawing function no touchy :D 173void bmpDraw(char *filename, 174 int x, int y) { 175 176 File bmpFile; 177 int bmpWidth, bmpHeight; // 178 W+H in pixels 179 uint8_t bmpDepth; // Bit depth (currently must 180 be 24) 181 uint32_t bmpImageoffset; // Start of image data in file 182 uint32_t 183 rowSize; // Not always = bmpWidth; may have padding 184 uint8_t sdbuffer[3*BUFFPIXEL]; 185 // pixel in buffer (R+G+B per pixel) 186 uint16_t lcdbuffer[BUFFPIXEL]; // pixel 187 out buffer (16-bit per pixel) 188 uint8_t buffidx = sizeof(sdbuffer); // Current 189 position in sdbuffer 190 boolean goodBmp = false; // Set to true on valid 191 header parse 192 boolean flip = true; // BMP is stored bottom-to-top 193 194 int w, h, row, col; 195 uint8_t r, g, b; 196 uint32_t pos = 0, startTime 197 = millis(); 198 uint8_t lcdidx = 0; 199 boolean first = true; 200 201 if((x 202 >= tft.width()) || (y >= tft.height())) return; 203 204 Serial.println(); 205 progmemPrint(PSTR("Loading 206 image '")); 207 Serial.print(filename); 208 Serial.println('\\''); 209 // Open 210 requested file on SD card 211 if ((bmpFile = SD.open(filename)) == NULL) { 212 213 progmemPrintln(PSTR("File not found")); 214 return; 215 } 216 217 // 218 Parse BMP header 219 if(read16(bmpFile) == 0x4D42) { // BMP signature 220 progmemPrint(PSTR("File 221 size: ")); Serial.println(read32(bmpFile)); 222 (void)read32(bmpFile); // Read 223 & ignore creator bytes 224 bmpImageoffset = read32(bmpFile); // Start of image 225 data 226 progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, 227 DEC); 228 // Read DIB header 229 progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile)); 230 231 bmpWidth = read32(bmpFile); 232 bmpHeight = read32(bmpFile); 233 if(read16(bmpFile) 234 == 1) { // # planes -- must be '1' 235 bmpDepth = read16(bmpFile); // bits 236 per pixel 237 progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth); 238 239 if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 240 241 242 goodBmp = true; // Supported BMP format -- proceed! 243 progmemPrint(PSTR("Image 244 size: ")); 245 Serial.print(bmpWidth); 246 Serial.print('x'); 247 248 Serial.println(bmpHeight); 249 250 // BMP rows are padded (if needed) 251 to 4-byte boundary 252 rowSize = (bmpWidth * 3 + 3) & ~3; 253 254 // 255 If bmpHeight is negative, image is in top-down order. 256 // This is not 257 canon but has been observed in the wild. 258 if(bmpHeight < 0) { 259 bmpHeight 260 = -bmpHeight; 261 flip = false; 262 } 263 264 // Crop 265 area to be loaded 266 w = bmpWidth; 267 h = bmpHeight; 268 if((x+w-1) 269 >= tft.width()) w = tft.width() - x; 270 if((y+h-1) >= tft.height()) h 271 = tft.height() - y; 272 273 // Set TFT address window to clipped image bounds 274 275 tft.setAddrWindow(x, y, x+w-1, y+h-1); 276 277 for (row=0; row<h; 278 row++) { // For each scanline... 279 // Seek to start of scan line. It 280 might seem labor- 281 // intensive to be doing this on every line, but 282 this 283 // method covers a lot of gritty details like cropping 284 // 285 and scanline padding. Also, the seek only takes 286 // place if the file 287 position actually needs to change 288 // (avoids a lot of cluster math 289 in SD library). 290 if(flip) // Bitmap is stored bottom-to-top order (normal 291 BMP) 292 pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; 293 294 else // Bitmap is stored top-to-bottom 295 pos = bmpImageoffset 296 + row * rowSize; 297 if(bmpFile.position() != pos) { // Need seek? 298 299 bmpFile.seek(pos); 300 buffidx = sizeof(sdbuffer); // Force 301 buffer reload 302 } 303 304 for (col=0; col<w; col++) { // For 305 each column... 306 // Time to read more pixel data? 307 if 308 (buffidx >= sizeof(sdbuffer)) { // Indeed 309 // Push LCD buffer to 310 the display first 311 if(lcdidx > 0) { 312 tft.pushColors(lcdbuffer, 313 lcdidx, first); 314 lcdidx = 0; 315 first = false; 316 317 } 318 bmpFile.read(sdbuffer, sizeof(sdbuffer)); 319 buffidx 320 = 0; // Set index to beginning 321 } 322 323 // Convert pixel 324 from BMP to TFT format 325 b = sdbuffer[buffidx++]; 326 g 327 = sdbuffer[buffidx++]; 328 r = sdbuffer[buffidx++]; 329 lcdbuffer[lcdidx++] 330 = tft.color565(r,g,b); 331 } // end pixel 332 } // end scanline 333 334 // Write any remaining data to LCD 335 if(lcdidx > 0) { 336 tft.pushColors(lcdbuffer, 337 lcdidx, first); 338 } 339 progmemPrint(PSTR("Loaded in ")); 340 341 Serial.print(millis() - startTime); 342 Serial.println(" ms"); 343 344 } // end goodBmp 345 } 346 } 347 348 bmpFile.close(); 349 if(!goodBmp) 350 progmemPrintln(PSTR("BMP format not recognized.")); 351} 352 353// These read 354 16- and 32-bit types from the SD card file. 355// BMP data is stored little-endian, 356 Arduino is little-endian too. 357// May need to reverse subscript order if porting 358 elsewhere. 359 360uint16_t read16(File f) { 361 uint16_t result; 362 ((uint8_t 363 *)&result)[0] = f.read(); // LSB 364 ((uint8_t *)&result)[1] = f.read(); // MSB 365 366 return result; 367} 368 369uint32_t read32(File f) { 370 uint32_t result; 371 372 ((uint8_t *)&result)[0] = f.read(); // LSB 373 ((uint8_t *)&result)[1] = f.read(); 374 375 ((uint8_t *)&result)[2] = f.read(); 376 ((uint8_t *)&result)[3] = f.read(); // 377 MSB 378 return result; 379} 380 381// Copy string from flash to serial port 382// 383 Source string MUST be inside a PSTR() declaration! 384void progmemPrint(const char 385 *str) { 386 char c; 387 while(c = pgm_read_byte(str++)) Serial.print(c); 388} 389 390// 391 Same as above, with trailing newline 392void progmemPrintln(const char *str) { 393 394 progmemPrint(str); 395 Serial.println(); 396} 397 398
TFT_Shield_SD_1.ino
arduino
1/*This code is to use with 2.4" TFT LCD touch screen shield, it reads bmp images stored on SD card 2 *and shows them on the screen 3 *Refer to SurtrTech.com for more details 4 */ 5 6#include <SPFD5408_Adafruit_GFX.h> // Core graphics library 7#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library 8#include <SPI.h> 9#include <SD.h> 10 11#define LCD_CS A3 // Chip Select goes to Analog 3 12#define LCD_CD A2 // Command/Data goes to Analog 2 13#define LCD_WR A1 // LCD Write goes to Analog 1 14#define LCD_RD A0 // LCD Read goes to Analog 0 15 16#define SD_CS 10 //SD card pin on your shield 17 18Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4); 19 20void setup() 21{ 22 23 Serial.begin(9600); 24 tft.reset(); 25 uint16_t identifier = tft.readID(); 26 pinMode(10, OUTPUT); 27 digitalWrite(10, HIGH); 28 tft.begin(identifier); 29 if (!SD.begin(SD_CS)) { 30 progmemPrintln(PSTR("failed!")); 31 return; 32 } 33 34} 35 36void loop() 37{ 38 bmpDraw("Logo.bmp", 0, 0); //Calling the bmpDraw function ("Name_of_your_image.bmp",x,y) (x,y) is the starting position of the picture drawing 39 delay(2000); 40 bmpDraw("Img2.bmp", 0, 0); 41 delay(2000); 42 bmpDraw("Img3.bmp", 0, 0); 43 delay(2000); 44 45} 46 47 48#define BUFFPIXEL 20 //Drawing speed, 20 is meant to be the best but you can use 60 altough it takes a lot of uno's RAM 49 50//Drawing function, reads the file from the SD card and do the 51//conversion and drawing, also it shows messages on the Serial monitor in case of a problem 52//No touchy to this function :D 53 54void bmpDraw(char *filename, int x, int y) { 55 56 File bmpFile; 57 int bmpWidth, bmpHeight; // W+H in pixels 58 uint8_t bmpDepth; // Bit depth (currently must be 24) 59 uint32_t bmpImageoffset; // Start of image data in file 60 uint32_t rowSize; // Not always = bmpWidth; may have padding 61 uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel) 62 uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel) 63 uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer 64 boolean goodBmp = false; // Set to true on valid header parse 65 boolean flip = true; // BMP is stored bottom-to-top 66 int w, h, row, col; 67 uint8_t r, g, b; 68 uint32_t pos = 0, startTime = millis(); 69 uint8_t lcdidx = 0; 70 boolean first = true; 71 72 if((x >= tft.width()) || (y >= tft.height())) return; 73 74 Serial.println(); 75 progmemPrint(PSTR("Loading image '")); 76 Serial.print(filename); 77 Serial.println('\\''); 78 // Open requested file on SD card 79 if ((bmpFile = SD.open(filename)) == NULL) { 80 progmemPrintln(PSTR("File not found")); 81 return; 82 } 83 84 // Parse BMP header 85 if(read16(bmpFile) == 0x4D42) { // BMP signature 86 progmemPrint(PSTR("File size: ")); Serial.println(read32(bmpFile)); 87 (void)read32(bmpFile); // Read & ignore creator bytes 88 bmpImageoffset = read32(bmpFile); // Start of image data 89 progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, DEC); 90 // Read DIB header 91 progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile)); 92 bmpWidth = read32(bmpFile); 93 bmpHeight = read32(bmpFile); 94 if(read16(bmpFile) == 1) { // # planes -- must be '1' 95 bmpDepth = read16(bmpFile); // bits per pixel 96 progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth); 97 if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 98 99 goodBmp = true; // Supported BMP format -- proceed! 100 progmemPrint(PSTR("Image size: ")); 101 Serial.print(bmpWidth); 102 Serial.print('x'); 103 Serial.println(bmpHeight); 104 105 // BMP rows are padded (if needed) to 4-byte boundary 106 rowSize = (bmpWidth * 3 + 3) & ~3; 107 108 // If bmpHeight is negative, image is in top-down order. 109 // This is not canon but has been observed in the wild. 110 if(bmpHeight < 0) { 111 bmpHeight = -bmpHeight; 112 flip = false; 113 } 114 115 // Crop area to be loaded 116 w = bmpWidth; 117 h = bmpHeight; 118 if((x+w-1) >= tft.width()) w = tft.width() - x; 119 if((y+h-1) >= tft.height()) h = tft.height() - y; 120 121 // Set TFT address window to clipped image bounds 122 tft.setAddrWindow(x, y, x+w-1, y+h-1); 123 124 for (row=0; row<h; row++) { // For each scanline... 125 // Seek to start of scan line. It might seem labor- 126 // intensive to be doing this on every line, but this 127 // method covers a lot of gritty details like cropping 128 // and scanline padding. Also, the seek only takes 129 // place if the file position actually needs to change 130 // (avoids a lot of cluster math in SD library). 131 if(flip) // Bitmap is stored bottom-to-top order (normal BMP) 132 pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; 133 else // Bitmap is stored top-to-bottom 134 pos = bmpImageoffset + row * rowSize; 135 if(bmpFile.position() != pos) { // Need seek? 136 bmpFile.seek(pos); 137 buffidx = sizeof(sdbuffer); // Force buffer reload 138 } 139 140 for (col=0; col<w; col++) { // For each column... 141 // Time to read more pixel data? 142 if (buffidx >= sizeof(sdbuffer)) { // Indeed 143 // Push LCD buffer to the display first 144 if(lcdidx > 0) { 145 tft.pushColors(lcdbuffer, lcdidx, first); 146 lcdidx = 0; 147 first = false; 148 } 149 bmpFile.read(sdbuffer, sizeof(sdbuffer)); 150 buffidx = 0; // Set index to beginning 151 } 152 153 // Convert pixel from BMP to TFT format 154 b = sdbuffer[buffidx++]; 155 g = sdbuffer[buffidx++]; 156 r = sdbuffer[buffidx++]; 157 lcdbuffer[lcdidx++] = tft.color565(r,g,b); 158 } // end pixel 159 } // end scanline 160 // Write any remaining data to LCD 161 if(lcdidx > 0) { 162 tft.pushColors(lcdbuffer, lcdidx, first); 163 } 164 progmemPrint(PSTR("Loaded in ")); 165 Serial.print(millis() - startTime); 166 Serial.println(" ms"); 167 } // end goodBmp 168 } 169 } 170 171 bmpFile.close(); 172 if(!goodBmp) progmemPrintln(PSTR("BMP format not recognized.")); 173} 174 175// These read 16- and 32-bit types from the SD card file. 176// BMP data is stored little-endian, Arduino is little-endian too. 177// May need to reverse subscript order if porting elsewhere. 178 179uint16_t read16(File f) { 180 uint16_t result; 181 ((uint8_t *)&result)[0] = f.read(); // LSB 182 ((uint8_t *)&result)[1] = f.read(); // MSB 183 return result; 184} 185 186uint32_t read32(File f) { 187 uint32_t result; 188 ((uint8_t *)&result)[0] = f.read(); // LSB 189 ((uint8_t *)&result)[1] = f.read(); 190 ((uint8_t *)&result)[2] = f.read(); 191 ((uint8_t *)&result)[3] = f.read(); // MSB 192 return result; 193} 194 195// Copy string from flash to serial port 196// Source string MUST be inside a PSTR() declaration! 197void progmemPrint(const char *str) { 198 char c; 199 while(c = pgm_read_byte(str++)) Serial.print(c); 200} 201 202// Same as above, with trailing newline 203void progmemPrintln(const char *str) { 204 progmemPrint(str); 205 Serial.println(); 206} 207 208
Downloadable files
untitled
It's a shield :D
untitled
untitled
It's a shield :D
untitled
Comments
Only logged in users can leave comments
Anonymous user
2 years ago
for the TFT_Shield_SD_2.ino, will it work with jpeg?
Anonymous user
2 years ago
I try for display bmp image , but at starting when i compile Code_3, there is a error show with word " 'read16' was not declared in the scope". Please help I am new here and sorry for bad english
Anonymous user
2 years ago
Another way to solve it is to do a forward declaration: ```cpp void a(); // Just the signature! void b() { a(); } void a() {} ``` But if you define them before is also OK (And less code!)
Anonymous user
2 years ago
The problem is that the program does not have forward declarations of the functions, and they are being used before declaration. To solve it, just move them above the function that is yielding the error. Eg: ```cpp void a() {} void b(){ a(); } //OK! void b() { a(); } //BAD! void a() {} // <- this should be BEFORE b(){}. ``` And as a side note, well... the libraries work and the signature of the board is OK, but the only thing I see is a blank screen. I've heard that this is a common troubleshooting issue, but can't find a fix for it. Any ideas?
ianchance
3 years ago
what kind of SD card micro or large.
tarbear123
4 years ago
for the TFT_Shield_SD_2.ino, will it work with jpeg?
tarbear123
4 years ago
i want to display gif (from sd card) on a 32x32 led, do i need to convert them into rgb values to get them to display and if so,how do I do it?
Anonymous user
5 years ago
I try for display bmp image , but at starting when i compile Code_3, there is a error show with word " 'read16' was not declared in the scope". Please help I am new here and sorry for bad english
Anonymous user
2 years ago
Another way to solve it is to do a forward declaration: ```cpp void a(); // Just the signature! void b() { a(); } void a() {} ``` But if you define them before is also OK (And less code!)
Anonymous user
2 years ago
The problem is that the program does not have forward declarations of the functions, and they are being used before declaration. To solve it, just move them above the function that is yielding the error. Eg: ```cpp void a() {} void b(){ a(); } //OK! void b() { a(); } //BAD! void a() {} // <- this should be BEFORE b(){}. ``` And as a side note, well... the libraries work and the signature of the board is OK, but the only thing I see is a blank screen. I've heard that this is a common troubleshooting issue, but can't find a fix for it. Any ideas?
SurtrTech
40 Followers
•14 Projects
9
11
Anonymous user
2 years ago
i want to display gif (from sd card) on a 32x32 led, do i need to convert them into rgb values to get them to display and if so,how do I do it?