Shows how to use a display, the onboard SD Card and the onboard SPI Flash. Requires a display module with direct Arduino pinning

Dependencies:   DmTftLibrary SDFileSystem mbed

Committer:
displaymodule
Date:
Wed Jul 09 09:38:56 2014 +0000
Revision:
4:93ca338876e2
Parent:
3:e1e1053e286f
Updated library dependencies. Fixed warning. Fixed file position bug.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
displaymodule 0:3ecd25651727 1 /**********************************************************************************************
displaymodule 0:3ecd25651727 2 Copyright (c) 2014 DisplayModule. All rights reserved.
displaymodule 0:3ecd25651727 3
displaymodule 0:3ecd25651727 4 Redistribution and use of this source code, part of this source code or any compiled binary
displaymodule 0:3ecd25651727 5 based on this source code is permitted as long as the above copyright notice and following
displaymodule 0:3ecd25651727 6 disclaimer is retained.
displaymodule 0:3ecd25651727 7
displaymodule 0:3ecd25651727 8 DISCLAIMER:
displaymodule 0:3ecd25651727 9 THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES
displaymodule 0:3ecd25651727 10 NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE.
displaymodule 0:3ecd25651727 11 ********************************************************************************************/
displaymodule 0:3ecd25651727 12
displaymodule 0:3ecd25651727 13 #include "DmDrawBmpBase.h"
displaymodule 0:3ecd25651727 14
displaymodule 0:3ecd25651727 15 bool DmDrawBmpBase::drawBitmap(DmTftBase& tft, uint16_t x, uint16_t y, readFunc func, uint32_t userData) {
displaymodule 0:3ecd25651727 16 _readFunc = func;
displaymodule 0:3ecd25651727 17 _userData = userData;
displaymodule 0:3ecd25651727 18 _readPos = 0;
displaymodule 0:3ecd25651727 19
displaymodule 0:3ecd25651727 20 if (readBmpHeader()) {
displaymodule 0:3ecd25651727 21 if (IsValid565Bitmap()) {
displaymodule 0:3ecd25651727 22 return draw565Bitmap(tft, x, y);
displaymodule 0:3ecd25651727 23 }
displaymodule 0:3ecd25651727 24 if (IsValid888Bitmap()) {
displaymodule 0:3ecd25651727 25 return draw888Bitmap(tft, x, y);
displaymodule 0:3ecd25651727 26 }
displaymodule 0:3ecd25651727 27 }
displaymodule 0:3ecd25651727 28 return false;
displaymodule 0:3ecd25651727 29 }
displaymodule 0:3ecd25651727 30
displaymodule 0:3ecd25651727 31 bool DmDrawBmpBase::draw888Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) {
displaymodule 0:3ecd25651727 32 const uint8_t bytesPerPixel = 3;
displaymodule 0:3ecd25651727 33 uint8_t red, green, blue;
displaymodule 0:3ecd25651727 34 uint16_t row, column;
displaymodule 0:3ecd25651727 35 uint16_t bytesPerRow = (bytesPerPixel*_width + 3) & ~3;
displaymodule 0:3ecd25651727 36 uint8_t buff[20*bytesPerPixel];
displaymodule 0:3ecd25651727 37 uint8_t buffPos = sizeof(buff);
displaymodule 3:e1e1053e286f 38 uint16_t clipX = _width;
displaymodule 3:e1e1053e286f 39 uint16_t clipY = _height;
displaymodule 3:e1e1053e286f 40
displaymodule 3:e1e1053e286f 41 //make sure image fits
displaymodule 3:e1e1053e286f 42 if ((x + clipX) > tft.width()) {
displaymodule 3:e1e1053e286f 43 clipX = tft.width() - x;
displaymodule 3:e1e1053e286f 44 }
displaymodule 3:e1e1053e286f 45 if ((y + clipY) > tft.height()) {
displaymodule 3:e1e1053e286f 46 clipY = tft.height() - y;
displaymodule 3:e1e1053e286f 47 }
displaymodule 3:e1e1053e286f 48
displaymodule 0:3ecd25651727 49 tft.select();
displaymodule 3:e1e1053e286f 50 tft.setAddress(x, y, x+clipX-1, y+clipY-1);
displaymodule 0:3ecd25651727 51 tft.unSelect();
displaymodule 0:3ecd25651727 52
displaymodule 0:3ecd25651727 53 for(row=0; row<_height; row++) {
displaymodule 3:e1e1053e286f 54 _readPos = _bitmapOffset + (_height - 1 -row ) * bytesPerRow;
displaymodule 0:3ecd25651727 55 buffPos = sizeof(buff);
displaymodule 0:3ecd25651727 56
displaymodule 0:3ecd25651727 57 for(column=0; column<_width; column++) {
displaymodule 0:3ecd25651727 58 if (buffPos >= sizeof(buff)) {
displaymodule 0:3ecd25651727 59 tft.unSelect();
displaymodule 0:3ecd25651727 60 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:3ecd25651727 61 _readPos += sizeof(buff);
displaymodule 0:3ecd25651727 62 tft.select();
displaymodule 0:3ecd25651727 63 buffPos = 0;
displaymodule 0:3ecd25651727 64 }
displaymodule 0:3ecd25651727 65
displaymodule 0:3ecd25651727 66 blue = buff[buffPos++];
displaymodule 0:3ecd25651727 67 green = buff[buffPos++];
displaymodule 0:3ecd25651727 68 red = buff[buffPos++];
displaymodule 0:3ecd25651727 69
displaymodule 3:e1e1053e286f 70 if (row < clipY && column < clipX) {
displaymodule 3:e1e1053e286f 71 tft.sendData(Convert888to565(red, green, blue));
displaymodule 3:e1e1053e286f 72 }
displaymodule 0:3ecd25651727 73 }
displaymodule 0:3ecd25651727 74 }
displaymodule 0:3ecd25651727 75 tft.unSelect();
displaymodule 0:3ecd25651727 76 return true;
displaymodule 0:3ecd25651727 77 }
displaymodule 0:3ecd25651727 78
displaymodule 0:3ecd25651727 79 bool DmDrawBmpBase::draw565Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) {
displaymodule 0:3ecd25651727 80 const uint8_t bytesPerPixel = 2;
displaymodule 0:3ecd25651727 81 uint8_t buff[30*bytesPerPixel]; // Should be dividable by bytesPerPixel
displaymodule 0:3ecd25651727 82 uint8_t buffPos = sizeof(buff);
displaymodule 0:3ecd25651727 83 uint16_t bytesPerRow = (bytesPerPixel * _width + 3) & ~3; // bytes Per Row including padding to 4 bytes boundary
displaymodule 0:3ecd25651727 84 uint16_t paddingSize = bytesPerRow - (bytesPerPixel * _width); // paddingSize for each row
displaymodule 0:3ecd25651727 85 uint16_t height = -_height; // Change if load bottom-top
displaymodule 0:3ecd25651727 86 uint16_t pixel;
displaymodule 0:3ecd25651727 87 uint16_t row, column;
displaymodule 3:e1e1053e286f 88 uint16_t clipX = _width;
displaymodule 3:e1e1053e286f 89 uint16_t clipY = height;
displaymodule 0:3ecd25651727 90 _readPos = _bitmapOffset;
displaymodule 0:3ecd25651727 91
displaymodule 0:3ecd25651727 92 //_imageFile.seek(_bitmapOffset);
displaymodule 0:3ecd25651727 93
displaymodule 3:e1e1053e286f 94 //make sure image fits
displaymodule 3:e1e1053e286f 95 if ((x + clipX) > tft.width()) {
displaymodule 3:e1e1053e286f 96 clipX = tft.width() - x;
displaymodule 3:e1e1053e286f 97 }
displaymodule 3:e1e1053e286f 98 if ((y + clipY) > tft.height()) {
displaymodule 3:e1e1053e286f 99 clipY = tft.height() - y;
displaymodule 3:e1e1053e286f 100 }
displaymodule 3:e1e1053e286f 101
displaymodule 0:3ecd25651727 102 tft.select();
displaymodule 3:e1e1053e286f 103 tft.setAddress(x, y, x+clipX-1, y+clipY-1);
displaymodule 0:3ecd25651727 104 tft.unSelect();
displaymodule 0:3ecd25651727 105
displaymodule 0:3ecd25651727 106 for(row=0; row<height; row++) {
displaymodule 0:3ecd25651727 107 for(column=0; column<_width; column++) {
displaymodule 0:3ecd25651727 108 if (buffPos >= sizeof(buff)) {
displaymodule 0:3ecd25651727 109 tft.unSelect();
displaymodule 0:3ecd25651727 110 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:3ecd25651727 111 _readPos += sizeof(buff);
displaymodule 0:3ecd25651727 112 //_imageFile.read(buff, sizeof(buff));
displaymodule 0:3ecd25651727 113 tft.select();
displaymodule 0:3ecd25651727 114 buffPos = 0;
displaymodule 0:3ecd25651727 115 }
displaymodule 0:3ecd25651727 116 pixel = buff[buffPos++] & 0xFF;
displaymodule 0:3ecd25651727 117 pixel |= buff[buffPos++] << 8;
displaymodule 3:e1e1053e286f 118 if (row < clipY && column < clipX) {
displaymodule 3:e1e1053e286f 119 tft.sendData(pixel);
displaymodule 3:e1e1053e286f 120 }
displaymodule 0:3ecd25651727 121 }
displaymodule 0:3ecd25651727 122
displaymodule 0:3ecd25651727 123 if ( paddingSize > 0 ) { // Check if there is padding in the file
displaymodule 0:3ecd25651727 124 if ((sizeof(buff) - buffPos) >= paddingSize) { // Most common case, the padding is in the buffer
displaymodule 0:3ecd25651727 125 buffPos += paddingSize;
displaymodule 0:3ecd25651727 126 }
displaymodule 0:3ecd25651727 127 else { // Padding is not in the buffer, we have to load the buffer from file
displaymodule 0:3ecd25651727 128 tft.unSelect();
displaymodule 0:3ecd25651727 129 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:3ecd25651727 130 _readPos += sizeof(buff);
displaymodule 0:3ecd25651727 131 // _imageFile.read(buff, sizeof(buff));
displaymodule 0:3ecd25651727 132 tft.select();
displaymodule 0:3ecd25651727 133 buffPos = paddingSize-(sizeof(buff) - buffPos); // paddingSize (0-3) spaceLeftInBuffer (0-3) where spaceLeftInBuffer < paddingSize
displaymodule 0:3ecd25651727 134 }
displaymodule 0:3ecd25651727 135 }
displaymodule 0:3ecd25651727 136 }
displaymodule 0:3ecd25651727 137 tft.unSelect();
displaymodule 0:3ecd25651727 138
displaymodule 0:3ecd25651727 139 return true;
displaymodule 0:3ecd25651727 140 }
displaymodule 0:3ecd25651727 141
displaymodule 0:3ecd25651727 142 void DmDrawBmpBase::printBmpHeaderInfo() {
displaymodule 0:3ecd25651727 143 printf("Image size: %d\n", _fileSize);
displaymodule 0:3ecd25651727 144 printf("Image offset: %d\n", _bitmapOffset);
displaymodule 0:3ecd25651727 145 printf("Image size: %d, %d\n", _width, _height);
displaymodule 0:3ecd25651727 146 printf("BitsPerPixel: %d\n",_bitsPerPixel);
displaymodule 0:3ecd25651727 147 printf("Compression: %d\n",_compression);
displaymodule 0:3ecd25651727 148 printf("Is 24-bit bmp: %d\n", IsValid888Bitmap());
displaymodule 0:3ecd25651727 149 printf("Is 16-bit 565 bmp: %d\n", IsValid565Bitmap());
displaymodule 0:3ecd25651727 150 printf("Has 565 color mask: %d\n", Is565ColorMask());
displaymodule 0:3ecd25651727 151 }
displaymodule 0:3ecd25651727 152
displaymodule 0:3ecd25651727 153 bool DmDrawBmpBase::readBmpHeader() {
displaymodule 0:3ecd25651727 154 if (read16() !=0x4D42){ // read magic byte
displaymodule 0:3ecd25651727 155 return false;
displaymodule 0:3ecd25651727 156 }
displaymodule 0:3ecd25651727 157
displaymodule 0:3ecd25651727 158 _fileSize = read32();
displaymodule 0:3ecd25651727 159 read32(); // Value depends on application which created the image
displaymodule 0:3ecd25651727 160 _bitmapOffset = read32();
displaymodule 0:3ecd25651727 161
displaymodule 0:3ecd25651727 162 // read DIB header
displaymodule 0:3ecd25651727 163 _headerSize = read32();
displaymodule 0:3ecd25651727 164 _width = readInt32();
displaymodule 0:3ecd25651727 165 _height = readInt32();
displaymodule 0:3ecd25651727 166
displaymodule 0:3ecd25651727 167 if (read16() != 1) { // number of color planes must be 1
displaymodule 0:3ecd25651727 168 return false;
displaymodule 0:3ecd25651727 169 }
displaymodule 0:3ecd25651727 170
displaymodule 0:3ecd25651727 171 _bitsPerPixel = read16();
displaymodule 0:3ecd25651727 172 _compression = read32();
displaymodule 0:3ecd25651727 173
displaymodule 0:3ecd25651727 174 if (_bitmapOffset == 66 || _bitmapOffset == 70) { // V3 or v2 format
displaymodule 0:3ecd25651727 175 //setPosition(54);
displaymodule 0:3ecd25651727 176 _readPos = 54;
displaymodule 0:3ecd25651727 177 _redMask = read32();
displaymodule 0:3ecd25651727 178 _greenMask = read32();
displaymodule 0:3ecd25651727 179 _blueMask = read32();
displaymodule 0:3ecd25651727 180 }
displaymodule 0:3ecd25651727 181 else {
displaymodule 0:3ecd25651727 182 _redMask = 0x00;
displaymodule 0:3ecd25651727 183 _greenMask = 0x00;
displaymodule 0:3ecd25651727 184 _blueMask = 0x00;
displaymodule 0:3ecd25651727 185 }
displaymodule 0:3ecd25651727 186
displaymodule 0:3ecd25651727 187 if (!IsValid888Bitmap() && !IsValid565Bitmap())
displaymodule 0:3ecd25651727 188 {
displaymodule 0:3ecd25651727 189 return false;
displaymodule 0:3ecd25651727 190 }
displaymodule 0:3ecd25651727 191
displaymodule 0:3ecd25651727 192 return true;
displaymodule 0:3ecd25651727 193 }
displaymodule 0:3ecd25651727 194
displaymodule 0:3ecd25651727 195 // In this context a valid bitmap
displaymodule 0:3ecd25651727 196 // - Stored bottom to top
displaymodule 0:3ecd25651727 197 // - 24-bit file
displaymodule 0:3ecd25651727 198 // - No compression
displaymodule 0:3ecd25651727 199 bool DmDrawBmpBase::IsValid888Bitmap() {
displaymodule 0:3ecd25651727 200 if (_height > 0 && _bitsPerPixel == 24 && _compression == 0)
displaymodule 0:3ecd25651727 201 {
displaymodule 0:3ecd25651727 202 return true;
displaymodule 0:3ecd25651727 203 }
displaymodule 0:3ecd25651727 204 return false;
displaymodule 0:3ecd25651727 205 }
displaymodule 0:3ecd25651727 206
displaymodule 0:3ecd25651727 207 // In this context a valid bitmap
displaymodule 0:3ecd25651727 208 // - Stored top to bottom
displaymodule 0:3ecd25651727 209 // - 16-bit file
displaymodule 0:3ecd25651727 210 // - Compression 3 (BI_BITFIELDS)
displaymodule 0:3ecd25651727 211 // - Have a 565 Colormask
displaymodule 0:3ecd25651727 212 bool DmDrawBmpBase::IsValid565Bitmap() {
displaymodule 0:3ecd25651727 213 if (_height < 0 && _bitsPerPixel == 16 && _compression == 3 && Is565ColorMask())
displaymodule 0:3ecd25651727 214 {
displaymodule 0:3ecd25651727 215 return true;
displaymodule 0:3ecd25651727 216 }
displaymodule 0:3ecd25651727 217 return false;
displaymodule 0:3ecd25651727 218 }
displaymodule 0:3ecd25651727 219
displaymodule 0:3ecd25651727 220 bool DmDrawBmpBase::Is565ColorMask() {
displaymodule 0:3ecd25651727 221 if (_redMask == 0xF800 && _greenMask == 0x7E0 && _blueMask == 0x1F)
displaymodule 0:3ecd25651727 222 {
displaymodule 0:3ecd25651727 223 return true;
displaymodule 0:3ecd25651727 224 }
displaymodule 0:3ecd25651727 225 return false;
displaymodule 0:3ecd25651727 226 }
displaymodule 0:3ecd25651727 227
displaymodule 0:3ecd25651727 228 int32_t DmDrawBmpBase::readInt32() {
displaymodule 0:3ecd25651727 229 int32_t d;
displaymodule 0:3ecd25651727 230 uint16_t b;
displaymodule 0:3ecd25651727 231
displaymodule 0:3ecd25651727 232 b = read16();
displaymodule 0:3ecd25651727 233 d = read16();
displaymodule 0:3ecd25651727 234 d <<= 16;
displaymodule 0:3ecd25651727 235 d |= b;
displaymodule 0:3ecd25651727 236 return d;
displaymodule 0:3ecd25651727 237 }
displaymodule 0:3ecd25651727 238
displaymodule 0:3ecd25651727 239 uint32_t DmDrawBmpBase::read32() {
displaymodule 0:3ecd25651727 240 uint32_t d;
displaymodule 0:3ecd25651727 241 uint16_t b;
displaymodule 0:3ecd25651727 242
displaymodule 0:3ecd25651727 243 b = read16();
displaymodule 0:3ecd25651727 244 d = read16();
displaymodule 0:3ecd25651727 245 d <<= 16;
displaymodule 0:3ecd25651727 246 d |= b;
displaymodule 0:3ecd25651727 247 return d;
displaymodule 0:3ecd25651727 248 }
displaymodule 0:3ecd25651727 249
displaymodule 0:3ecd25651727 250 uint16_t DmDrawBmpBase::read16() {
displaymodule 0:3ecd25651727 251 //uint16_t d;
displaymodule 0:3ecd25651727 252 //uint8_t b;
displaymodule 0:3ecd25651727 253 uint8_t buff[2];
displaymodule 0:3ecd25651727 254 //b = _imageFile.read();
displaymodule 0:3ecd25651727 255 //d = _imageFile.read();
displaymodule 0:3ecd25651727 256 _readFunc(_userData, buff, _readPos, 2);
displaymodule 0:3ecd25651727 257 _readPos+=2;
displaymodule 0:3ecd25651727 258 //d <<= 8;
displaymodule 0:3ecd25651727 259 //d |= b;
displaymodule 0:3ecd25651727 260 //return d;
displaymodule 0:3ecd25651727 261 return (buff[1] << 8) | buff[0];
displaymodule 0:3ecd25651727 262 }
displaymodule 0:3ecd25651727 263
displaymodule 0:3ecd25651727 264 // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
displaymodule 0:3ecd25651727 265 uint16_t DmDrawBmpBase::Convert888to565(uint8_t red, uint8_t green, uint8_t blue){
displaymodule 0:3ecd25651727 266 return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
displaymodule 0:3ecd25651727 267 }