(*********************************************************************

    LCD tester program for DisplayTech 204B LCD display (4x20 chars)
    Target platform: DOS, compiler: Borland Pascal 7.0

Original documentation:
 LCD display: 
      http://www.displaytech.com.hk/pdf/char/204b%20series-v12.PDF	
 Centronics printer port:
      http://www.nullmodem.com/DB-25.htm

           !! NO WARRANTY !! This application is "as is".
                   You use at your own risk!

  Jozsef Laszlo, joco@szabolcs.net

  Pin assignments:

  From then LPT port:             DisplayTech 204B panel
  -------------------             ----------------------
  -STROBE                           (4) RS
  -AUTO FD                          (5) R/W
  -SEL IN                           (6) E
  D0..D7                        (7..14) DB0..DB7
  Drive POWER connector:
  +5V (red)                         (1) Vss
  GND (black)                       (2) Vdd
                                    (3) --|2K2|--> back to GND +
                                   (15) N/C ++
                                   (16) N/C ++

 + Pull the Vo line down to GND via a 2K2 resistor.
++ You don't need the backlight for this test. (You can solder the K (16)
   to GND and the A (15) to +12V (yellow) via 330-470 Ohm resistor though.)
*********************************************************************)
uses crt;

const
     LPT1 = $378;

     ch1 : array[0..7] of byte=($1f,$11,$11,$11,$11,$11,$11,$1f); { rect }
     ch2 : array[0..7] of byte=($02,$04,$0e,$01,$0f,$11,$0f,$00); { a'   }
     ch3 : array[0..7] of byte=($00,$10,$08,$04,$02,$01,$00,$00); { /    }

                               {  -   \   |   / }
      cc : array[0..3] of byte=($b0,$02,$7c,$2f); { anim.chars }

procedure portinit;
begin
 port[LPT1+2]:=$08;
end;

procedure CMDwrite(cmd:byte);
begin
 port[LPT1]:=cmd;
 port[LPT1+2]:=$03; { strobe=L, auto fd=L, sel in=H  xx000x11 }
 delay(1);
 port[LPT1+2]:=$0b; { strobe=L, auto fd=L, sel in=L  xx001x11 }
end;

procedure CGaddress(addr:byte);
begin
 addr:=addr and 63; { valid address range is $00 .. $3f }
 CMDwrite($40 or addr);
end;

procedure DDaddress(addr:byte);
begin
 addr:=addr and 127; { valid address range is $00 .. $7f }
 CMDwrite($80 or addr);
end;

procedure DataWrite(data:byte);
begin
 port[LPT1]:=data;
 port[LPT1+2]:=$02; { strobe=H, auto fd=L, sel in=H  xx000x11 }
 delay(1);
 port[LPT1+2]:=$0a; { strobe=H, auto fd=L, sel in=L  xx001x11 }
end;

procedure LCDinit;
begin
  delay(15);
  CMDwrite($3f);
  delay(4);
  CMDwrite($3f);
  delay(1);
  CMDwrite($3f);
  delay(10);
  CMDwrite($38);
end;

procedure DefChar(idx:byte; src:pointer);
var
   i : integer;
   p : ^byte;
begin
 p:=src;
 CGaddress((idx and 7) shl 3);
 for i:=0 to 7 do
  begin
   DataWrite(p^); inc(p);
  end;
end;

var i : integer;

BEGIN
 clrscr;
 portinit;

 LCDinit;

 CMDwrite($01); { DISPLAY CLEAR }
 CMDwrite($03); { CURSOR HOME   }
 CMDwrite($06); { ENTRY MODE    }
 CMDwrite($0c); { DISPLAY ON    }

 DDaddress($00);
 for i:=0 to 19 do datawrite(65+i); { capital chars   }
 DDaddress($40);
 for i:=0 to 19 do datawrite(97+i); { lowercase chars }

 Defchar(0,@ch1);
 Defchar(1,@ch2);
 Defchar(2,@ch3);
 DDaddress($14);
 DataWrite($00);
 DataWrite($01);

 writeln('You should see something on the LCD display by now!');
 writeln('Press ENTER to quit.');

 i:=0;
 repeat { "animation" }
  DDaddress($67); { bottom-right corner }
  DataWrite(byte(cc[i and 3]));
  inc(i); delay(100);
 until keypressed;
 while keypressed do readkey;

 portinit;
END.