Fork of David Smart's RA8875 library for the purpose of adding touch screen support

Fork of RA8875 by David Smart

Revision:
31:c72e12cd5c67
Parent:
29:422616aa04bd
Child:
32:0e4f2ae512e2
--- a/GraphicsDisplay.cpp	Sun Jan 19 04:42:25 2014 +0000
+++ b/GraphicsDisplay.cpp	Mon Jan 20 19:19:48 2014 +0000
@@ -4,6 +4,7 @@
  */
 
 #include "GraphicsDisplay.h"
+#include "Bitmap.h"
 
 #define DEBUG "GD"
 // ...
@@ -13,10 +14,31 @@
 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
 #define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+void HexDump(char * title, uint8_t * p, int count)
+{
+    int i;
+    char buf[100] = "0000: ";
+    
+    if (*title)
+        INFO("%s", title);
+    for (i=0; i<count; ) {
+        sprintf(buf + strlen(buf), "%02X ", *(p+i));
+        if ((++i & 0x0F) == 0x00) {
+            INFO("%s", buf);
+            if (i < count)
+                sprintf(buf, "%04X: ", i);
+            else
+                buf[0] = '\0';
+        }
+    }
+    if (strlen(buf))
+        INFO("%s", buf);
+}
 #else
 #define INFO(x, ...)
 #define WARN(x, ...)
 #define ERR(x, ...)
+#define HexDump(a, b)
 #endif
 
 // #define LOCALFONT
@@ -174,7 +196,12 @@
     _y2 = y + h - 1;
 }
 
-void GraphicsDisplay::putp(int colour)
+void GraphicsDisplay::WindowMax(void)
+{
+    window(0,0, width(),height());
+}
+
+void GraphicsDisplay::putp(color_t colour)
 {
     // put pixel at current pixel location
     pixel(_x, _y, colour);
@@ -189,7 +216,7 @@
     }
 }
 
-void GraphicsDisplay::fill(int x, int y, int w, int h, int colour)
+void GraphicsDisplay::fill(int x, int y, int w, int h, color_t colour)
 {
     window(x, y, w, h);
     for(int i=0; i<w*h; i++) {
@@ -206,7 +233,7 @@
 void GraphicsDisplay::blit(int x, int y, int w, int h, const int * colour)
 {
     window(x, y, w, h);
-    for(int i=0; i<w*h; i++) {
+    for (int i=0; i<w*h; i++) {
         putp(colour[i]);
     }
 }
@@ -227,7 +254,6 @@
             INFO(" %2d = %02X", i>>3, byte);
         int c = ((byte << offset) & 0x80) ? _foreground : _background;
         putp(c);
-        //wait_ms(100);
     }
     return w;
 }
@@ -256,8 +282,155 @@
     return charWidth;
 }
 
