Contiki 2.6
|
00001 /******************************************************************************* 00002 * 00003 * hal_lcd.c 00004 * 00005 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * 00014 * Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the 00017 * distribution. 00018 * 00019 * Neither the name of Texas Instruments Incorporated nor the names of 00020 * its contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00026 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00027 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00028 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00029 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00030 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00031 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ******************************************************************************/ 00036 00037 #include "contiki-conf.h" 00038 00039 #include "hal_MSP-EXP430F5438.h" 00040 #include "hal_lcd_fonts.h" 00041 00042 unsigned char LcdInitMacro[] = { 00043 0x74, 0x00, 0x00, 0x76, 0x00, 0x01, // R00 start oscillation 00044 0x74, 0x00, 0x01, 0x76, 0x00, 0x0D, // R01 driver output control 00045 0x74, 0x00, 0x02, 0x76, 0x00, 0x4C, // R02 LCD - driving waveform control 00046 0x74, 0x00, 0x03, 0x76, 0x12, 0x14, // R03 Power control 00047 0x74, 0x00, 0x04, 0x76, 0x04, 0x66, // R04 Contrast control 00048 0x74, 0x00, 0x05, 0x76, 0x00, 0x10, // R05 Entry mode 00049 0x74, 0x00, 0x06, 0x76, 0x00, 0x00, // R06 RAM data write mask 00050 0x74, 0x00, 0x07, 0x76, 0x00, 0x15, // R07 Display control 00051 0x74, 0x00, 0x08, 0x76, 0x00, 0x03, // R08 Cursor Control 00052 0x74, 0x00, 0x09, 0x76, 0x00, 0x00, // R09 RAM data write mask 00053 0x74, 0x00, 0x0A, 0x76, 0x00, 0x15, // R0A 00054 0x74, 0x00, 0x0B, 0x76, 0x00, 0x03, // R0B Horizontal Cursor Position 00055 0x74, 0x00, 0x0C, 0x76, 0x00, 0x03, // R0C Vertical Cursor Position 00056 0x74, 0x00, 0x0D, 0x76, 0x00, 0x00, // R0D 00057 0x74, 0x00, 0x0E, 0x76, 0x00, 0x15, // R0E 00058 0x74, 0x00, 0x0F, 0x76, 0x00, 0x03, // R0F 00059 0x74, 0x00, 0x10, 0x76, 0x00, 0x15, // R0E 00060 0x74, 0x00, 0x11, 0x76, 0x00, 0x03, // R0F 00061 }; 00062 00063 unsigned char Read_Block_Address_Macro[] = {0x74, 0x00, 0x12, 0x77, 0x00, 0x00}; 00064 unsigned char Draw_Block_Value_Macro[] = {0x74, 0x00, 0x12, 0x76, 0xFF, 0xFF}; 00065 unsigned char Draw_Block_Address_Macro[] = {0x74, 0x00, 0x11, 0x76, 0x00, 0x00}; 00066 00067 unsigned int LcdAddress = 0, LcdTableAddress = 0; 00068 unsigned char contrast = 0x66; 00069 unsigned char backlight = 8; 00070 int LCD_MEM[110 * 17]; //This array stores a copy of all data on the LCD 00071 //screen. If memory is an issue though, this array 00072 //can be eliminated and the halLcdReadBlock() 00073 //command can be used instead whenever you are 00074 //manipulating the currently displayed data. 00075 00076 /**********************************************************************//** 00077 * @brief Sends 3+3 bytes of data to the LCD using the format specified 00078 * by the LCD Guide. 00079 * 00080 * @param Data[] Data array for transmission 00081 * 00082 * @return none 00083 *************************************************************************/ 00084 00085 void halLcdSendCommand(unsigned char Data[]) 00086 { 00087 unsigned char i; 00088 00089 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00090 for (i = 0; i < 6; i++) 00091 { 00092 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00093 UCB2TXBUF = Data[i]; // Load data 00094 00095 if (i == 2) //Pull CS up after 3 bytes 00096 { 00097 while (UCB2STAT & UCBUSY) ; 00098 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00099 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00100 } 00101 } 00102 while (UCB2STAT & UCBUSY) ; 00103 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00104 } 00105 00106 /**********************************************************************//** 00107 * @brief Initializes the USCI module, LCD device for communication. 00108 * 00109 * - Sets up the SPI2C Communication Module 00110 * - Performs Hitachi LCD Initialization Procedure 00111 * 00112 * @param none 00113 * 00114 * @return none 00115 *************************************************************************/ 00116 00117 void halLcdInit(void) 00118 { 00119 volatile unsigned int i = 0; 00120 00121 LCD_CS_RST_OUT |= LCD_CS_PIN | LCD_RESET_PIN; 00122 LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN; 00123 00124 LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN; 00125 00126 LCD_CS_RST_OUT &= ~LCD_RESET_PIN; // Reset LCD 00127 __delay_cycles(0x47FF); //Reset Pulse 00128 LCD_CS_RST_OUT |= LCD_RESET_PIN; 00129 00130 // UCLK,MOSI setup, SOMI cleared 00131 LCD_SPI_SEL |= LCD_MOSI_PIN + LCD_CLK_PIN; 00132 LCD_SPI_SEL &= ~LCD_MISO_PIN; 00133 LCD_SPI_DIR &= ~(LCD_MISO_PIN + LCD_MOSI_PIN); // Pin direction controlled by module, 00134 // Set both pins to input as default 00135 00136 // Initialize the USCI_B2 module for SPI operation 00137 UCB2CTL1 = UCSWRST; // Hold USCI in SW reset mode while configuring 00138 // it 00139 UCB2CTL0 = UCMST + UCSYNC + UCCKPL + UCMSB; // 3-pin, 8-bit SPI master 00140 UCB2CTL1 |= UCSSEL_2; // SMCLK 00141 UCB2BR0 = 4; // Note: Do not exceed D/S spec for UCLK! 00142 UCB2BR1 = 0; 00143 UCB2CTL1 &= ~UCSWRST; // Release USCI state machine 00144 UCB2IFG &= ~UCRXIFG; 00145 00146 // Wake-up the LCD as per datasheet specifications 00147 halLcdActive(); 00148 00149 // LCD Initialization Routine Using Predefined Macros 00150 halLcdSendCommand(&LcdInitMacro[1 * 6]); 00151 halLcdSendCommand(&LcdInitMacro[2 * 6]); 00152 halLcdSendCommand(&LcdInitMacro[4 * 6]); 00153 halLcdSendCommand(&LcdInitMacro[5 * 6]); 00154 halLcdSendCommand(&LcdInitMacro[6 * 6]); 00155 halLcdSendCommand(&LcdInitMacro[7 * 6]); 00156 00157 } 00158 00159 /**********************************************************************//** 00160 * @brief Shuts down the LCD display and hdisables the USCI communication. 00161 * 00162 * @param none 00163 * 00164 * @return none 00165 *************************************************************************/ 00166 00167 void halLcdShutDown(void) 00168 { 00169 halLcdStandby(); 00170 00171 LCD_CS_RST_DIR |= LCD_CS_PIN | LCD_RESET_PIN; 00172 LCD_CS_RST_OUT &= ~(LCD_CS_PIN | LCD_RESET_PIN); 00173 LCD_CS_RST_OUT &= ~LCD_RESET_PIN; 00174 00175 LCD_SPI_SEL &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN); 00176 LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN; 00177 LCD_CS_RST_OUT &= ~(LCD_MOSI_PIN + LCD_CLK_PIN + LCD_MISO_PIN); 00178 00179 UCB2CTL0 = UCSWRST; 00180 } 00181 00182 /**********************************************************************//** 00183 * @brief Initializes the LCD backlight PWM signal. 00184 * 00185 * @param none 00186 * 00187 * @return none 00188 * 00189 *************************************************************************/ 00190 00191 void halLcdBackLightInit(void) 00192 { 00193 LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN; 00194 LCD_BACKLT_OUT |= LCD_BACKLIGHT_PIN; 00195 LCD_BACKLT_SEL |= LCD_BACKLIGHT_PIN; 00196 00197 TA0CCTL3 = OUTMOD_7; 00198 TA0CCR3 = TA0CCR0 >> 1; 00199 backlight = 8; 00200 00201 TA0CCR0 = 400; 00202 TA0CTL = TASSEL_2 + MC_1; 00203 } 00204 00205 /**********************************************************************//** 00206 * @brief Get function for the backlight PWM's duty cycle. 00207 * 00208 * @param none 00209 * 00210 * @return backlight One of the the 17 possible settings - valued 0 to 16. 00211 * 00212 *************************************************************************/ 00213 00214 unsigned int halLcdGetBackLight(void) 00215 { 00216 return backlight; 00217 } 00218 00219 /**********************************************************************//** 00220 * @brief Set function for the backlight PWM's duty cycle 00221 * 00222 * @param BackLightLevel The target backlight duty cycle - valued 0 to 16. 00223 * 00224 * @return none 00225 *************************************************************************/ 00226 00227 void halLcdSetBackLight(unsigned char BackLightLevel) 00228 { 00229 unsigned int dutyCycle = 0, i, dummy; 00230 00231 if (BackLightLevel > 0) 00232 { 00233 TA0CCTL3 = OUTMOD_7; 00234 dummy = (TA0CCR0 >> 4); 00235 00236 for (i = 0; i < BackLightLevel; i++) 00237 dutyCycle += dummy; 00238 00239 TA0CCR3 = dutyCycle; 00240 00241 // If the backlight was previously turned off, turn it on. 00242 if (!backlight) 00243 TA0CTL |= MC0; 00244 } 00245 else 00246 { 00247 TA0CCTL3 = 0; 00248 TA0CTL &= ~MC0; 00249 } 00250 backlight = BackLightLevel; 00251 } 00252 00253 /**********************************************************************//** 00254 * @brief Turns off the backlight. 00255 * 00256 * Clears the respective GPIO and timer settings. 00257 * 00258 * @param none 00259 * 00260 * @return none 00261 *************************************************************************/ 00262 00263 void halLcdShutDownBackLight(void) 00264 { 00265 LCD_BACKLT_DIR |= LCD_BACKLIGHT_PIN; 00266 LCD_BACKLT_OUT &= ~(LCD_BACKLIGHT_PIN); 00267 LCD_BACKLT_SEL &= ~LCD_BACKLIGHT_PIN; 00268 00269 TA0CCTL3 = 0; 00270 TA0CTL = 0; 00271 00272 backlight = 0; 00273 } 00274 00275 /**********************************************************************//** 00276 * @brief Set function for the contrast level of the LCD. 00277 * 00278 * @param ContrastLevel The target contrast level 00279 * 00280 * @return none 00281 *************************************************************************/ 00282 00283 void halLcdSetContrast(unsigned char ContrastLevel) 00284 { 00285 if (ContrastLevel > 127) ContrastLevel = 127; 00286 if (ContrastLevel < 70) ContrastLevel = 70; 00287 LcdInitMacro[0x04 * 6 + 5] = ContrastLevel; 00288 halLcdSendCommand(&LcdInitMacro[0x04 * 6]); 00289 } 00290 00291 /**********************************************************************//** 00292 * @brief Get function for the contrast level of the LCD. 00293 * 00294 * @param none 00295 * 00296 * @return ContrastLevel The LCD constrast level 00297 *************************************************************************/ 00298 00299 unsigned char halLcdGetContrast(void) 00300 { 00301 return LcdInitMacro[0x04 * 6 + 5]; 00302 } 00303 00304 /**********************************************************************//** 00305 * @brief Turns the LCD cursor on at the current text position. 00306 * 00307 * @param none 00308 * 00309 * @return none 00310 *************************************************************************/ 00311 00312 void halLcdCursor(void) 00313 { 00314 LcdInitMacro[8 * 6 + 5] ^= BIT2; 00315 halLcdSendCommand(&LcdInitMacro[8 * 6]); 00316 00317 LcdInitMacro[0x0B * 6 + 5] = ((LcdAddress & 0x1F) << 3); 00318 LcdInitMacro[0x0B * 6 + 4] = ((LcdAddress & 0x1F) << 3) + 3; 00319 LcdInitMacro[0x0C * 6 + 5] = (LcdAddress >> 5); 00320 LcdInitMacro[0x0C * 6 + 4] = (LcdAddress >> 5) + 7; 00321 halLcdSendCommand(&LcdInitMacro[0x0B * 6]); 00322 halLcdSendCommand(&LcdInitMacro[0x0C * 6]); 00323 00324 halLcdSetAddress(LcdAddress); 00325 } 00326 00327 /**********************************************************************//** 00328 * @brief Turns off the LCD cursor. 00329 * 00330 * @param none 00331 * 00332 * @return none 00333 *************************************************************************/ 00334 00335 void halLcdCursorOff(void) 00336 { 00337 LcdInitMacro[8 * 6 + 5] &= ~BIT2; 00338 halLcdSendCommand(&LcdInitMacro[8 * 6]); 00339 } 00340 00341 /**********************************************************************//** 00342 * @brief Inverts the grayscale values of the LCD display (Black <> white). 00343 * 00344 * @param none 00345 * 00346 * @return none 00347 *************************************************************************/ 00348 00349 void halLcdReverse(void) 00350 { 00351 LcdInitMacro[7 * 6 + 5] ^= BIT1; 00352 halLcdSendCommand(&LcdInitMacro[7 * 6]); 00353 } 00354 00355 /**********************************************************************//** 00356 * @brief Sets the LCD in standby mode to reduce power consumption. 00357 * 00358 * @param none 00359 * 00360 * @return none 00361 *************************************************************************/ 00362 00363 void halLcdStandby(void) 00364 { 00365 LcdInitMacro[3 * 6 + 5] &= (~BIT3) & (~BIT2); 00366 LcdInitMacro[3 * 6 + 5] |= BIT0; 00367 halLcdSendCommand(&LcdInitMacro[3 * 6]); 00368 } 00369 00370 /**********************************************************************//** 00371 * @brief Puts the LCD into active mode. 00372 * 00373 * @param none 00374 * 00375 * @return none 00376 *************************************************************************/ 00377 00378 void halLcdActive(void) 00379 { 00380 halLcdSendCommand(LcdInitMacro); // R00 start oscillation 00381 00382 // Wait a minimum of 25ms after issuing "start oscillation" 00383 // command (to accomodate for MCLK up to 25MHz) 00384 { 00385 int i; 00386 for(i = 0; i < 5; ++i) { 00387 __delay_cycles(50000); 00388 } 00389 } 00390 00391 LcdInitMacro[3 * 6 + 5] |= BIT3; 00392 LcdInitMacro[3 * 6 + 5] &= ~BIT0; 00393 halLcdSendCommand(&LcdInitMacro[3 * 6]); // R03 Power control 00394 } 00395 00396 /**********************************************************************//** 00397 * @brief Sets the pointer location in the LCD. 00398 * 00399 * - LcdAddress = Address 00400 * - LcdTableAddress = Correct Address Row + Column 00401 * = (Address / 0x20)* 17 + Column 00402 * 00403 * @param Address The target pointer location in the LCD. 00404 * 00405 * @return none 00406 *************************************************************************/ 00407 00408 void halLcdSetAddress(int Address) 00409 { 00410 int temp; 00411 00412 Draw_Block_Address_Macro[4] = Address >> 8; 00413 Draw_Block_Address_Macro[5] = Address & 0xFF; 00414 halLcdSendCommand(Draw_Block_Address_Macro); 00415 LcdAddress = Address; 00416 temp = Address >> 5; // Divided by 0x20 00417 temp = temp + (temp << 4); 00418 //Multiplied by (1+16) and added by the offset 00419 LcdTableAddress = temp + (Address & 0x1F); 00420 } 00421 00422 /**********************************************************************//** 00423 * @brief Draws a block at the specified LCD address. 00424 * 00425 * A block is the smallest addressable memory on the LCD and is 00426 * equivalent to 8 pixels, each of which is represented by 2 bits 00427 * that represent a grayscale value between 00b and 11b. 00428 * 00429 * @param Address The address at which to draw the block. 00430 * 00431 * @param Value The value of the block 00432 * 00433 * @return none 00434 *************************************************************************/ 00435 00436 void halLcdDrawBlock(unsigned int Address, unsigned int Value) 00437 { 00438 halLcdSetAddress(Address); 00439 halLcdDrawCurrentBlock(Value); 00440 } 00441 00442 /**********************************************************************//** 00443 * @brief Writes Value to LCD CGram and MSP430 internal LCD table. 00444 * 00445 * Also updates the LcdAddress and LcdTableAddress to the correct values. 00446 * 00447 * @param Value The value of the block to be written to the LCD. 00448 * 00449 * @return none 00450 *************************************************************************/ 00451 00452 void halLcdDrawCurrentBlock(unsigned int Value) 00453 { 00454 int temp; 00455 00456 Draw_Block_Value_Macro[4] = Value >> 8; 00457 Draw_Block_Value_Macro[5] = Value & 0xFF; 00458 LCD_MEM[LcdTableAddress] = Value; 00459 00460 halLcdSendCommand(Draw_Block_Value_Macro); 00461 00462 LcdAddress++; 00463 temp = LcdAddress >> 5; // Divided by 0x20 00464 temp = temp + (temp << 4); 00465 // Multiplied by (1+16) and added by the offset 00466 LcdTableAddress = temp + (LcdAddress & 0x1F); 00467 00468 // If LcdAddress gets off the right edge, move to next line 00469 if ((LcdAddress & 0x1F) > 0x11) 00470 halLcdSetAddress((LcdAddress & 0xFFE0) + 0x20); 00471 if (LcdAddress == LCD_Size) 00472 halLcdSetAddress(0); 00473 } 00474 00475 /**********************************************************************//** 00476 * @brief Returns the LCD CGRAM value at location Address. 00477 * 00478 * @param Address The address of the block to be read from the LCD. 00479 * 00480 * @return Value The value held at the specified address. 00481 *************************************************************************/ 00482 00483 int halLcdReadBlock(unsigned int Address) 00484 { 00485 int i = 0, Value = 0, ReadData[7]; 00486 00487 halLcdSetAddress(Address); 00488 halLcdSendCommand(Read_Block_Address_Macro); 00489 00490 LCD_CS_RST_OUT &= ~LCD_CS_PIN; // start transfer CS=0 00491 UCB2TXBUF = 0x77; // Transmit first character 0x77 00492 00493 while (!(UCB2IFG & UCTXIFG)) ; 00494 while (UCB2STAT & UCBUSY) ; 00495 00496 //Read 5 dummies values and 2 valid address data 00497 LCD_SPI_SEL &= ~LCD_MOSI_PIN; //Change SPI2C Dir 00498 LCD_SPI_SEL |= LCD_MISO_PIN; 00499 00500 for (i = 0; i < 7; i++) 00501 { 00502 UCB2IFG &= ~UCRXIFG; 00503 UCB2TXBUF = 1; // load dummy byte 1 for clk 00504 while (!(UCB2IFG & UCRXIFG)) ; 00505 ReadData[i] = UCB2RXBUF; 00506 } 00507 LCD_CS_RST_OUT |= LCD_CS_PIN; // Stop Transfer CS = 1 00508 00509 LCD_SPI_SEL |= LCD_MOSI_PIN; //Change SPI2C Dir 00510 LCD_SPI_SEL &= ~LCD_MISO_PIN; 00511 LCD_CS_RST_DIR |= LCD_MOSI_PIN + LCD_CLK_PIN; 00512 LCD_CS_RST_DIR &= ~LCD_MISO_PIN; 00513 00514 Value = (ReadData[5] << 8) + ReadData[6]; 00515 return Value; 00516 } 00517 00518 /**********************************************************************//** 00519 * @brief Draw a Pixel of grayscale at coordinate (x,y) to LCD 00520 * 00521 * @param x x-coordinate for grayscale value 00522 * 00523 * @param y y-coordinate for grayscale value 00524 * 00525 * @param GrayScale The intended grayscale value of the pixel - one of 00526 * four possible settings. 00527 * 00528 * @return none 00529 *************************************************************************/ 00530 00531 void halLcdPixel(int x, int y, unsigned char GrayScale) 00532 { 00533 int Address, Value; 00534 unsigned char offset; 00535 00536 //Each line increments by 0x20 00537 if ((x >= 0) && (x < LCD_COL) && (y >= 0) && (y < LCD_ROW)) 00538 { 00539 Address = (y << 5) + (x >> 3); //Narrow down to 8 possible pixels 00540 00541 Value = LCD_MEM[(y << 4) + y + (x >> 3)]; //y * 17 --> row. x>>3 --> column 00542 00543 offset = (x & 0x07) << 1; //3 LSBs = pos. within the 8 columns 00544 Value &= ~(3 << offset); //clear out the corresponding bits 00545 Value |= GrayScale << offset; //set pixel to GrayScale level 00546 00547 halLcdDrawBlock(Address, Value); 00548 } 00549 } 00550 00551 /**********************************************************************//** 00552 * @brief Clears entire LCD CGRAM as well as LCD_MEM. 00553 * 00554 * @param none 00555 * 00556 * @return none 00557 *************************************************************************/ 00558 00559 void halLcdClearScreen(void) 00560 { 00561 int i, j, k, Current_Location = 0; 00562 00563 halLcdSetAddress(0); 00564 00565 for (i = 0; i < 110; i++) 00566 { 00567 //prepare to send image 00568 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00569 for (k = 0; k < 3; k++) 00570 { 00571 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00572 UCB2TXBUF = Draw_Block_Value_Macro[k]; // Load data 00573 } 00574 while (UCB2STAT & UCBUSY) ; 00575 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00576 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00577 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00578 UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data 00579 00580 //send blank line 00581 for (j = 0; j < 17; j++) 00582 { 00583 LCD_MEM[LcdTableAddress++] = 0x00; 00584 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00585 UCB2TXBUF = 0x00; // Load data 00586 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00587 UCB2TXBUF = 0x00; // Load data 00588 } 00589 //Clear the partially visible block at the edge of the screen 00590 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00591 UCB2TXBUF = 0x00; // Load data 00592 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00593 UCB2TXBUF = 0x00; // Load data 00594 while (UCB2STAT & UCBUSY) ; 00595 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00596 00597 Current_Location += 0x20; 00598 halLcdSetAddress(Current_Location); 00599 } 00600 00601 halLcdSetAddress(0); 00602 } 00603 00604 /**********************************************************************//** 00605 * @brief Loads an image of size = rows * columns, starting at the 00606 * coordinate (x,y). 00607 * 00608 * @param Image[] The image to be loaded 00609 * 00610 * @param Rows The number of rows in the image. Size = Rows * Columns. 00611 * 00612 * @param Columns The number of columns in the image. Size = Rows * Columns. 00613 * 00614 * @param x x-coordinate of the image's starting location 00615 * 00616 * @param y y-coordinate of the image's starting location 00617 * 00618 * @return none 00619 *************************************************************************/ 00620 00621 void halLcdImage(const unsigned int Image[], int Columns, int Rows, int x, int y) 00622 { 00623 int i, CurrentLocation; 00624 00625 CurrentLocation = (y << 5) + (x >> 3); 00626 halLcdSetAddress(CurrentLocation); 00627 for (i = 0; i < Rows; i++) 00628 { 00629 halLcdDrawCurrentLine(Image, Columns); 00630 Image += Columns; 00631 CurrentLocation += 0x20; 00632 halLcdSetAddress(CurrentLocation); 00633 } 00634 } 00635 00636 /**********************************************************************//** 00637 * @brief Writes Value to LCD CGram and MSP430 internal LCD table. 00638 * 00639 * Also updates the LcdAddress and LcdTableAddress to the correct values. 00640 * 00641 * @param *value Pointer to the line to be written to the LCD. 00642 * 00643 * @return none 00644 *************************************************************************/ 00645 00646 void halLcdDrawCurrentLine(const unsigned int *value, int Columns) 00647 { 00648 unsigned char i; 00649 00650 //prepare to send image 00651 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00652 for (i = 0; i < 3; i++) 00653 { 00654 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00655 UCB2TXBUF = Draw_Block_Value_Macro[i]; // Load data 00656 } 00657 while (UCB2STAT & UCBUSY) ; 00658 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00659 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00660 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00661 UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data 00662 00663 //send the image 00664 for (i = 0; i < Columns; i++) 00665 { 00666 // Make sure we are not writing outside LCD_MEM[] 00667 if (LcdTableAddress >= sizeof(LCD_MEM)){ 00668 break; 00669 } 00670 LCD_MEM[LcdTableAddress++] = *value; 00671 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00672 UCB2TXBUF = (*value) >> 8; // Load data 00673 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00674 UCB2TXBUF = (*value++) & 0xFF; // Load data 00675 } 00676 00677 while (UCB2STAT & UCBUSY) ; 00678 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00679 } 00680 00681 /**********************************************************************//** 00682 * @brief Clears an image of size rows x columns starting at (x, y). 00683 * 00684 * @param Columns The size, in columns, of the image to be cleared. 00685 * 00686 * @param Rows The size, in rows, of the image to be cleared. 00687 * 00688 * @param x x-coordinate of the image to be cleared 00689 * 00690 * @param y y-coordinate of the image to be cleared 00691 * 00692 * @return none 00693 *************************************************************************/ 00694 00695 void halLcdClearImage(int Columns, int Rows, int x, int y) 00696 { 00697 int i, j, k, Current_Location; 00698 00699 Current_Location = (y << 5) + (x >> 3); 00700 halLcdSetAddress(Current_Location); 00701 00702 for (i = 0; i < Rows; i++) 00703 { 00704 //prepare to send image 00705 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00706 for (k = 0; k < 3; k++) 00707 { 00708 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00709 UCB2TXBUF = Draw_Block_Value_Macro[k]; // Load data 00710 } 00711 while (UCB2STAT & UCBUSY) ; 00712 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00713 LCD_CS_RST_OUT &= ~LCD_CS_PIN; //CS = 0 --> Start Transfer 00714 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00715 UCB2TXBUF = Draw_Block_Value_Macro[3]; // Load data 00716 00717 //send blank line 00718 for (j = 0; j < Columns; j++) 00719 { 00720 LCD_MEM[LcdTableAddress++] = 0x00; 00721 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00722 UCB2TXBUF = 0x00; // Load data 00723 while (!(UCB2IFG & UCTXIFG)) ; // Wait for TXIFG 00724 UCB2TXBUF = 0x00; // Load data 00725 } 00726 while (UCB2STAT & UCBUSY) ; 00727 LCD_CS_RST_OUT |= LCD_CS_PIN; //CS = 1 --> Stop Transfer 00728 00729 Current_Location += 0x20; 00730 halLcdSetAddress(Current_Location); 00731 } 00732 } 00733 00734 /**********************************************************************//** 00735 * @brief Writes Value to LCD CGRAM. Pointers internal to the LCD 00736 * are also updated. 00737 * 00738 * @param Value The value to be written to the current LCD pointer 00739 * 00740 * @return none 00741 *************************************************************************/ 00742 00743 void halLcdDrawTextBlock(unsigned int Value) 00744 { 00745 int temp; 00746 00747 Draw_Block_Value_Macro[4] = Value >> 8; 00748 Draw_Block_Value_Macro[5] = Value & 0xFF; 00749 LCD_MEM[LcdTableAddress] = Value; 00750 00751 halLcdSendCommand(Draw_Block_Value_Macro); 00752 00753 LcdAddress++; 00754 temp = LcdAddress >> 5; // Divided by 0x20 00755 temp = temp + (temp << 4); 00756 //Multiplied by (1+16) and added by the offset 00757 LcdTableAddress = temp + (LcdAddress & 0x1F); 00758 00759 // If LcdAddress gets off the right edge, move to next line 00760 if ((LcdAddress & 0x1F) > 0x10) 00761 halLcdSetAddress((LcdAddress & 0xFFE0) + 0x20); 00762 00763 if (LcdAddress >= LCD_Size) 00764 halLcdSetAddress(0); 00765 } 00766 00767 /**********************************************************************//** 00768 * @brief Displays the string to the LCD starting at current location. 00769 * 00770 * Writes all the data to LCD_MEM first, then updates all corresponding 00771 * LCD CGRAM locations at once, in a continuous fashion. 00772 * 00773 * @param String[] The string to be displayed on LCD. 00774 * 00775 * @param TextStyle Value that specifies whether the string is to be 00776 * inverted or overwritten. 00777 * - Invert = 0x01 00778 * - Overwrite = 0x04 00779 * 00780 * @return none 00781 *************************************************************************/ 00782 00783 void halLcdPrint(char String[], unsigned char TextStyle) 00784 { 00785 int i, j, Counter = 0, BlockValue; 00786 int Address, LCD_MEM_Add, ActualAddress; 00787 int temp; 00788 char LookUpChar; 00789 00790 ActualAddress = LcdAddress; 00791 Counter = LcdAddress & 0x1F; 00792 i = 0; 00793 00794 while (String[i] != 0) // Stop on null character 00795 { 00796 LookUpChar = fonts_lookup[String[i]]; 00797 00798 for (j = 0; j < FONT_HEIGHT; j++) 00799 { 00800 Address = ActualAddress + j * 0x20; 00801 temp = Address >> 5; 00802 temp += (temp << 4); 00803 00804 LCD_MEM_Add = temp + (Address & 0x1F); 00805 00806 BlockValue = LCD_MEM[LCD_MEM_Add]; 00807 00808 if (TextStyle & GRAYSCALE_TEXT) 00809 { 00810 if (TextStyle & INVERT_TEXT) 00811 if (TextStyle & OVERWRITE_TEXT) 00812 BlockValue = 0xAAAA - GrayScale_fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00813 else 00814 BlockValue |= 0xAAAA - GrayScale_fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00815 else 00816 if (TextStyle & OVERWRITE_TEXT) 00817 BlockValue = GrayScale_fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00818 else 00819 BlockValue |= GrayScale_fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00820 } 00821 else 00822 { 00823 if (TextStyle & INVERT_TEXT) 00824 if (TextStyle & OVERWRITE_TEXT) 00825 BlockValue = 0xFFFF - fonts[LookUpChar * 13 + j]; 00826 else 00827 BlockValue |= 0xFFFF - fonts[LookUpChar * 13 + j]; 00828 00829 else 00830 if (TextStyle & OVERWRITE_TEXT) 00831 BlockValue = fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00832 else 00833 BlockValue |= fonts[LookUpChar * (FONT_HEIGHT + 1) + j]; 00834 } 00835 halLcdDrawBlock(Address, BlockValue); 00836 } 00837 00838 Counter++; 00839 if (Counter == 17) 00840 { 00841 Counter = 0; 00842 ActualAddress += 0x20 * FONT_HEIGHT - 16; 00843 if (ActualAddress > LCD_Last_Pixel - 0x20 * FONT_HEIGHT) 00844 ActualAddress = 0; 00845 } 00846 else 00847 ActualAddress++; 00848 i++; 00849 } 00850 halLcdSetAddress(ActualAddress); 00851 00852 } 00853 00854 /**********************************************************************//** 00855 * @brief Displays the string to the LCD starting at (x,y) location. 00856 * 00857 * Writes all the data to LCD_MEM first, then updates all corresponding 00858 * LCD CGRAM locations at once, in a continuous fashion. 00859 * 00860 * @param String[] String to be displayed on LCD 00861 * 00862 * @param x x-coordinate of the write location on the LCD 00863 * 00864 * @param y y-coordinate of the write location on the LCD 00865 * 00866 * @param TextStyle Value that specifies whether the string is to be 00867 * inverted or overwritten. 00868 * - Invert = 0x01 00869 * - Overwrite = 0x04 00870 *************************************************************************/ 00871 00872 void halLcdPrintXY(char String[], int x, int y, unsigned char TextStyle) 00873 { 00874 //Each line increments by 0x20 00875 halLcdSetAddress((y << 5) + (x >> 3)); //Narrow down to 8 possible pixels 00876 halLcdPrint(String, TextStyle); 00877 } 00878 00879 /**********************************************************************//** 00880 * @brief Displays a string on the LCD on the specified line. 00881 * 00882 * @param String[] The string to be displayed on LCD. 00883 * 00884 * @param Line The line on the LCD on which to print the string. 00885 * 00886 * @param TextStyle Value that specifies whether the string is to be 00887 * inverted or overwritten. 00888 * - Invert = 0x01 00889 * - Overwrite = 0x04 00890 * 00891 * @return none 00892 *************************************************************************/ 00893 00894 void halLcdPrintLine(char String[], unsigned char Line, unsigned char TextStyle) 00895 { 00896 int temp; 00897 00898 temp = Line * FONT_HEIGHT; 00899 halLcdSetAddress(temp << 5); // 0x20 = 2^5 00900 halLcdPrint(String, TextStyle); 00901 } 00902 00903 /**********************************************************************//** 00904 * @brief Prints a string beginning on a given line and column. 00905 * 00906 * @param String[] The string to be displayed on LCD. 00907 * 00908 * @param Line The line on which to print the string of text 00909 * 00910 * @param Col The column on which to print the string of text 00911 * 00912 * @param TextStyle Value that specifies whether the string is to be 00913 * inverted or overwritten. 00914 * - Invert = 0x01 00915 * - Overwrite = 0x04 00916 * 00917 * @return none 00918 *************************************************************************/ 00919 00920 void halLcdPrintLineCol(char String[], unsigned char Line, unsigned char Col, 00921 unsigned char TextStyle) 00922 { 00923 int temp; 00924 00925 temp = Line * FONT_HEIGHT; 00926 temp <<= 5; 00927 temp += Col; 00928 00929 halLcdSetAddress(temp); // 0x20 = 2^5 00930 halLcdPrint(String, TextStyle); 00931 } 00932 00933 /**********************************************************************//** 00934 * @brief Draws a horizontral line from (x1,y) to (x2,y) of GrayScale level 00935 * 00936 * @param x1 x-coordinate of the first point 00937 * 00938 * @param x2 x-coordinate of the second point 00939 * 00940 * @param y y-coordinate of both points 00941 * 00942 * @param GrayScale Grayscale level of the horizontal line 00943 * 00944 * @return none 00945 *************************************************************************/ 00946 00947 void halLcdHLine(int x1, int x2, int y, unsigned char GrayScale) 00948 { 00949 int x_dir, x; 00950 00951 if (x1 < x2) 00952 x_dir = 1; 00953 else 00954 x_dir = -1; 00955 x = x1; 00956 while (x != x2) 00957 { 00958 halLcdPixel(x, y, GrayScale); 00959 x += x_dir; 00960 } 00961 } 00962 00963 /**********************************************************************//** 00964 * @brief Draws a vertical line from (x,y1) to (x,y2) of GrayScale level 00965 * 00966 * @param x x-coordinate of both points 00967 * 00968 * @param y1 y-coordinate of the first point 00969 * 00970 * @param y2 y-coordinate of the second point 00971 * 00972 * @param GrayScale GrayScale level of the vertical line 00973 * 00974 * @return none 00975 *************************************************************************/ 00976 00977 void halLcdVLine(int x, int y1, int y2, unsigned char GrayScale) 00978 { 00979 int y_dir, y; 00980 00981 if (y1 < y2) 00982 y_dir = 1; 00983 else 00984 y_dir = -1; 00985 y = y1; 00986 while (y != y2) 00987 { 00988 halLcdPixel(x, y, GrayScale); 00989 y += y_dir; 00990 } 00991 } 00992 00993 /**********************************************************************//** 00994 * @brief Draws a line from (x1,y1) to (x2,y2) of GrayScale level. 00995 * 00996 * Uses Bresenham's line algorithm. 00997 * 00998 * @param x1 x-coordinate of the first point 00999 * 01000 * @param y1 y-coordinate of the first point 01001 * 01002 * @param x2 x-coordinate of the second point 01003 * 01004 * @param y2 y-coordinate of the second point 01005 * 01006 * @param GrayScale Grayscale level of the line 01007 * 01008 * @return none 01009 *************************************************************************/ 01010 01011 void halLcdLine(int x1, int y1, int x2, int y2, unsigned char GrayScale) 01012 { 01013 int x, y, deltay, deltax, d; 01014 int x_dir, y_dir; 01015 01016 if (x1 == x2) 01017 halLcdVLine(x1, y1, y2, GrayScale); 01018 else 01019 { 01020 if (y1 == y2) 01021 halLcdHLine(x1, x2, y1, GrayScale); 01022 else // a diagonal line 01023 { 01024 if (x1 > x2) 01025 x_dir = -1; 01026 else x_dir = 1; 01027 if (y1 > y2) 01028 y_dir = -1; 01029 else y_dir = 1; 01030 01031 x = x1; 01032 y = y1; 01033 deltay = ABS(y2 - y1); 01034 deltax = ABS(x2 - x1); 01035 01036 if (deltax >= deltay) 01037 { 01038 d = (deltay << 1) - deltax; 01039 while (x != x2) 01040 { 01041 halLcdPixel(x, y, GrayScale); 01042 if (d < 0) 01043 d += (deltay << 1); 01044 else 01045 { 01046 d += ((deltay - deltax) << 1); 01047 y += y_dir; 01048 } 01049 x += x_dir; 01050 } 01051 } 01052 else 01053 { 01054 d = (deltax << 1) - deltay; 01055 while (y != y2) 01056 { 01057 halLcdPixel(x, y, GrayScale); 01058 if (d < 0) 01059 d += (deltax << 1); 01060 else 01061 { 01062 d += ((deltax - deltay) << 1); 01063 x += x_dir; 01064 } 01065 y += y_dir; 01066 } 01067 } 01068 } 01069 } 01070 } 01071 01072 /**********************************************************************//** 01073 * @brief Draw a circle of Radius with center at (x,y) of GrayScale level. 01074 * 01075 * Uses Bresenham's circle algorithm 01076 * 01077 * @param x x-coordinate of the circle's center point 01078 * 01079 * @param y y-coordinate of the circle's center point 01080 * 01081 * @param Radius Radius of the circle 01082 * 01083 * @param GrayScale Grayscale level of the circle 01084 *************************************************************************/ 01085 01086 void halLcdCircle(int x, int y, int Radius, int GrayScale) 01087 { 01088 int xx, yy, ddF_x, ddF_y, f; 01089 01090 ddF_x = 0; 01091 ddF_y = -(2 * Radius); 01092 f = 1 - Radius; 01093 01094 xx = 0; 01095 yy = Radius; 01096 halLcdPixel(x + xx, y + yy, GrayScale); 01097 halLcdPixel(x + xx, y - yy, GrayScale); 01098 halLcdPixel(x - xx, y + yy, GrayScale); 01099 halLcdPixel(x - xx, y - yy, GrayScale); 01100 halLcdPixel(x + yy, y + xx, GrayScale); 01101 halLcdPixel(x + yy, y - xx, GrayScale); 01102 halLcdPixel(x - yy, y + xx, GrayScale); 01103 halLcdPixel(x - yy, y - xx, GrayScale); 01104 while (xx < yy) 01105 { 01106 if (f >= 0) 01107 { 01108 yy--; 01109 ddF_y += 2; 01110 f += ddF_y; 01111 } 01112 xx++; 01113 ddF_x += 2; 01114 f += ddF_x + 1; 01115 halLcdPixel(x + xx, y + yy, GrayScale); 01116 halLcdPixel(x + xx, y - yy, GrayScale); 01117 halLcdPixel(x - xx, y + yy, GrayScale); 01118 halLcdPixel(x - xx, y - yy, GrayScale); 01119 halLcdPixel(x + yy, y + xx, GrayScale); 01120 halLcdPixel(x + yy, y - xx, GrayScale); 01121 halLcdPixel(x - yy, y + xx, GrayScale); 01122 halLcdPixel(x - yy, y - xx, GrayScale); 01123 } 01124 } 01125 01126 /**********************************************************************//** 01127 * @brief Scrolls a single row of pixels one column to the left. 01128 * 01129 * The column that is scrolled out of the left side of the LCD will be 01130 * displayed the right side of the LCD. 01131 * 01132 * @param y The row of pixels to scroll. y = 0 is at the top-left 01133 * corner of the LCD. 01134 * 01135 * @return none 01136 *************************************************************************/ 01137 01138 void halLcdScrollRow(int y) 01139 { 01140 int i, Address, LcdTableAddressTemp; 01141 unsigned int temp; 01142 01143 Address = y << 5; 01144 01145 halLcdSetAddress(Address); 01146 01147 //Multiplied by (1+16) and added by the offset 01148 LcdTableAddressTemp = y + (y << 4); 01149 temp = ((LCD_MEM[LcdTableAddressTemp] & 0x0003) << 14); 01150 01151 for (i = 0; i < 0x10; i++) 01152 halLcdDrawCurrentBlock(((LCD_MEM[LcdTableAddressTemp + i] & 0xFFFC) >> 2) \ 01153 + ((LCD_MEM[LcdTableAddressTemp + i + 1] & 0x0003) << 14)); 01154 01155 halLcdDrawCurrentBlock(((LCD_MEM[LcdTableAddressTemp + 0x10] & 0xFFFC) >> 2) + temp); 01156 } 01157 01158 /**********************************************************************//** 01159 * @brief Scrolls multiple rows of pixels, yStart to yEnd, 01160 * one column to the left. 01161 * 01162 * The column that is scrolled out of the left side of the LCD will be 01163 * displayed the right side of the LCD. y = 0 is at the top-left of the 01164 * LCD screen. 01165 * 01166 * @param yStart The beginning row to be scrolled 01167 * 01168 * @param yEnd The last row to be scrolled 01169 * 01170 * @return none 01171 *************************************************************************/ 01172 01173 void halLcdHScroll(int yStart, int yEnd) 01174 { 01175 int i; 01176 01177 for (i = yStart; i < yEnd + 1; i++) 01178 halLcdScrollRow(i); 01179 } 01180 01181 /**********************************************************************//** 01182 * @brief Scrolls a line of text one column to the left. 01183 * 01184 * @param Line The line of text to be scrolled. 01185 * 01186 * @return none 01187 *************************************************************************/ 01188 01189 void halLcdScrollLine(int Line) 01190 { 01191 int i, Row; 01192 01193 Row = Line * FONT_HEIGHT; 01194 01195 for (i = Row; i < Row + FONT_HEIGHT; i++) 01196 halLcdScrollRow(i); 01197 } 01198