Sharp LCD library forked to use a Lucida 8 pt font

Fork of SharpLCD by Rohit Grover

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SharpLCD.hpp Source File

SharpLCD.hpp

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 "mbed.h"
00018 #include "core_cmInstr.h"
00019 //#include "font.h"
00020 #include "dotfont.h"
00021 
00022 #ifndef __SHARP_LCD_HPP__
00023 #define __SHARP_LCD_HPP__
00024 
00025 /**
00026  * This driver is meant for the monochrome LCD display (model
00027  * no: LS013B4DN04) from Sharp.
00028  *
00029  * The LCD has the following pixel dimensions: width=96pixels,
00030  * height=96pixels. This is a monochrome display with an inbuilt
00031  * memory of 1 bit per pixel. If a pixel-bit is set to one, the
00032  * corresponding pixel will show as black.
00033  *
00034  * The LCD memory is accessible to the micro-controller only through a
00035  * serial interface; and <i>only for write operations</i>. It is
00036  * necessary for the application to maintain its own frame-buffer
00037  * memory in the micro-controller's SRAM (see fb_alloc())---the
00038  * application is not restricted to a single framebuffer; if SRAM size
00039  * permits, multiple buffers may be employed. In order to update the
00040  * LCD, the application first draws (bitmaps or text) into some
00041  * framebuffer memory, and then flushes the framebuffer to the LCD
00042  * over the serial interface.
00043  *
00044  * Here's some sample code to drive the LCD display:
00045  *
00046  *     DigitalOut led1(LED1);
00047  *     SharpLCD lcd(p9, MBED_SPI0);
00048  *
00049  *     uint8_t framebuffer[SharpLCD::SIZEOF_FRAMEBUFFER_FOR_ALLOC];
00050  *
00051  *     int main(void)
00052  *     {
00053  *         SharpLCD::FrameBuffer fb(framebuffer);
00054  *
00055  *         lcd.enableDisplay();
00056  *         lcd.clear();
00057  *         fb.printString(lookupFontFace("DejaVu Serif", 8),
00058  *                        20,
00059  *                        40,
00060  *                        BLACK,
00061  *                        "Rohit");
00062  *         lcd.drawFrameBuffer(fb);
00063  *
00064  *         led1 = 1;
00065  *         while (true) {
00066  *             wait(0.5);
00067  *             led1 = !led1;
00068  *         }
00069  *     }
00070  */
00071 
00072 class SharpLCD {
00073 public:
00074     class FrameBuffer {
00075     public:
00076         /**
00077          * \brief initialize the hardware dependent component of a given
00078          * framebuffer; and set it up to show all-white.
00079          *
00080          * \note This does not update the LCD automatically; it only
00081          * initializes a framebuffer.
00082          *
00083          * \param[in] fb
00084          *     A memory buffer to initialize.
00085          */
00086         FrameBuffer(uint8_t *fb);
00087 
00088         /**
00089          * Clear the framebuffer to prepare for new drawing. The cleared buffer
00090          * still needs to be drawn on the LCD if clearning the LCD is desired.
00091          */
00092         void clear(void);
00093 
00094         /**
00095          * \brief Copy over a bitmap to a specified location into the framebuffer.
00096          *
00097          * This is the main work-horse for displaying bitmaps on the LCD. We
00098          * only support mono-chrome bitmaps with an encoding of 1 for white
00099          * and 0 for black. We have rendering tools to convert a bitmap into
00100          * the required encoding.
00101 
00102          * \note The placement of the target bitmap is limited to the LCD's
00103          * boundary--otherwise this routine fails.
00104          *
00105          * In case you are wondering, 'blit' stands for Block Image Transfer.
00106          *
00107          * Sample code:
00108          * <pre>
00109                 fb_bitBlit(fb,
00110                            (const uint8_t *)pixel_data,
00111                            width,
00112                            height,
00113                            0, // posx
00114                            0  // posy
00115                            );
00116                 lcd_drawFrameBuffer(fb);
00117         </pre>
00118          */
00119         void bitBlit(const uint8_t *bitmap,
00120                      unsigned int   width,  /*!< width of the bitmap */
00121                      unsigned int   height, /*!< height of the bitmap */
00122                      unsigned int   posx,   /*!< x-offset for the
00123                                              * placement of the top-left
00124                                              * corner of the bitmap
00125                                              * w.r.t. the top-left
00126                                              * corner of the screen */
00127                      unsigned int   posy    /*!< y-offset for the
00128                                              * placement of the top-left
00129                                              * corner of the bitmap
00130                                              * w.r.t. the top-left
00131                                              * corner of the screen */
00132             );
00133 
00134         /*
00135          * \brief Fetch a byte (8-bit pixel sequence) from a given scan-line
00136          * in the framebuffer.
00137          *
00138          * The scan-line is identified by the row; and pixels are grouped into
00139          * 8-bit bytes within a row.
00140          *
00141          * \note This function is declared inline for a faster implementation.
00142          *
00143          * \param[in] framebuffer
00144          *     The framebuffer to fetch the byte from.
00145          *
00146          * \param[in] row
00147          *     The row index of the scan line.
00148          *
00149          * \param[in] byteIndex
00150          *     The pixel-index expressed as a byte-index.
00151          */
00152         uint8_t
00153         getRowByte(unsigned int row, unsigned int byteIndex) {
00154             return buffer[rowColToIndex(row, byteIndex)];
00155         }
00156 
00157         /*
00158          * \brief Set a byte (8-bit pixel sequence) for a given scan-line in
00159          * the framebuffer.
00160          *
00161          * The scan-line is identified by the row; and pixels are grouped into
00162          * 8-bit bytes within a row.
00163          *
00164          * \note This function is declared inline for a faster implementation.
00165          *
00166          * \param[in] framebuffer
00167          *     The framebuffer to set the byte into.
00168          *
00169          * \param[in] row
00170          *     The row index of the scan line.
00171          *
00172          * \param[in] byteIndex
00173          *     The pixel-index expressed as a byte-index.
00174          *
00175          * \param[in] pixels
00176          *     The actual 8 pixels to set.
00177          */
00178         void
00179         setRowByte(unsigned int row, unsigned int byteIndex, uint8_t pixels) {
00180             buffer[rowColToIndex(row, byteIndex)] = pixels;
00181         }
00182 
00183         /**
00184          * \brief The printf function for the frameBuffer.
00185          *
00186          * This can be used to render strings in a given
00187          * font-face. Internally, it uses fb_bitBlit to bilt the glyphs onto a
00188          * framebuffer. Currently, since bitBlit doesn't handle the case where
00189          * a bitmap exceeds the framebuffer's boundary, you must be very
00190          * careful about the placement of the text string. Later, when
00191          * fb_bitBlit is able to handle bitmaps which fall outside the LCD's
00192          * boundary, the rendered text may be clipped if it doesn't fit the
00193          * frame.
00194          *
00195          * \param[in] face
00196          *     The font-face to be used for rendering the text.
00197          *
00198          * \param[in] baselineX
00199          *     The X-offset from the left corner of the screen of the starting
00200          *     pen position; this defines the X-coordinate of the baseline.
00201          *
00202          * \param[in] baselineY
00203          *     The Y-offset from the top corner of the screen of the starting
00204          *     pen position; this defines the Y-coordinate of the baseline.
00205          *
00206          * \param[in] fgColor
00207          *     The foreground colour.
00208          *
00209          * \param[in] string
00210          *     The text to be rendered.
00211          *
00212          * Sample code:
00213          * <pre>
00214          *      face = lookupFontFace("DejaVu Serif", 9);
00215          *      if (face == NULL) {
00216          *          TRACE_FATAL("failed to find face for DejaVu Serif; 10\n");
00217          *      }
00218          *      fb_printString(fb,
00219          *                     face,
00220          *                     90,      // baselineX
00221          *                     140,     // baselineY
00222          *                     BLACK,   // foregroundColor
00223          *                     "Hello Mr. Obama!");
00224          *      lcd_drawFrameBuffer(fb);
00225          * </pre>
00226          */
00227 //      void printString(const font_face_t *face,
00228 //                         unsigned short     baselineX,
00229 //                         unsigned short     baselineY,
00230 //                         font_color_t       fgColor,
00231 //                         const char        *string);
00232         
00233         void printString(const FONT_INFO *face,
00234                          unsigned short     baselineX,
00235                          unsigned short     baselineY,
00236                          const char        *string);
00237 
00238         const uint8_t *getBuffer(void) const {
00239             return (buffer);
00240         }
00241 
00242         uint8_t *getBuffer(void) {
00243             return (buffer);
00244         }
00245 
00246     private:
00247         unsigned rowColToIndex(unsigned row, unsigned col) {
00248             return (row * LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE) + LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA + col;
00249         }
00250 
00251     private:
00252         uint8_t *const buffer;
00253     };
00254 
00255 public:
00256     SharpLCD(PinName enable, PinName cs, PinName mosi, PinName miso_unused, PinName sclk, PinName _unused = NC) :
00257         displayEnable(enable, 0), chipSelect(cs, 0), spi(mosi, miso_unused, sclk, _unused) {
00258         spi.frequency(1000000);
00259         spi.format(8, 0);
00260     };
00261 
00262     /**
00263      * \brief Turn on the LCD's display.
00264      *
00265      * \note Updates to the LCD's memory won't show up on the display
00266      * until the display is enabled through this function.
00267      */
00268     void enableDisplay(void);
00269 
00270     /**
00271      * \brief Turn off the LCD's display---i.e. make it go blank.
00272      *
00273      * \note The LCD will retain its memory even when the display is disabled.
00274      *
00275      * This is different from re-initializing the LCD's display, since it does
00276      * not affect the LCD memory. When the display is re-enabled, the LCD
00277      * will show the contents of its memory.
00278      */
00279     void disableDisplay(void);
00280 
00281     /**
00282      * \brief Clear the LCD's display
00283      *
00284      * Write all-white to the LCD's memory.  If a frameBuffer is passed in
00285      * then it is re-initialized as well; otherwise this function does not
00286      * operate on any global frame-buffer and updating any
00287      * application-specific frameBuffer is still the application's
00288      * responsibility.
00289      */
00290     void clear(void);
00291 
00292     static uint8_t bitReverse8(uint8_t byte) {
00293         #if (__CORTEX_M >= 0x03)
00294             return (uint8_t)(__RBIT(byte) >> 24);
00295         #else /* #if (__CORTEX_M < 0x03) */
00296             uint8_t rev8 = 0;
00297 
00298             for (unsigned i = 0; i < 8; i++) {
00299                 if (byte & (1 << i)) {
00300                     rev8 |= 1 << (7 - i);
00301                 }
00302             }
00303 
00304             return rev8;
00305         #endif /* #if (__CORTEX_M >= 0x03) */
00306     }
00307 
00308     /**
00309      * \brief Update LCD using a given framebuffer.
00310      *
00311      * The entire contents of the framebuffer will be DMA'd to the LCD;
00312      * the calling thread will loose the CPU during the transfer, but
00313      * other threads may remain active in that duration.
00314      *
00315      * \param[in] fb
00316      *     The frame buffer to send to the LCD hardware.
00317      */
00318     void drawFrameBuffer(const FrameBuffer &fb);
00319 
00320     /**
00321      * Toggle the VCOM mode of the LCD; it is recommended to trigger this
00322      * periodically. Check the datasheet.
00323      */
00324     void toggleVCOM(void);
00325 
00326 private:
00327     /**
00328      * Helper function to write out a buffer onto the LCD's SPI channel.
00329      */
00330     void writeBuffer(const uint8_t *buffer, unsigned len);
00331 
00332 public:
00333     static const unsigned LCD_WIDTH  = 96;  ///< Constant defining the LCD's geometry.
00334     static const unsigned LCD_HEIGHT = 96;  ///< Constant defining the LCD's geometry.
00335     static const unsigned LCD_END_OF_DUMMY_SIZE = 2;
00336     static const unsigned LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA =
00337         (1 + /* mode byte in SPI update command */
00338          1   /* addr byte in SPI update command */);
00339     static const unsigned LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE =
00340         (LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA + (LCD_WIDTH / 8));
00341 
00342     static const unsigned SIZEOF_FRAMEBUFFER = (LCD_HEIGHT * LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE);
00343     static const unsigned SIZEOF_FRAMEBUFFER_FOR_ALLOC = SIZEOF_FRAMEBUFFER + LCD_END_OF_DUMMY_SIZE;
00344 
00345 private:
00346     /* Constants for the LCD's command protocol */
00347     static const uint8_t M0_FLAG = 0x80;
00348     static const uint8_t M1_FLAG = 0x40;
00349     static const uint8_t M2_FLAG = 0x20;
00350     static const uint8_t DUMMY8  = 0x00;
00351 
00352 private:
00353     DigitalOut displayEnable;
00354     DigitalOut chipSelect;
00355     SPI        spi;
00356 };
00357 
00358 inline void
00359 SharpLCD::enableDisplay(void) {
00360     displayEnable = 1;
00361 }
00362 
00363 inline void
00364 SharpLCD::disableDisplay(void) {
00365     displayEnable = 0;
00366 }
00367 
00368 #endif /* #ifndef __SHARP_LCD_HPP__ */