ButterflyMP3
|
00001 //***************************************************************************** 00002 // 00003 // File........: LCD_driver.c 00004 // 00005 // Author(s)...: ATMEL Norway 00006 // 00007 // Target(s)...: ATmega169 00008 // 00009 // Compiler....: AVR-GCC 3.3.1; avr-libc 1.0 00010 // 00011 // Description.: Functions used to control the AVR Butterfly LCD 00012 // 00013 // Revisions...: 1.0 00014 // 00015 // YYYYMMDD - VER. - COMMENT - SIGN. 00016 // 00017 // 20021015 - 1.0 - Written for STK502 - JLL 00018 // 20030116 - 2.0 - Code adapted to AVR Butterfly - KS 00019 // 20031009 port to avr-gcc/avr-libc - M.Thomas 00020 // 00021 //***************************************************************************** 00022 00023 00024 // Include files. 00025 #include <avr/io.h> 00026 #include <avr/pgmspace.h> 00027 #include <inttypes.h> 00028 //#include <avr/signal.h> //This header file is obsolete. Use <avr/interrupt.h>. 00029 #include <avr/interrupt.h> 00030 // mt - only for AUTO: 00031 #include "main.h" 00032 // mt - for gButtonTimeout 00033 #include "button.h" 00034 #include "LCD_driver.h" 00035 #include "avrfat16.h" 00036 00037 #define BOOL char 00038 #define FALSE 0 00039 #define TRUE (!FALSE) 00040 00041 // Variable from "button.c" to prevent button-bouncing 00042 extern unsigned char gButtonTimeout; 00043 00044 extern BOOL gAutoPressJoystick; 00045 00046 // Used to indicate when the LCD interrupt handler should update the LCD 00047 // mt jw char gLCD_Update_Required = FALSE; 00048 volatile char gLCD_Update_Required = FALSE; 00049 00050 // LCD display buffer (for double buffering). 00051 char LCD_Data[LCD_REGISTER_COUNT]; 00052 00053 // Buffer that contains the text to be displayed 00054 // Note: Bit 7 indicates that this character is flashing 00055 char gTextBuffer[TEXTBUFFER_SIZE]; 00056 00057 // Only six letters can be shown on the LCD. 00058 // With the gScroll and gScrollMode variables, 00059 // one can select which part of the buffer to show 00060 volatile signed char gScroll; 00061 volatile char gScrollMode; 00062 00064 char gLCD_Start_Scroll_Timer = 0; 00065 00066 // The gFlashTimer is used to determine the on/off 00067 // timing of flashing characters 00068 char gFlashTimer = 0; 00069 00070 // Turns on/off the colons on the LCD 00071 char gColon = 0; 00072 00073 // switch to filename rather than standard buffer 00074 char gShowFilename; 00075 00076 // Look-up table used when converting ASCII to 00077 // LCD display data (segment control) 00078 // mt __flash unsigned int LCD_character_table[] = 00079 unsigned int LCD_character_table[] PROGMEM = 00080 { 00081 0x0A51, // '*' Degree sign 00082 0x2A80, // '+' 00083 0x4000, // ',' (Not defined) 00084 0x0A00, // '-' 00085 0x8000, // '.' 00086 0x4008, // '/' (Not defined) 00087 0x5559, // '0' 00088 0x0118, // '1' 00089 0x1e11, // '2 00090 0x1b11, // '3 00091 0x0b50, // '4 00092 0x1b41, // '5 00093 0x1f41, // '6 00094 0x0111, // '7 00095 0x1f51, // '8 00096 0x1b51, // '9' 00097 0x1f00, // ':' (Not defined) 00098 0x0000, // ';' (Not defined) 00099 0x0000, // '<' (Not defined) 00100 0x0000, // '=' (Not defined) 00101 0x0000, // '>' (Not defined) 00102 0x0000, // '?' (Not defined) 00103 0x0000, // '@' (Not defined) 00104 0x0f51, // 'A' (+ 'a') 00105 0x3991, // 'B' (+ 'b') 00106 0x1441, // 'C' (+ 'c') 00107 0x3191, // 'D' (+ 'd') 00108 0x1e41, // 'E' (+ 'e') 00109 0x0e41, // 'F' (+ 'f') 00110 0x1d41, // 'G' (+ 'g') 00111 0x0f50, // 'H' (+ 'h') 00112 0x2080, // 'I' (+ 'i') 00113 0x1510, // 'J' (+ 'j') 00114 0x8648, // 'K' (+ 'k') 00115 0x1440, // 'L' (+ 'l') 00116 0x0578, // 'M' (+ 'm') 00117 0x8570, // 'N' (+ 'n') 00118 0x1551, // 'O' (+ 'o') 00119 0x0e51, // 'P' (+ 'p') 00120 0x9551, // 'Q' (+ 'q') 00121 0x8e51, // 'R' (+ 'r') 00122 0x9021, // 'S' (+ 's') 00123 0x2081, // 'T' (+ 't') 00124 0x1550, // 'U' (+ 'u') 00125 0x4448, // 'V' (+ 'v') 00126 0xc550, // 'W' (+ 'w') 00127 0xc028, // 'X' (+ 'x') 00128 0x2028, // 'Y' (+ 'y') 00129 0x5009, // 'Z' (+ 'z') 00130 0x0000, // '[' (Not defined) 00131 0x8020, // '\' (Not defined) 00132 0x0000, // ']' (Not defined) 00133 0x0000, // '^' (Not defined) 00134 0x1000 // '_' 00135 }; 00136 00137 00138 /***************************************************************************** 00139 * 00140 * Function name : LCD_Init 00141 * 00142 * Returns : None 00143 * 00144 * Parameters : None 00145 * 00146 * Purpose : Initialize LCD_displayData buffer. 00147 * Set up the LCD (timing, contrast, etc.) 00148 * 00149 *****************************************************************************/ 00150 void LCD_Init (void) 00151 { 00152 LCD_AllSegments(FALSE); // Clear segment buffer. 00153 00154 LCD_CONTRAST_LEVEL(LCD_INITIAL_CONTRAST); //Set the LCD contrast level 00155 00156 // Select asynchronous clock source, enable all COM pins and enable all 00157 // segment pins. 00158 LCDCRB = (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0); 00159 00160 // Set LCD prescaler to give a framerate of 32,0 Hz 00161 LCDFRR = (0<<LCDPS0) | (7<<LCDCD0); 00162 00163 LCDCRA = (1<<LCDEN) | (1<<LCDAB); // Enable LCD and set low power waveform 00164 00165 //Enable LCD start of frame interrupt 00166 LCDCRA |= (1<<LCDIE); 00167 00168 gLCD_Update_Required = FALSE; 00169 00170 //updated 2006-10-10, setting LCD drive time to 1150us in FW rev 07, 00171 //instead of previous 300us in FW rev 06. Due to some variations on the LCD 00172 //glass provided to the AVR Butterfly production. 00173 LCDCCR |= (1<<LCDDC2) | (1<<LCDDC1) | (1<<LCDDC0); 00174 } 00175 00176 00177 /***************************************************************************** 00178 * 00179 * Function name : LCD_WriteDigit(char c, char digit) 00180 * 00181 * Returns : None 00182 * 00183 * Parameters : Inputs 00184 * c: The symbol to be displayed in a LCD digit 00185 * digit: In which digit (0-5) the symbol should be displayed 00186 * Note: Digit 0 is the first used digit on the LCD, 00187 * i.e LCD digit 2 00188 * 00189 * Purpose : Stores LCD control data in the LCD_displayData buffer. 00190 * (The LCD_displayData is latched in the LCD_SOF interrupt.) 00191 * 00192 *****************************************************************************/ 00193 void LCD_WriteDigit(char c, char digit) 00194 { 00195 00196 unsigned int seg = 0x0000; // Holds the segment pattern 00197 char mask, nibble; 00198 char *ptr; 00199 char i; 00200 00201 00202 if (digit > 5) // Skip if digit is illegal 00203 return; 00204 00205 //Lookup character table for segmet data 00206 if ((c >= '*') && (c <= 'z')) 00207 { 00208 // c is a letter 00209 if (c >= 'a') // Convert to upper case 00210 c &= ~0x20; // if necessarry 00211 00212 c -= '*'; 00213 00214 //mt seg = LCD_character_table[c]; 00215 seg = (unsigned int) pgm_read_word(&LCD_character_table[(uint8_t)c]); 00216 } 00217 00218 // Adjust mask according to LCD segment mapping 00219 if (digit & 0x01) 00220 mask = 0x0F; // Digit 1, 3, 5 00221 else 00222 mask = 0xF0; // Digit 0, 2, 4 00223 00224 ptr = LCD_Data + (digit >> 1); // digit = {0,0,1,1,2,2} 00225 00226 for (i = 0; i < 4; i++) 00227 { 00228 nibble = seg & 0x000F; 00229 seg >>= 4; 00230 if (digit & 0x01) 00231 nibble <<= 4; 00232 *ptr = (*ptr & mask) | nibble; 00233 ptr += 5; 00234 } 00235 } 00236 00237 00238 00239 /***************************************************************************** 00240 * 00241 * Function name : LCD_AllSegments(unsigned char input) 00242 * 00243 * Returns : None 00244 * 00245 * Parameters : show - [TRUE;FALSE] 00246 * 00247 * Purpose : shows or hide all all LCD segments on the LCD 00248 * 00249 *****************************************************************************/ 00250 void LCD_AllSegments(char show) 00251 { 00252 unsigned char i; 00253 00254 if (show) 00255 show = 0xFF; 00256 00257 // Set/clear all bits in all LCD registers 00258 for (i=0; i < LCD_REGISTER_COUNT; i++) 00259 *(LCD_Data + i) = show; 00260 } 00261 00262 00263 /***************************************************************************** 00264 * 00265 * LCD Interrupt Routine 00266 * 00267 * Returns : None 00268 * 00269 * Parameters : None 00270 * 00271 * Purpose: Latch the LCD_displayData and Set LCD_status.updateComplete 00272 * 00273 *****************************************************************************/ 00274 00275 SIGNAL(SIG_LCD) 00276 { 00277 static char LCD_timer = LCD_TIMER_SEED; 00278 char c; 00279 char c_flash; 00280 char flash; 00281 00282 char EOL; 00283 unsigned char i; 00284 00285 // static char timeout_count; 00286 // static char auto_joystick_count; 00287 00288 c_flash=0; // mt 00289 // NAL- theese sections have been removed as they are now implemented in button.c 00290 // 00291 /**************** Button timeout for the button.c, START ****************/ 00292 /* if(!gButtonTimeout) 00293 { 00294 timeout_count++; 00295 00296 if(timeout_count > 3) 00297 { 00298 gButtonTimeout = TRUE; 00299 timeout_count = 0; 00300 } 00301 } 00302 */ 00303 /**************** Button timeout for the button.c, END ******************/ 00304 00305 /**************** Auto press joystick for the main.c, START *************/ 00306 /* 00307 if(gAutoPressJoystick == AUTO) 00308 { 00309 auto_joystick_count++; 00310 00311 if(auto_joystick_count > 16) 00312 { 00313 gAutoPressJoystick = TRUE; 00314 auto_joystick_count = 15; 00315 } 00316 } 00317 else 00318 auto_joystick_count = 0; 00319 */ 00320 00321 /**************** Auto press joystick for the main.c, END ***************/ 00322 00323 LCD_timer--; // Decreased every LCD frame 00324 00325 if (gScrollMode) 00326 { 00327 // If we are in scroll mode, and the timer has expired, 00328 // we will update the LCD 00329 if (LCD_timer == 0) 00330 { 00331 if (gLCD_Start_Scroll_Timer == 0) 00332 { 00333 gLCD_Update_Required = TRUE; 00334 } 00335 else 00336 gLCD_Start_Scroll_Timer--; 00337 } 00338 } 00339 else 00340 { // if not scrolling, 00341 // disble LCD start of frame interrupt 00342 // cbi(LCDCRA, LCDIE); //DEBUG 00343 gScroll = 0; 00344 } 00345 00346 00347 EOL = FALSE; 00348 if (gLCD_Update_Required == TRUE) 00349 { 00350 // Duty cycle of flashing characters 00351 if (gFlashTimer < (LCD_FLASH_SEED >> 1)) 00352 flash = 0; 00353 else 00354 flash = 1; 00355 00356 // Repeat for the six LCD characters 00357 for (i = 0; i < 6; i++) 00358 { 00359 if ((gScroll+i) >= 0 && (!EOL)) 00360 { 00361 // We have some visible characters 00362 if (gShowFilename){ 00363 c = FAT16_longfilename[i + gScroll]; 00364 }else{ 00365 c = gTextBuffer[i + gScroll]; 00366 } 00367 c_flash = c & 0x80 ? 1 : 0; 00368 c = c & 0x7F; 00369 00370 if (c == '\0') 00371 EOL = i+1; // End of character data 00372 } 00373 else 00374 c = ' '; 00375 00376 // Check if this character is flashing 00377 00378 if (c_flash && flash) 00379 LCD_WriteDigit(' ', i); 00380 else 00381 LCD_WriteDigit(c, i); 00382 } 00383 00384 // Copy the segment buffer to the real segments 00385 for (i = 0; i < LCD_REGISTER_COUNT; i++) 00386 *(pLCDREG + i) = *(LCD_Data+i); 00387 00388 // Handle colon 00389 if (gColon) 00390 *(pLCDREG + 8) = 0x01; 00391 else 00392 *(pLCDREG + 8) = 0x00; 00393 00394 // If the text scrolled off the display, 00395 // we have to start over again. 00396 if (EOL == 1) 00397 gScroll = -6; 00398 else 00399 gScroll++; 00400 00401 // No need to update anymore 00402 gLCD_Update_Required = FALSE; 00403 } 00404 00405 00406 // LCD_timer is used when scrolling text 00407 if (LCD_timer == 0) 00408 { 00409 /* if ((gScroll <= 0) || EOL) 00410 LCD_timer = LCD_TIMER_SEED/2; 00411 else*/ 00412 LCD_timer = LCD_TIMER_SEED; 00413 } 00414 00415 // gFlashTimer is used when flashing characters 00416 if (gFlashTimer == LCD_FLASH_SEED) 00417 gFlashTimer= 0; 00418 else 00419 gFlashTimer++; 00420 00421 }