;
; BOMB SOUND EFFECT FOR COP800.
; THE SERIAL INPUT (SI) AND TIMER I/O (TIO) PINS
; MUST BE TIED TO THE SERIAL OUTPUT (SO) PIN.
; OUTPUT IS ON SO.
; USE 20MHz XTAL, 1uS INSTR CYCLE TIME FOR THIS DEMO.
;
; WRITTEN BY: JERRY LEVENTER
; DATE:       OCTOBER 4, 1989
;
; EDITTED MAY 11, 1994 - REVISED FOR NEW ASSEMBLER (ASMCOP v4.2) 

	.TITLE BOMB8
	.CHIP	820
	.SECT MAIN,ROM,ABS=0
;
	PORTGC	=   0D5 	; PORT G CONFIGURATION
	SIOR	=   0E9 	; SIO SHIFT REGISTER
	TMRLO	=   0EA 	; TIMER LOW BYTE
	TMRHI	=   0EB 	; TIMER HIGH BYTE
	TAULO	=   0EC 	; TIMER REGISTER LOW BYTE
	TAUHI	=   0ED 	; TIMER REGISTER HIGH BYTE
	CNTRL	=   0EE 	; CONTROL REGISTER
	PSW	=   0EF 	; PSW REGISTER
	TRUN	=   4
	TPND	=   5
	BUSY	=   2
	GIE	=   0
;
; ****  EXPLOSION REGISTERS AND CONSTANTS  ****
;
; SOME OF THE FOLLOWING REGISTERS USE THE DRSZ 
; TEST AND MUST THEREFORE BE INITIALIZED TO AT 
; LEAST "1" .
;
	LASTR	=	0F6	; CONTROL LAST TONE
	  LAST	=	002	; LAST TONE CONSTANT
	  LAST2 =	004	; EXIT CONSTANT
	EXITR	= 	0F7	; TOTAL TIME TILL EXIT
	  EXIT	=	010 	; EXIT CONSTANT
	RNGVAL	=	0F3	; HOLDS CURRENT RING VALUE
	TCNTR	=	0F8	; TIME FOR EACH TONE FREQ
	  TCNT	=	0A	; CONSTANT VALUE
	LUPREG	=	0F9	; TONE COUNT INSIDE RING
	LUPCNT	=	0FA	; TONE COUNT OUTSIDE RING (VARIABLE)
	FLAG	=	000	; FLAG REGISTER FOR SUBROUTINES
;
	TVALO	=   0FF
	TVALHI	=   01A	
;
; **** WHISTLE REGISTERS AND CONSTANTS ****
;
	WSLO	=	02F	; TIMER VALUES
	WSLHI	=	000
	MINFQ	=	0FF	; FINAL (LOW FREQ) TIMER VALUE
;
	FCNTR	=	0F0	; FREQUENCY COUNT REGISTER
	  FCNT	=	000
;
;------------------------------------------------------------------------------
MAIN:	
	LD	SP,#02F 	; DEFAULT INITIALIZATION OF SP
	SBIT	0,FLAG		; SET SUBROUTINE FLAG
				; 1 = WHISTLE	
				; 0 = EXPLOSION
	JSR	WHISTLE
MAIN2:	RBIT	0,FLAG
	JSR	BOMB
	JP	.		; *** STOP HERE OR REPEAT ***
;-----------------------------------------------------------------------------
;
BOMB:	LD	PORTGC,#030	; CONFIGURE "SO" AS OUTPUT
	LD	CNTRL,#08A	; SK = DIV BY 8, PWM ON 
	LD 	PSW,#011	; ENABLE TIMER INTERRUPT
	LD	TMRLO,#TVALO	; INITIALIZE TIMER
	LD	TMRHI,#TVALHI
	LD	TAULO,#TVALO
	LD	TAUHI,#TVALHI
	LD	LASTR,#LAST	; INITIALIZE LAST TONE FLAG
	LD	EXITR,#EXIT 	; INITIALIZE EXIT COUNT
	LD	TCNTR,#TCNT	; INITIALIZE TONE COUNT
	LD	LUPCNT,#10	; INITIALIZE FIRST TONE FREQUENCY
	RBIT	1,FLAG		; RESET LAST TONE FLAG BIT
;	
NOISE:	SC			;
	LD	B,#RNGVAL	; POINT TO RING VALUE
	LD	[B+],#0FF	; INIT TO ALL ONE'S
	LD	[B],#0FF
	SBIT	TRUN,CNTRL	; START THE TIMER 
SHIFT:	RBIT	BUSY,PSW
	X	A,SIOR		; RANDOM # TO SIO
	SBIT	BUSY,PSW
	LD	A,LUPCNT	; RESTORE EXTRACTION COUNT
	X	A,LUPREG
