*** 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.