+// BMP Color Palette is BGRx
+//      BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
+// RGB16 is
+//      RRRR RGGG GGGB BBBB
+// swap to little endian
+//      GGGB BBBB RRRR RGGG
+color_t RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i)
+{
+    color_t c;
+ 
+    c  = ((colorPalette[i].rgbBlue  >> 3) <<  0);
+    c |= ((colorPalette[i].rgbGreen >> 2) <<  5);
+    c |= ((colorPalette[i].rgbRed   >> 3) << 11);
+    c = (c >> 8) | (c << 8);
+    //INFO("B %02X G %02X R %02X c %04X", colorPalette[i].rgbBlue, colorPalette[i].rgbGreen, 
+    //    colorPalette[i].rgbRed, c);
+    return c;
+}
 
 
+RetCode_t GraphicsDisplay::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
+{
+    #define OffsetPixelWidth    18
+    #define OffsetPixelHeight   22
+    #define OffsetFileSize      34
+    #define OffsetPixData       10
+    #define OffsetBPP           28
+
+    char filename[50];
+    BITMAPFILEHEADER BMP_Header;
+    BITMAPINFOHEADER BMP_Info;
+    RGBQUAD * colorPalette = NULL;
+    int colorCount;
+    char * lineBuffer = NULL;
+    
+    uint16_t BPP_t;
+    uint32_t PixelWidth, PixelHeight;
+    uint32_t start_data;
+    unsigned int    i, offset;
+    int padd,j;
+
+    // get the filename
+    LocalFileSystem local("local");
+    sprintf(filename,"/local/%s", Name_BMP);
+    INFO("Opening {%s}", filename);
+    FILE *Image = fopen(filename, "rb");  // open the bmp file
+    if (!Image) {
+        return(file_not_found);
+    }
+
+    fread(&BMP_Header, 1, sizeof(BMP_Header), Image);      // get the BMP Header
+    INFO("bfType %04X", BMP_Header.bfType);
+    //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
+    if (BMP_Header.bfType != BF_TYPE) { // BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
+        fclose(Image);
+        return(not_bmp_format);     // error no BMP file
+    }
+
+    fread(&BMP_Info, 1, sizeof(BMP_Info), Image);
+    //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+    BPP_t = BMP_Info.biBitCount;
+    INFO("biBitCount %04X", BPP_t);
+    if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16) {   // Support 4, 8, 16-bits per pixel
+        fclose(Image);
+        return(not_supported_format);
+    }
+
+    //PixelHeight = BMP_Header[OffsetPixelHeight] + (BMP_Header[OffsetPixelHeight + 1] << 8) + (BMP_Header[OffsetPixelHeight + 2] << 16) + (BMP_Header[OffsetPixelHeight + 3] << 24);
+    //PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
+    PixelHeight = BMP_Info.biHeight;
+    PixelWidth = BMP_Info.biWidth;
+    if (PixelHeight > height() + y || PixelWidth > width() + x) {
+        fclose(Image);
+        return(image_too_big);
+    }
+    INFO("(%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight);
+
+    if (BMP_Info.biBitCount <= 8) {
+        int paletteSize;
+        // Read the color palette
+        colorCount = 1 << BMP_Info.biBitCount;
+        paletteSize = sizeof(RGBQUAD) * colorCount;
+        //INFO("colors: %d, paletteSize: %d", colorCount, paletteSize);
+        colorPalette = (RGBQUAD *)malloc(paletteSize);
+        if (colorPalette == NULL) {
+            fclose(Image);
+            return(not_enough_ram);
+        }
+        fread(colorPalette, 1, paletteSize, Image);
+        HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
+    } else {
+        ERR("Bits per pixel > 8 [%d]", BMP_Info.biBitCount);
+    }
+
+    //start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
+    start_data = BMP_Header.bfOffBits;
+
+    //HexDump("Raw Data", (uint8_t *)&start_data, 32);
+    int lineBufSize = ((BPP_t * PixelWidth + 31)/32)*4;
+    //INFO("lineBufSize = %d", lineBufSize);
+    lineBuffer = (char *)malloc(lineBufSize);
+    if (lineBuffer == NULL) {
+        free(colorPalette);
+        fclose(Image);
+        return(not_enough_ram);
+    }
+
+    // the bmp lines are padded to multiple of 4 bytes
+    padd = -1;
+    do {
+        padd++;
+    } while ((PixelWidth * sizeof(color_t) + padd) % 4 != 0);
+
+    // Define window for top to bottom and left to right
+    window(x,y, PixelWidth,PixelHeight);
+    //INFO("(%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight);
+    for (j = PixelHeight - 1; j >= 0; j--) {               //Lines bottom up
+        //INFO("line %d", j);
+        offset = start_data + j * (lineBufSize + padd);   // start of line
+        fseek(Image, offset, SEEK_SET);
+        fread(lineBuffer, 1, lineBufSize, Image);       // read a line - slow !
+        //HexDump("Line", (uint8_t *)lineBuffer, lineBufSize);
+        for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
+            if (BPP_t == 4) {
+                uint8_t dPix = lineBuffer[i/2];
+                if ((i & 1) == 0)
+                    dPix >>= 4;
+                dPix &= 0x0F;
+                color_t color;
+                color = RGBQuadToRGB16(colorPalette, dPix);
+                putp(color);
+            } else if (BPP_t == 8) {
+                color_t color;
+                color = RGBQuadToRGB16(colorPalette, lineBuffer[i]);
+                putp(color);
+            } else if (BPP_t == 16) {
+                putp(lineBuffer[i] & 0xFF);
+                putp(lineBuffer[i] >> 8);
+            }
+        }
+    }
+    free(lineBuffer);
+    free(colorPalette);
+    fclose(Image);
+    //INFO("Freed and closed");
+    WindowMax();
+    return(noerror);
+}
+
 int GraphicsDisplay::columns()
 {
     return width() / 8;