/*
 * File:   LCD.c
 * Author: Christian Mares
 *
 * Created on 13 de diciembre de 2017, 20:47
 */

#define no1
#ifdef no1

#include "main.h"

//#define LCD_F_INSTR         1000                                    // Define a fast instruction execution time in terms of loop time (typically > 43us_
//#define LCD_S_INSTR         3000                                    // Define a slow instruction execution time in terms of loop time (typically > 1.35ms)
//#define LCD_STARTUP         20000                                   // Define the startup time for the LCD in terms of loop time (typically > 30ms)
//
//#define LCD_MAX_COLUMN      16

#define LCD_SendData(data) { PMADDR = LCDDATA;  PMDATA = data;  delay2(LCD_F_INSTR); }
#define LCD_SendCommand(command, delay) { PMADDR = LCDCMD; PMDATA = command; delay2(delay); }
#define LCD_TrapSafe_SendCommand(command, delay) { PMADDR = LCDCMD; PMDATA = command; delay3(delay); }
#define LCD_SetCustomChar(character) { PMADDR = LCDCMD; PMDATA = LCD_COMMAND_WRITE_CGRAM & character; delay2(LCD_F_INSTR); }
#define LCD_COMMAND_CLEAR_SCREEN        0x01
#define LCD_COMMAND_RETURN_HOME         0x02
#define LCD_COMMAND_WRITE_CGRAM         0x20

#define LCD_F_INSTR         2    //   2 == 50us                     // Define a fast instruction execution time in terms of loop time (typically > 43us_
#define LCD_S_INSTR         6    //   6 == 150us                    // Define a slow instruction execution time in terms of loop time (typically > 1.35ms)
#define LCD_STARTUP         120  // 120 == 30ms                     // Define the startup time for the LCD in terms of loop time (typically > 30ms)

#define LCD_FailSafe_F_INSTR 200 //   2 == 50us                     // Define a fast instruction execution time in terms of loop time (typically > 43us_
#define LCD_FailSafe_S_INSTR 600 //   6 == 150us                    // Define a slow instruction execution time in terms of loop time (typically > 1.35ms)

#define LCD_MAX_COLUMN      16

bool LCD_IS_ON = false;

void Inic_LCD( void){
  // PMP initialization
  PMCON  = 0x83BF;             // Enable the PMP
  PMMODE = 0x03FF;             // Master Mode 1
  PMAEN  = 0x0001;             // PMA0 enabled

  // initialise TMR1
//  T1CON = 0x8030;             // Fosc/2, prescaled 1:256, 16us/tick

  // wait for >30ms
  delay2(LCD_STARTUP);

  //initiate the HD44780 display 8-bit init sequence
  PMADDR = LCDCMD;            // command register
  PMDATA = 0b00111000;        // 8-bit interface, 2 lines, 5x7
  delay2(LCD_S_INSTR);

  PMDATA = 0b00001110;        // display ON, cursor off, blink off
  delay2(LCD_S_INSTR);

  PMDATA = 0b00000001;        // clear display
  delay2(LCD_STARTUP+LCD_F_INSTR);

  PMDATA = 0b00000110;        // increment cursor, no shift
  delay2(LCD_STARTUP+LCD_S_INSTR);
  
  LCD_IS_ON = true;
  
}

char readLCD( int addr){
  int dummy;
  while( PMMODEbits.BUSY);    // wait for PMP to be available
  PMADDR = addr;              // select the command address
  dummy = PMDATA;             // initiate a read cycle, dummy read
  while( PMMODEbits.BUSY);    // wait for PMP to be available
  return( PMDATA);            // read the status register
}
void writeLCD( int addr, unsigned char c){
  while( busyLCD());
  while( PMMODEbits.BUSY);    // wait for PMP to be available
  PMADDR = addr;
  PMDATA = c;
}
void LCD_Send_Char(char d){
  int z;//,x;

  // section of code to include special characters such as new line
  switch (d)
  {
      case'\n':
          setLCDC(0x3f);
          break;

      case'\r':
          z = addrLCD();
          z=(z+64);
          z=(z&0x40);
          setLCDC(z);
          break;

      case'\t':
//          z = addrLCD();
//          x= (5 - (z%5));
//          setLCDC((z+x));
          writeLCD( LCDDATA, ' ');
          break;

      default:
          writeLCD( LCDDATA, d);
          break;
  }
}
int LCD_Send_String(char *buffer){
    int i;
    unsigned int len= length(buffer);
    for (i = len; i; --i)
        LCD_Send_Char( *buffer++);
    
    return(len);
}
void LCD_Send_String_L(char* buffer, unsigned short length){
    while (length--){
        switch(*buffer){
            case 0x00:
                return;
            default:
                LCD_Send_Char(*buffer++);
                break;
        }
    }
}

void LCD_ClearScreen(){
    LCD_SendCommand ( LCD_COMMAND_CLEAR_SCREEN , LCD_S_INSTR ) ;
    LCD_SendCommand ( LCD_COMMAND_RETURN_HOME ,  LCD_S_INSTR ) ;
}
void LCD_Home(){
    LCD_SendCommand ( LCD_COMMAND_RETURN_HOME ,  LCD_S_INSTR ) ;
}

void LCD_TrapSafe_ClearScreen(){
    LCD_TrapSafe_SendCommand ( LCD_COMMAND_CLEAR_SCREEN , LCD_FailSafe_S_INSTR ) ;
    LCD_TrapSafe_SendCommand ( LCD_COMMAND_RETURN_HOME ,  LCD_FailSafe_S_INSTR ) ;
}
void LCD_TrapSafe_Home(){
    LCD_TrapSafe_SendCommand ( LCD_COMMAND_RETURN_HOME ,  LCD_FailSafe_S_INSTR ) ;
}

#endif