mirror of
https://github.com/netfun2000/lcd4linux.git
synced 2026-02-27 09:44:34 +08:00
[lcd4linux @ 2003-08-19 05:23:55 by reinelt]
HD44780 dual-controller patch from Jesse Brook Kovach git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@224 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $Id: HD44780.c,v 1.33 2003/08/19 04:28:41 reinelt Exp $
|
||||
/* $Id: HD44780.c,v 1.34 2003/08/19 05:23:55 reinelt Exp $
|
||||
*
|
||||
* driver for display modules based on the HD44780 chip
|
||||
*
|
||||
@@ -7,6 +7,9 @@
|
||||
* Modification for 4-Bit mode
|
||||
* 2003 Martin Hejl (martin@hejl.de)
|
||||
*
|
||||
* Modification for 2nd controller support
|
||||
* 2003 Jesse Brook Kovach <jkovach@wam.umd.edu>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,6 +27,9 @@
|
||||
*
|
||||
*
|
||||
* $Log: HD44780.c,v $
|
||||
* Revision 1.34 2003/08/19 05:23:55 reinelt
|
||||
* HD44780 dual-controller patch from Jesse Brook Kovach
|
||||
*
|
||||
* Revision 1.33 2003/08/19 04:28:41 reinelt
|
||||
* more Icon stuff, minor glitches fixed
|
||||
*
|
||||
@@ -203,6 +209,8 @@
|
||||
static LCD Lcd;
|
||||
static int Bits=0;
|
||||
static int GPO=0;
|
||||
static int Controllers = 0;
|
||||
static int Controller = 0;
|
||||
|
||||
static char *FrameBuffer1=NULL;
|
||||
static char *FrameBuffer2=NULL;
|
||||
@@ -210,12 +218,21 @@ static char *FrameBuffer2=NULL;
|
||||
static unsigned char SIGNAL_RW;
|
||||
static unsigned char SIGNAL_RS;
|
||||
static unsigned char SIGNAL_ENABLE;
|
||||
static unsigned char SIGNAL_ENABLE2;
|
||||
static unsigned char SIGNAL_GPO;
|
||||
|
||||
|
||||
static void HD_nibble(unsigned char nibble)
|
||||
static void HD_nibble(unsigned char controller, unsigned char nibble)
|
||||
{
|
||||
unsigned char enable;
|
||||
|
||||
// enable signal: 'controller' is a bitmask
|
||||
// bit 0 .. send to controller #0
|
||||
// bit 1 .. send to controller #1
|
||||
// so we can send a byte to both controllers at the same time!
|
||||
enable=0;
|
||||
if (controller&0x01) enable|=SIGNAL_ENABLE;
|
||||
if (controller&0x02) enable|=SIGNAL_ENABLE2;
|
||||
|
||||
// clear ENABLE
|
||||
// put data on DB1..DB4
|
||||
// nibble already contains RS bit!
|
||||
@@ -225,7 +242,7 @@ static void HD_nibble(unsigned char nibble)
|
||||
ndelay(T_AS);
|
||||
|
||||
// rise ENABLE
|
||||
parport_data(nibble | SIGNAL_ENABLE);
|
||||
parport_data(nibble | enable);
|
||||
|
||||
// Enable pulse width
|
||||
ndelay(T_PW);
|
||||
@@ -235,24 +252,33 @@ static void HD_nibble(unsigned char nibble)
|
||||
}
|
||||
|
||||
|
||||
static void HD_byte (unsigned char data, unsigned char RS)
|
||||
static void HD_byte (unsigned char controller, unsigned char data, unsigned char RS)
|
||||
{
|
||||
// send high nibble of the data
|
||||
HD_nibble (((data>>4)&0x0f)|RS);
|
||||
HD_nibble (controller, ((data>>4)&0x0f)|RS);
|
||||
|
||||
// Make sure we honour T_CYCLE
|
||||
ndelay(T_CYCLE-T_AS-T_PW);
|
||||
|
||||
// send low nibble of the data
|
||||
HD_nibble((data&0x0f)|RS);
|
||||
HD_nibble(controller, (data&0x0f)|RS);
|
||||
}
|
||||
|
||||
|
||||
static void HD_command (unsigned char cmd, int delay)
|
||||
static void HD_command (unsigned char controller, unsigned char cmd, int delay)
|
||||
{
|
||||
|
||||
unsigned char enable;
|
||||
|
||||
if (Bits==8) {
|
||||
|
||||
// enable signal: 'controller' is a bitmask
|
||||
// bit 0 .. send to controller #0
|
||||
// bit 1 .. send to controller #1
|
||||
// so we can send a byte to both controllers at the same time!
|
||||
enable=0;
|
||||
if (controller&0x01) enable|=SIGNAL_ENABLE;
|
||||
if (controller&0x02) enable|=SIGNAL_ENABLE2;
|
||||
|
||||
// put data on DB1..DB8
|
||||
parport_data (cmd);
|
||||
|
||||
@@ -263,11 +289,11 @@ static void HD_command (unsigned char cmd, int delay)
|
||||
ndelay(T_AS);
|
||||
|
||||
// send command
|
||||
parport_toggle (SIGNAL_ENABLE, 1, T_PW);
|
||||
|
||||
parport_toggle (enable, 1, T_PW);
|
||||
|
||||
} else {
|
||||
|
||||
HD_byte (cmd, 0);
|
||||
HD_byte (controller, cmd, 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -277,11 +303,20 @@ static void HD_command (unsigned char cmd, int delay)
|
||||
}
|
||||
|
||||
|
||||
static void HD_write (char *string, int len, int delay)
|
||||
static void HD_write (unsigned char controller, char *string, int len, int delay)
|
||||
{
|
||||
unsigned char enable;
|
||||
|
||||
if (Bits==8) {
|
||||
|
||||
// enable signal: 'controller' is a bitmask
|
||||
// bit 0 .. send to controller #0
|
||||
// bit 1 .. send to controller #1
|
||||
// so we can send a byte to both controllers at the same time!
|
||||
enable=0;
|
||||
if (controller&0x01) enable|=SIGNAL_ENABLE;
|
||||
if (controller&0x02) enable|=SIGNAL_ENABLE2;
|
||||
|
||||
// clear RW, set RS
|
||||
parport_control (SIGNAL_RW | SIGNAL_RS, SIGNAL_RS);
|
||||
|
||||
@@ -294,27 +329,26 @@ static void HD_write (char *string, int len, int delay)
|
||||
parport_data (*(string++));
|
||||
|
||||
// send command
|
||||
parport_toggle (SIGNAL_ENABLE, 1, T_PW);
|
||||
parport_toggle (enable, 1, T_PW);
|
||||
|
||||
// wait for command completion
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
|
||||
} else { // 4 bit mode
|
||||
|
||||
|
||||
while (len--) {
|
||||
|
||||
// send data with RS enabled
|
||||
HD_byte (*(string++), SIGNAL_RS);
|
||||
|
||||
HD_byte (controller, *(string++), SIGNAL_RS);
|
||||
|
||||
// wait for command completion
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void HD_setGPO (int bits)
|
||||
{
|
||||
if (Lcd.gpos>0) {
|
||||
@@ -334,8 +368,9 @@ static void HD_setGPO (int bits)
|
||||
|
||||
static void HD_define_char (int ascii, char *buffer)
|
||||
{
|
||||
HD_command (0x40|8*ascii, 40);
|
||||
HD_write (buffer, 8, 120); // 120 usec delay for CG RAM write
|
||||
// define chars on *both* controllers!
|
||||
HD_command (0x03, 0x40|8*ascii, 40);
|
||||
HD_write (0x03, buffer, 8, 120); // 120 usec delay for CG RAM write
|
||||
}
|
||||
|
||||
|
||||
@@ -348,10 +383,10 @@ int HD_clear (int full)
|
||||
|
||||
if (full) {
|
||||
memset (FrameBuffer2, ' ', Lcd.rows*Lcd.cols*sizeof(char));
|
||||
HD_command (0x01, 1640); // clear display
|
||||
HD_setGPO (GPO); // All GPO's off
|
||||
HD_command (0x03, 0x01, 1640); // clear *both* displays
|
||||
HD_setGPO (GPO); // all GPO's off
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -383,6 +418,17 @@ int HD_init (LCD *Self)
|
||||
}
|
||||
}
|
||||
|
||||
s=cfg_get("Controllers", "1");
|
||||
Controllers=strtol(s, &e, 0);
|
||||
if (*e!='\0' || Controllers<1 || Controllers>2) {
|
||||
error ("HD44780: bad Controllers '%s' in %s, should be '1' or '2'", s, cfg_file());
|
||||
return -1;
|
||||
}
|
||||
info ("wiring: using display with %d controllers", Controllers);
|
||||
|
||||
// current controller
|
||||
Controller=1;
|
||||
|
||||
Self->rows=rows;
|
||||
Self->cols=cols;
|
||||
Self->gpos=gpos;
|
||||
@@ -405,15 +451,17 @@ int HD_init (LCD *Self)
|
||||
info ("wiring: using %d bit mode", Bits);
|
||||
|
||||
if (Bits==8) {
|
||||
if ((SIGNAL_RS = parport_wire_ctrl ("RS", "AUTOFD"))==0xff) return -1;
|
||||
if ((SIGNAL_RW = parport_wire_ctrl ("RW", "GND") )==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE = parport_wire_ctrl ("ENABLE", "STROBE"))==0xff) return -1;
|
||||
if ((SIGNAL_GPO = parport_wire_ctrl ("GPO", "INIT") )==0xff) return -1;
|
||||
if ((SIGNAL_RS = parport_wire_ctrl ("RS", "AUTOFD"))==0xff) return -1;
|
||||
if ((SIGNAL_RW = parport_wire_ctrl ("RW", "GND") )==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE = parport_wire_ctrl ("ENABLE", "STROBE"))==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE2 = parport_wire_ctrl ("ENABLE2", "SELECT"))==0xff) return -1;
|
||||
if ((SIGNAL_GPO = parport_wire_ctrl ("GPO", "INIT") )==0xff) return -1;
|
||||
} else {
|
||||
if ((SIGNAL_RS = parport_wire_data ("RS", "DB4"))==0xff) return -1;
|
||||
if ((SIGNAL_RW = parport_wire_data ("RW", "DB5"))==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE = parport_wire_data ("ENABLE", "DB6"))==0xff) return -1;
|
||||
if ((SIGNAL_GPO = parport_wire_data ("GPO", "DB7"))==0xff) return -1;
|
||||
if ((SIGNAL_RS = parport_wire_data ("RS", "DB4"))==0xff) return -1;
|
||||
if ((SIGNAL_RW = parport_wire_data ("RW", "DB5"))==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE = parport_wire_data ("ENABLE", "DB6"))==0xff) return -1;
|
||||
if ((SIGNAL_ENABLE2 = parport_wire_data ("ENABLE2", "DB7"))==0xff) return -1;
|
||||
if ((SIGNAL_GPO = parport_wire_data ("GPO", "GND"))==0xff) return -1;
|
||||
}
|
||||
|
||||
if (parport_open() != 0) {
|
||||
@@ -431,24 +479,23 @@ int HD_init (LCD *Self)
|
||||
// set direction: write
|
||||
parport_direction (0);
|
||||
|
||||
// initialize display
|
||||
// initialize *both* displays
|
||||
if (Bits==8) {
|
||||
HD_command (0x30, 4100); // 8 Bit mode, wait 4.1 ms
|
||||
HD_command (0x30, 100); // 8 Bit mode, wait 100 us
|
||||
HD_command (0x30, 4100); // 8 Bit mode, wait 4.1 ms
|
||||
HD_command (0x38, 40); // 8 Bit mode, 1/16 duty cycle, 5x8 font
|
||||
HD_command (0x03, 0x30, 4100); // 8 Bit mode, wait 4.1 ms
|
||||
HD_command (0x03, 0x30, 100); // 8 Bit mode, wait 100 us
|
||||
HD_command (0x03, 0x30, 4100); // 8 Bit mode, wait 4.1 ms
|
||||
HD_command (0x03, 0x38, 40); // 8 Bit mode, 1/16 duty cycle, 5x8 font
|
||||
} else {
|
||||
HD_nibble(0x03); udelay(4100); // 4 Bit mode, wait 4.1 ms
|
||||
HD_nibble(0x03); udelay(100); // 4 Bit mode, wait 100 us
|
||||
HD_nibble(0x03); udelay(4100); // 4 Bit mode, wait 4.1 ms
|
||||
HD_nibble(0x02); udelay(100); // 4 Bit mode, wait 100 us
|
||||
HD_command (0x28, 40); // 4 Bit mode, 1/16 duty cycle, 5x8 font
|
||||
HD_nibble(0x03, 0x03); udelay(4100); // 4 Bit mode, wait 4.1 ms
|
||||
HD_nibble(0x03, 0x03); udelay(100); // 4 Bit mode, wait 100 us
|
||||
HD_nibble(0x03, 0x03); udelay(4100); // 4 Bit mode, wait 4.1 ms
|
||||
HD_nibble(0x03, 0x02); udelay(100); // 4 Bit mode, wait 100 us
|
||||
HD_command (0x03, 0x28, 40); // 4 Bit mode, 1/16 duty cycle, 5x8 font
|
||||
}
|
||||
|
||||
HD_command (0x08, 40); // Display off, cursor off, blink off
|
||||
HD_command (0x0c, 1640); // Display on, cursor off, blink off, wait 1.64 ms
|
||||
HD_command (0x06, 40); // curser moves to right, no shift
|
||||
|
||||
HD_command (0x03, 0x08, 40); // Display off, cursor off, blink off
|
||||
HD_command (0x03, 0x0c, 1640); // Display on, cursor off, blink off, wait 1.64 ms
|
||||
HD_command (0x03, 0x06, 40); // curser moves to right, no shift
|
||||
|
||||
bar_init(rows, cols, XRES, YRES, CHARS);
|
||||
bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank
|
||||
@@ -464,8 +511,15 @@ void HD_goto (int row, int col)
|
||||
{
|
||||
int pos;
|
||||
|
||||
if (Controllers>1 && row>=2) {
|
||||
row -= 2;
|
||||
Controller = 2;
|
||||
} else {
|
||||
Controller = 1;
|
||||
}
|
||||
|
||||
pos=(row%2)*64+(row/2)*20+col;
|
||||
HD_command (0x80|pos, 40);
|
||||
HD_command (Controller, (0x80|pos), 40);
|
||||
}
|
||||
|
||||
|
||||
@@ -528,7 +582,7 @@ int HD_flush (void)
|
||||
equal=0;
|
||||
}
|
||||
}
|
||||
HD_write (FrameBuffer1+row*Lcd.cols+pos1, pos2-pos1+1, 40); // 40 usec delay for write
|
||||
HD_write (Controller, FrameBuffer1+row*Lcd.cols+pos1, pos2-pos1+1, 50); // 50 usec delay for write
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: parport.c,v 1.4 2003/08/16 07:31:35 reinelt Exp $
|
||||
/* $Id: parport.c,v 1.5 2003/08/19 05:23:55 reinelt Exp $
|
||||
*
|
||||
* generic parallel port handling
|
||||
*
|
||||
@@ -20,6 +20,9 @@
|
||||
*
|
||||
*
|
||||
* $Log: parport.c,v $
|
||||
* Revision 1.5 2003/08/19 05:23:55 reinelt
|
||||
* HD44780 dual-controller patch from Jesse Brook Kovach
|
||||
*
|
||||
* Revision 1.4 2003/08/16 07:31:35 reinelt
|
||||
* double buffering in all drivers
|
||||
*
|
||||
@@ -340,7 +343,6 @@ void parport_control (unsigned char mask, unsigned char value)
|
||||
|
||||
// Strobe, Select and AutoFeed are inverted!
|
||||
value = mask & (value ^ (PARPORT_CONTROL_STROBE|PARPORT_CONTROL_SELECT|PARPORT_CONTROL_AUTOFD));
|
||||
// value ^= PARPORT_CONTROL_STROBE|PARPORT_CONTROL_SELECT|PARPORT_CONTROL_AUTOFD;
|
||||
|
||||
#ifdef WITH_PPDEV
|
||||
if (PPdev) {
|
||||
@@ -358,45 +360,50 @@ void parport_control (unsigned char mask, unsigned char value)
|
||||
}
|
||||
|
||||
|
||||
void parport_toggle (unsigned char bit, int level, int delay)
|
||||
void parport_toggle (unsigned char bits, int level, int delay)
|
||||
{
|
||||
unsigned char value1, value2;
|
||||
|
||||
// any signal affected?
|
||||
// Note: this may happen in case a signal is hardwired to GND
|
||||
if (bit==0) return;
|
||||
if (bits==0) return;
|
||||
|
||||
// prepare value
|
||||
value1=level?bits:0;
|
||||
value2=level?0:bits;
|
||||
|
||||
// Strobe, Select and AutoFeed are inverted!
|
||||
if (bit & (PARPORT_CONTROL_STROBE|PARPORT_CONTROL_SELECT|PARPORT_CONTROL_AUTOFD)) {
|
||||
level=!level;
|
||||
}
|
||||
value1 = bits & (value1 ^ (PARPORT_CONTROL_STROBE|PARPORT_CONTROL_SELECT|PARPORT_CONTROL_AUTOFD));
|
||||
value2 = bits & (value1 ^ (PARPORT_CONTROL_STROBE|PARPORT_CONTROL_SELECT|PARPORT_CONTROL_AUTOFD));
|
||||
|
||||
|
||||
#ifdef WITH_PPDEV
|
||||
if (PPdev) {
|
||||
struct ppdev_frob_struct frob;
|
||||
frob.mask=bit;
|
||||
frob.mask=bits;
|
||||
|
||||
// rise
|
||||
frob.val=level?bit:0;
|
||||
frob.val=value1;
|
||||
ioctl (PPfd, PPFCONTROL, &frob);
|
||||
|
||||
// pulse width
|
||||
ndelay(delay);
|
||||
|
||||
// lower
|
||||
frob.val=level?0:bit;
|
||||
frob.val=value2;
|
||||
ioctl (PPfd, PPFCONTROL, &frob);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// rise
|
||||
ctr = (ctr & ~bit) ^ (level?bit:0);
|
||||
ctr = (ctr & ~bits) ^ value1;
|
||||
outb (ctr, Port+2);
|
||||
|
||||
// pulse width
|
||||
ndelay(delay);
|
||||
|
||||
// lower
|
||||
ctr = (ctr & ~bit) ^ (level?0:bit);
|
||||
ctr = (ctr & ~bits) ^ value2;
|
||||
outb (ctr, Port+2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user