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>
33 // ----- Defines -----
35 #define LCD_TOTAL_VISIBLE_PAGES 4
36 #define LCD_PAGE_LEN 128
42 // Number of entries in the SPI0 TxFIFO
43 #define SPI0_TxFIFO_CNT ( ( SPI0_SR & SPI_SR_TXCTR ) >> 12 )
47 // ----- Structs -----
49 // ----- Function Declarations -----
52 void cliFunc_lcdCmd( char* args );
53 void cliFunc_lcdInit( char* args );
54 void cliFunc_lcdTest( char* args );
58 // ----- Variables -----
61 uint8_t cliFullToggleState = 0;
63 // Normal/Reverse Toggle State
64 uint8_t cliNormalReverseToggleState = 0;
66 // Scan Module command dictionary
67 CLIDict_Entry( lcdCmd, "Send byte via SPI, second argument enables a0. Defaults to control." );
68 CLIDict_Entry( lcdInit, "Re-initialize the LCD display." );
69 CLIDict_Entry( lcdTest, "Test out the LCD display." );
71 CLIDict_Def( lcdCLIDict, "ST LCD Module Commands" ) = {
72 CLIDict_Item( lcdCmd ),
73 CLIDict_Item( lcdInit ),
74 CLIDict_Item( lcdTest ),
75 { 0, 0, 0 } // Null entry for dictionary end
80 // ----- Interrupt Functions -----
84 // ----- Functions -----
86 inline void SPI_setup()
88 // Enable SPI internal clock
89 SIM_SCGC6 |= SIM_SCGC6_SPI0;
91 // Setup MOSI (SOUT) and SCLK (SCK)
92 PORTC_PCR6 = PORT_PCR_DSE | PORT_PCR_MUX(2);
93 PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(2);
96 PORTC_PCR4 = PORT_PCR_DSE | PORT_PCR_MUX(2);
99 SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(1);
101 // DSPI Clock and Transfer Attributes
102 // Frame Size: 8 bits
104 // CLK Low by default
105 SPI0_CTAR0 = SPI_CTAR_FMSZ(7)
109 | SPI_CTAR_PBR(0) | SPI_CTAR_BR(7);
112 // Write buffer to SPI FIFO
113 void SPI_write( uint8_t *buffer, uint8_t len )
116 for ( uint8_t byte = 0; byte < len; byte++ )
118 // Wait for SPI TxFIFO to have 4 or fewer entries
119 while ( !( SPI0_SR & SPI_SR_TFFF ) )
120 delayMicroseconds(10);
122 // Write byte to TxFIFO
124 SPI0_PUSHR = ( buffer[ byte ] & 0xff ) | SPI_PUSHR_PCS(1);
126 // Indicate transfer has completed
127 while ( !( SPI0_SR & SPI_SR_TCF ) );
128 SPI0_SR |= SPI_SR_TCF;
132 // Write to a control register
133 void LCD_writeControlReg( uint8_t byte )
135 // Wait for TxFIFO to be empt
136 while ( SPI0_TxFIFO_CNT != 0 );
138 // Set A0 low to enter control register mode
139 GPIOC_PCOR |= (1<<7);
141 // Write byte to SPI FIFO
142 SPI_write( &byte, 1 );
144 // Wait for TxFIFO to be empty
145 while ( SPI0_TxFIFO_CNT != 0 );
147 // Make sure data has transferred
148 delayMicroseconds(10); // XXX Adjust if SPI speed changes
150 // Set A0 high to go back to display register mode
151 GPIOC_PSOR |= (1<<7);
154 // Write to display register
155 // Pages 0-7 normal display
156 // Page 8 icon buffer
157 void LCD_writeDisplayReg( uint8_t page, uint8_t *buffer, uint8_t len )
159 // Set the register page
160 LCD_writeControlReg( 0xB0 | ( 0x0F & page ) );
162 // Set display start line
163 LCD_writeControlReg( 0x40 );
165 // Reset Column Address
166 LCD_writeControlReg( 0x10 );
167 LCD_writeControlReg( 0x00 );
169 // Write buffer to SPI
170 SPI_write( buffer, len );
173 inline void LCD_clearPage( uint8_t page )
175 // Set the register page
176 LCD_writeControlReg( 0xB0 | ( 0x0F & page ) );
178 // Set display start line
179 LCD_writeControlReg( 0x40 );
181 // Reset Column Address
182 LCD_writeControlReg( 0x10 );
183 LCD_writeControlReg( 0x00 );
185 for ( uint8_t page_reg = 0; page_reg < LCD_PAGE_LEN; page_reg++ )
189 // Write buffer to SPI
190 SPI_write( &byte, 1 );
193 // Wait for TxFIFO to be empty
194 while ( SPI0_TxFIFO_CNT != 0 );
201 for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ )
203 LCD_clearPage( page );
206 // Reset Page, Start Line, and Column Address
208 LCD_writeControlReg( 0xB0 );
211 LCD_writeControlReg( 0x40 );
213 // Reset Column Address
214 LCD_writeControlReg( 0x10 );
215 LCD_writeControlReg( 0x00 );
219 void LCD_initialize()
221 // ADC Select (Normal)
222 LCD_writeControlReg( 0xA0 );
225 LCD_writeControlReg( 0xAE );
227 // COM Scan Output Direction
228 LCD_writeControlReg( 0xC0 );
230 // LCD Bias (1/6 bias)
231 LCD_writeControlReg( 0xA2 );
233 // Power Supply Operating Mode (Internal Only)
234 LCD_writeControlReg( 0x2F );
236 // Internal Rb/Ra Ratio
237 LCD_writeControlReg( 0x26 );
240 LCD_writeControlReg( 0xE2 );
242 // Electric volume mode set, and value
243 LCD_writeControlReg( 0x81 );
244 LCD_writeControlReg( 0x00 );
247 LCD_writeControlReg( 0xAF );
254 inline void LCD_setup()
256 // Register Scan CLI dictionary
257 CLI_registerDictionary( lcdCLIDict, lcdCLIDictName );
262 // Setup Register Control Signal (A0)
263 // Start in display register mode (1)
264 GPIOC_PDDR |= (1<<7);
265 PORTC_PCR7 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
266 GPIOC_PSOR |= (1<<7);
268 // Setup LCD Reset pin (RST)
269 // 0 - Reset, 1 - Normal Operation
270 // Start in normal mode (1)
271 GPIOC_PDDR |= (1<<8);
272 PORTC_PCR8 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
273 GPIOC_PSOR |= (1<<8);
275 // Run LCD intialization sequence
279 // TODO Expose default settings
280 SIM_SCGC6 |= SIM_SCGC6_FTM0;
281 FTM0_CNT = 0; // Reset counter
287 // Set FTM to PWM output - Edge Aligned, Low-true pulses
288 FTM0_C0SC = 0x24; // MSnB:MSnA = 10, ELSnB:ELSnA = 01
292 // Base FTM clock selection (72 MHz system clock)
293 // Pre-scalar calculations
294 // 0 - 72 MHz - Highest power usage/best result
297 // 3 - 9 MHz - Slightly visible flicker (peripheral vision)
298 // 4 - 4 500 kHz - Visible flickering
302 // System clock, /w prescalar setting
303 FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS( STLcdBacklightPrescalar_define );
305 /* Write frequency TODO API
309 FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale);
313 FTM0_C0V = STLcdBacklightRed_define;
314 PORTC_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(4);
317 FTM0_C1V = STLcdBacklightGreen_define;
318 PORTC_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(4);
321 FTM0_C2V = STLcdBacklightBlue_define;
322 PORTC_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(4);
326 // LCD State processing loop
327 inline uint8_t LCD_scan()
329 // NOP - Screen Refresh
330 //LCD_writeControlReg( 0xE3 );
336 // ----- CLI Command Functions -----
338 void cliFunc_lcdInit( char* args )
340 print( NL ); // No \r\n by default after the command is entered
344 void cliFunc_lcdTest( char* args )
346 print( NL ); // No \r\n by default after the command is entered
350 uint8_t pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
354 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,
355 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,
356 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,
357 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,
359 //uint8_t pattern[] = { 0xFF, 0x00, 0x96, 0xFF, 0x00, 0xFF, 0x00 };
362 //LCD_writeDisplayReg( 0, pattern, sizeof( pattern ) );
364 for ( uint8_t page = 0; page < LCD_TOTAL_VISIBLE_PAGES; page++ )
366 LCD_writeDisplayReg( page, &logo[page * LCD_PAGE_LEN], LCD_PAGE_LEN );
370 void cliFunc_lcdCmd( char* args )
374 char* arg2Ptr = args;
376 print( NL ); // No \r\n by default after the command is entered
378 curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
379 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
382 if ( *arg1Ptr == '\0' )
386 uint8_t cmd = (uint8_t)numToInt( arg1Ptr );
388 curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
389 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
392 if ( *arg1Ptr == '\0' )
397 info_msg("Sending - ");
400 LCD_writeControlReg( cmd );