;Pink Music 
;A program for the PAIA 8700
; by Bob Yannes and Steve Witham

BYT1		=$00AC
BYT2		=$00AD
BYT3		=$00AE
BYT4		=$00AF
SHREG		=$00B0
KEY			=$00B1
DELTA		=$00B2
NUMBIT		=$00B3
NOTESTAT	=$00B4
TOTAL		=$00B5 ;-00B8
OLD			=$00B9 ;-00BC
SCALE		=$00BD ;-00DC
COUNTEMP	=$00DD
RANDOM		=$0100 ;-011F	

DISP		=$0820
DAC			=$0900
QUASH		=$09FC

ONBITS		=$C0 ;Constant
LIMIT		=$04 ;Constant
VOXNUM		=$04 ;Constant
TEMPO		=$20 ;Constant

	org $0000
BPOINT 		
	jmp PINK 		;BREAKPOINT TRAP.
PINK
	ldx #$FF		;INITIALIZE
	txs				;STACK POINTER.
	cld 			;SET HEX MODE.
	stx KEY 		;INITIALIZE KEY.
KEYLOOP
	lda KEY			;GET KEY...
	sta DISP		;AND SHOW IT.
	inc KEY			;NEXT KEY,
	eor KEY			;GET PATTERN OF CHANGED KEY BITS...
	sta DELTA		;AND STORE IT.
	ldx #VOXNUM		;GET # OF VOICES,
	ldy #0			;INITIALIZE RND # COUNTER.
VOXLOOP
	lda #0			;CLEAR THE
	sta TOTAL-1,x	;RUNNING SUM FOR VOICE #X.
	lda #8			;INITIALIZE BIT COUNTER...
	sta NUMBIT		;AND STORE IT.
	lda DELTA		;GET CHANGED BIT PATTERN.
RNDLOOP
	rol a			;PREPARE TO TEST LEFTMOST BIT.
	pha				;SAVE SHIFTED PATTERN.
	bcc ADDEM		;BIT DIDN'T CHANGE--KEEP OLD RND #.
PICK
	jsr RNDGEN		;BIT DID CHANGE--GET NEW RND #.
	and #7			;TRUNCATE IT.
	cmp #LIMIT+1	;# OUT OF RANGE?
	bcs PICK		;YES, GO GET ANOTHER.
	sta RANDOM,y	;NO STORE IT IN LOCATION Y.
ADDEM
	lda RANDOM,y	;GET THE RANDOM # FROM LOCATION Y.
	clc				;PREPARE TO ADD.
	adc TOTAL-1,x	;ADD IT TO THE RUNNING SUM FOR VOICE #
	sta TOTAL-1,x	;STORE THE RUNNING SUM (PINK #) FOR VO
	iny				;NEXT RND 
	pla				;GET SHIFTED PATTERN BACK.
	dec NUMBIT		;NEXT BIT.
	bne RNDLOOP		;DONE ALL BITS? IF NO, GO DO NEXT.
	dex				;NEXT VOICES.
	bne VOXLOOP		;DONE ALL VOICES? IF NO, GO DO NEXT.
	lda #ONBITS		;PLAY NOTES WITH
	jsr PLAY		;GATE & GLIDE FORCED ON.
	lda #0			;PLAY GATE & GLIDE ONLY
	jsr PLAY		;ON SUSTAINED NOTES.
	ldx #VOXNUM		;GET # OF VOICES,
SCALOOP
	ldy TOTAL-1,x	;GET PINK # FOR VOICE #X
	lda SCALE,y		;USE IT AS POINTER FOR SCALE TABLE.
	sta OLD-1,x		;STORE QUANTIZED NOTE FOR VOICE #X.
	dex				;NEXT VOICE.
	bne SCALOOP		;DONE ALL VOICES? IF NO, GO DO NEXT.
	beq KEYLOOP		;BRANCH ALWAYS.
PLAY
	sta NOTESTAT	;STORE GATE & GLIDE STATUS.
	lda #TEMPO		;INITIALIZE
	sta COUNTEMP	;TEMPO COUNTER.
TEMPLOOP
	ldx #VOXNUM		;GET # OF VOICES.
UPDATE
	lda OLD-1,x		;GET NOTE TO BE PLAYED.(OLD NOTE) VOICE
	ldy TOTAL-1,x	;GET NEW PINK # (POINTER) FOR VOICE #X.
	cmp SCALE,y		;OLD NOTE = NEW NOTE?
	bne CHOP		;NO, GO CLEAR.
	ora #ONBITS		;YES FORCE GATE & GLIDE ON.
CHOP
	ora NOTESTAT	;CLEAR GATE & GLIDE UNLESS FORCED.
	sta DAC			;LET DAC SETTLE...
	sta QUASH-1,x	;SEND IT TO QUASH CHANNEL #X...
	ldy #$25		;AND DELAY
SETTLE
	dey				;UNTIL QUASH
	bne SETTLE 		;SETTLES.
	dex				;NEXT VOICE.
	bne	UPDATE		;DONE ALL VOICES? IF NO, GO DO NEXT.
	dec COUNTEMP	;1 LESS TEMPO DELAY.
	bne TEMPLOOP	;DONS TEMPO DELAY? IF NO, DO IT ALL AG
	rts				;RETURN
	
RNDGEN
	tya				;SAVE
	pha				;Y.
	ldy BYT1
	lda BYT2
	sty BYT2		;BYT2=OLD BYT1.
	ldy BYT3
	sta BYT3		;BYT3=OLD BYT2.
	lda BYT4		;ACCUM.=OLD BYT4.
	sty BYT4		;BYTA=OLD BYT3.
	sty SHREG		;SHREG=OLD BYT3.
	asl SHREG		;SHIFTED ONCE
	rol a			;INTO A.
	sta BYT1
	asl SHREG		;TWICE.
	rol a
	asl SHREG		;THRICE.
	rol a
	asl SHREG		;FOURCE (FOURCE?).
	rol a
	eor BYT1		;EXOR WITH ONCE-SHIFTED BITS.
	sta BYT1		;BACK INTO BYT1 AS NEW RANDOM #.
	pla				;GET Y
	tay				;BACK.
	lda BYT1		;LOAD NEW RANDOM NUMBER.
	rts				;RETURN.
