0001 0000 ;******************************************************************************* 0002 0000 ;=============================================================================== 0003 0000 ; Program: v_scroll.asm 0004 0000 ; programmer(s): Dincer Aydin (dinceraydin@altavista.net) 0005 0000 ; function: vertical scroll effect 0006 0000 ; The effect is the same as the one you can see at the entrance of my LCD pages: 0007 0000 ; http://geocities.datacellar.net/SiliconValley/Circuit/8882/lcd/index.html 0008 0000 ;=============================================================================== 0009 0000 ;******************************************************************************* 0010 0000 ; This code requires a 2*16 LCD connected to a 8255 with base address of 00h 0011 0000 ; routines sendcomA & sendcom & sendcharA & sendchar have been tested on 0012 0000 ; >> 2*16 Hitachi LCD with HD44780 chip 0013 0000 ; >> Samsung 1*16 LCD with a KS0062F00 chip 0014 0000 ; >> 2*16 Epson LCD marked P300020400 SANTIS 1 ,and 0015 0000 ; >> noname 1*16 HD44780 based LCD. 0016 0000 ; The Z80 was clocked at 2 MHz and 4,9152 MHz for each display.This was done 0017 0000 ; because the routines mentioned above take many t states and in most cases 0018 0000 ; that will be longer that the time a HD44780 will need to execute a command. 0019 0000 ; 0020 0000 ; Connections: 0021 0000 ; LCD data bus(pins #14-#7) connected to Port A of a 8255 with 00h base address 0022 0000 ; LCD Enable pin(#6) connected to Port C bit #7 0023 0000 ; LCD R/W pin(#5) connected to Port C bit #6 0024 0000 ; LCD RS pin(#4) connected to Port C bit #5 0025 0000 0026 0000 #define equ .equ 0027 0000 #define end .end 0028 0000 0029 0000 ;8255 port address(base 00h): 0030 0000 paadr equ 00h ; Address of PortA 0031 0000 pbadr equ 01h ; Address of PortB 0032 0000 pcadr equ 02h ; Address of PortC 0033 0000 cwadr equ 03h ; Address of Control Word 0034 0000 ;stuff to be written into the control word of the 8255: 0035 0000 ;Some of the change the state of the ports and some manipulate 0036 0000 ;bits on port C 0037 0000 allpsin equ 9bh ; set all ports to input mode 0038 0000 paincout equ 90h ; A input,C output,B output 0039 0000 pandcout equ 80h ; set all ports to output mode 0040 0000 pacoutbin equ 82h ; A output,C output,B input 0041 0000 0042 0000 ;bit set/reset commands.These bits are the control signals for the LCD 0043 0000 enable equ 0fh ; set portC bit #6 0044 0000 disable equ 0eh ; reset portC bit #6 0045 0000 read equ 0dh ; set portC bit #5 0046 0000 write equ 0ch ; reset portC bit #5 0047 0000 command equ 0ah ; reset portC bit #4 0048 0000 data equ 0bh ; set portC bit #4 0049 0000 0050 0000 ; Define number of commands and length of string data 0051 0000 numofc equ 4h ; number of commands 0052 0000 0053 0000 0054 0000 ; initialization: 0055 0000 31 00 02 ld sp,200h ; Set stack pointer 0056 0003 0E 03 ld c,cwadr 0057 0005 3E 82 ld a,pacoutbin ; Ports A&C output,B input 0058 0007 ED 79 out (c),a 0059 0009 0060 0009 ; *********It all begins here**********: 0061 0009 ; This part sends commands to initialize the LCD 0062 0009 0063 0009 CD 05 01 call delay 0064 000C 3E 38 ld a,38h ; function set command 0065 000E 06 04 ld b,4 0066 0010 0E 03 again: ld c,cwadr 0067 0012 16 0A ld d,command 0068 0014 ED 51 out (c),d ; select the instruction register 0069 0016 16 0C ld d,write 0070 0018 ED 51 out (c),d ; reset RW pin for writing to LCD 0071 001A D3 00 out (paadr),a ; place the command into portA 0072 001C 16 0F ld d,enable 0073 001E ED 51 out (c),d ; enable the LCD 0074 0020 16 0E ld d,disable 0075 0022 ED 51 out (c),d ; disable the LCD 0076 0024 CD 05 01 call delay ; wait for a while 0077 0027 10 E7 djnz again ; loop till the command is sent 4 times 0078 0029 0079 0029 ; send commands to set input mode, cursor,number of lines ,and etc. 0080 0029 21 14 01 ld hl,combegadr ; set HL to point the first command 0081 002C 06 04 ld b,numofc ; put the number of commands to be sent in B 0082 002E nextcom: 0083 002E CD C3 00 call sendcom ; send (HL) as a command 0084 0031 23 inc hl ; point the next command 0085 0032 10 FA djnz nextcom ; loop till all commands are sent 0086 0034 0087 0034 ; Initialization is complete. 0088 0034 0089 0034 0090 0034 ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 0091 0034 ; This part sends strings to the LCD: 0092 0034 numofcts equ 6h ; number of characters to scroll 0093 0034 numofd_line1 equ 0Fh ; define the number of string bytes to be sent to line #1 0094 0034 numofd_line2 equ 08h ; define the number of string bytes to be sent to line #2 0095 0034 0096 0034 replay: 0097 0034 3E 01 ld a,01h ; 01h is the "Clear Screen" command 0098 0036 CD C4 00 call sendcomA ; command is sent 0099 0039 0100 0039 3E 40 ld a,40h ; set CGRAM address to 00h command 0101 003B CD C4 00 call sendcomA ; command is sent and the addrss counter is pointing 00h in CGRAM 0102 003E 0103 003E AF xor a ; clear A 0104 003F 06 40 ld b,64 ; 64 CGRAM locations 0105 0041 clear: 0106 0041 CD BC 00 call sendcharA ; 00h is written to a CG ram location (i.e it is cleared) 0107 0044 10 FB djnz clear ; loop till all CGRAM is cleared 0108 0046 ; CGRAM is clear and any garbage is gone 0109 0046 0110 0046 3E 80 ld a,80h ; 80h is the "set DDRAM address to 00h" command 0111 0048 CD C4 00 call sendcomA ; command is sent and the addrss counter is pointing 00h in DDRAM 0112 004B ; Now that DDRAM address is set, let's print the string data 0113 004B 21 18 01 ld hl,first_line ; set HL to point the first string byte 0114 004E 06 0F ld b,numofd_line1 ; put the number of string bytes to be sent in B 0115 0050 nextdata: 0116 0050 CD BB 00 call sendchar ; send (HL) as string data 0117 0053 CD 05 01 call delay 0118 0056 23 inc hl ; point the next string byte 0119 0057 10 F7 djnz nextdata ; loop till all string bytes are sent 0120 0059 0121 0059 21 2F 01 ld hl,scrolldat ; make HL point the bitmap data of the characters to be scrolled 0122 005C CD 78 00 call scroll ; call the routine that will make it scroll 0123 005F 0124 005F 3E C4 ld a,0C4h ; set DDRAM address so that the cursor moves to the 4th location of the second line 0125 0061 CD C4 00 call sendcomA 0126 0064 ; Now that DDRAM address is set, let's print the string data 0127 0064 21 27 01 ld hl,second_line ; set HL to point the first string byte 0128 0067 06 08 ld b,numofd_line2 ; put the number of string bytes to be sent in B 0129 0069 nextdata2: 0130 0069 CD BB 00 call sendchar ; send (HL) as string data 0131 006C 23 inc hl ; point the next string byte 0132 006D 10 FA djnz nextdata2 ; loop till all string bytes are sent 0133 006F 0134 006F 21 FF FF ld hl,0FFFFh 0135 0072 CD 01 01 call pdelay 0136 0075 0137 0075 C3 34 00 jp replay 0138 0078 ;==================================================================== 0139 0078 ; Subroutine name:Scroll 0140 0078 ; programmer: Dincer Aydin 0141 0078 ; input 1: HL pointing the data of the string to scroll 0142 0078 ; input 2: "numofcts" >>the number of the characters in the string to be scrolled 0143 0078 ; output: 0144 0078 ; Registers altered: many 0145 0078 ; function: 0146 0078 ;==================================================================== 0147 0078 scroll: 0148 0078 E5 push hl ;ld hl',hl 0149 0079 D9 exx 0150 007A E1 pop hl 0151 007B D9 exx 0152 007C 0153 007C 06 01 ld b,1 ; B is used as line counter 0154 007E 3E 47 ld a,47h ; A holds the command to set CGRAM 0155 0080 ; address to the bottom line 0156 0080 ; of the first custom chatacter in CGRAM 0157 0080 0158 0080 ; later in the program A will be increased by 8 to 0159 0080 ; create the command to set CGRAM address to the same 0160 0080 ; line of the next custom character in CGRAM 0161 0080 ; The value in B = the number of lines to be 0162 0080 ; written to CGRAM for each character. 0163 0080 0164 0080 CD 05 01 bidaha: call delay 0165 0083 0166 0083 D9 exx ;ld hl,hl' 0167 0084 E5 push hl 0168 0085 D9 exx 0169 0086 E1 pop hl 0170 0087 0171 0087 C5 push bc ; save bc 0172 0088 F5 push af ; save af 0173 0089 CD 99 00 call tkr ; write to CGRAM to display B lines of the bitmap data, 0174 008C ; starting from the laction specified by the command in A 0175 008C ; for the first custom character and A+8n command for the following 0176 008C ; custom characters (n being the number of the custom character) 0177 008C ; Need it be said that A and B are Z80 registers,not the hex numbers A and B ? 0178 008C F1 pop af ; restore bc 0179 008D C1 pop bc ; restore af 0180 008E 3D dec a ; derease A to create a new set CGRAM address command 0181 008F 04 inc b ; increase the number of lines to be sent a time 0182 0090 F5 push af ; save af 0183 0091 3E 09 ld a,09h ; see if all the lines are done (i.e. see if the aanimation is completed) 0184 0093 B8 cp b 0185 0094 C8 ret z ; return if so 0186 0095 F1 pop af ; else restore af 0187 0096 C3 80 00 jp bidaha ; and go shift all custom characters one more line up 0188 0099 0189 0099 0190 0099 16 06 tkr: ld d,numofcts ; d stores the number of custom characters to be scrolled 0191 009B 0192 009B F5 other: push af ; save bc 0193 009C C5 push bc ; save af 0194 009D CD AF 00 call ilk ; send the specified number of bytes belonging to this custom character 0195 00A0 C1 pop bc ; restore bc 0196 00A1 F1 pop af ; restore af 0197 00A2 0198 00A2 C6 08 add a,8h ; a is increased by 8 to create the command to set CGRAM address to the same 0199 00A4 ; line for the next custom character 0200 00A4 ; add 8 to l so that (HL) points to the bitmap data that belongs to the new CGRAM address 0201 00A4 F5 push af 0202 00A5 3E 08 ld a,8 0203 00A7 85 add a,l 0204 00A8 6F ld l,a 0205 00A9 F1 pop af 0206 00AA 15 dec d ; see if all the custom characters got their share 0207 00AB C2 9B 00 jp nz,other ; if not, go on with the next one 0208 00AE C9 ret ; else return 0209 00AF 0210 00AF E5 ilk: push hl ; save HL 0211 00B0 CD C4 00 call sendcomA ; send the commnad in A to set the CGRAM addres 0212 00B3 CD BB 00 next: call sendchar ; send the byte in (HL) to that CGRAM location 0213 00B6 23 inc hl ; 0214 00B7 10 FA djnz next ; dec B to see is all the lines of this character are done. Loop till they are done. 0215 00B9 E1 pop hl ; restore HL 0216 00BA C9 ret ; the specified number of bytes belonging to this custom character are sent.It is time to return. 0217 00BB 0218 00BB ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 0219 00BB 0220 00BB ; ==================================================================== 0221 00BB ; Subroutine name:sendcomA & sendcom & sendcharA & sendchar 0222 00BB ; programmer:Caner Buyuktuna & Dincer Aydin 0223 00BB ; input:A or (HL) 0224 00BB ; output: 0225 00BB ; Registers altered:A 0226 00BB ; function: sendcharA sends the data in A to the LCD 0227 00BB ; sendchar sends the data in (HL) to the LCD 0228 00BB ; sendcomA sends the command in A to the LCD 0229 00BB ; sendcom sends the command in (HL) to the LCD 0230 00BB ; ==================================================================== 0231 00BB sendchar: 0232 00BB 7E ld a,(hl) ; put the data to be sent to the LCD in A 0233 00BC sendcharA: 0234 00BC C5 push bc ; save BC 0235 00BD D5 push de ; save DE 0236 00BE 1E 0B ld e,data ; 0237 00C0 C3 C8 00 jp common 0238 00C3 0239 00C3 sendcom: 0240 00C3 7E ld a,(hl) 0241 00C4 sendcomA: 0242 00C4 C5 push bc ; save BC 0243 00C5 D5 push de ; save DE 0244 00C6 1E 0A ld e,command 0245 00C8 0246 00C8 common: 0247 00C8 CD DE 00 call bfcheck ; See if the LCD is busy. If it is busy wait,till it is not. 0248 00CB ED 59 out (c),e ; Set/reset RS accoring to the content of register E 0249 00CD 16 0C ld d,write 0250 00CF ED 51 out (c),d ; reset RW pin for writing to LCD 0251 00D1 D3 00 out (paadr),a ; place data/instrucrtion to be written into portA 0252 00D3 16 0F ld d,enable 0253 00D5 ED 51 out (c),d ; enable the LCD 0254 00D7 16 0E ld d,disable 0255 00D9 ED 51 out (c),d ; disable the LCD 0256 00DB D1 pop de ; restore DE 0257 00DC C1 pop bc ; restore BC 0258 00DD C9 ret ; return 0259 00DE ; ==================================================================== 0260 00DE ; Subroutine name:bfcheck 0261 00DE ; programmer:Dincer Aydin 0262 00DE ; input: 0263 00DE ; output: 0264 00DE ; Registers altered:D 0265 00DE ; function:Checks if the LCD is busy and waits until it is not busy 0266 00DE ; ==================================================================== 0267 00DE 0268 00DE bfcheck: 0269 00DE F5 push af ; save AF 0270 00DF 0E 03 ld c,cwadr 0271 00E1 16 90 ld d,paincout 0272 00E3 ED 51 out (c),d ; make A input,C output,B output 0273 00E5 16 0D ld d,read 0274 00E7 ED 51 out (c),d ; set RW pin for reading from LCD 0275 00E9 16 0A ld d,command 0276 00EB ED 51 out (c),d ; select the instruction register 0277 00ED check_again: 0278 00ED 16 0F ld d,enable 0279 00EF ED 51 out (c),d ; enable the LCD 0280 00F1 DB 00 in a,(paadr) ; read from LCD 0281 00F3 16 0E ld d,disable 0282 00F5 ED 51 out (c),d ; disable the LCD 0283 00F7 07 rlca ; rotate A left through C flag to see if the busy flag is set 0284 00F8 DA ED 00 jp c,check_again ; if busy check it again,else continue 0285 00FB 16 80 ld d,pandcout 0286 00FD ED 51 out (c),d ; set all ports to output mode 0287 00FF F1 pop af ; restore AF 0288 0100 C9 ret 0289 0101 0290 0101 ;==================================================================== 0291 0101 ; Subroutine name:DELAY 0292 0101 ; programmer(s):Dincer Aydin 0293 0101 ; input:- 0294 0101 ; output:- 0295 0101 ; Registers altered:- 0296 0101 ; function:delay 0297 0101 ; for more delay you can add a few nops or or some junk commands using the index 0298 0101 ; registers 0299 0101 ;==================================================================== 0300 0101 E5 pdelay: push hl 0301 0102 C3 09 01 jp comdelay 0302 0105 E5 delay: push hl 0303 0106 21 22 22 ld hl,2222h 0304 0109 comdelay: 0305 0109 2D dec l 0306 010A 00 nop 0307 010B C2 09 01 jp nz,comdelay 0308 010E 25 dec h 0309 010F C2 09 01 jp nz,comdelay 0310 0112 E1 pop hl 0311 0113 C9 ret 0312 0114 0313 0114 ;==================================================================== 0314 0114 ; commands and strings 0315 0114 combegadr: 0316 0114 01 80 0C 06 .db 01h,80h,0ch,06h ; clear display,set DD RAM adress, 0317 0118 ; turn on display with cursor hidden,set entry mode 0318 0118 0319 0118 first_line: 0320 0118 564552544943 .text "VERTICAL " 0320 011E 414C20 0321 0121 000102030405 .db 00h,01h,02h,03h,04h,05h ; first 5 custom characters 0322 0127 second_line: 0323 0127 497320436F6F .text "Is Cool!" 0323 012D 6C21 0324 012F 0325 012F scrolldat: 0326 012F 8F90908E8181 .db 143,144,144,142,129,129,158,128 ; S 0326 0135 9E80 0327 0137 80808E909091 .db 128,128,142,144,144,145,142,128 ; c 0327 013D 8E80 0328 013F 808096999090 .db 128,128,150,153,144,144,144,128 ; r 0328 0145 9080 0329 0147 80808E919191 .db 128,128,142,145,145,145,142,128 ; o 0329 014D 8E80 0330 014F 8C8484848484 .db 140,132,132,132,132,132,142,128 ; l 0330 0155 8E80 0331 0157 8C8484848484 .db 140,132,132,132,132,132,142,128 ; l 0331 015D 8E80 0332 015F 0333 015F endtasm: Number of errors = 0