/*
* File: lcd_HD44780.h
* Author: Darío
*
* Created on 9 de junio de 2016, 12:04
*/
//------------------------------------------------------------------------------
#include "lcd_HD44780.h"
//------------------------------------------------------------------------------
void inicializarDatosLCD(void);
//##############################################################################
//### I n i c i a l i z a c i o n d e l L C D c o n d e l a y s ####
//##############################################################################
/*
* La inicializacion del LCD se hace con delays para poder ejecutarla antes de
* activar las interrupciones y los timers.
*/
void LCDpasajeDatos(void)
{
LCD_E_PORT = 1; // habilita la comunicacion para que procese el nibble
__delay_us( 20 ); // delay para garantizar el pasaje de datos al lcd
LCD_E_PORT = 0; // deshabilita la comunicacion
}
//------------------------------------------------------------------------------
void LCDenviaByte( t_byte dato )
{
// transmite el nibble alto al lcd
LCD_D7_PORT = dato.b7;
LCD_D6_PORT = dato.b6;
LCD_D5_PORT = dato.b5;
LCD_D4_PORT = dato.b4;
LCDpasajeDatos(); // envia los datos al lcd
__delay_us( 10 );
// transmite el nibble bajo al lcd
LCD_D7_PORT = dato.b3;
LCD_D6_PORT = dato.b2;
LCD_D5_PORT = dato.b1;
LCD_D4_PORT = dato.b0;
LCDpasajeDatos();
__delay_ms(10);
}
//------------------------------------------------------------------------------
void LCDenviaComando( t_byte comando )
{
LCD_RS_PORT = 0; // aviso de envio de comando
__delay_us( 10 );
LCDenviaByte( comando );
}
//------------------------------------------------------------------------------
void LCD_Inicializar(void)
{
DetenerTimer();
inicializarDatosLCD();
t_byte dato[7];
// configura el lcd
dato[0].byte = 3;
dato[1].byte = 2;
dato[2].byte = 0x28;
dato[3].byte = 0xC;
dato[4].byte = 1;
dato[5].byte = 6;
dato[6].byte = _LCD_LIMPIAR_PANTALLA_;
for ( int i=0; i<100; i++ )
__delay_ms( 25 ); // espera a que el voltaje se estabilice
LCD_RS_PORT = 0; // aviso de envio de comando
LCD_E_PORT = 0; // deshabilita la comunicacion
LCD_D7_PORT = 0;
LCD_D6_PORT = 0;
LCD_D5_PORT = 1; // modo seteo
LCD_D4_PORT = 1; // bus de 4 bits
__delay_ms( 15 );
LCD_E_PORT = 1; // habilita la comunicacion
__delay_ms( 15 );
LCD_E_PORT = 0; // deshabilita la comunicacion
__delay_ms( 15 );
//----------------------------------
for ( int i=0; i<7; i++ )
LCDenviaByte( dato[i] );
for ( int i=0; i<20; i++ )
__delay_ms( 20 );
dato[6].byte = _LCD_LIMPIAR_PANTALLA_;
LCDenviaComando( dato[6] );
}
//##############################################################################
//######### M a n e j o d e l L C D c o n e l T i m e r ##########
//##############################################################################
void reiniciarTimerConPeriodo(uint16_t periodo)
{
DetenerTimer();
CambiarTiempoTimer( periodo );
TMR_Libre = false;
IniciarTimer();
}
//******************************************************************************
void agregarMensajeColaBuffer(char nroLinea, const unsigned char *cadena,
unsigned char lngCadena, unsigned long num)
{
// busca el primer espacio libre para agregar el mensaje
for( unsigned char i=0; i<LNG_COLA_BUFFER_LCD; i++ )
{
if( bufMsgLCD[i].lngMensaje == 0 )
{
// si el mensaje pasado es mayor que el permitido, lo descarta
if ( lngCadena <= LNG_COLA_TBYTE_LCD )
{
bufMsgLCD[i].lineaUno = nroLinea;
bufMsgLCD[i].lngMensaje = lngCadena;
bufMsgLCD[i].valorParam = num;
for( unsigned char j=0; j<lngCadena; j++ )
bufMsgLCD[i].mensaje[j] = cadena[j];
}
i = LNG_COLA_BUFFER_LCD;
}
}
}
bufferMsgLCD obtenerMensajeColaBuffer(void)
{
// extrae el fifo mensaje del bufer
bufferMsgLCD bufMsg = bufMsgLCD[0];
// corre los mensajes del bufer hacia adelante
for( unsigned char i=1; i<LNG_COLA_BUFFER_LCD; i++ )
bufMsgLCD[i-1] = bufMsgLCD[i];
// vacia el ultimo mensaje del bufer
for( unsigned char i=0; i<LNG_COLA_TBYTE_LCD; i++ )
bufMsgLCD[LNG_COLA_BUFFER_LCD-1].mensaje[i] = 0;
bufMsgLCD[LNG_COLA_BUFFER_LCD-1].lineaUno = false;
bufMsgLCD[LNG_COLA_BUFFER_LCD-1].lngMensaje = 0;
bufMsgLCD[LNG_COLA_BUFFER_LCD-1].valorParam = 0;
return bufMsg;
}
//------------------------------------------------------------------------------
void agregarCaracterColaBuffer(unsigned char iniIdx, unsigned char byte,
bool comando)
{
static unsigned char idxLinea=0;
if ( iniIdx == false )
{
buffer_t_byte[idxLinea].tByte.byte = byte;
buffer_t_byte[idxLinea].comando = comando;
idxLinea++;
}
else
idxLinea=0;
}
//------------------------------------------------------------------------------
void inicializarDatosLCD(void)
{
for( unsigned char i=0; i<LNG_COLA_BUFFER_LCD; i++ )
{
for( unsigned char j=0; j<16; j++ )
bufMsgLCD[i].mensaje[j] = 0;
bufMsgLCD[i].lineaUno = 0;
bufMsgLCD[i].lngMensaje = 0;
bufMsgLCD[i].valorParam = 0;
}
for( unsigned char i=0; i<16; i++ )
buffer_t_byte[i].tByte.byte = 0;
TMR_Libre = true;
caracterActual.comando = false;
caracterActual.tByte.byte = 0;
}
//------------------------------------------------------------------------------
bool convertirValorCaracterColaBufer( unsigned char valor, bool imprimir )
{
unsigned char caracter;
if ( (valor > 0) || (imprimir == true) )
{
caracter = valor + 48;
agregarCaracterColaBuffer( false, caracter, false );
return true;
}
else
return imprimir;
}
//------------------------------------------------------------------------------
/*
* % imprime números
* & imprime h.hhh.hhh:mm:ss
*/
void escribirLinea( char nroLinea, const unsigned char *cadena,
unsigned char lngCadena, unsigned long num )
{
unsigned char caracter;
if ( nroLinea == 0 )
{
caracter = _LCD_LIMPIAR_PANTALLA_; // limpia la pantalla
agregarCaracterColaBuffer( false, caracter, true );
// mueve el cursor al primer caracter de la primer linea
caracter = _LCD_L1_C_01_;
agregarCaracterColaBuffer( false, caracter, true );
}
else
{
// mueve el cursor al primer caracter de la segunda linea
caracter = _LCD_L2_C_01_;
agregarCaracterColaBuffer( false, caracter, true );
}
// procesa cada caracter de la cadena
for ( int i=0; i<lngCadena; i++ )
{
// si el caracter es comodin de numero o de hora
if ( *cadena == '%' || *cadena == '&' )
{ // crea un array para almacenar el pre procesamiento de los datos
unsigned long nums[3];
if ( *cadena == '%' ) // si es comodin de numeros
{
nums[0] = num; // almacena el numero en el primer char
nums[1] = 0; // del array y deja vacios el resto
nums[2] = 0;
}
else if ( *cadena == '&' ) // si es comodin de hora
{ // extrae las horas
nums[0] = ((num / 60) / 60);
// extrae los minutos
nums[1] = ((num - ((nums[0] * 60) * 60)) / 60);
// extrae los segundos
nums[2] = (num - (((nums[0] * 60) * 60) + (nums[1] * 60)));
}
for ( char i=0; i<3; i++) // procesa los elementos del array
{
unsigned char valimp;
bool imp = false;
// imprime números hasta un máximo de 9 billones
for ( unsigned long j=0, divs=1000000000; j<10; j++, divs = divs/10 )
{
valimp = (nums[i] / divs) % 10;
// imprime el número
imp = convertirValorCaracterColaBufer( valimp, imp );
if ( ((j==0) || (j==3) || (j==6)) && (imp == true) )
{
caracter = 46; // imprime el punto separador
agregarCaracterColaBuffer( false, caracter, false );
}
}
// si es número y su valor es cero, imprime un cero
if ( (*cadena == '%') && (nums[0] == 0) && (i == 2) )
convertirValorCaracterColaBufer( 0, true );
// si es hora
if ( *cadena == '&' )
{ // si el valor es cero
if ( (nums[i] == 0) )
convertirValorCaracterColaBufer( 0, true );
if ( i == 0 )
{
caracter = 'h';
agregarCaracterColaBuffer( false, caracter, false );
caracter = ' ';
agregarCaracterColaBuffer( false, caracter, false );
}
else if ( i == 1 )
{
caracter = 'm';
agregarCaracterColaBuffer( false, caracter, false );
caracter = ' ';
agregarCaracterColaBuffer( false, caracter, false );
}
else if ( i == 2 )
{
caracter = 's';
agregarCaracterColaBuffer( false, caracter, false );
}
}
}
}
else
{
caracter = *cadena;
agregarCaracterColaBuffer( false, caracter, false );
}
*cadena++;
}
agregarCaracterColaBuffer( true, caracter, false );
}
//------------------------------------------------------------------------------
void detener_Timer(void)
{
DetenerTimer();
TMR_Libre = true;
estadoActualTareaLCD = E_TAREALCD_LIBRE;
caracterActual.comando = false;
caracterActual.tByte.byte = 0;
}
//------------------------------------------------------------------------------
void enviarCaracterLCD(void)
{
static unsigned char idx=0;
// si hay un caracter para imprimir
if ( buffer_t_byte[idx].tByte.byte > 0 )
{
caracterActual = buffer_t_byte[idx];
idx++;
if (caracterActual.comando)
LCD_RS_PORT = 0; // aviso de envio de comando
else
LCD_RS_PORT = 1; // aviso de envio de datos
estadoActualTareaLCD = E_TAREALCD_ENV_BYTE_LCD_P1;
reiniciarTimerConPeriodo( LCD_TMR0_VAL_AVISO_ENV_BYTE ); // 5 ms
}
else
{
for( unsigned char i=1; i<LNG_COLA_TBYTE_LCD; i++ )
{
buffer_t_byte[i].comando = false;
buffer_t_byte[i].tByte.byte = 0;
}
idx = 0;
detener_Timer();
}
}
//------------------------------------------------------------------------------
void LCD_EjecutarTareasTimer(void)
{
switch( estadoActualTareaLCD )
{
case E_TAREALCD_ENV_BYTE_LCD_P1: //*************************************
// transmite el nibble alto al lcd
LCD_D7_PORT = caracterActual.tByte.b7;
LCD_D6_PORT = caracterActual.tByte.b6;
LCD_D5_PORT = caracterActual.tByte.b5;
LCD_D4_PORT = caracterActual.tByte.b4;
LCD_E_PORT = 1; // habilita la comunicacion para que procese el nibble
estadoActualTareaLCD = E_TAREALCD_ENV_BYTE_LCD_P2;
reiniciarTimerConPeriodo( LCD_TMR0_VAL_HABIL_COMUNIC_ENV_MSB );
break;
case E_TAREALCD_ENV_BYTE_LCD_P2: //*************************************
LCD_E_PORT = 0; // deshabilita la comunicacion
estadoActualTareaLCD = E_TAREALCD_ENV_BYTE_LCD_P3;
reiniciarTimerConPeriodo( LCD_TMR0_VAL_DESHAB_COMUNIC_PROCES_MSB );
break;
case E_TAREALCD_ENV_BYTE_LCD_P3: //*************************************
// transmite el nibble bajo al lcd
LCD_D7_PORT = caracterActual.tByte.b3;
LCD_D6_PORT = caracterActual.tByte.b2;
LCD_D5_PORT = caracterActual.tByte.b1;
LCD_D4_PORT = caracterActual.tByte.b0;
LCD_E_PORT = 1; // habilita la comunicacion para que procese el nibble
estadoActualTareaLCD = E_TAREALCD_ENV_BYTE_LCD_P4;
reiniciarTimerConPeriodo( LCD_TMR0_VAL_HABIL_COMUNIC_ENV_LSB );
break;
case E_TAREALCD_ENV_BYTE_LCD_P4: //*************************************
LCD_E_PORT = 0; // deshabilita la comunicacion
if ( buffer_t_byte[0].tByte.byte > 0 )
enviarCaracterLCD();
else
detener_Timer();
break;
}
}
//------------------------------------------------------------------------------
void LCD_ProcesarColaMensajes(void)
{
/*
* si en el bufer hay datos para imprimir y el timer esta libre
*/
if( (bufMsgLCD[0].lngMensaje > 0) && (TMR_Libre) )
{
// obtiene el primer mensaje del bufer
LCDmensajeActual = obtenerMensajeColaBuffer();
/*
* formatea el primer mensaje de la cola de mensajes para mostrar
* y queda listo para enviar al display con el protocolo de transmision
*/
escribirLinea(LCDmensajeActual.lineaUno, &(LCDmensajeActual.mensaje),
LCDmensajeActual.lngMensaje, LCDmensajeActual.valorParam);
/*
* comienza la impresion del mensaje
*/
enviarCaracterLCD();
}
}
//------------------------------------------------------------------------------
void LCD_EscribeLinea( char nroLinea, const unsigned char *cadena,
unsigned char lngCadena, unsigned long num )
{
agregarMensajeColaBuffer( nroLinea, cadena, lngCadena, num );
}
//------------------------------------------------------------------------------