	def	BUFFSIZE   6	  // 64   for circular buffers, not used here
	def	SYNCDEL    0x30   // # of cycles before first output byte
	def	SYNCLEN    0x130  // # of cycles of 'ZA' output sync.

// changed delay in isr8 from 0xd0 to 0x60  on 10/28/96
// DSPOS2: switch from AR6/7 to AR0/1 for misc..
//         Do fancy Cbits update in Rout rather than ISR8
//  AR0 bits 7-10 is A op. page register... always zero here.
//  AR1 bits 7-10 is Dest. page register... always zero here.
//  AR0 points to CS lookup table  (0x60 to 0x78) was AR7 in DSPOS
//  AR1 is used as a temp pointer  (0x00 to 0x7f) was AR6 in DSPOS
//  AR2 is the LEFT input pointer  (0x200 to 0x23f for size 64 buff)
//  AR3 is the RIGHT input pointer (0x300 to 0x33f for size 64 buff)
//  SYNCLEN (sync length) used to be 0x50/0x54
//  SYNCDEL (sync delay) used to be 0x20/0x21
//  changed IRQ1 from short to long irq.. seems to fix sporadic spdif glitch

	porg    0
        jmp     Start
        nop                     // no vector 1

	jmps	lout		// irq 0 vector 2  Left audio out
	jmps	rout		// irq 0 vector 3  Right audio out
	jmps	rin		// irq 1 vector 4  Right audio in
	jmps	lin		// irq 1 vector 5  Left audio in
	jmps	hin             // irq 2 vector 6  Host port in
	jmps	hout		// irq 2 vector 7  Host port out
	jmps	isr8            // irq 3 vector 8  Long interrupt

	porg    0x10
Start:
// setup the control registers
	ld	0, CR           // disable all interrupts
	mvd     IniCM1, CM1     // *** adjusted for a 6.144 clock
	mvp	0x9001, CM0	  // disable DAC  +400 for 192speed
// 4fc92 for 44.1
// 0405 for real time adjust with freq generator
// 2401 10/2 for 19khz
// 2001 9/2 for 21khz
// 1401 6/2 for 32khz
// 1402 6/3 for 48khz
// 2c02 12/3 for pass thru... from 8412
// 3005 13/6 for 44.3Khz
// a409 works 42/10 -> 22.8khz
// a415 works 42/22 -> 50.3khz

	rep	0xd0		// long wait before checking PLL
	jmps	wait

WaitForLock:
	and     LINT, 1, Temp     // wait for the PLL to stablize
	jmp     WaitForLock, NE

	mvp	0x000060,AR0      // AR0 points to the CS data
	mvp	0x180000, XMTCN   // resync CS    no DADR
	mvp	0xe00000, ASIC    // *** setup serial in
	mvp	0x00c800,SCPCN    // +004000 IRIEN   +008000 ORIEN
	mvp	0x1c0000, XMTCN   // resync CS    no DADR
	mvp	0x000002,LINT     // 20 for byte clk, 8 for cbl, 2 for PLL

	mvp	0x0238,AR2     // left input pointer (buff x200-x2ff)
	mvp	BUFFSIZE,MAR2
	mvp	0x0338,AR3     // right input pointer (buff x300-x3ff)
	mvp	BUFFSIZE,MAR3


	mvd	Lucnt, Lutmp   // number of samples between left U bit clicks

	mvp	0, Rst          // clear the reset..
	mvp	1,Hoincr        // start the count up for host output
	mvp	0,Hocnt
	mvp	houtz,Honxt
	mvp	hinc,Hinxt          // set the host input counter to zero

	ld      0x8f, CR  // Enable all interrupts (except debug)

	mvd	XMTCN,Temp      // needed to clear the interrupt.

Loop:
	jmp     Loop

//
// rin (Right audio in).. used to be a short interrupt.
//

rin:
	mvd	ASI,*AR3        // irq 1 vector 4  Right audio in
	reti

//
// lin (Left audio in).. used to be a short interrupt.
//

lin:
	mvd	ASI,*AR2        // irq 1 vector 5  Left audio in
	reti

//
//  rout (RIGHT OUT) about 33 cycles  plus up to 16 more if entire Cbit stuff
//  rout-rout1: move data in/out, handles sending Start_ID on Ubits.
//  rout2: check for output sync to start playing (PSYNC=0)
//  rout3: PSYNC=1, normal output.. adjust volume for analog out
//  rout4: PSYNC=2, inverted output.. adjust volume for analog out
//  rout5: PSYNC=3, difference mode that Tom hates so much
//  rout6: recording sync count.. if hocnt reaches SYNCDEL, pull REQ.
//  rout7-rout9: Fancy C-bits update, used to be in ISR8
//

