*** ASSEMBLY SUCCESSFUL ***

0010 AGAIN          009B ALLPSIN        0076 BFCHECK        0085 CHECK_AGAIN    
00A5 COMBEGADR      000A COMMAND        0060 COMMON         00A9 CUSTOM_DATA    
0003 CWADR          000B DATA           0099 DELAY          000E DISABLE        
000F ENABLE         002E NEXTCOM        003E NEXT_BYTE      004C NEXT_CHAR      
0004 NUMOFC         0000 PAADR          0082 PACOUTBIN      0090 PAINCOUT       
0080 PANDCOUT       0001 PBADR          0002 PCADR          009C PDELAY         
000D READ           0053 SENDCHAR       0054 SENDCHARA      005B SENDCOM        
005C SENDCOMA       000C WRITE          


;********************************************************************
;====================================================================
; Program: custom.asm
; programmer(s): Dincer Aydin
; function:Demonstrates how custom characters are defined and used
;====================================================================
;********************************************************************
; This code requires a 2*16 LCD connected to a 8255 with base address of 00h
; routines sendcomA & sendcom & sendcharA & sendchar have been tested on 
; >> 2*16 Hitachi LCD with HD44780 chip 
; >> Samsung 1*16 LCD with a KS0062F00 chip
; >> 2*16 Epson LCD marked P300020400 SANTIS 1 ,and 
; >> noname 1*16 HD44780 based LCD.
; The Z80 was clocked at 2 MHz and 4,9152 MHz for each display.This was done 
; because the routines mentioned above take many t states and in most cases 
; that will be longer that the time a HD44780 will need to execute a command. 
;
; Connections:
; LCD data bus(pins #14-#7) connected to Port A of a 8255 with 00h base address
; LCD Enable pin(#6) connected to Port C bit #7
; LCD R/W pin(#5) connected to Port C bit #6
; LCD RS pin(#4) connected to Port C bit #5


;8255 port address(base 00h):	
0000               PAADR        EQU  00H             ; Address of PortA
0000               PBADR        EQU  01H             ; Address of PortB
0000               PCADR        EQU  02H             ; Address of PortC
0000               CWADR        EQU  03H             ; Address of Control Word
;stuff to be written into the control word of the 8255:
;Some of the change the state of the ports and some manipulate
;bits on port C
0000               ALLPSIN      EQU  9BH             ; set all ports to input mode
0000               PAINCOUT     EQU  90H             ; A input,C output,B output
0000               PANDCOUT     EQU  80H             ; set all ports to output mode
0000               PACOUTBIN    EQU  82H             ; A output,C output,B input

;bit set/reset commands.These bits are the control signals for the LCD
0000               ENABLE       EQU  0FH             ; set portC bit #6
0000               DISABLE      EQU  0EH             ; reset portC bit #6
0000               READ         EQU  0DH             ; set portC bit #5
0000               WRITE        EQU  0CH             ; reset portC bit #5
0000               COMMAND      EQU  0AH             ; reset portC bit #4
0000               DATA         EQU  0BH             ; set portC bit #4

; Define number of commands and length of string data
0000               NUMOFC       EQU  4H              ; number of commands


; initialization:		
0000 31 00 02                   LD   SP,200H         ; Set stack pointer
0003 0E 03                      LD   C,CWADR         
0005 3E 82                      LD   A,PACOUTBIN     ; Ports A&C output,B input
0007 ED 79                      OUT  (C),A           

; *********It all begins here**********:
; This part sends commands to initialize the LCD

0009 CD 99 00                   CALL DELAY           
000C 3E 38                      LD   A,38H           ; function set command
000E 06 04                      LD   B,4             
0010 0E 03         AGAIN:       LD   C,CWADR         
0012 16 0A                      LD   D,COMMAND       
0014 ED 51                      OUT  (C),D           ; select the instruction register 
0016 16 0C                      LD   D,WRITE         
0018 ED 51                      OUT  (C),D           ; reset RW pin for writing to LCD
001A D3 00                      OUT  (PAADR),A       ; place the command into portA
001C 16 0F                      LD   D,ENABLE        
001E ED 51                      OUT  (C),D           ; enable the LCD
0020 16 0E                      LD   D,DISABLE       
0022 ED 51                      OUT  (C),D           ; disable the LCD 
0024 CD 99 00                   CALL DELAY           ; wait for a while
0027 10 E7                      DJNZ AGAIN           ; loop till the command is sent 4 times

; send commands to set input mode, cursor,number of lines ,and etc.
0029 21 A5 00                   LD   HL,COMBEGADR    ; set HL to point the first command
002C 06 04                      LD   B,NUMOFC        ; put the number of commands to be sent in B
002E CD 5B 00      NEXTCOM:     CALL SENDCOM         ; send (HL) as a command 
0031 23                         INC  HL              ; point the next command
0032 10 FA                      DJNZ NEXTCOM         ; loop till all commands are sent

; The code below will modify CG RAM contents to define 8 custom characters


0034 21 A9 00                   LD   HL,CUSTOM_DATA  ; make (HL) point custom character data
0037 3E 40                      LD   A,40H           
0039 CD 5C 00                   CALL SENDCOMA        ; Set CG RAM address to 00h by sendind 40h as a command


003C 06 40                      LD   B,40H           ; use B to count number of bytes to be written to CG RAM
; 8 characters * 8 bytes = 64 bytes (40h) in this example
003E CD 53 00      NEXT_BYTE:   CALL SENDCHAR        ; write (HL) to CG RAM
0041 23                         INC  HL              ; point the next byte to be written to CG RAM
0042 10 FA                      DJNZ NEXT_BYTE       ; loop till all bytes are sent

; Now that custom characters are defined , let's see them on the LCD screen
; The code below will print characters 0-7 (the ones we defined) to LCD screen
0044 06 08                      LD   B,8H            ; use B to count the number of bytes to be written to DD RAM 
0046 3E 80                      LD   A,80H           
0048 CD 5C 00                   CALL SENDCOMA        ; Set DD RAM adres to 00h by sending 80h as a command
004B AF                         XOR  A               ; clear a
004C CD 54 00      NEXT_CHAR:   CALL SENDCHARA       ; print ASCII character corresponding to the value in A
004F 3C                         INC  A               
0050 10 FA                      DJNZ NEXT_CHAR       ; loop till ASCII characters 0-7 are sent to the LCD
0052 76                         HALT                 


; ====================================================================
; Subroutine name:sendcomA & sendcom & sendcharA & sendchar 
; programmer:Caner Buyuktuna & Dincer Aydin
; input:A or (HL)
; output:
; Registers altered:A 
; function:	sendcharA sends the data in A to the LCD
;  	  	sendchar sends the data in (HL) to the LCD
; 		sendcomA sends the command in A to the LCD
;  		sendcom sends the command in (HL) to the LCD	
; ====================================================================
0053 7E            SENDCHAR:    LD   A,(HL)          ; put the data to be sent to the LCD in A
0054 C5            SENDCHARA:   PUSH BC              ; save BC
0055 D5                         PUSH DE              ; save DE
0056 1E 0B                      LD   E,DATA          ;  
0058 C3 60 00                   JP   COMMON          

005B 7E            SENDCOM:     LD   A,(HL)          
005C C5            SENDCOMA:    PUSH BC              ; save BC
005D D5                         PUSH DE              ; save DE   
005E 1E 0A                      LD   E,COMMAND       

0060 CD 76 00      COMMON:      CALL BFCHECK         ; See if the LCD is busy. If it is busy wait,till it is not.
0063 ED 59                      OUT  (C),E           ; Set/reset RS accoring to the content of register E
0065 16 0C                      LD   D,WRITE         
0067 ED 51                      OUT  (C),D           ; reset RW pin for writing to LCD
0069 D3 00                      OUT  (PAADR),A       ; place data/instrucrtion to be written into portA
006B 16 0F                      LD   D,ENABLE        
006D ED 51                      OUT  (C),D           ; enable the LCD
006F 16 0E                      LD   D,DISABLE       
0071 ED 51                      OUT  (C),D           ; disable the LCD 
0073 D1                         POP  DE              ; restore DE
0074 C1                         POP  BC              ; restore BC
0075 C9                         RET                  ; return
; ====================================================================
; Subroutine name:bfcheck
; programmer:Dincer Aydin
; input:
; output:
; Registers altered:D
; function:Checks if the LCD is busy and waits until it is not busy
; ====================================================================

0076 F5            BFCHECK:     PUSH AF              ; save AF
0077 0E 03                      LD   C,CWADR         
0079 16 90                      LD   D,PAINCOUT      
007B ED 51                      OUT  (C),D           ; make A input,C output,B output
007D 16 0D                      LD   D,READ          
007F ED 51                      OUT  (C),D           ; set RW pin for reading from LCD
0081 16 0A                      LD   D,COMMAND       
0083 ED 51                      OUT  (C),D           ; select the instruction register 
0085 16 0F         CHECK_AGAIN: LD   D,ENABLE        
0087 ED 51                      OUT  (C),D           ; enable the LCD
0089 DB 00                      IN   A,(PAADR)       ; read from LCD
008B 16 0E                      LD   D,DISABLE       
008D ED 51                      OUT  (C),D           ; disable the LCD 
008F 07                         RLCA                 ; rotate A left through C flag to see if the busy flag is set
0090 DA 85 00                   JP   C,CHECK_AGAIN   ; if busy check it again,else continue
0093 16 80                      LD   D,PANDCOUT      
0095 ED 51                      OUT  (C),D           ; set all ports to output mode
0097 F1                         POP  AF              ; restore AF
0098 C9                         RET                  

;====================================================================
; Subroutine name:DELAY and PDELAY
; programmer(s):Dincer Aydin
; input:the value in HL (for PDELAY only)
; output:-
; Registers altered:H,L
; function:delay 
; for more delay you can add a few nops or or some junk commands using the index 
; registers
; pdelay uses what you put into HL before you called the PDELAY routine 
;====================================================================

0099 21 10 10      DELAY:       LD   HL,1010H        
009C 2D            PDELAY:      DEC  L               
009D C2 9C 00                   JP   NZ,PDELAY       
00A0 25                         DEC  H               
00A1 C2 9C 00                   JP   NZ,PDELAY       
00A4 C9                         RET                  

;====================================================================
; commands and strings
00A5 01 80 0C 06   COMBEGADR:   DB   01H,80H,0CH,06H
; clear display,set DD RAM adress,
; turn on display with cursor hidden,set entry mode
; These are the values to create some custom characters
00A9 00 04 02 1F   CUSTOM_DATA: DB   0,4,2,31
00AD 02 04 00 00                DB   2,4,0,0
; right arrow				
00B1 00 04 08 1F                DB   0,4,8,31
00B5 08 04 00 00                DB   8,4,0,0
; left arrow
00B9 04 0E 15 04                DB   4,14,21,4
00BD 04 00 00 00                DB   4,0,0,0
; up arrow
00C1 00 00 00 04                DB   0,0,0,4
00C5 04 15 0E 04                DB   4,21,14,4
; down arrow
00C9 08 14 14 08                DB   8,20,20,8
00CD 05 06 05 05                DB   5,6,5,5
; single-character "OK"
00D1 0E 11 11 1F                DB   14,17,17,31
00D5 1B 1B 1F 00                DB   27,27,31,0
; locked (padlock closed)
00D9 0E 10 10 1F                DB   14,16,16,31
00DD 1B 1B 1F 00                DB   27,27,31,0
; unlocked (padlock open)
00E1 11 12 17 09                DB   17,18,23,9
00E5 13 04 07 00                DB   19,4,7,0
; single-character "1/2"

; The custom character data above is taken from "LCD Serial Backpack App Note No. 2" 
; from Scott Edwards Electronics Inc. 









    Source: geocities.com/siliconvalley/circuit/8882/files

               ( geocities.com/siliconvalley/circuit/8882)                   ( geocities.com/siliconvalley/circuit)                   ( geocities.com/siliconvalley)