5,947 bytes added,
07:14, 15 March 2007 <pre>
;; This source is part of the AY-3-8912 PSG additional notes document
;; and shows that it is possible to change the output latch data
;; when the corresponding port has been set to input.
;;
;; Example 1 showed that it is possible to write any 8-bit data to the output latch
;; and read it back. The test used port B as an example.
;;
;;
;; This example will setup a initial value in the output latch, set the port to input,
;; then attempt to write to the output latch. If the data has changed, then it is possible
;; to change the output latch when the port is set to input.
;; To read the output latch, we must set the port to output mode.
;; The code can be adjusted (as indicated below) to select either port
;; A or port B.
;;
;; Note: This test relies on the following facts:
;; - the input to port B is always &ff.
;; - the input to port A is &ff if NO key is pressed
;;
;; This example is for the Amstrad CPC and also shows how
;; to read/write data from the PSG.
;;
;; This example can be assembled using Maxam or compatible assembler.
;;
;; assemble, then jump to &8000 to begin
;;
;; (c) Kevin Thacker 2001,2002
;;
;; This source is released under the GNU Public License v2.
;; this is the index of the PSG port register to test
;; (14 for PSG port A, 15 for PSG port B)
;; comment this line to test port A
;; uncomment this line to test port B
.psg_port_register equ 15
;; comment this line to test port B
;; uncomment this line to test port A
;;.psg_port_register equ 14
;; comment this line to test port A
;; uncomment this line to test port B
.psg_port_mixer_enable equ %10000000
;; comment this line to test port B
;; uncomment this line to test port A
;;.psg_port_mixer_enable equ %01000000
org &8000
;; disable interrupts
;; (do not let CPC firmware effect this test)
di
;;-------------------------------------------------------------------------------
;; set port to output
ld c,7 ;; PSG mixer register
ld a,%00111111 ;; port A input, port B output
;; disable noise for channels A,B and C
;; disable tone for channels A,B and C
or psg_port_mixer_enable
;; set port A or B (depending on setting
;; of psg_port_mixer_enable) to output
call write_reg
;;-------------------------------------------------------------------------------
;; write &ff into output latch of port. From example 1 we have proved that this
;; will store data into the output latch.
ld c,psg_port_register
ld a,&ff
call write_reg
;;-------------------------------------------------------------------------------
;; set port to input
ld c,7 ;; PSG mixer register
ld a,%00111111 ;; port A input, port B output
;; disable noise for channels A,B and C
;; disable tone for channels A,B and C
call write_reg
;;-------------------------------------------------------------------------------
;; write 10 into output latch of port. If the data is written to the output latch,
;; then it will change from &ff (the value written above) to 10 (the new value).
ld c,psg_port_register
ld a,10
call write_reg
;;-------------------------------------------------------------------------------
;; set port to output
ld c,7
ld a,%00111111
or psg_port_mixer_enable
call write_reg
;;-------------------------------------------------------------------------------
;; now read the output latch
ld c,psg_port_register
call read_reg
;; enable interrupts
ei
;; display contents of register A as hex
call print_hex_number
ret
;;-------------------------------------------------------------------------------
;; display a number as hex
;;
;; Entry Conditions:
;;
;; A = number (0-255)
;;
.print_hex_number
push af
;; transfer upper nibble into lower nibble
rrca
rrca
rrca
rrca
;; display nibble
call print_digit
pop af
;; display lower nibble
;; print a hex digit on the screen
.print_digit
;; mask off lower bits 3..0
and &f
;; convert number (0-15) to ASCII character "0","1"..."9","A"..."F"
add a,"0"
cp "0"+10
jr c,pd2
add a,"A"-"0"-10
.pd2
;; display ASCII char on screen
jp txt_output
;;------------------------------------------------
;; Read from a AY-3-8912 register
;;
;; Entry conditions:
;;
;; C = register number
;; PPI port A is assumed to be set to output.
;; PSG operation is assumed to be "inactive"
;;
;; Exit conditions:
;;
;; A = register data
;; BC corrupt
;;
;; This function is compatible with the CPC+.
.read_reg
;; step 1 - select register
;; write register index to PPI port A
ld b,&f4
out (c),c
;; set PSG operation - "select register"
ld bc,&f6c0
out (c),c
;; set PSG operation - "inactive"
ld bc,&f600
out (c),c
;; PPI port A set to input, PPI port B set to input,
;; PPI port C (lower) set to output, PPI port C (upper) set to output
ld bc,&f700+%10010010
out (c),c
;; set PSG operation - "read register data"
ld bc,&f640
out (c),c
;; step 2 - read data from register
;; read PSG register data from PPI port A
ld b,&f4
in a,(c)
;; PPI port A set to output, PPI port B set to input,
;; PPI port C (lower) set to output, PPI port C (upper) set to output
ld bc,&f700+%10000010
out (c),c
;; set PSG operation - "inactive"
ld bc,&f600
out (c),c
ret
;;------------------------------------------------
;; Write to a AY-3-8912 register
;;
;; Entry conditions:
;;
;; C = register number
;; A = data
;; PPI port A is assumed to be set to output.
;; PSG operation is assumed to be "inactive"
;;
;; Exit conditions:
;;
;; BC corrupt
;;
;; This function is compatible with the CPC+.
.write_reg
;; step 1 - select register
;; write register index to PPI port A
ld b,&f4
out (c),c
;; set PSG operation - "select register"
ld bc,&f6c0
out (c),c
;; set PSG operation - "inactive"
ld bc,&f600
out (c),c
;; step 2 - write data to register
;; write data to PPI port A
ld b,&f4
out (c),a
;; set PSG operation - "write data to register"
ld bc,&f680
out (c),c
;; set PSG operation - "inactive"
ld bc,&f600
out (c),c
ret
</pre>