Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Committer:
WiredHome
Date:
Thu Jun 01 11:00:40 2017 +0000
Revision:
146:373d59f08357
Parent:
142:6e9bff59878a
Parent:
145:5eb2492acdda
Child:
151:ae94daaaf8ad
Child:
152:a013ac0133e4
Adopt new callback structure for ISRs,; Provide hooks for swMalloc for advanced memory usage tracking.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dreschpe 0:de9d1462a835 1 /* mbed GraphicsDisplay Display Library Base Class
dreschpe 0:de9d1462a835 2 * Copyright (c) 2007-2009 sford
dreschpe 0:de9d1462a835 3 * Released under the MIT License: http://mbed.org/license/mit
WiredHome 32:0e4f2ae512e2 4 *
WiredHome 34:c99ec28fac66 5 * Derivative work by D.Smart 2014
dreschpe 0:de9d1462a835 6 */
WiredHome 19:3f82c1161fd2 7
dreschpe 0:de9d1462a835 8 #include "GraphicsDisplay.h"
WiredHome 31:c72e12cd5c67 9 #include "Bitmap.h"
WiredHome 42:7cbdfd2bbfc5 10 #include "string.h"
dreschpe 0:de9d1462a835 11
WiredHome 145:5eb2492acdda 12 //#include "Utility.h" // private memory manager
WiredHome 145:5eb2492acdda 13 #ifndef UTILITY_H
WiredHome 145:5eb2492acdda 14 #define swMalloc malloc // use the standard
WiredHome 145:5eb2492acdda 15 #define swFree free
WiredHome 145:5eb2492acdda 16 #endif
WiredHome 145:5eb2492acdda 17
WiredHome 121:6bc4911f5e55 18 //#define DEBUG "GD "
WiredHome 29:422616aa04bd 19 // ...
WiredHome 29:422616aa04bd 20 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 29:422616aa04bd 21 //
WiredHome 29:422616aa04bd 22 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 115:c9862fd0c689 23 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 115:c9862fd0c689 24 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 115:c9862fd0c689 25 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 98:ecebed9b80b2 26 static void HexDump(const char * title, const uint8_t * p, int count)
WiredHome 31:c72e12cd5c67 27 {
WiredHome 31:c72e12cd5c67 28 int i;
WiredHome 31:c72e12cd5c67 29 char buf[100] = "0000: ";
WiredHome 31:c72e12cd5c67 30
WiredHome 31:c72e12cd5c67 31 if (*title)
WiredHome 31:c72e12cd5c67 32 INFO("%s", title);
WiredHome 31:c72e12cd5c67 33 for (i=0; i<count; ) {
WiredHome 31:c72e12cd5c67 34 sprintf(buf + strlen(buf), "%02X ", *(p+i));
WiredHome 31:c72e12cd5c67 35 if ((++i & 0x0F) == 0x00) {
WiredHome 31:c72e12cd5c67 36 INFO("%s", buf);
WiredHome 31:c72e12cd5c67 37 if (i < count)
WiredHome 31:c72e12cd5c67 38 sprintf(buf, "%04X: ", i);
WiredHome 31:c72e12cd5c67 39 else
WiredHome 31:c72e12cd5c67 40 buf[0] = '\0';
WiredHome 31:c72e12cd5c67 41 }
WiredHome 31:c72e12cd5c67 42 }
WiredHome 31:c72e12cd5c67 43 if (strlen(buf))
WiredHome 31:c72e12cd5c67 44 INFO("%s", buf);
WiredHome 31:c72e12cd5c67 45 }
WiredHome 29:422616aa04bd 46 #else
WiredHome 29:422616aa04bd 47 #define INFO(x, ...)
WiredHome 29:422616aa04bd 48 #define WARN(x, ...)
WiredHome 29:422616aa04bd 49 #define ERR(x, ...)
WiredHome 32:0e4f2ae512e2 50 #define HexDump(a, b, c)
WiredHome 29:422616aa04bd 51 #endif
WiredHome 29:422616aa04bd 52
WiredHome 19:3f82c1161fd2 53
WiredHome 42:7cbdfd2bbfc5 54 char mytolower(char a) {
WiredHome 42:7cbdfd2bbfc5 55 if (a >= 'A' && a <= 'Z')
WiredHome 42:7cbdfd2bbfc5 56 return (a - 'A' + 'a');
WiredHome 42:7cbdfd2bbfc5 57 else
WiredHome 42:7cbdfd2bbfc5 58 return a;
WiredHome 42:7cbdfd2bbfc5 59 }
WiredHome 42:7cbdfd2bbfc5 60 /// mystrnicmp exists because not all compiler libraries have this function.
WiredHome 42:7cbdfd2bbfc5 61 ///
WiredHome 42:7cbdfd2bbfc5 62 /// Some have strnicmp, others _strnicmp, and others have C++ methods, which
WiredHome 42:7cbdfd2bbfc5 63 /// is outside the scope of this C-portable set of functions.
WiredHome 42:7cbdfd2bbfc5 64 ///
WiredHome 42:7cbdfd2bbfc5 65 /// @param l is a pointer to the string on the left
WiredHome 42:7cbdfd2bbfc5 66 /// @param r is a pointer to the string on the right
WiredHome 42:7cbdfd2bbfc5 67 /// @param n is the number of characters to compare
WiredHome 42:7cbdfd2bbfc5 68 /// @returns -1 if l < r
WiredHome 42:7cbdfd2bbfc5 69 /// @returns 0 if l == r
WiredHome 42:7cbdfd2bbfc5 70 /// @returns +1 if l > r
WiredHome 42:7cbdfd2bbfc5 71 ///
WiredHome 42:7cbdfd2bbfc5 72 int mystrnicmp(const char *l, const char *r, size_t n) {
WiredHome 42:7cbdfd2bbfc5 73 int result = 0;
WiredHome 42:7cbdfd2bbfc5 74
WiredHome 42:7cbdfd2bbfc5 75 if (n != 0) {
WiredHome 42:7cbdfd2bbfc5 76 do {
WiredHome 42:7cbdfd2bbfc5 77 result = mytolower(*l++) - mytolower(*r++);
WiredHome 42:7cbdfd2bbfc5 78 } while ((result == 0) && (*l != '\0') && (--n > 0));
WiredHome 42:7cbdfd2bbfc5 79 }
WiredHome 42:7cbdfd2bbfc5 80 if (result < -1)
WiredHome 42:7cbdfd2bbfc5 81 result = -1;
WiredHome 42:7cbdfd2bbfc5 82 else if (result > 1)
WiredHome 42:7cbdfd2bbfc5 83 result = 1;
WiredHome 42:7cbdfd2bbfc5 84 return result;
WiredHome 42:7cbdfd2bbfc5 85 }
WiredHome 42:7cbdfd2bbfc5 86
WiredHome 42:7cbdfd2bbfc5 87
WiredHome 29:422616aa04bd 88 GraphicsDisplay::GraphicsDisplay(const char *name)
WiredHome 29:422616aa04bd 89 : TextDisplay(name)
WiredHome 19:3f82c1161fd2 90 {
WiredHome 29:422616aa04bd 91 font = NULL;
dreschpe 0:de9d1462a835 92 }
WiredHome 19:3f82c1161fd2 93
WiredHome 104:8d1d3832a215 94 //GraphicsDisplay::~GraphicsDisplay()
WiredHome 104:8d1d3832a215 95 //{
WiredHome 104:8d1d3832a215 96 //}
WiredHome 104:8d1d3832a215 97
WiredHome 98:ecebed9b80b2 98 RetCode_t GraphicsDisplay::SelectUserFont(const unsigned char * _font)
WiredHome 29:422616aa04bd 99 {
WiredHome 98:ecebed9b80b2 100 font = _font; // trusting them, but it might be good to put some checks in here...
WiredHome 98:ecebed9b80b2 101 return noerror;
WiredHome 29:422616aa04bd 102 }
WiredHome 98:ecebed9b80b2 103
WiredHome 29:422616aa04bd 104 int GraphicsDisplay::character(int x, int y, int c)
WiredHome 29:422616aa04bd 105 {
WiredHome 101:e0aad446094a 106 return fontblit(x, y, c);
WiredHome 29:422616aa04bd 107 }
WiredHome 19:3f82c1161fd2 108
WiredHome 111:efe436c43aba 109 RetCode_t GraphicsDisplay::window(rect_t r)
WiredHome 19:3f82c1161fd2 110 {
WiredHome 111:efe436c43aba 111 return window(r.p1.x, r.p1.y, r.p2.x + 1 - r.p1.x, r.p2.y + 1 - r.p1.y);
WiredHome 111:efe436c43aba 112 }
WiredHome 111:efe436c43aba 113
WiredHome 114:dbfb996bfbf3 114 RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t _width, dim_t _height)
WiredHome 111:efe436c43aba 115 {
WiredHome 114:dbfb996bfbf3 116 if (_width == (dim_t)-1)
WiredHome 114:dbfb996bfbf3 117 _width = width() - x;
WiredHome 114:dbfb996bfbf3 118 if (_height == (dim_t)-1)
WiredHome 114:dbfb996bfbf3 119 _height = height() - y;
WiredHome 114:dbfb996bfbf3 120
WiredHome 111:efe436c43aba 121 // Save the window metrics
WiredHome 111:efe436c43aba 122 windowrect.p1.x = x;
WiredHome 111:efe436c43aba 123 windowrect.p1.y = y;
WiredHome 114:dbfb996bfbf3 124 windowrect.p2.x = x + _width - 1;
WiredHome 114:dbfb996bfbf3 125 windowrect.p2.y = y + _height - 1;
dreschpe 0:de9d1462a835 126 // current pixel location
dreschpe 0:de9d1462a835 127 _x = x;
dreschpe 0:de9d1462a835 128 _y = y;
WiredHome 32:0e4f2ae512e2 129 return noerror;
dreschpe 0:de9d1462a835 130 }
WiredHome 19:3f82c1161fd2 131
WiredHome 79:544eb4964795 132 RetCode_t GraphicsDisplay::WindowMax(void)
WiredHome 31:c72e12cd5c67 133 {
WiredHome 79:544eb4964795 134 return window(0,0, width(),height());
WiredHome 31:c72e12cd5c67 135 }
WiredHome 31:c72e12cd5c67 136
WiredHome 55:dfbabef7003e 137 RetCode_t GraphicsDisplay::_putp(color_t color)
WiredHome 19:3f82c1161fd2 138 {
WiredHome 33:b6b710758ab3 139 pixel(_x, _y, color);
dreschpe 0:de9d1462a835 140 // update pixel location based on window settings
dreschpe 0:de9d1462a835 141 _x++;
WiredHome 111:efe436c43aba 142 if(_x > windowrect.p2.x) {
WiredHome 111:efe436c43aba 143 _x = windowrect.p1.x;
dreschpe 0:de9d1462a835 144 _y++;
WiredHome 111:efe436c43aba 145 if(_y > windowrect.p2.y) {
WiredHome 111:efe436c43aba 146 _y = windowrect.p1.y;
dreschpe 0:de9d1462a835 147 }
dreschpe 0:de9d1462a835 148 }
WiredHome 32:0e4f2ae512e2 149 return noerror;
dreschpe 0:de9d1462a835 150 }
dreschpe 0:de9d1462a835 151
WiredHome 109:7b94f06f085b 152 RetCode_t GraphicsDisplay::fill(loc_t x, loc_t y, dim_t w, dim_t h, color_t color)
WiredHome 19:3f82c1161fd2 153 {
WiredHome 79:544eb4964795 154 return fillrect(x,y, x+w, y+h, color);
dreschpe 0:de9d1462a835 155 }
WiredHome 19:3f82c1161fd2 156
WiredHome 61:8f3153bf0baa 157 RetCode_t GraphicsDisplay::cls(uint16_t layers)
WiredHome 19:3f82c1161fd2 158 {
WiredHome 142:6e9bff59878a 159 int restore = GetDrawingLayer();
WiredHome 142:6e9bff59878a 160 if (layers & 1) {
WiredHome 142:6e9bff59878a 161 SelectDrawingLayer(0);
WiredHome 142:6e9bff59878a 162 fill(0, 0, width(), height(), _background);
WiredHome 142:6e9bff59878a 163 }
WiredHome 142:6e9bff59878a 164 if (layers & 2) {
WiredHome 142:6e9bff59878a 165 SelectDrawingLayer(1);
WiredHome 142:6e9bff59878a 166 fill(0, 0, width(), height(), _background);
WiredHome 142:6e9bff59878a 167 }
WiredHome 142:6e9bff59878a 168 SelectDrawingLayer(restore);
WiredHome 142:6e9bff59878a 169 return noerror;
dreschpe 0:de9d1462a835 170 }
WiredHome 19:3f82c1161fd2 171
WiredHome 109:7b94f06f085b 172 RetCode_t GraphicsDisplay::blit(loc_t x, loc_t y, dim_t w, dim_t h, const int * color)
WiredHome 19:3f82c1161fd2 173 {
WiredHome 111:efe436c43aba 174 rect_t restore = windowrect;
dreschpe 0:de9d1462a835 175 window(x, y, w, h);
WiredHome 37:f19b7e7449dc 176 _StartGraphicsStream();
WiredHome 31:c72e12cd5c67 177 for (int i=0; i<w*h; i++) {
WiredHome 55:dfbabef7003e 178 _putp(color[i]);
dreschpe 0:de9d1462a835 179 }
WiredHome 37:f19b7e7449dc 180 _EndGraphicsStream();
WiredHome 111:efe436c43aba 181 //return WindowMax();
WiredHome 111:efe436c43aba 182 return window(restore);
dreschpe 0:de9d1462a835 183 }
WiredHome 19:3f82c1161fd2 184
WiredHome 98:ecebed9b80b2 185 // 8 byte "info" section
WiredHome 98:ecebed9b80b2 186 //0x00, // unknown ????????
WiredHome 98:ecebed9b80b2 187 //0x00, // unknown ????????
WiredHome 98:ecebed9b80b2 188 //0x20,0x00, // First char 32
WiredHome 98:ecebed9b80b2 189 //0x7F,0x00, // Last char 127
WiredHome 98:ecebed9b80b2 190 //0x25, // Font Height 37
WiredHome 98:ecebed9b80b2 191 //0x00, // Unknown 0 ????????
WiredHome 98:ecebed9b80b2 192 //
WiredHome 98:ecebed9b80b2 193 //0x01,0x88,0x01,0x00 // ' ' is 1 pixel wide, data is at offset 0x0188
WiredHome 98:ecebed9b80b2 194 //0x0B,0xAD,0x01,0x00 // '!' is 11 pixels wide, data is at offset 0x01AD
WiredHome 98:ecebed9b80b2 195 //0x0D,0xF7,0x01,0x00 // '"' is 13 pixels wide, data is at offset 0x01F7
WiredHome 98:ecebed9b80b2 196 //...
WiredHome 98:ecebed9b80b2 197 //0x00,... // ' ' data stream.
WiredHome 98:ecebed9b80b2 198 //0x00,0x06,0x00,0x07,0x80,0x07,0xC0,0x07,0xC0,0x07,0xC0 // '!'
WiredHome 98:ecebed9b80b2 199 //...
WiredHome 101:e0aad446094a 200
WiredHome 101:e0aad446094a 201
WiredHome 109:7b94f06f085b 202 const uint8_t * GraphicsDisplay::getCharMetrics(const unsigned char c, dim_t * width, dim_t * height)
WiredHome 19:3f82c1161fd2 203 {
WiredHome 98:ecebed9b80b2 204 uint16_t offsetToCharLookup;
WiredHome 98:ecebed9b80b2 205 uint16_t firstChar = font[3] * 256 + font[2];
WiredHome 98:ecebed9b80b2 206 uint16_t lastChar = font[5] * 256 + font[4];
WiredHome 109:7b94f06f085b 207 dim_t charHeight = font[6];
WiredHome 98:ecebed9b80b2 208 const unsigned char * charRecord; // width, data, data, data, ...
WiredHome 98:ecebed9b80b2 209
WiredHome 98:ecebed9b80b2 210 INFO("first:%d, last:%d, c:%d", firstChar, lastChar, c);
WiredHome 98:ecebed9b80b2 211 if (c < firstChar || c > lastChar)
WiredHome 101:e0aad446094a 212 return NULL; // advance zero pixels since it was unprintable...
WiredHome 101:e0aad446094a 213
WiredHome 101:e0aad446094a 214 // 8 bytes of preamble to the first level lookup table
WiredHome 101:e0aad446094a 215 offsetToCharLookup = 8 + 4 * (c - firstChar); // 4-bytes: width(pixels), 16-bit offset from table start, 0
WiredHome 109:7b94f06f085b 216 dim_t charWidth = font[offsetToCharLookup];
WiredHome 101:e0aad446094a 217 charRecord = font + font[offsetToCharLookup + 2] * 256 + font[offsetToCharLookup + 1];
WiredHome 101:e0aad446094a 218 //INFO("hgt:%d, wdt:%d", charHeight, charWidth);
WiredHome 101:e0aad446094a 219 if (width)
WiredHome 101:e0aad446094a 220 *width = charWidth;
WiredHome 101:e0aad446094a 221 if (height)
WiredHome 101:e0aad446094a 222 *height = charHeight;
WiredHome 101:e0aad446094a 223 return charRecord;
WiredHome 101:e0aad446094a 224 }
WiredHome 101:e0aad446094a 225
WiredHome 109:7b94f06f085b 226
WiredHome 109:7b94f06f085b 227 int GraphicsDisplay::fontblit(loc_t x, loc_t y, const unsigned char c)
WiredHome 101:e0aad446094a 228 {
WiredHome 109:7b94f06f085b 229 const uint8_t * charRecord; // width, data, data, data, ...
WiredHome 109:7b94f06f085b 230 dim_t charWidth, charHeight;
WiredHome 101:e0aad446094a 231 charRecord = getCharMetrics(c, &charWidth, &charHeight);
WiredHome 101:e0aad446094a 232 if (charRecord) {
WiredHome 101:e0aad446094a 233 INFO("hgt:%d, wdt:%d", charHeight, charWidth);
WiredHome 101:e0aad446094a 234 // clip to the edge of the screen
WiredHome 101:e0aad446094a 235 //if (x + charWidth >= width())
WiredHome 101:e0aad446094a 236 // charWidth = width() - x;
WiredHome 101:e0aad446094a 237 //if (y + charHeight >= height())
WiredHome 101:e0aad446094a 238 // charHeight = height() - y;
WiredHome 109:7b94f06f085b 239 booleanStream(x,y,charWidth, charHeight, charRecord);
WiredHome 101:e0aad446094a 240 return charWidth;
WiredHome 101:e0aad446094a 241 } else {
WiredHome 101:e0aad446094a 242 return 0;
WiredHome 29:422616aa04bd 243 }
dreschpe 0:de9d1462a835 244 }
dreschpe 0:de9d1462a835 245
WiredHome 31:c72e12cd5c67 246 // BMP Color Palette is BGRx
WiredHome 31:c72e12cd5c67 247 // BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
WiredHome 31:c72e12cd5c67 248 // RGB16 is
WiredHome 31:c72e12cd5c67 249 // RRRR RGGG GGGB BBBB
WiredHome 31:c72e12cd5c67 250 // swap to little endian
WiredHome 31:c72e12cd5c67 251 // GGGB BBBB RRRR RGGG
WiredHome 32:0e4f2ae512e2 252 color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i)
WiredHome 31:c72e12cd5c67 253 {
WiredHome 31:c72e12cd5c67 254 color_t c;
WiredHome 31:c72e12cd5c67 255
WiredHome 31:c72e12cd5c67 256 c = ((colorPalette[i].rgbBlue >> 3) << 0);
WiredHome 31:c72e12cd5c67 257 c |= ((colorPalette[i].rgbGreen >> 2) << 5);
WiredHome 31:c72e12cd5c67 258 c |= ((colorPalette[i].rgbRed >> 3) << 11);
WiredHome 31:c72e12cd5c67 259 return c;
WiredHome 31:c72e12cd5c67 260 }
WiredHome 29:422616aa04bd 261
WiredHome 93:6fbc516de05e 262 // RGB16 little endian
WiredHome 93:6fbc516de05e 263 // GGGB BBBB RRRR RGGG
WiredHome 93:6fbc516de05e 264 // swap
WiredHome 93:6fbc516de05e 265 // RRRR RGGG GGGB BBBB
WiredHome 93:6fbc516de05e 266 // RRRR R
WiredHome 93:6fbc516de05e 267 // extend to BMP Color Palette is BGRx
WiredHome 93:6fbc516de05e 268 // BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
WiredHome 41:2956a0a221e5 269 RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c)
WiredHome 41:2956a0a221e5 270 {
WiredHome 41:2956a0a221e5 271 RGBQUAD q;
WiredHome 41:2956a0a221e5 272
WiredHome 41:2956a0a221e5 273 memset(&q, 0, sizeof(q));
WiredHome 93:6fbc516de05e 274 c = (c << 8) | (c >> 8); // swap
WiredHome 72:ecffe56af969 275 q.rgbBlue = ((c & 0x001F) << 3) | (c & 0x07); /* Blue value */
WiredHome 93:6fbc516de05e 276 q.rgbGreen = ((c & 0x07E0) >> 3) | ((c >> 9) & 0x03); /* Green value */
WiredHome 93:6fbc516de05e 277 q.rgbRed = ((c & 0xF800) >> 8) | ((c >> 13) & 0x07); /* Red value */
WiredHome 41:2956a0a221e5 278 q.rgbReserved = 0;
WiredHome 41:2956a0a221e5 279 return q;
WiredHome 41:2956a0a221e5 280 }
WiredHome 41:2956a0a221e5 281
WiredHome 42:7cbdfd2bbfc5 282 RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image)
WiredHome 31:c72e12cd5c67 283 {
WiredHome 31:c72e12cd5c67 284 BITMAPINFOHEADER BMP_Info;
WiredHome 31:c72e12cd5c67 285 RGBQUAD * colorPalette = NULL;
WiredHome 31:c72e12cd5c67 286 int colorCount;
WiredHome 32:0e4f2ae512e2 287 uint8_t * lineBuffer = NULL;
WiredHome 69:636867df24a1 288 color_t * pixelBuffer = NULL;
WiredHome 31:c72e12cd5c67 289 uint16_t BPP_t;
WiredHome 95:ef538bd687c0 290 dim_t PixelWidth, PixelHeight;
WiredHome 31:c72e12cd5c67 291 unsigned int i, offset;
WiredHome 31:c72e12cd5c67 292 int padd,j;
WiredHome 59:fb40aad4efd4 293 #ifdef DEBUG
WiredHome 112:325ca91bc03d 294 //uint32_t start_data;
WiredHome 59:fb40aad4efd4 295 #endif
WiredHome 31:c72e12cd5c67 296
WiredHome 42:7cbdfd2bbfc5 297 // Now, Read the bitmap info header
WiredHome 31:c72e12cd5c67 298 fread(&BMP_Info, 1, sizeof(BMP_Info), Image);
WiredHome 59:fb40aad4efd4 299 HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
WiredHome 31:c72e12cd5c67 300 BPP_t = BMP_Info.biBitCount;
WiredHome 31:c72e12cd5c67 301 INFO("biBitCount %04X", BPP_t);
WiredHome 112:325ca91bc03d 302 if (BPP_t != 1 && BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel
WiredHome 31:c72e12cd5c67 303 fclose(Image);
WiredHome 31:c72e12cd5c67 304 return(not_supported_format);
WiredHome 31:c72e12cd5c67 305 }
WiredHome 112:325ca91bc03d 306 if (BMP_Info.biCompression != 0) { // Only the "no comporession" option is supported.
WiredHome 112:325ca91bc03d 307 fclose(Image);
WiredHome 112:325ca91bc03d 308 return(not_supported_format);
WiredHome 112:325ca91bc03d 309 }
WiredHome 31:c72e12cd5c67 310 PixelHeight = BMP_Info.biHeight;
WiredHome 31:c72e12cd5c67 311 PixelWidth = BMP_Info.biWidth;
WiredHome 79:544eb4964795 312 INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height());
WiredHome 31:c72e12cd5c67 313 if (PixelHeight > height() + y || PixelWidth > width() + x) {
WiredHome 31:c72e12cd5c67 314 fclose(Image);
WiredHome 31:c72e12cd5c67 315 return(image_too_big);
WiredHome 31:c72e12cd5c67 316 }
WiredHome 31:c72e12cd5c67 317 if (BMP_Info.biBitCount <= 8) {
WiredHome 31:c72e12cd5c67 318 int paletteSize;
WiredHome 31:c72e12cd5c67 319 // Read the color palette
WiredHome 31:c72e12cd5c67 320 colorCount = 1 << BMP_Info.biBitCount;
WiredHome 31:c72e12cd5c67 321 paletteSize = sizeof(RGBQUAD) * colorCount;
WiredHome 145:5eb2492acdda 322 colorPalette = (RGBQUAD *)swMalloc(paletteSize);
WiredHome 31:c72e12cd5c67 323 if (colorPalette == NULL) {
WiredHome 31:c72e12cd5c67 324 fclose(Image);
WiredHome 31:c72e12cd5c67 325 return(not_enough_ram);
WiredHome 31:c72e12cd5c67 326 }
WiredHome 31:c72e12cd5c67 327 fread(colorPalette, 1, paletteSize, Image);
WiredHome 59:fb40aad4efd4 328 HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
WiredHome 31:c72e12cd5c67 329 }
WiredHome 31:c72e12cd5c67 330
WiredHome 32:0e4f2ae512e2 331 int lineBufSize = ((BPP_t * PixelWidth + 7)/8);
WiredHome 59:fb40aad4efd4 332 INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
WiredHome 145:5eb2492acdda 333 lineBuffer = (uint8_t *)swMalloc(lineBufSize);
WiredHome 31:c72e12cd5c67 334 if (lineBuffer == NULL) {
WiredHome 145:5eb2492acdda 335 swFree(colorPalette);
WiredHome 31:c72e12cd5c67 336 fclose(Image);
WiredHome 31:c72e12cd5c67 337 return(not_enough_ram);
WiredHome 31:c72e12cd5c67 338 }
WiredHome 145:5eb2492acdda 339 pixelBuffer = (color_t *)swMalloc(PixelWidth * sizeof(color_t));
WiredHome 41:2956a0a221e5 340 if (pixelBuffer == NULL) {
WiredHome 145:5eb2492acdda 341 swFree(lineBuffer);
WiredHome 69:636867df24a1 342 if (colorPalette)
WiredHome 145:5eb2492acdda 343 swFree(colorPalette);
WiredHome 41:2956a0a221e5 344 fclose(Image);
WiredHome 41:2956a0a221e5 345 return(not_enough_ram);
WiredHome 41:2956a0a221e5 346 }
WiredHome 31:c72e12cd5c67 347
WiredHome 112:325ca91bc03d 348 padd = (lineBufSize % 4);
WiredHome 112:325ca91bc03d 349 if (padd)
WiredHome 112:325ca91bc03d 350 padd = 4 - padd;
WiredHome 31:c72e12cd5c67 351
WiredHome 32:0e4f2ae512e2 352 // Define window for top to bottom and left to right so writing auto-wraps
WiredHome 111:efe436c43aba 353 rect_t restore = windowrect;
WiredHome 31:c72e12cd5c67 354 window(x,y, PixelWidth,PixelHeight);
WiredHome 136:224e03d5c31f 355 // SetGraphicsCursor(x, y);
WiredHome 136:224e03d5c31f 356 // _StartGraphicsStream();
WiredHome 112:325ca91bc03d 357
WiredHome 112:325ca91bc03d 358 //start_data = BMP_Info.bfOffBits;
WiredHome 112:325ca91bc03d 359 //HexDump("Raw Data", (uint8_t *)&start_data, 32);
WiredHome 59:fb40aad4efd4 360 INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
WiredHome 32:0e4f2ae512e2 361 for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up
WiredHome 42:7cbdfd2bbfc5 362 offset = fileOffset + j * (lineBufSize + padd); // start of line
WiredHome 31:c72e12cd5c67 363 fseek(Image, offset, SEEK_SET);
WiredHome 32:0e4f2ae512e2 364 fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow !
WiredHome 79:544eb4964795 365 //INFO("offset: %6X", offset);
WiredHome 112:325ca91bc03d 366 //HexDump("Line", lineBuffer, lineBufSize);
WiredHome 32:0e4f2ae512e2 367 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT
WiredHome 112:325ca91bc03d 368 if (BPP_t == 1) {
WiredHome 112:325ca91bc03d 369 uint8_t dPix = lineBuffer[i/8];
WiredHome 112:325ca91bc03d 370 uint8_t bMask = 0x80 >> (i % 8);
WiredHome 112:325ca91bc03d 371 uint8_t bit = (bMask & dPix) ? 0 : 1;
WiredHome 136:224e03d5c31f 372 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, bit);
WiredHome 112:325ca91bc03d 373 } else if (BPP_t == 4) {
WiredHome 31:c72e12cd5c67 374 uint8_t dPix = lineBuffer[i/2];
WiredHome 31:c72e12cd5c67 375 if ((i & 1) == 0)
WiredHome 31:c72e12cd5c67 376 dPix >>= 4;
WiredHome 31:c72e12cd5c67 377 dPix &= 0x0F;
WiredHome 41:2956a0a221e5 378 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix);
WiredHome 31:c72e12cd5c67 379 } else if (BPP_t == 8) {
WiredHome 41:2956a0a221e5 380 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]);
WiredHome 32:0e4f2ae512e2 381 } else if (BPP_t == 16) {
WiredHome 41:2956a0a221e5 382 pixelBuffer[i] = lineBuffer[i];
WiredHome 32:0e4f2ae512e2 383 } else if (BPP_t == 24) {
WiredHome 37:f19b7e7449dc 384 color_t color;
WiredHome 32:0e4f2ae512e2 385 color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]);
WiredHome 41:2956a0a221e5 386 pixelBuffer[i] = color;
WiredHome 31:c72e12cd5c67 387 }
WiredHome 31:c72e12cd5c67 388 }
WiredHome 41:2956a0a221e5 389 pixelStream(pixelBuffer, PixelWidth, x, y++);
WiredHome 31:c72e12cd5c67 390 }
WiredHome 136:224e03d5c31f 391 // _EndGraphicsStream();
WiredHome 111:efe436c43aba 392 window(restore);
WiredHome 145:5eb2492acdda 393 swFree(pixelBuffer); // don't leak memory
WiredHome 145:5eb2492acdda 394 swFree(lineBuffer);
WiredHome 69:636867df24a1 395 if (colorPalette)
WiredHome 145:5eb2492acdda 396 swFree(colorPalette);
WiredHome 32:0e4f2ae512e2 397 return (noerror);
WiredHome 31:c72e12cd5c67 398 }
WiredHome 31:c72e12cd5c67 399
WiredHome 42:7cbdfd2bbfc5 400
WiredHome 42:7cbdfd2bbfc5 401 RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName)
WiredHome 42:7cbdfd2bbfc5 402 {
WiredHome 42:7cbdfd2bbfc5 403 if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) {
WiredHome 42:7cbdfd2bbfc5 404 return RenderBitmapFile(x,y,FileName);
WiredHome 115:c9862fd0c689 405 } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".jpg", 4) == 0) {
WiredHome 115:c9862fd0c689 406 return RenderJpegFile(x,y,FileName);
WiredHome 42:7cbdfd2bbfc5 407 } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) {
WiredHome 42:7cbdfd2bbfc5 408 return RenderIconFile(x,y,FileName);
WiredHome 42:7cbdfd2bbfc5 409 } else {
WiredHome 42:7cbdfd2bbfc5 410 return not_supported_format;
WiredHome 42:7cbdfd2bbfc5 411 }
WiredHome 42:7cbdfd2bbfc5 412 }
WiredHome 42:7cbdfd2bbfc5 413
WiredHome 115:c9862fd0c689 414 RetCode_t GraphicsDisplay::RenderJpegFile(loc_t x, loc_t y, const char *Name_JPG)
WiredHome 115:c9862fd0c689 415 {
WiredHome 145:5eb2492acdda 416 #define JPEG_WORK_SPACE_SIZE 3100 // Worst case requirements for the decompression
WiredHome 115:c9862fd0c689 417 JDEC * jdec;
WiredHome 115:c9862fd0c689 418 uint16_t * work;
WiredHome 115:c9862fd0c689 419 RetCode_t r = noerror; // start optimistic
WiredHome 115:c9862fd0c689 420 FILE * fh = fopen(Name_JPG, "rb");
WiredHome 115:c9862fd0c689 421
WiredHome 115:c9862fd0c689 422 if (!fh)
WiredHome 115:c9862fd0c689 423 return(file_not_found);
WiredHome 120:be2aaa3adf72 424 //INFO("RenderJpegFile(%d,%d,%s)", x,y, Name_JPG);
WiredHome 145:5eb2492acdda 425 work = (uint16_t *)swMalloc(JPEG_WORK_SPACE_SIZE);
WiredHome 115:c9862fd0c689 426 if (work) {
WiredHome 145:5eb2492acdda 427 jdec = (JDEC *)swMalloc(sizeof(JDEC));
WiredHome 115:c9862fd0c689 428 if (jdec) {
WiredHome 120:be2aaa3adf72 429 memset(work, 0, JPEG_WORK_SPACE_SIZE/sizeof(uint16_t));
WiredHome 120:be2aaa3adf72 430 memset(jdec, 0, sizeof(JDEC));
WiredHome 115:c9862fd0c689 431 r = (RetCode_t)jd_prepare(jdec, NULL, work, JPEG_WORK_SPACE_SIZE, fh);
WiredHome 115:c9862fd0c689 432 INFO("jd_prepare returned %d", r);
WiredHome 115:c9862fd0c689 433
WiredHome 115:c9862fd0c689 434 if (r == noerror) {
WiredHome 136:224e03d5c31f 435 img_x = x; // save the origin for the privOutput function
WiredHome 136:224e03d5c31f 436 img_y = y;
WiredHome 115:c9862fd0c689 437 r = (RetCode_t)jd_decomp(jdec, NULL, 0);
WiredHome 115:c9862fd0c689 438 } else {
WiredHome 115:c9862fd0c689 439 r = not_supported_format; // error("jd_prepare error:%d", r);
WiredHome 115:c9862fd0c689 440 }
WiredHome 145:5eb2492acdda 441 swFree(jdec);
WiredHome 115:c9862fd0c689 442 } else {
WiredHome 115:c9862fd0c689 443 WARN("checkpoint");
WiredHome 115:c9862fd0c689 444 r = not_enough_ram;
WiredHome 115:c9862fd0c689 445 }
WiredHome 145:5eb2492acdda 446 swFree(work);
WiredHome 115:c9862fd0c689 447 } else {
WiredHome 115:c9862fd0c689 448 WARN("checkpoint");
WiredHome 115:c9862fd0c689 449 r = not_enough_ram;
WiredHome 115:c9862fd0c689 450 }
WiredHome 115:c9862fd0c689 451 fclose(fh);
WiredHome 115:c9862fd0c689 452 return r; // error("jd_decomp error:%d", r);
WiredHome 115:c9862fd0c689 453 }
WiredHome 115:c9862fd0c689 454
WiredHome 42:7cbdfd2bbfc5 455 RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP)
WiredHome 42:7cbdfd2bbfc5 456 {
WiredHome 42:7cbdfd2bbfc5 457 BITMAPFILEHEADER BMP_Header;
WiredHome 42:7cbdfd2bbfc5 458
WiredHome 42:7cbdfd2bbfc5 459 INFO("Opening {%s}", Name_BMP);
WiredHome 42:7cbdfd2bbfc5 460 FILE *Image = fopen(Name_BMP, "rb");
WiredHome 42:7cbdfd2bbfc5 461 if (!Image) {
WiredHome 42:7cbdfd2bbfc5 462 return(file_not_found);
WiredHome 42:7cbdfd2bbfc5 463 }
WiredHome 42:7cbdfd2bbfc5 464
WiredHome 42:7cbdfd2bbfc5 465 fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header
WiredHome 42:7cbdfd2bbfc5 466 INFO("bfType %04X", BMP_Header.bfType);
WiredHome 59:fb40aad4efd4 467 HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
WiredHome 42:7cbdfd2bbfc5 468 if (BMP_Header.bfType != BF_TYPE) {
WiredHome 42:7cbdfd2bbfc5 469 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 470 return(not_bmp_format);
WiredHome 42:7cbdfd2bbfc5 471 }
WiredHome 112:325ca91bc03d 472 INFO("bfOffits %04X", BMP_Header.bfOffBits);
WiredHome 42:7cbdfd2bbfc5 473 RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image);
WiredHome 42:7cbdfd2bbfc5 474 if (rt != noerror) {
WiredHome 42:7cbdfd2bbfc5 475 return rt;
WiredHome 42:7cbdfd2bbfc5 476 } else {
WiredHome 42:7cbdfd2bbfc5 477 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 478 return (noerror);
WiredHome 42:7cbdfd2bbfc5 479 }
WiredHome 42:7cbdfd2bbfc5 480 }
WiredHome 42:7cbdfd2bbfc5 481
WiredHome 42:7cbdfd2bbfc5 482 RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO)
WiredHome 42:7cbdfd2bbfc5 483 {
WiredHome 42:7cbdfd2bbfc5 484 ICOFILEHEADER ICO_Header;
WiredHome 42:7cbdfd2bbfc5 485 ICODIRENTRY ICO_DirEntry;
WiredHome 42:7cbdfd2bbfc5 486
WiredHome 42:7cbdfd2bbfc5 487 INFO("Opening {%s}", Name_ICO);
WiredHome 42:7cbdfd2bbfc5 488 FILE *Image = fopen(Name_ICO, "rb");
WiredHome 42:7cbdfd2bbfc5 489 if (!Image) {
WiredHome 42:7cbdfd2bbfc5 490 return(file_not_found);
WiredHome 42:7cbdfd2bbfc5 491 }
WiredHome 42:7cbdfd2bbfc5 492
WiredHome 42:7cbdfd2bbfc5 493 fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header
WiredHome 42:7cbdfd2bbfc5 494 HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header));
WiredHome 42:7cbdfd2bbfc5 495 if (ICO_Header.Reserved_zero != 0
WiredHome 42:7cbdfd2bbfc5 496 || ICO_Header.icType != IC_TYPE
WiredHome 42:7cbdfd2bbfc5 497 || ICO_Header.icImageCount == 0) {
WiredHome 42:7cbdfd2bbfc5 498 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 499 return(not_ico_format);
WiredHome 42:7cbdfd2bbfc5 500 }
WiredHome 42:7cbdfd2bbfc5 501
WiredHome 42:7cbdfd2bbfc5 502 // Read ONLY the first of n possible directory entries.
WiredHome 42:7cbdfd2bbfc5 503 fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image);
WiredHome 42:7cbdfd2bbfc5 504 HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry));
WiredHome 42:7cbdfd2bbfc5 505 INFO("biBitCount %04X", ICO_DirEntry.biBitCount);
WiredHome 42:7cbdfd2bbfc5 506 if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico
WiredHome 42:7cbdfd2bbfc5 507 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 508 return(not_supported_format);
WiredHome 42:7cbdfd2bbfc5 509 }
WiredHome 42:7cbdfd2bbfc5 510
WiredHome 42:7cbdfd2bbfc5 511 RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image);
WiredHome 42:7cbdfd2bbfc5 512 if (rt == noerror) {
WiredHome 42:7cbdfd2bbfc5 513 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 514 return (noerror);
WiredHome 42:7cbdfd2bbfc5 515 } else {
WiredHome 42:7cbdfd2bbfc5 516 return rt;
WiredHome 42:7cbdfd2bbfc5 517 }
WiredHome 42:7cbdfd2bbfc5 518 }
WiredHome 42:7cbdfd2bbfc5 519
WiredHome 19:3f82c1161fd2 520 int GraphicsDisplay::columns()
WiredHome 19:3f82c1161fd2 521 {
WiredHome 19:3f82c1161fd2 522 return width() / 8;
dreschpe 0:de9d1462a835 523 }
dreschpe 0:de9d1462a835 524
WiredHome 19:3f82c1161fd2 525 int GraphicsDisplay::rows()
WiredHome 19:3f82c1161fd2 526 {
WiredHome 19:3f82c1161fd2 527 return height() / 8;
WiredHome 19:3f82c1161fd2 528 }