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