This driver is meant for the monochrome LCD display (model no: LS013B4DN04) from Sharp; but it should be easily adaptable to other Sharp displays.
SharpLCD.hpp@2:270ee57c0367, 2014-07-30 (annotated)
- Committer:
- rgrover1
- Date:
- Wed Jul 30 07:53:49 2014 +0000
- Revision:
- 2:270ee57c0367
- Parent:
- 1:ffc1d1d55581
- Child:
- 3:761d0f489b61
Add FrameBuffer::clear()
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
rgrover1 | 0:62d7cfac67ca | 1 | /* mbed Microcontroller Library |
rgrover1 | 0:62d7cfac67ca | 2 | * Copyright (c) 2006-2013 ARM Limited |
rgrover1 | 0:62d7cfac67ca | 3 | * |
rgrover1 | 0:62d7cfac67ca | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
rgrover1 | 0:62d7cfac67ca | 5 | * you may not use this file except in compliance with the License. |
rgrover1 | 0:62d7cfac67ca | 6 | * You may obtain a copy of the License at |
rgrover1 | 0:62d7cfac67ca | 7 | * |
rgrover1 | 0:62d7cfac67ca | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
rgrover1 | 0:62d7cfac67ca | 9 | * |
rgrover1 | 0:62d7cfac67ca | 10 | * Unless required by applicable law or agreed to in writing, software |
rgrover1 | 0:62d7cfac67ca | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
rgrover1 | 0:62d7cfac67ca | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
rgrover1 | 0:62d7cfac67ca | 13 | * See the License for the specific language governing permissions and |
rgrover1 | 0:62d7cfac67ca | 14 | * limitations under the License. |
rgrover1 | 0:62d7cfac67ca | 15 | */ |
rgrover1 | 0:62d7cfac67ca | 16 | |
rgrover1 | 0:62d7cfac67ca | 17 | #include "mbed.h" |
rgrover1 | 1:ffc1d1d55581 | 18 | #include "core_cmInstr.h" |
rgrover1 | 0:62d7cfac67ca | 19 | #include "font.h" |
rgrover1 | 0:62d7cfac67ca | 20 | |
rgrover1 | 0:62d7cfac67ca | 21 | #ifndef __SHARP_LCD_HPP__ |
rgrover1 | 0:62d7cfac67ca | 22 | #define __SHARP_LCD_HPP__ |
rgrover1 | 0:62d7cfac67ca | 23 | |
rgrover1 | 0:62d7cfac67ca | 24 | /** |
rgrover1 | 0:62d7cfac67ca | 25 | * This driver is meant for the monochrome LCD display (model |
rgrover1 | 0:62d7cfac67ca | 26 | * no: LS013B4DN04) from Sharp. |
rgrover1 | 0:62d7cfac67ca | 27 | * |
rgrover1 | 0:62d7cfac67ca | 28 | * The LCD has the following pixel dimensions: width=96pixels, |
rgrover1 | 0:62d7cfac67ca | 29 | * height=96pixels. This is a monochrome display with an inbuilt |
rgrover1 | 0:62d7cfac67ca | 30 | * memory of 1 bit per pixel. If a pixel-bit is set to one, the |
rgrover1 | 0:62d7cfac67ca | 31 | * corresponding pixel will show as black. |
rgrover1 | 0:62d7cfac67ca | 32 | * |
rgrover1 | 0:62d7cfac67ca | 33 | * The LCD memory is accessible to the micro-controller only through a |
rgrover1 | 0:62d7cfac67ca | 34 | * serial interface; and <i>only for write operations</i>. It is |
rgrover1 | 0:62d7cfac67ca | 35 | * necessary for the application to maintain its own frame-buffer |
rgrover1 | 0:62d7cfac67ca | 36 | * memory in the micro-controller's SRAM (see fb_alloc())---the |
rgrover1 | 0:62d7cfac67ca | 37 | * application is not restricted to a single framebuffer; if SRAM size |
rgrover1 | 0:62d7cfac67ca | 38 | * permits, multiple buffers may be employed. In order to update the |
rgrover1 | 0:62d7cfac67ca | 39 | * LCD, the application first draws (bitmaps or text) into some |
rgrover1 | 0:62d7cfac67ca | 40 | * framebuffer memory, and then flushes the framebuffer to the LCD |
rgrover1 | 0:62d7cfac67ca | 41 | * over the serial interface. |
rgrover1 | 0:62d7cfac67ca | 42 | * |
rgrover1 | 0:62d7cfac67ca | 43 | * Here's some sample code to drive the LCD display: |
rgrover1 | 0:62d7cfac67ca | 44 | * |
rgrover1 | 0:62d7cfac67ca | 45 | * DigitalOut led1(LED1); |
rgrover1 | 0:62d7cfac67ca | 46 | * SharpLCD lcd(p9, MBED_SPI0); |
rgrover1 | 0:62d7cfac67ca | 47 | * |
rgrover1 | 0:62d7cfac67ca | 48 | * uint8_t framebuffer[SharpLCD::SIZEOF_FRAMEBUFFER_FOR_ALLOC]; |
rgrover1 | 0:62d7cfac67ca | 49 | * |
rgrover1 | 0:62d7cfac67ca | 50 | * int main(void) |
rgrover1 | 0:62d7cfac67ca | 51 | * { |
rgrover1 | 0:62d7cfac67ca | 52 | * SharpLCD::FrameBuffer fb(framebuffer); |
rgrover1 | 0:62d7cfac67ca | 53 | * |
rgrover1 | 0:62d7cfac67ca | 54 | * lcd.enableDisplay(); |
rgrover1 | 0:62d7cfac67ca | 55 | * lcd.clear(); |
rgrover1 | 0:62d7cfac67ca | 56 | * fb.printString(lookupFontFace("DejaVu Serif", 8), |
rgrover1 | 0:62d7cfac67ca | 57 | * 20, |
rgrover1 | 0:62d7cfac67ca | 58 | * 40, |
rgrover1 | 0:62d7cfac67ca | 59 | * BLACK, |
rgrover1 | 0:62d7cfac67ca | 60 | * "Rohit"); |
rgrover1 | 0:62d7cfac67ca | 61 | * lcd.drawFrameBuffer(fb); |
rgrover1 | 0:62d7cfac67ca | 62 | * |
rgrover1 | 0:62d7cfac67ca | 63 | * led1 = 1; |
rgrover1 | 0:62d7cfac67ca | 64 | * while (true) { |
rgrover1 | 0:62d7cfac67ca | 65 | * wait(0.5); |
rgrover1 | 0:62d7cfac67ca | 66 | * led1 = !led1; |
rgrover1 | 0:62d7cfac67ca | 67 | * } |
rgrover1 | 0:62d7cfac67ca | 68 | * } |
rgrover1 | 0:62d7cfac67ca | 69 | */ |
rgrover1 | 0:62d7cfac67ca | 70 | |
rgrover1 | 0:62d7cfac67ca | 71 | class SharpLCD { |
rgrover1 | 0:62d7cfac67ca | 72 | public: |
rgrover1 | 0:62d7cfac67ca | 73 | class FrameBuffer { |
rgrover1 | 0:62d7cfac67ca | 74 | public: |
rgrover1 | 0:62d7cfac67ca | 75 | /** |
rgrover1 | 0:62d7cfac67ca | 76 | * \brief initialize the hardware dependent component of a given |
rgrover1 | 0:62d7cfac67ca | 77 | * framebuffer; and set it up to show all-white. |
rgrover1 | 0:62d7cfac67ca | 78 | * |
rgrover1 | 0:62d7cfac67ca | 79 | * \note This does not update the LCD automatically; it only |
rgrover1 | 0:62d7cfac67ca | 80 | * initializes a framebuffer. |
rgrover1 | 0:62d7cfac67ca | 81 | * |
rgrover1 | 0:62d7cfac67ca | 82 | * \param[in] fb |
rgrover1 | 0:62d7cfac67ca | 83 | * A memory buffer to initialize. |
rgrover1 | 0:62d7cfac67ca | 84 | */ |
rgrover1 | 0:62d7cfac67ca | 85 | FrameBuffer(uint8_t *fb); |
rgrover1 | 0:62d7cfac67ca | 86 | |
rgrover1 | 0:62d7cfac67ca | 87 | /** |
rgrover1 | 2:270ee57c0367 | 88 | * Clear the framebuffer to prepare for new drawing. The cleared buffer |
rgrover1 | 2:270ee57c0367 | 89 | * still needs to be drawn on the LCD if clearning the LCD is desired. |
rgrover1 | 2:270ee57c0367 | 90 | */ |
rgrover1 | 2:270ee57c0367 | 91 | void clear(void); |
rgrover1 | 2:270ee57c0367 | 92 | |
rgrover1 | 2:270ee57c0367 | 93 | /** |
rgrover1 | 0:62d7cfac67ca | 94 | * \brief Copy over a bitmap to a specified location into the framebuffer. |
rgrover1 | 0:62d7cfac67ca | 95 | * |
rgrover1 | 0:62d7cfac67ca | 96 | * This is the main work-horse for displaying bitmaps on the LCD. We |
rgrover1 | 0:62d7cfac67ca | 97 | * only support mono-chrome bitmaps with an encoding of 1 for white |
rgrover1 | 0:62d7cfac67ca | 98 | * and 0 for black. We have rendering tools to convert a bitmap into |
rgrover1 | 0:62d7cfac67ca | 99 | * the required encoding. |
rgrover1 | 0:62d7cfac67ca | 100 | |
rgrover1 | 0:62d7cfac67ca | 101 | * \note The placement of the target bitmap is limited to the LCD's |
rgrover1 | 0:62d7cfac67ca | 102 | * boundary--otherwise this routine fails. |
rgrover1 | 0:62d7cfac67ca | 103 | * |
rgrover1 | 0:62d7cfac67ca | 104 | * In case you are wondering, 'blit' stands for Block Image Transfer. |
rgrover1 | 0:62d7cfac67ca | 105 | * |
rgrover1 | 0:62d7cfac67ca | 106 | * Sample code: |
rgrover1 | 0:62d7cfac67ca | 107 | * <pre> |
rgrover1 | 0:62d7cfac67ca | 108 | fb_bitBlit(fb, |
rgrover1 | 0:62d7cfac67ca | 109 | (const uint8_t *)pixel_data, |
rgrover1 | 0:62d7cfac67ca | 110 | width, |
rgrover1 | 0:62d7cfac67ca | 111 | height, |
rgrover1 | 0:62d7cfac67ca | 112 | 0, // posx |
rgrover1 | 0:62d7cfac67ca | 113 | 0 // posy |
rgrover1 | 0:62d7cfac67ca | 114 | ); |
rgrover1 | 0:62d7cfac67ca | 115 | lcd_drawFrameBuffer(fb); |
rgrover1 | 0:62d7cfac67ca | 116 | </pre> |
rgrover1 | 0:62d7cfac67ca | 117 | */ |
rgrover1 | 0:62d7cfac67ca | 118 | void bitBlit(const uint8_t *bitmap, |
rgrover1 | 0:62d7cfac67ca | 119 | unsigned int width, /*!< width of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 120 | unsigned int height, /*!< height of the bitmap */ |
rgrover1 | 0:62d7cfac67ca | 121 | unsigned int posx, /*!< x-offset for the |
rgrover1 | 0:62d7cfac67ca | 122 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 123 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 124 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 125 | * corner of the screen */ |
rgrover1 | 0:62d7cfac67ca | 126 | unsigned int posy /*!< y-offset for the |
rgrover1 | 0:62d7cfac67ca | 127 | * placement of the top-left |
rgrover1 | 0:62d7cfac67ca | 128 | * corner of the bitmap |
rgrover1 | 0:62d7cfac67ca | 129 | * w.r.t. the top-left |
rgrover1 | 0:62d7cfac67ca | 130 | * corner of the screen */ |
rgrover1 | 0:62d7cfac67ca | 131 | ); |
rgrover1 | 0:62d7cfac67ca | 132 | |
rgrover1 | 0:62d7cfac67ca | 133 | /* |
rgrover1 | 0:62d7cfac67ca | 134 | * \brief Fetch a byte (8-bit pixel sequence) from a given scan-line |
rgrover1 | 0:62d7cfac67ca | 135 | * in the framebuffer. |
rgrover1 | 0:62d7cfac67ca | 136 | * |
rgrover1 | 0:62d7cfac67ca | 137 | * The scan-line is identified by the row; and pixels are grouped into |
rgrover1 | 0:62d7cfac67ca | 138 | * 8-bit bytes within a row. |
rgrover1 | 0:62d7cfac67ca | 139 | * |
rgrover1 | 0:62d7cfac67ca | 140 | * \note This function is declared inline for a faster implementation. |
rgrover1 | 0:62d7cfac67ca | 141 | * |
rgrover1 | 0:62d7cfac67ca | 142 | * \param[in] framebuffer |
rgrover1 | 0:62d7cfac67ca | 143 | * The framebuffer to fetch the byte from. |
rgrover1 | 0:62d7cfac67ca | 144 | * |
rgrover1 | 0:62d7cfac67ca | 145 | * \param[in] row |
rgrover1 | 0:62d7cfac67ca | 146 | * The row index of the scan line. |
rgrover1 | 0:62d7cfac67ca | 147 | * |
rgrover1 | 0:62d7cfac67ca | 148 | * \param[in] byteIndex |
rgrover1 | 0:62d7cfac67ca | 149 | * The pixel-index expressed as a byte-index. |
rgrover1 | 0:62d7cfac67ca | 150 | */ |
rgrover1 | 0:62d7cfac67ca | 151 | uint8_t |
rgrover1 | 0:62d7cfac67ca | 152 | getRowByte(unsigned int row, unsigned int byteIndex) { |
rgrover1 | 0:62d7cfac67ca | 153 | return buffer[rowColToIndex(row, byteIndex)]; |
rgrover1 | 0:62d7cfac67ca | 154 | } |
rgrover1 | 0:62d7cfac67ca | 155 | |
rgrover1 | 0:62d7cfac67ca | 156 | /* |
rgrover1 | 0:62d7cfac67ca | 157 | * \brief Set a byte (8-bit pixel sequence) for a given scan-line in |
rgrover1 | 0:62d7cfac67ca | 158 | * the framebuffer. |
rgrover1 | 0:62d7cfac67ca | 159 | * |
rgrover1 | 0:62d7cfac67ca | 160 | * The scan-line is identified by the row; and pixels are grouped into |
rgrover1 | 0:62d7cfac67ca | 161 | * 8-bit bytes within a row. |
rgrover1 | 0:62d7cfac67ca | 162 | * |
rgrover1 | 0:62d7cfac67ca | 163 | * \note This function is declared inline for a faster implementation. |
rgrover1 | 0:62d7cfac67ca | 164 | * |
rgrover1 | 0:62d7cfac67ca | 165 | * \param[in] framebuffer |
rgrover1 | 0:62d7cfac67ca | 166 | * The framebuffer to set the byte into. |
rgrover1 | 0:62d7cfac67ca | 167 | * |
rgrover1 | 0:62d7cfac67ca | 168 | * \param[in] row |
rgrover1 | 0:62d7cfac67ca | 169 | * The row index of the scan line. |
rgrover1 | 0:62d7cfac67ca | 170 | * |
rgrover1 | 0:62d7cfac67ca | 171 | * \param[in] byteIndex |
rgrover1 | 0:62d7cfac67ca | 172 | * The pixel-index expressed as a byte-index. |
rgrover1 | 0:62d7cfac67ca | 173 | * |
rgrover1 | 0:62d7cfac67ca | 174 | * \param[in] pixels |
rgrover1 | 0:62d7cfac67ca | 175 | * The actual 8 pixels to set. |
rgrover1 | 0:62d7cfac67ca | 176 | */ |
rgrover1 | 0:62d7cfac67ca | 177 | void |
rgrover1 | 0:62d7cfac67ca | 178 | setRowByte(unsigned int row, unsigned int byteIndex, uint8_t pixels) { |
rgrover1 | 0:62d7cfac67ca | 179 | buffer[rowColToIndex(row, byteIndex)] = pixels; |
rgrover1 | 0:62d7cfac67ca | 180 | } |
rgrover1 | 0:62d7cfac67ca | 181 | |
rgrover1 | 0:62d7cfac67ca | 182 | /** |
rgrover1 | 0:62d7cfac67ca | 183 | * \brief The printf function for the frameBuffer. |
rgrover1 | 0:62d7cfac67ca | 184 | * |
rgrover1 | 0:62d7cfac67ca | 185 | * This can be used to render strings in a given |
rgrover1 | 0:62d7cfac67ca | 186 | * font-face. Internally, it uses fb_bitBlit to bilt the glyphs onto a |
rgrover1 | 0:62d7cfac67ca | 187 | * framebuffer. Currently, since bitBlit doesn't handle the case where |
rgrover1 | 0:62d7cfac67ca | 188 | * a bitmap exceeds the framebuffer's boundary, you must be very |
rgrover1 | 0:62d7cfac67ca | 189 | * careful about the placement of the text string. Later, when |
rgrover1 | 0:62d7cfac67ca | 190 | * fb_bitBlit is able to handle bitmaps which fall outside the LCD's |
rgrover1 | 0:62d7cfac67ca | 191 | * boundary, the rendered text may be clipped if it doesn't fit the |
rgrover1 | 0:62d7cfac67ca | 192 | * frame. |
rgrover1 | 0:62d7cfac67ca | 193 | * |
rgrover1 | 0:62d7cfac67ca | 194 | * \param[in] face |
rgrover1 | 0:62d7cfac67ca | 195 | * The font-face to be used for rendering the text. |
rgrover1 | 0:62d7cfac67ca | 196 | * |
rgrover1 | 0:62d7cfac67ca | 197 | * \param[in] baselineX |
rgrover1 | 0:62d7cfac67ca | 198 | * The X-offset from the left corner of the screen of the starting |
rgrover1 | 0:62d7cfac67ca | 199 | * pen position; this defines the X-coordinate of the baseline. |
rgrover1 | 0:62d7cfac67ca | 200 | * |
rgrover1 | 0:62d7cfac67ca | 201 | * \param[in] baselineY |
rgrover1 | 0:62d7cfac67ca | 202 | * The Y-offset from the top corner of the screen of the starting |
rgrover1 | 0:62d7cfac67ca | 203 | * pen position; this defines the Y-coordinate of the baseline. |
rgrover1 | 0:62d7cfac67ca | 204 | * |
rgrover1 | 0:62d7cfac67ca | 205 | * \param[in] fgColor |
rgrover1 | 0:62d7cfac67ca | 206 | * The foreground colour. |
rgrover1 | 0:62d7cfac67ca | 207 | * |
rgrover1 | 0:62d7cfac67ca | 208 | * \param[in] string |
rgrover1 | 0:62d7cfac67ca | 209 | * The text to be rendered. |
rgrover1 | 0:62d7cfac67ca | 210 | * |
rgrover1 | 0:62d7cfac67ca | 211 | * Sample code: |
rgrover1 | 0:62d7cfac67ca | 212 | * <pre> |
rgrover1 | 0:62d7cfac67ca | 213 | * face = lookupFontFace("DejaVu Serif", 9); |
rgrover1 | 0:62d7cfac67ca | 214 | * if (face == NULL) { |
rgrover1 | 0:62d7cfac67ca | 215 | * TRACE_FATAL("failed to find face for DejaVu Serif; 10\n"); |
rgrover1 | 0:62d7cfac67ca | 216 | * } |
rgrover1 | 0:62d7cfac67ca | 217 | * fb_printString(fb, |
rgrover1 | 0:62d7cfac67ca | 218 | * face, |
rgrover1 | 0:62d7cfac67ca | 219 | * 90, // baselineX |
rgrover1 | 0:62d7cfac67ca | 220 | * 140, // baselineY |
rgrover1 | 0:62d7cfac67ca | 221 | * BLACK, // foregroundColor |
rgrover1 | 0:62d7cfac67ca | 222 | * "Hello Mr. Obama!"); |
rgrover1 | 0:62d7cfac67ca | 223 | * lcd_drawFrameBuffer(fb); |
rgrover1 | 0:62d7cfac67ca | 224 | * </pre> |
rgrover1 | 0:62d7cfac67ca | 225 | */ |
rgrover1 | 0:62d7cfac67ca | 226 | void printString(const font_face_t *face, |
rgrover1 | 0:62d7cfac67ca | 227 | unsigned short baselineX, |
rgrover1 | 0:62d7cfac67ca | 228 | unsigned short baselineY, |
rgrover1 | 0:62d7cfac67ca | 229 | font_color_t fgColor, |
rgrover1 | 0:62d7cfac67ca | 230 | const char *string); |
rgrover1 | 0:62d7cfac67ca | 231 | |
rgrover1 | 0:62d7cfac67ca | 232 | const uint8_t *getBuffer(void) const { |
rgrover1 | 0:62d7cfac67ca | 233 | return (buffer); |
rgrover1 | 0:62d7cfac67ca | 234 | } |
rgrover1 | 0:62d7cfac67ca | 235 | |
rgrover1 | 0:62d7cfac67ca | 236 | uint8_t *getBuffer(void) { |
rgrover1 | 0:62d7cfac67ca | 237 | return (buffer); |
rgrover1 | 0:62d7cfac67ca | 238 | } |
rgrover1 | 0:62d7cfac67ca | 239 | |
rgrover1 | 0:62d7cfac67ca | 240 | private: |
rgrover1 | 0:62d7cfac67ca | 241 | unsigned rowColToIndex(unsigned row, unsigned col) { |
rgrover1 | 0:62d7cfac67ca | 242 | return (row * LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE) + LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA + col; |
rgrover1 | 0:62d7cfac67ca | 243 | } |
rgrover1 | 0:62d7cfac67ca | 244 | |
rgrover1 | 0:62d7cfac67ca | 245 | private: |
rgrover1 | 0:62d7cfac67ca | 246 | uint8_t *const buffer; |
rgrover1 | 0:62d7cfac67ca | 247 | }; |
rgrover1 | 0:62d7cfac67ca | 248 | |
rgrover1 | 0:62d7cfac67ca | 249 | public: |
rgrover1 | 1:ffc1d1d55581 | 250 | SharpLCD(PinName enable, PinName cs, PinName mosi, PinName miso_unused, PinName sclk, PinName _unused = NC) : |
rgrover1 | 1:ffc1d1d55581 | 251 | displayEnable(enable), chipSelect(cs), spi(mosi, miso_unused, sclk, _unused) { |
rgrover1 | 0:62d7cfac67ca | 252 | displayEnable = 0; |
rgrover1 | 0:62d7cfac67ca | 253 | chipSelect = 0; |
rgrover1 | 0:62d7cfac67ca | 254 | spi.frequency(1000000); |
rgrover1 | 0:62d7cfac67ca | 255 | spi.format(8, 0); |
rgrover1 | 0:62d7cfac67ca | 256 | }; |
rgrover1 | 0:62d7cfac67ca | 257 | |
rgrover1 | 0:62d7cfac67ca | 258 | /** |
rgrover1 | 0:62d7cfac67ca | 259 | * \brief Turn on the LCD's display. |
rgrover1 | 0:62d7cfac67ca | 260 | * |
rgrover1 | 0:62d7cfac67ca | 261 | * \note Updates to the LCD's memory won't show up on the display |
rgrover1 | 0:62d7cfac67ca | 262 | * until the display is enabled through this function. |
rgrover1 | 0:62d7cfac67ca | 263 | */ |
rgrover1 | 0:62d7cfac67ca | 264 | void enableDisplay(void); |
rgrover1 | 0:62d7cfac67ca | 265 | |
rgrover1 | 0:62d7cfac67ca | 266 | /** |
rgrover1 | 0:62d7cfac67ca | 267 | * \brief Turn off the LCD's display---i.e. make it go blank. |
rgrover1 | 0:62d7cfac67ca | 268 | * |
rgrover1 | 0:62d7cfac67ca | 269 | * \note The LCD will retain its memory even when the display is disabled. |
rgrover1 | 0:62d7cfac67ca | 270 | * |
rgrover1 | 0:62d7cfac67ca | 271 | * This is different from re-initializing the LCD's display, since it does |
rgrover1 | 0:62d7cfac67ca | 272 | * not affect the LCD memory. When the display is re-enabled, the LCD |
rgrover1 | 0:62d7cfac67ca | 273 | * will show the contents of its memory. |
rgrover1 | 0:62d7cfac67ca | 274 | */ |
rgrover1 | 0:62d7cfac67ca | 275 | void disableDisplay(void); |
rgrover1 | 0:62d7cfac67ca | 276 | |
rgrover1 | 0:62d7cfac67ca | 277 | /** |
rgrover1 | 0:62d7cfac67ca | 278 | * \brief Clear the LCD's display |
rgrover1 | 0:62d7cfac67ca | 279 | * |
rgrover1 | 0:62d7cfac67ca | 280 | * Write all-white to the LCD's memory. If a frameBuffer is passed in |
rgrover1 | 0:62d7cfac67ca | 281 | * then it is re-initialized as well; otherwise this function does not |
rgrover1 | 0:62d7cfac67ca | 282 | * operate on any global frame-buffer and updating any |
rgrover1 | 0:62d7cfac67ca | 283 | * application-specific frameBuffer is still the application's |
rgrover1 | 0:62d7cfac67ca | 284 | * responsibility. |
rgrover1 | 0:62d7cfac67ca | 285 | */ |
rgrover1 | 0:62d7cfac67ca | 286 | void clear(void); |
rgrover1 | 0:62d7cfac67ca | 287 | |
rgrover1 | 0:62d7cfac67ca | 288 | static uint8_t bitReverse8(uint8_t byte) { |
rgrover1 | 1:ffc1d1d55581 | 289 | #if (__CORTEX_M >= 0x03) |
rgrover1 | 1:ffc1d1d55581 | 290 | return (uint8_t)(__RBIT(byte) >> 24); |
rgrover1 | 1:ffc1d1d55581 | 291 | #else /* #if (__CORTEX_M < 0x03) */ |
rgrover1 | 1:ffc1d1d55581 | 292 | uint8_t rev8 = 0; |
rgrover1 | 1:ffc1d1d55581 | 293 | |
rgrover1 | 1:ffc1d1d55581 | 294 | for (unsigned i = 0; i < 8; i++) { |
rgrover1 | 1:ffc1d1d55581 | 295 | if (byte & (1 << i)) { |
rgrover1 | 1:ffc1d1d55581 | 296 | rev8 |= 1 << (7 - i); |
rgrover1 | 1:ffc1d1d55581 | 297 | } |
rgrover1 | 1:ffc1d1d55581 | 298 | } |
rgrover1 | 1:ffc1d1d55581 | 299 | |
rgrover1 | 1:ffc1d1d55581 | 300 | return rev8; |
rgrover1 | 1:ffc1d1d55581 | 301 | #endif /* #if (__CORTEX_M >= 0x03) */ |
rgrover1 | 0:62d7cfac67ca | 302 | } |
rgrover1 | 0:62d7cfac67ca | 303 | |
rgrover1 | 0:62d7cfac67ca | 304 | /** |
rgrover1 | 0:62d7cfac67ca | 305 | * \brief Update LCD using a given framebuffer. |
rgrover1 | 0:62d7cfac67ca | 306 | * |
rgrover1 | 0:62d7cfac67ca | 307 | * The entire contents of the framebuffer will be DMA'd to the LCD; |
rgrover1 | 0:62d7cfac67ca | 308 | * the calling thread will loose the CPU during the transfer, but |
rgrover1 | 0:62d7cfac67ca | 309 | * other threads may remain active in that duration. |
rgrover1 | 0:62d7cfac67ca | 310 | * |
rgrover1 | 0:62d7cfac67ca | 311 | * \param[in] fb |
rgrover1 | 0:62d7cfac67ca | 312 | * The frame buffer to send to the LCD hardware. |
rgrover1 | 0:62d7cfac67ca | 313 | */ |
rgrover1 | 0:62d7cfac67ca | 314 | void drawFrameBuffer(const FrameBuffer &fb); |
rgrover1 | 0:62d7cfac67ca | 315 | |
rgrover1 | 0:62d7cfac67ca | 316 | /** |
rgrover1 | 0:62d7cfac67ca | 317 | * Toggle the VCOM mode of the LCD; it is recommended to trigger this |
rgrover1 | 0:62d7cfac67ca | 318 | * periodically. Check the datasheet. |
rgrover1 | 0:62d7cfac67ca | 319 | */ |
rgrover1 | 0:62d7cfac67ca | 320 | void toggleVCOM(void); |
rgrover1 | 0:62d7cfac67ca | 321 | |
rgrover1 | 0:62d7cfac67ca | 322 | private: |
rgrover1 | 0:62d7cfac67ca | 323 | /** |
rgrover1 | 0:62d7cfac67ca | 324 | * Helper function to write out a buffer onto the LCD's SPI channel. |
rgrover1 | 0:62d7cfac67ca | 325 | */ |
rgrover1 | 0:62d7cfac67ca | 326 | void writeBuffer(const uint8_t *buffer, unsigned len); |
rgrover1 | 0:62d7cfac67ca | 327 | |
rgrover1 | 0:62d7cfac67ca | 328 | public: |
rgrover1 | 0:62d7cfac67ca | 329 | static const unsigned LCD_WIDTH = 96; ///< Constant defining the LCD's geometry. |
rgrover1 | 0:62d7cfac67ca | 330 | static const unsigned LCD_HEIGHT = 96; ///< Constant defining the LCD's geometry. |
rgrover1 | 0:62d7cfac67ca | 331 | static const unsigned LCD_END_OF_DUMMY_SIZE = 2; |
rgrover1 | 0:62d7cfac67ca | 332 | static const unsigned LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA = |
rgrover1 | 0:62d7cfac67ca | 333 | (1 + /* mode byte in SPI update command */ |
rgrover1 | 0:62d7cfac67ca | 334 | 1 /* addr byte in SPI update command */); |
rgrover1 | 0:62d7cfac67ca | 335 | static const unsigned LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE = |
rgrover1 | 0:62d7cfac67ca | 336 | (LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE_METADATA + (LCD_WIDTH / 8)); |
rgrover1 | 0:62d7cfac67ca | 337 | |
rgrover1 | 0:62d7cfac67ca | 338 | static const unsigned SIZEOF_FRAMEBUFFER = (LCD_HEIGHT * LCD_FRAMEBUFFER_SIZEOF_SCAN_LINE); |
rgrover1 | 0:62d7cfac67ca | 339 | static const unsigned SIZEOF_FRAMEBUFFER_FOR_ALLOC = SIZEOF_FRAMEBUFFER + LCD_END_OF_DUMMY_SIZE; |
rgrover1 | 0:62d7cfac67ca | 340 | |
rgrover1 | 0:62d7cfac67ca | 341 | private: |
rgrover1 | 0:62d7cfac67ca | 342 | /* Constants for the LCD's command protocol */ |
rgrover1 | 0:62d7cfac67ca | 343 | static const uint8_t M0_FLAG = 0x80; |
rgrover1 | 0:62d7cfac67ca | 344 | static const uint8_t M1_FLAG = 0x40; |
rgrover1 | 0:62d7cfac67ca | 345 | static const uint8_t M2_FLAG = 0x20; |
rgrover1 | 0:62d7cfac67ca | 346 | static const uint8_t DUMMY8 = 0x00; |
rgrover1 | 0:62d7cfac67ca | 347 | |
rgrover1 | 0:62d7cfac67ca | 348 | private: |
rgrover1 | 0:62d7cfac67ca | 349 | DigitalOut displayEnable; |
rgrover1 | 0:62d7cfac67ca | 350 | DigitalOut chipSelect; |
rgrover1 | 0:62d7cfac67ca | 351 | SPI spi; |
rgrover1 | 0:62d7cfac67ca | 352 | }; |
rgrover1 | 0:62d7cfac67ca | 353 | |
rgrover1 | 0:62d7cfac67ca | 354 | inline void |
rgrover1 | 0:62d7cfac67ca | 355 | SharpLCD::enableDisplay(void) { |
rgrover1 | 0:62d7cfac67ca | 356 | displayEnable = 1; |
rgrover1 | 0:62d7cfac67ca | 357 | } |
rgrover1 | 0:62d7cfac67ca | 358 | |
rgrover1 | 0:62d7cfac67ca | 359 | inline void |
rgrover1 | 0:62d7cfac67ca | 360 | SharpLCD::disableDisplay(void) { |
rgrover1 | 0:62d7cfac67ca | 361 | displayEnable = 0; |
rgrover1 | 0:62d7cfac67ca | 362 | } |
rgrover1 | 0:62d7cfac67ca | 363 | |
rgrover1 | 0:62d7cfac67ca | 364 | #endif /* #ifndef __SHARP_LCD_HPP__ */ |