LCD LIB
Fork of RA8875 by
Revision 96:40b74dd3695b, committed 2015-11-28
- Comitter:
- WiredHome
- Date:
- Sat Nov 28 15:39:44 2015 +0000
- Parent:
- 95:ef538bd687c0
- Child:
- 97:03c509c3db18
- Child:
- 98:ecebed9b80b2
- Commit message:
- Changes for the print screen function to use callbacks.
Changed in this revision
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 |
--- a/RA8875.cpp Tue Jul 07 17:05:59 2015 +0000 +++ b/RA8875.cpp Sat Nov 28 15:39:44 2015 +0000 @@ -97,6 +97,9 @@ , cs(csel) , res(reset) { + c_callback = NULL; + obj_callback = NULL; + method_callback = NULL; } //RA8875::~RA8875() @@ -1587,9 +1590,205 @@ RetCode_t RA8875::PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) { (void)layer; + + // AttachPrintHandler(this, RA8875::_printCallback); + // return PrintScreen(x,y,w,h); return PrintScreen(x, y, w, h, Name_BMP); } +RetCode_t RA8875::_printCallback(RA8875::filecmd_t cmd, uint8_t * buffer, uint16_t size) +{ + HexDump("CB", buffer, size); + switch(cmd) { + case RA8875::OPEN: + //pc.printf("About to write %lu bytes\r\n", *(uint32_t *)buffer); + _printFH = fopen("file.bmp", "w+b"); + if (_printFH == 0) + return file_not_found; + break; + case RA8875::WRITE: + //pc.printf(" Write %4u bytes\r\n", size); + fwrite(buffer, 1, size, _printFH); + break; + case RA8875::CLOSE: + //pc.printf(" close\r\n"); + fclose(_printFH); + _printFH = 0; + break; + default: + //pc.printf("Unexpected callback %d\r\n", cmd); + return file_not_found; + //break; + } + return noerror; +} + +RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h) +{ + BITMAPFILEHEADER BMP_Header; + BITMAPINFOHEADER BMP_Info; + uint8_t * lineBuffer = NULL; + color_t * pixelBuffer = NULL; + color_t * pixelBuffer2 = NULL; + + INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP); + if (x >= 0 && x < width() + && y >= 0 && y < height() + && w > 0 && x + w <= width() + && h > 0 && y + h <= height()) { + + BMP_Header.bfType = BF_TYPE; + BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Header); + BMP_Header.bfReserved1 = 0; + BMP_Header.bfReserved2 = 0; + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Header); + + BMP_Info.biSize = sizeof(BMP_Info); + BMP_Info.biWidth = w; + BMP_Info.biHeight = h; + BMP_Info.biPlanes = 1; + BMP_Info.biBitCount = 24; + BMP_Info.biCompression = BI_RGB; + BMP_Info.biSizeImage = 0; + BMP_Info.biXPelsPerMeter = 0; + BMP_Info.biYPelsPerMeter = 0; + BMP_Info.biClrUsed = 0; + BMP_Info.biClrImportant = 0; + + // Allocate the memory we need to proceed + int lineBufSize = ((24 * w + 7)/8); + lineBuffer = (uint8_t *)malloc(lineBufSize); + if (lineBuffer == NULL) { + ERR("Not enough RAM for PrintScreen lineBuffer"); + return(not_enough_ram); + } + + #define DOUBLEBUF /* one larger buffer instead of two */ + + #ifdef DOUBLEBUF + // In the "#else", pixelBuffer2 malloc returns a value, + // but is actually causing a failure later. + // This test helps determine if it is truly out of memory, + // or if malloc is broken. + pixelBuffer = (color_t *)malloc(2 * w * sizeof(color_t)); + pixelBuffer2 = pixelBuffer + (w * sizeof(color_t)); + #else + pixelBuffer = (color_t *)malloc(w * sizeof(color_t)); + pixelBuffer2 = (color_t *)malloc(w * sizeof(color_t)); + #endif + if (pixelBuffer == NULL || pixelBuffer2 == NULL) { + ERR("Not enough RAM for pixelBuffer"); + #ifndef DOUBLEBUF + if (pixelBuffer2) + free(pixelBuffer2); + #endif + if (pixelBuffer) + free(pixelBuffer); + free(lineBuffer); + if (pixelBuffer) + free(pixelBuffer); + return(not_enough_ram); + } + + // Get the file primed... + privateCallback(OPEN, (uint8_t *)&BMP_Header.bfSize, 4); + + // Be optimistic - don't check for errors. + HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + //fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); + privateCallback(WRITE, (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + + HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + //fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); + privateCallback(WRITE, (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + + //color_t transparency = GetBackgroundTransparencyColor(); + LayerMode_T ltpr0 = GetLayerMode(); + + uint16_t prevLayer = GetDrawingLayer(); + // If only one of the layers is visible, select that layer + switch(ltpr0) { + case ShowLayer0: + SelectDrawingLayer(0); + break; + case ShowLayer1: + SelectDrawingLayer(1); + break; + default: + break; + } + + // Read the display from the last line toward the top + // so we can write the file in one pass. + for (int j = h - 1; j >= 0; j--) { + if (ltpr0 >= 2) // Need to combine the layers... + SelectDrawingLayer(0); // so read layer 0 first + // Read one line of pixels to a local buffer + if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { + ERR("getPixelStream error, and no recovery handler..."); + } + if (ltpr0 >= 2) { // Need to combine the layers... + SelectDrawingLayer(1); // so read layer 1 next + if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) { + ERR("getPixelStream error, and no recovery handler..."); + } + } + INFO("1st Color: %04X", pixelBuffer[0]); + HexDump("Raster", (uint8_t *)pixelBuffer, w); + // Convert the local buffer to RGBQUAD format + int lb = 0; + for (int i=0; i<w; i++) { + RGBQUAD q0 = RGB16ToRGBQuad(pixelBuffer[x+i]); // Scale to 24-bits + RGBQUAD q1 = RGB16ToRGBQuad(pixelBuffer2[x+i]); // Scale to 24-bits + switch (ltpr0) { + case 0: + case 1: + 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 + 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; + break; + } + } + if (j == h - 1) { + HexDump("Line", lineBuffer, lineBufSize); + } + // Write to disk + //fwrite(lineBuffer, sizeof(char), lb, Image); + privateCallback(WRITE, (uint8_t *)lineBuffer, lb); + } + SelectDrawingLayer(prevLayer); + //fclose(Image); + privateCallback(CLOSE, NULL, 0); + + #ifndef DOUBLEBUF + if (pixelBuffer2) + free(pixelBuffer2); + #endif + if (pixelBuffer) + free(pixelBuffer); + free(lineBuffer); + if (pixelBuffer) + free(pixelBuffer); + INFO("Image closed"); + return noerror; + } else { + return bad_parameter; + } +} RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) {
--- a/RA8875.h Tue Jul 07 17:05:59 2015 +0000 +++ b/RA8875.h Sat Nov 28 15:39:44 2015 +0000 @@ -104,6 +104,7 @@ //namespace SW_graphics //{ +class FPointerDummy; // used by the callback methods. /// This is a graphics library for the Raio RA8875 Display Controller chip /// attached to a 4-wire SPI interface. @@ -219,6 +220,49 @@ TP_Auto, ///< Auto touch detection mode TP_Manual, ///< Manual touch detection mode } tpmode_t; + + /// printscreen callback commands + typedef enum + { + OPEN, ///< command to open the file. cast uint32_t * to the buffer to get the total size to be written. + WRITE, ///< command to write some data, buffer points to the data and the size is in bytes. + CLOSE, ///< command to close the file + } filecmd_t; + + /// print screen callback + /// + /// The special form of the print screen will pass one blob at a time + /// to the callback. There are basic command declaring that the stream + /// can be opened, a block written, and the stream closed. There is + /// also a command to communicate the total size being delivered. + /// + /// @code + /// lcd.PrintScreen(x,y,w,h,callback); + /// ... + /// void callback(filecmd_t cmd, uint8_t * buffer, uint16_t size) { + /// switch(cmd) { + /// case OPEN: + /// pc.printf("About to write %u bytes\r\n", *(uint32_t *)buffer); + /// fh = fopen("file.bmp", "w+b"); + /// break; + /// case WRITE: + /// fwrite(buffer, size, fh); + /// break; + /// case CLOSE: + /// fclose(fh); + /// break; + /// default: + /// pc.printf("Unexpected callback %d\r\n", cmd); + /// break; + /// } + /// } + /// @endcode + /// + /// @param cmd is the command to execute. @see filecmd_t. + /// @param buffer is a pointer to the buffer being passed. + /// @param size is the number of bytes in the buffer. + /// + typedef RetCode_t (* PrintCallback_T)(filecmd_t cmd, uint8_t * buffer, uint16_t size); /// Constructor for a display based on the RAiO RA8875 /// display controller. @@ -1812,6 +1856,51 @@ /// RetCode_t PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP); + /// This method captures the specified area as a 24-bit bitmap file + /// and delivers it to the previously attached callback. + /// + /// Even though this is a 16-bit display, the stored image is in + /// 24-bit format. + /// + /// This method will interrogate the current display setting and + /// create a bitmap based on those settings. For instance, if + /// only layer 1 is visible, then the bitmap is only layer 1. However, + /// if there is some other operation in effect (transparent mode), it + /// will return the blended image. + /// + /// @param[in] x is the left edge of the region to capture + /// @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. + /// @return success or error code. + /// + RetCode_t PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h); + + /// PrintScreen callback registration. + /// + /// This method attaches a simple c-compatible callback of type PrintCallback_T. + /// Then, the PrintScreen(x,y,w,h) method is called. Each chunk of data in the + /// BMP file to be created is passed to this callback. + /// + /// @param callback is the callback function. + /// + void AttachPrintHandler(PrintCallback_T callback) { c_callback = callback; } + + /// PrintScreen callback registration. + /// + /// This method attaches a c++ class method as a callback of type PrintCallback_T. + /// Then, the PrintScreen(x,y,w,h) method is called. Each chunk of data in the + /// BMP file to be created is passed to this callback. + /// + /// @param object is the class hosting the callback function. + /// @param callback is the callback function. + /// + template <class T> + void AttachPrintHandler(T *object, RetCode_t (T::*member)(void)) { + obj_callback = (FPointerDummy *)item; + method_callback = (uint32_t (FPointerDummy::*)(uint32_t))method; + } + /// This method captures the specified area as a 24-bit bitmap file, /// including the option of layer selection. /// @@ -2003,8 +2092,29 @@ void RegisterPerformance(method_e method); Timer performance; #endif + + RetCode_t _printCallback(RA8875::filecmd_t cmd, uint8_t * buffer, uint16_t size); + + FILE * _printFH; ///< PrintScreen file handle + + RetCode_t privateCallback(filecmd_t cmd, uint8_t * buffer, uint16_t size) { + if (c_callback != NULL) { + return (*c_callback)(cmd, buffer, size); + } + else { + if (obj_callback != NULL && method_callback != NULL) { + return (obj_callback->*method_callback)(cmd, buffer, size); + } + } + return noerror; + } + + RetCode_t (* c_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size); + FPointerDummy *obj_callback; + RetCode_t (FPointerDummy::*method_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size); }; + //} // namespace //using namespace SW_graphics;