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