[ 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.

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 <usbstk5515.h>
#include <usbstk5515_i2c.h>
#include <AIC_func.h>
#include <sar.h>
#include <stdio.h>
//#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<HPL; j++) { if(i>=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 >> 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 < (ASIZE); i++) { AIC_read2(&amp;right, &amp;left); in[i] = right; } while(1) { if(i>=ASIZE) i=0;
AIC_read2(&amp;right, &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.

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!

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

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

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int i;
unsigned short j, n, FTV, fs;
char name[256];
if(argc > 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 <= 100; i++){ n = (unsigned short) i; j = (unsigned short) (FTV*(1+n*fs)); fprintf(fp, "%hu, \t%hu\n", n, j>>10);
}
/* for understanding bit shifts with unsigned shorts...
int rate = 1024;
for (i=0; i<66000*2; i+=rate){ j = (unsigned int) i; printf("%hu\n", j>>10);
}
*/
fclose(fp);
return 0;
}