1 /* Copyright (C) 2015 by Jacob Alexander
3 * This file is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This file is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this file. If not, see <http://www.gnu.org/licenses/>.
17 // ----- Includes -----
20 #include <Lib/ScanLib.h>
32 // ----- Defines -----
34 #define LCD_TOTAL_VISIBLE_PAGES 4
35 #define LCD_PAGE_LEN 128
41 // Number of entries in the SPI0 TxFIFO
42 #define SPI0_TxFIFO_CNT ( ( SPI0_SR & SPI_SR_TXCTR ) >> 12 )
46 // ----- Structs -----
48 // ----- Function Declarations -----
51 void cliFunc_lcdCmd( char* args );
52 void cliFunc_lcdInit( char* args );
53 void cliFunc_lcdTest( char* args );
57 // ----- Variables -----
60 uint8_t cliFullToggleState = 0;
62 // Normal/Reverse Toggle State
63 uint8_t cliNormalReverseToggleState = 0;
65 // Scan Module command dictionary
66 CLIDict_Entry( lcdCmd, "Send byte via SPI, second argument enables a0. Defaults to control." );
67 CLIDict_Entry( lcdInit, "Re-initialize the LCD display." );
68 CLIDict_Entry( lcdTest, "Test out the LCD display." );
70 CLIDict_Def( lcdCLIDict, "ST LCD Module Commands" ) = {
71 CLIDict_Item( lcdCmd ),
72 CLIDict_Item( lcdInit ),
73 CLIDict_Item( lcdTest ),
74 { 0, 0, 0 } // Null entry for dictionary end
79 // ----- Interrupt Functions -----
83 // ----- Functions -----
85 inline void SPI_setup()
87 // Enable SPI internal clock
88 SIM_SCGC6 |= SIM_SCGC6_SPI0;
90 // Setup MOSI (SOUT) and SCLK (SCK)
91 PORTC_PCR6 = PORT_PCR_DSE | PORT_PCR_MUX(2);
92 PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(2);
95 PORTC_PCR4 = PORT_PCR_DSE | PORT_PCR_MUX(2);
98 SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(1);
100 // DSPI Clock and Transfer Attributes
101 // Frame Size: 8 bits
103 // CLK Low by default
104 SPI0_CTAR0 = SPI_CTAR_FMSZ(7)
108 | SPI_CTAR_PBR(0) | SPI_CTAR_BR(7);
111 // Write buffer to SPI FIFO
112 void SPI_write( uint8_t *buffer, uint8_t len )
115 for ( uint8_t byte = 0; byte < len; byte++ )
117 // Wait for SPI TxFIFO to have 4 or fewer entries
118 while ( !( SPI0_SR & SPI_SR_TFFF ) )
119 delayMicroseconds(10);
121 // Write byte to TxFIFO
123 SPI0_PUSHR = ( buffer[ byte ] & 0xff ) | SPI_PUSHR_PCS(1);
125 // Indicate transfer has completed
126 while ( !( SPI0_SR & SPI_SR_TCF ) );
127 SPI0_SR |= SPI_SR_TCF;
131 // Write to a control register
132 void LCD_writeControlReg( uint8_t byte )
134 // Wait for TxFIFO to be empt
135 while ( SPI0_TxFIFO_CNT != 0 );
137 // Set A0 low to enter control register mode
138 GPIOC_PCOR |= (1<<7);
140 // Write byte to SPI FIFO
141 SPI_write( &byte, 1 );
143 // Wait for TxFIFO to be empty
144 while ( SPI0_TxFIFO_CNT != 0 );
146 // Make sure data has transferred
147 delayMicroseconds(10); // XXX Adjust if SPI speed changes
149 // Set A0 high to go back to display register mode
150 GPIOC_PSOR |= (1<<7);
153 // Write to display register
154 // Pages 0-7 normal display
155 // Page 8 icon buffer
156 void LCD_writeDisplayReg( uint8_t page, uint8_t *buffer, uint8_t len )
158 // Set the register page
159 LCD_writeControlReg( 0xB0 | ( 0x0F & page ) );
161 // Set display start line
162 LCD_writeControlReg( 0x40 );
164 // Reset Column Address
165 LCD_writeControlReg( 0x10 );
166 LCD_writeControlReg( 0x00 );
168 // Write buffer to SPI
169 SPI_write( buffer, len );
172 inline void LCD_clearPage( uint8_t page )
174 // Set the register page
175 LCD_writeControlReg( 0xB0 | ( 0x0F & page ) );
177 // Set display start line
178 LCD_writeControlReg( 0x40 );
180 // Reset Column Address
181 LCD_writeControlReg( 0x10 );
182 LCD_writeControlReg( 0x00 );
184 for ( uint8_t page_reg = 0; page_reg < LCD_PAGE_LEN; page_reg++ )
188 // Write buffer to SPI
189 SPI_write( &byte, 1 );
192 // Wait for TxFIFO to be empty
193 while ( SPI0_TxFIFO_CNT != 0 );
200 for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ )
202 LCD_clearPage( page );
205 // Reset Page, Start Line, and Column Address
207 LCD_writeControlReg( 0xB0 );
210 LCD_writeControlReg( 0x40 );
212 // Reset Column Address
213 LCD_writeControlReg( 0x10 );
214 LCD_writeControlReg( 0x00 );
218 void LCD_initialize()
220 // ADC Select (Normal)
221 LCD_writeControlReg( 0xA0 );
224 LCD_writeControlReg( 0xAE );
226 // COM Scan Output Direction
227 LCD_writeControlReg( 0xC0 );
229 // LCD Bias (1/6 bias)
230 LCD_writeControlReg( 0xA2 );
232 // Power Supply Operating Mode (Internal Only)
233 LCD_writeControlReg( 0x2F );
235 // Internal Rb/Ra Ratio
236 LCD_writeControlReg( 0x26 );
239 LCD_writeControlReg( 0xE2 );
241 // Electric volume mode set, and value
242 LCD_writeControlReg( 0x81 );
243 LCD_writeControlReg( 0x00 );
246 LCD_writeControlReg( 0xAF );
253 inline void LCD_setup()
255 // Register Scan CLI dictionary
256 CLI_registerDictionary( lcdCLIDict, lcdCLIDictName );
261 // Setup Register Control Signal (A0)
262 // Start in display register mode (1)
263 GPIOC_PDDR |= (1<<7);
264 PORTC_PCR7 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
265 GPIOC_PSOR |= (1<<7);
267 // Setup LCD Reset pin (RST)
268 // 0 - Reset, 1 - Normal Operation
269 // Start in normal mode (1)
270 GPIOC_PDDR |= (1<<8);
271 PORTC_PCR8 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
272 GPIOC_PSOR |= (1<<8);
274 // Run LCD intialization sequence
278 // TODO Expose default settings
280 GPIOC_PDDR |= (1<<1);
281 PORTC_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
282 GPIOC_PCOR |= (1<<1);
283 GPIOC_PDDR |= (1<<2);
284 PORTC_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
285 GPIOC_PCOR |= (1<<2);
286 GPIOC_PDDR |= (1<<3);
287 PORTC_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
288 GPIOC_PCOR |= (1<<3);
292 // LCD State processing loop
293 inline uint8_t LCD_scan()
295 // NOP - Screen Refresh
296 //LCD_writeControlReg( 0xE3 );
302 // ----- CLI Command Functions -----
304 void cliFunc_lcdInit( char* args )
306 print( NL ); // No \r\n by default after the command is entered
310 void cliFunc_lcdTest( char* args )
312 print( NL ); // No \r\n by default after the command is entered
316 uint8_t pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 //uint8_t pattern[] = { 0xFF, 0x00, 0x96, 0xFF, 0x00, 0xFF, 0x00 };
328 //LCD_writeDisplayReg( 0, pattern, sizeof( pattern ) );
330 for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ )
332 LCD_writeDisplayReg( page, &logo[page * LCD_PAGE_LEN], LCD_PAGE_LEN );
336 void cliFunc_lcdCmd( char* args )
340 char* arg2Ptr = args;
342 print( NL ); // No \r\n by default after the command is entered
344 curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
345 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
348 if ( *arg1Ptr == '\0' )
352 uint8_t cmd = (uint8_t)numToInt( arg1Ptr );
354 curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
355 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
358 if ( *arg1Ptr == '\0' )
363 info_msg("Sending - ");
366 LCD_writeControlReg( cmd );