Pascal Demo code to drive NEC uPD7228G
Here is some Turbo Pascal 6 code to drive the EA-N16025AR
module via the printer port.
These modules use the NEC uPD7228G chips. A later form of the
chip is uPD16434 in 10299e10.pdf currently downloadable as a 1.8Mb
scanned in data sheet from
NEC uPD7228G chips.
The NEC web page is
NEC's Web Site at http://www.nec.de, but it does not have the Chip details any more
Thanks to michael.gaus@ngi.de , here is a scanned sheet for
the modules: ea-x_series.pdf. ( 556k
bytes). It does however have some interesting information about
the EA-N series modules which use the NEC uPD7228G as well.
I brought some of these displays from or Greenweld Electronics .
Doug Rice, doug.h.rice@btinternet.com
Updated 6th June 1999 & 1st May 2000
Copyright 1999
{
| This demo program drives the LCD display via the LPT port.
| The modules clock is driven by an external oscillator of about 100kHz
|
| This demo does not read the /BUSY line.
| This demo does not support reading from the Display module.
| This demo does not support the serial input mode.
|
| This code was written from the chip's data sheets.
| The module's pin connections have been reverse engineered.
| The data sheet for the module has yet to be located.
EA-N16025AR uses a pair of NEC D7228G LCD chips a 2 X 16 display
EA-N20016AR possibly also uses a pair of NEC D7228G chips. 1 x 20 display
EA-N16025AR uses a pair of NEC D7228G LCD chips
===============================================
A later form of the chip is uPD16434 in 10299e10.pdf currently downloadable
as a 1.8Mb scanned in data sheet. The NEC web page is
NEC's Web Site at http://www.nec.de
Looking from the Display side, the connector has 14 pins.
I will number them from right to left
[ DISPLAY ]
[ ]
14 13 12 11 10 9 8 7 6 5 4 3 2 1
LPT1 conn chip name
db0 14 27 D0 SI I,O
db1 13 28 D1 P/-S I,O Data 1 or Parrallel /serial mode
db2 12 29 D2 CAE I,O
db3 11 30 D3 S0 I,O
NC 10 32 /BUSY O
db5 9 35 /STB /SCK I Strobes each nibble into chip
db6 8 36 C /D I Command /data 1 for command, 0 for data and reading
db7 7 40 RESET I RESET
db4 6 39 /CS I Selects the display
clk 5 41 CLOCK I
NC 4 CASE
-ve 3 - Vlcd
gnd 2 34 Vss GND
+4.5V 1 33 Vdd +ve
The D7228G can be programmed Parrallel or serially.
|
}
program lcd_hack;
USES crt;
var
G_CA :integer; { used to select which 7228 chip is addressed}
MM :integer;
try :integer;
counter :integer;
base :integer;
dummy :char;
const
{ Configure to the port address of the Printer port being used }
LPT1 = $378;
{ LPT1 = $3BC; }
{ The Epson EA-N 16025AR uses 2 NEC D 7228G chip in a pair. }
{ data bits LTP+0}
{ during rising edge of Strobe input NSTRB }
D0 = $01; { 0; }
D1 = $02; { 1; }
D2 = $04; { 2; }
D3 = $08; { 3; }
SI = $01; { 0; Serial Input }
SO = $08; { 3; Serial Output }
{ during falling edge of RESET input }
PNS = $02; { 1; select parrallel/-Serial on falling RESET }
CAE = $04; { 2; Chip Address Enable ( for serial mode only ) }
{ during rising edge of Strobe input NSTRB }
CA0 = $01; { 0; CA = chip select, CAE enabled or always during parrallel }
CA1 = $02; { 1; if D0,D1 = CA0,CA1 pins as STRB goes low }
{ Strobe input, }
{ If parrallel mode,strobes in nibble }
{ If serial mode,strobes in each bit -see data sheet }
NSTB = $20;{ 5;/Strobe }
{ hold at the same level for whole 8 bits }
CND = $40; { 6; selects if 8 bits are Command or /DATA, }
RESET= $80; { 4; Reset, active high }
NCS = $10; { 7; /Chip Select, active low }
{ cntl bits LTP+2 }
CLOCK = $04; { 3; } { Commands }
{
| Chip commands:-
| ========================================
}
{ Set Frame Frequency, Divides the CLOCK input }
SFF_0 = $10; { div 2^14 }
SFF_1 = $11;
SFF_2 = $12;
SFF_3 = $13;
SFF_4 = $14; { div 2^10 }
{ Set Multiplexing Mode }
{
| The two chips work together.
| They are only joined by the sync pins which are joined together.
| Configure sync as output on one chip, and an inputs on the other.
|
| Commands need to be sent to each chip seperately.
|
| Select the Chip by putting the CA on DB0,DB1
| during falling edge of NSTRB.
|
| The nibbles of the data are read in on rising edge of NSTRB.
| The most significant nibble is written in first.
|
|
| The display forms four segments.
| R0-R7 [ ][ ] LDPI = 39 to 0
| R8-R15 [ ][ ] LDPI = 39 to 0 +$40
| C0-C49 C0-C49 for 10 char display.
| C0-C40 C0-C40 for 8 char display.
| CA=0, CA=3,
|
| Row pins are either R0 to R7 or R8 to R15.
| Col pins 42 to 49 can be configured to be R8 to R15
| The SMM command configures these.
|
}
SMM = $18; { See Data Sheet }
{
SMM_8_R07_C42_ip_mem0 = $18+0;
SMM_8_R07_C42_ip_mem1 = $18+1;
SMM_8_R07_C42_op_mem0 = $18+2;
SMM_8_R07_C42_op_mem1 = $18+3;
SMM_16_R815_C42_ip_mem0 = $18+4;
SMM_16_R815_C42_ip_mem1 = $18+5;
SMM_16_R07_C42_op_mem0 = $18+6;
SMM_16_R07_R158_op_mem1 = $18+7;
{ Display On }
DISP_ON = $09;
{ Display Off }
DISP_OFF = $08;
{ Load Data Pointer Immediate }
LDPI = $80; { There are two banks, add $40 for Bank 1 }
{ In Char mode the pointer increments by 5}
SRM = $60; { Set Read Mode }
{ Set Write Mode - The LSB is top pixel, the MSB is pixel in cursor }
SWM = $64; { Set Write mode - replace }
SORM = $68; { Set OR mode - OR new bits with those present }
SANDM = $6C; { Set AND mode - AND new bits with those present }
{ Add to SWM,SORM,SANDM,BRESET,BSET, to change Data Pointer }
INC = 0;
DEC = 1;
EQU = 3;
{ Character Commands - The data causes a Char to be copied to screen }
SCML = $71; { Set Char mode, copy Char from Char rom }
SCMR = $72;
{ Bit Commands, BIT to be set needs to be x 4 then added }
BRESET = $20;
BSET = $40;
{ When in Char mode the cursor is set or cleared }
CLCURS = $7C;
WRCURS = $7D;
{ put the display into sleep mode }
STOP = $01;
var
CNT,cnt2 : byte;
procedure wlcd( cmd:byte );
begin
port[ LPT1 ] := cmd;
delay(10);
{ 50 works }
end;
procedure wlcdc( cmd:byte );
begin
port[ LPT1+2 ] := cmd;
delay(10);
{ 50 works }
end;
procedure wlcdReset;
begin
{
{ Select Parrallel mode
RESET -----______ When RESET is goes low sample line
P/-S -----------
CAE ----------- only used in serial mode.
}
wlcd( NSTB OR D1 OR CAE OR NCS );
delay(2);
wlcd( NSTB OR D1 OR CAE );
delay(2);
wlcd( RESET OR NSTB OR D1 OR CAE );
delay(2);
wlcd( NSTB OR D1 OR CAE );
delay(2);
end;
procedure wlcdByte( cmd:byte; cnd:byte );
var
CA : integer;
begin
CA := g_ca;
{
CS ---___________________-- Chip Select
D0,D3----CA---DDD--CA--DDD--- Data Lines or CA lines
STRB -----_____-----____----- Strobe
CND ===x==================x= Command/ not data
RESET________________________ Reset
0 123 45 67 89 A
}
{0:}
wlcd( NCS OR NSTB OR CA OR cnd );
delay(2);
{1:}
wlcd( NSTB OR CA OR cnd );
delay(2);
{2:}
wlcd( CA OR cnd );
delay(2);
{4:}
wlcd( ( (cmd shr 4) AND $0F ) or cnd );
delay(2);
{5:}
wlcd( NSTB OR ( (cmd shr 4) AND $0F ) or cnd );
delay(2);
{6: start the next nibble }
wlcd( NSTB OR CA OR cnd );
delay(2);
{7:}
wlcd( CA OR cnd );
delay(2);
{8:}
wlcd( ( cmd AND $0F ) or cnd );
delay(2);
{9:}
wlcd( NSTB OR ( cmd AND $0F ) or cnd );
delay(2);
{A:}
wlcd( NCS OR NSTB OR ( cmd AND $0F ) or cnd );
delay(2);
end;
procedure wlcdCMD( cmd:byte );
begin
wlcdByte( cmd,CND);
end;
procedure wlcdDATA( cmd:byte );
begin
wlcdByte( cmd,0);
end;
procedure wlcdInit;
begin
wlcdReset;
{ Configure left chip as the master, sync is output }
g_ca := 0;
wlcdCMD( SMM + 7 ); { set Sync to output }
wlcdCMD( SFF_4 );
wlcdCMD( DISP_ON );
g_ca := 3;
wlcdCMD( SMM + 5 ); { set Sync to input }
wlcdCMD( SFF_4 );
wlcdCMD( DISP_ON );
end;
BEGIN
g_ca := 0;
MM := 0;
try := 0;
base := $20;
while ( 1= 1 ) do
begin
try := try + 1 ;
mm := ( try SHR 3 ) and 7 ;
G_CA := try and 3;
mm := 3;
{ when trying to find out what worked mm was added to the SMM cmd }
g_ca := 0; { Write commands and data to Left chip }
writeln(try:4,mm:4,g_ca:4);
wlcdInit;
g_ca := 3; { Write commands and data to Right chip }
{ Write directly to pixels }
wlcdCMD( SWM );
wlcdCMD( LDPI );
for counter := 0 to 4 do
begin
wlcdDATA( counter );
end;
wlcdDATA( $14 );
wlcdDATA( $22 );
wlcdDATA( $41 );
wlcdDATA( $22 );
wlcdDATA( $14 );
wlcdCMD( SORM );
wlcdDATA( $14 );
wlcdDATA( $22 );
wlcdDATA( $41 );
wlcdDATA( $22 );
wlcdDATA( $14 );
wlcdCMD( SANDM );
wlcdDATA( $14 );
wlcdDATA( $22 );
wlcdDATA( $41 );
wlcdDATA( $22 );
wlcdDATA( $14 );
wlcdDATA( $AA );
wlcdDATA( $55 );
wlcdDATA( $AA );
wlcdDATA( $55 );
wlcdDATA( $AA );
wlcdCMD( LDPI +$40);
{
for counter := 0 to 255 do
begin
wlcdDATA( counter );
end;
}
wlcdCMD( SCMR );
wlcdCMD( LDPI + $0 + 5*8-1 );
wlcdDATA( $30 );
wlcdDATA( $31 );
wlcdDATA( $32 );
wlcdDATA( $33 );
g_ca := 3;
wlcdCMD( LDPI );
wlcdDATA( $30 );
wlcdDATA( $31 );
wlcdDATA( $32 );
wlcdDATA( $33 );
wlcdDATA( $34 );
wlcdDATA( $35 );
wlcdDATA( $36 );
wlcdDATA( $37 );
wlcdCMD( LDPI + +$40 + 39);
wlcdCMD( SCML );
for counter := 0 to 7 do
begin
wlcdCMD( CLCURS );
end;
{ Position Cursor to the bottom left }
wlcdCMD( LDPI + 39 );
wlcdCMD( SCML );
wlcdDATA( ORD(' '));
wlcdDATA( ORD('H'));
wlcdDATA( ORD('e'));
wlcdDATA( ORD('l'));
wlcdDATA( ORD('l'));
wlcdDATA( ORD('o'));
wlcdDATA( ORD(' '));
wlcdDATA( ORD(' '));
wlcdCMD( LDPI + $40 + 39 );
wlcdCMD( SCML );
wlcdDATA( ORD(' '));
wlcdDATA( ORD('W'));
wlcdDATA( ORD('o'));
wlcdDATA( ORD('r'));
wlcdDATA( ORD('l'));
wlcdDATA( ORD('d'));
wlcdDATA( ORD(' '));
wlcdDATA( ORD(' '));
g_ca := 3;
wlcdCMD( LDPI );
wlcdDATA( $30 );
wlcdDATA( $31 );
wlcdDATA( $32 );
wlcdDATA( $33 );
wlcdDATA( $34 );
wlcdDATA( $35 );
wlcdDATA( $36 );
wlcdDATA( $37 );
wlcdDATA( $38 );
wlcdDATA( $39 );
wlcdDATA( $41 );
wlcdDATA( $42 );
wlcdCMD( LDPI + $40 );
wlcdCMD( SCML );
wlcdDATA( $40 );
wlcdDATA( $41 );
wlcdDATA( $42 );
wlcdDATA( $43 );
wlcdDATA( $44 );
wlcdDATA( $45 );
wlcdDATA( $46 );
wlcdDATA( $47 );
wlcdDATA( $48 );
wlcdDATA( $49 );
{ now address each quarter in turn }
g_ca:=3;
wlcdCMD( SCML );
wlcdCMD( LDPI + 39);
for counter := 0 to 7 do
begin
wlcdDATA( base + counter );
end;
wlcdCMD( LDPI + 39);
for counter := 0 to 7 do
begin
wlcdCMD( CLCURS );
end;
g_ca:=0;
wlcdCMD( SCML );
wlcdCMD( LDPI + 39);
for counter := 8 to 15 do
begin
wlcdDATA( base + counter );
end;
wlcdCMD( LDPI + 39);
for counter := 0 to 7 do
begin
wlcdCMD( CLCURS );
end;
g_ca:=3;
wlcdCMD( SCML );
wlcdCMD( LDPI + $40 + 39);
for counter := 16 to 23 do
begin
wlcdDATA( base + counter );
end;
wlcdCMD( LDPI + $40 + 39);
for counter := 0 to 7 do
begin
wlcdCMD( CLCURS );
end;
g_ca:=0;
wlcdCMD( SCML );
wlcdCMD( LDPI + $40 + 39);
for counter := 24 to 31 do
begin
wlcdDATA( base + counter );
end;
wlcdCMD( LDPI + $40 + 39);
for counter := 0 to 7 do
begin
wlcdCMD( CLCURS );
end;
base := base + 32;
g_ca:=0;
wlcdCMD( STOP );
g_ca:=3;
wlcdCMD( STOP );
writeln('++++++++++++++++');
end;
END.
Last Modified: