Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
spitftbitmap.ino
Go to the documentation of this file.
1 /***************************************************
2  This is our Bitmap drawing example for the Adafruit ILI9341 Breakout and Shield
3  ----> http://www.adafruit.com/products/1651
4 
5  Check out the links above for our tutorials and wiring diagrams
6  These displays use SPI to communicate, 4 or 5 pins are required to
7  interface (RST is optional)
8  Adafruit invests time and resources providing this open source code,
9  please support Adafruit and open-source hardware by purchasing
10  products from Adafruit!
11 
12  Written by Limor Fried/Ladyada for Adafruit Industries.
13  MIT license, all text above must be included in any redistribution
14  ****************************************************/
15 
16 
17 #include <Adafruit_GFX.h> // Core graphics library
18 #include "Adafruit_ILI9341.h" // Hardware-specific library
19 #include <SPI.h>
20 #include <SD.h>
21 
22 // TFT display and SD card will share the hardware SPI interface.
23 // Hardware SPI pins are specific to the Arduino board type and
24 // cannot be remapped to alternate pins. For Arduino Uno,
25 // Duemilanove, etc., pin 11 = MOSI, pin 12 = MISO, pin 13 = SCK.
26 
27 #define TFT_DC 9
28 #define TFT_CS 10
30 
31 #define SD_CS 4
32 
33 void setup(void)
34 {
35  Serial.begin(9600);
36 
37  tft.begin();
39 
40  yield();
41 
42  Serial.print("Initializing SD card...");
43  if (!SD.begin(SD_CS))
44  {
45  Serial.println("failed!");
46  }
47  Serial.println("OK!");
48 
49  bmpDraw("purple.bmp", 0, 0);
50 }
51 
52 void loop()
53 {
54 }
55 
56 // This function opens a Windows Bitmap (BMP) file and
57 // displays it at the given coordinates. It's sped up
58 // by reading many pixels worth of data at a time
59 // (rather than pixel by pixel). Increasing the buffer
60 // size takes more of the Arduino's precious RAM but
61 // makes loading a little faster. 20 pixels seems a
62 // good balance.
63 
64 #define BUFFPIXEL 20
65 
66 void bmpDraw(char *filename, uint8_t x, uint16_t y)
67 {
68 
69  File bmpFile;
70  int bmpWidth, bmpHeight; // W+H in pixels
71  uint8_t bmpDepth; // Bit depth (currently must be 24)
72  uint32_t bmpImageoffset; // Start of image data in file
73  uint32_t rowSize; // Not always = bmpWidth; may have padding
74  uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
75  uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
76  boolean goodBmp = false; // Set to true on valid header parse
77  boolean flip = true; // BMP is stored bottom-to-top
78  int w, h, row, col;
79  uint8_t r, g, b;
80  uint32_t pos = 0, startTime = millis();
81 
82  if ((x >= tft.width()) || (y >= tft.height())) return;
83 
84  Serial.println();
85  Serial.print(F("Loading image '"));
86  Serial.print(filename);
87  Serial.println('\'');
88 
89  // Open requested file on SD card
90  if ((bmpFile = SD.open(filename)) == NULL)
91  {
92  Serial.print(F("File not found"));
93  return;
94  }
95 
96  // Parse BMP header
97  if (read16(bmpFile) == 0x4D42) // BMP signature
98  {
99  Serial.print(F("File size: "));
100  Serial.println(read32(bmpFile));
101  (void)read32(bmpFile); // Read & ignore creator bytes
102  bmpImageoffset = read32(bmpFile); // Start of image data
103  Serial.print(F("Image Offset: "));
104  Serial.println(bmpImageoffset, DEC);
105  // Read DIB header
106  Serial.print(F("Header size: "));
107  Serial.println(read32(bmpFile));
108  bmpWidth = read32(bmpFile);
109  bmpHeight = read32(bmpFile);
110  if (read16(bmpFile) == 1) // # planes -- must be '1'
111  {
112  bmpDepth = read16(bmpFile); // bits per pixel
113  Serial.print(F("Bit Depth: "));
114  Serial.println(bmpDepth);
115  if ((bmpDepth == 24) && (read32(bmpFile) == 0)) // 0 = uncompressed
116  {
117 
118  goodBmp = true; // Supported BMP format -- proceed!
119  Serial.print(F("Image size: "));
120  Serial.print(bmpWidth);
121  Serial.print('x');
122  Serial.println(bmpHeight);
123 
124  // BMP rows are padded (if needed) to 4-byte boundary
125  rowSize = (bmpWidth * 3 + 3) & ~3;
126 
127  // If bmpHeight is negative, image is in top-down order.
128  // This is not canon but has been observed in the wild.
129  if (bmpHeight < 0)
130  {
131  bmpHeight = -bmpHeight;
132  flip = false;
133  }
134 
135  // Crop area to be loaded
136  w = bmpWidth;
137  h = bmpHeight;
138  if ((x+w-1) >= tft.width()) w = tft.width() - x;
139  if ((y+h-1) >= tft.height()) h = tft.height() - y;
140 
141  // Set TFT address window to clipped image bounds
142  tft.setAddrWindow(x, y, x+w-1, y+h-1);
143 
144  for (row=0; row<h; row++) // For each scanline...
145  {
146 
147  // Seek to start of scan line. It might seem labor-
148  // intensive to be doing this on every line, but this
149  // method covers a lot of gritty details like cropping
150  // and scanline padding. Also, the seek only takes
151  // place if the file position actually needs to change
152  // (avoids a lot of cluster math in SD library).
153  if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
154  pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
155  else // Bitmap is stored top-to-bottom
156  pos = bmpImageoffset + row * rowSize;
157  if (bmpFile.position() != pos) // Need seek?
158  {
159  bmpFile.seek(pos);
160  buffidx = sizeof(sdbuffer); // Force buffer reload
161  }
162 
163  for (col=0; col<w; col++) // For each pixel...
164  {
165  // Time to read more pixel data?
166  if (buffidx >= sizeof(sdbuffer)) // Indeed
167  {
168  bmpFile.read(sdbuffer, sizeof(sdbuffer));
169  buffidx = 0; // Set index to beginning
170  }
171 
172  // Convert pixel from BMP to TFT format, push to display
173  b = sdbuffer[buffidx++];
174  g = sdbuffer[buffidx++];
175  r = sdbuffer[buffidx++];
176  tft.pushColor(tft.color565(r,g,b));
177  } // end pixel
178  } // end scanline
179  Serial.print(F("Loaded in "));
180  Serial.print(millis() - startTime);
181  Serial.println(" ms");
182  } // end goodBmp
183  }
184  }
185 
186  bmpFile.close();
187  if (!goodBmp) Serial.println(F("BMP format not recognized."));
188 }
189 
190 // These read 16- and 32-bit types from the SD card file.
191 // BMP data is stored little-endian, Arduino is little-endian too.
192 // May need to reverse subscript order if porting elsewhere.
193 
194 uint16_t read16(File &f)
195 {
196  uint16_t result;
197  ((uint8_t *)&result)[0] = f.read(); // LSB
198  ((uint8_t *)&result)[1] = f.read(); // MSB
199  return result;
200 }
201 
202 uint32_t read32(File &f)
203 {
204  uint32_t result;
205  ((uint8_t *)&result)[0] = f.read(); // LSB
206  ((uint8_t *)&result)[1] = f.read();
207  ((uint8_t *)&result)[2] = f.read();
208  ((uint8_t *)&result)[3] = f.read(); // MSB
209  return result;
210 }
static uint16_t read16(File &f)
int16_t height(void) const
void pushColor(uint16_t color)
uint16_t color565(uint8_t r, uint8_t g, uint8_t b)
#define BUFFPIXEL
int16_t width(void) const
#define TFT_DC
static int16_t pos
static void bmpDraw(char *filename, uint8_t x, uint16_t y)
static void loop()
#define SD_CS
#define TFT_CS
static void setup(void)
#define ILI9341_BLUE
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
void fillScreen(uint16_t color)
Adafruit_ILI9341 tft
static uint32_t read32(File &f)