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
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)
Revision 163:17526689a3ed, committed 2019-02-13
- Comitter:
- WiredHome
- Date:
- Wed Feb 13 04:20:12 2019 +0000
- Parent:
- 162:a2d7f1988711
- Child:
- 164:76edd7d9cb68
- Commit message:
- Add ability to PrintScreen as an 8-bit bitmap, as an alternate to the default of 24-bit.
Changed in this revision
--- a/Bitmap.h Mon Feb 11 03:44:42 2019 +0000 +++ b/Bitmap.h Wed Feb 13 04:20:12 2019 +0000 @@ -31,7 +31,7 @@ uint16_t bfReserved1; ///< reserved placeholder for the structure footprint uint16_t bfReserved2; ///< reserved placeholder for the structure footprint uint32_t bfOffBits; ///< Offset to bitmap data - } BITMAPFILEHEADER; + } BITMAPFILEHEADER; // Size: 14B /// Bitmap information header typedef struct /**** BMP file info structure ****/ @@ -47,7 +47,7 @@ int32_t biYPelsPerMeter; ///< Y pixels per meter uint32_t biClrUsed; ///< Number of colors used uint32_t biClrImportant; ///< Number of important colors - } BITMAPINFOHEADER; + } BITMAPINFOHEADER; // Size: 40B #pragma pop #define BF_TYPE 0x4D42 /* "MB" */
--- a/RA8875.cpp Mon Feb 11 03:44:42 2019 +0000 +++ b/RA8875.cpp Wed Feb 13 04:20:12 2019 +0000 @@ -101,6 +101,75 @@ "external abort", ///< during an idle callback, the user code initiated an abort }; +typedef struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; +} rgbTrio_t; + +static const rgbTrio_t WebColorPalette[] = { + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x33,0xFF}, {0x00,0x00,0x66,0xFF}, {0x00,0x00,0x99,0xFF}, {0x00,0x00,0xCC,0xFF}, {0x00,0x00,0xFF,0xFF}, + {0x00,0x33,0x00,0xFF}, {0x00,0x33,0x33,0xFF}, {0x00,0x33,0x66,0xFF}, {0x00,0x33,0x99,0xFF}, {0x00,0x33,0xCC,0xFF}, {0x00,0x33,0xFF,0xFF}, + {0x00,0x66,0x00,0xFF}, {0x00,0x66,0x33,0xFF}, {0x00,0x66,0x66,0xFF}, {0x00,0x66,0x99,0xFF}, {0x00,0x66,0xCC,0xFF}, {0x00,0x66,0xFF,0xFF}, + {0x00,0x99,0x00,0xFF}, {0x00,0x99,0x33,0xFF}, {0x00,0x99,0x66,0xFF}, {0x00,0x99,0x99,0xFF}, {0x00,0x99,0xCC,0xFF}, {0x00,0x99,0xFF,0xFF}, + {0x00,0xCC,0x00,0xFF}, {0x00,0xCC,0x33,0xFF}, {0x00,0xCC,0x66,0xFF}, {0x00,0xCC,0x99,0xFF}, {0x00,0xCC,0xCC,0xFF}, {0x00,0xCC,0xFF,0xFF}, + {0x00,0xFF,0x00,0xFF}, {0x00,0xFF,0x33,0xFF}, {0x00,0xFF,0x66,0xFF}, {0x00,0xFF,0x99,0xFF}, {0x00,0xFF,0xCC,0xFF}, {0x00,0xFF,0xFF,0xFF}, + {0x33,0x00,0x00,0xFF}, {0x33,0x00,0x33,0xFF}, {0x33,0x00,0x66,0xFF}, {0x33,0x00,0x99,0xFF}, {0x33,0x00,0xCC,0xFF}, {0x33,0x00,0xFF,0xFF}, + {0x33,0x33,0x00,0xFF}, {0x33,0x33,0x33,0xFF}, {0x33,0x33,0x66,0xFF}, {0x33,0x33,0x99,0xFF}, {0x33,0x33,0xCC,0xFF}, {0x33,0x33,0xFF,0xFF}, + {0x33,0x66,0x00,0xFF}, {0x33,0x66,0x33,0xFF}, {0x33,0x66,0x66,0xFF}, {0x33,0x66,0x99,0xFF}, {0x33,0x66,0xCC,0xFF}, {0x33,0x66,0xFF,0xFF}, + {0x33,0x99,0x00,0xFF}, {0x33,0x99,0x33,0xFF}, {0x33,0x99,0x66,0xFF}, {0x33,0x99,0x99,0xFF}, {0x33,0x99,0xCC,0xFF}, {0x33,0x99,0xFF,0xFF}, + {0x33,0xCC,0x00,0xFF}, {0x33,0xCC,0x33,0xFF}, {0x33,0xCC,0x66,0xFF}, {0x33,0xCC,0x99,0xFF}, {0x33,0xCC,0xCC,0xFF}, {0x33,0xCC,0xFF,0xFF}, + {0x33,0xFF,0x00,0xFF}, {0x33,0xFF,0x33,0xFF}, {0x33,0xFF,0x66,0xFF}, {0x33,0xFF,0x99,0xFF}, {0x33,0xFF,0xCC,0xFF}, {0x33,0xFF,0xFF,0xFF}, + {0x66,0x00,0x00,0xFF}, {0x66,0x00,0x33,0xFF}, {0x66,0x00,0x66,0xFF}, {0x66,0x00,0x99,0xFF}, {0x66,0x00,0xCC,0xFF}, {0x66,0x00,0xFF,0xFF}, + {0x66,0x33,0x00,0xFF}, {0x66,0x33,0x33,0xFF}, {0x66,0x33,0x66,0xFF}, {0x66,0x33,0x99,0xFF}, {0x66,0x33,0xCC,0xFF}, {0x66,0x33,0xFF,0xFF}, + {0x66,0x66,0x00,0xFF}, {0x66,0x66,0x33,0xFF}, {0x66,0x66,0x66,0xFF}, {0x66,0x66,0x99,0xFF}, {0x66,0x66,0xCC,0xFF}, {0x66,0x66,0xFF,0xFF}, + {0x66,0x99,0x00,0xFF}, {0x66,0x99,0x33,0xFF}, {0x66,0x99,0x66,0xFF}, {0x66,0x99,0x99,0xFF}, {0x66,0x99,0xCC,0xFF}, {0x66,0x99,0xFF,0xFF}, + {0x66,0xCC,0x00,0xFF}, {0x66,0xCC,0x33,0xFF}, {0x66,0xCC,0x66,0xFF}, {0x66,0xCC,0x99,0xFF}, {0x66,0xCC,0xCC,0xFF}, {0x66,0xCC,0xFF,0xFF}, + {0x66,0xFF,0x00,0xFF}, {0x66,0xFF,0x33,0xFF}, {0x66,0xFF,0x66,0xFF}, {0x66,0xFF,0x99,0xFF}, {0x66,0xFF,0xCC,0xFF}, {0x66,0xFF,0xFF,0xFF}, + {0x99,0x00,0x00,0xFF}, {0x99,0x00,0x33,0xFF}, {0x99,0x00,0x66,0xFF}, {0x99,0x00,0x99,0xFF}, {0x99,0x00,0xCC,0xFF}, {0x99,0x00,0xFF,0xFF}, + {0x99,0x33,0x00,0xFF}, {0x99,0x33,0x33,0xFF}, {0x99,0x33,0x66,0xFF}, {0x99,0x33,0x99,0xFF}, {0x99,0x33,0xCC,0xFF}, {0x99,0x33,0xFF,0xFF}, + {0x99,0x66,0x00,0xFF}, {0x99,0x66,0x33,0xFF}, {0x99,0x66,0x66,0xFF}, {0x99,0x66,0x99,0xFF}, {0x99,0x66,0xCC,0xFF}, {0x99,0x66,0xFF,0xFF}, + {0x99,0x99,0x00,0xFF}, {0x99,0x99,0x33,0xFF}, {0x99,0x99,0x66,0xFF}, {0x99,0x99,0x99,0xFF}, {0x99,0x99,0xCC,0xFF}, {0x99,0x99,0xFF,0xFF}, + {0x99,0xCC,0x00,0xFF}, {0x99,0xCC,0x33,0xFF}, {0x99,0xCC,0x66,0xFF}, {0x99,0xCC,0x99,0xFF}, {0x99,0xCC,0xCC,0xFF}, {0x99,0xCC,0xFF,0xFF}, + {0x99,0xFF,0x00,0xFF}, {0x99,0xFF,0x33,0xFF}, {0x99,0xFF,0x66,0xFF}, {0x99,0xFF,0x99,0xFF}, {0x99,0xFF,0xCC,0xFF}, {0x99,0xFF,0xFF,0xFF}, + {0xCC,0x00,0x00,0xFF}, {0xCC,0x00,0x33,0xFF}, {0xCC,0x00,0x66,0xFF}, {0xCC,0x00,0x99,0xFF}, {0xCC,0x00,0xCC,0xFF}, {0xCC,0x00,0xFF,0xFF}, + {0xCC,0x33,0x00,0xFF}, {0xCC,0x33,0x33,0xFF}, {0xCC,0x33,0x66,0xFF}, {0xCC,0x33,0x99,0xFF}, {0xCC,0x33,0xCC,0xFF}, {0xCC,0x33,0xFF,0xFF}, + {0xCC,0x66,0x00,0xFF}, {0xCC,0x66,0x33,0xFF}, {0xCC,0x66,0x66,0xFF}, {0xCC,0x66,0x99,0xFF}, {0xCC,0x66,0xCC,0xFF}, {0xCC,0x66,0xFF,0xFF}, + {0xCC,0x99,0x00,0xFF}, {0xCC,0x99,0x33,0xFF}, {0xCC,0x99,0x66,0xFF}, {0xCC,0x99,0x99,0xFF}, {0xCC,0x99,0xCC,0xFF}, {0xCC,0x99,0xFF,0xFF}, + {0xCC,0xCC,0x00,0xFF}, {0xCC,0xCC,0x33,0xFF}, {0xCC,0xCC,0x66,0xFF}, {0xCC,0xCC,0x99,0xFF}, {0xCC,0xCC,0xCC,0xFF}, {0xCC,0xCC,0xFF,0xFF}, + {0xCC,0xFF,0x00,0xFF}, {0xCC,0xFF,0x33,0xFF}, {0xCC,0xFF,0x66,0xFF}, {0xCC,0xFF,0x99,0xFF}, {0xCC,0xFF,0xCC,0xFF}, {0xCC,0xFF,0xFF,0xFF}, + {0xFF,0x00,0x00,0xFF}, {0xFF,0x00,0x33,0xFF}, {0xFF,0x00,0x66,0xFF}, {0xFF,0x00,0x99,0xFF}, {0xFF,0x00,0xCC,0xFF}, {0xFF,0x00,0xFF,0xFF}, + {0xFF,0x33,0x00,0xFF}, {0xFF,0x33,0x33,0xFF}, {0xFF,0x33,0x66,0xFF}, {0xFF,0x33,0x99,0xFF}, {0xFF,0x33,0xCC,0xFF}, {0xFF,0x33,0xFF,0xFF}, + {0xFF,0x66,0x00,0xFF}, {0xFF,0x66,0x33,0xFF}, {0xFF,0x66,0x66,0xFF}, {0xFF,0x66,0x99,0xFF}, {0xFF,0x66,0xCC,0xFF}, {0xFF,0x66,0xFF,0xFF}, + {0xFF,0x99,0x00,0xFF}, {0xFF,0x99,0x33,0xFF}, {0xFF,0x99,0x66,0xFF}, {0xFF,0x99,0x99,0xFF}, {0xFF,0x99,0xCC,0xFF}, {0xFF,0x99,0xFF,0xFF}, + {0xFF,0xCC,0x00,0xFF}, {0xFF,0xCC,0x33,0xFF}, {0xFF,0xCC,0x66,0xFF}, {0xFF,0xCC,0x99,0xFF}, {0xFF,0xCC,0xCC,0xFF}, {0xFF,0xCC,0xFF,0xFF}, + {0xFF,0xFF,0x00,0xFF}, {0xFF,0xFF,0x33,0xFF}, {0xFF,0xFF,0x66,0xFF}, {0xFF,0xFF,0x99,0xFF}, {0xFF,0xFF,0xCC,0xFF}, {0xFF,0xFF,0xFF,0xFF}, + + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, + {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, +}; + +#define sqr(a) (double)((a) * (a)) + +static int FindNearestWebColor(uint8_t r, uint8_t g, uint8_t b) { + int bestNdx = 0; + float bestDiff = sqrt(sqr(r - WebColorPalette[0].r) + sqr(g - WebColorPalette[0].g) + sqr(b - WebColorPalette[0].b)); + for (int i=1; i<216; i++) { + float thisDiff = sqrt(sqr(r - WebColorPalette[i].r) + sqr(g - WebColorPalette[i].g) + sqr(b - WebColorPalette[i].b)); + if (thisDiff < bestDiff) { + bestDiff = thisDiff; + bestNdx = i; + } + } + return bestNdx; +} + RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name) : GraphicsDisplay(name) @@ -2241,7 +2310,8 @@ } } -RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) + +RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP, uint8_t bitsPerPixel) { BITMAPFILEHEADER BMP_Header; BITMAPINFOHEADER BMP_Info; @@ -2249,33 +2319,49 @@ color_t * pixelBuffer = NULL; color_t * pixelBuffer2 = NULL; - INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP); + INFO("(%d,%d)-(%d,%d)x%d %s", x,y,w,h,bitsPerPixel,Name_BMP); if (x >= 0 && x < screenwidth && y >= 0 && y < screenheight && w > 0 && x + w <= screenwidth && h > 0 && y + h <= screenheight) { - BMP_Header.bfType = BF_TYPE; - BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Info); BMP_Header.bfReserved1 = 0; BMP_Header.bfReserved2 = 0; - BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); + switch (bitsPerPixel) { + case 24: + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); + BMP_Header.bfSize = (h * RoundUp(w * sizeof(RGBQUAD),4)) + BMP_Header.bfOffBits; + break; + case 8: + default: + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette); + INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits); + //if (BMP_Header.bfOffBits & 0x03) { + // BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03)); + //} + BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits; + break; + } + INFO("Offset to Bitstream %X", BMP_Header.bfOffBits); // Bytes in the line buffer - int lineBufSize = RoundUp(3 * w, 4); // ((24 * w + 7)/8); + int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4); INFO("LineBufSize: %d", lineBufSize); BMP_Info.biSize = sizeof(BMP_Info); BMP_Info.biWidth = w; BMP_Info.biHeight = h; BMP_Info.biPlanes = 1; - BMP_Info.biBitCount = 24; + BMP_Info.biBitCount = bitsPerPixel; BMP_Info.biCompression = BI_RGB; BMP_Info.biSizeImage = lineBufSize * h; BMP_Info.biXPelsPerMeter = 0; BMP_Info.biYPelsPerMeter = 0; - BMP_Info.biClrUsed = 0; - BMP_Info.biClrImportant = 0; + // for 24-bit, there is no palette, so these are zero + // for 8-bit, there can be up to 256 RGB values in the palette + + BMP_Info.biClrUsed = (bitsPerPixel == 24) ? 0 : sizeof(WebColorPalette)/sizeof(WebColorPalette[0]); // for 8b/pixel + BMP_Info.biClrImportant = BMP_Info.biClrUsed; // Allocate the memory we need to proceed lineBuffer = (uint8_t *)swMalloc(lineBufSize); @@ -2329,7 +2415,16 @@ HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); - + + if (bitsPerPixel != 24) { + HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); + fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image); + if (0 && sizeof(WebColorPalette) % 4) { + const uint8_t padd[] = { 0, 0, 0 }; + fwrite(&padd, sizeof(char), + (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4, Image); + } + } //color_t transparency = GetBackgroundTransparencyColor(); LayerMode_T ltpr0 = GetLayerMode(); @@ -2366,7 +2461,7 @@ } } INFO("Line: %3d", j); - HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t)); + //HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t)); // Convert the local buffer to RGBQUAD format int lb = 0; for (int i=0; i<w; i++) { @@ -2382,25 +2477,36 @@ case 2: // lighten-overlay (@TODO Not supported yet) case 6: // Floating Windows (@TODO not sure how to support) default: // Reserved... + //lineBuffer[lb++] = q0.rgbBlue; + //lineBuffer[lb++] = q0.rgbGreen; + //lineBuffer[lb++] = q0.rgbRed; + break; + case 3: // transparent mode (@TODO Read the background color register for transparent) + case 4: // boolean or + q0.rgbBlue = q0.rgbBlue | q1.rgbBlue; + q0.rgbGreen = q0.rgbGreen | q1.rgbGreen; + q0.rgbRed = q0.rgbRed | q1.rgbRed; + break; + case 5: // boolean AND + q0.rgbBlue = q0.rgbBlue & q1.rgbBlue; + q0.rgbGreen = q0.rgbGreen & q1.rgbGreen; + q0.rgbRed = q0.rgbRed & q1.rgbRed; + break; + } + switch (bitsPerPixel) { + case 24: lineBuffer[lb++] = q0.rgbBlue; lineBuffer[lb++] = q0.rgbGreen; lineBuffer[lb++] = q0.rgbRed; break; - case 3: // transparent mode (@TODO Read the background color register for transparent) - case 4: // boolean or - lineBuffer[lb++] = q0.rgbBlue | q1.rgbBlue; - lineBuffer[lb++] = q0.rgbGreen | q1.rgbGreen; - lineBuffer[lb++] = q0.rgbRed | q1.rgbRed; - break; - case 5: // boolean AND - lineBuffer[lb++] = q0.rgbBlue & q1.rgbBlue; - lineBuffer[lb++] = q0.rgbGreen & q1.rgbGreen; - lineBuffer[lb++] = q0.rgbRed & q1.rgbRed; + case 8: + default: + lineBuffer[lb++] = FindNearestWebColor(q0.rgbRed,q0.rgbGreen,q0.rgbBlue); break; } } //if (j == h - 1) { - HexDump("Line", lineBuffer, lineBufSize); + // HexDump("Line", lineBuffer, lineBufSize); //} // Write to disk fwrite(lineBuffer, sizeof(char), lineBufSize, Image);
--- a/RA8875.h Mon Feb 11 03:44:42 2019 +0000 +++ b/RA8875.h Wed Feb 13 04:20:12 2019 +0000 @@ -2674,10 +2674,12 @@ /// @param[in] y is the top edge of the region to capture /// @param[in] w is the width of the region to capture /// @param[in] h is the height of the region to capture. - /// @param[out] Name_BMP is the filename to write the image to. + /// @param[in] Name_BMP is the filename to write the image to. + /// @param[in] bitsPerPixel is optional, defaults to 24, and only + /// accepts the values 24, 8 /// @return success or error code. /// - RetCode_t PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP); + RetCode_t PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP, uint8_t bitsPerPixel = 24); /// This method captures the specified area as a 24-bit bitmap file