Contiki 2.6

hal_lcd.c

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