MAG-85 Construction:

44780-Controlled LCD Interface Test Program

Important Memory Locations:
START     0100 (start of initialization)
COUT      0200 (lcd character out)
NIBOUT    0209 (LCD character nibble out)
SOUT      0218 (lcd string output)
LCOUT     0230 (lcd command byte out)
CNOUT     0239 (lcd command nibble out)
CMDOUT    0246 (lcd command byte+delay output)
DELAY     0300 (delay routine)
SDELAY    0301 (short delay)
FULLDELAY 0306 (very long delay)
LDELAY    0308 (long delay)

BLINK     0151 (SOD LED blinker in program.)

Mem
Loc   Value    Opcode     Comment          
0000  C3 00 01 JMP START   ; Jump to program start.
.
.
.
; Main program
0100  FE       DI         ; No Interrupts.
0101  26 1F    MVI H,$1F  ; Set up SP.
0103  2E FF    MVI L,$FF
0105  F9       SPHL
0106  CD 06 03 CALL FULLDELAY ; Wait on LCD Reset.
0109  3E 03    MVI A,$03  ; Start LCD Reset Seq.
010B  CD 39 02 CALL CNOUT
010E  06 07    MVI B, $07; Delay
0110  CD 08 03 CALL LDELAY
0113  3E 03    MVI A,$03 ; Step 2 in reset seq.
0115  CD 39 02 CALL CNOUT
0118  3E 3C    MVI A,$3C ; Delay
011A  CD 01 03 CALL SDELAY
011D  3E 03    MVI A,#03 ; Step 3 in reset seq.
011F  CD 39 02 CALL CNOUT
0122  3E 10    MVI A,$10 ; Delay
0124  CD 01 03 CALL SDELAY
0127  3E 02    MVI A,$02 ; last step in reset
0129  CD 39 02 CALL CNOUT
012C  3E 10    MVI A,$10 ; Delay
012E  CD 01 03 CALL SDELAY ; end of reset
0131  3E 28    MVI A,$28   ; 1st LCD command
0133  CD 46 02 CALL CMDOUT ; 4 bits, 2 lines
0136  3E06     MVI A,$06   ; 2nd LCD command
0138  CD 46 02 CALL CMDOUT ; Entry Mode Set
013B  3E 0F    MVI A,$0F   ; 3rd LCD command
013D  CD 46 02 CALL CMDOUT ; Disp, Cursor, Blink ON
0140  3E 01    MVI A,$01   ; 4th LCD command
0142  CD 46 02 CALL CMDOUT ; Clear Display
0145  3E 80    MVI A,$08   ; Last LCD command
0147  CD 46 02 CALL CMDOUT ; Set data address 00
014A  26 04    MVI H,$04   ; Set up string pointer
014C  2E 00    MVI L,$00
014E  CD 18 02 CALL SOUT   ; Send string to LCD
0151  3E C0    MVI A,$C0   ; Turn on SOD LED
0153  30       SIM
0154  CD 06 03 CALL FULLDELAY ; delay
0157  3E 40    MVI,$40     ; Turn off SOD LED
0159  30       SIM
015A  CD 06 03 CALL FULLDELAY ; delay
015D  C3 51 01 JMP BLINK   ; keep on blinking
.
.
.
; LCD Character Data Routines
0200  F5       PUSH PSW    ; Preserve char byte
0201  1F       RAR         ; Rotate high nibble
0202  1F       RAR         ; into low nibble
0203  1F       RAR
0204  1F       RAR
0205  CD 09 02 CALL NIBOUT ; send out nibble
0208  F1       POP PSW     ; get char byte back
0209  E6 0F    ANI $0F     ; mask non-data out
020B  F6 80    ORI $80     ; set RS, char data
020D  D3 00    OUT 00      ; send to LCD latch
020F  F6 20    ORI $20     ; pulse E line
0211  D3 00    OUT 00
0213  E6 DF    ANI $DF     ; E off
0215  D3 00    OUT 00
0217  C9       RET         ; return to caller

0218  7E       MOV A,M     ; Get a char byte
0219  FE 00    CPI $00     ; Is it a NULL?
021B  C8       RZ          ; Yes, end of string.
021C  CD 00 02 CALL COUT   ; send out the character
021F  3E 09    MVI A,$09   ; delay for LCD
0221  CD 01 03 CALL SDELAY
0224  23       INX H       ; advance data pointer
0225  C3 18 02 JMP SOUT    ; get next character
.
.
.
;LCD Command Routines
0230  F5       PUSH PSW    ; preserve command
0231  1F       RAR         ; Rotate high nibble
0232  1F       RAR         ; into low nibble.
0233  1F       RAR
0234  1F       RAR
0235  CD 02 39 CALL CNOUT  ; send nibble out
0238  F1       POP PSW     ; get command byte
0239  E6 0F    ANI $0F     ; mask off high nibble
023B  D3 00    OUT 00      ; send to LCD (RS low)
023D  F6 20    ORI $20     ; Pulse E
023F  D3 00    OUT 00
0241  E6 DF    ANI $DF
0243  D3 00    OUT 00
0245  C9       RET         ; Done, go back.
0246  F5       PUSH PSW    ; save command byte
0247  CD 30 02 CALL LCOUT  ; send command byte out
024A  F1       POP PSW     ; get command back
024B  FE 07    CPI $07     ; is it 07 or less?
024D  D2 56 02 JNC 0256    ; if so, use slow delay
0250  3E 09    MVI A,$09   ; delay for fast command
0252  CD 01 30 CALL SDELAY
0255  C9       RET         ; and go back
0256  AF       XRA A       ; Slow command delay
0257  06 03    MVI B,$03
0259  CD 08 03 CALL LDELAY
025C  RET                  ; go back
.
.
.
;Delay Routines
0300  AF       XRA A       ; Clear A
0301  3D       DCR A       ; Count down
0302  C2 01 03 JNZ SDELAY  ; until 0
0305  C9       RET         ; then return.
0306  AF       XRA A       ; Clear A
0307  47       MOV B,A     ; and B.
0308  3D       DCR A       ; Count A down
0309  C2 08 03 JNZ LDELAY  ; until 0
030C  05       DCR B       ; then count B down
030D  C2 08 03 JNZ LDELAY   ; until 0
0310  C9       RET         ; then return.
.
.
.
; ASCII data to be sent to screen:
0400 4D 41 47 2D 38 35 20 69 ; MAG-85 i
0409 73 20 72 65 61 64 79 21 ; s ready!
0410 20 20 20 20 20 20 20 20 ;        
0418 20 20 20 20 20 20 20 20 ;        
0420 20 20 20 20 20 20 20 20 ;        
0428 59 6F 75 72 20 4C 43 44 ; Your LCD
0430 20 77 6F 72 6B 73 21 20 ;  works! 
0438 20 20 20 20 20 20 20 20 ;          
0440 20 20 20 20 20 20 20 20 ;         
0448 20 20 20 20 20 20 20 20 ;         
0450 00 FF FF FF FF FF FF FF FF ; (Null)

This program will display the message "MAG-85 is ready!" on the first line of the LCD, then message "Your LCD works!" on the second line. The display will "wrap" and leave the cursor blinking at the start of the first line of all 80 characters of data are programmed into your memory as above.

It is set up for a 2x16 character display. Each line is 40 characters to the LCD internally, however. It will display fine on larger displays, but will leave a lot of characters just as spaces. If you're using a larger display, just add characters in place of the spaces in the data.

LCDINIT5.BIN: Binary Dump of the Memory

LCDINIT5.TXT: Text Dump of the Memory