Fork of David Smart's RA8875 library
Fork of RA8875 by
Revision 31:c72e12cd5c67, committed 2014-01-20
- 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
--- /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 {