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:
Mon Nov 06 01:41:55 2017 +0000
Revision:
152:a013ac0133e4
Parent:
146:373d59f08357
Child:
153:8a85efb3eb71
Initial support for GIF rendering

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