mirror of
				https://github.com/esp8266/Arduino.git
				synced 2025-10-30 04:26:50 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			328 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|   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 <SD.h>
 | |
| #include <SPI.h>
 | |
| #include <Streaming.h>
 | |
| 
 | |
| #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;
 | |
| }
 |