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