ButterflyMP3

LCD_driver.c

Go to the documentation of this file.
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 }
 All Files Functions Variables Typedefs Enumerations Enumerator Defines