rout:
	mvd	*AR3, Rsampi  // input
	mvd	Rsamp, XMT    // SPDIF output
	mvd	Rsampa, DAC   // DAC output
	ld	0x8f, CR

	mvd	Lsampi, ACC       // subtract  Left from Right sample
	sub	Rsampi, ACC, Y3   // store difference signal...

	mvd     Lutmp, ACC           // has Lutmp reached Lucnt?
	sub     Lucnt, ACC, Temp
	jmp	rout1, NE            // if not then abort..
	and	Rucnt, 0xffff, Temp  // Are we in the middle of
	jmp	rout1, EQ            // a Start_ID?
	mvd	Rucnt, ACC           // if so, decrement the Rucnt (which
	sub	One, ACC, Rucnt      // start at 300) and continue with
	jmp	rout2                // the U bit still on during the R chan.
rout1:
	mvp	0x1c0000, XMTCN      // turn OFF the U bit.. no DADR
rout2:
	and	Psync, 3, Temp   // if PSYNC = 0, then disable output
	jmp	rout3, NE
	mvp	0,Rsamp
	mvp	0,Rsampa

	and	Rsampi, 0xffff00, Stemp   //  only top 16 MSBs
	sub	Stemp, 0x7a6100, Temp    //  check for 'za' sync marker
	jmp	rout6, NE                // if not the sync then keep going
	mvp	1, Psync       // L=L and R=R so set PSYNC to 1
	mvp	0, Rsampi

	jmp	rout6            // continue at 6..

rout3:
	sub	Psync, 1, Temp   //  if PSYNC = 1, normal output...
	jmp	rout4, NE
	mvd	Rsampi, Rsamp    // send Right sample on Right output.
	mvd	Rsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Rsampa    // DAC output
	jmp	rout6            // continue at 6..

rout4:
	sub	Psync, 3, Temp   //  if PSYNC isn't 3, it must be 2.
	jmp	rout5, EQ
	mvd	Lsampi, Rsamp    // if 2, swap channels, send Left to Right.
	mvd	Rsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Rsampa    // DAC output
	jmp	rout6            // continue at 6...

rout5:
	mvd	Y3, Rsamp        // if PSYNC = 3, send difference (L-R).
	mvd	Rsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Rsampa    // DAC output

rout6:                             // Ah.. and finally...
	sub	Hocnt, SYNCDEL, Temp  // if Hocnt > SYNCDEL
	jmp	rout7, LT          // then skip...
	mvd	Hoincr, ACC        // else if Hocnt < (SYNCDEL+1)
	add	Hocnt, ACC, Hocnt  // Hocnt += 1
	sub	Hocnt, SYNCDEL+1, Temp  // if Hocnt just REACHED SYNCDEL+1
	jmp	rout7, NE          // then send out dummy to SCPOUT..
	mvp	0,SCPOUT           // get the ball rolling!

rout7:                             // not done yet, lets do fancy Cbits
	and	LINT, 0x10, Temp   // only do this every 8th time
	jmp	rout9, EQ	   // If Byte Clock is on,
	and	Lntold, 0x10, Temp
	jmp	rout9, NE	   // and was NOT on last time..

	and	LINT, 4, Temp  // try to force Cbits in sync!
	jmp	rout8, EQ      // if CBL is on
	and	Lntold, 4, Temp
	jmp	rout8, NE      // and was NOT on last time
	mvp	0x000061,AR0   // reset the pointer..

rout8:
	mvd	*AR0+,XMTCS     // send out the next 8 C bits from the table
	mvp	0x1c0000, XMTCN // *** added to enable TX.. this is goofy no DADR
	mvd	XMTCN,Temp      // needed to clear the interrupt.
	sub	AR0,0x78,Temp   // check to see if we're at the end
	jmp	rout9,NE         // of the table, if so reset.
	mvp	0x000060,AR0

rout9:
	mvd	LINT, Lntold
	reti

//
//  lout (LEFT OUTPUT).. about 34 cycles.
//  lout-lout1: move data in/out, handles DAT-HEAD click on Ubits.
//  lout2: check for output sync to start playing (PSYNC=0)
//  lout3: PSYNC=1, normal output.. adjust volume for analog out
//  lout4: PSYNC=2, inverted output.. adjust volume for analog out
//  lout5: PSYNC=3, difference mode that Tom hates so much
//  lout6-lout8: handle the IRQ count and pull IRQ if needed.
//

