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
DmDrawBmpBase.cpp@6:0f69891b105e, 2015-01-22 (annotated)
- Committer:
- displaymodule
- Date:
- Thu Jan 22 05:54:22 2015 +0000
- Revision:
- 6:0f69891b105e
- Parent:
- 4:93ca338876e2
Add DM_TFT43_108, DM_TFT50_111 based on new lib drv: DmTftRa8875
Who changed what in which revision?
User | Revision | Line number | New 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 | } |