;; This source is part of the AY-3-8912 PSG additional notes document
;; and shows:
;;
;; when a PSG register is written to, and then read back, some bits will always
;; be set to 0.
;;
;; 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

;; list first 14 registers 
ld b,14
;; start at register 0
ld c,0
.loop
push bc

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

push bc
;; write 0x0ff to the register (attempt to set all bits to "1")
ld a,&ff
call write_reg
pop bc

;; read actual register's contents
call read_reg

ei

;; display number in register A as binary
call print_binary_number

;; display a new-line
ld a,10
call txt_output
ld a,13
call txt_output

pop bc
djnz loop
ret

;;-------------------------------------------------------------------------------
;; display a number as a 8-digit binary number 
;;
;; Entry Conditions:
;;
;; A = number (0-255)
;;
;; Exit Conditions:
;;
;; A,B corrupt

.print_binary_number
;; 8 digits in binary number
ld b,8
.pbn1
;; transfer bit 7 into carry
rlca
push af
;; convert to ASCII
;; 0-> "0" and 1-> "1"
adc a,"0"
;; display digit on the screen
call txt_output

pop af
djnz pbn1
ret

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