TEST
Dependencies: max32630fthr Adafruit_FeatherOLED USBDevice
Drivers/LS013B7DH03/BufferedDisplay.cpp@1:f60eafbf009a, 2019-04-10 (annotated)
- Committer:
- gmehmet
- Date:
- Wed Apr 10 14:56:25 2019 +0300
- Revision:
- 1:f60eafbf009a
upload from local
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gmehmet | 1:f60eafbf009a | 1 | /***************************************************************************//** |
gmehmet | 1:f60eafbf009a | 2 | * @file BufferedDisplay.cpp |
gmehmet | 1:f60eafbf009a | 3 | * @brief Buffered version of GraphicsDisplay |
gmehmet | 1:f60eafbf009a | 4 | ******************************************************************************* |
gmehmet | 1:f60eafbf009a | 5 | * @section License |
gmehmet | 1:f60eafbf009a | 6 | * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> |
gmehmet | 1:f60eafbf009a | 7 | ******************************************************************************* |
gmehmet | 1:f60eafbf009a | 8 | * |
gmehmet | 1:f60eafbf009a | 9 | * Permission is granted to anyone to use this software for any purpose, |
gmehmet | 1:f60eafbf009a | 10 | * including commercial applications, and to alter it and redistribute it |
gmehmet | 1:f60eafbf009a | 11 | * freely, subject to the following restrictions: |
gmehmet | 1:f60eafbf009a | 12 | * |
gmehmet | 1:f60eafbf009a | 13 | * 1. The origin of this software must not be misrepresented; you must not |
gmehmet | 1:f60eafbf009a | 14 | * claim that you wrote the original software. |
gmehmet | 1:f60eafbf009a | 15 | * 2. Altered source versions must be plainly marked as such, and must not be |
gmehmet | 1:f60eafbf009a | 16 | * misrepresented as being the original software. |
gmehmet | 1:f60eafbf009a | 17 | * 3. This notice may not be removed or altered from any source distribution. |
gmehmet | 1:f60eafbf009a | 18 | * |
gmehmet | 1:f60eafbf009a | 19 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
gmehmet | 1:f60eafbf009a | 20 | * obligation to support this Software. Silicon Labs is providing the |
gmehmet | 1:f60eafbf009a | 21 | * Software "AS IS", with no express or implied warranties of any kind, |
gmehmet | 1:f60eafbf009a | 22 | * including, but not limited to, any implied warranties of merchantability |
gmehmet | 1:f60eafbf009a | 23 | * or fitness for any particular purpose or warranties against infringement |
gmehmet | 1:f60eafbf009a | 24 | * of any proprietary rights of a third party. |
gmehmet | 1:f60eafbf009a | 25 | * |
gmehmet | 1:f60eafbf009a | 26 | * Silicon Labs will not be liable for any consequential, incidental, or |
gmehmet | 1:f60eafbf009a | 27 | * special damages, or any other relief, or for any claim by any third party, |
gmehmet | 1:f60eafbf009a | 28 | * arising from your use of this Software. |
gmehmet | 1:f60eafbf009a | 29 | * |
gmehmet | 1:f60eafbf009a | 30 | ******************************************************************************/ |
gmehmet | 1:f60eafbf009a | 31 | |
gmehmet | 1:f60eafbf009a | 32 | #include "BufferedDisplay.h" |
gmehmet | 1:f60eafbf009a | 33 | |
gmehmet | 1:f60eafbf009a | 34 | #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)) |
gmehmet | 1:f60eafbf009a | 35 | |
gmehmet | 1:f60eafbf009a | 36 | namespace silabs { |
gmehmet | 1:f60eafbf009a | 37 | |
gmehmet | 1:f60eafbf009a | 38 | BufferedDisplay::BufferedDisplay(const char *name) : GraphicsDisplay(name) { |
gmehmet | 1:f60eafbf009a | 39 | memset((uint8_t*)_pixelBuffer, White, sizeof(_pixelBuffer)); // init full frame buffer |
gmehmet | 1:f60eafbf009a | 40 | memset((uint8_t*)_dirtyRows, 0xFF, sizeof(_dirtyRows)); // init dirty status |
gmehmet | 1:f60eafbf009a | 41 | } |
gmehmet | 1:f60eafbf009a | 42 | |
gmehmet | 1:f60eafbf009a | 43 | /** |
gmehmet | 1:f60eafbf009a | 44 | * Override of GraphicsDisplay's pixel() |
gmehmet | 1:f60eafbf009a | 45 | */ |
gmehmet | 1:f60eafbf009a | 46 | |
gmehmet | 1:f60eafbf009a | 47 | void BufferedDisplay::pixel(int x, int y, int colour) { |
gmehmet | 1:f60eafbf009a | 48 | /* Apply constraint to x and y */ |
gmehmet | 1:f60eafbf009a | 49 | if(x < 0 || y < 0) return; |
gmehmet | 1:f60eafbf009a | 50 | if(x >= DISPLAY_WIDTH || y >= DISPLAY_HEIGHT) return; |
gmehmet | 1:f60eafbf009a | 51 | |
gmehmet | 1:f60eafbf009a | 52 | /***************************************************************************************************************** |
gmehmet | 1:f60eafbf009a | 53 | * The display expects LSB input, while the SPI is configured for 8bit MSB transfers. Therefore, we should |
gmehmet | 1:f60eafbf009a | 54 | * construct the framebuffer accordingly, so that an MSB transmission will put pixel 0 first on the wire. |
gmehmet | 1:f60eafbf009a | 55 | * |
gmehmet | 1:f60eafbf009a | 56 | * So the actual pixel layout in framebuffer (for 128x128) is as follows: |
gmehmet | 1:f60eafbf009a | 57 | * { //Framebuffer |
gmehmet | 1:f60eafbf009a | 58 | * { //Line 0 |
gmehmet | 1:f60eafbf009a | 59 | * {p0, p1, p2, p3, p4, p5, p6, p7}, //Line 0 byte 0 (byte 0) |
gmehmet | 1:f60eafbf009a | 60 | * {p8, p9,p10,p11,p12,p13,p14,p15}, //Line 0 byte 1 (byte 1) |
gmehmet | 1:f60eafbf009a | 61 | * ... |
gmehmet | 1:f60eafbf009a | 62 | * {p120,p121,p122,p123,p124,p125,p126,p127} //Line 0 byte 15 (byte 15) |
gmehmet | 1:f60eafbf009a | 63 | * }, |
gmehmet | 1:f60eafbf009a | 64 | * { //Line 1 |
gmehmet | 1:f60eafbf009a | 65 | * {p128,p129,p130,p131,p132,p133,p134,p135}, //Line 1 byte 0 (byte 16) |
gmehmet | 1:f60eafbf009a | 66 | * ... |
gmehmet | 1:f60eafbf009a | 67 | * }, |
gmehmet | 1:f60eafbf009a | 68 | * ... |
gmehmet | 1:f60eafbf009a | 69 | * { //Line 127 |
gmehmet | 1:f60eafbf009a | 70 | * {...}, //Line 127 byte 0 (byte 2032) |
gmehmet | 1:f60eafbf009a | 71 | * ... |
gmehmet | 1:f60eafbf009a | 72 | * {...} //Line 127 byte 15 (byte 2047) = 128*128 bits |
gmehmet | 1:f60eafbf009a | 73 | * } |
gmehmet | 1:f60eafbf009a | 74 | * } |
gmehmet | 1:f60eafbf009a | 75 | * |
gmehmet | 1:f60eafbf009a | 76 | * This means that to calculate the actual bit position in the framebuffer byte, we need to swap the bit |
gmehmet | 1:f60eafbf009a | 77 | * 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. |
gmehmet | 1:f60eafbf009a | 78 | *****************************************************************************************************************/ |
gmehmet | 1:f60eafbf009a | 79 | uint8_t swapx = 7 - ((unsigned int)x & 0x07); |
gmehmet | 1:f60eafbf009a | 80 | x = ((unsigned int)x & 0xFFFFFFF8) | swapx; |
gmehmet | 1:f60eafbf009a | 81 | |
gmehmet | 1:f60eafbf009a | 82 | /* Since we are dealing with 1-bit pixels, we can avoid having to do bitshift and comparison operations twice. |
gmehmet | 1:f60eafbf009a | 83 | * 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. |
gmehmet | 1:f60eafbf009a | 84 | */ |
gmehmet | 1:f60eafbf009a | 85 | bool change = ((_pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (x & DISPLAY_BUFFER_TYPE_MASK))) != ((colour & 0x01) << (x & DISPLAY_BUFFER_TYPE_MASK))); |
gmehmet | 1:f60eafbf009a | 86 | if(change) { |
gmehmet | 1:f60eafbf009a | 87 | /* Pixel's value and requested value are different, so since it's binary, we can simply do an XOR */ |
gmehmet | 1:f60eafbf009a | 88 | _pixelBuffer[((y * DISPLAY_WIDTH) + x) / DISPLAY_BUFFER_TYPE_SIZE] ^= (1 << (x & DISPLAY_BUFFER_TYPE_MASK)); |
gmehmet | 1:f60eafbf009a | 89 | |
gmehmet | 1:f60eafbf009a | 90 | /* notify dirty status of this line */ |
gmehmet | 1:f60eafbf009a | 91 | _dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y & DISPLAY_BUFFER_TYPE_MASK)); |
gmehmet | 1:f60eafbf009a | 92 | } |
gmehmet | 1:f60eafbf009a | 93 | } |
gmehmet | 1:f60eafbf009a | 94 | |
gmehmet | 1:f60eafbf009a | 95 | int BufferedDisplay::width() { |
gmehmet | 1:f60eafbf009a | 96 | return DISPLAY_WIDTH; |
gmehmet | 1:f60eafbf009a | 97 | } |
gmehmet | 1:f60eafbf009a | 98 | int BufferedDisplay::height() { |
gmehmet | 1:f60eafbf009a | 99 | return DISPLAY_HEIGHT; |
gmehmet | 1:f60eafbf009a | 100 | } |
gmehmet | 1:f60eafbf009a | 101 | |
gmehmet | 1:f60eafbf009a | 102 | /** |
gmehmet | 1:f60eafbf009a | 103 | * Function to move bitmap into frame buffer |
gmehmet | 1:f60eafbf009a | 104 | * arguments: |
gmehmet | 1:f60eafbf009a | 105 | * * bitmap: pointer to uint8 array containing horizontal pixel data |
gmehmet | 1:f60eafbf009a | 106 | * * bmpWidth: width of the bitmap in pixels (must be multiple of 8) |
gmehmet | 1:f60eafbf009a | 107 | * * bmpHeight: height of the bitmap in pixels |
gmehmet | 1:f60eafbf009a | 108 | * * startX: starting position to apply bitmap in horizontal direction (0 = leftmost) (must be multiple of 8) |
gmehmet | 1:f60eafbf009a | 109 | * * startY: starting position to apply bitmap in vertical direction (0 = topmost) |
gmehmet | 1:f60eafbf009a | 110 | */ |
gmehmet | 1:f60eafbf009a | 111 | void BufferedDisplay::showBMP(const uint8_t* bitmap, const uint32_t bmpWidth, const uint32_t bmpHeight, const uint32_t startX, const uint32_t startY) { |
gmehmet | 1:f60eafbf009a | 112 | uint32_t bmpLine = 0, y = startY, bytesPerLine = ((bmpWidth >= (DISPLAY_WIDTH - startX)) ? (DISPLAY_WIDTH - startX) : bmpWidth) / 8; |
gmehmet | 1:f60eafbf009a | 113 | |
gmehmet | 1:f60eafbf009a | 114 | /* Apply constraints */ |
gmehmet | 1:f60eafbf009a | 115 | if((bmpWidth & 0x07) != 0) return; |
gmehmet | 1:f60eafbf009a | 116 | if((startX & 0x07) != 0) return; |
gmehmet | 1:f60eafbf009a | 117 | if(startX >= DISPLAY_WIDTH) return; |
gmehmet | 1:f60eafbf009a | 118 | |
gmehmet | 1:f60eafbf009a | 119 | //Superflouous due to for-loop check |
gmehmet | 1:f60eafbf009a | 120 | //if((startY >= DISPLAY_HEIGHT) return; |
gmehmet | 1:f60eafbf009a | 121 | |
gmehmet | 1:f60eafbf009a | 122 | /* Copy over bytes to the framebuffer, do not write outside framebuffer boundary */ |
gmehmet | 1:f60eafbf009a | 123 | for(; y < DISPLAY_HEIGHT; y++) { |
gmehmet | 1:f60eafbf009a | 124 | /* Check that we are not writing more than the BMP height */ |
gmehmet | 1:f60eafbf009a | 125 | if(bmpLine >= bmpHeight) break; |
gmehmet | 1:f60eafbf009a | 126 | |
gmehmet | 1:f60eafbf009a | 127 | /* Copy over one line (bmpLine) from the BMP file to the corresponding line (y) in the pixel buffer */ |
gmehmet | 1:f60eafbf009a | 128 | memcpy( (void*) &(((uint8_t*)_pixelBuffer)[((y * DISPLAY_WIDTH) + startX) / 8]), |
gmehmet | 1:f60eafbf009a | 129 | (const void*) &(bitmap[bmpLine * (bmpWidth / 8)]), |
gmehmet | 1:f60eafbf009a | 130 | bytesPerLine); |
gmehmet | 1:f60eafbf009a | 131 | |
gmehmet | 1:f60eafbf009a | 132 | /* Set dirty status for the line we just overwrote */ |
gmehmet | 1:f60eafbf009a | 133 | _dirtyRows[y / DISPLAY_BUFFER_TYPE_SIZE] |= (1 << (y % DISPLAY_BUFFER_TYPE_SIZE)); |
gmehmet | 1:f60eafbf009a | 134 | bmpLine++; |
gmehmet | 1:f60eafbf009a | 135 | } |
gmehmet | 1:f60eafbf009a | 136 | |
gmehmet | 1:f60eafbf009a | 137 | return; |
gmehmet | 1:f60eafbf009a | 138 | } |
gmehmet | 1:f60eafbf009a | 139 | } |