LCD library for Sharp LS013B7DH01
Dependents: mbed_weloop_screen_demo
Fork of SharpLCD by
FrameBuffer.cpp@0:62d7cfac67ca, 2014-07-23 (annotated)
- Committer:
- rgrover1
- Date:
- Wed Jul 23 10:40:35 2014 +0000
- Revision:
- 0:62d7cfac67ca
- Child:
- 2:270ee57c0367
initial working checkin
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 | 0:62d7cfac67ca | 21 | uint8_t *pfb; |
rgrover1 | 0:62d7cfac67ca | 22 | unsigned int row; |
rgrover1 | 0:62d7cfac67ca | 23 | unsigned int index; |
rgrover1 | 0:62d7cfac67ca | 24 | |
rgrover1 | 0:62d7cfac67ca | 25 | /* initialize the frame buffer */ |
rgrover1 | 0:62d7cfac67ca | 26 | pfb = buffer; |
rgrover1 | 0:62d7cfac67ca | 27 | for (row = 0; row < LCD_HEIGHT; row++) { |
rgrover1 | 0:62d7cfac67ca | 28 | for (index = 0; index < LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE; index++) { |
rgrover1 | 0:62d7cfac67ca | 29 | switch (index) { |
rgrover1 | 0:62d7cfac67ca | 30 | case 0: |
rgrover1 | 0:62d7cfac67ca | 31 | *pfb++ = M0_FLAG; /* update line command */ |
rgrover1 | 0:62d7cfac67ca | 32 | break; |
rgrover1 | 0:62d7cfac67ca | 33 | case 1: |
rgrover1 | 0:62d7cfac67ca | 34 | *pfb++ = bitReverse8(row + 1); |
rgrover1 | 0:62d7cfac67ca | 35 | break; |
rgrover1 | 0:62d7cfac67ca | 36 | default: |
rgrover1 | 0:62d7cfac67ca | 37 | *pfb++ = 0xFF; /* all white */ |
rgrover1 | 0:62d7cfac67ca | 38 | break; |
rgrover1 | 0:62d7cfac67ca | 39 | } |
rgrover1 | 0:62d7cfac67ca | 40 | } |
rgrover1 | 0:62d7cfac67ca | 41 | } |
rgrover1 | 0:62d7cfac67ca | 42 | |
rgrover1 | 0:62d7cfac67ca | 43 | /* Make sure the dummy bytes are clear */ |
rgrover1 | 0:62d7cfac67ca | 44 | ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER] = DUMMY8; |
rgrover1 | 0:62d7cfac67ca | 45 | ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER + 1] = DUMMY8; |
rgrover1 | 0:62d7cfac67ca | 46 | } |
rgrover1 | 0:62d7cfac67ca | 47 | |
rgrover1 | 0:62d7cfac67ca | 48 | void |
rgrover1 | 0:62d7cfac67ca | 49 | SharpLCD::FrameBuffer::bitBlit(const uint8_t *bitmap, |
rgrover1 | 0:62d7cfac67ca | 50 | unsigned int width, /* width of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 51 | unsigned int height, /* height of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 52 | unsigned int posx, /* x-offset of the top-left |
rgrover1 | 0:62d7cfac67ca | 53 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 54 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 55 | * corner of the screen */ |
rgrover1 | 0:62d7cfac67ca | 56 | unsigned int posy /* y-offset of the top-left |
rgrover1 | 0:62d7cfac67ca | 57 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 58 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 59 | * corner of the screen */) |
rgrover1 | 0:62d7cfac67ca | 60 | { |
rgrover1 | 0:62d7cfac67ca | 61 | unsigned int row; |
rgrover1 | 0:62d7cfac67ca | 62 | unsigned int col; |
rgrover1 | 0:62d7cfac67ca | 63 | unsigned int bitsToBlitInRow; |
rgrover1 | 0:62d7cfac67ca | 64 | unsigned int destByteIndex; /* within the current row */ |
rgrover1 | 0:62d7cfac67ca | 65 | unsigned int destBitIndexMod8; /* bits to the right of this index in |
rgrover1 | 0:62d7cfac67ca | 66 | * 'destByte' need to be blitted next; |
rgrover1 | 0:62d7cfac67ca | 67 | * MSB has index 0. */ |
rgrover1 | 0:62d7cfac67ca | 68 | unsigned int srcByteIndex; /* byte index within the source bitmap */ |
rgrover1 | 0:62d7cfac67ca | 69 | unsigned int srcBitIndexMod8; /* bits to the right of this index in |
rgrover1 | 0:62d7cfac67ca | 70 | * source byte (at index srcByteIndex) |
rgrover1 | 0:62d7cfac67ca | 71 | * need to be blitted to the dest; MSB |
rgrover1 | 0:62d7cfac67ca | 72 | * has index 0. */ |
rgrover1 | 0:62d7cfac67ca | 73 | const unsigned int endRow = posy + height; |
rgrover1 | 0:62d7cfac67ca | 74 | uint8_t destByte; |
rgrover1 | 0:62d7cfac67ca | 75 | uint8_t srcBits; |
rgrover1 | 0:62d7cfac67ca | 76 | |
rgrover1 | 0:62d7cfac67ca | 77 | #if 0 |
rgrover1 | 0:62d7cfac67ca | 78 | unsigned long current_cycle_count = Get_system_register(AVR32_COUNT); |
rgrover1 | 0:62d7cfac67ca | 79 | #endif |
rgrover1 | 0:62d7cfac67ca | 80 | |
rgrover1 | 0:62d7cfac67ca | 81 | // ASSERT(bitmap != NULL, "%s: passed in a NULL bitmap", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 82 | // ASSERT(width > 0, "%s: passed in an invalid width", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 83 | // ASSERT(height > 0, "%s: passed in an invalid height", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 84 | // ASSERT(posx + width <= LCD_WIDTH, |
rgrover1 | 0:62d7cfac67ca | 85 | // "%s: bitmap will exceed the screen width", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 86 | // ASSERT(posy + height <= LCD_HEIGHT, |
rgrover1 | 0:62d7cfac67ca | 87 | // "%s: bitmap will exceed the screen height", __FUNCTION__); |
rgrover1 | 0:62d7cfac67ca | 88 | |
rgrover1 | 0:62d7cfac67ca | 89 | /* |
rgrover1 | 0:62d7cfac67ca | 90 | * A couple of helpful macros to maintain a source bitstream. |
rgrover1 | 0:62d7cfac67ca | 91 | */ |
rgrover1 | 0:62d7cfac67ca | 92 | #define SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(M) do { \ |
rgrover1 | 0:62d7cfac67ca | 93 | uint8_t mask; \ |
rgrover1 | 0:62d7cfac67ca | 94 | \ |
rgrover1 | 0:62d7cfac67ca | 95 | mask = ((uint8_t)((uint8_t)1 << (M)) - 1); \ |
rgrover1 | 0:62d7cfac67ca | 96 | srcBits <<= (M); \ |
rgrover1 | 0:62d7cfac67ca | 97 | srcBits |= (bitmap[srcByteIndex] >> (8 - (srcBitIndexMod8 + (M)))) & mask; \ |
rgrover1 | 0:62d7cfac67ca | 98 | \ |
rgrover1 | 0:62d7cfac67ca | 99 | /* update the indices */ \ |
rgrover1 | 0:62d7cfac67ca | 100 | srcBitIndexMod8 += (M); \ |
rgrover1 | 0:62d7cfac67ca | 101 | if (srcBitIndexMod8 == 8) { \ |
rgrover1 | 0:62d7cfac67ca | 102 | srcBitIndexMod8 = 0; \ |
rgrover1 | 0:62d7cfac67ca | 103 | srcByteIndex++; \ |
rgrover1 | 0:62d7cfac67ca | 104 | } \ |
rgrover1 | 0:62d7cfac67ca | 105 | } while (0) |
rgrover1 | 0:62d7cfac67ca | 106 | |
rgrover1 | 0:62d7cfac67ca | 107 | /* Left-shift N bits into srcBits; fetching them from the source |
rgrover1 | 0:62d7cfac67ca | 108 | * bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 109 | #define SHIFT_INTO_SRC_BITS(N) do { \ |
rgrover1 | 0:62d7cfac67ca | 110 | uint8_t bitsToShift; \ |
rgrover1 | 0:62d7cfac67ca | 111 | \ |
rgrover1 | 0:62d7cfac67ca | 112 | bitsToShift = (N); \ |
rgrover1 | 0:62d7cfac67ca | 113 | \ |
rgrover1 | 0:62d7cfac67ca | 114 | if ((srcBitIndexMod8 + (N)) > 8) { \ |
rgrover1 | 0:62d7cfac67ca | 115 | bitsToShift = 8 - srcBitIndexMod8; \ |
rgrover1 | 0:62d7cfac67ca | 116 | SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ |
rgrover1 | 0:62d7cfac67ca | 117 | bitsToShift = (N) - bitsToShift; \ |
rgrover1 | 0:62d7cfac67ca | 118 | } \ |
rgrover1 | 0:62d7cfac67ca | 119 | \ |
rgrover1 | 0:62d7cfac67ca | 120 | SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ |
rgrover1 | 0:62d7cfac67ca | 121 | } while (0) |
rgrover1 | 0:62d7cfac67ca | 122 | |
rgrover1 | 0:62d7cfac67ca | 123 | srcByteIndex = 0; |
rgrover1 | 0:62d7cfac67ca | 124 | srcBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 125 | for (row = posy; row < endRow; row++) { |
rgrover1 | 0:62d7cfac67ca | 126 | col = posx; |
rgrover1 | 0:62d7cfac67ca | 127 | bitsToBlitInRow = width; |
rgrover1 | 0:62d7cfac67ca | 128 | destBitIndexMod8 = col & 0x7 /* col % 8 */; |
rgrover1 | 0:62d7cfac67ca | 129 | destByteIndex = col >> 3 /* col / 8 */; |
rgrover1 | 0:62d7cfac67ca | 130 | srcBits = 0; |
rgrover1 | 0:62d7cfac67ca | 131 | |
rgrover1 | 0:62d7cfac67ca | 132 | /* While there are bits in this row remaining to be blitted to |
rgrover1 | 0:62d7cfac67ca | 133 | * the destination, ... */ |
rgrover1 | 0:62d7cfac67ca | 134 | while (bitsToBlitInRow) { |
rgrover1 | 0:62d7cfac67ca | 135 | if ((destBitIndexMod8 == 0) && (bitsToBlitInRow >= 8)) { |
rgrover1 | 0:62d7cfac67ca | 136 | /* We know that destBitIndexMod8 == 0, which means that |
rgrover1 | 0:62d7cfac67ca | 137 | * the destination is byte aligned and we can simply |
rgrover1 | 0:62d7cfac67ca | 138 | * do the equivalent of a memcpy. */ |
rgrover1 | 0:62d7cfac67ca | 139 | while (bitsToBlitInRow >= 8) { |
rgrover1 | 0:62d7cfac67ca | 140 | SHIFT_INTO_SRC_BITS(8); |
rgrover1 | 0:62d7cfac67ca | 141 | setRowByte(row, destByteIndex, srcBits); |
rgrover1 | 0:62d7cfac67ca | 142 | |
rgrover1 | 0:62d7cfac67ca | 143 | bitsToBlitInRow -= 8; |
rgrover1 | 0:62d7cfac67ca | 144 | destByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 145 | } |
rgrover1 | 0:62d7cfac67ca | 146 | } else { |
rgrover1 | 0:62d7cfac67ca | 147 | uint8_t blit; /* number of bits to blit in this iteration */ |
rgrover1 | 0:62d7cfac67ca | 148 | uint8_t mask; |
rgrover1 | 0:62d7cfac67ca | 149 | uint8_t leftShift; |
rgrover1 | 0:62d7cfac67ca | 150 | |
rgrover1 | 0:62d7cfac67ca | 151 | /* This will be a read-modify-write operation, so we |
rgrover1 | 0:62d7cfac67ca | 152 | * need to fetch the destination byte. */ |
rgrover1 | 0:62d7cfac67ca | 153 | destByte = getRowByte(row, destByteIndex); |
rgrover1 | 0:62d7cfac67ca | 154 | |
rgrover1 | 0:62d7cfac67ca | 155 | if ((destBitIndexMod8 + bitsToBlitInRow) >= 8) { |
rgrover1 | 0:62d7cfac67ca | 156 | blit = 8 - destBitIndexMod8; |
rgrover1 | 0:62d7cfac67ca | 157 | leftShift = 0; |
rgrover1 | 0:62d7cfac67ca | 158 | } else { |
rgrover1 | 0:62d7cfac67ca | 159 | blit = bitsToBlitInRow; |
rgrover1 | 0:62d7cfac67ca | 160 | leftShift = (8 - (destBitIndexMod8 + bitsToBlitInRow)); |
rgrover1 | 0:62d7cfac67ca | 161 | } |
rgrover1 | 0:62d7cfac67ca | 162 | |
rgrover1 | 0:62d7cfac67ca | 163 | SHIFT_INTO_SRC_BITS(blit); |
rgrover1 | 0:62d7cfac67ca | 164 | mask = ((uint8_t)((uint8_t)1 << blit) - 1) << leftShift; |
rgrover1 | 0:62d7cfac67ca | 165 | |
rgrover1 | 0:62d7cfac67ca | 166 | /* update destByte */ |
rgrover1 | 0:62d7cfac67ca | 167 | destByte &= ~mask; |
rgrover1 | 0:62d7cfac67ca | 168 | destByte |= ((uint8_t)(srcBits << leftShift) & mask); |
rgrover1 | 0:62d7cfac67ca | 169 | |
rgrover1 | 0:62d7cfac67ca | 170 | setRowByte(row, destByteIndex, destByte); |
rgrover1 | 0:62d7cfac67ca | 171 | |
rgrover1 | 0:62d7cfac67ca | 172 | /* update dest indices */ |
rgrover1 | 0:62d7cfac67ca | 173 | bitsToBlitInRow -= blit; |
rgrover1 | 0:62d7cfac67ca | 174 | destBitIndexMod8 += blit; |
rgrover1 | 0:62d7cfac67ca | 175 | if (destBitIndexMod8 == 8) { |
rgrover1 | 0:62d7cfac67ca | 176 | destBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 177 | destByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 178 | } |
rgrover1 | 0:62d7cfac67ca | 179 | } |
rgrover1 | 0:62d7cfac67ca | 180 | } |
rgrover1 | 0:62d7cfac67ca | 181 | |
rgrover1 | 0:62d7cfac67ca | 182 | /* potentially update srcByteIndex */ |
rgrover1 | 0:62d7cfac67ca | 183 | if (srcBitIndexMod8 != 0) { |
rgrover1 | 0:62d7cfac67ca | 184 | srcBitIndexMod8 = 0; |
rgrover1 | 0:62d7cfac67ca | 185 | srcByteIndex++; |
rgrover1 | 0:62d7cfac67ca | 186 | } |
rgrover1 | 0:62d7cfac67ca | 187 | } |
rgrover1 | 0:62d7cfac67ca | 188 | } |
rgrover1 | 0:62d7cfac67ca | 189 | |
rgrover1 | 0:62d7cfac67ca | 190 | void |
rgrover1 | 0:62d7cfac67ca | 191 | SharpLCD::FrameBuffer::printString(const font_face_t *face, |
rgrover1 | 0:62d7cfac67ca | 192 | unsigned short baselineX, |
rgrover1 | 0:62d7cfac67ca | 193 | unsigned short baselineY, |
rgrover1 | 0:62d7cfac67ca | 194 | font_color_t fgColor, |
rgrover1 | 0:62d7cfac67ca | 195 | const char *string) |
rgrover1 | 0:62d7cfac67ca | 196 | { |
rgrover1 | 0:62d7cfac67ca | 197 | unsigned char ch; |
rgrover1 | 0:62d7cfac67ca | 198 | while ((ch = *string++) != '\0') { |
rgrover1 | 0:62d7cfac67ca | 199 | if ((ch < FONT_LOWEST_SUPPORTED_CHAR_ENCODING) || |
rgrover1 | 0:62d7cfac67ca | 200 | (ch > FONT_HIGHEST_SUPPORTED_CHAR_ENCODING)) { |
rgrover1 | 0:62d7cfac67ca | 201 | // TRACE_WARNING("printString: attempt to render unsupported char (enc: 0x%x)\n", ch); |
rgrover1 | 0:62d7cfac67ca | 202 | continue; |
rgrover1 | 0:62d7cfac67ca | 203 | } |
rgrover1 | 0:62d7cfac67ca | 204 | |
rgrover1 | 0:62d7cfac67ca | 205 | const glyph_t *glyph = &face->glyphs[ch - FONT_LOWEST_SUPPORTED_CHAR_ENCODING]; |
rgrover1 | 0:62d7cfac67ca | 206 | |
rgrover1 | 0:62d7cfac67ca | 207 | if ((glyph->width > 0) && (glyph->height > 0)) { |
rgrover1 | 0:62d7cfac67ca | 208 | bitBlit(&face->bitmaps[glyph->bitmapIndex], /* bitmap */ |
rgrover1 | 0:62d7cfac67ca | 209 | glyph->width, /* width of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 210 | glyph->height, /* height of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 211 | baselineX + glyph->bearingX, /* x-offset for the |
rgrover1 | 0:62d7cfac67ca | 212 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 213 | * corner of the bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 214 | baselineY - glyph->bearingY /* y-offset for the |
rgrover1 | 0:62d7cfac67ca | 215 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 216 | * corner of the bitmap. */ |
rgrover1 | 0:62d7cfac67ca | 217 | ); |
rgrover1 | 0:62d7cfac67ca | 218 | } |
rgrover1 | 0:62d7cfac67ca | 219 | |
rgrover1 | 0:62d7cfac67ca | 220 | baselineX += glyph->advance; |
rgrover1 | 0:62d7cfac67ca | 221 | } |
rgrover1 | 0:62d7cfac67ca | 222 | } |