home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------
- ; This program tests the DRC-II card. It tests all 4 banks of 64 k.
- ;
- ; Since this program uses the ASMLIB library, it is easily modified and
- ; added to. All the rouines and code have been written as simply and as
- ; linearly as possible to allow mods and additions.
- ;
- ; Written R.C.H. 19/01/84
- ; Last Update R.C.H. 19/01/84
- ;----------------------------------------------------------------
- ;
- ; ASMLIB library routine names
- ;
- extrn prolog,nibasc,pdacc,dispatch,inline
- extrn quit,listout,consout,crlf,clear
- extrn pdde,delay,cst,bell,cie,coe,caps
- extrn randinit,rand8,pmenu,phde,hexasc,phacc
- extrn xyinline,setxy,atoasc
- extrn ionum,tname,pstring,cursor,pstr
- extrn setatt,ramwbt,rambpt
- extrn lzb,nolzb,blzb,clkrd
- ;
- maclib z80
- ;
- ; Memory test variables
- ;
- t9t1 equ 50000 ; interrupts iteration size
- t9t2 equ 500 ; port addressing iteration size
- t9t3 equ 1 ; walking bit iteration size
- t9t4 equ 1 ; barber pole test iteration size
- t9t5 equ 05 ; ldir / lddr iteration test size
- ctc0 equ 08ch
- ctc1 equ ctc0+1
- ctc2 equ ctc0+2
- ctc3 equ ctc0+3
- bnk$max equ 3 ; test banks 00,01,02,03
- mstart equ 00000h ; test memory ending at
- mend equ 0bfffh ; test memory starting at
- ;
- super$start:
- call prolog
- jmp start
- nop
- nop ; make on an 8 address boundary
- ;
- ; This is the interupt interrupt table that must start on an address
- ; boundary of 8
- ;
- vectors:
- dw int0
- dw int1
- dw int2
- dw int3 ; interrupt address vectors
- ;
- start:
- ; Initializations
- ; Clear all the ram storage areas used by this test
- lxi h,sram
- mvi m,00
- mov e,l
- mov d,h
- inx d ; bump for the destination
- lxi b,eram-sram-1 ; the size
- ldir
- ;
- mvi a,bnk$max ; indicate maximum bank
- sta t9$bnk
- call sel$bnk ; force a select and display of bank 0
- ;
- ; shift initialized random number seed to the real seed.
- lxi h,iseed
- lxi d,seed
- lxi b,6
- ldir ; shift the initialized seed
- ;
- ;----------------------------------------------------------------
- ; The DRC-II is tested by the following things.
- ;
- ; 1) Fast interrupts from a CTC on SBC-800. This can cause problems
- ; if DRC-II decoding and refresf circuitry is faulty.
- ; 2) Port decoding by quickly writing to ports F0..FE to check for
- ; a faulty port decoder chip of excess glitches on the bus.
- ; 3) Walking bit test up memory and down memory.
- ; 4) Barber pole memory test up and down memory.
- ; 5) Test with a repeated number of LDIR Z-80 instructions.
- ; 6) Test with a number of LDDR instructions.
- ;
- ; These tests are meant to be the most demanding that the DRC-II can
- ; ever experience. This is meant to show up marginal boards.
- ;----------------------------------------------------------------
- ;
- call clear
- call t9$overlay ; display the overlay
- lxi d,140bh
- sded cur$cur ; save the current cursor address
- call cursor ; set up
- mvi a,'*'
- call dispatch
- xra a
- sta t9$no ; save the test number as 00
- ;
- test9$start:
- lded cur$cur
- call cursor ; reset to the current cursor position
- call do$test9 ; do the actual test
- ;
- ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; This section must bump the number of loops counter
- ; then must display it on the screen.
- ; When all tests have been done for a bank, the next bank must be selected
- ; and dislayed on the screen.
- ; After this it must move the test indicator star to the next
- ; test in the loop.
- ;
- lded cur$cur
- push d ; save for later use
- mov a,d ; get X value
- adi 16 ; point to the loop counter x value
- mov d,a ; save back
- call cursor ; set it up
- ; Get the loop value, bump, save, write
- lda t9$no ; get test 9 test number, 0..4
- lxi h,t9$loops ; point to the loop counters
- mov e,a
- mvi d,00 ; use t9$no to index into loop values
- dad d
- dad d ; Now HL -> an individual loop value
- mov e,m
- inx h
- mov d,m
- inx d ; Bump the value
- mov m,d ; save
- dcx h
- mov m,e ; save all
- ; DE = loops done
- call pdde ; print as a decimal
- ;
- ; Move the test indicator star.
- pop d ; restore cursor address
- call cursor ; set up
- mvi a,' '
- call dispatch ; clear it
- ; Go to the next test position.
- lded cur$cur
- mov a,e ; get y address
- cpi 19 ; last ??
- jrz t9$restart
- inr e
- inr e ; points to next test
- ; Bump the test number
- lda t9$no
- inr a ; indicate next test in progress
- jr t9$restart$over
- t9$restart:
- lxi d,140bh
- xra a ; re-set to test number 00
- t9$restart$over:
- sta t9$no ; save the test number
- push psw
- sded cur$cur ; save the address
- call cursor ; set the cursor
- mvi a,'*'
- call dispatch
- ; Select the next bank to be tested
- pop psw
- ora a ; bank zero again ??
- cz sel$bnk ; select next bank then
- ; Now check for the end of tests.
- ;
- call chk$abrt
- jmp test9$start
- ;
- chk$abrt:
- call cst
- rz ; 00 = No character there
- call cie ; Else we get the typed character
- pop h ; clear the stack
- ;
- call inline
- db 0dh,0ah,'Bye$'
- jmp 0e000h ; jump to monitor warm start
- ;
- ; This routine must select a memory bank in the range 0..3. The bank
- ; number is saved in t9$bnk and used for display when an error happens
- ; also the number is used to increment to get the actual bank number.
- ;
- sel$bnk:
- lxi d,01906h ; line 6, col 25
- call cursor ; set the cursor up
- ; Now get the last bank number and send it.
- lda t9$bnk ; check if > maximum
- cpi bnk$max ; too far ??
- jrnz sel$bnk1
- mvi a,0ffh ; use bank 00 next time
- sel$bnk1$
- inr a ; get the next bank for testing
- sta t9$bnk
- out 0ffh ; send it
- call lzb
- call phacc ; display the bank number
- call blzb ; display standard
- ret
- ;
- ; This is the actual memory testing section
- ; This decodes the test that must be done then jumps to it.
- ; A return is done from the test if all is well else the test
- ; will jump to test9$fail for an error.
- ;
- do$test9:
- lxi h,test9$table
- lda t9$no ; get the test number
- mov e,a
- mvi d,00
- dad d
- dad d ; Now HL -> and address to go to
- mov e,m ; get low address
- inx h
- mov d,m ; get high address
- push d ; put address on stack
- ret ; goto the address
- ;
- test9$table: ; A table of routine addresses
- dw test9$test1 ; Interrupts
- dw test9$test2 ; Port decoding
- dw test9$test3 ; Walking Bit
- dw test9$test4 ; Barber pole
- dw test9$test5 ; LDIR / LDDR
- ;
- ;----------------~~~~~~~~~~~~~~~~----------------
- ; The memory test routines
- ;~~~~~~~~~~~~~~~~----------------~~~~~~~~~~~~~~~~
- ;
- ; Do an interrupt response test. This initializes the
- ; SBC-800 CTC channel 3 for fast interrupts then counts for
- ; the iteration size to complete the test. When done the interrupts
- ; are disabled.
- ; If no SBC-800 there then this test returns immediately.
- ;
- ;
- test9$test1:
- ; Fill memory with a random value.
- lxi d,seed
- call randinit ; initialize random number generator
- lxi d,seed
- call rand8
- lhld mem$start
- mov m,a ; send the byte into ram
- mov e,l
- mov d,h ; get a copy
- inx d ; point to next byte in ram
- lbcd mem$size ; get memory size
- ldir ; fill memory.
- ;
- ; Now we start the Interrupt test by enabling interrupts on CTC channel 3
- ;
- ; Set up interrupt vectors.
- lxi h,t9t1 ; get iteration size
- shld int$count ; clear the interrupt counter
- lxi d,vectors
- mov a,e ; low 8 bits of address
- out ctc0 ; send. This is accepted as a vector
- mov a,d ; high 8 bits
- stai ; put into interrupt register of Z80
- ; Initialize the CTC for interrupts on channel 3 only
- mvi a,085h ; timer mode with interrupts
- out ctc3 ; in timer mode, clk is from the bus
- mvi a,20 ; count down value
- out ctc3 ; put in the value
- im2 ; enable interrupts NOW
- ei
- ;
- ; Perform wait till int$count = 00 and exit then.
- ;
- t9t1$loop:
- lhld int$count
- mov a,h
- ora l ; H = L = 0 ??
- jnz t9t1$loop
- jmp stop$ctc
- ;
- ; These are the interrupt service routines
- int0:
- int1:
- int2:
- call stop$ctc ; stop the CTC
- call inline ; display a message now
- db 0dh,0ah,'SBC-800 Illegal Interrupt$'
- ret ; return to the main loop
- ;
- int3:
- lhld int$count
- dcx h
- shld int$count
- ; Check if this is the end of the cycle
- mov a,l
- ora h ; does H = L = 00 ??
- jz stop$ctc
- ; If not a stop then keep on.
- ei ; re-enable interrupts
- reti ; return from interrupt
- ;
- stop$ctc: ; Clear the CTC
- di ; stop interrupts
- call dumret
- mvi a,2
- out ctc3 ; stop the timer NOW
- mvi a,45 ; tell it a time constant follows
- out ctc3
- mvi a,13 ; the constant
- out ctc3 ; this starts it counting ONLY
- ei ; re-enable interrupts for any pending
- ;
- ; Since we have stopped the CTC , now we can check if memory got corrupted
- ; while the interrupts were enabled and running.
- ;
- lhld mem$start
- lbcd mem$size ; load registers
- dcx b ; check 1 byte less
- ;
- t1$chk$loop:
- mov a,m ; get current byte
- inx h ; point to next byte
- cmp m ; does m(HL) = m(HL+1) ??
- jnz test9$fail ; on a fail, print again.
- dcx b
- mov a,c
- ora b ; does B = C = 00 ??
- jnz t1$chk$loop ; loop till BC = 0
- ; Clear the check symbol
- ret
- ;
- dumret:
- reti ; clear pending CTC status
- ;
- ;
- ; ~~~~~~~~~~~~~~~~----------------~~~~~~~~~~~~~~~~
- ; This test does many output instructions to port addresses close to the
- ; bank select port of the DRC-II in the hope that this will trigger the
- ; DRC-II to glitch and de-select itself. This is usually caused by faulty
- ; port decoding logic.
- ; ports user are f0..fe
- ; ----------------~~~~~~~~~~~~~~~~----------------
- ;
- test9$test2:
- lxi h,t9t2 ; port iteration size
- test9$test2$loop:
- call chk$abrt ; look for a key press
- push h ; save loop counter
- mvi b,0eh ; number of ports
- mvi c,0f0h ; start port address
- port$loop:
- call send$port ; send port (HL) times
- call chk$abrt ; look for an exit command
- inr c
- djnz port$loop
- ; Check for end of tests
- pop h ; restore counter
- dcx h
- mov a,l
- ora h ; see if H = L = 0 ???
- jrnz test9$test2$loop
- ret ; keep on till done
- ;
- ; Now the subroutine
- send$port:
- push b ; save
- mvi b,255 ; loop size
- outir ; send m(HL) -> p(C) for (B) times
- pop b
- ret
- ;
- ; This is the walking bit test. This is taken from the
- ; ASMLIB library which is a routine by Leventhals' book 'Z-80 Subroutines'
- ;
- test9$test3:
- lxi b,t9t3 ; number of loops
- ; the loop. Load registers, call the routine, exit if an error.
- test9$test3$loop:
- push b ; save it
- call chk$abrt
- lded mem$start ; start of memory
- lhld mem$end ; end of memory
- call ramwbt ; do the test
- pop b
- jc test9$fail ; error exit if a failure.
- dcx b
- mov a,c
- ora b ; does B = C = 00 ????
- jrnz test9$test3$loop
- ret ; do a return when all loop pass
- ;
- ; ~~~~ Barber Pole Test ~~~~
- ;
- ; This is the barber pole test. This is taken from the
- ; ASMLIB library which is a routine by Leventhals' book 'Z-80 Subroutines'
- ;
- test9$test4:
- lxi b,t9t4 ; number of loops
- ; the loop. Load registers, call the routine, exit if an error.
- test9$test4$loop:
- push b ; save it
- call chk$abrt
- lded mem$start ; start of memory
- lhld mem$end ; end of memory
- call rambpt ; do the test
- pop b
- jc test9$fail ; error exit if a failure.
- dcx b
- mov a,c
- ora b ; does B = C = 00 ????
- jrnz test9$test4$loop
- ret ; do a return when all loops pass
- ;
- ; ~~~~ LDIR / LDDR test. ~~~~
- ; This moves a byte up and down the total available memory and then checks
- ; is for accuracy. On each iteration the byte is loaded from the random number
- ; generator so that a wide range of test values is checked.
- ; Each iteration does an LDIR then a check, an LDDR then a check.
- ;
- test9$test5:
- lxi b,t9t5 ; get the number of loops
- t9t5$loop:
- push b ; save
- ; Do the LDIR test first
- lxi d,seed ; get a random number
- call rand8 ; A = random number
- lbcd mem$size ; get size of memory to test
- dcx b ; one less
- lhld mem$start ; get start address
- mov m,a ; load the seed
- mov e,l
- mov d,h ; copy into DE for the destination
- inx d ; bump by one to propogate up ram
- ldir ; do the move.
- mov e,a ; save check value
- call chk$abrt
- lhld mem$start
- lbcd mem$size
- dcx b ; one byte less
- ; Now the check of the byte in memory. Use a Z-80 auto check.
- mvi a,'I'
- call coe
- mvi a,8
- call coe
- t9t5$loop2:
- call chk$abrt ; abort ????
- mov a,e ; restore checking value
- cci ; check m(HL) = A
- jnz t9t5$error
- mov e,a ; save
- mov a,c
- ora b ; does B = C = 0 ??
- jnz t9t5$loop2
- ;
- ; **** Now do the LDDR checking. This is done in a similar way ****
- ;
- lxi d,seed ; get a random number
- call rand8 ; A = random number
- lbcd mem$size ; get size of memory to test
- ; dcx b ; one less
- lhld mem$end ; get start address
- mov m,a ; load the seed
- mov e,l
- mov d,h ; copy into DE for the destination
- dcx d ; deduct one to propogate down ram
- lddr ; do the move.
- mov e,a ; save the check value
- call chk$abrt
- lhld mem$start
- lbcd mem$size
- dcx b ; one byte less to test
- ;
- mvi a,'D' ; indicate a Decrementing test
- call coe
- mvi a,8 ; backspace
- call coe
- ; Now the check of the byte in memory. Use a Z-80 auto check.
- t9t5$loop3:
- call chk$abrt
- mov a,e ; restore checking value
- cci ; check m(HL) = A
- jnz t9t5$error
- mov e,a ; save
- mov a,c
- ora b ; does B = C = 0 ??
- jnz t9t5$loop3
- ; Decrement the iteration counter and check for end of this test.
- pop b ; restore iteration counter
- dcx b ; one less loop to do
- mov a,c
- ora b ; check if the iteration is done
- jnz t9t5$loop
- ; Clear old I or D when here
- mvi a,' ' ; blank it
- call coe
- ret ; exit if all done
- ;
- ;
- t9t5$error:
- pop b ; restore stack
- jmp test9$fail
- ;
- ; If a test fails then this routine is called. It increments the
- ; fail counter, displays the value and also the address where the fail
- ; occurred. This is the error section.
- ;
- ; On calling here HL -> error address in memory
- ;
- test9$fail:
- push h ; save the failure address
- ; Index to the fail column
- lded cur$cur ; get current cursor address
- mov a,d ; get X address
- adi 23 ; add 23 to get to the fail column
- mov d,a
- call cursor ; get there
- ; Now get the number of fails, bump, save, display
- lxi h,t9$fails ; point to start of fail table
- lda t9$no ; get the test number
- mov e,a
- mvi d,00 ; load an index
- dad d
- dad d ; now HL -> fail number for this test
- mov e,m
- inx h
- mov d,m ; now DE = number of fails
- inx d ; bump
- mov m,d
- dcx h
- mov m,e ; saved now
- ; Now display it
- call pdde ; display as a decimal.
- ; Now we need to display the address where the fail occurred
- call inline
- db ' $' ; Use spaces to get there
- pop d ; restore HL -> DE for display
- call phde ; display it as hex
- ; Now we display the bank where it happened.
- call inline
- db ' bank ($'
- lda t9$bnk ; get the bank number
- call lzb
- call phacc ; print it
- call nolzb
- mvi a,')'
- call coe
- ;
- ; After all this, bump the total number of fails, save and then display.
- lxi d,0d15h ; col 13, line 21
- call cursor
- lhld t9$total$fails
- inx h
- shld t9$total$fails
- xchg
- call pdde ; display as a decimal
- call blzb ; go back to standard blanking
- ret ; all done
- ;
- ;----------------------------------------------------------------
- ; Major section to display the test 9 overlay that has all the parameters
- ; etc on it. This also displays the time start and a few other things to
- ; improve the niceness of the program.
- ;----------------------------------------------------------------
- ;
- t9$overlay:
- lxi d,t9$menu
- call pmenu ; display the text in one go
- ; Put a line under the double line test headings
- lxi d,010ah ; col 1 , line 10
- call cursor
- mvi b,61 ; do 61 times
- mvi a,'-' ; send this character
- call pstr ; print a string of characters entry
- ;
- ; Now display the iteration size values
- call blzb ; select standard blanking
- lxi d,1c0bh ; X=28, Y=11
- call cursor
- lxi d,t9t1 ; first test size display
- call pdde ; display as a decimal
- ;
- lxi d,1c0dh ; X=28, Y=13
- call cursor
- lxi d,t9t2 ; second test size display
- call pdde ; display as a decimal
- ;
- lxi d,1c0fh ; X=28, Y=15
- call cursor
- lxi d,t9t3 ; third test size display
- call pdde ; display as a decimal
- ;
- lxi d,1c11h ; X=28, Y=17
- call cursor
- lxi d,t9t4 ; fourth test
- call pdde
- ;
- lxi d,1c13h ; X=28, Y=19
- call cursor
- lxi d,t9t5 ; fourth test
- call pdde
- ;
- ; Put a line under the tests, this places them in a table
- lxi d,0114h
- call cursor
- mvi a,'-'
- mvi b,61
- call pstr
- ;
- ; Display the time now
- lxi d,03004h
- call cursor
- lxi d,tim$buf ; locate a time string buffer
- call clkrd
- ;
- call nolzb ; display time without lzb
- lda hrs
- ani 03fh ; mask off top bits
- call phacc
- mvi a,':' ; a spacer
- call dispatch
- lda mins
- call phacc
- mvi a,':'
- call dispatch
- lda secs
- call phacc
- ; Now get memory start address and save
- lxi d,01a04h
- call cursor
- lxi d,mstart
- sded mem$start ; save the start address
- call phde ; display without LZB
- ; Get the memory end address, display, save then calculate the memory size
- ; to be tested.
- lxi d,01a05h
- call cursor
- ; Load 0bfffh as the memory end address
- lxi d,mend ; memory end
- sded mem$end
- call phde
- ; Now the memory size
- ; lxi h,0bffh ; save as the memory size
- lxi h,mend - mstart ; memory start - end
- shld mem$size ; save the memory size
- ;
- call blzb
- ret
- ;
- iseed db 5,89,90,198,5,245
- ;
- t9$menu:
- db 26,01,'Memory Test - ROM Version$'
- db 21,04,'From$'
- db 23,05,'To$'
- db 36,04,'Time Start$'
- db 38,05,'Time End$'
- db 21,06,'Bank$'
- db 03,08,'Test$'
- db 16,08,'Current Iterations Loops Fails Fail Address$'
- db 18,09,'Test Size$'
- db 01,11,'Interrupts$'
- db 01,13,'Port Addressing$'
- db 01,15,'Walking Bit$'
- db 01,17,'Barber Pole$'
- db 01,19,'LDIR / LDDR$'
- db 01,21,'Total Fails$'
- db 01,23,'Press Any Key To Quit$'
- db 0ffh
- ;
- dseg
- ;
- ; Simple data atorage areas. Use the D switch in the linker
- ; to set these after assembly.
- ;
- sram: ; start of ram
- ;
- seed: db 0,0,0,0,0,0 ; random number seed value
- t9$no: db 00 ; test 9 section #
- t9$bnk: db 00 ; memory board bank number
- t9$loops:
- db 00,00 ; section loop counter
- db 00,00 ; section loop counter
- db 00,00 ; section loop counter
- db 00,00 ; section loop counter
- db 00,00 ; section loop counter
- ;
- t9$fails:
- db 00,00 ; number of fails
- db 00,00 ; number of fails
- db 00,00 ; number of fails
- db 00,00 ; number of fails
- db 00,00 ; number of fails
- ;
- t9$total$fails:
- db 00,00 ; total number of fails
- ;
- mem$start:
- db 00,00
- ;
- mem$end:
- db 00,00
- ;
- mem$size:
- db 00,00
- ;
- int$count:
- db 00,00 ; number of interrupt cycles
- ;
- cur$cur:
- db 00,00 ; current cursor position
- ;
- tim$buf:
- db 00,00,00,00
- hrs db 00
- mins db 00
- secs db 00
- ;
- eram: ; end of ram
- ;
- ;
- end
-
-