;Beep+AY music driver prototype
;by utz 08'2016
;code is PD


BORDER equ #ff
AYCTRL equ #ff
AYDATA equ #bf

AY_A_FLO equ #00
AY_A_FHI equ #01
AY_B_FLO equ #02
AY_B_FHI equ #03
AY_C_FLO equ #04
AY_C_FHI equ #05
AY_NOISP equ #06
AY_MIXER equ #07
AY_A_VOL equ #08
AY_B_VOL equ #09
AY_C_VOL equ #0a
AY_ENV_F equ #0b
AY_ENV_C equ #0c
AY_ENV_S equ #0d


	org origin
	
init
	ei			;detect kempston
	halt
	in a,(#1f)
	inc a
	jr nz,_skip
	ld (maskKempston),a
_skip	
	di

	ld b,AYCTRL
	ld c,#fb
	ld d,#80
	ld a,AY_MIXER		;mixer
	out (c),a
	ld b,AYDATA
	ld a,#ff		;disable all	
	out (c),a
	
	exx
	push hl			;preserve HL' for return to BASIC
	ld (oldSP),sp
	ld hl,musicData
	ld (seqpntr),hl

;******************************************************************
rdseq
seqpntr equ $+1
	ld sp,0
	xor a
	pop de			;pattern pointer to DE
	or d
	ld (seqpntr),sp
	jr nz,rdptn0
	
	;jp exit		;uncomment to disable looping
	
	ld sp,loop		;get loop point
	jr rdseq+3

;******************************************************************
rdptn0
	ld (ptnpntr),de
rdptn
	in a,(#1f)		;read joystick
maskKempston equ $+1
	and #1f
	ld c,a
	in a,(#fe)		;read kbd
	cpl
	or c
	and #1f
	jp nz,exit


ptnpntr equ $+1
	ld sp,0
	
	pop af
	jr z,rdseq
	
	ld i,a
	
	pop hl
	ld (freq1),hl		;beeper ch1 divider
	
	pop hl
	ld (freq2),hl		;beeper ch2 div
	
	pop hl
	ld (freq3),hl		;beeper ch3 div
	
	pop hl
	ld a,h
	ld (duty1),a		;beeper duty cycle settings
	
	ld a,l
	ld (duty2),a
	
	pop af
	ld (duty3),a
	
	
	ld de,ayFreqTab
	ld c,#fd
	
	pop hl			;ay freq 1
	
	ld b,AYCTRL
	xor a			;AY_A_FLO
	out (c),a
	ld b,AYDATA
	out (c),l
	
	ld b,AYCTRL
	inc a			;AY_A_FHI
	out (c),a
	ld b,AYDATA
	out (c),h
	
	pop hl			;ay freq2
	
	ld b,AYCTRL
	inc a			;AY_B_FLO
	out (c),a
	ld b,AYDATA
	out (c),l
	
	ld b,AYCTRL
	inc a			;AY_B_FHI
	out (c),a
	ld b,AYDATA
	out (c),h
	
	pop hl			;ay freq2
	
	ld b,AYCTRL
	inc a			;AY_C_FLO
	out (c),a
	ld b,AYDATA
	out (c),l
	
	ld b,AYCTRL
	inc a			;AY_C_FHI
	out (c),a
	ld b,AYDATA
	out (c),h
	
	
	ld b,AYCTRL
	ld a,AY_MIXER		;mixer
	out (c),a
	ld b,AYDATA
	pop af
	out (c),a
	
	jp p,_skip0		;if bit 7 of control byte is set
				;buzzer envelope shape and freq follows
	ld b,AYCTRL
	ld a,AY_ENV_C
	out (c),a
	
	ld b,AYDATA
	ld a,0
	out (c),a
	
	pop hl			;H = shape, L = freq
	ld b,AYCTRL
	ld a,AY_ENV_F
	out (c),a
	ld b,AYDATA
	out (c),l
	
	ld b,AYCTRL
	ld a,AY_ENV_S
	out (c),a
	ld b,AYDATA
	out (c),h
	
	

_skip0	
	jr c,_skip1		;if bit 1 of control byte is set, skip reloading
				;env1
	pop hl
	ld (ayenv1),hl
	
	ld b,AYCTRL
	ld a,AY_A_VOL		;envelope A (envelopes generated in software)
	out (c),a
	ld a,(hl)
	ld b,AYDATA
	out (c),a
	
_skip1
	jr z,_skip2		;if bit 4 of control byte is set...
	pop hl
	ld (ayenv2),hl
	
	ld b,AYCTRL
	ld a,AY_B_VOL		;env B
	out (c),a
	ld a,(hl)
	ld b,AYDATA
	out (c),a
	
	
_skip2
	jp pe,_skip3		;if bit 2 of ctrlbyte is set...
	pop hl
	ld (ayenv3),hl
	
	ld b,AYCTRL
	ld a,AY_C_VOL		;env C
	out (c),a
	ld a,(hl)
	ld b,AYDATA
	out (c),a
	
	
_skip3


	ld (ptnpntr),sp

	xor a
	ld c,a
	ld h,a
	ld l,a
	ld ix,0
	ld iy,0	
	ex af,af'
	
;*******************************************************************************
playBeep
	
freq1 equ $+1
	ld de,0			;10
	add hl,de		;11
	
duty1 equ $+1
	ld a,0			;7
	add a,h			;4
	rl c			;8
	
freq2 equ $+1
	ld de,0			;10
	add ix,de		;15
duty2 equ $+1
	ld a,0			;7
	add a,ixh		;8
	rl c			;8
	
freq3 equ $+1
	ld de,0			;10
	add iy,de		;15
duty3 equ $+1
	ld a,0			;7
	add a,iyh		;8

	
	ld a,#f			;7
	adc a,c			;4
	ld c,0			;7
	
	and BORDER		;7
	out (#fe),a		;11
	
	ex af,af'		;4
	dec a			;4
	jp z,updateTimer	;10
	ex af,af'		;4
	
	nop			;4
	jp playBeep		;10
				;200
	
;*******************************************************************************	
updateTimer

	ex af,af'
	
	exx
	
	ld b,AYCTRL
	ld c,#fd
	ld a,AY_A_VOL
	out (c),a
	
ayenv1 equ $+1
	ld hl,0
	inc hl
	ld a,(hl)		;vol A
	cp d
	jr z,_skip1
	
	ld (ayenv1),hl
	ld b,AYDATA
	out (c),a

_skip1	
	ld b,AYCTRL
	ld a,AY_B_VOL		;vol B
	out (c),a
	
ayenv2 equ $+1
	ld hl,0
	inc hl
	ld a,(hl)
	cp d
	jr z,_skip2
	
	ld (ayenv2),hl
	ld b,AYDATA
	out (c),a

_skip2	
	ld b,AYCTRL
	ld a,AY_C_VOL		;vol C
	out (c),a
	
ayenv3 equ $+1
	ld hl,0
	inc hl
	ld a,(hl)
	cp d
	jr z,_skip3
	
	ld (ayenv3),hl
	ld b,AYDATA
	out (c),a
	
_skip3	
	exx
	
	
	
	ld a,i
	dec a
	jp z,rdptn
	ld i,a
	jp playBeep
	
;******************************************************************
exit
	ld b,AYCTRL
	ld a,AY_C_VOL		;vol C
	out (c),a
	ld b,AYDATA
	xor a
	out (c),a
	
	ld b,AYCTRL
	ld a,AY_B_VOL		;vol C
	out (c),a
	ld b,AYDATA
	xor a
	out (c),a
	
	ld b,AYCTRL
	ld a,AY_A_VOL		;vol C
	out (c),a
	ld b,AYDATA
	xor a
	out (c),a


	ld b,AYCTRL
	ld c,#fb
	ld a,AY_MIXER		;mixer
	out (c),a
	ld b,AYDATA
	ld a,#ff		;disable all	
	out (c),a

oldSP equ $+1
	ld sp,0
	pop hl
	exx
	ei
	ret
;******************************************************************
ayFreqTab
	include "freqtab.asm"
	
musicData
	include "music.asm"
