This driver is meant for the monochrome LCD display (model no: LS013B4DN04) from Sharp; but it should be easily adaptable to other Sharp displays.
FrameBuffer.cpp@2:270ee57c0367, 2014-07-30 (annotated)
- Committer:
- rgrover1
- Date:
- Wed Jul 30 07:53:49 2014 +0000
- Revision:
- 2:270ee57c0367
- Parent:
- 0:62d7cfac67ca
Add FrameBuffer::clear()
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
rgrover1 | 0:62d7cfac67ca | 1 | /* mbed Microcontroller Library |
rgrover1 | 0:62d7cfac67ca | 2 | * Copyright (c) 2006-2013 ARM Limited |
rgrover1 | 0:62d7cfac67ca | 3 | * |
rgrover1 | 0:62d7cfac67ca | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
rgrover1 | 0:62d7cfac67ca | 5 | * you may not use this file except in compliance with the License. |
rgrover1 | 0:62d7cfac67ca | 6 | * You may obtain a copy of the License at |
rgrover1 | 0:62d7cfac67ca | 7 | * |
rgrover1 | 0:62d7cfac67ca | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
rgrover1 | 0:62d7cfac67ca | 9 | * |
rgrover1 | 0:62d7cfac67ca | 10 | * Unless required by applicable law or agreed to in writing, software |
rgrover1 | 0:62d7cfac67ca | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
rgrover1 | 0:62d7cfac67ca | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
rgrover1 | 0:62d7cfac67ca | 13 | * See the License for the specific language governing permissions and |
rgrover1 | 0:62d7cfac67ca | 14 | * limitations under the License. |
rgrover1 | 0:62d7cfac67ca | 15 | */ |
rgrover1 | 0:62d7cfac67ca | 16 | |
rgrover1 | 0:62d7cfac67ca | 17 | #include "SharpLCD.hpp" |
rgrover1 | 0:62d7cfac67ca | 18 | |
rgrover1 | 0:62d7cfac67ca | 19 | SharpLCD::FrameBuffer::FrameBuffer(uint8_t *fb) : buffer(fb) |
rgrover1 | 0:62d7cfac67ca | 20 | { |
rgrover1 | 2:270ee57c0367 | 21 | clear(); |
rgrover1 | 2:270ee57c0367 | 22 | |
rgrover1 | 2:270ee57c0367 | 23 | /* Make sure the dummy bytes are clear */ |
rgrover1 | 2:270ee57c0367 | 24 | ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER] = DUMMY8; |
rgrover1 | 2:270ee57c0367 | 25 | ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER + 1] = DUMMY8; |
rgrover1 | 2:270ee57c0367 | 26 | } |
rgrover1 | 2:270ee57c0367 | 27 | |
rgrover1 | 2:270ee57c0367 | 28 | void |
rgrover1 | 2:270ee57c0367 | 29 | SharpLCD::FrameBuffer::clear(void) |
rgrover1 | 2:270ee57c0367 | 30 | { |
rgrover1 | 0:62d7cfac67ca | 31 | uint8_t *pfb; |
rgrover1 | 0:62d7cfac67ca | 32 | unsigned int row; |
rgrover1 | 0:62d7cfac67ca | 33 | unsigned int index; |
rgrover1 | 0:62d7cfac67ca | 34 | |
rgrover1 | 0:62d7cfac67ca | 35 | /* initialize the frame buffer */ |
rgrover1 | 0:62d7cfac67ca | 36 | pfb = buffer; |
rgrover1 | 0:62d7cfac67ca | 37 | for (row = 0; row < LCD_HEIGHT; row++) { |
rgrover1 | 0:62d7cfac67ca | 38 | for (index = 0; index < LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE; index++) { |
rgrover1 | 0:62d7cfac67ca | 39 | switch (index) { |
rgrover1 | 0:62d7cfac67ca | 40 | case 0: |
rgrover1 | 0:62d7cfac67ca | 41 | *pfb++ = M0_FLAG; /* update line command */ |
rgrover1 | 0:62d7cfac67ca | 42 | break; |
rgrover1 | 0:62d7cfac67ca | 43 | case 1: |
rgrover1 | 0:62d7cfac67ca | 44 | *pfb++ = bitReverse8(row + 1); |
rgrover1 | 0:62d7cfac67ca | 45 | break; |
rgrover1 | 0:62d7cfac67ca | 46 | default: |
rgrover1 | 0:62d7cfac67ca | 47 | *pfb++ = 0xFF; /* all white */ |
rgrover1 | 0:62d7cfac67ca | 48 | break; |
rgrover1 | 0:62d7cfac67ca | 49 | } |
rgrover1 | 0:62d7cfac67ca | 50 | } |
rgrover1 | 0:62d7cfac67ca | 51 | } |
rgrover1 | 0:62d7cfac67ca | 52 | } |
rgrover1 | 0:62d7cfac67ca | 53 | |
rgrover1 | 0:62d7cfac67ca | 54 | void |
rgrover1 | 0:62d7cfac67ca | 55 | SharpLCD::FrameBuffer::bitBlit(const uint8_t *bitmap, |
rgrover1 | 0:62d7cfac67ca | 56 | unsigned int width, /* width of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 57 | unsigned int height, /* height of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 58 | unsigned int posx, /* x-offset of the top-left |
rgrover1 | 0:62d7cfac67ca | 59 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 60 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 61 | * corner of the screen */ |
rgrover1 | 0:62d7cfac67ca | 62 | unsigned int posy /* y-offset of the top-left |
rgrover1 | 0:62d7cfac67ca | 63 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 64 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 65 | * corner of the screen */) |
rgrover1 | 0:62d7cfac67ca | 66 | { |
rgrover1 | 0:62d7cfac67ca | 67 | unsigned int row; |
rgrover1 | 0:62d7cfac67ca | 68 | unsigned int col; |
rgrover1 | 0:62d7cfac67ca | 69 | unsigned int bitsToBlitInRow; |
rgrover1 | 0:62d7cfac67ca | 70 | unsigned int destByteIndex; /* within the current row */ |
rgrover1 | 0:62d7cfac67ca | 71 | unsigned int destBitIndexMod8; /* bits to the right of this index in |
rgrover1 | 0:62d7cfac67ca | 72 | * 'destByte' need to be blitted next; |
rgrover1 | 0:62d7cfac67ca | 73 | * MSB has index 0. */ |
rgrover1 | 0:62d7cfac67ca | 74 | unsigned int srcByteIndex; /* byte index within the source bitmap */ |
rgrover1 | 0:62d7cfac67ca | 75 | unsigned int srcBitIndexMod8; /* bits to the right of this index in |
rgrover1 | 0:62d7cfac67ca | 76 | * source byte (at index srcByteIndex) |
rgrover1 | 0:62d7cfac67ca | 77 | * need to be blitted to the dest; MSB |
rgrover1 | 0:62d7cfac67ca | 78 | * has index 0. */ |
rgrover1 | 0:62d7cfac67ca | 79 | const unsigned int endRow = posy + height; |
rgrover1 | 0:62d7cfac67ca | 80 | uint8_t destByte; |
rgrover1 | 0:62d7cfac67ca | 81 | uint8_t srcBits; |
rgrover1 | 0:62d7cfac67ca | 82 | |
rgrover1 | 0:62d7cfac67ca | 83 | #if 0 |
rgrover1 | 0:62d7cfac67ca | 84 | unsigned long current_cycle_count = Get_system_register(AVR32_COUNT); |
rgrover1 | 0:62d7cfac67ca | 85 | #endif |
rgrover1 | 0:62d7cfac67ca | 86 | |
rgrover1 | 0:62d7cfac67ca | 87 | // ASSERT(bitmap != NULL, "%s: passed in a NULL bitmap", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 88 | // ASSERT(width > 0, "%s: passed in an invalid width", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 89 | // ASSERT(height > 0, "%s: passed in an invalid height", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 90 | // ASSERT(posx + width <= LCD_WIDTH, |
rgrover1 | 0:62d7cfac67ca | 91 | // "%s: bitmap will exceed the screen width", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 92 | // ASSERT(posy + height <= LCD_HEIGHT, |
rgrover1 | 0:62d7cfac67ca | 93 | // "%s: bitmap will exceed the screen height", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 94 | |
rgrover1 | 0:62d7cfac67ca | 95 | /* |
rgrover1 | 0:62d7cfac67ca | 96 | * A couple of helpful macros to maintain a source bitstream. |
rgrover1 | 0:62d7cfac67ca | 97 | */ |
rgrover1 | 0:62d7cfac67ca | 98 | #define SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(M) do { \ |
rgrover1 | 0:62d7cfac67ca | 99 | uint8_t mask; \ |
rgrover1 | 0:62d7cfac67ca | 100 | \ |
rgrover1 | 0:62d7cfac67ca | 101 | mask = ((uint8_t)((uint8_t)1 << (M)) - 1); \ |
rgrover1 | 0:62d7cfac67ca | 102 | srcBits <<= (M); \ |
rgrover1 | 0:62d7cfac67ca | 103 | srcBits |= (bitmap[srcByteIndex] >> (8 - (srcBitIndexMod8 + (M)))) & mask; \ |
rgrover1 | 0:62d7cfac67ca | 104 | \ |
rgrover1 | 0:62d7cfac67ca | 105 | /* update the indices */ \ |
rgrover1 | 0:62d7cfac67ca | 106 | srcBitIndexMod8 += (M); \ |
rgrover1 | 0:62d7cfac67ca | 107 | if (srcBitIndexMod8 == 8) { \ |
rgrover1 | 0:62d7cfac67ca | 108 | srcBitIndexMod8 = 0; \ |
rgrover1 | 0:62d7cfac67ca | 109 | srcByteIndex++; \ |
rgrover1 | 0:62d7cfac67ca | 110 | } \ |
rgrover1 | 0:62d7cfac67ca | 111 | } while (0) |
rgrover1 | 0:62d7cfac67ca | 112 | |
rgrover1 | 0:62d7cfac67ca | 113 | /* Left-shift N bits into srcBits; fetching them from the source |
rgrover1 | 0:62d7cfac67ca | 114 | * bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 115 | #define SHIFT_INTO_SRC_BITS(N) do { \ |
rgrover1 | 0:62d7cfac67ca | 116 | uint8_t bitsToShift; \ |
rgrover1 | 0:62d7cfac67ca | 117 | \ |
rgrover1 | 0:62d7cfac67ca | 118 | bitsToShift = (N); \ |
rgrover1 | 0:62d7cfac67ca | 119 | \ |
rgrover1 | 0:62d7cfac67ca | 120 | if ((srcBitIndexMod8 + (N)) > 8) { \ |
rgrover1 | 0:62d7cfac67ca | 121 | bitsToShift = 8 - srcBitIndexMod8; \ |
rgrover1 | 0:62d7cfac67ca | 122 | SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ |
rgrover1 | 0:62d7cfac67ca | 123 | bitsToShift = (N) - bitsToShift; \ |
rgrover1 | 0:62d7cfac67ca | 124 | } \ |
rgrover1 | 0:62d7cfac67ca | 125 | \ |
rgrover1 | 0:62d7cfac67ca | 126 | SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ |
rgrover1 | 0:62d7cfac67ca | 127 | } while (0) |
rgrover1 | 0:62d7cfac67ca | 128 | |
rgrover1 | 0:62d7cfac67ca | 129 | srcByteIndex = 0; |
rgrover1 | 0:62d7cfac67ca | 130 | srcBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 131 | for (row = posy; row < endRow; row++) { |
rgrover1 | 0:62d7cfac67ca | 132 | col = posx; |
rgrover1 | 0:62d7cfac67ca | 133 | bitsToBlitInRow = width; |
rgrover1 | 0:62d7cfac67ca | 134 | destBitIndexMod8 = col & 0x7 /* col % 8 */; |
rgrover1 | 0:62d7cfac67ca | 135 | destByteIndex = col >> 3 /* col / 8 */; |
rgrover1 | 0:62d7cfac67ca | 136 | srcBits = 0; |
rgrover1 | 0:62d7cfac67ca | 137 | |
rgrover1 | 0:62d7cfac67ca | 138 | /* While there are bits in this row remaining to be blitted to |
rgrover1 | 0:62d7cfac67ca | 139 | * the destination, ... */ |
rgrover1 | 0:62d7cfac67ca | 140 | while (bitsToBlitInRow) { |
rgrover1 | 0:62d7cfac67ca | 141 | if ((destBitIndexMod8 == 0) && (bitsToBlitInRow >= 8)) { |
rgrover1 | 0:62d7cfac67ca | 142 | /* We know that destBitIndexMod8 == 0, which means that |
rgrover1 | 0:62d7cfac67ca | 143 | * the destination is byte aligned and we can simply |
rgrover1 | 0:62d7cfac67ca | 144 | * do the equivalent of a memcpy. */ |
rgrover1 | 0:62d7cfac67ca | 145 | while (bitsToBlitInRow >= 8) { |
rgrover1 | 0:62d7cfac67ca | 146 | SHIFT_INTO_SRC_BITS(8); |
rgrover1 | 0:62d7cfac67ca | 147 | setRowByte(row, destByteIndex, srcBits); |
rgrover1 | 0:62d7cfac67ca | 148 | |
rgrover1 | 0:62d7cfac67ca | 149 | bitsToBlitInRow -= 8; |
rgrover1 | 0:62d7cfac67ca | 150 | destByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 151 | } |
rgrover1 | 0:62d7cfac67ca | 152 | } else { |
rgrover1 | 0:62d7cfac67ca | 153 | uint8_t blit; /* number of bits to blit in this iteration */ |
rgrover1 | 0:62d7cfac67ca | 154 | uint8_t mask; |
rgrover1 | 0:62d7cfac67ca | 155 | uint8_t leftShift; |
rgrover1 | 0:62d7cfac67ca | 156 | |
rgrover1 | 0:62d7cfac67ca | 157 | /* This will be a read-modify-write operation, so we |
rgrover1 | 0:62d7cfac67ca | 158 | * need to fetch the destination byte. */ |
rgrover1 | 0:62d7cfac67ca | 159 | destByte = getRowByte(row, destByteIndex); |
rgrover1 | 0:62d7cfac67ca | 160 | |
rgrover1 | 0:62d7cfac67ca | 161 | if ((destBitIndexMod8 + bitsToBlitInRow) >= 8) { |
rgrover1 | 0:62d7cfac67ca | 162 | blit = 8 - destBitIndexMod8; |
rgrover1 | 0:62d7cfac67ca | 163 | leftShift = 0; |
rgrover1 | 0:62d7cfac67ca | 164 | } else { |
rgrover1 | 0:62d7cfac67ca | 165 | blit = bitsToBlitInRow; |
rgrover1 | 0:62d7cfac67ca | 166 | leftShift = (8 - (destBitIndexMod8 + bitsToBlitInRow)); |
rgrover1 | 0:62d7cfac67ca | 167 | } |
rgrover1 | 0:62d7cfac67ca | 168 | |
rgrover1 | 0:62d7cfac67ca | 169 | SHIFT_INTO_SRC_BITS(blit); |
rgrover1 | 0:62d7cfac67ca | 170 | mask = ((uint8_t)((uint8_t)1 << blit) - 1) << leftShift; |
rgrover1 | 0:62d7cfac67ca | 171 | |
rgrover1 | 0:62d7cfac67ca | 172 | /* update destByte */ |
rgrover1 | 0:62d7cfac67ca | 173 | destByte &= ~mask; |
rgrover1 | 0:62d7cfac67ca | 174 | destByte |= ((uint8_t)(srcBits << leftShift) & mask); |
rgrover1 | 0:62d7cfac67ca | 175 | |
rgrover1 | 0:62d7cfac67ca | 176 | setRowByte(row, destByteIndex, destByte); |
rgrover1 | 0:62d7cfac67ca | 177 | |
rgrover1 | 0:62d7cfac67ca | 178 | /* update dest indices */ |
rgrover1 | 0:62d7cfac67ca | 179 | bitsToBlitInRow -= blit; |
rgrover1 | 0:62d7cfac67ca | 180 | destBitIndexMod8 += blit; |
rgrover1 | 0:62d7cfac67ca | 181 | if (destBitIndexMod8 == 8) { |
rgrover1 | 0:62d7cfac67ca | 182 | destBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 183 | destByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 184 | } |
rgrover1 | 0:62d7cfac67ca | 185 | } |
rgrover1 | 0:62d7cfac67ca | 186 | } |
rgrover1 | 0:62d7cfac67ca | 187 | |
rgrover1 | 0:62d7cfac67ca | 188 | /* potentially update srcByteIndex */ |
rgrover1 | 0:62d7cfac67ca | 189 | if (srcBitIndexMod8 != 0) { |
rgrover1 | 0:62d7cfac67ca | 190 | srcBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 191 | srcByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 192 | } |
rgrover1 | 0:62d7cfac67ca | 193 | } |
rgrover1 | 0:62d7cfac67ca | 194 | } |
rgrover1 | 0:62d7cfac67ca | 195 | |
rgrover1 | 0:62d7cfac67ca | 196 | void |
rgrover1 | 0:62d7cfac67ca | 197 | SharpLCD::FrameBuffer::printString(const font_face_t *face, |
rgrover1 | 0:62d7cfac67ca | 198 | unsigned short baselineX, |
rgrover1 | 0:62d7cfac67ca | 199 | unsigned short baselineY, |
rgrover1 | 0:62d7cfac67ca | 200 | font_color_t fgColor, |
rgrover1 | 0:62d7cfac67ca | 201 | const char *string) |
rgrover1 | 0:62d7cfac67ca | 202 | { |
rgrover1 | 0:62d7cfac67ca | 203 | unsigned char ch; |
rgrover1 | 0:62d7cfac67ca | 204 | while ((ch = *string++) != '\0') { |
rgrover1 | 0:62d7cfac67ca | 205 | if ((ch < FONT_LOWEST_SUPPORTED_CHAR_ENCODING) || |
rgrover1 | 0:62d7cfac67ca | 206 | (ch > FONT_HIGHEST_SUPPORTED_CHAR_ENCODING)) { |
rgrover1 | 0:62d7cfac67ca | 207 | // TRACE_WARNING("printString: attempt to render unsupported char (enc: 0x%x)\n", ch); |
rgrover1 | 0:62d7cfac67ca | 208 | continue; |
rgrover1 | 0:62d7cfac67ca | 209 | } |
rgrover1 | 0:62d7cfac67ca | 210 | |
rgrover1 | 0:62d7cfac67ca | 211 | const glyph_t *glyph = &face->glyphs[ch - FONT_LOWEST_SUPPORTED_CHAR_ENCODING]; |
rgrover1 | 0:62d7cfac67ca | 212 | |
rgrover1 | 0:62d7cfac67ca | 213 | if ((glyph->width > 0) && (glyph->height > 0)) { |
rgrover1 | 0:62d7cfac67ca | 214 | bitBlit(&face->bitmaps[glyph->bitmapIndex], /* bitmap */ |
rgrover1 | 0:62d7cfac67ca | 215 | glyph->width, /* width of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 216 | glyph->height, /* height of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 217 | baselineX + glyph->bearingX, /* x-offset for the |
rgrover1 | 0:62d7cfac67ca | 218 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 219 | * corner of the bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 220 | baselineY - glyph->bearingY /* y-offset for the |
rgrover1 | 0:62d7cfac67ca | 221 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 222 | * corner of the bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 223 | ); |
rgrover1 | 0:62d7cfac67ca | 224 | } |
rgrover1 | 0:62d7cfac67ca | 225 | |
rgrover1 | 0:62d7cfac67ca | 226 | baselineX += glyph->advance; |
rgrover1 | 0:62d7cfac67ca | 227 | } |
rgrover1 | 0:62d7cfac67ca | 228 | } |