Fork of David Smart's RA8875 library for the purpose of adding touch screen support
Fork of RA8875 by
GraphicsDisplay.cpp
- Committer:
- WiredHome
- Date:
- 2014-01-23
- Revision:
- 34:c99ec28fac66
- Parent:
- 33:b6b710758ab3
- Child:
- 37:f19b7e7449dc
File content as of revision 34:c99ec28fac66:
/* mbed GraphicsDisplay Display Library Base Class * Copyright (c) 2007-2009 sford * Released under the MIT License: http://mbed.org/license/mit * * Derivative work by D.Smart 2014 */ #include "GraphicsDisplay.h" #include "Bitmap.h" // Defining USE_HW causes compilation of code that uses hardware drawing // provided by the super-class. #define USE_HW //#define DEBUG "GD" // ... // INFO("Stuff to show %d", var); // new-line is automatically appended // #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #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, c) #endif // #define LOCALFONT #ifdef LOCALFONT const unsigned char FONT8x8[97][8] = { 0x08, 0x08, 0x08, 0X00, 0X00, 0X00, 0X00, 0X00, // columns, rows, num_bytes_per_char 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // space 0x20 0x30, 0x78, 0x78, 0x30, 0x30, 0X00, 0x30, 0X00, // ! 0x6C, 0x6C, 0x6C, 0X00, 0X00, 0X00, 0X00, 0X00, // " 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0X00, // # 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0X00, // $ 0X00, 0x63, 0x66, 0x0C, 0x18, 0x33, 0x63, 0X00, // % 0x1C, 0x36, 0x1C, 0x3B, 0x6E, 0x66, 0x3B, 0X00, // & 0x30, 0x30, 0x60, 0X00, 0X00, 0X00, 0X00, 0X00, // ' 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0X00, // ( 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0X00, // ) 0X00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0X00, 0X00, // * 0X00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0X00, 0X00, // + 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0x30, // , 0X00, 0X00, 0X00, 0x7E, 0X00, 0X00, 0X00, 0X00, // - 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0X00, // . 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0X00, // / (forward slash) 0x3E, 0x63, 0x63, 0x6B, 0x63, 0x63, 0x3E, 0X00, // 0 0x30 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x7E, 0X00, // 1 0x3C, 0x66, 0x06, 0x1C, 0x30, 0x66, 0x7E, 0X00, // 2 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0X00, // 3 0x0E, 0x1E, 0x36, 0x66, 0x7F, 0x06, 0x0F, 0X00, // 4 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0X00, // 5 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0X00, // 6 0x7E, 0x66, 0x06, 0x0C, 0x18, 0x18, 0x18, 0X00, // 7 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0X00, // 8 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0X00, // 9 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0X00, // : 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0x30, // ; 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0X00, // < 0X00, 0X00, 0x7E, 0X00, 0X00, 0x7E, 0X00, 0X00, // = 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0X00, // > 0x3C, 0x66, 0x06, 0x0C, 0x18, 0X00, 0x18, 0X00, // ? 0x3E, 0x63, 0x6F, 0x69, 0x6F, 0x60, 0x3E, 0X00, // @ 0x40 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0X00, // A 0x7E, 0x33, 0x33, 0x3E, 0x33, 0x33, 0x7E, 0X00, // B 0x1E, 0x33, 0x60, 0x60, 0x60, 0x33, 0x1E, 0X00, // C 0x7C, 0x36, 0x33, 0x33, 0x33, 0x36, 0x7C, 0X00, // D 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x31, 0x7F, 0X00, // E 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x30, 0x78, 0X00, // F 0x1E, 0x33, 0x60, 0x60, 0x67, 0x33, 0x1F, 0X00, // G 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0X00, // H 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // I 0x0F, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0X00, // J 0x73, 0x33, 0x36, 0x3C, 0x36, 0x33, 0x73, 0X00, // K 0x78, 0x30, 0x30, 0x30, 0x31, 0x33, 0x7F, 0X00, // L 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0X00, // M 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63, 0X00, // N 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0X00, // O 0x7E, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0X00, // P 0x50 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x0E, 0X00, // Q 0x7E, 0x33, 0x33, 0x3E, 0x36, 0x33, 0x73, 0X00, // R 0x3C, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x3C, 0X00, // S 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // T 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0X00, // U 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // V 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0X00, // W 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0X00, // X 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0X00, // Y 0x7F, 0x63, 0x46, 0x0C, 0x19, 0x33, 0x7F, 0X00, // Z 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0X00, // [ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0X00, // \ (back slash) 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0X00, // ] 0x08, 0x1C, 0x36, 0x63, 0X00, 0X00, 0X00, 0X00, // ^ 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0xFF, // _ 0x18, 0x18, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, // ` 0x60 0X00, 0X00, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0X00, // a 0x70, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0X00, // b 0X00, 0X00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0X00, // c 0x0E, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3B, 0X00, // d 0X00, 0X00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0X00, // e 0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0X00, // f 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x7C, // g 0x70, 0x30, 0x36, 0x3B, 0x33, 0x33, 0x73, 0X00, // h 0x18, 0X00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0X00, // i 0x06, 0X00, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, // j 0x70, 0x30, 0x33, 0x36, 0x3C, 0x36, 0x73, 0X00, // k 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // l 0X00, 0X00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0X00, // m 0X00, 0X00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0X00, // n 0X00, 0X00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0X00, // o 0X00, 0X00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78, // p 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F, // q 0X00, 0X00, 0x6E, 0x3B, 0x33, 0x30, 0x78, 0X00, // r 0X00, 0X00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0X00, // s 0x08, 0x18, 0x3E, 0x18, 0x18, 0x1A, 0x0C, 0X00, // t 0X00, 0X00, 0x66, 0x66, 0x66, 0x66, 0x3B, 0X00, // u 0X00, 0X00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // v 0X00, 0X00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0X00, // w 0X00, 0X00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0X00, // x 0X00, 0X00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x7C, // y 0X00, 0X00, 0x7E, 0x4C, 0x18, 0x32, 0x7E, 0X00, // z 0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0X00, // { 0x0C, 0x0C, 0x0C, 0X00, 0x0C, 0x0C, 0x0C, 0X00, // | 0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0X00, // } 0x3B, 0x6E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // ~ 0x1C, 0x36, 0x36, 0x1C, 0X00, 0X00, 0X00, 0X00 // DEL }; #endif // LOCALFONT GraphicsDisplay::GraphicsDisplay(const char *name) : TextDisplay(name) { font = NULL; //foreground(0xFFFF); //background(0x0000); } RetCode_t GraphicsDisplay::set_font(const unsigned char * _font) { font = _font; INFO("set_font(%lu) %lu", _font, font); return noerror; // trusting them, but it might be good to put some checks in here... } #ifdef LOCALFONT int GraphicsDisplay::character(int x, int y, int value) { INFO("character(%d,%d,%c)", x, t, value); if (value <= 0x1F && value >= 7F) return 0; return blitbit(x, y, FONT8X8[0][0], FONT8X8[0][1], (char *)&(FONT8x8[value - 0x1F][0])); } #else int GraphicsDisplay::character(int x, int y, int c) { unsigned int offset; const unsigned char * charRecord; if (c <= 0x1F || c >= 0x7F) return 0; offset = font[0]; // bytes / char charRecord = &font[((c - ' ') * offset) + 4]; // start of char bitmap return fontblit(x, y, font, charRecord); } #endif RetCode_t GraphicsDisplay::window(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { // current pixel location _x = x; _y = y; // window settings _x1 = x; _x2 = x + w - 1; _y1 = y; _y2 = y + h - 1; return noerror; } void GraphicsDisplay::WindowMax(void) { window(0,0, width(),height()); } RetCode_t GraphicsDisplay::putp(color_t color) { // put pixel at current pixel location pixel(_x, _y, color); // update pixel location based on window settings _x++; if(_x > _x2) { _x = _x1; _y++; if(_y > _y2) { _y = _y1; } } return noerror; } void GraphicsDisplay::fill(int x, int y, int w, int h, color_t color) { #ifdef USE_HW fillrect(x,y, x+w, y+h, color); #else window(x, y, w, h); for(int i=0; i<w*h; i++) { putp(color); } #endif } RetCode_t GraphicsDisplay::cls() { fill(0, 0, width(), height(), _background); return noerror; } void GraphicsDisplay::blit(int x, int y, int w, int h, const int * color) { window(x, y, w, h); for (int i=0; i<w*h; i++) { putp(color[i]); } } int GraphicsDisplay::blitbit(int x, int y, int w, int h, const char * color) { _foreground = 0xFFFF; INFO("blitbit(%d,%d, %d,%d, %02X) [%04X,%04X]", x,y, w,h, *color, _foreground, _background); INFO("%lu %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", color, color[0], color[1], color[2], color[3], color[4], color[5], color[6], color[7], color[8], color[9], color[10], color[11], color[12], color[13], color[14], color[15]); window(x, y, w, h); for (int i = 0; i < w*h; i++) { char byte = color[i >> 3]; int offset = i & 0x7; if (offset == 0) INFO(" %2d = %02X", i>>3, byte); int c = ((byte << offset) & 0x80) ? _foreground : _background; putp(c); } return w; } int GraphicsDisplay::fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar) { _foreground = 0xFFFF; //int fontWidth = font[1]; // get hor size of font int fontHeight = font[2]; // get vert size of font int bytesPerLine = font[3]; // bytes per line int charWidth = fontChar[0]; // width of this character int px, py; window(x, y, charWidth, fontHeight); for (py = 0; py < fontHeight; py++) { int bitmask = 1 << (py & 7); for (px = 0; px < charWidth; px++) { int offset = (py / 8) + px * bytesPerLine; unsigned char byte = fontChar[offset + 1]; // skip the char's # bits wide value int c = (byte & bitmask) ? _foreground : _background; putp(c); } } 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 GraphicsDisplay::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::RenderBitmapFile(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 BITMAPFILEHEADER BMP_Header; BITMAPINFOHEADER BMP_Info; RGBQUAD * colorPalette = NULL; int colorCount; uint8_t * lineBuffer = NULL; uint16_t BPP_t; uint32_t PixelWidth, PixelHeight; uint32_t start_data; unsigned int i, offset; int padd,j; INFO("Opening {%s}", Name_BMP); FILE *Image = fopen(Name_BMP, "rb"); 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) { fclose(Image); return(not_bmp_format); } 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 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel fclose(Image); return(not_supported_format); } 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; 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); } int lineBufSize = ((BPP_t * PixelWidth + 7)/8); //INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize); lineBuffer = (uint8_t *)malloc(lineBufSize); if (lineBuffer == NULL) { free(colorPalette); fclose(Image); return(not_enough_ram); } // the Raw Data records are padded to a multiple of 4 bytes int recordSize = 2; if (BPP_t == 4) { recordSize = 1; } else if (BPP_t == 8) { recordSize = 1; } else if (BPP_t == 16) { recordSize = 2; } else if (BPP_t == 24) { recordSize = 3; } padd = -1; do { padd++; } while ((PixelWidth * recordSize + padd) % 4 != 0); // Define window for top to bottom and left to right so writing auto-wraps window(x,y, PixelWidth,PixelHeight); SetGraphicsCursor(x, y); _StartGraphicsStream(); start_data = BMP_Header.bfOffBits; HexDump("Raw Data", (uint8_t *)&start_data, 32); //bool tag = true; //INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd); for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up offset = start_data + j * (lineBufSize + padd); // start of line fseek(Image, offset, SEEK_SET); fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! //INFO("offset: %6X", offset); //if (tag) // 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; putp(RGBQuadToRGB16(colorPalette, dPix)); } else if (BPP_t == 8) { putp(RGBQuadToRGB16(colorPalette, lineBuffer[i])); } else if (BPP_t == 16) { putp(lineBuffer[i]); } else if (BPP_t == 24) { color_t color; // BGR color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]); //if (tag) // INFO("color[%2d]: RGB(%02X,%02X,%02X) => %04X", // i, lineBuffer[i*2], lineBuffer[i*3+1], lineBuffer[i*3+0], color); color = (color >> 8) | (color << 8); putp(color); } } //tag = false; } free(lineBuffer); free(colorPalette); fclose(Image); _EndGraphicsStream(); WindowMax(); return (noerror); } int GraphicsDisplay::columns() { return width() / 8; } int GraphicsDisplay::rows() { return height() / 8; }