Stuckeymax
Joined: 15 Dec 2006 Posts: 2 Location: Atlanta, GA
|
LCD Driver fix for Optrex 4x20 C-51847NFJ-SLW-ADN |
Posted: Tue Apr 28, 2009 8:31 pm |
|
|
Code: | ///////////////////////////////////////////////////////////////////////////
//// LCD.C ////
//// Driver for common LCD modules ////
//// ////
//// lcd_init() Must be called before any other function. ////
//// ////
//// lcd_putc(c) Will display c on the next position of the LCD. ////
//// The following have special meaning: ////
//// \f Clear display ////
//// \n Go to start of second line ////
//// \b Move back one position ////
//// ////
//// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
//// ////
//// lcd_getc(x,y) Returns character at position x,y on LCD ////
//// Note repair 100 uS delay added Line 190 ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
//// ////
//// CCS lcd_init modified by SMc to correct LCD startup problems ////
//// with an Optrex C-51847NFJ-SLW-ADN 4x20 Transreflective Display ////
//// DK P/N 73-1249-ND 100 uS delay inserted Line 193 ////
///////////////////////////////////////////////////////////////////////////
#ifndef __LCD_C__
#define __LCD_C__
#ifndef LCD_TYPE
#define LCD_TYPE 2 // 0=5x7, 1=5x10, 2=2 or 4 lines
#endif
#define LCD_DELAY_CYCLES 3
#define NUM_COLS 20
//#if NUM_COLS==20
//these maps are for 4x20
const int8 lcd_line_off[] = {0x80, 0xc0, 0x94, 0xd4};
//#elif NUM_COLS==16
//these maps are for 4x16
// const int8 lcd_line_off[] = {0x80, 0xc0, 0x90, 0xd0};
//#endif
#define NUM_LINES (sizeof(lcd_line_off)/sizeof(int8))
int8 g_LCDCurrX, g_LCDCurrY;
int8 const LCD_INIT_STRING[4] = {0x20 | (LCD_TYPE << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// use the following block if pins are on one port
typedef struct
{
int1 enable;
int1 rs;
int1 rw;
int1 blank;
int8 dataPort:4;
} LCDPinout;
LCDPinout g_LCDLAT, g_LCDPORT, g_LCDTRIS;
#locate g_LCDLAT=getenv("SFR:LATD")
#locate g_LCDPORT=getenv("SFR:PORTD")
#locate g_LCDTRIS=getenv("SFR:TRISD")
#define lcd_data_set(d) g_LCDLAT.dataPort = d
#define lcd_data_get() (g_LCDPORT.dataPort)
#define lcd_tris_read() g_LCDTRIS.dataPort = 0xF
#define lcd_tris_write() g_LCDTRIS.dataPort = 0
#define lcd_tris_init() g_LCDTRIS = 0x08
#define lcd_output_enable(x) g_LCDLAT.enable = x
#define lcd_output_rs(x) g_LCDLAT.rs = x
#define lcd_output_rw(x) g_LCDLAT.rw = x
// use the following block if pins are all over the place
/*
#define lcd_output_enable(x) output_bit(LCD_ENABLE_PIN, x)
#define lcd_output_rs(x) output_bit(LCD_RS_PIN, x)
#define lcd_output_rw(x) output_bit(LCD_RW_PIN, x)
void lcd_data_set(int8 data)
{
output_bit(LCD_D4_PIN, bit_test(data,0));
output_bit(LCD_D5_PIN, bit_test(data,1));
output_bit(LCD_D6_PIN, bit_test(data,2));
output_bit(LCD_D7_PIN, bit_test(data,3));
}
int8 lcd_data_get(void)
{
int8 ret=0;
if (input(LCD_D4_PIN)) bit_set(ret,0);
if (input(LCD_D5_PIN)) bit_set(ret,1);
if (input(LCD_D6_PIN)) bit_set(ret,2);
if (input(LCD_D7_PIN)) bit_set(ret,3);
return(ret);
}
void lcd_tris_read(void)
{
output_float(LCD_D4_PIN);
output_float(LCD_D5_PIN);
output_float(LCD_D6_PIN);
output_float(LCD_D7_PIN);
}
void lcd_tris_write(void)
{
output_drive(LCD_D4_PIN);
output_drive(LCD_D5_PIN);
output_drive(LCD_D6_PIN);
output_drive(LCD_D7_PIN);
}
void lcd_tris_init(void)
{
output_drive(LCD_ENABLE_PIN);
output_drive(LCD_RS_PIN);
output_drive(LCD_RW_PIN);
}
*/
int8 lcd_read_byte(void)
{
int8 low,high;
lcd_tris_read();
lcd_output_rw(1);
delay_cycles(LCD_DELAY_CYCLES);
lcd_output_enable(1);
delay_cycles(LCD_DELAY_CYCLES);
high = lcd_data_get();
lcd_output_enable(0);
delay_cycles(LCD_DELAY_CYCLES);
lcd_output_enable(1);
delay_us(1);
low = lcd_data_get();
lcd_output_enable(0);
lcd_tris_write();
return( (high<<4) | low);
}
void lcd_send_nibble( int8 n )
{
lcd_data_set(n);
delay_cycles(LCD_DELAY_CYCLES);
lcd_output_enable(1);
delay_us(2);
lcd_output_enable(0);
}
void lcd_send_byte( int8 address, int8 n ) {
lcd_output_rs(0);
while ( bit_test(lcd_read_byte(),7) ) ;
lcd_output_rs(address);
delay_cycles(LCD_DELAY_CYCLES);
lcd_output_rw(0);
delay_cycles(LCD_DELAY_CYCLES);
lcd_output_enable(0);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
delay_us(75);
}
void lcd_init(void)
{
int8 i;
lcd_output_rs(0);
lcd_output_rw(0);
lcd_output_enable(0);
lcd_tris_init();
lcd_tris_write();
delay_ms(5);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
delay_us(100); //Provides a short delay between nibble(2) and init string
//to correct LCD startup/cursor positioning problems
for(i=0;i<=3;++i) {
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
}
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
// set new cursor position
g_LCDCurrX = x % NUM_COLS;
g_LCDCurrY = y % NUM_LINES;
// wrap the y position by number of lines
address = lcd_line_off[g_LCDCurrY];
address += g_LCDCurrX;
lcd_send_byte(0, address);
}
void lcd_gotoxy(int8 xy)
{
int8 address;
g_LCDCurrX = xy % NUM_COLS;
g_LCDCurrY = xy / NUM_COLS;
// wrap the y position by number of lines
address = lcd_line_off[g_LCDCurrY];
address += g_LCDCurrX;
lcd_send_byte(0, address);
}
void lcd_putc( char c)
{
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
lcd_gotoxy(0,0);
break;
case '\n' : lcd_gotoxy(g_LCDCurrX, g_LCDCurrY+1); break;
case '\r' : lcd_gotoxy(0, g_LCDCurrY); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
void lcd_cursor_off(void) {
lcd_send_byte(0,0x0C); //turn LCD cursor OFF
}
void lcd_cursor_on(void) {
lcd_send_byte(0,0x0F); //turn LCD cursor ON
}
#endif |
|
|