Fork of Silabs MemoryLCD library

Dependents:   demoUI whrmDemoUI Host_Software_MAX32664GWEB_HR_EXTENDED Host_Software_MAX32664GWEC_SpO2_HR-_EXTE ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BufferedDisplay.cpp Source File

BufferedDisplay.cpp

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  * @file BufferedDisplay.cpp
00003  * @brief Buffered version of GraphicsDisplay
00004  *******************************************************************************
00005  * @section License
00006  * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
00007  *******************************************************************************
00008  *
00009  * Permission is granted to anyone to use this software for any purpose,
00010  * including commercial applications, and to alter it and redistribute it
00011  * freely, subject to the following restrictions:
00012  *
00013  * 1. The origin of this software must not be misrepresented; you must not
00014  *    claim that you wrote the original software.
00015  * 2. Altered source versions must be plainly marked as such, and must not be
00016  *    misrepresented as being the original software.
00017  * 3. This notice may not be removed or altered from any source distribution.
00018  *
00019  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
00020  * obligation to support this Software. Silicon Labs is providing the
00021  * Software "AS IS", with no express or implied warranties of any kind,
00022  * including, but not limited to, any implied warranties of merchantability
00023  * or fitness for any particular purpose or warranties against infringement
00024  * of any proprietary rights of a third party.
00025  *
00026  * Silicon Labs will not be liable for any consequential, incidental, or
00027  * special damages, or any other relief, or for any claim by any third party,
00028  * arising from your use of this Software.
00029  *
00030  ******************************************************************************/
00031 
00032 #include "../screen/BufferedDisplay.h"
00033 
00034 #define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7))
00035 
00036 namespace silabs {
00037 
00038     BufferedDisplay::BufferedDisplay(const char *name) : GraphicsDisplay(name) {
00039         memset((uint8_t*)_pixelBuffer, White, sizeof(_pixelBuffer));    // init full frame buffer
00040         memset((uint8_t*)_dirtyRows, 0xFF, sizeof(_dirtyRows));         // init dirty status
00041     }
00042 
00043     /**
00044      * Override of GraphicsDisplay's pixel()
00045      */
00046 
00047     void BufferedDisplay::pixel(int x, int y, int colour) {
00048         /* Apply constraint to x and y */
00049         if(x < 0 || y < 0) return;
00050         if(x >= DISPLAY_WIDTH || y >= DISPLAY_HEIGHT) return;
00051         
00052         /***************************************************************************************************************** 
00053          * The display expects LSB input, while the SPI is configured for 8bit MSB transfers. Therefore, we should  
00054          * construct the framebuffer accordingly, so that an MSB transmission will put pixel 0 first on the wire.
00055          *
00056          * So the actual pixel layout in framebuffer (for 128x128) is as follows:
00057          * {                                                    //Framebuffer
00058          *  {                                                   //Line 0
00059          *   {p0, p1, p2, p3, p4, p5, p6, p7},                  //Line 0 byte 0 (byte 0)
00060          *   {p8, p9,p10,p11,p12,p13,p14,p15},                  //Line 0 byte 1 (byte 1)
00061          *   ...
00062          *   {p120,p121,p122,p123,p124,p125,p126,p127}          //Line 0 byte 15 (byte 15)
00063          *  },        
00064          *  {                                                   //Line 1
00065          *   {p128,p129,p130,p131,p132,p133,p134,p135},         //Line 1 byte 0 (byte 16)
00066          *   ...
00067          *  },
00068          *  ...
00069          *  {                                                   //Line 127
00070          *   {...},                                             //Line 127 byte 0 (byte 2032)
00071          *   ...
00072          *   {...}                                              //Line 127 byte 15 (byte 2047) = 128*128 bits
00073          *  }
00074          * }
00075          *
00076          * This means that to calculate the actual bit position in the framebuffer byte, we need to swap the bit 
00077          * order of the lower three bits. So pixel 7 becomes bit offset 0, 6 -> 1, 5 -> 2, 4->3, 3->4, 2->5, 1->6 and 0->7.
00078          *****************************************************************************************************************/
00079         uint8_t swapx = 7 - ((unsigned int)x & 0x07);
00080         x = ((unsigned int)x & 0xFFFFFFF8) | swapx;
00081 
00082         /* Since we are dealing with 1-bit pixels, we can avoid having to do bitshift and comparison operations twice.
00083          * Basically, do the comparison with the requested state and current state, and if it changed, do an XOR on the framebuffer pixel and set the line to dirty.
00084          */
00085         bool change = ((_pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (x & DISPLAY_BUFFER_TYPE_MASK))) != ((colour & 0x01) << (x & DISPLAY_BUFFER_TYPE_MASK)));
00086         if(change) {
00087             /* Pixel's value and requested value are different, so since it's binary, we can simply do an XOR */
00088             _pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] ^= (1 << (x & DISPLAY_BUFFER_TYPE_MASK));
00089 
00090             /* notify dirty status of this line */
00091             _dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y & DISPLAY_BUFFER_TYPE_MASK));
00092         }
00093     }
00094 
00095     int BufferedDisplay::width() {
00096         return DISPLAY_WIDTH;
00097     }
00098     int BufferedDisplay::height() {
00099         return DISPLAY_HEIGHT;
00100     }
00101 
00102     /**
00103      * Function to move bitmap into frame buffer
00104      * arguments:
00105      *  * bitmap: pointer to uint8 array containing horizontal pixel data
00106      *  * bmpWidth: width of the bitmap in pixels (must be multiple of 8)
00107      *  * bmpHeight: height of the bitmap in pixels
00108      *  * startX: starting position to apply bitmap in horizontal direction (0 = leftmost) (must be multiple of 8)
00109      *  * startY: starting position to apply bitmap in vertical direction (0 = topmost)
00110      */
00111     void BufferedDisplay::showBMP(const uint8_t* bitmap, const uint32_t bmpWidth, const uint32_t bmpHeight, const uint32_t startX, const uint32_t startY) {
00112         uint32_t bmpLine = 0, y = startY, bytesPerLine = ((bmpWidth >= (DISPLAY_WIDTH - startX)) ? (DISPLAY_WIDTH - startX) : bmpWidth) / 8;
00113 
00114         /* Apply constraints */
00115         if((bmpWidth & 0x07) != 0) return;
00116         if((startX & 0x07) != 0) return;
00117         if(startX >= DISPLAY_WIDTH) return;
00118         
00119         //Superflouous due to for-loop check
00120         //if((startY >= DISPLAY_HEIGHT) return;
00121 
00122         /* Copy over bytes to the framebuffer, do not write outside framebuffer boundary */
00123         for(; y < DISPLAY_HEIGHT; y++) {
00124             /* Check that we are not writing more than the BMP height */
00125             if(bmpLine >= bmpHeight) break;
00126             
00127             /* Copy over one line (bmpLine) from the BMP file to the corresponding line (y) in the pixel buffer */
00128             memcpy( (void*) &(((uint8_t*)_pixelBuffer)[((y * DISPLAY_WIDTH) + startX) / 8]),
00129                     (const void*) &(bitmap[bmpLine * (bmpWidth / 8)]),
00130                     bytesPerLine);
00131 
00132             /* Set dirty status for the line we just overwrote */
00133             _dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y % DISPLAY_BUFFER_TYPE_SIZE));
00134             bmpLine++;
00135         }
00136 
00137         return;
00138     }
00139 }