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