hd44780

HD44780

This driver supports all display modules based on the Hitachi HD44780 chip. These displays are made by different manufactures, and come in various sizes. The HD44780 is probably the most common display driver.

The displays are connected to the parallel board (see Wiring below), and are quite timing-critical. There's no way to delay a usermode program under Linux for e.g. 40 usec, so we have to do busy-waiting. This has been done in a delay loop, which had to be calibrated. Since 0.9.8 there are two new delay loops, one based on the processor's TSC (Time Stamp Counter), one based on gettimeofday(). LCD4Linux decides automatically which one to use (it prefers the TSC method, but falls back to gettimeofday() if neither the TSC flag nor the MHz value is set in /proc/cpuinfo). Calibration is no longer necessary!

The driver knows of two ways of controlling the parallel port: The (old, ugly and unportable) raw programming of ports, and the new, cool, great ppdev() style. You decide which one to use by specifying either a hexadecimal value or a device file with the 'Port' entry in the config file.

Note that the old port programming only works with standard ports (0x3f8, 2f8,…), but not with PCI parallel port cards. Also, some secured linux systems (LEAF kernels with the grsecurity patches being one) do not allow a userspace program to do raw I/O (not even if running as root), so you have to use ppdev there anyway.

ppdev requires kernel 2.4 or newer, and the ppdev kernel module loaded. The configure script detects if you have the required include files, and deactivates ppdev if they are not there. You should use ppdev whenever possible! Raw port access may be dropped someday.

