EE 586L Report

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

Nolan Miller - 5339012800

EE-434 Assignment 2 - January 28, 2016


Due to the difficulty involved with benchmarking the code, it is not clear what the units of the timing function return value
should be. They are consistent throughout the optimization and are proportional to clock cycles so I will give them the unit
tics.

Baseline
Here is a snippet of the relevant (to be optimized) sections of my code. It had a dt value of roughly 5866 tics.
# define delay 1000
short filt_buff [ delay ] = {0};
float alpha = .1;
short filter ( short input ) {
int i ;
// iir comb filter
short out = filt_buff [0]* alpha + input *(1 - alpha );
for ( i = 1; i < delay ; i ++) {
filt_buff [i -1] = filt_buff [ i ];
}
filt_buff [ delay -1] = out ;
return out ;
}
// Interrupt Service Routine
interrupt void c_int11 () {
tic ();
// Start the timer
if (++ loopindex >= loop_count ) {
loopindex = 0;
if ( led_state ) {
DSK6713_LED_on (0);
led_state = 0;
} else {
DSK6713_LED_off (0);
led_state = 1;
}
}
if (++ period_indx >= period_count ) {
period_indx = 0;
}
short smpl = 0;
if ( DSK6713_DIP_get (1)) {
smpl = input_sample ();
} else {
smpl = sin_tbl [( period_indx * tbl_size )/ period_count ];
}
output_sample ( filter ( smpl ));
int dt = toc ();
// get timer value
return ;
// breakpoint set here to examine dt
}

Optimization 1
I optimized the filter buffer to use a circular buffer rather than the data-shifting method previously used. This improved the
run-time from 5866 tics to 140 tics. It also significantly sped up the execution so the buffer had to be extended.
# define delay 10000
short filt_buff [ delay ] = {0};
float alpha = .1;
short idx = 0;
// don t shift memory , shift index
short filter ( short input ) {
idx = ( idx - 1 + delay ) % delay ;
// iir comb filter
short out = filt_buff [ idx ]* alpha + input *(1 - alpha );
filt_buff [( idx +1)% delay ] = out ;
return out ;
}

Optimization 2
I started using a board that was not broken and the behavior changed (although the performance did not). To correct for
the change, I changed the alpha value from .1 to .3. I then changed the buffer iteration direction to reduce the number of
ops. This reduced the time from 140 to 135 tics.
# define delay 10000
short filt_buff [ delay ] = {0};
float alpha = .3;
short idx = 0;
// don t shift memory , shift index
short filter ( short input ) {
idx = ( idx + 1) % delay ;
// iir comb filter
short out = filt_buff [ idx ]* alpha + input *(1 - alpha );
filt_buff [ idx ] = out ;
return out ;
}

Optimization 3
I removed the local variable from the filter function and condensed the function to a single line. The run time went from 135
to 130 tics.
# define delay 10000
short filt_buff [ delay ] = {0};
float alpha = .3;
short idx = 0;
// don t shift memory , shift index
short filter ( short input ) {
return filt_buff [ idx ] = filt_buff [ idx =( idx +1)% delay ]* alpha + input *(1 - alpha );
}

Optimization 4
I removed the Function call entirely and performed all logic in the ISR. The run time went from 130 to 117 tics.
// Interrupt Service Routine
interrupt void c_int11 () {
tic ();
// start the timer
if (++ loopindex >= loop_count ) {
loopindex = 0;
if ( led_state ) {
DSK6713_LED_on (0);
led_state = 0;
} else {
DSK6713_LED_off (0);
led_state = 1;
}
}
if (++ period_indx >= period_count ) {
period_indx = 0;
}
short smpl ;
short dip = DSK6713_DIP_get (1);
if ( dip == 0) {
smpl = input_sample ();
} else {
smpl = sin_tbl [( period_indx * tbl_size )/ period_count ];
}
output_sample ( filt_buff [ idx ] = filt_buff [ idx =( idx +1)% delay ]* alpha + smpl *(1 - alpha ));
int dt = toc ();
// get timer value
return ;
// return from interrupt
}

