;; This source is part of the AY-3-8912 PSG additional notes document
;; and shows the operation of the output latch for port A or B.
;;
;; The code can be adjusted (as indicated below) to select either port
;; A or port B.
;;
;; This example is for the Amstrad CPC and also shows how
;; to read/write data from the PSG.
;;
;; Note: This test relies on the following facts:
;; - the input to port B is always &ff. This means it is possible to use port B to store any 8-bit
;;   data.
;; - the input to port A is &ff if NO keys are pressed
;;   this means that it is possible to use port A to store any 8-bit data if NO keys are pressed.
;;
;; This example can be assembled using Maxam or compatible assembler.
;;
;; assemble, then jump to &8000 to begin
;;
;; (c) Kevin Thacker, 2001-2002
;; This source code 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

;; firmware function to display ASCII character on the screen at the current
;; text cursor location
.txt_output		equ &bb5a

;; disable interrupts
;; (do not let CPC firmware effect this test)
di

;;------------------------------------------------
;; set PSG 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 11 into PSG port output latch

ld c,psg_port_register	;; PSG port register
ld a,11					;; data
call write_reg

;;------------------------------------------------
;; read PSG port output latch

ld c,psg_port_register	;; PSG port register
call read_reg
;; Z80 register A now contains the data from the PSG port output latch

;; 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