Aside: Frying ATMEGA16-U2 on Uno (R3)

[ Sudden Uno Death Syndrome ]

Looks like we have one potential explanation for why so many (3?) of our Unos stopped working when we are trying to drive multiple servos through them!

We might have ended driving too much current through the USB chip…but wasn’t USB limited to supporting 500 mA? One way to check this would be to replace the chip on the board. Oh SMD…

fry

Advertisements

Codec Setup

1.3vpsu

[ 1.3V supply ]

From [ Audio Cape RevA ]’s BOM:

BeagleBone Audio Cape 8/14/2012
Rev A
ITM QTY PART DESIGNATOR PART DESCRIPTIONS MAN PART # COMMENTS
1 4 C1,C2,C3,C4 10uF,10V CAP CER 10UF 10V Y5V 0805 TDK C2012Y5V1A106Z
3 2 C46,C47 47uF CAP CER 47UF 10V X5R 1210 Murata GRM32ER61A476KE20L
4 4 C48,C49,C53,C61 47pF CAP CER 47PF 50V C0G 5% 0402 TDK C1005C0G1H470J
5 9 C50,C51,C52,C54,C57,C60,C63,C78,C79 0.1uF CAP 0.1uF 16V 10% 0402 X7R Kemet C0402C104K4RACT
6 5 C55,C56,C58,C59,C62 10uF,0805 CAP CER 10UF 10V Y5V 0805 TDK C2012Y5V1A106Z
8 4 D1,D2,D3,D4 PGB0010603MR Ferrite Bead 150 Ohm 800mA Steward LI0805H151R-10
9 2 D5,D6 598-8170-107F LED Green SMD 20mA 2V 0805 Dialight 598-8170-107F
10 3 FB6,FB7,FB8 MMZ1608R301A FERRITE CHIP 300 OHM 500MA 0603 TDK MMZ1608R301A
11 2 P1,P2 2×23 HEADER FEMALE .100 CL Dual Row- Straight Socket Strip- using .025″ Sq. Pins MLE SSHQ-123-D-08-G-LF
2×23 HEADER FEMALE .100 CL Dual Row- Straight Socket Strip- using .025″ Sq. Pins MLE SSHQ-123-D-08-F-LF
12 1 P3 2×5 HEADER FEMALE .100 CL Dual Row- Straight Socket Strip- using .025″ Sq. Pins MLE SSHQ-105-D-08-G-LF
2×5 HEADER FEMALE .100 CL Dual Row- Straight Socket Strip- using .025″ Sq. Pins MLE SSHQ-105-D-08-F-LF
13 2 P6,P7 PHONOJACK STEREO-R CONN JACK STEREO 3POS 3.5MM SMD CUI SJ1-3513-SMT
14 1 Q1 DMC56404 TRANS NPN/NPN W/RES 50V SMINI6 Panasonic DMC564040R
16 3 R108,R109,R110 33,402 RES 33.0 OHM 1/16W 1% 0402 SMD Yaego RC0805FR-0749R9L
17 1 R111 .1,0805 RES .10 OHM 1/8W 5% 0805 CTS 73L3R10J
18 1 R112 28K RES 28.0K OHM 1/16W 1% 0402 SMD Yaego RC0402FR-0728KL
19 1 R113 56.2K RES 56.2K OHM 1/16W 1% 0402 SMD Yaego CRCW040256K2FKED
20 2 R114,R115 5.6K RES 5.6K OHM 1/16W 5% 0402 SMD Yaego RC0402JR-075K6L
21 3 R116,R117,R118 4.75K RES 4.75K OHM 1/16W 1% 0402 SMD  Stackpole Electronics RMCF0402FT4K75
22 2 R119,R120 470,5% RES 470 OHM 1/10W 5% 0402 SMD Panasonic ERJ-2GEJ471X
23 2 R121,R122 100K,1% Resistor 100Kohm 1/16W 1% 0402 Yageo CRCW0402100KJNED
24 1 R123 10K Resistor 10Kohm 1/16W 5% 0402 Rohm MCR01MZPJ103
25 2 R130,R132 402 Resistor Zero ohm Jumper 0402 Yaego RC0402JR-070RL
27 1 SW1 2 POS Dip Switch SWITCH TAPE SEAL 2 POS SMD CTS 219-2MST
29 1 U6 TLV320AIC3106 IC STER AUD CODEC 32 BIT 48-VQFN TI TLV320AIC3106IRGZR
30 1 U7 TPS73701DRBR IC REG LDO CAP FREE 8-SON TI TPS73701DRBR
31 1 U8 CAT24C256W IC EEPROM 256KBIT 400KHZ 8SOIC ON CAT24C256WI-G
33 1 Y1 12MHz OSCILLATOR 12.000 MHZ 3.3V SMD Fox FXO-HC735-12

