/* TFT Touch Shield 2.0 examples - tftbmp2 loovee 2013-1-21 this demo can show all bmp file in root Directory of SD card please ensure that your image file is 320x240 size. MAX_BMP can config the max file to display FILENAME_LEN can config the max length of file name */ #include #include #include #include "TFTv2.h" #define MAX_BMP 10 // bmp file num #define FILENAME_LEN 20 // max file name length const int PIN_SD_CS = 4; // pin of sd card const long __Gnbmp_height = 320; // bmp hight const long __Gnbmp_width = 240; // bmp width long __Gnbmp_image_offset = 0;; int __Gnfile_num = 0; // num of file char __Gsbmp_files[MAX_BMP][FILENAME_LEN]; // file name File bmpFile; // if bmp file return 1, else return 0 bool checkBMP(char *_name, char r_name[]) { int len = 0; if (NULL == _name) { return false; } while (*_name) { r_name[len++] = *(_name++); if (len > FILENAME_LEN) { return false; } } r_name[len] = '\0'; if (len < 5) { return false; } // if xxx.bmp or xxx.BMP if (r_name[len - 4] == '.' \ && (r_name[len - 3] == 'b' || (r_name[len - 3] == 'B')) \ && (r_name[len - 2] == 'm' || (r_name[len - 2] == 'M')) \ && (r_name[len - 1] == 'p' || (r_name[len - 1] == 'P'))) { return true; } return false; } // search root to find bmp file void searchDirectory() { File root = SD.open("/"); // root while (true) { File entry = root.openNextFile(); if (! entry) { break; } if (!entry.isDirectory()) { char *ptmp = entry.name(); char __Name[20]; if (checkBMP(ptmp, __Name)) { Serial.println(__Name); strcpy(__Gsbmp_files[__Gnfile_num++], __Name); } } entry.close(); } Serial.print("get "); Serial.print(__Gnfile_num); Serial.println(" file: "); for (int i = 0; i < __Gnfile_num; i++) { Serial.println(__Gsbmp_files[i]); } } void setup() { Serial.begin(115200); pinMode(PIN_SD_CS, OUTPUT); digitalWrite(PIN_SD_CS, HIGH); Tft.TFTinit(); Sd2Card card; card.init(SPI_FULL_SPEED, PIN_SD_CS); if (!SD.begin(PIN_SD_CS)) { Serial.println("failed!"); while (1); // init fail, die here } Serial.println("SD OK!"); searchDirectory(); TFT_BL_ON; } void loop() { /* static int dirCtrl = 0; for(unsigned char i=0; i<__Gnfile_num; i++) { bmpFile = SD.open(__Gsbmp_files[i]); if (! bmpFile) { Serial.println("didnt find image"); while (1); } if(! bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } dirCtrl = 1-dirCtrl; bmpdraw(bmpFile, 0, 0, dirCtrl); bmpFile.close(); delay(1000); } */ bmpFile = SD.open("pfvm_1.bmp"); if (! bmpFile) { Serial.println("didnt find image"); while (1); } if (! bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } bmpdraw(bmpFile, 0, 0, 1); bmpFile.close(); while (1); } /*********************************************/ // This procedure reads a bitmap and draws it to the screen // its sped up by reading many pixels worth of data at a time // instead of just one pixel at a time. increading the buffer takes // more RAM but makes the drawing a little faster. 20 pixels' worth // is probably a good place #define BUFFPIXEL 60 // must be a divisor of 240 #define BUFFPIXEL_X3 180 // BUFFPIXELx3 #define UP_DOWN 1 #define DOWN_UP 0 // dir - 1: up to down // dir - 2: down to up void bmpdraw(File f, int x, int y, int dir) { if (bmpFile.seek(__Gnbmp_image_offset)) { Serial.print("pos = "); Serial.println(bmpFile.position()); } uint32_t time = millis(); uint8_t sdbuffer[BUFFPIXEL_X3]; // 3 * pixels to buffer for (int i = 0; i < __Gnbmp_height; i++) { if (dir) { bmpFile.seek(__Gnbmp_image_offset + (__Gnbmp_height - 1 - i) * 240 * 3); } for (int j = 0; j < (240 / BUFFPIXEL); j++) { bmpFile.read(sdbuffer, BUFFPIXEL_X3); uint8_t buffidx = 0; int offset_x = j * BUFFPIXEL; unsigned int __color[BUFFPIXEL]; for (int k = 0; k < BUFFPIXEL; k++) { __color[k] = sdbuffer[buffidx + 2] >> 3; // read __color[k] = __color[k] << 6 | (sdbuffer[buffidx + 1] >> 2); // green __color[k] = __color[k] << 5 | (sdbuffer[buffidx + 0] >> 3); // blue buffidx += 3; } Tft.setCol(offset_x, offset_x + BUFFPIXEL); if (dir) { Tft.setPage(i, i); } else { Tft.setPage(__Gnbmp_height - i - 1, __Gnbmp_height - i - 1); } Tft.sendCMD(0x2c); TFT_DC_HIGH; TFT_CS_LOW; for (int m = 0; m < BUFFPIXEL; m++) { SPI.transfer(__color[m] >> 8); SPI.transfer(__color[m]); delay(10); } TFT_CS_HIGH; } } Serial.print(millis() - time, DEC); Serial.println(" ms"); } boolean bmpReadHeader(File f) { // read header uint32_t tmp; uint8_t bmpDepth; if (read16(f) != 0x4D42) { // magic bytes missing return false; } // read file size tmp = read32(f); Serial.print("size 0x"); Serial.println(tmp, HEX); // read and ignore creator bytes read32(f); __Gnbmp_image_offset = read32(f); Serial.print("offset "); Serial.println(__Gnbmp_image_offset, DEC); // read DIB header tmp = read32(f); Serial.print("header size "); Serial.println(tmp, DEC); int bmp_width = read32(f); int bmp_height = read32(f); if (bmp_width != __Gnbmp_width || bmp_height != __Gnbmp_height) { // if image is not 320x240, return false return false; } if (read16(f) != 1) { return false; } bmpDepth = read16(f); Serial.print("bitdepth "); Serial.println(bmpDepth, DEC); if (read32(f) != 0) { // compression not supported! return false; } Serial.print("compression "); Serial.println(tmp, DEC); return true; } /*********************************************/ // These read data from the SD card file and convert them to big endian // (the data is stored in little endian format!) // LITTLE ENDIAN! uint16_t read16(File f) { uint16_t d; uint8_t b; b = f.read(); d = f.read(); d <<= 8; d |= b; return d; } // LITTLE ENDIAN! uint32_t read32(File f) { uint32_t d; uint16_t b; b = read16(f); d = read16(f); d <<= 16; d |= b; return d; }