Fork of David Smart's RA8875 library

Fork of RA8875 by David Smart

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Mon Jan 20 19:19:48 2014 +0000
Parent:
30:e0f2da88bdf6
Child:
32:0e4f2ae512e2
Commit message:
Support for Bitmap graphics (tested 4-bit and 8-bit formats, have not tested 1-bit or 24-bit).

Changed in this revision

Bitmap.h Show annotated file Show diff for this revision Revisions of this file
DisplayDefs.h Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplay.h Show annotated file Show diff for this revision Revisions of this file
RA8875.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875.h Show annotated file Show diff for this revision Revisions of this file
TextDisplay.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bitmap.h	Mon Jan 20 19:19:48 2014 +0000
@@ -0,0 +1,83 @@
+//
+// Windows BMP file definitions.
+//
+// Adapted from code written by Michael Sweet from Paul Bourke's
+// web site: http://paulbourke.net/dataformats/bmp/
+//
+
+#ifndef _BITMAP_H_
+#define _BITMAP_H_
+
+#include <mbed.h>
+
+// BITMAPFILEHEADER
+// BITMAPINFOHEADER
+// Optional Palette
+// Raw Data
+
+//
+// Bitmap file data structures
+//
+#pragma push
+#pragma pack(2)
+
+typedef struct                 /**** BMP file header structure ****/
+    {
+    uint16_t    bfType;           /* Magic number for file */
+    uint32_t    bfSize;           /* Size of file */
+    uint16_t    bfReserved1;      /* Reserved */
+    uint16_t    bfReserved2;      /* ... */
+    uint32_t    bfOffBits;        /* Offset to bitmap data */
+    } BITMAPFILEHEADER;
+
+#define BF_TYPE 0x4D42            /* "MB" */
+
+typedef struct                    /**** BMP file info structure ****/
+    {
+    uint32_t    biSize;           /* Size of info header */
+    uint32_t    biWidth;          /* Width of image */
+    uint32_t    biHeight;         /* Height of image */
+    uint16_t    biPlanes;         /* Number of color planes */
+    uint16_t    biBitCount;       /* Number of bits per pixel */
+    uint32_t    biCompression;    /* Type of compression to use */
+    uint32_t    biSizeImage;      /* Size of image data */
+    int32_t     biXPelsPerMeter;  /* X pixels per meter */
+    int32_t     biYPelsPerMeter;  /* Y pixels per meter */
+    uint32_t    biClrUsed;        /* Number of colors used */
+    uint32_t    biClrImportant;   /* Number of important colors */
+    } BITMAPINFOHEADER;
+#pragma pop
+
+/*
+ * Constants for the biCompression field...
+ */
+
+#  define BI_RGB       0             /* No compression - straight BGR data */
+#  define BI_RLE8      1             /* 8-bit run-length compression */
+#  define BI_RLE4      2             /* 4-bit run-length compression */
+#  define BI_BITFIELDS 3             /* RGB bitmap with RGB masks */
+
+typedef struct                       /**** Colormap entry structure ****/
+    {
+    uint8_t  rgbBlue;          /* Blue value */
+    uint8_t  rgbGreen;         /* Green value */
+    uint8_t  rgbRed;           /* Red value */
+    uint8_t  rgbReserved;      /* Reserved */
+    } RGBQUAD;
+
+typedef struct                       /**** Bitmap information structure ****/
+    {
+    BITMAPINFOHEADER bmiHeader;      /* Image header */
+    RGBQUAD          bmiColors[256]; /* Image colormap */
+    } BITMAPINFO;
+
+
+/*
+ * Prototypes...
+ */
+
+//extern GLubyte *LoadDIBitmap(const char *filename, BITMAPINFO **info);
+//extern int32_t    SaveDIBitmap(const char *filename, BITMAPINFO *info,
+//                            GLubyte *bits);
+
+#endif // _BITMAP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DisplayDefs.h	Mon Jan 20 19:19:48 2014 +0000
@@ -0,0 +1,18 @@
+#ifndef DISPLAYDEFS_H
+#define DISPLAYDEFS_H
+
+typedef uint16_t color_t;
+
+/// return values from functions
+typedef enum
+{
+    noerror,                ///< no errors, command completed successfully
+    bad_parameter,          ///< one or more parameters are invalid
+    file_not_found,         ///< specified file could not be found
+    not_bmp_format,         ///< file is a not bmp file
+    not_supported_format,   ///< file format is not yet supported
+    image_too_big,          ///< image is too large for the screen
+    not_enough_ram,         ///< could not allocate ram for scanline
+} RetCode_t;
+
+#endif // DISPLAYDEFS_H
--- 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;
--- a/GraphicsDisplay.h	Sun Jan 19 04:42:25 2014 +0000
+++ b/GraphicsDisplay.h	Mon Jan 20 19:19:48 2014 +0000
@@ -27,10 +27,11 @@
     virtual int height() = 0;
         
     virtual void window(unsigned int x,unsigned int y,unsigned int w,unsigned int h);