Note that you have to use parport devices (usually /dev/parports/* or /dev/parport* with major number 99), the printer devices (/dev/printers/* or /dev/lp* with major number 6) do NOT work! If you are using devfs or udev, these devices may become visible as soon as you load the ppdev kernel module.

The driver fully supports the text, bar and icon widgets.


Display <name> {
    Driver 'HD44780'
    Model <string>
    Bus <string>
    Port <string>
    Device <string>
    Controllers <1|2|3|4>
    Bits <4|8>
    UseBusy <0|1>
    GPOs <number>
    Backlight <0|1>
    Brightness <number> 
    Size <string>
    Size1 <string>
    Size2 <string>
    Size3 <string>
    Size4 <string>
    asc255bug <0|1>
    Icons <number>
    Wire {
        RW        <string>
        RS        <string>
        ENABLE    <string>
        ENABLE2   <string>
        ENABLE3   <string>
        ENABLE4   <string>
        BACKLIGHT <string>
        GPO       <string>
        POWER     <string>
    }
    Timing {
        fuzz      <percentage>
        CY        <number of nanoseconds>
        PW        <number of nanoseconds>
        AS        <number of nanoseconds>
        AH        <number of nanoseconds>
        INIT1     <number of microseconds>
        INIT2     <number of microseconds>
        EXEC      <number of microseconds>
        WRCG      <number of microseconds>
        CLEAR     <number of microseconds>
        HOME      <number of microseconds>
        ONOFF     <number of microseconds>
        GPO_ST    <number of nanoseconds>
        GPO_PW    <number of nanoseconds>
        POWER     <number of milliseconds>
    }
}

Driver'HD44780'
Modelsee below
Bus'parport' (default) or 'i2c'
Porteither the hexadecimal address of the parallel port (“0x378”) or a ppdev device (“/dev/parports/0”)
DeviceThe I2C device
Controllersset to 2 if you have a dual-controller display, or number of real displays; default: 1
Bits4 (4-bit-mode) or 8 (8-bit-mode, default)
!UseBusy0 (don't use Busy-Flag checking, default) or 1 (use Busy-Flag checking)
GPOsnumber of general purpose outputs, use 0 (zero, which is the default) to deactivate this feature
Backlightbacklight on/off
Brightnessbacklight level (Noritake displays only)
Size<columns>x<rows> e.g. “16×2”; for multiple displays the overall size
Size2, Size3, Size4<columns>x<rows> for second, third and forth display
asc255bugset to 1 if you don't get solid blocks in bars, but an inverted P (the Portishead syndrome :-) or a { (curly brace) on a KS0073
IconsNumber of user-defined chars reserved for Icons (default: 0)
Wire.*see below
Timing.*see below

The driver supports different models of the HD44780, which can be selected with the 'Model' parameter:

generic standard HD44780 display (default)
Noritakesame as 'generic', but with software-controlled backlight
Soekrisvery special interface which supports busy-flag checking in 4-bit-mode
HD66712a controller similar to the HD44780, but with slightly different RAM-Layout (use this model for a KS0073, too!)
LCM-162a small interface between the parallel port and a HD44780 display which can be found in the Nexcom Blade Servers. It is hard-wired (no 'Wire'-section necessary, uses 8-bit-mode with busy-flag checking, and has a little keypad with four keys.

Display HD44780-generic {
    Driver 'HD44780'
    Model 'generic'
    Port '/dev/parports/0'
    Size '20x4'
    Wire {
        RW        'GND'
        RS        'AUTOFD'
        ENABLE    'STROBE'
        ENABLE2   'GND'
        BACKLIGHT 'GND'
        GPO       'GND'
        POWER     'GND'
    }
}
Display HD44780-winamp {
    Driver 'HD44780'
    Model 'generic'
    UseBusy 1
    Port '/dev/parports/0'
    Size '20x4'
    Wire {
        RW        'AUTOFD'
        RS        'INIT'
        ENABLE    'STROBE'
        ENABLE2   'GND'
        BACKLIGHT 'GND'
        GPO       'GND'
        POWER     'GND'
    }
}
Display HD44780-kernelconcepts {
    Driver 'HD44780'
    Model 'HD66712'
    UseBusy 1
    Port '/dev/parports/0'
    Size '20x4'
    Wire {
        RW        'AUTOFD'
        RS        'INIT'
        ENABLE    'STROBE'
        ENABLE2   'GND'
        BACKLIGHT 'GND'
        GPO       'GND'
        POWER     'GND'
    }
}
Display HD44780-dual {
    Driver 'HD44780'
    Model 'generic'
    Port '/dev/parports/0'
    Controllers 2
    Size '20x6'
    Size1 '16x4'
    Size2 '20x2'
    Wire {
        RW        'GND'
        RS        'AUTOFD'
        ENABLE    'STROBE'
        ENABLE2   'SLCTIN'
        BACKLIGHT 'GND'
        GPO       'GND'
        POWER     'GND'
    }
}

The driver provides the following functions:

LCD::Backlight(n)turns the backlight on (1) or off (0)
LCD::Brightness(n)sets the backlight level to n (0..3) (Noritake displays only!)

There are two basic wiring modes for HD44780-Displays: a 4 bit and a 8 bit mode. Since 0.9.11 lcd4linux supports both modes!

There are large (40×4) displays which internally consist of two HD44780 chips, with two seperate “Enable” lines. Since 0.9.11 lcd4linux supports these displays, too!

You can connect up to four displays on one bus (example schematic below), connecting all “RS” lines and seperate all “Enable” lines to one parallel port. The size of the displays is given with “Size1”, “Size2”, “Size3” and “Size4” and are automatically evaluated to form “Size”, so you can omit it, too. It is assumed that all displays (controllers) are one below the other to form “one big display”, with <rows> being the row-size of the biggest display. Edit the layout to correspond with the “Size” parameter and you can control all displays at once.

Normally a HD44780-based display has 14 or 16 pins, where pins 15 and 16 are used for backlight. Power (+5V) must be supplied via pins 1(GND) and 2(+5V), be careful not to change polarity, you will destroy your display! Pin 3 is used to control the contrast, you can either hardwire it to GND (pin 1) or place a potentiometer (10k-20k) between pins 1 and 2, and connect pin 3 to the slider.

There are a lot of different wirings out there (lcdproc, WinAmp, …), so I decided to implement a parallel port abstraction layer which makes the wiring completely configurable! (this is what the Wire.xy entries in the configuration are for). This feature is available in V0.9.9, previous versions still use the default wiring. If you don't use the this default wiring scheme, you have to change these lines accordingly.

The wiring configuration uses abstract signal names (e.g. STROBE) instead of pin numbers on the parallel port. So here's a translation table:

PinNameI/O
1STROBEOut
2DB0I/O
3DB1I/O
4DB2I/O
5DB3I/O
6DB4I/O
7DB5I/O
8DB6I/O
9DB7I/O
10ACKIn
11BUSYIn
12PAPEROUTIn
13SELECTIn
14AUTOFDOut
15ERRORIn
16INITOut
17SLCTINOut
18-25GNDn/a

A HD44780-Display usually has 16 Pins (if you find only 14, there's no backlight, so pin 15 and 16 are missing)

PinNameComment
1GNDground
2VCCsupply voltage +5V
3LCD_DRIVEcontrast voltage (0 .. +5V)
4RSRegister Select (low=instruction, high=data)
5R/WRead / not Write (high=read, low=write)
6ENABLEstarts data read/write
7DB0Data Bit 0
8DB1Data Bit 1
9DB2Data Bit 2
10DB3Data Bit 3
11DB4Data Bit 4
12DB5Data Bit 5
13DB6Data Bit 6
14DB7Data Bit 7
15BACKLIGHTbacklight supply voltage
16BL GNDbacklight ground

Warning: I've seen displays with the pins in the following order: 15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 !!!

Now for the wiring details in 8-bit mode:

  • The data lines (DB0..DB7 on the display, DB0..DB7 on the parallel port) are connected directly.
  • The “RS” signal has to be connected to one of the control signals (STROBE, SLCTIN, AUTOFD or INIT). LCD4Linux's default is AUTOFD.
  • The “RW” signal from the display may be harwired to GND, we do not read anything from the display. If you want to use busy-flag checking, you have to connect it to a control signal, which must be specified with the Wire.RW line. LCD4Linux's default is GND
  • The “Enable” signal has to be connected to one of the control signals. LCD4Linux's default is STROBE.
  • The second, third and fourth “Enable” (for displays with two controllers or multiple displays) signal has to be connected to one of the control signals. LCD4Linux's default is GND (i.e. not connected).

and with 4-bit mode:

  • The data lines DB4..DB7 on the display are connected to DB0..DB3 on the parallel port. The remaining DB0..DB3 on the display are not used.
  • The “RS” signal has to be connected to one of the other data lines (DB4..7). LCD4Linux's default is DB4.
  • The “RW” signal from the display may be harwired to GND, we do not read anything from the display. If you want to use busy-flag checking, you have to connect it to a control signal, which must be specified with the Wire.RW line. LCD4Linux's default is GND.
  • The “Enable” signal has to be connected to one of the other data lines. LCD4Linux's default is DB6.
  • The second, third and fourth “Enable” (for displays with two controllers or multiple displays) signal has to be connected to one of the control signals. LCD4Linux's default is GND (i.e. not connected).

If you use the WinAmp-style wiring, connect the following pins:

Display Pin 4 (RS) ⇒ Parallelport Pin 16 (Init) \

Display Pin 5 (R/W) ⇒ Parallelport Pin 14 (AutoFD) \

Display Pin 6 (Enable) ⇒ Parallelport Pin 1 (Strobe) \

The wiring entries in lcd4linux.conf sould read:

 Wire {
    RW        'AUTOFD'
    RS        'INIT'
    ENABLE    'STROBE'
    ENABLE2   'GND'
    BACKLIGHT 'GND'
    GPO       'GND'
    POWER     'GND'
 }

Other wiring examples: lcd4linux default 8-bit wiring:

 Wire {
    RW        'GND'
    RS        'AUTOFD'
    ENABLE    'STROBE'
    ENABLE2   'SLCTIN'
    BACKLIGHT 'GND'
    GPO       'INIT'
    POWER     'GND'
 }

lcd4linux default 4-bit wiring:

 Wire {
    RS        'DB4'
    RW        'DB5'
    ENABLE    'DB6'
    ENABLE2   'DB7'
    BACKLIGHT 'GND'
    GPO       'GND'
    POWER     'GND'
 }

As I said above, HD44780 are quite timing-critial. First, there is the low-level timing on the parallel port, second is the execution time needed for various commands (especially if you're not using busy-flag checking). In the past, we tried to use worst-case values, as the timings differ from datasheet to datasheet. But this did not always work, some displays really need smaller values…

So I decided to make the timings configurable. That's what the Timing section in the lcd4linux.conf is for. Note that under normal circumstances you won't need such a section, lcd4linux uses default values which should work with most displays.

You should consult the datasheet of your display before messing around with these values!

To make it easier to play with the timing values, I invented a fuzz factor, which modifies all other timing values. This factor is interpreted as a percentage, with a default of 100% (meaning no modification). If you specify a fuzz factor of 150, this leads to all timings being multiplied by 1.5 (so the default 1000 ns Enable Cycle Time will be 1500 ns).

NameDescriptionDefaultUnit
CYEnably cycle time1000ns
PWEnably pulse width450ns
ASAddress setup time140ns
AHAddress hold time20ns
NameDescriptionDefaultUnit
INIT1First init sequence4100us
INIT2Second init sequence100us
EXECnormal execution time80us
WRCGCG RAM Write120us
CLEARClear Display2250us
HOMECursor Home2250us
ONOFFDisplay On/Off Control2250us

If you're using a 74HCT573 or similar as a latch to control one or more GPO's, you may specify the timing, too:

NameDescriptionDefaultUnit
GPO_ST74HCT573 set-up time20ns
GPO_PW74HCT573 enable pulse width230ns

If you're fetching supply voltage from an unused pin from the parallel port (see below), you can control how long LCD4linux delays after rising this power pin:

NameDescriptionDefaultUnit
POWERdelay between rising the power supply signal and further initialisation500ms
 Timing {
    CY    1000  
    PW     450  
    AS     140  
    AH      20  
    INIT1 4100
    INIT2  100
    EXEC    80
    WRCG   120
    CLEAR 2250
    HOME  2250
    ONOFF 2250
    GPO_ST  20
    GPO_PW 230
    POWER  500
 }

If your Display (or your interface) provides a way to control the backlight by software, LCD4Linux supports this, too. You need an additional control signal from the parallel port. You have to specify this signal with the Wire.Backlight entry in the config file (the default is GND, i.e. not connected). The initial backlight state my be specified with the Backlight parameter in the Display section.

If you have a Noritake Display, backlight brightness can be controlled, too. The initial backlight level my be specified with the Brightness parameter in the Display section.


You can connect up to 8 digital output lines to the parallel port with a simple additional circuit (e.g. to drive a LED). These lines can be controlled by lcd4linux, and need an additional control signal from the parallel port. You have to specify this signal with the Wire.GPO entry in the config file (the default is GND, i.e. not connected).

See the GPO widget section for how to use these GPO's.


It should be possible to get the power supply for your display from an unused signal from the parallel port. Please not that we're talking about display power supply, not the backlight!

If you want to try so, you have to specify this signal with the Wire.Power entry in the config file (the default is GND, i.e. no power from parport). To allow the display to settle down, there's a delay between rising this power-supply signal and the HD44780 initialisation sequence. You can modify this default delay of 500 msec with the Timing.POWER entry in the config file.

Note that this will probably work with a 5V parallel port only! (and most modern PC's deliver 3.3V)


I'm using a 'general purpose' interface board to quickly test various displays. It consists of a stabilized voltage regulator, a connector to the parallel port, the circuit to drive 8 LED's, and two potentiometers to control backlight and contrast. Here's the schematic and board (designed with eagle):

And here an example, two displays on one bus (16×4 and 20×2):

'''ATTENTION! Wrongly cabled on Picture! Pin 6 of Display 2 have to be connected to Pin 17 (SelectIn) of Paralellport!


  • hd44780.txt
  • Last modified: 2020/07/17 18:33
  • (external edit)