Optimization 5
I removed removed the modular arithmetic. The run time went from 117 to 112 tics.
// Interrupt Service Routine
interrupt void c_int11 () {
tic ();
// start the timer
if ( ++ loopindex >= loop_count ) {
loopindex = 0;
if ( led_state ) {
DSK6713_LED_on (0);
led_state = 0;
} else {
DSK6713_LED_off (0);
led_state = 1;
}
}
if (++ period_indx >= period_count ) {
period_indx = 0;
}
short smpl ;
short dip = DSK6713_DIP_get (1);
if ( dip == 0) {
smpl = input_sample ();
} else {
smpl = sin_tbl [( period_indx * tbl_size )/ period_count ];
}
if (++ idx >= delay ) {
idx = 0;
}
output_sample ( filt_buff [ idx ] = filt_buff [ idx ]* alpha + smpl *(1 - alpha ));
int dt = toc ();
// get timer value
return ;
// return from interrupt
}

Failed optimization
The original iteration was pretty sparse of floating point operations (with the only exception being the setup which I didnt
count in the runtime and the multiplication of the alpha factors). I tried computing the alpha multiplications with fixed
point ops, however it actually reduced the performance by a factor of about 2 (presumably because of the increase in the
total number of ops required - extra divisions for normalization).

Optimized source code


// sine8_intr . c Assignment 2 solution : Nolan Miller
# include " DSK6713_AIC23 . h "
// codec support
# include < math .h >
# include < csl_timer .h >
# include < csl .h >
# include < csl_irq .h >
Uint32 fs = D S K 6 7 1 3 _ A I C 2 3 _ F R E Q _ 4 4 K H Z ;
// set sampling rate
# define D S K 6 7 1 3 _ A I C 2 3 _ I N P U T _ M I C 0 x0015
# define D S K 6 7 1 3 _ A I C 2 3 _ I N P U T _ L I N E 0 x0011
Uint16 inputsource = D S K 6 7 1 3 _ A I C 2 3 _ I N P U T _ M I C ; // select input
short loopindex = 0;

// look up table index

// Uint16 sps = 44100;


# define FLASH_RATE 2 // Hz
Uint16 loop_count = (44100 / (2 * FLASH_RATE ));
short led_state = 0;
# define AUDIO_FREQ 100
Uint16 period_indx = 0;
Uint16 period_count = (44100 / ( AUDIO_FREQ ));
# define tbl_size 100
short sin_tbl [ tbl_size ] = {0};
// {0 , 643 , 985 , 866 , 342 , -342 , -866 , -985 , -643 , 0};
# define gain 10000
# define M_PI 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6
// // GIVES US A TIMER ////
TIMER_Handle tm ;
void timer_init (){
tm = TIMER_open ( TIMER_DEV1 , TIMER_OPEN_RESET );
TIMER_configArgs ( tm , TIMER_CTL_RMK (
TIMER_CTL_INVINP_NO ,
TIMER_CTL_CLKSRC_CPUOVR4 ,
TIMER_CTL_CP_PULSE ,
TIMER_CTL_HLD_YES ,
TIMER_CTL_GO_NO ,
TIMER_CTL_PWID_ONE ,
TIMER_CTL_DATOUT_0 ,
TIMER_CTL_INVOUT_NO ,
T I ME R _ CT L _ FU N C _G P I O ) , 0 x00100000 , 0 x00000000 );
}
void tic () { TIMER_start ( tm );}
int toc () { return TIMER_getCount ( tm );}
// // BACK TO THE CODE NOW ////
void init_sin_tbl () {
int i ;
for ( i = 0; i < tbl_size ; i ++) {
sin_tbl [ i ] = ( short ) round ( gain * sin ( i *( M_PI *2.0/( tbl_size -1))));
}
}
5

# define delay 10000


short filt_buff [ delay ] = {0};
float alpha = .3;
short idx = 0;
// Interrupt Service Routine
interrupt void c_int11 () {
tic (); // start the timer
if ( ++ loopindex >= loop_count ) {
loopindex = 0;
if ( led_state ) {
DSK6713_LED_on (0);
led_state = 0;
} else {
DSK6713_LED_off (0);
led_state = 1;
}
}
if (++ period_indx >= period_count ) {
period_indx = 0;
}
short smpl ;
short dip = DSK6713_DIP_get (1);
if ( dip == 0) {
smpl = input_sample ();
} else {
smpl = sin_tbl [( period_indx * tbl_size )/ period_count ];
}
if (++ idx >= delay ) {
idx = 0;
}
output_sample ( filt_buff [ idx ] = filt_buff [ idx ]* alpha + smpl *(1 - alpha ));
int dt = toc ();
// get timer value
return ;
// return from interrupt
}
void main () {
init_sin_tbl ();
timer_init (); // setup the timer
DSK6713_LED_init ();
DSK6713_DIP_init ();
comm_intr ();
// initialise DSK
while (1);
// infinite loop
}

You might also like