Using Ti’s FIR, indexing HRIR issues, SW2 is messed up

Replaced UMich’s FIR with the hand-optimized FIR from Ti. Does work better! Exact quantifying needed.

Also found that SW2 on my board is messed up. SW1 works.

Still need to work on indexing filter weights. The current method of copying filter weights inside a for loop just feels wrong. But it works (almost.)

Most of this program is for testing different modes. Only the filtration section at the bottom is really important for this post.

/*
 * fir_filter.c
 * A crude implementation for using HRIRs. A 200 tap HRIR was loaded for each channel.
 *      Author: GSI
 */

#include <usbstk5515.h>
#include <usbstk5515_i2c.h>
#include <AIC_func.h>
#include <sar.h>
#include <stdio.h>
#include <Dsplib.h>
#include "hrir_l_subject3_el10_azAll.h"
#include "hrir_r_subject3_el10_azAll.h"

#define ASIZE 		200

#define TCR0 		*((ioport volatile Uint16 *)0x1810)
#define TIMCNT1_0 	*((ioport volatile Uint16 *)0x1814)
#define TIME_START  0x8001
#define TIME_STOP   0x8000

#define LED_out1 *((ioport volatile Uint16*) 0x1C0A )
#define LED_out2 *((ioport volatile Uint16*) 0x1C0B )
#define LED_dir1 *((ioport volatile Uint16*) 0x1C06 )
#define LED_dir2 *((ioport volatile Uint16*) 0x10C7 )

//initializing LED GPIOs as outputs. LEDs are active low => writing 1s to keep them off
void LED_init() {
	LED_dir1 |= (Uint16) (3 << 14); //GPIOs 14, 15
	LED_dir2 |= (Uint16) 3; 		//GPIOs 16, 17
	//switching them off (driving high)
	LED_out1 |= (Uint16) (3 << 14);
	LED_out2 |= (Uint16) 3;
}

//LED toggling based on index inputted
void toggle_LED(int index) {
	if		(index == 3){ 	//Blue: 					GPIO[14]
		LED_out1 = (Uint16)(3<< (14) );
		LED_out2 = (Uint16)(1<< (0) );
	}
	else if(index == 2) {	//Yellow(ish) <-- LOL: 		GPIO[15]
		LED_out1 = (Uint16)(3<< (14) );
		LED_out2 = (Uint16)(2<< (0) );
	}
	else if(index == 1) {	//Red: 						GPIO[16]
		LED_out1 = (Uint16)(1<< (14) );
		LED_out2 = (Uint16)(3<< (0) );
	}
	else if(index == 0) { 	//Green: 					GPIO[17]
		LED_out1 = (Uint16)(2<< (14) );
		LED_out2 = (Uint16)(3<< (0) );
	}
	else { 	//Green: 					GPIO[17]
		LED_out1 = (Uint16)(3<< (14) );
		LED_out2 = (Uint16)(3<< (0) );
	}
}

Int16 in_left[ASIZE], in_right[ASIZE];
Uint16 delta_time;

