]> git.sur5r.net Git - freertos/blob - Demo/MSP430X_MSP430F5438_IAR/MSP-EXP430F5438_HAL/hal_lcd.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / MSP430X_MSP430F5438_IAR / MSP-EXP430F5438_HAL / hal_lcd.c
1 /**\r
2  * @file  hal_lcd.c\r
3  *\r
4  * Copyright 2010 Texas Instruments, Inc.\r
5 ***************************************************************************/\r
6 \r
7 #include "msp430.h"\r
8 #include "hal_MSP-EXP430F5438.h"\r
9 #include "hal_lcd_fonts.h"\r
10 \r
11 unsigned char LcdInitMacro[]={\r
12             0x74,0x00,0x00,0x76,0x00,0x01,  // R00 start oscillation\r
13             0x74,0x00,0x01,0x76,0x00,0x0D,  // R01 driver output control\r
14             0x74,0x00,0x02,0x76,0x00,0x4C,  // R02 LCD - driving waveform control\r
15             0x74,0x00,0x03,0x76,0x12,0x14,  // R03 Power control\r
16             0x74,0x00,0x04,0x76,0x04,0x66,  // R04 Contrast control\r
17             0x74,0x00,0x05,0x76,0x00,0x10,  // R05 Entry mode\r
18             0x74,0x00,0x06,0x76,0x00,0x00,  // R06 RAM data write mask\r
19             0x74,0x00,0x07,0x76,0x00,0x15,  // R07 Display control\r
20             0x74,0x00,0x08,0x76,0x00,0x03,  // R08 Cursor Control\r
21             0x74,0x00,0x09,0x76,0x00,0x00,  // R09 RAM data write mask\r
22             0x74,0x00,0x0A,0x76,0x00,0x15,  // R0A\r
23             0x74,0x00,0x0B,0x76,0x00,0x03,  // R0B Horizontal Cursor Position\r
24             0x74,0x00,0x0C,0x76,0x00,0x03,  // R0C Vertical Cursor Position\r
25             0x74,0x00,0x0D,0x76,0x00,0x00,  // R0D\r
26             0x74,0x00,0x0E,0x76,0x00,0x15,  // R0E\r
27             0x74,0x00,0x0F,0x76,0x00,0x03,  // R0F\r
28             0x74,0x00,0x10,0x76,0x00,0x15,  // R0E\r
29             0x74,0x00,0x11,0x76,0x00,0x03,  // R0F\r
30 };\r
31 \r
32 unsigned char Read_Block_Address_Macro[]= {0x74,0x00,0x12,0x77,0x00,0x00};\r
33 unsigned char Draw_Block_Value_Macro[]={0x74,0x00,0x12,0x76,0xFF,0xFF};\r
34 unsigned char Draw_Block_Address_Macro[]={0x74,0x00,0x11,0x76,0x00,0x00};\r
35 \r
36 unsigned int  LcdAddress = 0, LcdTableAddress = 0;\r
37 unsigned char contrast   = 0x66;\r
38 unsigned char backlight  = 8;\r
39 int LCD_MEM[110*17];            //This array stores a copy of all data on the LCD\r
40                                                         //screen. If memory is an issue though, this array\r
41                                                         //can be eliminated and the halLcdReadBlock()\r
42                                                         //command can be used instead whenever you are\r
43                                                         //manipulating the currently displayed data.\r
44 \r
45 /**********************************************************************//**\r
46  * @brief  Sends 3+3 bytes of data to the LCD using the format specified\r
47  *         by the LCD Guide.\r
48  *\r
49  * @param  Data[] Data array for transmission\r
50  *\r
51  * @return none\r
52  *************************************************************************/\r
53 void halLcdSendCommand(unsigned char Data[])\r
54 {\r
55   unsigned char i;\r
56 \r
57   LCD_CS_RST_OUT &= ~LCD_CS_PIN;            //CS = 0 --> Start Transfer\r
58   for ( i = 0; i < 6; i++ )\r
59   {\r
60     while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
61     UCB2TXBUF = Data[i];                    // Load data\r
62 \r
63     if (i == 2)                             //Pull CS up after 3 bytes\r
64     {\r
65       while (UCB2STAT & UCBUSY);        \r
66       LCD_CS_RST_OUT |= LCD_CS_PIN;         //CS = 1 --> Stop Transfer\r
67       LCD_CS_RST_OUT &= ~LCD_CS_PIN;        //CS = 0 --> Start Transfer \r
68     }\r
69   }\r
70   while (UCB2STAT & UCBUSY);            \r
71   LCD_CS_RST_OUT |= LCD_CS_PIN;             //CS = 1 --> Stop Transfer\r
72 }\r
73 \r
74 /**********************************************************************//**\r
75  * @brief  Initializes the USCI module, LCD device for communication.\r
76  *\r
77  * - Sets up the SPI2C Communication Module\r
78  * - Performs Hitachi LCD Initialization Procedure\r
79  *\r
80  * @param  none\r
81  *\r
82  * @return none\r
83  *************************************************************************/\r
84 void halLcdInit(void)\r
85 {\r
86   volatile unsigned int i=0;\r
87 \r
88   LCD_CS_RST_OUT |= LCD_CS_PIN | LCD_RESET_PIN ;\r
89   LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN ;\r
90 \r
91   LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN;\r
92 \r
93   LCD_CS_RST_OUT &= ~LCD_RESET_PIN;         // Reset LCD\r
94   __delay_cycles(0x47FF);                   //Reset Pulse\r
95   LCD_CS_RST_OUT |= LCD_RESET_PIN;\r
96 \r
97   // UCLK,MOSI setup, SOMI cleared\r
98   LCD_SPI_SEL |= LCD_MOSI_PIN + LCD_CLK_PIN;\r
99   LCD_SPI_SEL &= ~LCD_MISO_PIN;\r
100   LCD_SPI_DIR &= ~(LCD_MISO_PIN + LCD_MOSI_PIN);            // Pin direction controlled by module,\r
101                                                             // Set both pins to input as default\r
102 \r
103   // Initialize the USCI_B2 module for SPI operation\r
104   UCB2CTL1 = UCSWRST;                       // Hold USCI in SW reset mode while configuring it\r
105   UCB2CTL0 = UCMST+UCSYNC+UCCKPL+UCMSB;     // 3-pin, 8-bit SPI master\r
106   UCB2CTL1 |= UCSSEL_2;                     // SMCLK\r
107   UCB2BR0 = 4;                              // Note: Do not exceed D/S spec for UCLK!\r
108   UCB2BR1 = 0;\r
109   UCB2CTL1 &= ~UCSWRST;                     // Release USCI state machine\r
110   UCB2IFG &= ~UCRXIFG;\r
111 \r
112   // Wake-up the LCD as per datasheet specifications\r
113   halLcdActive();\r
114 \r
115   // LCD Initialization Routine Using Predefined Macros\r
116   halLcdSendCommand(&LcdInitMacro[ 1 * 6 ]);\r
117   halLcdSendCommand(&LcdInitMacro[ 2 * 6 ]);\r
118   halLcdSendCommand(&LcdInitMacro[ 4 * 6 ]);\r
119   halLcdSendCommand(&LcdInitMacro[ 5 * 6 ]);\r
120   halLcdSendCommand(&LcdInitMacro[ 6 * 6 ]);\r
121   halLcdSendCommand(&LcdInitMacro[ 7 * 6 ]);\r
122 \r
123 }\r
124 \r
125 /**********************************************************************//**\r
126  * @brief  Shuts down the LCD display and hdisables the USCI communication.\r
127  *\r
128  * @param  none\r
129  *\r
130  * @return none\r
131  *************************************************************************/\r
132 void halLcdShutDown(void)\r
133 {\r
134   halLcdStandby();\r
135 \r
136   LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN ;\r
137   LCD_CS_RST_OUT &= ~(LCD_CS_PIN | LCD_RESET_PIN );\r
138   LCD_CS_RST_OUT &= ~LCD_RESET_PIN;\r
139 \r
140   LCD_SPI_SEL &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN);\r
141   LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN;\r
142   LCD_CS_RST_OUT &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN);\r
143 \r
144   UCB2CTL0 = UCSWRST;\r
145 }\r
146 \r
147 /**********************************************************************//**\r
148  * @brief  Initializes the LCD backlight PWM signal.\r
149  *\r
150  * @param  none\r
151  *\r
152  * @return none\r
153  *\r
154  *************************************************************************/\r
155 void halLcdBackLightInit(void)\r
156 {\r
157   LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN;\r
158   LCD_BACKLT_OUT |= LCD_BACKLIGHT_PIN;\r
159   LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN;\r
160 \r
161   TA0CCTL3 = OUTMOD_7;\r
162   TA0CCR3 = TA0CCR0 >> 1 ;\r
163   backlight = 8;\r
164 \r
165   TA0CCR0 = 400;\r
166   TA0CTL = TASSEL_2+MC_1;\r
167 }\r
168 \r
169 /**********************************************************************//**\r
170  * @brief  Get function for the backlight PWM's duty cycle.\r
171  *\r
172  * @param  none\r
173  *\r
174  * @return backlight One of the the 17 possible settings - valued 0 to 16.\r
175  *\r
176  *************************************************************************/\r
177 unsigned int halLcdGetBackLight(void)\r
178 {\r
179   return backlight;\r
180 }\r
181 \r
182 /**********************************************************************//**\r
183  * @brief  Set function for the backlight PWM's duty cycle\r
184  *\r
185  * @param  BackLightLevel The target backlight duty cycle - valued 0 to 16.\r
186  *\r
187  * @return none\r
188  *************************************************************************/\r
189 void halLcdSetBackLight(unsigned char BackLightLevel)\r
190 {\r
191   unsigned int dutyCycle = 0, i, dummy;\r
192 \r
193   if (BackLightLevel > 0)\r
194   {\r
195     TA0CCTL3 = OUTMOD_7;\r
196     dummy = (TA0CCR0 >> 4);\r
197 \r
198     for (i = 0; i < BackLightLevel; i++)\r
199       dutyCycle += dummy;\r
200 \r
201     TA0CCR3 = dutyCycle;\r
202 \r
203     // If the backlight was previously turned off, turn it on.\r
204     if (!backlight)\r
205       TA0CTL |= MC0;\r
206   }\r
207   else\r
208   {     \r
209     TA0CCTL3 = 0;\r
210     TA0CTL &= ~MC0;\r
211   }\r
212   backlight = BackLightLevel;\r
213 }\r
214 \r
215 /**********************************************************************//**\r
216  * @brief  Turns off the backlight.\r
217  *\r
218  * Clears the respective GPIO and timer settings.\r
219  *\r
220  * @param  none\r
221  *\r
222  * @return none\r
223  *************************************************************************/\r
224 void halLcdShutDownBackLight(void)\r
225 {\r
226   LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN;\r
227   LCD_BACKLT_OUT &= ~(LCD_BACKLIGHT_PIN);\r
228   LCD_BACKLT_SEL &= ~LCD_BACKLIGHT_PIN;\r
229 \r
230   TA0CCTL3 = 0;\r
231   TA0CTL = 0;\r
232 \r
233   backlight = 0;\r
234 }\r
235 \r
236 /**********************************************************************//**\r
237  * @brief  Set function for the contrast level of the LCD.\r
238  *\r
239  * @param  ContrastLevel The target contrast level\r
240  *\r
241  * @return none\r
242  *************************************************************************/\r
243 void halLcdSetContrast(unsigned char ContrastLevel)\r
244 {\r
245   if (ContrastLevel > 127) ContrastLevel = 127;\r
246   if (ContrastLevel < 70) ContrastLevel = 70;\r
247   LcdInitMacro[ 0x04 * 6 + 5 ] = ContrastLevel;\r
248   halLcdSendCommand(&LcdInitMacro[ 0x04 * 6 ]);\r
249 }\r
250 \r
251 /**********************************************************************//**\r
252  * @brief  Get function for the contrast level of the LCD.\r
253  *\r
254  * @param  none\r
255  *\r
256  * @return ContrastLevel The LCD constrast level\r
257  *************************************************************************/\r
258 unsigned char halLcdGetContrast(void)\r
259 {\r
260   return LcdInitMacro[ 0x04 * 6 + 5 ] ;\r
261 }\r
262 \r
263 /**********************************************************************//**\r
264  * @brief  Turns the LCD cursor on at the current text position.\r
265  *\r
266  * @param  none\r
267  *\r
268  * @return none\r
269  *************************************************************************/\r
270 void halLcdCursor(void)\r
271 {\r
272   LcdInitMacro[  8 * 6 + 5 ] ^= BIT2;\r
273   halLcdSendCommand(&LcdInitMacro[ 8 * 6 ]);\r
274 \r
275   LcdInitMacro[ 0x0B * 6 + 5 ] = ((LcdAddress & 0x1F) << 3) ;\r
276   LcdInitMacro[ 0x0B * 6 + 4 ] = ( (LcdAddress & 0x1F) << 3 ) + 3;\r
277   LcdInitMacro[ 0x0C * 6 + 5 ] = (LcdAddress >> 5);\r
278   LcdInitMacro[ 0x0C * 6 + 4 ] = (LcdAddress >> 5) + 7;\r
279   halLcdSendCommand(&LcdInitMacro[ 0x0B * 6 ]);\r
280   halLcdSendCommand(&LcdInitMacro[ 0x0C * 6 ]);\r
281 \r
282   halLcdSetAddress(LcdAddress);\r
283 }\r
284 \r
285 /**********************************************************************//**\r
286  * @brief  Turns off the LCD cursor.\r
287  *\r
288  * @param  none\r
289  *\r
290  * @return none\r
291  *************************************************************************/\r
292 void halLcdCursorOff(void)\r
293 {\r
294   LcdInitMacro[  8 * 6 + 5 ] &= ~BIT2;\r
295   halLcdSendCommand(&LcdInitMacro[ 8 * 6 ]);\r
296 }\r
297 \r
298 /**********************************************************************//**\r
299  * @brief  Inverts the grayscale values of the LCD display (Black <> white).\r
300  *\r
301  * @param  none\r
302  *\r
303  * @return none\r
304  *************************************************************************/\r
305 void halLcdReverse(void)\r
306 {\r
307   LcdInitMacro[  7 * 6 + 5 ] ^= BIT1;\r
308   halLcdSendCommand(&LcdInitMacro[ 7 * 6 ]);\r
309 }\r
310 \r
311 /**********************************************************************//**\r
312  * @brief  Sets the LCD in standby mode to reduce power consumption.\r
313  *\r
314  * @param  none\r
315  *\r
316  * @return none\r
317  *************************************************************************/\r
318 void halLcdStandby(void)\r
319 {\r
320   LcdInitMacro[ 3 * 6 + 5 ] &= (~BIT3) & (~BIT2);\r
321   LcdInitMacro[ 3 * 6 + 5 ] |= BIT0;\r
322   halLcdSendCommand(&LcdInitMacro[ 3 * 6 ]);\r
323 }\r
324 \r
325 /**********************************************************************//**\r
326  * @brief  Puts the LCD into active mode.\r
327  *\r
328  * @param  none\r
329  *\r
330  * @return none\r
331  *************************************************************************/\r
332 void halLcdActive(void)\r
333 {\r
334   halLcdSendCommand(LcdInitMacro);                  // R00 start oscillation\r
335 \r
336   // Wait a minimum of 25ms after issuing "start oscillation"\r
337   // command (to accomodate for MCLK up to 25MHz)\r
338   __delay_cycles(250000);\r
339 \r
340   LcdInitMacro[ 3 * 6 + 5 ] |= BIT3;\r
341   LcdInitMacro[ 3 * 6 + 5 ] &= ~BIT0;\r
342   halLcdSendCommand(&LcdInitMacro[ 3 * 6 ]);        // R03 Power control\r
343 }\r
344 \r
345 /**********************************************************************//**\r
346  * @brief  Sets the pointer location in the LCD.\r
347  *\r
348  * - LcdAddress      = Address                                          \r
349  * - LcdTableAddress = Correct Address Row + Column\r
350  *                   = (Address / 0x20)* 17 + Column\r
351  *\r
352  * @param  Address The target pointer location in the LCD.\r
353  *\r
354  * @return none\r
355  *************************************************************************/\r
356 void halLcdSetAddress(int Address)\r
357 {\r
358   int temp;\r
359 \r
360   Draw_Block_Address_Macro[4] = Address >> 8;\r
361   Draw_Block_Address_Macro[5] = Address & 0xFF;\r
362   halLcdSendCommand(Draw_Block_Address_Macro);\r
363   LcdAddress = Address;\r
364   temp = Address >> 5;                      // Divided by 0x20\r
365   temp = temp + (temp << 4);\r
366   //Multiplied by (1+16) and added by the offset\r
367   LcdTableAddress = temp + (Address & 0x1F);\r
368 }\r
369 \r
370 /**********************************************************************//**\r
371  * @brief  Draws a block at the specified LCD address.\r
372  *\r
373  * A block is the smallest addressable memory on the LCD and is\r
374  * equivalent to 8 pixels, each of which is represented by 2 bits\r
375  * that represent a grayscale value between 00b and 11b.\r
376  *\r
377  * @param  Address The address at which to draw the block.\r
378  *\r
379  * @param  Value   The value of the block\r
380  *\r
381  * @return none\r
382  *************************************************************************/\r
383 void halLcdDrawBlock(unsigned int Address, unsigned int Value)\r
384 {\r
385   halLcdSetAddress(Address);\r
386   halLcdDrawCurrentBlock(Value);\r
387 }\r
388 \r
389 /**********************************************************************//**\r
390  * @brief  Writes Value to LCD CGram and MSP430 internal LCD table.\r
391  *\r
392  * Also updates the LcdAddress and LcdTableAddress to the correct values.\r
393  *\r
394  * @param  Value The value of the block to be written to the LCD.\r
395  *\r
396  * @return none\r
397  *************************************************************************/\r
398 void halLcdDrawCurrentBlock(unsigned int Value)\r
399 {\r
400   int temp;\r
401 \r
402   Draw_Block_Value_Macro[4] = Value >> 8;\r
403   Draw_Block_Value_Macro[5] = Value & 0xFF;\r
404   LCD_MEM[ LcdTableAddress ] = Value;\r
405 \r
406   halLcdSendCommand(Draw_Block_Value_Macro);\r
407 \r
408   LcdAddress++;\r
409   temp = LcdAddress >> 5;                   // Divided by 0x20\r
410   temp = temp + (temp << 4);\r
411   // Multiplied by (1+16) and added by the offset\r
412   LcdTableAddress = temp + (LcdAddress & 0x1F);\r
413 \r
414   // If LcdAddress gets off the right edge, move to next line\r
415   if ((LcdAddress & 0x1F) > 0x11)\r
416     halLcdSetAddress( (LcdAddress & 0xFFE0) + 0x20 );\r
417   if (LcdAddress == LCD_Size)\r
418     halLcdSetAddress( 0 );\r
419 }\r
420 \r
421 /**********************************************************************//**\r
422  * @brief  Returns the LCD CGRAM value at location Address.\r
423  *\r
424  * @param  Address The address of the block to be read from the LCD.\r
425  *\r
426  * @return Value   The value held at the specified address.\r
427  *************************************************************************/\r
428 int halLcdReadBlock(unsigned int Address)\r
429 {\r
430   int i = 0, Value = 0, ReadData[7];\r
431 \r
432   halLcdSetAddress( Address );\r
433   halLcdSendCommand(Read_Block_Address_Macro);\r
434 \r
435   LCD_CS_RST_OUT &= ~LCD_CS_PIN;              // start transfer CS=0\r
436   UCB2TXBUF = 0x77;                         // Transmit first character 0x77\r
437 \r
438   while (!(UCB2IFG & UCTXIFG));\r
439   while (UCB2STAT & UCBUSY);\r
440 \r
441   //Read 5 dummies values and 2 valid address data\r
442   LCD_SPI_SEL &= ~LCD_MOSI_PIN;             //Change SPI2C Dir\r
443   LCD_SPI_SEL |= LCD_MISO_PIN;\r
444 \r
445   for (i = 0; i < 7; i ++ )\r
446   {\r
447     UCB2IFG &= ~UCRXIFG;\r
448     UCB2TXBUF = 1;                          // load dummy byte 1 for clk\r
449     while (!(UCB2IFG & UCRXIFG));\r
450     ReadData[i] = UCB2RXBUF;\r
451   }\r
452   LCD_CS_RST_OUT |= LCD_CS_PIN;              // Stop Transfer CS = 1\r
453 \r
454   LCD_SPI_SEL |= LCD_MOSI_PIN;               //Change SPI2C Dir\r
455   LCD_SPI_SEL &= ~LCD_MISO_PIN;\r
456   LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN;\r
457   LCD_CS_RST_DIR &= ~LCD_MISO_PIN;\r
458 \r
459   Value = (ReadData[5] << 8) + ReadData[6];\r
460   return Value;\r
461 }\r
462 \r
463 /**********************************************************************//**\r
464  * @brief  Draw a Pixel of grayscale at coordinate (x,y) to LCD\r
465  *\r
466  * @param  x         x-coordinate for grayscale value\r
467  *\r
468  * @param  y         y-coordinate for grayscale value\r
469  *\r
470  * @param  GrayScale The intended grayscale value of the pixel - one of\r
471  *                   four possible settings.\r
472  *\r
473  * @return none\r
474  *************************************************************************/\r
475 void halLcdPixel( int x, int y, unsigned char GrayScale)\r
476 {\r
477   int  Address, Value;\r
478   unsigned char offset;\r
479 \r
480   //Each line increments by 0x20\r
481   if ( (x>=0 ) && (x<LCD_COL) && (y>=0) && (y<LCD_ROW))\r
482   {\r
483     Address = (y << 5) + (x >> 3) ;         //Narrow down to 8 possible pixels\r
484 \r
485     Value = LCD_MEM[(y << 4)+ y + (x>>3)];  //y * 17 --> row. x>>3 --> column\r
486 \r
487     offset = (x & 0x07) << 1;      //3 LSBs = pos. within the 8 columns\r
488     Value &= ~  (3 << offset);     //clear out the corresponding bits\r
489     Value |= GrayScale << offset;  //set pixel to GrayScale level\r
490 \r
491     halLcdDrawBlock( Address, Value );\r
492   }\r
493 }\r
494 \r
495 /**********************************************************************//**\r
496  * @brief  Clears entire LCD CGRAM as well as LCD_MEM.\r
497  *\r
498  * @param  none\r
499  *\r
500  * @return none\r
501  *************************************************************************/\r
502 void halLcdClearScreen(void)\r
503 {\r
504   int i, j, k, Current_Location = 0;\r
505   halLcdSetAddress(0);\r
506 \r
507   for (i=0; i < 110; i++)\r
508   {\r
509     //prepare to send image\r
510     LCD_CS_RST_OUT &= ~LCD_CS_PIN;            //CS = 0 --> Start Transfer\r
511     for ( k = 0; k < 3; k++ )\r
512     {\r
513       while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
514       UCB2TXBUF = Draw_Block_Value_Macro[k];     // Load data\r
515     }\r
516     while (UCB2STAT & UCBUSY);          \r
517     LCD_CS_RST_OUT |= LCD_CS_PIN;         //CS = 1 --> Stop Transfer\r
518     LCD_CS_RST_OUT &= ~LCD_CS_PIN;        //CS = 0 --> Start Transfer   \r
519     while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
520     UCB2TXBUF = Draw_Block_Value_Macro[3];     // Load data\r
521 \r
522     //send blank line\r
523     for (j=0; j < 17; j++)\r
524     {\r
525           LCD_MEM[ LcdTableAddress++ ] = 0x00;\r
526       while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
527       UCB2TXBUF = 0x00;                   // Load data\r
528       while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
529       UCB2TXBUF = 0x00;                   // Load data\r
530     }\r
531     //Clear the partially visible block at the edge of the screen\r
532     while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
533       UCB2TXBUF = 0x00;                   // Load data\r
534     while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
535       UCB2TXBUF = 0x00;                   // Load data\r
536     while (UCB2STAT & UCBUSY);          \r
537     LCD_CS_RST_OUT |= LCD_CS_PIN;             //CS = 1 --> Stop Transfer\r
538 \r
539     Current_Location += 0x20;\r
540     halLcdSetAddress(Current_Location );\r
541   }\r
542 \r
543   halLcdSetAddress(0);\r
544 }\r
545 \r
546 /**********************************************************************//**\r
547  * @brief  Loads an image of size = rows * columns, starting at the\r
548  *         coordinate (x,y).\r
549  *\r
550  * @param  Image[] The image to be loaded\r
551  *\r
552  * @param  Rows    The number of rows in the image. Size = Rows * Columns.\r
553  *\r
554  * @param  Columns The number of columns in the image. Size = Rows * Columns.\r
555  *\r
556  * @param  x       x-coordinate of the image's starting location\r
557  *\r
558  * @param  y       y-coordinate of the image's starting location\r
559  *\r
560  * @return none\r
561  *************************************************************************/\r
562 void halLcdImage(const unsigned int Image[], int Columns, int Rows, int x, int y)\r
563 {\r
564   int i, CurrentLocation;\r
565 \r
566   CurrentLocation = (y << 5) + (x >> 3);\r
567   halLcdSetAddress(CurrentLocation);\r
568   for (i=0; i < Rows; i++)\r
569   {\r
570     halLcdDrawCurrentLine(Image, Columns);\r
571     Image += Columns;\r
572     CurrentLocation += 0x20;\r
573     halLcdSetAddress(CurrentLocation);\r
574   }\r
575 }\r
576 \r
577 /**********************************************************************//**\r
578  * @brief  Writes Value to LCD CGram and MSP430 internal LCD table.\r
579  *\r
580  * Also updates the LcdAddress and LcdTableAddress to the correct values.\r
581  *\r
582  * @param  *value Pointer to the line to be written to the LCD.\r
583  *\r
584  * @return none\r
585  *************************************************************************/\r
586 void halLcdDrawCurrentLine(const unsigned int *value, int Columns)\r
587 {\r
588   unsigned char i;\r
589 \r
590   //prepare to send image\r
591   LCD_CS_RST_OUT &= ~LCD_CS_PIN;            //CS = 0 --> Start Transfer\r
592   for ( i = 0; i < 3; i++ )\r
593   {\r
594       while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
595       UCB2TXBUF = Draw_Block_Value_Macro[i];     // Load data\r
596   }\r
597   while (UCB2STAT & UCBUSY);            \r
598   LCD_CS_RST_OUT |= LCD_CS_PIN;         //CS = 1 --> Stop Transfer\r
599   LCD_CS_RST_OUT &= ~LCD_CS_PIN;        //CS = 0 --> Start Transfer     \r
600   while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
601   UCB2TXBUF = Draw_Block_Value_Macro[3];     // Load data\r
602 \r
603   //send the image\r
604   for ( i = 0; i < Columns; i++ )\r
605   {     \r
606     // Make sure we are not writing outside LCD_MEM[]\r
607     if (LcdTableAddress >= sizeof(LCD_MEM)) {\r
608         break;\r
609     }\r
610         LCD_MEM[ LcdTableAddress++ ] = *value;\r
611         while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
612     UCB2TXBUF = (*value) >> 8;                   // Load data\r
613     while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
614     UCB2TXBUF = (*value++) & 0xFF;                   // Load data\r
615   }\r
616 \r
617   while (UCB2STAT & UCBUSY);            \r
618   LCD_CS_RST_OUT |= LCD_CS_PIN;             //CS = 1 --> Stop Transfer\r
619 }\r
620 \r
621 /**********************************************************************//**\r
622  * @brief  Clears an image of size rows x columns starting at (x, y).\r
623  *\r
624  * @param  Columns The size, in columns, of the image to be cleared.\r
625  *\r
626  * @param  Rows    The size, in rows, of the image to be cleared.\r
627  *\r
628  * @param  x       x-coordinate of the image to be cleared\r
629  *\r
630  * @param  y       y-coordinate of the image to be cleared\r
631  *\r
632  * @return none\r
633  *************************************************************************/\r
634 void halLcdClearImage(int Columns, int Rows, int x, int y)\r
635 {\r
636   int i,j,k, Current_Location;\r
637   Current_Location = (y << 5) + (x >> 3);\r
638   halLcdSetAddress( Current_Location );\r
639 \r
640   for (i=0; i < Rows; i++)\r
641   {\r
642     //prepare to send image\r
643     LCD_CS_RST_OUT &= ~LCD_CS_PIN;            //CS = 0 --> Start Transfer\r
644     for ( k = 0; k < 3; k++ )\r
645     {\r
646       while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
647       UCB2TXBUF = Draw_Block_Value_Macro[k];     // Load data\r
648     }\r
649     while (UCB2STAT & UCBUSY);          \r
650     LCD_CS_RST_OUT |= LCD_CS_PIN;         //CS = 1 --> Stop Transfer\r
651     LCD_CS_RST_OUT &= ~LCD_CS_PIN;        //CS = 0 --> Start Transfer   \r
652     while (!(UCB2IFG & UCTXIFG));           // Wait for TXIFG\r
653     UCB2TXBUF = Draw_Block_Value_Macro[3];     // Load data\r
654 \r
655     //send blank line\r
656     for (j=0; j < Columns; j++)\r
657     {\r
658           LCD_MEM[ LcdTableAddress++ ] = 0x00;\r
659       while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
660       UCB2TXBUF = 0x00;                   // Load data\r
661       while (!(UCB2IFG & UCTXIFG));       // Wait for TXIFG\r
662       UCB2TXBUF = 0x00;                   // Load data\r
663     }\r
664     while (UCB2STAT & UCBUSY);          \r
665     LCD_CS_RST_OUT |= LCD_CS_PIN;             //CS = 1 --> Stop Transfer\r
666 \r
667     Current_Location += 0x20;\r
668     halLcdSetAddress(Current_Location );\r
669   }\r
670 }\r
671 \r
672 /**********************************************************************//**\r
673  * @brief  Writes Value to LCD CGRAM. Pointers internal to the LCD\r
674  *         are also updated.\r
675  *\r
676  * @param  Value The value to be written to the current LCD pointer\r
677  *\r
678  * @return none\r
679  *************************************************************************/\r
680 void halLcdDrawTextBlock(unsigned int Value)\r
681 {\r
682   int temp;\r
683 \r
684   Draw_Block_Value_Macro[4] = Value >> 8;\r
685   Draw_Block_Value_Macro[5] = Value & 0xFF;\r
686   LCD_MEM[ LcdTableAddress ] = Value;\r
687 \r
688   halLcdSendCommand(Draw_Block_Value_Macro);\r
689 \r
690   LcdAddress++;\r
691   temp = LcdAddress >> 5;                   // Divided by 0x20\r
692   temp = temp + (temp << 4);\r
693   //Multiplied by (1+16) and added by the offset\r
694   LcdTableAddress = temp + (LcdAddress & 0x1F);\r
695 \r
696   // If LcdAddress gets off the right edge, move to next line\r
697   if ((LcdAddress & 0x1F) > 0x10)\r
698     halLcdSetAddress( (LcdAddress & 0xFFE0) + 0x20 );\r
699 \r
700   if (LcdAddress >= LCD_Size)\r
701     halLcdSetAddress( 0 );\r
702 }\r
703 \r
704 /**********************************************************************//**\r
705  * @brief  Displays the string to the LCD starting at current location.\r
706  *\r
707  * Writes all the data to LCD_MEM first, then updates all corresponding\r
708  * LCD CGRAM locations at once, in a continuous fashion.\r
709  *\r
710  * @param  String[]  The string to be displayed on LCD.\r
711  *\r
712  * @param  TextStyle Value that specifies whether the string is to be\r
713  *                   inverted or overwritten.\r
714  *                   - Invert    = 0x01\r
715  *                   - Overwrite = 0x04\r
716  *\r
717  * @return none\r
718  *************************************************************************/\r
719 void halLcdPrint( char String[], unsigned char TextStyle)\r
720 {\r
721   int i, j, Counter=0, BlockValue;\r
722   int Address, LCD_MEM_Add, ActualAddress;\r
723   int temp;\r
724   char LookUpChar;\r
725 \r
726   ActualAddress = LcdAddress;\r
727   Counter =  LcdAddress & 0x1F;\r
728   i=0;\r
729 \r
730   while (String[i]!=0)                      // Stop on null character\r
731   {\r
732     LookUpChar = fonts_lookup[String[i]];\r
733 \r
734     for (j=0;j < FONT_HEIGHT ;j++)\r
735     {\r
736       Address = ActualAddress + j*0x20;\r
737       temp = Address >> 5;\r
738       temp += (temp <<4);\r
739 \r
740       LCD_MEM_Add = temp + (Address & 0x1F);\r
741 \r
742       BlockValue = LCD_MEM[ LCD_MEM_Add ];\r
743 \r
744       if(TextStyle & GRAYSCALE_TEXT)\r
745       {\r
746         if (TextStyle & INVERT_TEXT)\r
747           if (TextStyle & OVERWRITE_TEXT)\r
748             BlockValue = 0xAAAA - GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
749           else\r
750             BlockValue |= 0xAAAA - GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
751         else\r
752           if (TextStyle & OVERWRITE_TEXT)\r
753             BlockValue = GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
754           else\r
755             BlockValue |= GrayScale_fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
756       }\r
757       else\r
758       {\r
759         if (TextStyle & INVERT_TEXT)\r
760           if (TextStyle & OVERWRITE_TEXT)\r
761             BlockValue = 0xFFFF - fonts[LookUpChar*13+j];\r
762           else\r
763             BlockValue |= 0xFFFF - fonts[LookUpChar*13+j];\r
764 \r
765         else\r
766           if (TextStyle & OVERWRITE_TEXT)\r
767             BlockValue = fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
768           else\r
769             BlockValue |= fonts[LookUpChar*(FONT_HEIGHT+1) +j];\r
770       }\r
771       halLcdDrawBlock( Address, BlockValue);\r
772     }\r
773 \r
774     Counter++;\r
775     if (Counter == 17)\r
776     {\r
777       Counter = 0;\r
778       ActualAddress += 0x20*FONT_HEIGHT  - 16;\r
779       if (ActualAddress > LCD_Last_Pixel-0x20*FONT_HEIGHT )\r
780         ActualAddress = 0;\r
781     }\r
782     else\r
783       ActualAddress++;\r
784     i++;\r
785   }\r
786   halLcdSetAddress(ActualAddress);\r
787 \r
788 }\r
789 \r
790 /**********************************************************************//**\r
791  * @brief  Displays the string to the LCD starting at (x,y) location.\r
792  *\r
793  * Writes all the data to LCD_MEM first, then updates all corresponding\r
794  * LCD CGRAM locations at once, in a continuous fashion.\r
795  *\r
796  * @param  String[]  String to be displayed on LCD\r
797  *\r
798  * @param  x         x-coordinate of the write location on the LCD\r
799  *\r
800  * @param  y         y-coordinate of the write location on the LCD\r
801  *\r
802  * @param  TextStyle Value that specifies whether the string is to be\r
803  *                   inverted or overwritten.\r
804  *                   - Invert    = 0x01\r
805  *                   - Overwrite = 0x04\r
806  *************************************************************************/\r
807 void halLcdPrintXY( char String[], int x, int y, unsigned char TextStyle)\r
808 {\r
809   //Each line increments by 0x20\r
810   halLcdSetAddress( (y << 5) + (x >> 3)) ;  //Narrow down to 8 possible pixels\r
811   halLcdPrint(String,  TextStyle);\r
812 }\r
813 \r
814 /**********************************************************************//**\r
815  * @brief  Displays a string on the LCD on the specified line.\r
816  *\r
817  * @param  String[]  The string to be displayed on LCD.\r
818  *\r
819  * @param  Line      The line on the LCD on which to print the string.\r
820  *\r
821  * @param  TextStyle Value that specifies whether the string is to be\r
822  *                   inverted or overwritten.\r
823  *                   - Invert    = 0x01\r
824  *                   - Overwrite = 0x04\r
825  *\r
826  * @return none\r
827  *************************************************************************/\r
828 void halLcdPrintLine(char String[], unsigned char Line, unsigned char TextStyle)\r
829 {\r
830   int temp;\r
831   temp = Line * FONT_HEIGHT ;\r
832   halLcdSetAddress( temp << 5 ) ;           // 0x20 = 2^5\r
833   halLcdPrint(String, TextStyle);\r
834 }\r
835 \r
836 /**********************************************************************//**\r
837  * @brief  Prints a string beginning on a given line and column.\r
838  *\r
839  * @param  String[]  The string to be displayed on LCD.\r
840  *\r
841  * @param  Line      The line on which to print the string of text\r
842  *\r
843  * @param  Col       The column on which to print the string of text\r
844  *\r
845  * @param  TextStyle Value that specifies whether the string is to be\r
846  *                   inverted or overwritten.\r
847  *                   - Invert    = 0x01\r
848  *                   - Overwrite = 0x04\r
849  *\r
850  * @return none\r
851  *************************************************************************/\r
852 void halLcdPrintLineCol(char String[], unsigned char Line, unsigned char Col,\r
853                         unsigned char TextStyle)\r
854 {\r
855   int temp;\r
856 \r
857   temp = Line * FONT_HEIGHT;\r
858   temp <<= 5;\r
859   temp += Col;\r
860 \r
861   halLcdSetAddress( temp ) ;                // 0x20 = 2^5\r
862   halLcdPrint(String, TextStyle);\r
863 }\r
864 \r
865 \r
866 /**********************************************************************//**\r
867  * @brief  Draws a horizontral line from (x1,y) to (x2,y) of GrayScale level\r
868  *\r
869  * @param  x1        x-coordinate of the first point\r
870  *\r
871  * @param  x2        x-coordinate of the second point\r
872  *\r
873  * @param  y         y-coordinate of both points\r
874  *\r
875  * @param  GrayScale Grayscale level of the horizontal line\r
876  *\r
877  * @return none\r
878  *************************************************************************/\r
879 void halLcdHLine( int x1, int x2, int y, unsigned char GrayScale)\r
880 {\r
881   int x_dir, x;\r
882   if ( x1 < x2 )\r
883     x_dir = 1;\r
884   else\r
885     x_dir = -1;\r
886   x = x1;\r
887   while (x != x2)\r
888   {\r
889     halLcdPixel( x,y, GrayScale);\r
890     x += x_dir;\r
891   }\r
892 }\r
893 \r
894 /**********************************************************************//**\r
895  * @brief  Draws a vertical line from (x,y1) to (x,y2) of GrayScale level\r
896  *\r
897  * @param  x         x-coordinate of both points\r
898  *\r
899  * @param  y1        y-coordinate of the first point\r
900  *\r
901  * @param  y2        y-coordinate of the second point\r
902  *\r
903  * @param  GrayScale GrayScale level of the vertical line\r
904  *\r
905  * @return none\r
906  *************************************************************************/\r
907 void halLcdVLine( int x, int y1, int y2, unsigned char GrayScale)\r
908 {\r
909   int y_dir, y;\r
910   if ( y1 < y2 )\r
911     y_dir = 1;\r
912   else\r
913     y_dir = -1;\r
914   y = y1;\r
915   while (y != y2)\r
916   {\r
917     halLcdPixel( x,y, GrayScale);\r
918     y += y_dir;\r
919   }\r
920 }\r
921 \r
922 /**********************************************************************//**\r
923  * @brief  Draws a line from (x1,y1) to (x2,y2) of GrayScale level.\r
924  *\r
925  * Uses Bresenham's line algorithm.\r
926  *\r
927  * @param  x1         x-coordinate of the first point\r
928  *\r
929  * @param  y1         y-coordinate of the first point\r
930  *\r
931  * @param  x2         x-coordinate of the second point\r
932  *\r
933  * @param  y2         y-coordinate of the second point\r
934  *\r
935  * @param  GrayScale  Grayscale level of the line\r
936  *\r
937  * @return none\r
938  *************************************************************************/\r
939 void halLcdLine( int x1, int y1, int x2, int y2, unsigned char GrayScale)\r
940 {\r
941   int x, y, deltay, deltax, d;\r
942   int x_dir, y_dir;\r
943 \r
944   if ( x1 == x2 )\r
945     halLcdVLine( x1, y1, y2, GrayScale );\r
946   else\r
947   {\r
948     if ( y1 == y2 )\r
949       halLcdHLine( x1, x2, y1, GrayScale );\r
950     else                                    // a diagonal line\r
951     {\r
952       if (x1 > x2)\r
953         x_dir = -1;\r
954       else x_dir = 1;\r
955       if (y1 > y2)\r
956         y_dir = -1;\r
957       else y_dir = 1;\r
958 \r
959       x = x1;\r
960       y = y1;\r
961       deltay = ABS(y2 - y1);\r
962       deltax = ABS(x2 - x1);\r
963 \r
964       if (deltax >= deltay)\r
965       {\r
966         d = (deltay << 1) - deltax;\r
967         while (x != x2)\r
968         {\r
969           halLcdPixel(x, y,  GrayScale);\r
970           if ( d < 0 )\r
971             d += (deltay << 1);\r
972           else\r
973           {\r
974             d += ((deltay - deltax) << 1);\r
975             y += y_dir;\r
976           }\r
977           x += x_dir;\r
978         }\r
979       }\r
980       else\r
981       {\r
982         d = (deltax << 1) - deltay;\r
983         while (y != y2)\r
984         {\r
985           halLcdPixel(x, y, GrayScale);\r
986           if ( d < 0 )\r
987             d += (deltax << 1);\r
988           else\r
989           {\r
990             d += ((deltax - deltay) << 1);\r
991             x += x_dir;\r
992           }\r
993           y += y_dir;\r
994         }\r
995       }\r
996     }\r
997   }\r
998 }\r
999 \r
1000 \r
1001 /**********************************************************************//**\r
1002  * @brief  Draw a circle of Radius with center at (x,y) of GrayScale level.\r
1003  *\r
1004  * Uses Bresenham's circle algorithm\r
1005  *\r
1006  * @param  x         x-coordinate of the circle's center point\r
1007  *\r
1008  * @param  y         y-coordinate of the circle's center point\r
1009  *\r
1010  * @param  Radius    Radius of the circle\r
1011  *\r
1012  * @param  GrayScale Grayscale level of the circle\r
1013  *************************************************************************/\r
1014 void halLcdCircle(int x, int y, int Radius, int GrayScale)\r
1015 {\r
1016   int xx, yy, ddF_x, ddF_y, f;\r
1017 \r
1018   ddF_x = 0;\r
1019   ddF_y = -(2 * Radius);\r
1020   f = 1 - Radius;\r
1021 \r
1022   xx = 0;\r
1023   yy = Radius;\r
1024   halLcdPixel(x + xx, y + yy, GrayScale);\r
1025   halLcdPixel(x + xx, y - yy, GrayScale);\r
1026   halLcdPixel(x - xx, y + yy, GrayScale);\r
1027   halLcdPixel(x - xx, y - yy, GrayScale);\r
1028   halLcdPixel(x + yy, y + xx, GrayScale);\r
1029   halLcdPixel(x + yy, y - xx, GrayScale);\r
1030   halLcdPixel(x - yy, y + xx, GrayScale);\r
1031   halLcdPixel(x - yy, y - xx, GrayScale);\r
1032   while (xx < yy)\r
1033   {\r
1034     if (f >= 0)\r
1035     {\r
1036       yy--;\r
1037       ddF_y += 2;\r
1038       f += ddF_y;\r
1039     }\r
1040     xx++;\r
1041     ddF_x += 2;\r
1042     f += ddF_x + 1;\r
1043     halLcdPixel(x + xx, y + yy, GrayScale);\r
1044     halLcdPixel(x + xx, y - yy, GrayScale);\r
1045     halLcdPixel(x - xx, y + yy, GrayScale);\r
1046     halLcdPixel(x - xx, y - yy, GrayScale);\r
1047     halLcdPixel(x + yy, y + xx, GrayScale);\r
1048     halLcdPixel(x + yy, y - xx, GrayScale);\r
1049     halLcdPixel(x - yy, y + xx, GrayScale);\r
1050     halLcdPixel(x - yy, y - xx, GrayScale);\r
1051   }\r
1052 }\r
1053 \r
1054 /**********************************************************************//**\r
1055  * @brief  Scrolls a single row of pixels one column to the left.\r
1056  *\r
1057  * The column that is scrolled out of the left side of the LCD will be\r
1058  * displayed the right side of the LCD.\r
1059  *\r
1060  * @param  y    The row of pixels to scroll. y = 0 is at the top-left\r
1061  *              corner of the LCD.\r
1062  *\r
1063  * @return none\r
1064  *************************************************************************/\r
1065 void halLcdScrollRow(int y)\r
1066 {\r
1067   int i, Address, LcdTableAddressTemp;\r
1068   unsigned int temp;\r
1069 \r
1070   Address = y << 5;\r
1071 \r
1072   halLcdSetAddress( Address );\r
1073 \r
1074   //Multiplied by (1+16) and added by the offset\r
1075   LcdTableAddressTemp = y + (y << 4);\r
1076   temp = ((LCD_MEM[LcdTableAddressTemp] & 0x0003) <<14);\r
1077 \r
1078   for (i = 0; i < 0x10; i++)\r
1079     halLcdDrawCurrentBlock( ( (LCD_MEM[LcdTableAddressTemp+i] & 0xFFFC ) >> 2 ) \\r
1080     + ((LCD_MEM[LcdTableAddressTemp+i+1] & 0x0003) << 14 ));\r
1081 \r
1082   halLcdDrawCurrentBlock( (( LCD_MEM[LcdTableAddressTemp + 0x10] & 0xFFFC ) >> 2) + temp);\r
1083 }\r
1084 \r
1085 /**********************************************************************//**\r
1086  * @brief  Scrolls multiple rows of pixels, yStart to yEnd,\r
1087  *         one column to the left.\r
1088  *\r
1089  * The column that is scrolled out of the left side of the LCD will be\r
1090  * displayed the right side of the LCD. y = 0 is at the top-left of the\r
1091  * LCD screen.\r
1092  *\r
1093  * @param  yStart The beginning row to be scrolled\r
1094  *\r
1095  * @param  yEnd   The last row to be scrolled\r
1096  *\r
1097  * @return none\r
1098  *************************************************************************/\r
1099 void halLcdHScroll(int yStart, int yEnd)\r
1100 {\r
1101   int i ;\r
1102 \r
1103   for (i = yStart; i < yEnd+1; i++)\r
1104     halLcdScrollRow(i);\r
1105 }\r
1106 \r
1107 /**********************************************************************//**\r
1108  * @brief  Scrolls a line of text one column to the left.\r
1109  *\r
1110  * @param  Line The line of text to be scrolled.\r
1111  *\r
1112  * @return none\r
1113  *************************************************************************/\r
1114 void halLcdScrollLine(int Line)\r
1115 {\r
1116   int i, Row ;\r
1117 \r
1118   Row = Line * FONT_HEIGHT;\r
1119 \r
1120   for (i = Row; i < Row + FONT_HEIGHT ; i++)\r
1121     halLcdScrollRow(i);\r
1122 }\r