lout:
	mvd	*AR2, Lsampi  // input
	mvd	Lsamp, XMT    // SPDIF output
	mvd	Lsampa, DAC   // DAC output
	ld	0x8f, CR

	and	Lucnt, 0xffff, Temp  // is Lucnt zero?
	jmp	lout1,EQ             // if so, skip over U bit stuff.
	mvd	Lutmp, ACC
	sub	One, ACC, Lutmp      // Lutmp -= 1
	jmp	lout1,NE             // have we reached zero?
	mvp	0x5c0000, XMTCN      // if so, turn ON U bit!  no DADR
	mvd     Lucnt, Lutmp         // and restart the counter..
	jmp	lout2                // next time on Rout, handle Start_ID

lout1:
	mvp	0x1c0000, XMTCN      // turn OFF U bit.. no DADR
lout2:
	and	Psync, 3, Temp       // if PSYNC = 0, disable output
	jmp	lout3, NE
	mvp	0,Lsamp
	mvp	0,Lsampa

	and	Lsampi, 0xffff00, Stemp    // only top 16 MSBs
	sub	Stemp, 0x7a6100, Temp     //  check for 'za' sync marker
	jmp	lout6, NE                 // if not the sync then keep going
	mvp	2, Psync        // L=R and R=L so set PSYNC to 2
	mvp	0, Lsampi

	jmp	lout6                // continue at 6

lout3:
	sub	Psync, 1, Temp   // if PSYNC = 1, normal output
	jmp	lout4, NE
	mvd     Lsampi, Lsamp    // send Left sample during Left output..
	mvd     Lsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Lsampa    // DAC output
	jmp	lout6            // continue at 6.

lout4:
	sub	Psync, 3, Temp   // if PSYNC isn't 3, must be 2.
	jmp	lout5, EQ
	mvd     Rsampi, Lsamp    // if 2, swap channels.. Right to Left.
	mvd     Lsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Lsampa    // DAC output
	jmp	lout6            // continue at 6.

lout5:
	mvd     Y3, Lsamp        // if PSYNC = 3, send difference (L-R).
	mvd     Lsamp, ACC
	mpy	Vol,ACC,ACC      // multiply by volume (0x400000 is norm)
	shf	2, Lsampa    // DAC output

lout6:                           // and here at the end..
	and	Irqtmp, 0xffffff, Temp
	jmp	lout8, EQ        // if Irqtmp is zero, don't send IRQ

	mvd	Irqtmp, ACC
	sub	One, ACC, Irqtmp // Irqtmp =- 1
	jmp	lout7, NE
	mvd	Irqcnt, Irqtmp   // if we reached zero, restart counter.

lout7:
	sub	Irqtmp, 5, Temp  // is 5 < Irqtmp
	jmp	lout8, LT        // ie: if Irqtmp > 5, then skip

	add     IniCM0, 0x10000, CM0     //  if Irqtmp < 6, turn on XF (IRQ!)
	reti

lout8:
	mvd     IniCM0, CM0     // otherwise, turn off XF (no IRQ..)
	reti

//
//  hin (Host port input state machine)
//  hinc: state 0, wait for command byte
//  hind1: state 1, wait for MSB of data
//  hind2: state 2, wait for mid byte of data
//  hind3: state 3, wait for LSB of data and store 24 bit data.
//  hinend: from hinc, if c=255 -> end command, start host out state machine.
//


hin:
	mvp	ACC, Sacc           // save ACCumulator
	mvd	Hinxt,ACC           // Get next routine from state machine
	jmp	ACC

hinc:
	mvd	SCPIN, Hicmd
	mvd	Sacc, ACC
	and	Hicmd, 255, Temp  // ignore if 0
	jmp	hinc2, EQ
	sub	Hicmd, 255, Temp  // signal end if cmd is 255
	jmp	hinend, EQ
	mvp	hind1, Hinxt
hinc2:
	reti

hind1:
	mpyl	SCPIN,0x10000,Hidat
	mvp	hind2, Hinxt
	mvd	Sacc, ACC
	reti

hind2:
	mpyl	SCPIN,0x100,Hitmp    // we don't want to MPYL into ACC
	mvd	Hitmp, ACC           // ... that would mess up LSbits
	add	Hidat,ACC,Hidat
	mvp	hind3, Hinxt
	mvd	Sacc, ACC
	reti

hind3:
	mvd	SCPIN,ACC    // get LSB of 'data'
	add	Hidat,ACC,Hidat

	mvp	hinc, Hinxt
	mvd	Sacc, ACC

	and	Hicmd, 0x80, Temp   // if bit 7 of command is zero, skip!
	jmp	hind32, EQ

	and	Hicmd, 0x7f, AR1    // take lower 7 bits of CMD
	mvd	Hidat, *AR1         // and put the 24bit data in that memory
hind32:
	reti

hinend:
	mvp	0,Hocnt       // hmmmm.... start host output stuff
	mvp	houtz,Honxt
	sub	Rst, 1, Temp
	jmp     Start, EQ
	reti

