;; This source is part of the AY-3-8912 PSG additional notes document
;; and shows:
;;
;; when port B is set to input, the input data to the port is 0x0ff.
;;
;; This code is designed for port B only. 
;;
;; 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.

org &8000


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

;; firmware function to set x,y coordinate of text cursor			
.txt_set_cursor	equ &bb75

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

;;-------------------------------------------------------------------------------
;; set port B to input
ld c,7								;; PSG mixer register
ld a,%00111111						;; port A input, port A output
									;; disable noise for channels A,B and C
									;; disable tone for channels A,B and C
call write_reg

;; enable interrupts
ei


;;-------------------------------------------------------------------------------
;; loop and display register 15 contents on the screen.

.loop
;; set position of text cursor
ld h,1
ld l,1
call txt_set_cursor

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

;; read PSG register 15
ld c,15
call read_reg

ei

;; display contents of register A in hex on the screen
call print_hex_number
jp loop


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