Int16 FIR(Int16* in, Int16* hrir,  Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++) { if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in[index] * (Int32)hrir[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

void main(void)
{
	LED_init();
	Uint16 i, n, az = 0;
//	Uint16 start_time;
//	Uint16 end_time;
	Int16 right[1], left[1]; //AIC inputs
	Int16 out_left[1], out_right[1];
	Int16 dbuffer_l[ASIZE+2] = {0};
	Int16 dbuffer_r[ASIZE+2] = {0};
	Int16 hrir_left[ASIZE], hrir_right[ASIZE];
	Int16 scaling = 16;
	Uint16 key;
	Uint16 filter = 3;

	USBSTK5515_init(); 	//Initializing the Processor
	AIC_init(); 		//Initializing the Audio Codec
	Init_SAR(); 		//Initializing the SAR ADC for key presses
	//Priming the PUMP
	for(i = 0; i < (ASIZE); i++) { AIC_read2(right, left); in_right[i] = right[0]; in_left[i] = left[0]; dbuffer_r[i] = right[0]; dbuffer_l[i] = left[0]; } while(1) { if(i>=ASIZE) i=0;
		//if(j>=WTIME){
		//	if(key == SW2) az += 1;
		//	j = 0;
		//}
		AIC_read2(right, left);
		in_left[i] = left[0];
		in_right[i] = right[0];

		if (filter == 0){ //bypass
			out_left[0] 	= left[0];
			out_right[0] 	= right[0];
		}
		else if (filter == 1){ //redundant calculation (slow down)
			//scaling*FIR(in_left, hrir_l, i, az);
			//scaling*FIR(in_right, hrir_r, i, az);
			out_left[0] 	= left[0]-right[0];
			out_right[0] 	= right[0]-left[0];
		}
		else if (filter == 2){
			fir(in_left,
				hrir_left,
				out_left,
				dbuffer_l,
				1,
				ASIZE);
			fir(in_right,
				hrir_right,
				out_right,
				dbuffer_r,
				1,
				ASIZE);
			out_left[0] 	= left[0];
			out_right[0] 	= right[0];
			//using the HRIR output
			//out_left[0] 	= scaling*FIR(in_left, hrir_l, i, az);
			//out_right[0] 	= scaling*FIR(in_right, hrir_r, i, az);

		}
		else if (filter == 3){
			for (n=0; n<ASIZE; n++){ hrir_left[n] = hrir_l[az*ASIZE +n]; hrir_right[n] = hrir_r[az*ASIZE +n]; } fir(left, hrir_left, out_left, dbuffer_l, 1, ASIZE); fir(right, hrir_right, out_right, dbuffer_r, 1, ASIZE); out_left[0] = scaling*out_left[0]; out_right[0] = scaling*out_right[0]; //mono summed (using left channel) //out_left = scaling*FIR(in_left, hrir_l, i, az); //out_right = scaling*FIR(in_left, hrir_r, i, az); } else{ out_left[0] = 0; out_right[0] = 0; } //POSTFILTER: AIC_write2(out_right[0], out_left[0]); toggle_LED(az%4);//filter); key = Get_Key_Human(); //if (key == SW1) filter += 1; if (key == SW1) az += 1; if (filter>4) filter = 0;
		if (az > 47) az = 0; //az = 48, 49, 50 scaryyy
		i++;

		//printf("%i\n", az);
	}
}

10000 tap headers, slow implementations and distortion

Here’s a little MATLAB routine which can be used to convert CIPIC’s .mat files to C headers:

function hrir_az2c(file, arrName, hrir, el)
%// arrName: name for the C array that will be created, could use a string corresponding to the MATLAB array:
%// hrir: the hrir 25x50x200 array
%// el: current plan is to output one header per elevation per L/R channel
%// Adapted from Aj's post here: 
%// http://www.mathworks.com/matlabcentral/newsreader/view_thread/48182

scale = 1e3; %// weights are very small -> round to 0s
[max_el, max_az, max_tap] = size(hrir);
if (el>max_el)
    el = max_el;
end
toWrite = ['Int16 ', arrName, '[', num2str(max_az*max_tap), '] = {'];
for az = 1:max_az
    for tap = 1:max_tap
        if az ~= max_az && tap ~= max_tap
            toWrite = [ toWrite, sprintf('%i, ', int16(scale.*hrir(el, az, tap)))];
        end
    end
end
toWrite = [toWrite, sprintf('%i};', int16(scale.*hrir(el, max_az, max_tap)))];

fid = fopen([file, '.h'], 'w');
fprintf(fid, toWrite);
fclose(fid);
end

For some reason, Code Composer Studio doesn’t appear to like 2-D arrays. So, I resorted to using one long array, and indexing different filters out of it.

Also, I used the switches to switch between different modes:

[1] No filtering done. Codec input is directly outputted
[2] Filtering done (left channel through left HRIR, likewise for right channel), but codec input still directly outputted. This is to observe some distortion that creeps in in comparison to [1]. Reason being slow code.
[3] Filtering done, and outputted
[4] Filtering done in the mono sense: the same channel is run through left and right HRIRs and outputted in stereo

Mode [4] is not working as expected. It might be that my HRIR switching is not working. The LCD display can be used to verify the azimuth indexing being used.

Also, it should be noted that this code has a crude timer to make sure that HRIRs don’t start switching rapidly the moment the switch is pressed. This is crude, it would be better to detect changes in the switch’s state.

Here’s the latest version of the program. I hope to add sound samples soon (codec board needs to be resolved for doing the recording ūüôā )

/*
 * fir_filter.c
 * A crude implementation for using HRIRs. A 100 tap HRIR was loaded for each channel.
 *      Author: GSI + Abhinav
 */

#include <usbstk5515.h>
#include <usbstk5515_i2c.h>
#include <AIC_func.h>
#include <sar.h>
#include <stdio.h>
#include "hrir_l_subject3_el10_azAll.h"
#include "hrir_r_subject3_el10_azAll.h"

#define ASIZE 		200

#define TCR0 		*((ioport volatile Uint16 *)0x1810)
#define TIMCNT1_0 	*((ioport volatile Uint16 *)0x1814)
#define TIME_START  0x8001
#define TIME_STOP   0x8000

Int16 in_left[ASIZE], in_right[ASIZE];
Uint16 delta_time;

Int16 FIR_left(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_left[index] * (Int32)hrir_l[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

Int16 FIR_right(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_right[index] * (Int32)hrir_r[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

Int16 FIR(Int16* in, Int16* hrir,  Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++)
	{
		if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in[index] * (Int32)hrir[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}



void main(void)
{
	Uint16 i, az = 0, j = 0, WTIME = 100;
//	Uint16 start_time;
//	Uint16 end_time;
	Int16 right, left; //AIC inputs
	Int16 out_left, out_right;
	Uint16 key;
	Uint16 filter = 0;

	USBSTK5515_init(); 	//Initializing the Processor
	AIC_init(); 		//Initializing the Audio Codec
	Init_SAR(); 		//Initializing the SAR ADC for key presses
	//Priming the PUMP
	for(i = 0; i < (ASIZE); i++)
	{
		AIC_read2(&right, &left);
		in_right[i] = right;
		in_left[i] = left;
	}
	while(1)
	{
		if(i>=ASIZE) i=0;
		if(j>=WTIME){
			if(key == SW2) az += 1;
			j = 0;
		}

		AIC_read2(&right, &left);
		in_left[i] = left;
		in_right[i] = right;

		if (filter == 0){ //bypass
			out_left = left;
			out_right = right;
		}
		else if (filter == 1){ //redundant calculation (slow down)
			16*FIR_left(i, az);
			16*FIR_right(i, az);
			out_left = left;
			out_right = right;
		}
		else if (filter == 2){ //using the HRIR output
			out_left = 16*FIR_left(i, az);
			out_right = 16*FIR_right(i, az);
		}
		else if (filter == 3){ //mono summed (using right channel)
			out_left = 16*FIR(in_right, hrir_l, i, az);
			out_right = 16*FIR(in_right, hrir_r, i, az);
		}
		else{
			out_left = 0;
			out_right= 0;
		}
		//POSTFILTER:
		AIC_write2(out_right, out_left);

		key = Get_Key_Human();
		if (key == SW1) filter += 1;
		if (filter>4) filter = 0;
		if (az > 50) az = 0;
		//filter = 1;
		//if (filter)
		//	AIC_write2(16*out_right, 16*out_left);
		//else
		//	AIC_write2(right, left);
		i++, j++;
	}
}

Something is up with ezDSP’s switches + HRIRs!

Pressing SW2 sometimes has the same effect as pressing SW1! By the way, 2-D arrays appear to act weird in CCS, so I just went with one-d arrays for the HRIRs.

Also, some of the azimuths of these HRIRs give super high volumes. Its very scary.

Things to be improved:

  • Using one FIR routine instead of 2!
  • Some gain control?
  • Smoothing out the transitions between HRIRs. Actually, it would be nice to use the LCD to see how rapidly the azimuths are changing (using WTIME in the following code is not really good…)
/*
 * fir_filter.c
 * A crude implementation for using HRIRs. A 100 tap HRIR was loaded for each channel.
 *      Author: GSI
 */

#include <usbstk5515.h>
#include <usbstk5515_i2c.h>
#include <AIC_func.h>
#include <sar.h>
#include <stdio.h>
#include "hrir_l_subject3_el10_azAll.h"
#include "hrir_r_subject3_el10_azAll.h"

#define ASIZE 		200

#define TCR0 		*((ioport volatile Uint16 *)0x1810)
#define TIMCNT1_0 	*((ioport volatile Uint16 *)0x1814)
#define TIME_START  0x8001
#define TIME_STOP   0x8000

Int16 in_left[ASIZE], in_right[ASIZE];
Uint16 delta_time;

Int16 FIR_left(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++) { if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_left[index] * (Int32)hrir_l[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}

Int16 FIR_right(Uint16 i, Uint16 az)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;
	//The actual filter work
	for(j=0; j<ASIZE; j++) { if(i>=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in_right[index] * (Int32)hrir_r[az*ASIZE + j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum >> 15);  	// Conversion from 32 Q30 to 16 Q15.
}


void main(void)
{
	Uint16 i, az = 0, j = 0, WTIME = 100;
//	Uint16 start_time;
//	Uint16 end_time;
	Int16 right, left; //AIC inputs
	Int16 out_left, out_right;
	Uint16 key;
	Uint16 filter = 0;

	USBSTK5515_init(); 	//Initializing the Processor
	AIC_init(); 		//Initializing the Audio Codec
	Init_SAR(); 		//Initializing the SAR ADC for key presses
	//Priming the PUMP
	for(i = 0; i < (ASIZE); i++) { AIC_read2(&right, &left); in_right[i] = right; in_left[i] = left; } while(1) { if(i>=ASIZE) i=0;
		if(j>=WTIME){
			if(key == SW2) az += 1;
			j = 0;
		}

		AIC_read2(&right, &left);
		in_left[i] = left;
		in_right[i] = right;
		out_left = FIR_left(i, az);
		out_right = FIR_right(i, az);
		//POSTFILTER:

		key = Get_Key_Human();
		if (key == SW1) filter = !filter;
		if (az > 50) az = 0;
		//filter = 1;
		if (filter)
			AIC_write2(16*out_right, 16*out_left);
		else
			AIC_write2(right, left);
		i++, j++;
	}
}

TL071 with a single supply: attempt #2

[ source ]

I setup the circuit in the bottom right, with a 5V supply though. A 500 mVpp sine wave at about 100 Hz was inputted with varying offset:

IMG_9031

It appears that I was getting a gain of 1 (not expected.) The voltage scales get a bit confusing because the cables used on both of the channels had different impedance (10x vs 1x)

And here’s what the breadboard looked like:

IMG_9032

This problem needs some more thinking (and datasheet reading!)

Aside: Saxophone and Soldering Attempts (fail)

We tried helping one of our marching band members fix a little problem with his saxophone. The problem was that we couldn’t get the contact area hot enough for solder to melt over the entire area… A blow torch would have been better!

However, watching our prototyping guru, nicknamed Spock for anonymity, was very informative! Spock used solder paste, and first tried to heat the connection up with a hot air gun. That partially worked. So, Spock decided to switch to a ~140W soldering iron. That also didn’t cut it. But the coolest thing was that Spock used tape to keep a watch on how hot the surrounding areas of the saxophone were getting!

IMG_9012 IMG_9011 IMG_9010 IMG_9009

Lab 2: FIRs and Circular Buffers

[ EECS Lab 2 ] [ spru422j ]

We finally have a 60-tap FIR running on the ezDSP (long ways to go still…) Anyway, the feeling you get on hearing your favorite music pop out of your DSP is a really good one! The surprising feeling is realizing that there’s a lot that can be done with 60 taps, by just changing the taps around! I need to have many more such days!

Following UMich’s lab, here’s 60-tap low pass FIR using MATLAB’s fdatool:
[ magnitude and phase response ] [ impulse response ] [ group delay ] [ pole zero ]

On FIRs: [ direct vs transposed ]

/*
 * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
 * Generated by MATLAB(R) 8.5 and the Signal Processing Toolbox 7.0.
 * Generated on: 11-Oct-2015 01:37:33
 *
 * Discrete-Time FIR Filter (real)
 * -------------------------------
 * Filter Structure  : Direct-Form FIR
 * Filter Length     : 61
 * Stable            : Yes
 * Linear Phase      : Yes (Type 1)
 */

#define LPL 61
Int16 LP[61] = {
       -5,     15,     16,    -15,    -35,      9,     64,     16,    -92,
      -69,    105,    150,    -81,   -251,     -1,    349,    161,   -406,
     -405,    369,    723,   -177,  -1086,   -255,   1449,   1082,  -1761,
    -2820,   1971,  10202,  14339,  10202,   1971,  -2820,  -1761,   1082,
     1449,   -255,  -1086,   -177,    723,    369,   -405,   -406,    161,
      349,     -1,   -251,    -81,    150,    105,    -69,    -92,     16,
       64,      9,    -35,    -15,     16,     15,     -5
};

Working with a 60-tap FIR is like building on a constraint, and a low pass filter quickly gets boring. So I tried a high pass too. But I think switching out HRIRs, or doing an LMS filter would be more fun.

For today, some problems we ran into:
– Resolving the audio codec function calls. Linking the right paths solved this problem (I just started with the ‘starting_point’ project from the wonderful lab course at UMich.
– For some reason, Code Composer Studio isn’t able¬†to see my filter’s header file anymore. Copy-pasted the coefficients in for now.

SearchPath

Instead of going with the function generator option, I just plugged in Spotify through the lab’s low pass filter. I doubt that it wasn’t keeping up, but the low passing wasn’t very pronounced (given that cutoff was around 9kHz.)(Note from the future: Dr Anderson thinks that a WAV file still might give more content at higher frequencies than an mp3)

Anyway, I made a high pass filter instead, so the filter’s output would easier to hear. Then I made use of SW0 to enable bypassing the filter’s output (and enjoying unaltered – mostly – stereo music!

High pass filtering now works.
[ high pass ]

/*
 * fir_filter.c
 * Originally from EECS 452. 
 * Edits:
 * - a high pass filter is used instead of the low pass from the lab.
 * - SW1 can be pressed to switch between listening to the filter's output, and the actual audio (through the codec)
 */

#include &lt;usbstk5515.h&gt;
#include &lt;usbstk5515_i2c.h&gt;
#include &lt;AIC_func.h&gt;
#include &lt;sar.h&gt;
#include &lt;stdio.h&gt;
//#include "high_pass.h"

#define HPL 61
Int16 HP[61] = {
        2,      5,      9,     12,     14,     12,      3,    -15,    -40,
      -71,   -100,   -118,   -115,    -81,     -9,    100,    237,    380,
      498,    556,    514,    341,     18,   -457,  -1059,  -1747,  -2456,
    -3114,  -3648,  -3997,  28650,  -3997,  -3648,  -3114,  -2456,  -1747,
    -1059,   -457,     18,    341,    514,    556,    498,    380,    237,
      100,     -9,    -81,   -115,   -118,   -100,    -71,    -40,    -15,
        3,     12,     14,     12,      9,      5,      2
};

#define ASIZE 		61

#define TCR0 		*((ioport volatile Uint16 *)0x1810)
#define TIMCNT1_0 	*((ioport volatile Uint16 *)0x1814)
#define TIME_START  0x8001
#define TIME_STOP   0x8000

Int16 in [ASIZE];
Uint16 delta_time;


Int16 FIR(Uint16 i)
{
	Int32 sum;
	Uint16 j;
	Uint32 index;
	sum=0;

	//The actual filter work
	for(j=0; j&lt;HPL; j++) { if(i&gt;=j)
 			index = i - j;
		else
 			index = ASIZE + i - j;
		sum += (Int32)in[index] * (Int32)HP[j];
	}
	sum = sum + 0x00004000;			// So we round rather than truncate.
	return (Int16) (sum &gt;&gt; 15);  	// Conversion from 32 Q30 to 16 Q15.

}


void main(void)
{
	Uint16 i;
//	Uint16 start_time;
//	Uint16 end_time;
	Int16 right, left; //AIC inputs
	Int16 out;
	Uint16 key;
	Uint16 filter = 0;

	USBSTK5515_init(); 	//Initializing the Processor
	AIC_init(); 		//Initializing the Audio Codec
	Init_SAR(); 		//Initializing the SAR ADC for key presses
	//Priming the PUMP
	for(i = 0; i &lt; (ASIZE); i++) { AIC_read2(&amp;amp;right, &amp;amp;left); in[i] = right; } while(1) { if(i&gt;=ASIZE) i=0;
		AIC_read2(&amp;amp;right, &amp;amp;left);
		in[i] = left;
		out = FIR(i);
		//POSTFILTER:
		key = Get_Key_Human();
		if (key == SW1) filter = !filter;

		if (filter)
			AIC_write2(out, out);
		else
			AIC_write2(right, left);
		i++;
	}
}

The next step on the FIR front will be going back to the HRIRs! Will probably have to play around with the formatting to get the weights out of MATLAB.

I also have to¬†figure out¬†why the FIR buffers are setup the way they are…that is, why the FIR implementation does not begin with the newest values on top!

[ MATLAB C header ] [ string formatting ]

function hrir2head(name, w)
%Adapted from Aj's post here: 
%http://www.mathworks.com/matlabcentral/newsreader/view_thread/48182
fid = fopen([name, '.h'], 'w');
[w1end, w2end, w3end] = size(w);
fprintf(fid,'Int16 w[%d][%d][%d];\n', w1end, w2end, w3end);
for i = 1:w1end
    for j = 1:w2end
        for k = 1:w3end
            fprintf(fid,'w[%d][%d][%d]=%f15;\n', i, j, k, w(i, j, k));
        end
    end
end
fclose(fid);
end

That’s all for FIR for today. I have also been working on the digital synthesis section of lab2 over this weekend (yay, fall break!)

The digital synthesis section is very interesting, but I am still wrapping my head around how indexing differently into the sine table would change the sine wave’s frequency. It appears as if smaller steps (FTV) will make the sine output have longer steps, which should get us a lower frequency sine wave after smoothing out with a low pass filter. On the other hand, a bigger FTV values would make the duration of steps smaller, resulting in higher frequency sine waves.

Screen Shot 2015-10-12 at 3.02.26 AM

[ source ]

Thus, the more rapidly the indexes switch, the higher the frequency of the sine wave we should get (low pass filtering will smoothen the steps out.) But I am not sure about the exact relationship yet!

img001

[ unsigned int ] [ %hu ] [ argv ] [ snprintf ] [ atoi ]

Here is a small exercise in C and plotting to visualize how the indexes change.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main(int argc, char *argv[]){
	int i;
	unsigned short j, n, FTV, fs;
	char name[256];

	if(argc &gt; 1)FTV = (unsigned short) atoi(argv[1]);	
	else FTV = 1;
	printf("FTV: %hu\n", FTV);

	fs = 48000; //multiplying directly might be changing the type!

	FILE *fp;
	snprintf(name, sizeof name,"%s%hu%s", "out_", FTV, ".csv");
	fp = fopen(name, "w");

	for (i = 1; i &lt;= 100; i++){ n = (unsigned short) i; j = (unsigned short) (FTV*(1+n*fs)); fprintf(fp, "%hu, \t%hu\n", n, j&gt;&gt;10);
	}

/* for understanding bit shifts with unsigned shorts...
 	int rate = 1024;
 	for (i=0; i&lt;66000*2; i+=rate){ j = (unsigned int) i; printf("%hu\n", j&gt;&gt;10);
 	}
 */
	fclose(fp);
	return 0;
}

QFVindexing