Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
