////////////////////////////////////////////////////////////////////////////////
///                        Flex_LCD4x20_3pines.c                             ///
///            Driver for temperature and humidity sensor                    ///
///            Realizado por PicTrance                                       ///
///            junio del 2011, Puebla - México                               ///
///            Compiler: CCS                                                 ///
///                                                                          ///
///            Modificacion del del felx_lcd_3pins.c  y del Flex_LCD420.c    ///
///                                                                          ///
/// lcd_init()  - Iicializa el sensor sht21 -                                ///
///                                                                          ///
/// lcd_putc(c) - para mandar a escribir en el LCD                           ///
///                                                                          ///
/// lcd_gotoxy(x,y) - para mandar el cursor auna posicion especifia en el lcd///
///                                                                          ///
/// lcd_setcursor_vb(visible,blink) - para hacer el cursor visible           ///
///                          u ocultaro y también poder hacer que parpadee   ///
///                                                                          ///
/// Modificación del felx_lcd_3pins.c y del Flex_LCD420.c                    ///
/// por PicTrance (I.S.R.)                                                   ///
/// Trabaja con 3 pines y 74VHC164                                           ///
/// 8-Bit Serial-In, Parallel-Out Shift Register                             ///
/// La LCD se usa en modo 4bits, Revisar diagrama de conexion Adjunto        ///
/// No esta habilitada la lectura del LCD                                    ///
/// RW debe ir a gnd                                                         ///
///                                                                          ///
/// Definir pines antes de llamar libreria                                   ///
/// #define LCD_E     PIN_A0                                                 ///
/// #define LCD_CK    PIN_A1                                                 ///
/// #define LCD_DAT   PIN_A2                                                 ///
////////////////////////////////////////////////////////////////////////////////

//Definir pines antes de llamar libreria//
//#define LCD_E     PIN_A0
//#define LCD_CK    PIN_A1
//#define LCD_DAT   PIN_A2

// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/

//========================================
int RS_bit;
int8 lcd_line; // para ir de linea en linea de las 4 del lcd
#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)


int8 const LCD_INIT_STRING[4] = {
   0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
   0xc,                     // Display on
   1,                       // Clear display
   6                        // Increment cursor
};


//-----------------------------------------------
void lcd_send_nibble(int8 nibble, int rs_bit){
   int x;
   if(RS_bit==1)
      nibble=nibble|0x10;

   for(x=0;x<5;x++){
      output_bit(LCD_DAT,shift_right(&nibble,1,0));
      delay_us(1000);
      output_low(LCD_CK);
      delay_us(1000);
      output_high(LCD_CK);}

   output_high(LCD_E);
   delay_us(2000);
   output_low(LCD_E);
   delay_us(2000);
}

//----------------------------------------
// Send a byte to the LCD.

void lcd_send_byte(int8 address, int8 n){
//output_low(LCD_RS);
   RS_bit=0;
   delay_us(100000);


   if(address)
      //output_high(LCD_RS);
      RS_bit=1;
   else
      //output_low(LCD_RS);
      RS_bit=0;

   delay_us(1000);


   output_low(LCD_E);

   lcd_send_nibble(n >> 4,RS_bit);
   lcd_send_nibble(n & 0xf,RS_bit);
}

//----------------------------
void lcd_init(void){
   int8 i;

   //output_low(LCD_RS);
   RS_bit=0;

   output_low(LCD_E);

   delay_ms(200);

   for(i=0 ;i < 3; i++){
      lcd_send_nibble(0x03,RS_bit);
      delay_ms(50);
   }

   lcd_send_nibble(0x02,RS_bit);

   for(i=0; i < sizeof(LCD_INIT_STRING); i++){
      lcd_send_byte(0, LCD_INIT_STRING[i]);
      delay_ms(50);
   }
}

//----------------------------
void lcd_gotoxy(int8 x, int8 y){
   int8 address;

   switch(y){
      case 1:
         address = LCD_LINE_1_ADDRESS;
         break;
      case 2:
         address = LCD_LINE_2_ADDRESS;
         break;
      case 3:
         address = LCD_LINE_3_ADDRESS;
         break;
      case 4:
         address = LCD_LINE_4_ADDRESS;
         break;
      default:
         address = LCD_LINE_1_ADDRESS;
         break;
      }

   address += x-1;
   lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c){
   switch(c){
      case '\f':
         lcd_send_byte(0,1);
         lcd_line = 1;
         delay_ms(80);
         break;
      case '\n':
         lcd_gotoxy(1, ++lcd_line);
         break;
      case '\b':
         lcd_send_byte(0,0x10);
         break;
      default:
         lcd_send_byte(1,c);
         break;
   }
}

//------------------------------
void lcd_setcursor_vb(short visible, short blink){
   lcd_send_byte(0, 0xC|(visible<<1)|blink);
}