//
//  hout... about 8, but this happens 2x per channel.
//  houtz: send 'z' for sync
//  houta: send 'a' for sync  'za' sync happens from hocnt=SYNCDEL to SYNCLEN
//  hout00: send zeros (hocnt=SYNCLEN to SYNCLEN+4.. actually only 4 bytes.
//  houtl1: send MSB of left sample
//  houtl2: send LSB of left sample
//  houtr1: send MSB of right sample
//  houtr2: send LSB of right sample (then goto houtl1 again)
//

hout:
	mvp	ACC, Sacc           // save ACCumulator
	mvd	Honxt,ACC           // Get next routine from state machine
	jmp	ACC

houtz:
	sub	Hocnt, SYNCDEL+1, Temp   // if Hocnt hasn't reached SYNCDEL+1
	jmp	houtz2, GT               // then skip it..
	mvp	0x7a,SCPOUT	// send 'z' sync
	mvp	houta,Honxt
	add	Hocnt, 1, Hocnt
houtz2:
	mvd	Sacc, ACC
	reti

houta:
	mvp	0x61,SCPOUT	// send 'a' sync
	mvp	houtz,Honxt
	mvd	Sacc, ACC
	sub	Hocnt, SYNCLEN, Temp    // time to break out of 'za' sync?
	jmp	houta2, NE
	mvp	hout00,Honxt
houta2:
	reti

hout00:
	mvp	0,SCPOUT	// send a zero right and left for Tom.
	mvd	Sacc, ACC
	add	Hocnt, 1, Hocnt
	sub	Hocnt, SYNCLEN+4, Temp
	jmp	hout02, NE
	mvp	houtl1, Honxt
hout02:
	reti

houtl1:
	mvd	Lsamp, Hotmp       //  send MSB of Left sample
	mpy	Hotmp,0x100,SCPOUT
	mvp	houtl2,Honxt
	mvd	Sacc, ACC
	reti

houtl2:
	mpy	Hotmp,0x10000,SCPOUT  // send LSB of (left) sample.
	mvp	houtr1,Honxt
	mvd	Sacc, ACC
	reti

houtr1:
	mvd	Rsamp, Hotmp       //  send MSB of Right sample
	mpy	Hotmp,0x100,SCPOUT
	mvp	houtr2,Honxt
	mvd	Sacc, ACC
	reti

houtr2:
	mpy	Hotmp,0x10000,SCPOUT   // send LSB of (Right) sample
	mvp	houtl1,Honxt
	mvd	Sacc, ACC
	reti

//
//  isr8... only used now if DSP loses PLL lock.. mute DAC and wait.
//

isr8:
	mvp	0x9001, CM0	  // disable DAC

	rep	0x60		// long wait before checking PLL
	jmps	wait

WaitForLock1:
	and     LINT, 1, Temp     // wait for the PLL to stablize
	jmp     WaitForLock1, NE

//	mvp     0xb001, CM0       // enable DAC

	mvp	0,Hocnt         // start the countdown for host output
	mvp	houtz,Honxt
	mvp	hinc,Hinxt          // set the host input counter to zero
	mvd	XMTCN,Temp      // needed to clear the interrupt.

	reti


wait:
	rep	0x3fff		// long wait!!
	nop                     // just do nothing 16384 times..
	ret                     // that's 64 audio sample pairs


	dorg    0     // there can be 128 variables here.
	dw	0            // 128
Vol:	dw	0x400000
Lsamp:  dw      0
Rsamp:	dw	0
Lsampi:	dw	0
Rsampi:	dw	0
Lsampa:	dw	0
Rsampa:	dw	0
IniCM0:	dw	0x00b001     // 136
IniCM1:	dw	0x001402     // 137
Lucnt:	dw	1440  // 1440 for 48, 1323 for 44.1, 1920 for 32lp
Rucnt:	dw	300          // 139
Lutmp:	dw	1
Y3:	dw	0
Irqcnt:	dw	2048         // 142
Bozo:	dw	0	// 143
Irqtmp:	dw	5
	dw	0
Psync:	dw	1            // 146
Hinxt:	dw	0
Hicmd:	dw	0
Hidat:	dw	0x400000
Hitmp:	dw	0
Hotmp:	dw	0
Hoincr:	dw	0            // 152
Hocnt:	dw	0
Honxt:	dw	0
Sacc:	dw	0
Sshad:	dw	0
Rst:	dw	0        // 157
Lntold:	dw	0
Zero:	dw	0
One:	dw	1
Temp:	dw      0
Stemp:	dw	0

	dorg	0x060
	dw      0x003000  // should be 003000
	dw      0xc00f00  // should be 000300
	dw      0x000000  // should be 000000
	dw      0x000c00  // 000c00 for 48, 000f00 for 32, 000000 for 44.1
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000
	dw	0x000000