-    virtual void putp(int colour);
+    virtual void WindowMax(void);
+    virtual void putp(color_t colour);
     
     virtual RetCode_t cls();
-    virtual void fill(int x, int y, int w, int h, int colour);
+    virtual void fill(int x, int y, int w, int h, color_t colour);
     virtual void blit(int x, int y, int w, int h, const int * colour);    
     
     virtual int blitbit(int x, int y, int w, int h, const char * colour);
@@ -50,6 +51,22 @@
     ///
     virtual int fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar);
     
+    /// This method reads a disk file that is in bitmap format and 
+    /// puts it on the screen.
+    ///
+    /// @note This only reads 16-bit bitmap format.
+    /// @note This is a slow operation, partially due to the use of
+    ///         the local file system, and partially because bmp files
+    ///         are stored from the bottom up, and the memory is written
+    ///         from the top down.
+    ///
+    /// @param x is the horizontal pixel coordinate
+    /// @param y is the vertical pixel coordinate
+    /// @param Name_BMP is the filename on the local file system.
+    /// @returns success or error code.
+    ///
+    RetCode_t BMP_16(unsigned int x, unsigned int y, const char *Name_BMP);
+    
     /// prints one character at the specified coordinates.
     ///
     /// This will print the character at the specified pixel coordinates.
--- a/RA8875.cpp	Sun Jan 19 04:42:25 2014 +0000
+++ b/RA8875.cpp	Mon Jan 20 19:19:48 2014 +0000
@@ -736,7 +736,6 @@
     return ret;
 }
 
-
 RetCode_t RA8875::frequency(unsigned long Hz)
 {
     spi.frequency(Hz);
--- a/RA8875.h	Sun Jan 19 04:42:25 2014 +0000
+++ b/RA8875.h	Mon Jan 20 19:19:48 2014 +0000
@@ -87,9 +87,13 @@
 /// of column and row, which is measured in character positions (and dependent
 /// on the font size), and other text APIs permit pixel level positioning.
 ///
+/// @todo Bitmap support.
+/// @todo Bitmap support could be sped up significantly using more hw features 
+///         (e.g. graphics cursor to avoid setting x,y coords for every pixel)
+/// @todo Add Scroll support for text.
 /// @todo Add 2-Layer support.
+/// @todo Improve sync between internal and externa font support - cursor, window, scroll.
 /// @todo Find out why it can't shift frequency after constructor runs.
-/// @todo Bitmap support.
 /// @todo Add Hardware reset signal.
 /// @todo Add Touch Screen support.
 /// @todo Add Keypad Support.
@@ -101,24 +105,24 @@
     /// font type selection.
     typedef enum
     {
-        ISO8859_1,
-        ISO8859_2,
-        ISO8859_3,
-        ISO8859_4
+        ISO8859_1,      ///< ISO8859-1 font
+        ISO8859_2,      ///< ISO8859-2 font
+        ISO8859_3,      ///< ISO8859-3 font
+        ISO8859_4       ///< ISO8859-4 font
     } font_t;
     
     /// font rotation selection
     typedef enum
     {
-        normal,
-        rotated
+        normal,         ///< normal orientation
+        rotated         ///< rotated orientation
     } font_angle_t;
     
     /// alignment  
     typedef enum
     {
-        align_none,
-        align_full
+        align_none,     ///< align - none
+        align_full      ///< align - full
     } alignment_t;    
     
     /// Scale factor - 1, 2, 3 4
@@ -130,8 +134,8 @@
     /// Clear screen region
     typedef enum
     {
-        FULLWINDOW,
-        ACTIVEWINDOW
+        FULLWINDOW,     ///< Full screen
+        ACTIVEWINDOW    ///< active window/region
     } Region_t;
     
     /// Constructor for a display based on the RAiO RA8875 
--- a/TextDisplay.h	Sun Jan 19 04:42:25 2014 +0000
+++ b/TextDisplay.h	Mon Jan 20 19:19:48 2014 +0000
@@ -18,14 +18,7 @@
 
 #include "mbed.h"
 
-typedef uint16_t color_t;
-
-/// return values from functions
-typedef enum
-{
-    noerror,
-    bad_parameter
-} RetCode_t;
+#include "DisplayDefs.h"
 
 class TextDisplay : public Stream
 {