Beispiel #1
0
/*
 * Helper function to write aic23 registers
 */
static void set_aic23_register(MCBSP_Handle hMcbsp, Uint16 reg, Uint16 val) {
	val &= 0x1ff;
	//LOG_printf(&LOG0, "Transmit data: %d", (reg<<9) | val);
	while(!MCBSP_xrdy(hMcbsp));
	MCBSP_write(hMcbsp, (reg<<9) | val);
	while (MCBSP_xrdy(hMcbsp));
}
void codec_reg_set(uint16_t num, uint16_t val)
{
	val &= 0x1ff;
	while(!MCBSP_xrdy(mcbspControlHandle));
	MCBSP_write(mcbspControlHandle, (num << 9) | val);
	while(!MCBSP_xrdy(mcbspControlHandle));
}
Beispiel #3
0
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	int out = 0;
	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	//create temporary variable of left channel for processing
	short tempF = temp.channel[1];
	//scale up input value to Q-26
	int tempScaled = tempF << 11;

	int i;

	out = tempScaled;

	//reset the cyclical buffer sub-index
	if(n >= 3){
		n = 0;
	}

	//calculate the output of each second order section and pass it to the next
	for(i = 0; i < 11; i++)
	{
		out = lordBiquad(out, i);
	}
	n++;

	//downscale the output back to Q-15 and cast as a short before writing to the codec
	temp.channel[0] = (short)(out >> 11);

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
Beispiel #4
0
main()
{
	LOG_printf(&myLog, "main begin");
	/*DSK6713_LED_toggle(0);
	DSK6713_LED_toggle(1);
	DSK6713_LED_toggle(2);
	DSK6713_LED_toggle(3);*/
	hMcbsp = 0;

	
	CSL_init();  
	
	/* Configure McBSP0 and AIC23 */
	Config_DSK6713_AIC23();
	
	/* Configure McBSP1*/
	hMcbsp = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
    MCBSP_config(hMcbsp, &datainterface_config);
    
	/* configure EDMA */
    config_EDMA();

    /* finally the interrupts */
    config_interrupts();

    //MCBSP_start(hMcbsp, RRST, 0xffffffff);									//	EIGEN!!!:	Start Field: Recieve
    MCBSP_start(hMcbsp, MCBSP_RCV_START | MCBSP_XMIT_START | MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220);		//	EIGEN!!!:	Start Field: Recieve
    																			//				Es gibt auch noch MCBSP_SRGR_START (start sample Rate Generator) und MCBSP_SRGR_FRAMESYNC (start frame sync. generation)
    MCBSP_write(hMcbsp, 0x0); 	/* one shot */
	LOG_printf(&myLog, "main end");

	//DSK6713_LED_toggle(2);
} /* finished*/
Beispiel #5
0
// for out to Left and Right channels
void output_sample(int out_data) {

	short CHANNEL_data;

    // clear data structure
	AIC_data.uint=0;

    // 32-bit data -->data structure
	AIC_data.uint=out_data;


	/********************************************************************************
	 *  The existing interface defaults to right channel. To default instead to the
	 * left channel and use output_sample(short), left and right channels are swapped
	 * In main source program use LEFT 0 and RIGHT 1 (opposite of what is used here)
	 ********************************************************************************/
	// swap left and right channels
	CHANNEL_data=AIC_data.channel[RIGHT];
	AIC_data.channel[RIGHT]=AIC_data.channel[LEFT];
	AIC_data.channel[LEFT]=CHANNEL_data;

	// if ready to transmit
	if (poll) while(!MCBSP_xrdy(DSK6713_AIC23_DATAHANDLE));

	// write/output data
	MCBSP_write(DSK6713_AIC23_DATAHANDLE,AIC_data.uint);
}
Beispiel #6
0
main()
{

	CSL_init();  
	
	/* Configure McBSP0 and AIC23 */
	Config_DSK6713_AIC23();
	
	/* Configure McBSP1*/
	hMcbsp = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
    MCBSP_config(hMcbsp, &datainterface_config);
    
	/* configure EDMA */
    config_EDMA();

	DSK6713_LED_off(0);
	DSK6713_LED_on(1);
	DSK6713_LED_off(2);
	DSK6713_LED_on(3);
    /* finally the interrupts */
    config_interrupts();

    MCBSP_start(hMcbsp, MCBSP_XMIT_START | MCBSP_RCV_START, 0xffffffff);		// Start Audio IN & OUT transmision
    MCBSP_write(hMcbsp, 0x0); 	/* one shot */

    configComplete = 1;
    //t_reg = DSK6713_rget(DSK6713_MISC);
    //t_reg |= MCBSP1SEL;				// Set MCBSP1SEL to 1 (extern)
    //DSK6713_rset(DSK6713_MISC,t_reg);

} /* finished*/
Beispiel #7
0
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	int out = 0;
	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	//create temporary variable of left channel for processing
	short tempIn = temp.channel[1];
	//Shift input signal to a Q-26 number
	int tempScaled = tempIn << 11;

	//initialize storage variable for calculating intermediate values
	//sum will be a Q-26 number
	int sum = 0;

	//loop variables
	int k, i;
	//reset cyclical buffer index
	if(n >= 11)
	{
		n = 0;
	}


	//calculate intermediate values

	//iterate to sum the last 18 intermediate values*A_coefficients
	for(k = 1; k<L; k++){
		i = n - k;
		if(i < 0){
			i += L;
		}

		//coefficients are Q-12 and intermediate values are Q-14 resulting in adding Q-26 numbers to sum
		sum += ((DEN[k])*(w[i]));
	}
	//subtract sum(Q-26) from the current scaled reading(Q-26) and scale down to Q-14 to store as an intermediate value
	w[n] = (tempScaled - sum) >> 12;

	//iterate to sum the current and last 18 intermediate values*B_coefficients
	for(k=0;k<L;k++){
		i = n - k;
		if(i < 0){
			i += L;
		}
		//scale down intermediate values to avoid output overflow
		out += (NUM[k]*(w[i] >> 10));
	}

	n++;

	//scale down the output and cast as a short before writing to the codec
	temp.channel[0] = (short)(out >> 8);

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	float out = 0;
	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	//create temporary variable of left channel for processing
	float tempF = temp.channel[1];
	float sum = 0;

	//perform scaling => [-1, 1)
	tempF /= 32768;

	int k, i;
	if(n >= 11)
	{
		n = 0;
	}


	//calculate intermediate values

	//iterate to sum the last 18 intermediate values*A_coefficients
	for(k = 1; k<L; k++){
		i = n - k;
		if(i < 0){
			i += L;
		}
		sum += DEN[k]*w[i];
	}
	//subtract sum from the current scaled reading
	w[n] = tempF - sum;
	if(w[n] > maxIntermediate){
		maxIntermediate = w[n];
	}
	if(w[n] < maxMin){
		maxMin = w[n];
	}

	//iterate to sum the current and last 18 intermediate values*B_coefficients
	for(k=0;k<L;k++){
		i = n - k;
		if(i < 0){
			i += L;
		}
		out += NUM[k] * w[i];
	}

	n++;

	//rescale and output
	out *= 32768;
	temp.channel[0] = (short)out;

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
Beispiel #9
0
/*
 *  initEdma() - Initialize the DMA controller.  Use linked transfers to
 *               automatically transition from ping to pong and visa-versa.
 */