;    
; -------------------------------------------------------------
;    RING COUNTER (17 STAGE)
;
;    THIS IS A SEVENTEEN STAGE RING COUNTER (LINEAR
;    FEEDBACK SHIFT REGISTER) WITH THE RRC COMMAND.
;    THE COUNTER'S 14th AND 17th STAGES THROUGH AN             
;    EXCLUSIVE-OR SERVE AS THE FEEDBACK FUNCTION. 
;    THIS 14,17 RING COUNTER BREAKS DOWN INTO         
;    1 CYCLE OF [(2 ** 17) - 1] COUNTS.  SINCE THE EXCLUSIVE OR
;    OCCURS AFTER THE ROTATE, IT IS THE 15th AND CARRY
;    STAGES THAT ARE XOR'D (BIT 2 AND CARRY).
;
;    BEFORE ROTATE:	14   	17
;    AFTER ROTATE:	15	CARRY   
;
;	CARRY BIT = STAGE ONE
;	LOW ORDER BIT = STAGE 17 
; -------------------------------------------------------------     
RING:	LD	A,[B]		; GET RANDOM #		
	RRC	A		; ROTATE UPPER BYTE
	X	A,[B-]
	LD	A,[B]
	RRC	A		; ROTATE LOWER BYTE
	X	A,[B+]
	LD	A,#004		; PERFORM XOR	
	AND	A,[B]
	IFEQ	A,#000
	JP	TSTLUP
	IFC
	JP	RC
	SC
	JP	TSTLUP
RC:	RC
TSTLUP:	DRSZ	LUPREG		; POINT TO UPPER BYTE
	JP	RING		; EXTRACT THIS # ?
	LD      A,[B]   	; NO, KEEP ROTATING
	JMP	SHIFT		; YES
;
; ****	INTERRUPT ROUTINE ****
;
	.=	0FF
	IFBIT	TPND,PSW	; TEST FOR EXIT
	JP	TMOUT
	JP	.		; ERROR
;
TMOUT:	RBIT	TRUN,CNTRL	; STOP TIMER
	IFBIT	0,FLAG		; BRANCH TO ROUTINE
	JMP	WSINT		; SET = WHISTLE, RESET = EXPLOSION
;
	LD	B,#LUPCNT
	DRSZ	TCNTR		; TEST FOR NEW TONE 
	JP	NXT		; NO, DON'T INCREMENT LUPCNT
	JP	NEWF		; YES
NXT:	SBIT	4,PSW		; ENABLE TIMER INTRRUPT
	RBIT	5,PSW		; RESET	TIMER PENDING FLAG
	LD	B,#RNGVAL	; POINT TO RANDOM #
	SBIT	TRUN,CNTRL	; RESTART TIMER
	RETI			; RETURN TO RING COUNTER
NEWF:	DRSZ	EXITR		; DO LAST TONE ?
	JP	NF		; NO
	DRSZ	LASTR		; IS LAST TONE DONE ?
	JP	LST		; NO
	JP	NLST		; YES, RETURN TO MAIN 
LST:	LD	EXITR,#LAST2	; LENGTHEN THE LAST TONE
	SBIT	1,FLAG		; SET LAST TONE FLAG
	JP	NF2	
NLST:	LD	A,SP		; ** RESTORE STACK POINTER **
	ADD	A,#002		; ** AND RETURN TO MAIN    **
	X	A,SP
	RET
;
NF:	IFBIT	1,FLAG		; LAST TONE ?
	JP	NF2		; YES, DON'T INCREMENT LUPCNT
	LD	A,[B]		; NEW TONE
	ADD	A,#04		; INCR EXTRACT COUNT (LUPCNT)
	X	A,[B]
NF2:	LD	TCNTR,#TCNT	; REINITIALIZE TONE TIME
	JMP 	NXT
; -----------------------------------------------------------
WSINT:	IFBIT	5,FCNTR		; READY FOR NEW FREQUENCY ?
	JP	TM		; YES
	LD	A,FCNTR		; NO, INCREMENT COUNT
	INC	A
	X	A,FCNTR
	RETSK			; NO, RETURN TO WHISTLE
TM:	LD	FCNTR,#FCNT	; RESET NEW FREQUENCY COUNT
	LD	B,#TAULO	; POINT TO AUTORELOAD REG
	LD	A,[B]		; CHANGE FREQUENCY
	IFEQ	A,#MINFQ	; TIMER = MIN FREQ ?
	JP	OVER
	INC	A
	X	A,[B]		; STORE FREQ IN AUTO RELOAD
	RETSK
OVER:	LD	A,SP		; ** RESTORE STACK POINTER **
	ADD	A,#002		; **  AND RETURN TO MAIN   **
	X	A,SP
	RET
;------------------------------------------------------------------------------
WHISTLE:LD	PORTGC,#008	; TIO PIN (G3) AS OUTPUT
	LD	CNTRL,#0A2	; PWM WITH TIO TOGGLE, 8Tc
	LD	FCNTR,#FCNT	; INIT FREQ COUNTER
	LD	TMRLO,#WSLO	; WHISTLE VALUE FOR TIMER
	LD	TMRHI,#WSLHI
	LD	TAULO,#WSLO
	LD	TAUHI,#WSLHI
;
BEGIN:	LD	PSW,#011	; ENTI, GIE = 1, TPND = 0
	SBIT	TRUN,CNTRL	; START TIMER
	JP	.		; LOOP UNTIL TIMER INTERRUPT
	JP	BEGIN		; RETURN HERE FROM INTERRUPT
	.END
