text: /**
   * @file lcd.h
   * @author <b>Group 20:</b>
   <ul>
  	<li>Pradyumna Kumar
  	<li>Jayanth Tadinada
  	<li>Sharjeel Imam
   </ul>
   * @section DESCRIPTION
   This file defines various functions for Firebird V movement, interrupts, motor speed and pin configurations
   
   LCD Connections:
   			 LCD	  Microcontroller Pins
   			  RS  --> PC0
  			  RW  --> PC1
  			  EN  --> PC2
  			  DB7 --> PC7
  			  DB6 --> PC6
  			  DB5 --> PC5
  			  DB4 --> PC4
  
   Note: 
    1. Make sure that in the configuration options following settings are 
   	done for proper operation of the code
  
   	Microcontroller: atmega2560
   	Frequency: 11059200
   	Optimization: -O0 (For more information read section: Selecting proper optimization options 
  						below figure 4.22 in the hardware manual)
  
   2. Buzzer is connected to PC3. Hence to operate buzzer without interfearing with the LCD, 
   	buzzer should be turned on or off only using buzzer function 
  * @section LICENSE
     Copyright (c) 2010, ERTS Lab IIT Bombay erts@cse.iitb.ac.in 
     All rights reserved.
  
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions are met:
  
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
  
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in
       the documentation and/or other materials provided with the
       distribution.
  
     * Neither the name of the copyright holders nor the names of
       contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
  
     * Source code can be used for academic purpose. 
  	 For commercial use permission form the author needs to be taken.
  
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE. 
  
    Software released under Creative Commence cc by-nc-sa licence.
    For legal information refer to: 
    http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode
  
  ********************************************************************************/
  
  #define FCPU 11059200ul //!< The frequency of CPU crystal
  #define RS 0
  #define RW 1
  #define EN 2
  #define lcd_port PORTC	//!< PORT to which LCD is connected
  
  #define sbit(reg,bit)	reg |= (1<<bit)			//!<  to set a certain bit of given register. 
  #define cbit(reg,bit)	reg &= ~(1<<bit)		//!<  to reset a certain bit of given register.
  
  unsigned int temp; //!< A global variable used for temporary storage in various functions.
  unsigned int unit; //!< Number of chars to be written on the LCD Screen.
  unsigned int tens; //!< Means only two chars of the given string are to be printed
  unsigned int hundred; //!< Means only three chars of the given string are to be printed
  unsigned int thousand; //!< Means only four chars of the given string are to be printed
  unsigned int million; //!< Means only six chars of the given string are to be printed
  
  
  void lcd_reset();
  void lcd_init();
  void lcd_wr_command(unsigned char);
  void lcd_wr_char(char);
  void lcd_line1();
  void lcd_line2();
  void lcd_string(char*);
  
  /**
   * Initialize the LCD ports. This functions need to be called only once and before calling any other LCD related function.
   * This function is called through port_init() and not directly.
   */
  void lcd_port_config (void)
  {
   DDRC = DDRC | 0xF7; //all the LCD pin's direction set as output
   PORTC = PORTC & 0x80; // all the LCD pins are set to logic 0 except PORTC 7
  }
  
  /**
   * Will reset the LCD screen and set it to work in 4bit mode.
   */
   void lcd_set_4bit()
  {
  	_delay_ms(1);
  
  	cbit(lcd_port,RS);				//RS=0 --- Command Input
  	cbit(lcd_port,RW);				//RW=0 --- Writing to LCD
  	lcd_port = 0x30;				//Sending 3
  	sbit(lcd_port,EN);				//Set Enable Pin
  	_delay_ms(5);					//Delay
  	cbit(lcd_port,EN);				//Clear Enable Pin
  
  	_delay_ms(1);
  
  	cbit(lcd_port,RS);				//RS=0 --- Command Input
  	cbit(lcd_port,RW);				//RW=0 --- Writing to LCD
  	lcd_port = 0x30;				//Sending 3
  	sbit(lcd_port,EN);				//Set Enable Pin
  	_delay_ms(5);					//Delay
  	cbit(lcd_port,EN);				//Clear Enable Pin
  
  	_delay_ms(1);
  
  	cbit(lcd_port,RS);				//RS=0 --- Command Input
  	cbit(lcd_port,RW);				//RW=0 --- Writing to LCD
  	lcd_port = 0x30;				//Sending 3
  	sbit(lcd_port,EN);				//Set Enable Pin
  	_delay_ms(5);					//Delay
  	cbit(lcd_port,EN);				//Clear Enable Pin
  
  	_delay_ms(1);
  
  	cbit(lcd_port,RS);				//RS=0 --- Command Input
  	cbit(lcd_port,RW);				//RW=0 --- Writing to LCD
  	lcd_port = 0x20;				//Sending 2 to initialise LCD 4-bit mode
  	sbit(lcd_port,EN);				//Set Enable Pin
  	_delay_ms(5);					//Delay
  	cbit(lcd_port,EN);				//Clear Enable Pin
  
  	
  }
  
  /**
   * Initialize the LCD screen so that we can write to it. Call this function only once.
   */
   void lcd_init()
  {
  	_delay_ms(1);
  
  	lcd_wr_command(0x28);			//LCD 4-bit mode and 2 lines.
  	lcd_wr_command(0x01);
  	lcd_wr_command(0x06);
  	lcd_wr_command(0x0E);
  	lcd_wr_command(0x80);
  		
  }	 
  	 
  /**
   * @param cmd - send a character command to LCD.
   */
   void lcd_wr_command(unsigned char cmd)
  {
  	unsigned char temp;
  	temp = cmd;
  	temp = temp & 0xF0;
  	lcd_port &= 0x0F;
  	lcd_port |= temp;
  	cbit(lcd_port,RS);
  	cbit(lcd_port,RW);
  	sbit(lcd_port,EN);
  	_delay_ms(5);
  	cbit(lcd_port,EN);
  	
  	cmd = cmd & 0x0F;
  	cmd = cmd<<4;
  	lcd_port &= 0x0F;
  	lcd_port |= cmd;
  	cbit(lcd_port,RS);
  	cbit(lcd_port,RW);
  	sbit(lcd_port,EN);
  	_delay_ms(5);
  	cbit(lcd_port,EN);
  }
  
  /**
   * @param letter - Write a single character to LCD screen. 
   */
  void lcd_wr_char(char letter)
  {
  	char temp;
  	temp = letter;
  	temp = (temp & 0xF0);
  	lcd_port &= 0x0F;
  	lcd_port |= temp;
  	sbit(lcd_port,RS);
  	cbit(lcd_port,RW);
  	sbit(lcd_port,EN);
  	_delay_ms(5);
  	cbit(lcd_port,EN);
  
  	letter = letter & 0x0F;
  	letter = letter<<4;
  	lcd_port &= 0x0F;
  	lcd_port |= letter;
  	sbit(lcd_port,RS);
  	cbit(lcd_port,RW);
  	sbit(lcd_port,EN);
  	_delay_ms(5);
  	cbit(lcd_port,EN);
  }
  
  
  /**
   * Bring cursor to 1,1
   */
  void lcd_home()
  {
  	lcd_wr_command(0x80);
  }
  
  
  /**
   * @param str - a pointer to a string to be printed on the lcd screen.
   */
  void lcd_string(char *str)
  {
  	while(*str != '\0')
  	{
  		lcd_wr_char(*str);
  		str++;
  	}
  }
  
  /**
   *  Takes the cuser to row,column.
   * @param row - row number 
   * @param column - column number 
   *
   */
  void lcd_cursor (char row, char column)
  {
  	switch (row) {
  		case 1: lcd_wr_command (0x80 + column - 1); break;
  		case 2: lcd_wr_command (0xc0 + column - 1); break;
  		case 3: lcd_wr_command (0x94 + column - 1); break;
  		case 4: lcd_wr_command (0xd4 + column - 1); break;
  		default: break;
  	}
  }
  
  /**
   * Given a value print it upto certain characters. For example lcd_print(0,0,1000,1); will print 1 on the LCD screen.
   * @param row - Row number
   * @param coloumn - column number where cursor is to be moved
   * @param value - value to be printed on the screen.
   * @param digits - number of digits in the value to be printed.
   * 
   */
  void lcd_print (char row, char coloumn, unsigned int value, int digits)
  {
  	unsigned char flag=0;
  	if(row==0||coloumn==0)
  	{
  		lcd_home();
  	}
  	else
  	{
  		lcd_cursor(row,coloumn);
  	}
  	if(digits==5 || flag==1)
  	{
  		million=value/10000+48;
  		lcd_wr_char(million);
  		flag=1;
  	}
  	if(digits==4 || flag==1)
  	{
  		temp = value/1000;
  		thousand = temp%10 + 48;
  		lcd_wr_char(thousand);
  		flag=1;
  	}
  	if(digits==3 || flag==1)
  	{
  		temp = value/100;
  		hundred = temp%10 + 48;
  		lcd_wr_char(hundred);
  		flag=1;
  	}
  	if(digits==2 || flag==1)
  	{
  		temp = value/10;
  		tens = temp%10 + 48;
  		lcd_wr_char(tens);
  		flag=1;
  	}
  	if(digits==1 || flag==1)
  	{
  		unit = value%10 + 48;
  		lcd_wr_char(unit);
  	}
  	if(digits>5)
  	{
  		lcd_wr_char('E');
  	}
  	
  }
  