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:
Mon Jul 07 11:43:01 2014 +0000
Revision:
3:e1e1053e286f
Parent:
0:3ecd25651727
Child:
4:93ca338876e2
Updated library dependencies. Added basic clipping of BMP files.

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