Sharp LCD library forked to use a Lucida 8 pt font
Fork of SharpLCD by
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__ */
Generated on Thu Jul 14 2022 05:46:27 by
1.7.2
