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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FrameBuffer.cpp Source File

FrameBuffer.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "SharpLCD.hpp"
00018 
00019 SharpLCD::FrameBuffer::FrameBuffer(uint8_t *fb) : buffer(fb)
00020 {
00021     clear();
00022 
00023     /* Make sure the dummy bytes are clear */
00024     ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER]     = DUMMY8;
00025     ((uint8_t *)buffer)[SIZEOF_FRAMEBUFFER + 1] = DUMMY8;
00026 }
00027 
00028 void
00029 SharpLCD::FrameBuffer::clear(void)
00030 {
00031     uint8_t     *pfb;
00032     unsigned int row;
00033     unsigned int index;
00034 
00035     /* initialize the frame buffer */
00036     pfb = buffer;
00037     for (row = 0; row < LCD_HEIGHT; row++) {
00038         for (index = 0; index < LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE; index++) {
00039             switch (index) {
00040             case 0:
00041                 *pfb++ = M0_FLAG; /* update line command */
00042                 break;
00043             case 1:
00044                 *pfb++ = bitReverse8(row + 1);
00045                 break;
00046             default:
00047                 *pfb++ = 0xFF; /* all white */
00048                 break;
00049             }
00050         }
00051     }
00052 }
00053 
00054 void
00055 SharpLCD::FrameBuffer::bitBlit(const uint8_t *bitmap,
00056                                unsigned int   width,  /* width of the bitmap */
00057                                unsigned int   height, /* height of the bitmap */
00058                                unsigned int   posx,   /* x-offset of the top-left
00059                                                        * corner of the bitmap
00060                                                        * w.r.t. the top-left
00061                                                        * corner of the screen */
00062                                unsigned int   posy    /* y-offset of the top-left
00063                                                        * corner of the bitmap
00064                                                        * w.r.t. the top-left
00065                                                        * corner of the screen */)
00066 {
00067     unsigned int row;
00068     unsigned int col;
00069     unsigned int bitsToBlitInRow;
00070     unsigned int destByteIndex; /* within the current row */
00071     unsigned int destBitIndexMod8; /* bits to the right of this index in
00072                                     * 'destByte' need to be blitted next;
00073                                     * MSB has index 0. */
00074     unsigned int srcByteIndex;  /* byte index within the source bitmap */
00075     unsigned int srcBitIndexMod8; /* bits to the right of this index in
00076                                    * source byte (at index srcByteIndex)
00077                                    * need to be blitted to the dest; MSB
00078                                    * has index 0. */
00079     const unsigned int endRow = posy + height;
00080     uint8_t      destByte;
00081     uint8_t      srcBits;
00082 
00083 #if 0
00084     unsigned long current_cycle_count = Get_system_register(AVR32_COUNT);
00085 #endif
00086 
00087     // ASSERT(bitmap != NULL, "%s: passed in a NULL bitmap", __FUNCTION__);
00088     // ASSERT(width > 0, "%s: passed in an invalid width", __FUNCTION__);
00089     // ASSERT(height > 0, "%s: passed in an invalid height", __FUNCTION__);
00090     // ASSERT(posx + width <= LCD_WIDTH,
00091     //        "%s: bitmap will exceed the screen width", __FUNCTION__);
00092     // ASSERT(posy + height <= LCD_HEIGHT,
00093     //        "%s: bitmap will exceed the screen height", __FUNCTION__);
00094 
00095     /*
00096      * A couple of helpful macros to maintain a source bitstream.
00097      */
00098 #define SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(M) do {                \
00099         uint8_t mask;                                                   \
00100                                                                         \
00101         mask      = ((uint8_t)((uint8_t)1 << (M)) - 1);                 \
00102         srcBits <<= (M);                                                \
00103         srcBits  |= (bitmap[srcByteIndex] >> (8 - (srcBitIndexMod8 + (M)))) & mask; \
00104                                                                         \
00105         /* update the indices */                                        \
00106         srcBitIndexMod8 += (M);                                         \
00107         if (srcBitIndexMod8 == 8) {                                     \
00108             srcBitIndexMod8 = 0;                                        \
00109             srcByteIndex++;                                             \
00110         }                                                               \
00111 } while (0)
00112 
00113 /* Left-shift N bits into srcBits; fetching them from the source
00114  * bitmap. */
00115 #define SHIFT_INTO_SRC_BITS(N) do {                                          \
00116         uint8_t bitsToShift;                                                 \
00117                                                                              \
00118         bitsToShift = (N);                                                   \
00119                                                                              \
00120         if ((srcBitIndexMod8 + (N)) > 8) {                                   \
00121             bitsToShift = 8 - srcBitIndexMod8;                               \
00122             SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift);           \
00123             bitsToShift = (N) - bitsToShift;                                 \
00124         }                                                                    \
00125                                                                              \
00126         SHIFT_INTO_SRC_BITS_FROM_SINGLE_SRC_BYTE(bitsToShift);               \
00127 } while (0)
00128 
00129     srcByteIndex    = 0;
00130     srcBitIndexMod8 = 0;
00131     for (row = posy; row < endRow; row++) {
00132         col              = posx;
00133         bitsToBlitInRow  = width;
00134         destBitIndexMod8 = col & 0x7  /* col % 8 */;
00135         destByteIndex    = col >> 3   /* col / 8 */;
00136         srcBits          = 0;
00137 
00138         /* While there are bits in this row remaining to be blitted to
00139          * the destination, ... */
00140         while (bitsToBlitInRow) {
00141             if ((destBitIndexMod8 == 0) && (bitsToBlitInRow >= 8)) {
00142                 /* We know that destBitIndexMod8 == 0, which means that
00143                  * the destination is byte aligned and we can simply
00144                  * do the equivalent of a memcpy. */
00145                 while (bitsToBlitInRow >= 8) {
00146                     SHIFT_INTO_SRC_BITS(8);
00147                     setRowByte(row, destByteIndex, srcBits);
00148 
00149                     bitsToBlitInRow -= 8;
00150                     destByteIndex++;
00151                 }
00152             } else {
00153                 uint8_t blit; /* number of bits to blit in this iteration */
00154                 uint8_t mask;
00155                 uint8_t leftShift;
00156 
00157                 /* This will be a read-modify-write operation, so we
00158                  * need to fetch the destination byte. */
00159                 destByte = getRowByte(row, destByteIndex);
00160 
00161                 if ((destBitIndexMod8 + bitsToBlitInRow) >= 8) {
00162                     blit      = 8 - destBitIndexMod8;
00163                     leftShift = 0;
00164                 } else {
00165                     blit      = bitsToBlitInRow;
00166                     leftShift = (8 - (destBitIndexMod8 + bitsToBlitInRow));
00167                 }
00168 
00169                 SHIFT_INTO_SRC_BITS(blit);
00170                 mask = ((uint8_t)((uint8_t)1 << blit) - 1) << leftShift;
00171 
00172                 /* update destByte */
00173                 destByte &= ~mask;
00174                 destByte |= ((uint8_t)(srcBits << leftShift) & mask);
00175 
00176                 setRowByte(row, destByteIndex, destByte);
00177 
00178                 /* update dest indices */
00179                 bitsToBlitInRow  -= blit;
00180                 destBitIndexMod8 += blit;
00181                 if (destBitIndexMod8 == 8) {
00182                     destBitIndexMod8 = 0;
00183                     destByteIndex++;
00184                 }
00185             }
00186         }
00187 
00188         /* potentially update srcByteIndex */
00189         if (srcBitIndexMod8 != 0) {
00190             srcBitIndexMod8 = 0;
00191             srcByteIndex++;
00192         }
00193     }
00194 }
00195 
00196 void
00197 SharpLCD::FrameBuffer::printString(const font_face_t *face,
00198                                    unsigned short     baselineX,
00199                                    unsigned short     baselineY,
00200                                    font_color_t       fgColor,
00201                                    const char        *string)
00202 {
00203     unsigned char ch;
00204     while ((ch = *string++) != '\0') {
00205         if ((ch < FONT_LOWEST_SUPPORTED_CHAR_ENCODING) ||
00206             (ch > FONT_HIGHEST_SUPPORTED_CHAR_ENCODING)) {
00207             // TRACE_WARNING("printString: attempt to render unsupported char (enc: 0x%x)\n", ch);
00208             continue;
00209         }
00210 
00211         const glyph_t *glyph = &face->glyphs[ch - FONT_LOWEST_SUPPORTED_CHAR_ENCODING];
00212 
00213         if ((glyph->width > 0) && (glyph->height > 0)) {
00214             bitBlit(&face->bitmaps[glyph->bitmapIndex], /* bitmap */
00215                     glyph->width,  /* width of the bitmap */
00216                     glyph->height, /* height of the bitmap */
00217                     baselineX + glyph->bearingX, /* x-offset for the
00218                                                   * placement of the top-left
00219                                                   * corner of the bitmap. */
00220                     baselineY - glyph->bearingY  /* y-offset for the
00221                                                   * placement of the top-left
00222                                                   * corner of the bitmap. */
00223                );
00224         }
00225 
00226         baselineX += glyph->advance;
00227     }
00228 }