This driver is meant for the monochrome LCD display (model no: LS013B4DN04) from Sharp; but it should be easily adaptable to other Sharp displays.

Dependents:   sharpLCD-demo

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?

UserRevisionLine numberNew 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 }