@@ -29,30 +29,215 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
29
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
*/
31
31
32
- #ifndef _ARDUINO_TFT_H
33
- #define _ARDUINO_TFT_H
32
+ #ifndef _ARDUINO_LCD_SCREEN_H
33
+ #define _ARDUINO_LCD_SCREEN_H
34
34
35
- #include " Arduino.h"
36
- #include " utility/ Adafruit_GFX.h"
37
- #include " utility/Adafruit_ST7735 .h"
35
+ #include < Arduino.h>
36
+ #include < Adafruit_GFX.h>
37
+ #include " utility/Arduino_ILI9163 .h"
38
38
39
- // / The Arduino LCD is a ST7735-based device.
39
+ /*
40
+ * This library can work with or without the presence of an SD
41
+ * reading library (to load images). At the moment, only the
42
+ * Arduino SD library is supported; it is included in
43
+ * standard Arduino libraries.
44
+ *
45
+ * The presence of the SD library is detected by looking at the
46
+ * __SD_H__ preprocessor variable, defined into
47
+ * Arduino SD library to avoid double inclusion. This means
48
+ * that in order to use the image-related API of Adafruit_GFX,
49
+ * SD.h *must* be included before Adafruit_GFX.
50
+ *
51
+ * The bottom part of this include file contains the actual image
52
+ * loading code; if it was in a separate .cpp file, there were no
53
+ * way to check if the SD library was present or not.
54
+ *
55
+ * A partial solution was to include SD.h anyway, see if that works
56
+ * (i.e. it is found in the include search path) and act accordingly.
57
+ * But this solution relied on the preprocessor to issue only a
58
+ * warning when an include file is not found. Avr-gcc, used for
59
+ * Arduino 8-bit MCUs, does that, but the standard gcc-4.4, used for
60
+ * Arduino Due, issues a fatal error and stops compilation.
61
+ *
62
+ * The best solution so far is to put the code here. It works if this
63
+ * include is used only in one .cpp file in the build (this is the
64
+ * case of most Arduino sketches); if used in multiple .cpp files,
65
+ * the linker may complain about duplicate definitions.
66
+ *
67
+ */
68
+
69
+ #if defined(__SD_H__) // Arduino SD library
70
+ #include " utility/PImage.h"
71
+ #else
72
+ #warning "The SD library was not found. loadImage() and image() won't be supported."
73
+ #endif
74
+
75
+ // / The Arduino LCD is a ILI9163-based device.
40
76
// / By default, it is mounted horizontally.
41
- // / TFT class follows the convention of other
77
+ // / LcdScreen class follows the convention of other
42
78
// / Arduino library classes by adding a begin() method
43
79
// / to be called in the setup() routine.
44
80
// / @author Enrico Gueli <[email protected] >
45
- class TFT : public Adafruit_ST7735 {
81
+ class LcdScreen : public Arduino_ILI9163 {
46
82
public:
47
- TFT (uint8_t CS, uint8_t RS, uint8_t RST);
83
+ LcdScreen (uint8_t CS, uint8_t RS, uint8_t RST);
48
84
49
85
void begin ();
86
+
87
+ #if defined(__SD_H__) // Arduino SD library
88
+ PImage loadImage (const char * fileName) { return PImage::loadImage (fileName); }
89
+
90
+ void image (PImage & img, uint16_t x, uint16_t y);
91
+ #endif
50
92
};
51
93
52
94
// / Esplora boards have hard-wired connections with
53
95
// / the Arduino LCD if mounted on the onboard connector.
54
96
#if ARDUINO_AVR_ESPLORA // are we building for Esplora?
55
- extern TFT EsploraTFT;
97
+ extern LcdScreen EsploraTFT;
56
98
#endif
57
99
58
- #endif // _ARDUINO_TFT_H
100
+ #if defined(__SD_H__) // Arduino SD library
101
+
102
+ #define BUFFPIXEL 20
103
+
104
+ void LcdScreen::image (PImage & img, uint16_t x, uint16_t y) {
105
+ int w, h, row, col;
106
+ uint8_t r, g, b;
107
+ uint32_t pos = 0 ;
108
+ uint8_t sdbuffer[3 *BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
109
+ uint8_t buffidx = sizeof (sdbuffer); // Current position in sdbuffer
110
+
111
+ // Crop area to be loaded
112
+ w = img._bmpWidth ;
113
+ h = img._bmpHeight ;
114
+ if ((x+w-1 ) >= width ()) w = width () - x;
115
+ if ((y+h-1 ) >= height ()) h = height () - y;
116
+
117
+ // // Set TFT address window to clipped image bounds
118
+ // setAddrWindow(x, y, x+w-1, y+h-1);
119
+
120
+ for (row=0 ; row<h; row++) { // For each scanline...
121
+ // Seek to start of scan line. It might seem labor-
122
+ // intensive to be doing this on every line, but this
123
+ // method covers a lot of gritty details like cropping
124
+ // and scanline padding. Also, the seek only takes
125
+ // place if the file position actually needs to change
126
+ // (avoids a lot of cluster math in SD library).
127
+ if (img._flip ) // Bitmap is stored bottom-to-top order (normal BMP)
128
+ pos = img._bmpImageoffset + (img._bmpHeight - 1 - row) * img._rowSize ;
129
+ else // Bitmap is stored top-to-bottom
130
+ pos = img._bmpImageoffset + row * img._rowSize ;
131
+ if (img._bmpFile .position () != pos) { // Need seek?
132
+ img._bmpFile .seek (pos);
133
+ buffidx = sizeof (sdbuffer); // Force buffer reload
134
+ }
135
+
136
+ for (col=0 ; col<w; col++) { // For each pixel...
137
+ // Time to read more pixel data?
138
+ if (buffidx >= sizeof (sdbuffer)) { // Indeed
139
+ img._bmpFile .read (sdbuffer, sizeof (sdbuffer));
140
+ buffidx = 0 ; // Set index to beginning
141
+ }
142
+
143
+ // Convert pixel from BMP to TFT format, push to display
144
+ b = sdbuffer[buffidx++];
145
+ g = sdbuffer[buffidx++];
146
+ r = sdbuffer[buffidx++];
147
+ // pushColor(tft.Color565(r,g,b));
148
+ drawPixel (x + col, y + row, Color565 (r, g, b));
149
+
150
+ } // end pixel
151
+ } // end scanline
152
+
153
+ }
154
+
155
+
156
+
157
+
158
+ // These read 16- and 32-bit types from the SD card file.
159
+ // BMP data is stored little-endian, Arduino is little-endian too.
160
+ // May need to reverse subscript order if porting elsewhere.
161
+
162
+ uint16_t PImage::read16 (File f) {
163
+ uint16_t result;
164
+ ((uint8_t *)&result)[0 ] = f.read (); // LSB
165
+ ((uint8_t *)&result)[1 ] = f.read (); // MSB
166
+ return result;
167
+ }
168
+
169
+ uint32_t PImage::read32 (File f) {
170
+ uint32_t result;
171
+ ((uint8_t *)&result)[0 ] = f.read (); // LSB
172
+ ((uint8_t *)&result)[1 ] = f.read ();
173
+ ((uint8_t *)&result)[2 ] = f.read ();
174
+ ((uint8_t *)&result)[3 ] = f.read (); // MSB
175
+ return result;
176
+ }
177
+
178
+
179
+ PImage PImage::loadImage (const char * fileName) {
180
+ File bmpFile;
181
+ int bmpWidth, bmpHeight; // W+H in pixels
182
+ uint8_t bmpDepth; // Bit depth (currently must be 24)
183
+ uint32_t bmpImageoffset; // Start of image data in file
184
+ uint32_t rowSize; // Not always = bmpWidth; may have padding
185
+ bool flip = true ; // BMP is stored bottom-to-top
186
+
187
+
188
+ // Open requested file on SD card
189
+ if ((bmpFile = SD.open (fileName)) == NULL ) {
190
+ Serial.print (F (" loadImage: file not found: " ));
191
+ Serial.println (fileName);
192
+ return PImage (); // load error
193
+ }
194
+
195
+
196
+
197
+ // Parse BMP header
198
+ if (read16 (bmpFile) != 0x4D42 ) { // BMP signature
199
+ Serial.println (F (" loadImage: file doesn't look like a BMP" ));
200
+ return PImage ();
201
+ }
202
+
203
+ Serial.print (F (" File size: " )); Serial.println (read32 (bmpFile));
204
+ (void )read32 (bmpFile); // Read & ignore creator bytes
205
+ bmpImageoffset = read32 (bmpFile); // Start of image data
206
+ Serial.print (F (" Image Offset: " )); Serial.println (bmpImageoffset, DEC);
207
+ // Read DIB header
208
+ Serial.print (F (" Header size: " )); Serial.println (read32 (bmpFile));
209
+ bmpWidth = read32 (bmpFile);
210
+ bmpHeight = read32 (bmpFile);
211
+ if (read16 (bmpFile) != 1 ) { // # planes -- must be '1'
212
+ Serial.println (F (" loadImage: invalid n. of planes" ));
213
+ return PImage ();
214
+ }
215
+
216
+ bmpDepth = read16 (bmpFile); // bits per pixel
217
+ Serial.print (F (" Bit Depth: " )); Serial.println (bmpDepth);
218
+ if ((bmpDepth != 24 ) || (read32 (bmpFile) != 0 )) { // 0 = uncompressed {
219
+ Serial.println (F (" loadImage: invalid pixel format" ));
220
+ return PImage ();
221
+ }
222
+
223
+ Serial.print (F (" Image size: " ));
224
+ Serial.print (bmpWidth);
225
+ Serial.print (' x' );
226
+ Serial.println (bmpHeight);
227
+
228
+ // BMP rows are padded (if needed) to 4-byte boundary
229
+ rowSize = (bmpWidth * 3 + 3 ) & ~3 ;
230
+
231
+ // If bmpHeight is negative, image is in top-down order.
232
+ // This is not canon but has been observed in the wild.
233
+ if (bmpHeight < 0 ) {
234
+ bmpHeight = -bmpHeight;
235
+ flip = false ;
236
+ }
237
+
238
+ return PImage (bmpFile, bmpWidth, bmpHeight, bmpDepth, bmpImageoffset, rowSize, flip);
239
+ }
240
+
241
+ #endif // __SD_H__
242
+
243
+ #endif // _ARDUINO_LCD_SCREEN_H
0 commit comments