Fork of Silabs MemoryLCD library
Dependents: demoUI whrmDemoUI Host_Software_MAX32664GWEB_HR_EXTENDED Host_Software_MAX32664GWEC_SpO2_HR-_EXTE ... more
C++ library for Sharp Microelectronics 1.28 inch LCD TFT, LS013B7DH03, SPI bus. Forked from Silicon Labs MemoryLCD display driver.
LS013B7DH03.cpp@2:2f10f00fe56c, 2015-04-14 (annotated)
- Committer:
- Steven Cooreman
- Date:
- Tue Apr 14 15:25:58 2015 -0400
- Revision:
- 2:2f10f00fe56c
- Parent:
- 0:a0faa86660d4
- Child:
- 12:ca0bcb4777e9
Move to event_callback_t for xfer callbacks
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Steven Cooreman |
0:a0faa86660d4 | 1 | /***************************************************************************//** |
Steven Cooreman |
0:a0faa86660d4 | 2 | * @file LS013B7DH03.cpp |
Steven Cooreman |
0:a0faa86660d4 | 3 | * @brief Driver class for the Sharp LS013B7DH03 memory LCD on some kits. |
Steven Cooreman |
0:a0faa86660d4 | 4 | ******************************************************************************* |
Steven Cooreman |
0:a0faa86660d4 | 5 | * @section License |
Steven Cooreman |
0:a0faa86660d4 | 6 | * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> |
Steven Cooreman |
0:a0faa86660d4 | 7 | ******************************************************************************* |
Steven Cooreman |
0:a0faa86660d4 | 8 | * |
Steven Cooreman |
0:a0faa86660d4 | 9 | * Permission is granted to anyone to use this software for any purpose, |
Steven Cooreman |
0:a0faa86660d4 | 10 | * including commercial applications, and to alter it and redistribute it |
Steven Cooreman |
0:a0faa86660d4 | 11 | * freely, subject to the following restrictions: |
Steven Cooreman |
0:a0faa86660d4 | 12 | * |
Steven Cooreman |
0:a0faa86660d4 | 13 | * 1. The origin of this software must not be misrepresented; you must not |
Steven Cooreman |
0:a0faa86660d4 | 14 | * claim that you wrote the original software. |
Steven Cooreman |
0:a0faa86660d4 | 15 | * 2. Altered source versions must be plainly marked as such, and must not be |
Steven Cooreman |
0:a0faa86660d4 | 16 | * misrepresented as being the original software. |
Steven Cooreman |
0:a0faa86660d4 | 17 | * 3. This notice may not be removed or altered from any source distribution. |
Steven Cooreman |
0:a0faa86660d4 | 18 | * |
Steven Cooreman |
0:a0faa86660d4 | 19 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
Steven Cooreman |
0:a0faa86660d4 | 20 | * obligation to support this Software. Silicon Labs is providing the |
Steven Cooreman |
0:a0faa86660d4 | 21 | * Software "AS IS", with no express or implied warranties of any kind, |
Steven Cooreman |
0:a0faa86660d4 | 22 | * including, but not limited to, any implied warranties of merchantability |
Steven Cooreman |
0:a0faa86660d4 | 23 | * or fitness for any particular purpose or warranties against infringement |
Steven Cooreman |
0:a0faa86660d4 | 24 | * of any proprietary rights of a third party. |
Steven Cooreman |
0:a0faa86660d4 | 25 | * |
Steven Cooreman |
0:a0faa86660d4 | 26 | * Silicon Labs will not be liable for any consequential, incidental, or |
Steven Cooreman |
0:a0faa86660d4 | 27 | * special damages, or any other relief, or for any claim by any third party, |
Steven Cooreman |
0:a0faa86660d4 | 28 | * arising from your use of this Software. |
Steven Cooreman |
0:a0faa86660d4 | 29 | * |
Steven Cooreman |
0:a0faa86660d4 | 30 | ******************************************************************************/ |
Steven Cooreman |
0:a0faa86660d4 | 31 | |
Steven Cooreman |
0:a0faa86660d4 | 32 | #include <mbed.h> |
Steven Cooreman |
0:a0faa86660d4 | 33 | #include "LS013B7DH03.h" |
Steven Cooreman |
0:a0faa86660d4 | 34 | #include "SPI.h" |
Steven Cooreman |
0:a0faa86660d4 | 35 | |
Steven Cooreman |
0:a0faa86660d4 | 36 | /* LS013B7DH03 SPI commands */ |
Steven Cooreman |
0:a0faa86660d4 | 37 | #define LS013B7DH03_CMD_UPDATE (0x01) |
Steven Cooreman |
0:a0faa86660d4 | 38 | #define LS013B7DH03_CMD_ALL_CLEAR (0x04) |
Steven Cooreman |
0:a0faa86660d4 | 39 | |
Steven Cooreman |
0:a0faa86660d4 | 40 | /* Macro to switch endianness on char value */ |
Steven Cooreman |
0:a0faa86660d4 | 41 | #define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7)) |
Steven Cooreman |
0:a0faa86660d4 | 42 | |
Steven Cooreman |
0:a0faa86660d4 | 43 | namespace silabs { |
Steven Cooreman |
0:a0faa86660d4 | 44 | |
Steven Cooreman |
0:a0faa86660d4 | 45 | LS013B7DH03::LS013B7DH03(mbed::SPI * spi, DigitalOut * CS, DigitalOut * ExtCom, const char *name) : BufferedDisplay(name) { |
Steven Cooreman |
0:a0faa86660d4 | 46 | //Save pointer to ChipSelect pin |
Steven Cooreman |
0:a0faa86660d4 | 47 | _CS = CS; |
Steven Cooreman |
0:a0faa86660d4 | 48 | _CS->write(0); |
Steven Cooreman |
0:a0faa86660d4 | 49 | |
Steven Cooreman |
0:a0faa86660d4 | 50 | //Save pointer to ExtCom pin |
Steven Cooreman |
0:a0faa86660d4 | 51 | _EXTCOM = ExtCom; |
Steven Cooreman |
0:a0faa86660d4 | 52 | _EXTCOM->write(0); |
Steven Cooreman |
0:a0faa86660d4 | 53 | |
Steven Cooreman |
0:a0faa86660d4 | 54 | //Save pointer to spi peripheral |
Steven Cooreman |
0:a0faa86660d4 | 55 | _spi = spi; |
Steven Cooreman |
2:2f10f00fe56c | 56 | _internalEventCallback.attach(this, &LS013B7DH03::_cbHandler); |
Steven Cooreman |
0:a0faa86660d4 | 57 | |
Steven Cooreman |
0:a0faa86660d4 | 58 | //Initialize |
Steven Cooreman |
0:a0faa86660d4 | 59 | _spi->set_dma_usage((DMAUsage)DMA_USAGE_NEVER); |
Steven Cooreman |
0:a0faa86660d4 | 60 | _refreshCount = 0; |
Steven Cooreman |
0:a0faa86660d4 | 61 | _lcdPolarity = 0; |
Steven Cooreman |
0:a0faa86660d4 | 62 | _state = IDLE; |
Steven Cooreman |
0:a0faa86660d4 | 63 | _completionCallbackPtr = NULL; |
Steven Cooreman |
0:a0faa86660d4 | 64 | _rowCount = 0; |
Steven Cooreman |
0:a0faa86660d4 | 65 | |
Steven Cooreman |
0:a0faa86660d4 | 66 | //Start toggling the EXTCOM pin |
Steven Cooreman |
2:2f10f00fe56c | 67 | //_displayToggler.attach(this, &LS013B7DH03::toggle, 0.008f); |
Steven Cooreman |
0:a0faa86660d4 | 68 | } |
Steven Cooreman |
0:a0faa86660d4 | 69 | |
Steven Cooreman |
0:a0faa86660d4 | 70 | /** |
Steven Cooreman |
0:a0faa86660d4 | 71 | * Call this function at 55 ~ 65 Hz to keep the display up-to-date. |
Steven Cooreman |
0:a0faa86660d4 | 72 | */ |
Steven Cooreman |
0:a0faa86660d4 | 73 | void LS013B7DH03::toggle() { |
Steven Cooreman |
0:a0faa86660d4 | 74 | _EXTCOM->write(!_EXTCOM->read()); |
Steven Cooreman |
0:a0faa86660d4 | 75 | _refreshCount++; |
Steven Cooreman |
0:a0faa86660d4 | 76 | } |
Steven Cooreman |
0:a0faa86660d4 | 77 | |
Steven Cooreman |
0:a0faa86660d4 | 78 | /** |
Steven Cooreman |
0:a0faa86660d4 | 79 | * Function to get internal refresh counter |
Steven Cooreman |
0:a0faa86660d4 | 80 | */ |
Steven Cooreman |
0:a0faa86660d4 | 81 | uint32_t LS013B7DH03::getRefreshTicks() { |
Steven Cooreman |
0:a0faa86660d4 | 82 | return _refreshCount; |
Steven Cooreman |
0:a0faa86660d4 | 83 | } |
Steven Cooreman |
0:a0faa86660d4 | 84 | |
Steven Cooreman |
0:a0faa86660d4 | 85 | /** |
Steven Cooreman |
0:a0faa86660d4 | 86 | * Call this function to push all changes to the display |
Steven Cooreman |
0:a0faa86660d4 | 87 | */ |
Steven Cooreman |
0:a0faa86660d4 | 88 | int LS013B7DH03::update( cbptr_t callback ) { |
Steven Cooreman |
0:a0faa86660d4 | 89 | uint32_t rowCount = 0; |
Steven Cooreman |
0:a0faa86660d4 | 90 | bool update = false; |
Steven Cooreman |
0:a0faa86660d4 | 91 | |
Steven Cooreman |
0:a0faa86660d4 | 92 | // Check if something actually changed in the pixelbuffer |
Steven Cooreman |
0:a0faa86660d4 | 93 | for(rowCount = 0; rowCount < DISPLAY_HEIGHT/DISPLAY_BUFFER_TYPE_SIZE; rowCount++) { |
Steven Cooreman |
0:a0faa86660d4 | 94 | if(_dirtyRows[rowCount] != 0) update = true; |
Steven Cooreman |
0:a0faa86660d4 | 95 | } |
Steven Cooreman |
0:a0faa86660d4 | 96 | |
Steven Cooreman |
0:a0faa86660d4 | 97 | if(update == false) return LS013B7DH03_NO_ACTION; |
Steven Cooreman |
0:a0faa86660d4 | 98 | |
Steven Cooreman |
0:a0faa86660d4 | 99 | // Watch out to not mess up a transfer |
Steven Cooreman |
0:a0faa86660d4 | 100 | if(_state != IDLE) return LS013B7DH03_ERROR_BUSY; |
Steven Cooreman |
0:a0faa86660d4 | 101 | |
Steven Cooreman |
0:a0faa86660d4 | 102 | _completionCallbackPtr = callback; |
Steven Cooreman |
0:a0faa86660d4 | 103 | |
Steven Cooreman |
0:a0faa86660d4 | 104 | // Take control |
Steven Cooreman |
0:a0faa86660d4 | 105 | _state = WAIT_WRITE; |
Steven Cooreman |
0:a0faa86660d4 | 106 | _rowCount = 0; |
Steven Cooreman |
0:a0faa86660d4 | 107 | |
Steven Cooreman |
0:a0faa86660d4 | 108 | //Initialize the command vector |
Steven Cooreman |
0:a0faa86660d4 | 109 | _cmd[0] = (uint8_t)SWAP8(LS013B7DH03_CMD_UPDATE); |
Steven Cooreman |
0:a0faa86660d4 | 110 | _cmd[1] = SWAP8(1); |
Steven Cooreman |
0:a0faa86660d4 | 111 | |
Steven Cooreman |
0:a0faa86660d4 | 112 | // Activate LCD |
Steven Cooreman |
0:a0faa86660d4 | 113 | _CS->write(1); |
Steven Cooreman |
0:a0faa86660d4 | 114 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f); |
Steven Cooreman |
0:a0faa86660d4 | 115 | |
Steven Cooreman |
0:a0faa86660d4 | 116 | return LS013B7DH03_OK; |
Steven Cooreman |
0:a0faa86660d4 | 117 | } |
Steven Cooreman |
0:a0faa86660d4 | 118 | |
Steven Cooreman |
0:a0faa86660d4 | 119 | /** |
Steven Cooreman |
0:a0faa86660d4 | 120 | * Function to test display buffer |
Steven Cooreman |
0:a0faa86660d4 | 121 | */ |
Steven Cooreman |
0:a0faa86660d4 | 122 | int LS013B7DH03::showDemo() { |
Steven Cooreman |
0:a0faa86660d4 | 123 | for(uint32_t i = 0; i < DISPLAY_BUFFER_ELEMENTS; i+=2) { |
Steven Cooreman |
0:a0faa86660d4 | 124 | _pixelBuffer[i] = 0x00FFF000; |
Steven Cooreman |
0:a0faa86660d4 | 125 | } |
Steven Cooreman |
0:a0faa86660d4 | 126 | memset((void*)_dirtyRows, 0xFF, sizeof(_dirtyRows)); |
Steven Cooreman |
0:a0faa86660d4 | 127 | |
Steven Cooreman |
0:a0faa86660d4 | 128 | return LS013B7DH03_OK; |
Steven Cooreman |
0:a0faa86660d4 | 129 | } |
Steven Cooreman |
0:a0faa86660d4 | 130 | |
Steven Cooreman |
0:a0faa86660d4 | 131 | /** |
Steven Cooreman |
0:a0faa86660d4 | 132 | * Call this function to immediately clear the display |
Steven Cooreman |
0:a0faa86660d4 | 133 | */ |
Steven Cooreman |
0:a0faa86660d4 | 134 | int LS013B7DH03::clearImmediate( cbptr_t callback ) { |
Steven Cooreman |
0:a0faa86660d4 | 135 | // Watch out to not mess up a transfer |
Steven Cooreman |
0:a0faa86660d4 | 136 | if(_state != IDLE) return LS013B7DH03_ERROR_BUSY; |
Steven Cooreman |
0:a0faa86660d4 | 137 | |
Steven Cooreman |
0:a0faa86660d4 | 138 | _state = WAIT_CLEAR; |
Steven Cooreman |
0:a0faa86660d4 | 139 | _completionCallbackPtr = callback; |
Steven Cooreman |
0:a0faa86660d4 | 140 | |
Steven Cooreman |
0:a0faa86660d4 | 141 | // Clear out the pixel buffer |
Steven Cooreman |
0:a0faa86660d4 | 142 | memset((void*)_pixelBuffer, White, sizeof(_pixelBuffer)); |
Steven Cooreman |
0:a0faa86660d4 | 143 | memset((void*)_dirtyRows, 0, sizeof(_dirtyRows)); |
Steven Cooreman |
0:a0faa86660d4 | 144 | |
Steven Cooreman |
0:a0faa86660d4 | 145 | _cmd[0] = (uint8_t)(SWAP8(LS013B7DH03_CMD_ALL_CLEAR | _lcdPolarity)); |
Steven Cooreman |
0:a0faa86660d4 | 146 | _cmd[1] = 0; |
Steven Cooreman |
0:a0faa86660d4 | 147 | |
Steven Cooreman |
0:a0faa86660d4 | 148 | // Wait for the ChipSelect line |
Steven Cooreman |
0:a0faa86660d4 | 149 | _CS->write(1); |
Steven Cooreman |
0:a0faa86660d4 | 150 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f); |
Steven Cooreman |
0:a0faa86660d4 | 151 | |
Steven Cooreman |
0:a0faa86660d4 | 152 | return LS013B7DH03_OK; |
Steven Cooreman |
0:a0faa86660d4 | 153 | } |
Steven Cooreman |
0:a0faa86660d4 | 154 | |
Steven Cooreman |
0:a0faa86660d4 | 155 | void LS013B7DH03::_cbHandlerTimeout( void ) { |
Steven Cooreman |
0:a0faa86660d4 | 156 | this->_cbHandler(0); |
Steven Cooreman |
0:a0faa86660d4 | 157 | } |
Steven Cooreman |
0:a0faa86660d4 | 158 | |
Steven Cooreman |
0:a0faa86660d4 | 159 | void LS013B7DH03::_cbHandler( int event ) { |
Steven Cooreman |
0:a0faa86660d4 | 160 | if((_state == WAIT_WRITE) || (_state == WRITING)) |
Steven Cooreman |
0:a0faa86660d4 | 161 | { |
Steven Cooreman |
0:a0faa86660d4 | 162 | _state = WRITING; |
Steven Cooreman |
0:a0faa86660d4 | 163 | while(_rowCount < DISPLAY_HEIGHT) { |
Steven Cooreman |
0:a0faa86660d4 | 164 | // Determine the next line to send |
Steven Cooreman |
0:a0faa86660d4 | 165 | if((_dirtyRows[_rowCount / DISPLAY_BUFFER_TYPE_SIZE] & (1 << (_rowCount % DISPLAY_BUFFER_TYPE_SIZE))) != 0) { |
Steven Cooreman |
0:a0faa86660d4 | 166 | |
Steven Cooreman |
0:a0faa86660d4 | 167 | // Row is dirty, send an update to the display |
Steven Cooreman |
0:a0faa86660d4 | 168 | _cmd[1] = (uint8_t)SWAP8(_rowCount + 1); |
Steven Cooreman |
0:a0faa86660d4 | 169 | memcpy((void*)&(_cmd[2]), (const void*)&(_pixelBuffer[_rowCount*(DISPLAY_WIDTH/DISPLAY_BUFFER_TYPE_SIZE)]), DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE)); |
Steven Cooreman |
0:a0faa86660d4 | 170 | |
Steven Cooreman |
2:2f10f00fe56c | 171 | if(_spi->transfer((uint8_t*)_cmd, (2 + (DISPLAY_WIDTH / DISPLAY_BUFFER_TYPE_SIZE * sizeof(DISPLAY_BUFFER_TYPE))) , (uint8_t*)NULL, 0, _internalEventCallback, SPI_EVENT_COMPLETE) != 0) { |
Steven Cooreman |
0:a0faa86660d4 | 172 | // SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here. |
Steven Cooreman |
0:a0faa86660d4 | 173 | _state = DONE; |
Steven Cooreman |
0:a0faa86660d4 | 174 | |
Steven Cooreman |
0:a0faa86660d4 | 175 | // Make sure the handler is called again |
Steven Cooreman |
0:a0faa86660d4 | 176 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f); |
Steven Cooreman |
0:a0faa86660d4 | 177 | } |
Steven Cooreman |
0:a0faa86660d4 | 178 | |
Steven Cooreman |
0:a0faa86660d4 | 179 | // Transaction is in progress, so update row state |
Steven Cooreman |
0:a0faa86660d4 | 180 | _dirtyRows[_rowCount / DISPLAY_BUFFER_TYPE_SIZE] &= ~(1 << (_rowCount % DISPLAY_BUFFER_TYPE_SIZE)); |
Steven Cooreman |
0:a0faa86660d4 | 181 | _rowCount++; |
Steven Cooreman |
0:a0faa86660d4 | 182 | return; |
Steven Cooreman |
0:a0faa86660d4 | 183 | } |
Steven Cooreman |
0:a0faa86660d4 | 184 | |
Steven Cooreman |
0:a0faa86660d4 | 185 | // Row wasn't touched, so check the next row |
Steven Cooreman |
0:a0faa86660d4 | 186 | _rowCount++; |
Steven Cooreman |
0:a0faa86660d4 | 187 | } |
Steven Cooreman |
0:a0faa86660d4 | 188 | |
Steven Cooreman |
0:a0faa86660d4 | 189 | // Done sending! |
Steven Cooreman |
0:a0faa86660d4 | 190 | _cmd[1] = 0xFF; |
Steven Cooreman |
0:a0faa86660d4 | 191 | _state = TRANSFERS_DONE; |
Steven Cooreman |
2:2f10f00fe56c | 192 | if(_spi->transfer((uint8_t*)_cmd, 2, (uint8_t*)NULL, 0, _internalEventCallback, SPI_EVENT_COMPLETE) != 0) { |
Steven Cooreman |
0:a0faa86660d4 | 193 | // SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here. |
Steven Cooreman |
0:a0faa86660d4 | 194 | _state = DONE; |
Steven Cooreman |
0:a0faa86660d4 | 195 | |
Steven Cooreman |
0:a0faa86660d4 | 196 | // Make sure the handler is called again |
Steven Cooreman |
0:a0faa86660d4 | 197 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f); |
Steven Cooreman |
0:a0faa86660d4 | 198 | } |
Steven Cooreman |
0:a0faa86660d4 | 199 | return; |
Steven Cooreman |
0:a0faa86660d4 | 200 | } |
Steven Cooreman |
0:a0faa86660d4 | 201 | else if (_state == WAIT_CLEAR) |
Steven Cooreman |
0:a0faa86660d4 | 202 | { |
Steven Cooreman |
0:a0faa86660d4 | 203 | _state = TRANSFERS_DONE; |
Steven Cooreman |
2:2f10f00fe56c | 204 | if(_spi->transfer((uint8_t*)_cmd, 2, (uint8_t*)NULL, 0, _internalEventCallback, SPI_EVENT_COMPLETE) != 0) { |
Steven Cooreman |
0:a0faa86660d4 | 205 | // SPI is busy, with another transaction. This means the data to the LCD has been corrupted, so fail here. |
Steven Cooreman |
0:a0faa86660d4 | 206 | _state = DONE; |
Steven Cooreman |
0:a0faa86660d4 | 207 | |
Steven Cooreman |
0:a0faa86660d4 | 208 | // Make sure the handler is called again |
Steven Cooreman |
0:a0faa86660d4 | 209 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.1f); |
Steven Cooreman |
0:a0faa86660d4 | 210 | } |
Steven Cooreman |
0:a0faa86660d4 | 211 | return; |
Steven Cooreman |
0:a0faa86660d4 | 212 | } |
Steven Cooreman |
0:a0faa86660d4 | 213 | else if (_state == TRANSFERS_DONE) |
Steven Cooreman |
0:a0faa86660d4 | 214 | { |
Steven Cooreman |
0:a0faa86660d4 | 215 | _state = DONE; |
Steven Cooreman |
0:a0faa86660d4 | 216 | _csTimeout.attach(this, &LS013B7DH03::_cbHandlerTimeout, 0.01f); |
Steven Cooreman |
0:a0faa86660d4 | 217 | return; |
Steven Cooreman |
0:a0faa86660d4 | 218 | } |
Steven Cooreman |
0:a0faa86660d4 | 219 | else if (_state == DONE) |
Steven Cooreman |
0:a0faa86660d4 | 220 | { |
Steven Cooreman |
0:a0faa86660d4 | 221 | _CS->write(0); |
Steven Cooreman |
0:a0faa86660d4 | 222 | _state = IDLE; |
Steven Cooreman |
0:a0faa86660d4 | 223 | if(_completionCallbackPtr != 0) _completionCallbackPtr(); |
Steven Cooreman |
0:a0faa86660d4 | 224 | return; |
Steven Cooreman |
0:a0faa86660d4 | 225 | } |
Steven Cooreman |
0:a0faa86660d4 | 226 | } |
Steven Cooreman |
0:a0faa86660d4 | 227 | |
Steven Cooreman |
0:a0faa86660d4 | 228 | } // namespace silabs |