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
- Committer:
- rgrover1
- Date:
- 2014-07-30
- Revision:
- 2:270ee57c0367
- Parent:
- 0:62d7cfac67ca
File content as of revision 2:270ee57c0367:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "SharpLCD.hpp" SharpLCD::FrameBuffer::FrameBuffer(uint8_t *fb) : buffer(fb) { clear(); /* Make sure the dummy bytes are clear */ ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER] = DUMMY8; ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER + 1] = DUMMY8; } void SharpLCD::FrameBuffer::clear(void) { uint8_t *pfb; unsigned int row; unsigned int index; /* initialize the frame buffer */ pfb = buffer; for (row = 0; row < LCD_HEIGHT; row++) { for (index = 0; index < LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE; index++) { switch (index) { case 0: *pfb++ = M0_FLAG; /* update line command */ break; case 1: *pfb++ = bitReverse8(row + 1); break; default: *pfb++ = 0xFF; /* all white */ break; } } } } void SharpLCD::FrameBuffer::bitBlit(const uint8_t *bitmap, unsigned int width, /* width of the bitmap */ unsigned int height, /* height of the bitmap */ unsigned int posx, /* x-offset of the top-left * corner of the bitmap * w.r.t. the top-left * corner of the screen */ unsigned int posy /* y-offset of the top-left * corner of the bitmap * w.r.t. the top-left * corner of the screen */) { unsigned int row; unsigned int col; unsigned int bitsToBlitInRow; unsigned int destByteIndex; /* within the current row */ unsigned int destBitIndexMod8; /* bits to the right of this index in * 'destByte' need to be blitted next; * MSB has index 0. */ unsigned int srcByteIndex; /* byte index within the source bitmap */ unsigned int srcBitIndexMod8; /* bits to the right of this index in * source byte (at index srcByteIndex) * need to be blitted to the dest; MSB * has index 0. */ const unsigned int endRow = posy + height; uint8_t destByte; uint8_t srcBits; #if 0 unsigned long current_cycle_count = Get_system_register(AVR32_COUNT); #endif // ASSERT(bitmap != NULL, "%s: passed in a NULL bitmap", __FUNCTION__); // ASSERT(width > 0, "%s: passed in an invalid width", __FUNCTION__); // ASSERT(height > 0, "%s: passed in an invalid height", __FUNCTION__); // ASSERT(posx + width <= LCD_WIDTH, // "%s: bitmap will exceed the screen width", __FUNCTION__); // ASSERT(posy + height <= LCD_HEIGHT, // "%s: bitmap will exceed the screen height", __FUNCTION__); /* * A couple of helpful macros to maintain a source bitstream. */ #define SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(M) do { \ uint8_t mask; \ \ mask = ((uint8_t)((uint8_t)1 << (M)) - 1); \ srcBits <<= (M); \ srcBits |= (bitmap[srcByteIndex] >> (8 - (srcBitIndexMod8 + (M)))) & mask; \ \ /* update the indices */ \ srcBitIndexMod8 += (M); \ if (srcBitIndexMod8 == 8) { \ srcBitIndexMod8 = 0; \ srcByteIndex++; \ } \ } while (0) /* Left-shift N bits into srcBits; fetching them from the source * bitmap. */ #define SHIFT_INTO_SRC_BITS(N) do { \ uint8_t bitsToShift; \ \ bitsToShift = (N); \ \ if ((srcBitIndexMod8 + (N)) > 8) { \ bitsToShift = 8 - srcBitIndexMod8; \ SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ bitsToShift = (N) - bitsToShift; \ } \ \ SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift); \ } while (0) srcByteIndex = 0; srcBitIndexMod8 = 0; for (row = posy; row < endRow; row++) { col = posx; bitsToBlitInRow = width; destBitIndexMod8 = col & 0x7 /* col % 8 */; destByteIndex = col >> 3 /* col / 8 */; srcBits = 0; /* While there are bits in this row remaining to be blitted to * the destination, ... */ while (bitsToBlitInRow) { if ((destBitIndexMod8 == 0) && (bitsToBlitInRow >= 8)) { /* We know that destBitIndexMod8 == 0, which means that * the destination is byte aligned and we can simply * do the equivalent of a memcpy. */ while (bitsToBlitInRow >= 8) { SHIFT_INTO_SRC_BITS(8); setRowByte(row, destByteIndex, srcBits); bitsToBlitInRow -= 8; destByteIndex++; } } else { uint8_t blit; /* number of bits to blit in this iteration */ uint8_t mask; uint8_t leftShift; /* This will be a read-modify-write operation, so we * need to fetch the destination byte. */ destByte = getRowByte(row, destByteIndex); if ((destBitIndexMod8 + bitsToBlitInRow) >= 8) { blit = 8 - destBitIndexMod8; leftShift = 0; } else { blit = bitsToBlitInRow; leftShift = (8 - (destBitIndexMod8 + bitsToBlitInRow)); } SHIFT_INTO_SRC_BITS(blit); mask = ((uint8_t)((uint8_t)1 << blit) - 1) << leftShift; /* update destByte */ destByte &= ~mask; destByte |= ((uint8_t)(srcBits << leftShift) & mask); setRowByte(row, destByteIndex, destByte); /* update dest indices */ bitsToBlitInRow -= blit; destBitIndexMod8 += blit; if (destBitIndexMod8 == 8) { destBitIndexMod8 = 0; destByteIndex++; } } } /* potentially update srcByteIndex */ if (srcBitIndexMod8 != 0) { srcBitIndexMod8 = 0; srcByteIndex++; } } } void SharpLCD::FrameBuffer::printString(const font_face_t *face, unsigned short baselineX, unsigned short baselineY, font_color_t fgColor, const char *string) { unsigned char ch; while ((ch = *string++) != '\0') { if ((ch < FONT_LOWEST_SUPPORTED_CHAR_ENCODING) || (ch > FONT_HIGHEST_SUPPORTED_CHAR_ENCODING)) { // TRACE_WARNING("printString: attempt to render unsupported char (enc: 0x%x)\n", ch); continue; } const glyph_t *glyph = &face->glyphs[ch - FONT_LOWEST_SUPPORTED_CHAR_ENCODING]; if ((glyph->width > 0) && (glyph->height > 0)) { bitBlit(&face->bitmaps[glyph->bitmapIndex], /* bitmap */ glyph->width, /* width of the bitmap */ glyph->height, /* height of the bitmap */ baselineX + glyph->bearingX, /* x-offset for the * placement of the top-left * corner of the bitmap. */ baselineY - glyph->bearingY /* y-offset for the * placement of the top-left * corner of the bitmap. */ ); } baselineX += glyph->advance; } }