baa673cbbcb5be3f6b4c39b60746d0a4b97ce547
[matches/honours.git] / LCD_Driver.c
1 //*****************************************************************************\r
2 //\r
3 //  File........: LCD_driver.c\r
4 //\r
5 //  Author(s)...: ATMEL Norway\r
6 //\r
7 //  Target(s)...: ATmega169\r
8 //\r
9 //  Compiler....: AVR-GCC 4.1.1; avr-libc 1.4.5\r
10 //\r
11 //  Description.: Functions used to control the AVR Butterfly LCD\r
12 //\r
13 //  Revisions...: 1.0\r
14 //\r
15 //  YYYYMMDD - VER. - COMMENT                                       - SIGN.\r
16 //\r
17 //  20021015 - 1.0  - Written for STK502                            - JLL\r
18 //  20030116 - 2.0  - Code adapted to AVR Butterfly                 - KS\r
19 //  20031009          port to avr-gcc/avr-libc                      - M.Thomas\r
20 //  20070122          "updated 2006-10-10" included (from REV07)    - from Atmel\r
21 //  20070129          SIGNAL->ISR, gLCD_Start_Scroll_Timer volatile - mt\r
22 //\r
23 //*****************************************************************************\r
24 \r
25 \r
26 // Include files.\r
27 #include <avr/io.h>\r
28 #include <avr/pgmspace.h>\r
29 #include <avr/interrupt.h>\r
30 #include <stdint.h>\r
31 // mt - only for AUTO:\r
32 #include "main.h"\r
33 // mt - for gButtonTimeout\r
34 \r
35 #include "LCD_Driver.h"\r
36 \r
37 #ifndef BOOL\r
38 #define BOOL    char\r
39 #define FALSE   0\r
40 #define TRUE    (!FALSE)\r
41 #endif\r
42 \r
43 \r
44 // Used to indicate when the LCD interrupt handler should update the LCD\r
45 // mt jw char gLCD_Update_Required = FALSE;\r
46 volatile char gLCD_Update_Required = FALSE;\r
47 \r
48 // LCD display buffer (for double buffering).\r
49 volatile char LCD_Data[LCD_REGISTER_COUNT];\r
50 \r
51 // Buffer that contains the text to be displayed\r
52 // Note: Bit 7 indicates that this character is flashing\r
53 volatile char gTextBuffer[TEXTBUFFER_SIZE];\r
54 \r
55 // Only six letters can be shown on the LCD.\r
56 // With the gScroll and gScrollMode variables,\r
57 // one can select which part of the buffer to show\r
58 volatile signed char gScroll;\r
59 volatile char gScrollMode;\r
60 \r
61 ////Start-up delay before scrolling a string over the LCD\r
62 volatile char gLCD_Start_Scroll_Timer = 0;\r
63 \r
64 // The gFlashTimer is used to determine the on/off\r
65 // timing of flashing characters\r
66 volatile char gFlashTimer = 0;\r
67 \r
68 // Turns on/off the colons on the LCD\r
69 char gColon = 0;\r
70 \r
71 \r
72 // Look-up table used when converting ASCII to\r
73 // LCD display data (segment control)\r
74 // mt __flash unsigned int LCD_character_table[] =\r
75 unsigned int LCD_character_table[] PROGMEM =\r
76 {\r
77     0x0A51,     // '*' (?)\r
78     0x2A80,     // '+'\r
79     0x0000,     // ',' (Not defined)\r
80     0x0A00,     // '-'\r
81     0xFF00,     // '.' Fullstop\r
82     0x0000,     // '/' (Not defined)\r
83     0x5559,     // '0'\r
84     0x0118,     // '1'\r
85     0x1e11,     // '2\r
86     0x1b11,     // '3\r
87     0x0b50,     // '4\r
88     0x1b41,     // '5\r
89     0x1f41,     // '6\r
90     0x0111,     // '7\r
91     0x1f51,     // '8\r
92     0x1b51,     // '9'\r
93     0x0000,     // ':' (Not defined)\r
94     0x0000,     // ';' (Not defined)\r
95     0x0000,     // '<' (Not defined)\r
96     0x0000,     // '=' (Not defined)\r
97     0x0000,     // '>' (Not defined)\r
98     0x0000,     // '?' (Not defined)\r
99     0x0000,     // '@' (Not defined)\r
100     0x0f51,     // 'A' (+ 'a')\r
101     0x3991,     // 'B' (+ 'b')\r
102     0x1441,     // 'C' (+ 'c')\r
103     0x3191,     // 'D' (+ 'd')\r
104     0x1e41,     // 'E' (+ 'e')\r
105     0x0e41,     // 'F' (+ 'f')\r
106     0x1d41,     // 'G' (+ 'g')\r
107     0x0f50,     // 'H' (+ 'h')\r
108     0x2080,     // 'I' (+ 'i')\r
109     0x1510,     // 'J' (+ 'j')\r
110     0x8648,     // 'K' (+ 'k')\r
111     0x1440,     // 'L' (+ 'l')\r
112     0x0578,     // 'M' (+ 'm')\r
113     0x8570,     // 'N' (+ 'n')\r
114     0x1551,     // 'O' (+ 'o')\r
115     0x0e51,     // 'P' (+ 'p')\r
116     0x9551,     // 'Q' (+ 'q')\r
117     0x8e51,     // 'R' (+ 'r')\r
118     0x9021,     // 'S' (+ 's')\r
119     0x2081,     // 'T' (+ 't')\r
120     0x1550,     // 'U' (+ 'u')\r
121     0x4448,     // 'V' (+ 'v')\r
122     0xc550,     // 'W' (+ 'w')\r
123     0xc028,     // 'X' (+ 'x')\r
124     0x2028,     // 'Y' (+ 'y')\r
125     0x5009,     // 'Z' (+ 'z')\r
126     0x0000,     // '[' (Not defined)\r
127     0x0000,     // '\' (Not defined)\r
128     0x0000,     // ']' (Not defined)\r
129     0x0000,     // '^' (Not defined)\r
130     0x0000      // '_'\r
131 };\r
132 \r
133 \r
134 /*****************************************************************************\r
135 *\r
136 *   Function name : LCD_Init\r
137 *\r
138 *   Returns :       None\r
139 *\r
140 *   Parameters :    None\r
141 *\r
142 *   Purpose :       Initialize LCD_displayData buffer.\r
143 *                   Set up the LCD (timing, contrast, etc.)\r
144 *\r
145 *****************************************************************************/\r
146 void LCD_Init(void)\r
147 {\r
148     LCD_AllSegments(FALSE);                     // Clear segment buffer.\r
149 \r
150     LCD_CONTRAST_LEVEL(LCD_INITIAL_CONTRAST);    //Set the LCD contrast level\r
151 \r
152     // Select asynchronous clock source, enable all COM pins and enable all\r
153     // segment pins.\r
154     LCDCRB = (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0);\r
155 \r
156     // Set LCD prescaler to give a framerate of 32,0 Hz\r
157     LCDFRR = (0<<LCDPS0) | (7<<LCDCD0);    \r
158 \r
159     LCDCRA = (1<<LCDEN) | (1<<LCDAB);           // Enable LCD and set low power waveform\r
160 \r
161     //Enable LCD start of frame interrupt\r
162     LCDCRA |= (1<<LCDIE);\r
163 \r
164     //updated 2006-10-10, setting LCD drive time to 1150us in FW rev 07, \r
165     //instead of previous 300us in FW rev 06. Due to some variations on the LCD\r
166     //glass provided to the AVR Butterfly production.\r
167     LCDCCR |= (1<<LCDDC2) | (1<<LCDDC1) | (1<<LCDDC0);\r
168 \r
169     gLCD_Update_Required = FALSE;\r
170 \r
171 \r
172 }\r
173 \r
174 \r
175 /*****************************************************************************\r
176 *\r
177 *   Function name : LCD_WriteDigit(char c, char digit)\r
178 *\r
179 *   Returns :       None\r
180 *\r
181 *   Parameters :    Inputs\r
182 *                   c: The symbol to be displayed in a LCD digit\r
183 *                   digit: In which digit (0-5) the symbol should be displayed\r
184 *                   Note: Digit 0 is the first used digit on the LCD,\r
185 *                   i.e LCD digit 2\r
186 *\r
187 *   Purpose :       Stores LCD control data in the LCD_displayData buffer.\r
188 *                   (The LCD_displayData is latched in the LCD_SOF interrupt.)\r
189 *\r
190 *****************************************************************************/\r
191 void LCD_WriteDigit(char c, char digit)\r
192 {\r
193 \r
194     unsigned int seg = 0x0000;                  // Holds the segment pattern\r
195     char mask, nibble;\r
196     volatile char *ptr;\r
197     char i;\r
198 \r
199 \r
200     if (digit > 5)                              // Skip if digit is illegal\r
201         return;\r
202 \r
203     //Lookup character table for segmet data\r
204     if ((c >= '*') && (c <= 'z'))\r
205     {\r
206         // c is a letter\r
207         if (c >= 'a')                           // Convert to upper case\r
208             c &= ~0x20;                         // if necessarry\r
209 \r
210         c -= '*';\r
211 \r
212         //mt seg = LCD_character_table[c];\r
213         seg = (unsigned int) pgm_read_word(&LCD_character_table[(uint8_t)c]); \r
214     }\r
215 \r
216     // Adjust mask according to LCD segment mapping\r
217     if (digit & 0x01)\r
218         mask = 0x0F;                // Digit 1, 3, 5\r
219     else\r
220         mask = 0xF0;                // Digit 0, 2, 4\r
221 \r
222     ptr = LCD_Data + (digit >> 1);  // digit = {0,0,1,1,2,2}\r
223 \r
224     for (i = 0; i < 4; i++)\r
225     {\r
226         nibble = seg & 0x000F;\r
227         seg >>= 4;\r
228         if (digit & 0x01)\r
229             nibble <<= 4;\r
230         *ptr = (*ptr & mask) | nibble;\r
231         ptr += 5;\r
232     }\r
233 }\r
234 \r
235 \r
236 \r
237 /*****************************************************************************\r
238 *\r
239 *   Function name : LCD_AllSegments(unsigned char input)\r
240 *\r
241 *   Returns :       None\r
242 *\r
243 *   Parameters :    show -  [TRUE;FALSE]\r
244 *\r
245 *   Purpose :       shows or hide all all LCD segments on the LCD\r
246 *\r
247 *****************************************************************************/\r
248 void LCD_AllSegments(char show)\r
249 {\r
250     unsigned char i;\r
251 \r
252     if (show)\r
253         show = 0xFF;\r
254 \r
255     // Set/clear all bits in all LCD registers\r
256     for (i=0; i < LCD_REGISTER_COUNT; i++)\r
257         *(LCD_Data + i) = show;\r
258 }\r
259 \r
260 \r
261 /*****************************************************************************\r
262 *\r
263 *   LCD Interrupt Routine\r
264 *\r
265 *   Returns :       None\r
266 *\r
267 *   Parameters :    None\r
268 *\r
269 *   Purpose: Latch the LCD_displayData and Set LCD_status.updateComplete\r
270 *\r
271 *****************************************************************************/\r
272 \r
273 ISR(LCD_vect)\r
274 {\r
275     static char LCD_timer = LCD_TIMER_SEED;\r
276     char c;\r
277     char c_flash;\r
278     char flash;\r
279 \r
280     char EOL;\r
281     unsigned char i;\r
282 \r
283 \r
284 \r
285     c_flash=0; // mt\r
286 \r
287     LCD_timer--;                    // Decreased every LCD frame\r
288 \r
289     if (gScrollMode)\r
290     {\r
291         // If we are in scroll mode, and the timer has expired,\r
292         // we will update the LCD\r
293         if (LCD_timer == 0)\r
294         {\r
295             if (gLCD_Start_Scroll_Timer == 0)\r
296             {\r
297                 gLCD_Update_Required = TRUE;\r
298             }\r
299             else\r
300                 gLCD_Start_Scroll_Timer--;\r
301         }\r
302     }\r
303     else    \r
304     {   // if not scrolling,\r
305         // disble LCD start of frame interrupt\r
306         // cbi(LCDCRA, LCDIE);   //DEBUG\r
307         gScroll = 0;\r
308     }\r
309 \r
310 \r
311     EOL = FALSE;\r
312     if (gLCD_Update_Required == TRUE)\r
313     {\r
314         // Duty cycle of flashing characters\r
315         if (gFlashTimer < (LCD_FLASH_SEED >> 1))\r
316             flash = 0;\r
317         else\r
318             flash = 1;\r
319 \r
320         // Repeat for the six LCD characters\r
321         for (i = 0; i < 6; i++)\r
322         {\r
323             if ((gScroll+i) >= 0 && (!EOL))\r
324             {\r
325                 // We have some visible characters\r
326                 c = gTextBuffer[i + gScroll];\r
327                 c_flash = c & 0x80 ? 1 : 0;\r
328                 c = c & 0x7F;\r
329 \r
330                 if (c == '\0')\r
331                     EOL = i+1;      // End of character data\r
332             }\r
333             else\r
334                 c = ' ';\r
335 \r
336             // Check if this character is flashing\r
337 \r
338             if (c_flash && flash)\r
339                 LCD_WriteDigit(' ', i);\r
340             else\r
341                 LCD_WriteDigit(c, i);\r
342         }\r
343 \r
344         // Copy the segment buffer to the real segments\r
345         for (i = 0; i < LCD_REGISTER_COUNT; i++)\r
346             *(pLCDREG + i) = *(LCD_Data+i);\r
347 \r
348         // Handle colon\r
349         if (gColon)\r
350             *(pLCDREG + 8) = 0x01;\r
351         else\r
352             *(pLCDREG + 8) = 0x00;\r
353 \r
354         // If the text scrolled off the display,\r
355         // we have to start over again.\r
356         if (EOL == 1)\r
357             gScroll = -6;\r
358         else\r
359             gScroll++;\r
360 \r
361         // No need to update anymore\r
362         gLCD_Update_Required = FALSE;\r
363     }\r
364 \r
365 \r
366     // LCD_timer is used when scrolling text\r
367     if (LCD_timer == 0)\r
368     {\r
369 /*        if ((gScroll <= 0) || EOL)\r
370             LCD_timer = LCD_TIMER_SEED/2;\r
371         else*/\r
372             LCD_timer = LCD_TIMER_SEED;\r
373     }\r
374 \r
375     // gFlashTimer is used when flashing characters\r
376     if (gFlashTimer == LCD_FLASH_SEED)\r
377         gFlashTimer= 0;\r
378     else\r
379         gFlashTimer++;\r
380 \r
381 }\r

UCC git Repository :: git.ucc.asn.au