void initEdma(void)
{
    /* Configure transmit channel */
    hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET);  // get hEdmaXmt handle and reset channel
    hEdmaReloadXmtPing = EDMA_allocTable(-1);               // get hEdmaReloadXmtPing handle
    hEdmaReloadXmtPong = EDMA_allocTable(-1);               // get hEdmaReloadXmtPong handle

    gEdmaConfigXmt.dst = MCBSP_getXmtAddr(hMcbsp1);         // set the desination address to McBSP1 DXR

    gXmtChan = EDMA_intAlloc(-1);                           // get an open TCC
    gEdmaConfigXmt.opt |= EDMA_FMK(OPT,TCC,gXmtChan);       // set TCC to gXmtChan

    EDMA_config(hEdmaXmt, &gEdmaConfigXmt);                 // then configure the registers
    EDMA_config(hEdmaReloadXmtPing, &gEdmaConfigXmt);       // and the reload for Ping

    gEdmaConfigXmt.src = EDMA_SRC_OF(gBufferXmtPong);       // change the structure to have a source of Pong
    EDMA_config(hEdmaReloadXmtPong, &gEdmaConfigXmt);       // and configure the reload for Pong

    EDMA_link(hEdmaXmt,hEdmaReloadXmtPong);                 // link the regs to Pong
    EDMA_link(hEdmaReloadXmtPong,hEdmaReloadXmtPing);       // link Pong to Ping
    EDMA_link(hEdmaReloadXmtPing,hEdmaReloadXmtPong);       // and link Ping to Pong

    /* Configure receive channel */
    hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);  // get hEdmaRcv handle and reset channel
    hEdmaReloadRcvPing = EDMA_allocTable(-1);               // get hEdmaReloadRcvPing handle
    hEdmaReloadRcvPong = EDMA_allocTable(-1);               // get hEdmaReloadRcvPong handle

    gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1);         // and the desination address to McBSP1 DXR

    gRcvChan = EDMA_intAlloc(-1);                           // get an open TCC
    gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan);       // set TCC to gRcvChan

    EDMA_config(hEdmaRcv, &gEdmaConfigRcv);                 // then configure the registers
    EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv);       // and the reload for Ping

    gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong);       // change the structure to have a destination of Pong
    EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv);       // and configure the reload for Pong

    EDMA_link(hEdmaRcv,hEdmaReloadRcvPong);                 // link the regs to Pong
    EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing);       // link Pong to Ping
    EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong);       // and link Ping to Pong

    /* Enable interrupts in the EDMA controller */
    EDMA_intClear(gXmtChan);
    EDMA_intClear(gRcvChan);                                // clear any possible spurious interrupts

    EDMA_intEnable(gXmtChan);                               // enable EDMA interrupts (CIER)
    EDMA_intEnable(gRcvChan);                               // enable EDMA interrupts (CIER)

    EDMA_enableChannel(hEdmaXmt);                           // enable EDMA channel
    EDMA_enableChannel(hEdmaRcv);                           // enable EDMA channel

    /* Do a dummy write to generate the first McBSP transmit event */
    MCBSP_write(hMcbsp1, 0);
}
void sendData(uint32_t * ptr)
{
	while(!MCBSP_rrdy(mcbspDataHandle));
	MCBSP_write(mcbspDataHandle, *ptr);
	asm(" nop");
	asm(" nop");
	asm(" nop");
	asm(" nop");
	asm(" nop");
	asm(" nop");
}
Beispiel #11
0
unsigned char spiTransferByte(unsigned char arg_byte)
{
     unsigned char i;
     MCBSP_write(C55XX_SPI_hMcbsp, arg_byte);
     while (!MCBSP_xrdy(C55XX_SPI_hMcbsp));
     i = MCBSP_read(C55XX_SPI_hMcbsp);
#if 0
     if (arg_byte == 0 && i == 0) hpprintf ("*"); else
	  hpprintf("(%x)=%x\n", arg_byte, i);
#endif
     return i;
}
Beispiel #12
0
//for output from right channel
void output_right_sample(short out_data) {

    // clear data structure
	AIC_data.uint=0;

	// data from Right channel -->data structure
	AIC_data.channel[RIGHT]=out_data;

	// if ready to transmit
	if (poll) while(!MCBSP_xrdy(DSK6713_AIC23_DATAHANDLE));

	// output right channel
	MCBSP_write(DSK6713_AIC23_DATAHANDLE,AIC_data.uint);
}
Beispiel #13
0
unsigned char if_spiSend(hwInterface *iface, euint8 outgoing)
{
	unsigned char r;

/*	while((*(unsigned volatile long*)McBSP0_SPCR & 0x20000)==0);
	*(unsigned volatile char*)McBSP0_DXR=outgoing;
	while(((*(unsigned volatile long*)McBSP0_SPCR & 0x2)==0));
	r=*(unsigned volatile char*)McBSP0_DRR; */
	
	while(!MCBSP_xrdy(iface->port->hBsp));
	MCBSP_write(iface->port->hBsp,outgoing);
	while(!MCBSP_rrdy(iface->port->hBsp));
	r=MCBSP_read(iface->port->hBsp);
	
	return(r);
}
static void set_aic23_register(MCBSP_Handle hMcbsp,unsigned short regnum, unsigned short regval)
{
	/* Programmierung erfolgt so, dass in B[15:9] die Registernummer steht und
		in B[8:0] die zu schreibenden Daten */

    /* zur Sicherheit maskieren auf 9 Bit */
    regval &= 0x1ff;

    //regnum &= 0x07f;
    
    /* warten */
    while (!MCBSP_xrdy(hMcbsp));
    
    /* schreiben */
    MCBSP_write(hMcbsp, (regnum << 9) | regval);
}
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	int out = 0;
	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	//create temporary variable of left channel for processing
	short tempF = temp.channel[1];
	int sum = 0;

	int k, i;
	if(n >= 11)
	{
		n = 0;
	}

	//iterate to sum the last 18 intermediate values*A_coefficients
	for(k = 1; k<L; k++){
		i = n - k;
		if(i < 0){
			i += L;
		}
		sum += DEN[k]*w[i];
	}
	//subtract sum from the current scaled reading
	w[n] = tempF - sum;

	//iterate to sum the current and last 18 intermediate values*B_coefficients
	for(k=0;k<L;k++){
		i = n - k;
		if(i < 0){
			i += L;
		}
		out += NUM[k] * w[i];
	}

	n++;

	temp.channel[0] = (short)out;

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
Beispiel #16
0
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	float out = 0;
	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	//temp.channel[1] = temp.channel[0];

	//create temporary variable of left channel for processing
	float tempF = temp.channel[1];

	//perform scaling => [-1, 1)
	tempF /= 32768;

	//wait for buffer to fill up with samples before filtering
	//buffer is full, now perform filter
	int i,j;
	if(n >= ORDER)
	{
		n = 0;
	}

	x[n] = tempF;

	//Calculate filter gain
	for(i = 0; i < ORDER; i++){
		j = n - i;
		if(j < 0){
			j += ORDER;
		}
		out += B[i] * x[j];
	}
	n++;

	//rescale and output
	out *= 32768;
	temp.channel[0] = (short)out;

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
Beispiel #17
0
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	if(pingFlag == 1 && lflag == 1)
	{
		PONG[pongIndex].re = temp.channel[1];
		PONG[pongIndex].re /= 32768;
		PONG[pongIndex].im = 0;
		temp.channel[0] = (short)outputPING[pongIndex];
		pongIndex++;

		if(pongIndex >= FFT_LENGTH - (ORDER - 1))
		{
			pongFlag = 1;
			pongIndex = 0;
			pingFlag = 0;
		}
	}

	if(pongFlag == 1 && lflag == 1)
	{
		PING[pingIndex].re = temp.channel[1];
		PING[pingIndex].re /= 32768;
		PING[pingIndex].im = 0;
		temp.channel[0] = (short)outputPONG[pingIndex];
		pingIndex++;

		if(pingIndex >= FFT_LENGTH - (ORDER - 1))
		{
			pingFlag = 1;
			pingIndex = 0;
			pongFlag = 0;
		}
	}

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo);
}
Beispiel #18
0
void DSK6713_configure_AIC23() {
	/* Configure McBSP0 as control interface for aic23 */
	MCBSP_Handle MCBSP0_handle;
	MCBSP0_handle = MCBSP_open(MCBSP_DEV0, MCBSP_OPEN_RESET);

	MCBSP_config(MCBSP0_handle, &MCBSP0_config);
	MCBSP_start(MCBSP0_handle, MCBSP_XMIT_START | MCBSP_SRGR_START | MCBSP_SRGR_START, 220);

	set_aic23_register(MCBSP0_handle, RESET_REGISTER, 0x0000);
	set_aic23_register(MCBSP0_handle, POWER_DOWN_CONTROL, 0x0000);
	set_aic23_register(MCBSP0_handle, LEFT_LINE_INPUT_CHANNEL_VOLUME, 0x0017);
	set_aic23_register(MCBSP0_handle, RIGHT_LINE_INPUT_CHANNEL_VOLUME, 0x0017);
	set_aic23_register(MCBSP0_handle, LEFT_CHANNEL_HEADPHONE_VOLUME, 0x00f9);
	set_aic23_register(MCBSP0_handle, RIGHT_CHANNEL_HEADPHONE_VOLUME, 0x00f9);
	set_aic23_register(MCBSP0_handle, ANALOG_AUDIO_PATH, 0x0011);			// 00001 0010
	set_aic23_register(MCBSP0_handle, DIGITAL_AUDIO_PATH, 0x0000);			// 000000000
	set_aic23_register(MCBSP0_handle, DIGITAL_AUDIO_INTERFACE_FORMAT, 0x0043);	//0 0100 0001
	set_aic23_register(MCBSP0_handle, SAMPLE_RATE_CONTROL, 0x000d);		// 01100
	set_aic23_register(MCBSP0_handle, DIGITAL_INTERFACE_ACTIVATION, 0x0001);

	/* Configure McBSP1 as data interface for aic23 */
	MCBSP_Handle MCBSP1_handle;
	MCBSP1_handle = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
	MCBSP_config(MCBSP1_handle, &MCBSP1_config);
	MCBSP_start(MCBSP1_handle, MCBSP_XMIT_START|MCBSP_RCV_START|MCBSP_SRGR_FRAMESYNC|MCBSP_SRGR_START, 220);

	/* Configure receive EDMA */
	EDMA_Handle hEdmaRcv;
	EDMA_Handle hEdmaRcvA;
	EDMA_Handle hEdmaRcvB;

	hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);
	hEdmaRcvA = EDMA_allocTable(-1);
	hEdmaRcvB = EDMA_allocTable(-1);

	gEdmaRcvConfig.src = MCBSP_getRcvAddr(MCBSP1_handle);		// Get address of DRR
	gTccRcvChan = EDMA_intAlloc(-1);							// get next free transfer complete code
	gEdmaRcvConfig.opt |= EDMA_FMK(OPT, TCC, gTccRcvChan);
	EDMA_config(hEdmaRcv, &gEdmaRcvConfig);
	EDMA_config(hEdmaRcvA, &gEdmaRcvConfig);
	gEdmaRcvConfig.dst = EDMA_DST_OF(gRcvBufferB);
	EDMA_config(hEdmaRcvB, &gEdmaRcvConfig);

	EDMA_link(hEdmaRcv, hEdmaRcvB);
	EDMA_link(hEdmaRcvB, hEdmaRcvA);
	EDMA_link(hEdmaRcvA, hEdmaRcvB);

	/* Configure transmit EDMA */
	EDMA_Handle hEdmaXmt;
	EDMA_Handle hEdmaXmtA;
	EDMA_Handle hEdmaXmtB;

	hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET);
	hEdmaXmtA = EDMA_allocTable(-1);
	hEdmaXmtB = EDMA_allocTable(-1);

	gEdmaXmtConfig.dst = MCBSP_getXmtAddr(MCBSP1_handle);		// Get address of DXR
	gTccXmtChan = EDMA_intAlloc(-1);							// get next free transfer complete code
	gEdmaXmtConfig.opt |= EDMA_FMK(OPT, TCC, gTccXmtChan);
	EDMA_config(hEdmaXmt, &gEdmaXmtConfig);
	EDMA_config(hEdmaXmtA, &gEdmaXmtConfig);
	gEdmaXmtConfig.src = EDMA_DST_OF(gXmtBufferB);				// set source to buffer B
	EDMA_config(hEdmaXmtB, &gEdmaXmtConfig);

	EDMA_link(hEdmaXmt, hEdmaXmtB);
	EDMA_link(hEdmaXmtB, hEdmaXmtA);
	EDMA_link(hEdmaXmtA, hEdmaXmtB);


	EDMA_intClear(gTccRcvChan);
	EDMA_intClear(gTccXmtChan);
	EDMA_intEnable(gTccRcvChan);
	EDMA_intEnable(gTccXmtChan);

	gBufferState.cpuBufferState = StateB;		// inittial cpu buffer state

	EDMA_enableChannel(hEdmaRcv);
	EDMA_enableChannel(hEdmaXmt);

	IRQ_clear(IRQ_EVT_EDMAINT);
	IRQ_enable(IRQ_EVT_EDMAINT);

	MCBSP_write(MCBSP1_handle, 0x00);
}
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;
	short ii=0;
	short jj=0;

	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	// keep track of largest sample for diagnostics
	if (temp.channel[0]>max_samp)
		max_samp = temp.channel[0];

	if (state==0) {  // SEARCHING STATE

        // put sample in searching buffer
		buf[bufindex] = (float) temp.channel[0];  // right channel

	    // compute incoherent correlation
	    zc = 0;
	    zs = 0;
		for (ii=0;ii<M;ii++) {
			zc += mfc[ii]*buf[ii];
			zs += mfs[ii]*buf[ii];
		}
		zz = zc*zc+zs*zs;

		if (zz>T1) {  				// threshold exceeded?
			max_recbuf = 0;
			state = 1; 				// enter "recording" state (takes effect in next interrupt)
			DSK6713_LED_toggle(0);	// toggle LED here for diagnostics
			// record time of first sample (DRB fixed 4/19/2015: added +1)
			recbuf_start_clock = sincpulsebuf_counter-M+1; // should not be negative since we started counting when we launched the S->M sinc pulse
			recbufindex = M;		// start recording new samples at position M
			jj = bufindex;			//
			for (ii=0;ii<M;ii++){  	// copy samples from buf to first M elements of recbuf
				jj++;   				// the first time through, this puts us at the oldest sample
				if (jj>=M)
					jj=0;
				recbuf[ii] = buf[jj];
				buf[jj] = 0;  		// clear out searching buffer to avoid false trigger
			}
		}
		else {
			// increment and wrap pointer
		    bufindex++;
		    if (bufindex>=M)
		    	bufindex = 0;
		}

	}
	else if (state==1) { // RECORDING STATE

		// put sample in recording buffer
		recbuf[recbufindex] = (float) temp.channel[0];  // right channel
		recbufindex++;
		if (recbufindex>=(2*N+2*M)) {
			state = 2;  		// buffer is full
			delay_est_done = 0; // clear flag
			DSK6713_LED_toggle(0);	// toggle LED here for diagnostics
			recbufindex = 0; 	// shouldn't be necessary
		}
	}
	else if (state==2) { // CALCULATING DELAY ESTIMATES STATE
		if (delay_est_done==1) {  // are the delay estimates done calculating?
			state = 3; // next state
		}
	}
	else if (state==3) { // WRITE ADJUSTED VIRTUAL CLOCK BUFFER STATE
		delay_est_done = 0; // clear flag
		state = 0;  // xxx temporary
	}

	if (state==-1) { // WARMUP STATE (NO OUTPUT)
		if (sincpulsebuf_counter>LL/2) {
			state = 0;
		}
		temp.channel[1] = 0;
		temp.channel[0] = 0;
	}
	else {
		if (vclock_counter==buffer_swap_index)
			swap_pending = 1;
		if ((swap_pending==1)&&(state!=2)) // ok to swap buffer
		{
			swap_pending = 0;
			buffer_just_swapped = 1;
			if (current_clockbuf==0)
				current_clockbuf = 1;
			else
				current_clockbuf = 0;
		}
		temp.channel[1] = clockbuf_shifted[current_clockbuf][vclock_counter];  // slave *shifted* clock signal (always played)
//		temp.channel[1] = clockbuf[vclock_counter];  // slave *unshifted* clock signal (for debug)
		temp.channel[0] = sincpulsebuf[sincpulsebuf_counter];  // this initiates the sinc pulse exchange with the master
	}

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo); // output L/R channels

	// update virtual clock (cycles from 0 to L-1)
	vclock_counter++;
	if (vclock_counter>=L) {
		vclock_counter = 0; // clock tick occurred, wrap
	}

	// update sinc pulse counter (cycles from 0 to LL-1)
	// this is for sinc pulses from the slave to the master
	// sinc pulses from the slave to the master have their peak at
	// sincpulsebuf_counter = 0 (this makes clock offset calculations simple)
	sincpulsebuf_counter++;
	if (sincpulsebuf_counter>=LL) {
		sincpulsebuf_counter = 0; // wrap
	}

}
void codec_reset()
{
	while(!MCBSP_xrdy(mcbspControlHandle));
	MCBSP_write(mcbspControlHandle, (15 << 9) | 0);
	while(!MCBSP_xrdy(mcbspControlHandle));
}
interrupt void serialPortRcvISR()
{	union {Uint32 combo; short channel[2];} temp;

	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	// keep track of largest sample for diagnostics
	if (temp.channel[0]>max_samp)
		max_samp = temp.channel[0];

	if (state==STATE_SEARCH) {  // SEARCHING STATE
		//search_for_thresh(&(temp.channel[0]),PASSTHROUGH);
//		isSearching++;
		 // put sample in searching buffer

///*
		buf[bufindex] = (float) temp.channel[0];  // right channel
				if (PASSTHROUGH!=1) {
					temp.channel[0] = 0;  // can comment this out for debugging at home
				}

				// compute incoherent correlation
				zc = 0;
				zs = 0;
				for(i=0;i<M;i++) {
					zc += mfc[i]*buf[i];
					zs += mfs[i]*buf[i];
				}
				z = zc*zc+zs*zs;

				if (z>T1) {  				// threshold exceeded?
					max_recbuf = 0;
					state = 1; 				// enter "recording" state (takes effect in next interrupt)
					recbufindex = M;		// start recording new samples at position M
					j = bufindex;			//
					for (i=0;i<M;i++){  	// copy samples from buf to first M elements of recbuf
						j++;   				// the first time through, this puts us at the oldest sample
						if (j>=M)
							j=0;
						recbuf[i] = (short) buf[j];
						buf[j] = 0;  		// clear out searching buffer to avoid false trigger
					}
				}
				else {
					// increment and wrap pointer
					bufindex++;
					if (bufindex>=M)
						bufindex = 0;
				}

//*/
	}
	else if (state==STATE_RECORD) { // RECORDING STATE	
		//DEBUG
		if(!ledTriggered)
		{
			DSK6713_LED_toggle(0);
			ledTriggered = 1;
		}
		// put sample in recording buffer
		recbuf[recbufindex] = temp.channel[0];  // right channel
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		if (abs(recbuf[recbufindex])>max_recbuf) {
			max_recbuf = abs(recbuf[recbufindex]); // keep track of largest sample
		}
		recbufindex++;
		if (recbufindex>=(2*N+2*M)) {
			state = STATE_WAIT_CLOCK;  		// buffer is full (stop recording and start counting samples to next clock tick)
			recbufindex = 0; 	// shouldn't be necessary
			wait_count = 0;     // reset the wait counter
			if (max_recbuf<2048)
				playback_scale = 0;  // don't send response (signal was too weak)
			else if (max_recbuf<4096)
				playback_scale = 8;  // reply and scale by 8
			else if (max_recbuf<8192)
				playback_scale = 4;  // reply and scale by 4
			else if (max_recbuf<16384)
				playback_scale = 2;  // reply and scale by 2
			else
				playback_scale = 1;  // no scaling
		}
	}
	else if (state==STATE_WAIT_CLOCK) { // WAITING STATE (counting up samples until clock tick)
		if(ledTriggered){
		DSK6713_LED_toggle(0);
		ledTriggered = 0;
		}
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		wait_count++;
		// only way out of this state is when the virtual clock rolls over
	}
	else if (state==STATE_WAIT_PLAYBACK) { // WAITING STATE (counting down samples until reply)
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		wait_count--;
		if (wait_count<0) {
			state = 4;  // done waiting, time to play back rec_buffer in reverse
			recbufindex = 2*N+2*M;
		}
	}
	else if (state==STATE_RESPOND) { // RESPONSE STATE (play back recording buffer in reverse)
		recbufindex--;
		if (recbufindex>=0) {
			temp.channel[0] = playback_scale*recbuf[recbufindex];
		}
		else
		{
			state = STATE_SEARCH;  // go back to searching
		}
	}

	temp.channel[1] = clockbuf[vclock_counter];  // master clock signal (always played)

	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo); // output L/R channels

	// update virtual clock (cycles from 0 to L-1)
	vclock_counter++;
	if (vclock_counter>=L) {
		vclock_counter = 0; // clock tick occurred, wrap
		if (state==STATE_WAIT_CLOCK) {
			state = STATE_WAIT_PLAYBACK;
		}
	}

}
interrupt void serialPortRcvISR()
{
	union {Uint32 combo; short channel[2];} temp;

	temp.combo = MCBSP_read(DSK6713_AIC23_DATAHANDLE);
	// Note that right channel is in temp.channel[0]
	// Note that left channel is in temp.channel[1]

	// keep track of largest sample for diagnostics
	if (temp.channel[0]>max_samp)
		max_samp = temp.channel[0];

	// filter
	inbuf[inindex] = (float) temp.channel[0];  // right channel

	if (CLOCKOUTPUTCHANNEL==0) {
		// superimposed clocks and sync pulses, need to use HPF to avoid false detections
		hpfout = 0.0;
		ii = 0;
		for (kk=inindex;kk>=0;kk--){
			hpfout += inbuf[kk]*B[ii];
			ii++;
		}
		for (kk=BL-1;kk>inindex;kk--){
			hpfout += inbuf[kk]*B[ii];
			ii++;
		}
	}
	else {
		// clocks on left output, no need for HPF
		hpfout = (float) temp.channel[0];  // right channel
	}

	if (state==0) {  // SEARCHING STATE

        // put sample in searching buffer
		fbuf[bufindex] = hpfout;  // right channel
		buf[bufindex] = (float) temp.channel[0];  // unfiltered right channel
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}

	    // compute incoherent correlation on filtered buffer
	    zc = 0;
	    zs = 0;
		for(i=0;i<M;i++) {
			zc += mfc[i]*fbuf[i];
			zs += mfs[i]*fbuf[i];
		}
		z = zc*zc+zs*zs;

		if (z>T1) {  				// threshold exceeded?
			if (z<minz)
			minz = z;				// diagnostic
			if (z>maxz)
				maxz = z;			// diagnostic
			max_recbuf = 0;
			state = 1; 				// enter "recording" state (takes effect in next interrupt)
		    DSK6713_LED_toggle(0);  // toggle LED for diagnostics
			recbufindex = M;		// start recording new samples at position M
			j = bufindex;			//
			for (i=0;i<M;i++){  	// copy samples from buf to first M elements of recbuf
				j++;   				// the first time through, this puts us at the oldest sample
				if (j>=M)
					j=0;
				//recbuf[i] = (short) buf[j];  // Oct 28 bad idea
				recbuf[i] = (short) fbuf[j];  // DRB: filtered buffer copied now to avoid echoing back clock pulses
				fbuf[j] = 0;  		// clear out searching buffer to avoid false trigger
				buf[j] = 0;  		// clear out searching buffer to avoid false trigger
			}
		}
		else {
			// increment and wrap pointer
		    bufindex++;
		    if (bufindex>=M)
		    	bufindex = 0;
		}

	}
	else if (state==1) { // RECORDING STATE

		// put sample in recording buffer
		//recbuf[recbufindex] = temp.channel[0];  // right channel
		recbuf[recbufindex] = (short) hpfout;  // filtered right channel
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		if (abs(recbuf[recbufindex])>max_recbuf) {
			max_recbuf = abs(recbuf[recbufindex]); // keep track of largest sample for diagnostics
		}
		recbufindex++;
		if (recbufindex>=(2*N+2*M)) {
			state = 2;  		// buffer is full (stop recording and start counting samples to next clock tick)
			DSK6713_LED_toggle(0); // toggle LED for diagnostics
			recbufindex = 0; 	// shouldn't be necessary
			wait_count = 0;     // reset the wait counter
			if (max_recbuf<2000)
				playback_scale = 0;  // don't send response (signal was too weak)
			else if (max_recbuf<4000)
				playback_scale = 8;  // reply and scale by 8 (DRB now 4 to avoid overflow)
			else if (max_recbuf<8000)
				playback_scale = 4;  // reply and scale by 4 (DRB now 2 to avoid overflow)
			else if (max_recbuf<16000)
			playback_scale = 2;  // reply and scale by 2 (DRB now 1 tp avoid overflow)
			else
				playback_scale = 1;  // no scaling
		}
	}
	else if (state==2) { // WAITING STATE (counting up samples until clock tick)
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		wait_count++;
		// only way out of this state is when the virtual clock rolls over
	}
	else if (state==3) { // WAITING STATE (counting down samples until reply)
		if (PASSTHROUGH!=1) {
			temp.channel[0] = 0;  // can comment this out for debugging at home
		}
		wait_count--;
		if (wait_count<HPFGROUPDELAY) {
			state = 4;  // done waiting, time to play back rec_buffer in reverse
			recbufindex = 2*N+2*M;
		}
	}
	else if (state==4) { // RESPONSE STATE (play back recording buffer in reverse)
		recbufindex--;
		if (recbufindex>=0) {
			temp.channel[0] = playback_scale*recbuf[recbufindex];  // response always on right channel
		}
		else
		{
			state = 0;  // go back to searching
		}
	}

	// temp.channel[0] right channel has been previously set
	temp.channel[1] = 0;	// clear left channel
	temp.channel[CLOCKOUTPUTCHANNEL] += clockbuf[vclock_counter];  // master clock signal (always played)
//	temp.channel[0] = temp.channel[1];  // XXX DIAGNOSTIC FOR OUTPUT OFFSET TEST
//	temp.channel[0] = clockbuf[vclock_counter];  // XXX DIAGNOSTIC


	MCBSP_write(DSK6713_AIC23_DATAHANDLE, temp.combo); // output L/R channels

	// update virtual clock (cycles from 0 to L-1)
	vclock_counter++;
	if (vclock_counter>=L) {
		vclock_counter = 0; // clock tick occurred, wrap
		if (state==2) {
			state = 3;
		}
	}

	inindex++;
	if (inindex>BL-1)
		inindex = 0;

}