From 6fed874fc8159ca21ae029f21b06357a5f1eb2b4 Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Mon, 15 Nov 2004 13:00:48 +0000 Subject: --- FFT_Test/Copy of reverb.hcc | 246 ++++++++++++++++++++++++ FFT_Test/FFT_Test.hp | 291 ++++++++++++++++++++++++++++ FFT_Test/FFT_Test.pref | 105 +++++++++++ FFT_Test/FFT_test.hw | 2 + FFT_Test/config.hch | 10 + FFT_Test/debug.hcc | 92 +++++++++ FFT_Test/debug.hch | 51 +++++ FFT_Test/fft.hcc | 409 ++++++++++++++++++++++++++++++++++++++++ FFT_Test/fft.hch | 8 + FFT_Test/fft_hardware.hcc | 449 +++++++++++++++++++++++++++++++++++++++++++ FFT_Test/fft_new.hcc | 271 ++++++++++++++++++++++++++ FFT_Test/fft_old.hcc | 274 +++++++++++++++++++++++++++ FFT_Test/int_fft.hcc | 306 ++++++++++++++++++++++++++++++ FFT_Test/int_fft.hch | 1 + FFT_Test/main.hcc | 80 ++++++++ FFT_Test/presets.hch | 32 ++++ FFT_Test/reverb_4000.hcc | 385 +++++++++++++++++++++++++++++++++++++ FFT_Test/reverb_new.hcc | 450 ++++++++++++++++++++++++++++++++++++++++++++ FFT_Test/reverb_old.hcc | 385 +++++++++++++++++++++++++++++++++++++ FFT_Test/reverb_test.hcc | 396 ++++++++++++++++++++++++++++++++++++++ FFT_Test/runfft.hcc | 216 +++++++++++++++++++++ FFT_Test/runfft.hch | 1 + FFT_Test/runfft_test.hcc | 381 +++++++++++++++++++++++++++++++++++++ FFT_Test/weights256.hch | 267 ++++++++++++++++++++++++++ 24 files changed, 5108 insertions(+) create mode 100644 FFT_Test/Copy of reverb.hcc create mode 100644 FFT_Test/FFT_Test.hp create mode 100644 FFT_Test/FFT_Test.pref create mode 100644 FFT_Test/FFT_test.hw create mode 100644 FFT_Test/config.hch create mode 100644 FFT_Test/debug.hcc create mode 100644 FFT_Test/debug.hch create mode 100644 FFT_Test/fft.hcc create mode 100644 FFT_Test/fft.hch create mode 100644 FFT_Test/fft_hardware.hcc create mode 100644 FFT_Test/fft_new.hcc create mode 100644 FFT_Test/fft_old.hcc create mode 100644 FFT_Test/int_fft.hcc create mode 100644 FFT_Test/int_fft.hch create mode 100644 FFT_Test/main.hcc create mode 100644 FFT_Test/presets.hch create mode 100644 FFT_Test/reverb_4000.hcc create mode 100644 FFT_Test/reverb_new.hcc create mode 100644 FFT_Test/reverb_old.hcc create mode 100644 FFT_Test/reverb_test.hcc create mode 100644 FFT_Test/runfft.hcc create mode 100644 FFT_Test/runfft.hch create mode 100644 FFT_Test/runfft_test.hcc create mode 100644 FFT_Test/weights256.hch diff --git a/FFT_Test/Copy of reverb.hcc b/FFT_Test/Copy of reverb.hcc new file mode 100644 index 0000000..7d21e6d --- /dev/null +++ b/FFT_Test/Copy of reverb.hcc @@ -0,0 +1,246 @@ +/**************************************************************** +* * +* Copyright (C) 1991-2003 Celoxica Ltd. All rights reserved. * +* * +***************************************************************** +* * +* Project : PAL * +* Date : 31 JAN 2003 * +* File : reverb.hcc * +* Author : Matthew Aubury (MA) * +* Contributors: * +* * +* Description: * +* Simple audio reverb. * +* * +* Date Version Author Reason for change * +* * +* 29 OCT 2002 1.00 MA Created * +* * +****************************************************************/ +#define PAL_TARGET_CLOCK_RATE 25175000 + + +#include +#include "pal_master.hch" + +#include "debug.hch" +#include "fft.hch" + +#include "presets.hch" +#include "config.hch" +/* + * Forward declarations + */ + +static macro proc RunFFT (AudioIn, AudioOut); +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +//input buffer +ram signed 16 audio_buffer_in[256] with { block = "BlockRAM"}; +//output buffer +ram signed 16 audio_buffer_out[128] with { block = "BlockRAM"}; +//EQ settings for the FFT +ram unsigned 4 EQ_info[128] with { block = "BlockRAM"}; +//EQ settings received from the display +mpram +{ + ram unsigned 4 write[768]; + rom unsigned 4 read[768]; +}EQ_level with { block = "BlockRAM"}; + +mpram +{ + ram unsigned 7 write[256]; + rom unsigned 7 read[256]; +}fft_info with { block = "BlockRAM"}; + +signed 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +signed 16 *audioptr_out1,*audioptr_out2; +signed 16 *audioptr_temp; + +unsigned 3 active_preset; + +shared expr preset_address = (0@(active_preset-1))<<7; +/* + * Main program + */ +void main(void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + + } + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,6,6); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + } + } +} + +void LoadPresets() +{ + unsigned 16 temp; + unsigned 10 count; + unsigned 8 index; + + count=0; + do + { + par + { + temp = presets[index]; + index++; + } + par { EQ_level.write[count] = temp[7:4]; count++; } + par { EQ_level.write[count] = temp[3:0]; count++; } + par { EQ_level.write[count] = temp[15:12]; count++; } + par { EQ_level.write[count] = temp[11:8]; count++; } + } while (count<768); + +} + +/* + * FFT routine + */ +static macro proc RunFFT (AudioIn, AudioOut) +{ + signed 16 sample; + unsigned 6 sample_count; + unsigned 8 i; + unsigned 4 eqinfo; + + unsigned 1 FFT_Sync; + macro expr OW = PalAudioOutGetMaxDataWidthCT (); + macro expr IW = PalAudioInGetMaxDataWidthCT (); + signed LeftNew, RightNew; + signed Output_sample; + + active_preset = 3; + + //pointers for double and quadruple buffering: + audioptr_in1=&audio_buffer_in[0]; + audioptr_in2=&audio_buffer_in[64]; + audioptr_in3=&audio_buffer_in[128]; + audioptr_in4=&audio_buffer_in[192]; + + audioptr_out1=&audio_buffer_out[0]; + audioptr_out2=&audio_buffer_out[64]; + + FFT_Sync=0; + + LoadPresets(); +par +{ + for(;;) + { + if (FFT_Sync) //if 64 samples are read from ADC... + { + par + { + // switch pointers + audioptr_in1 = audioptr_in2; + audioptr_in2 = audioptr_in3; + audioptr_in3 = audioptr_in4; + audioptr_in4 = audioptr_in1; + + audioptr_out1 = audioptr_out2; + audioptr_out2 = audioptr_out1; + + FFT_Sync=0; + } + + // FFT calculation + perform_fft(audioptr_in1); + + /* for(i=0;i>1) + +#define DC_COMPONENT 8470527 +#define DC_COMPONENT_HARDWARE 131072 + +sema eq_RAM_sema; +unsigned 1 display_log; diff --git a/FFT_Test/debug.hcc b/FFT_Test/debug.hcc new file mode 100644 index 0000000..44736e3 --- /dev/null +++ b/FFT_Test/debug.hcc @@ -0,0 +1,92 @@ +#include + +#include "pal_master.hch" + +#include "debug.hch" + +void print_hex_value(unsigned value) +{ + unsigned 8 ch; + unsigned 4 i; + unsigned 32 tempvalue; + + tempvalue = 0 @ value; + + for(i = 0;i < 8;i++) + { + ch = 0 @ (tempvalue\\28); + tempvalue <<= 4; + ch += (ch > 9) ? 0x37 : 0x30; + PalDataPortWrite(PalRS232PortCT(0), ch); + } +} + + +void print_signed_hex_value(signed value, unsigned 6 size) +{ + unsigned 8 ch; + unsigned 4 i; + signed 32 stempvalue; + unsigned 32 utempvalue; + unsigned 6 bit; + unsigned 1 inverse; + + if(value & (1<> bit); + bit = size; + } + } + PalDataPortWrite(PalRS232PortCT(0), '-'); + } + else + { + utempvalue = (unsigned)stempvalue; + } + +/* if(stempvalue[size]==1) + { + PalDataPortWrite(PalRS232PortCT(0), '-'); + mask = ~(0 @ (1< 9) ? 0x37 : 0x30; + PalDataPortWrite(PalRS232PortCT(0), ch); + } +} + +void print_string(unsigned char *s) { + unsigned 10 i; + i = 0; + for(i = 0;'\0' != s[i];i++) + { + PalDataPortWrite(PalRS232PortCT(0), s[i]); + } + +} + +void print_eol(void) +{ + PalDataPortWrite(PalRS232PortCT(0), 0x0A); +// PalDataPortWrite(PalRS232PortCT(0), 0x0D); +} \ No newline at end of file diff --git a/FFT_Test/debug.hch b/FFT_Test/debug.hch new file mode 100644 index 0000000..9a661c9 --- /dev/null +++ b/FFT_Test/debug.hch @@ -0,0 +1,51 @@ +/**************************************************************************** + * + * print_hex_value (unsigned value) + * + * Arguments: (typical) + * value: The integer which will be printed + * + * Description: (typical) + * This function will print the integer through the RS232 interface in a + * 32-bit hexadecimal representation. + * Pre: Value must be smaller or equal to 32-bits. + * Post: A hex representation of value is printed. + * + ****************************************************************************/ +void print_hex_value(unsigned value); + + +/**************************************************************************** + * + * print_hex_value (signed value, ) + * + * Arguments: (typical) + * value: The integer which will be printed + * size: The width of the integer to be printed + * Description: (typical) + * This function will print the integer through the RS232 interface in a + * 32-bit hexadecimal representation. + * Pre: Value must be smaller or equal to 32-bits, and the value must be + signed. + * Post: A hex representation of value is printed. + * + ****************************************************************************/ +void print_signed_hex_value(signed value, unsigned 6 size); + +/**************************************************************************** + * + * print_string (unsigned char *s) + * + * Arguments: (typical) + * s: Pointer to an array containg a string top print. + * + * Description: (typical) + * This function will print a string through the RS232 interface. + * Pre: The array must be /0 terminated. + * Post: The string is printed as is. + * + ****************************************************************************/ +void print_string(unsigned char *s); + + +void print_eol(void); \ No newline at end of file diff --git a/FFT_Test/fft.hcc b/FFT_Test/fft.hcc new file mode 100644 index 0000000..82a1a29 --- /dev/null +++ b/FFT_Test/fft.hcc @@ -0,0 +1,409 @@ +#include +#include +#include "weights256.hch" +#include "config.hch" +#include "debug.hch" +#include "xilinxmult.hch" + +#define PERFORM_FFT_CALCULATION 1 +#define USE_UNSIGNED_AUDIO 0 +#define HARDWARE_MULTIPLY 1 +#define PRINT_DEBUG 0 +/* Define two multi-port RAMs for FFT calculation; one for real and one for imaginary values + * Extra block RAM settings are defined to make sure read and write actions can be performed + * within one clock-cycle. + * Left out extra settings on new board the clock changes TODO !!!! + */ +mpram +{ + ram signed 24 rwrite[256]; + rom signed 24 read[256]; +} real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +mpram +{ + ram signed 24 rwrite[256]; + rom signed 24 read[256]; +} imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +// multiplication factors for equalizer function +ram signed 7 eq_settings[16] = {0,2,4,7,10,13,16,19,22,26,30,35,41,48,55,63}; + + +/**************************************************************** +* Function: multiply * +* * +* Arguments * +* x,y signed variables * +* * +* Description * +* Just a multiplier. But by doing this in a function the * +* FPGA space needed is reduced. * +* * +* Return Values * +* The result after multiplication * +****************************************************************/ +macro proc multiply(result, op_a, op_b) +{ +#if HARDWARE_MULTIPLY + xilinxmult(result, adjs(op_a,18), adjs(op_b,18)); +#else + macro expr mul_width = (width(op_a) + width(op_b)); + result = adjs(op_a, mul_width) * adjs(op_b, mul_width); +#endif +/* signed result; + + fixed_mul(result,x,y); + return result;*/ +} +/*macro proc multiply(result, x,y) +{ +#if HARDWARE_MULTIPLY + xilinxmult(result, adjs(x,18), adjs(y,18)); +#else + result = ((adjs(x,36))*(adjs(y,36))); +#endif + +} +*/ + + + +/******************************************************************* +* Function: calculate_fft * +* * +* Arguments * +* select_inverse Boolean that indicates FFT or iFFT calculation * +* * +* Description * +* This routine performs the Fast Fourier Transform for * +* calculation of the frequency spectrum * +* * +*******************************************************************/ +void calculate_fft(unsigned 1 select_inverse) +{ + unsigned 4 level; + unsigned 8 point1,point2,j,f,k; + unsigned 9 e,i; + signed 16 weight1,weight2; + signed 24 p,q,r,t; + signed a,b; + + macro expr rescale (x) = (x[35] @ x[28:14]); + + for(level=1;level<=NUMBER_OF_COLUMNS;level++) // count all the columns + { + e=1<<(NUMBER_OF_COLUMNS-level+1); // number of points in each block in this column + f=(e>>1)<-8; // number of butterflies in each block in this column + + for(j=1;j<=f;j++) // count all the butterflies in each block + { + par + { + // Weight factors for real (the same for FFT and iFFT) + weight1 = weight_re[((j-1)<<(level-1))<-7]; + + + // Weight factors for imaginary (opposite for FFT and iFFT) + weight2 = (!select_inverse) ? (weight_im[((j-1)<<(level-1))<-7]) : -(weight_im[((j-1)<<(level-1))<-7]); + + /* ORIGINAL CODE BELOW, MODIFIED BECAUSE OF MISMATCHING OUTPUT WITH BORLAND TESTAPP + weight2 = (!select_inverse) ? -(weight_im[((j-1)<<(level-1))<-7]) : weight_im[((j-1)<<(level-1))<-7]; + */ + + + + for(i=0@j;i<=NUMBER_OF_POINTS;i+=e) // count all the blocks in this column + { // Butterfly calculation + par + { + point1 = ((i<-8)-1); + point2 = (((i<-8)+f)-1); + } + + par + { + p=real.read[point1]+real.rwrite[point2]; + q=imaginary.read[point1]+imaginary.rwrite[point2]; + } + + par + { + r=real.read[point1]-real.rwrite[point2]; + t=imaginary.read[point1]-imaginary.rwrite[point2]; + } + + multiply(a,r,weight1); + multiply(b,t,weight2); + + par + { + real.rwrite[point2] = ((a-b)>>FRACBITS)<-24; + imaginary.rwrite[point1] = q; + } + + multiply(a,t,weight1); + multiply(b,r,weight2); + + par + { + real.rwrite[point1] = p; + imaginary.rwrite[point2] = ((a+b)>>FRACBITS)<-24; + } + + } + } + } + } + + j=1; + for(i=1;i>1; + + + while(k>1; + } + + j+=k; + } + +} + +/********************************************************************/ + +void perform_fft(signed 16 *pcm_audio) +{ + unsigned 8 k; + signed 24 sample; +#if USE_UNSIGNED_AUDIO + unsigned 24 utemp; + signed 24 stemp; +#endif + + //initialize variables for the copying pipeline + k=0; + sample = adjs(pcm_audio[k],24); + // copy audio data to real-array before starting FFT calculation + // and set imaginary values to zero + do + { +#if USE_UNSIGNED_AUDIO + stemp = adjs(pcm_audio[k],24); + stemp >>= 1; + utemp = 0@((unsigned)((stemp + 32768)<-16)); + real.rwrite[k] = (signed)(utemp); +#else + //Copying the array values has been pipelined to prevent parallel access to the + //pcm_audio array. This copying procedure must be finished before another + //sample is read from the audio input. The time available for this loop is + //determined by the sampling rate of 44,1 Khz + par + { + //COPYING NEEDS TO BE DONE IN 2 STEPS, BECAUSE THE VALUE THAT NEEDS TO WRITTEN + //TO THE REAL-RAM NEEDS TO BE AVAILABLE ON THE START OFF THE CLOCKCYCLE. + sample = adjs(pcm_audio[k+1],24); + real.rwrite[k] = sample; + imaginary.rwrite[k] = 0; + k++; + } + +#endif + } while (k); + + + +#if PERFORM_FFT_CALCULATION + calculate_fft(0); +#endif + + +} + +/********************************************************************/ + +void perform_ifft(signed 16 *modified_audio/*, unsigned 6 *ifft_info*/) +{ + unsigned 6 k; + signed 24 p; + +#if PERFORM_FFT_CALCULATION + calculate_fft(1); +#endif + + k=0; +#if PRINT_DEBUG + do + { + print_string("real["); + print_hex_value(0@k); + print_string("]: "); + print_hex_value((unsigned)real.read[k]); + print_string(" imaginary["); + print_hex_value(0@k); + print_string("]: "); + print_hex_value((unsigned)imaginary.read[k]); + print_eol(); + k++; + } + while(k!=0); +#endif +//initialize variables for the copying pipeline +#if PERFORM_FFT_CALCULATION + p = (real.read[(0@k)+95] >> NUMBER_OF_COLUMNS); +#else + p = (real.read[(0@k)+95]); +#endif + + do + { + //Copying the array values has been pipelined to prevent parallel access to the + //pcm_audio array. This copying procedure must be finished before another + //sample is read from the audio input. The time available for this loop is + //determined by the sampling rate of 44,1 Khz + par + { +#if PERFORM_FFT_CALCULATION + // divide samples by number of points + p = (real.read[(0@k+1)+95] >> NUMBER_OF_COLUMNS); +#else + p = (real.read[(0@k+1)+95]); +#endif +#if USE_UNSIGNED_AUDIO + p -= 32768; + p <<= 1; +#endif + modified_audio[k] = (p <-16); + //ifft_info[k] = (unsigned)(p[15:10]); + k++; + } + } while(k); +} + +/********************************************************************/ +void equalize_audio(unsigned 4 *eq_level, unsigned 7 *fft_info) +{ +#if 0 + signed 24 p,q; + signed 16 a; + unsigned 8 i, mirror_i, bit, m, n; + unsigned 7 old_value; + unsigned 9 tmp; + + //macro expr equalize_bar = adjs(q,24)-adjs(a,24); + + macro proc equalize_bar() + { + signed result; + multiply(result, q,a); + return result[29:6]; + } + + p = real.read[0] - DC_COMPONENT; // remove DC component for calculations + real.rwrite[0] = p; +// imaginary.rwrite[0] = 0; // remove DC component + + + for(i=0;i<=NUMBER_OF_FREQUENCIES;i++) + { + // set multiplication factor (0..64) for current frequency bar + a = adjs(eq_settings[eq_level[i<-7]],16); + + // multiply frequency with this factor and divide by 64 (drop 6 LSB's) + q = real.read[i]; + p = equalize_bar; + real.rwrite[i] = p; + + q = imaginary.read[i]; + p = equalize_bar; + imaginary.rwrite[i] = p; + + // the upper part(128..255) of the spectrum is mirrored to the lower part; + // these values need to be adjusted too + if ((i<-7)!=0) // if not in DC component bar + { + mirror_i = (NUMBER_OF_POINTS-1)-i+1; + q = real.read[mirror_i]; + p = equalize_bar; + real.rwrite[mirror_i] = p; + + q = imaginary.read[mirror_i]; + p = equalize_bar; + imaginary.rwrite[mirror_i] = p; + } + } + + //write data to fft_info for display purposes + for(i=0;i>1; + fft_info[i<-7] = (old_value <= (tmp<-7)) ? (tmp<-7) : old_value-1; + } + else + { + old_value = fft_info[i<-7]; + fft_info[i<-7] = (old_value<=(unsigned)(p[21:15])) ? (unsigned)(p[21:15]) : old_value-1; + } + } + + // add DC component again before inverse FFT calculation is performed + p = real.read[0] + DC_COMPONENT; + real.rwrite[0] = p; +#endif +} diff --git a/FFT_Test/fft.hch b/FFT_Test/fft.hch new file mode 100644 index 0000000..6bcc8cc --- /dev/null +++ b/FFT_Test/fft.hch @@ -0,0 +1,8 @@ +#if HARDWARE_MULTIPLY +void perform_fft(signed 18 *pcm_audio); +void perform_ifft(signed 18 *modified_audio /*,unsigned 6 *ifft_info*/); +#else +void perform_fft(signed 16 *pcm_audio); +void perform_ifft(signed 16 *modified_audio /*,unsigned 6 *ifft_info*/); +#endif +void equalize_audio(unsigned 4 *eq_level, unsigned 7 *fft_info); diff --git a/FFT_Test/fft_hardware.hcc b/FFT_Test/fft_hardware.hcc new file mode 100644 index 0000000..8977a83 --- /dev/null +++ b/FFT_Test/fft_hardware.hcc @@ -0,0 +1,449 @@ +#include +#include +#include "weights256.hch" +#include "config.hch" +#include "debug.hch" +#include "xilinxmult.hch" + +#define PERFORM_FFT_CALCULATION 1 +#define USE_UNSIGNED_AUDIO 0 +#define PRINT_DEBUG 0 +/* Define two multi-port RAMs for FFT calculation; one for real and one for imaginary values + * Extra block RAM settings are defined to make sure read and write actions can be performed + * within one clock-cycle. + * Left out extra settings on new board the clock changes TODO !!!! + */ +#if HARDWARE_MULTIPLY +mpram +{ + ram signed 18 rwrite[256]; + rom signed 18 read[256]; +} real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +mpram +{ + ram signed 18 rwrite[256]; + rom signed 18 read[256]; +} imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; +#else +mpram +{ + ram signed 24 rwrite[256]; + rom signed 24 read[256]; +} real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +mpram +{ + ram signed 24 rwrite[256]; + rom signed 24 read[256]; +} imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; +#endif +// multiplication factors for equalizer function +ram signed 7 eq_settings[16] = {0,2,4,7,10,13,16,19,22,26,30,35,41,48,55,63}; + + +/**************************************************************** +* Function: multiply * +* * +* Arguments * +* x,y signed variables * +* * +* Description * +* Just a multiplier. But by doing this in a function the * +* FPGA space needed is reduced. * +* * +* Return Values * +* The result after multiplication * +****************************************************************/ +macro proc multiply(result, op_a, op_b) +{ +#if HARDWARE_MULTIPLY + xilinxmult(result, op_a, adjs(op_b,18)); +#else + result = (adjs(op_a,38))*(adjs(op_a,38)); +#endif +} + + + + +/******************************************************************* +* Function: calculate_fft * +* * +* Arguments * +* select_inverse Boolean that indicates FFT or iFFT calculation * +* * +* Description * +* This routine performs the Fast Fourier Transform for * +* calculation of the frequency spectrum * +* * +*******************************************************************/ +void calculate_fft(unsigned 1 select_inverse) +{ + unsigned 4 level; + unsigned 8 point1,point2,j,f,k; + unsigned 9 e,i; + signed 16 weight1,weight2; +#if HARDWARE_MULTIPLY + signed 18 p,q,r,t; +#else + signed 24 p,q,r,t; +#endif + signed a,b; + +#if HARDWARE_MULTIPLY + // Macro to provide rescaling of 36-bit result of fixed point multiply + // down to an 18-bit result. The range of bits selected depends on the + // number that represents the value of "1" in the trig function lookup + // tables. (Eg. for 16384 == 1, the lowest bit selected should be [14]). + macro expr rescale (x) = (x[35] @ x[30:14]); +#else + //Macro to rescale the multiply result down to a 24-bit value. + macro expr rescale (x) = ((x>>FRACBITS)<-24); +#endif + + for(level=1;level<=NUMBER_OF_COLUMNS;level++) // count all the columns + { + e=1<<(NUMBER_OF_COLUMNS-level+1); // number of points in each block in this column + f=(e>>1)<-8; // number of butterflies in each block in this column + + for(j=1;j<=f;j++) // count all the butterflies in each block + { + par + { + // Weight factors for real (the same for FFT and iFFT) + weight1 = weight_re[((j-1)<<(level-1))<-7]; + + + // Weight factors for imaginary (opposite for FFT and iFFT) + weight2 = (!select_inverse) ? (weight_im[((j-1)<<(level-1))<-7]) : -(weight_im[((j-1)<<(level-1))<-7]); + + /* ORIGINAL CODE BELOW, MODIFIED BECAUSE OF MISMATCHING OUTPUT WITH BORLAND TESTAPP + weight2 = (!select_inverse) ? -(weight_im[((j-1)<<(level-1))<-7]) : weight_im[((j-1)<<(level-1))<-7]; + */ + + + + for(i=0@j;i<=NUMBER_OF_POINTS;i+=e) // count all the blocks in this column + { // Butterfly calculation + par + { + point1 = ((i<-8)-1); + point2 = (((i<-8)+f)-1); + } + + par + { + p = (real.read[point1] >> 1) + (real.rwrite[point2] >> 1); + q = (imaginary.read[point1] >> 1) + (imaginary.rwrite[point2] >> 1); + } + + par + { + r = (real.read[point1] >> 1) - (real.rwrite[point2] >> 1); + t = (imaginary.read[point1] >> 1) - (imaginary.rwrite[point2] >> 1); + } + + multiply(a,r,weight1); + multiply(b,t,weight2); + + par + { + real.rwrite[point2] = (rescale(a-b)); + imaginary.rwrite[point1] = q; + } + + multiply(a,t,weight1); + multiply(b,r,weight2); + + par + { + real.rwrite[point1] = p; + imaginary.rwrite[point2] = (rescale(a+b)); + } + + } + } + } + } + + j=1; + for(i=1;i>1; + + + while(k>1; + } + + j+=k; + } + +} + +/********************************************************************/ +#if HARDWARE_MULTIPLY +void perform_fft(signed 18 *pcm_audio) +#else +void perform_fft(signed 16 *pcm_audio) +#endif +{ + unsigned 8 k; + + +#if HARDWARE_MULTIPLY + signed 18 sample; + k=0; + sample = adjs(pcm_audio[k],18); +#else + signed 24 sample; + k=0; + sample = adjs(pcm_audio[k],24); +#endif + + //initialize variables for the copying pipeline + + + // copy audio data to real-array before starting FFT calculation + // and set imaginary values to zero + do + { + //Copying the array values has been pipelined to prevent parallel access to the + //pcm_audio array. This copying procedure must be finished before another + //sample is read from the audio input. The time available for this loop is + //determined by the sampling rate of 44,1 Khz + par + { + //COPYING NEEDS TO BE DONE IN 2 STEPS, BECAUSE THE VALUE THAT NEEDS TO WRITTEN + //TO THE REAL-RAM NEEDS TO BE AVAILABLE ON THE START OFF THE CLOCKCYCLE. +#if HARDWARE_MULTIPLY + sample = adjs(pcm_audio[k+1],18); +#else + sample = adjs(pcm_audio[k+1],24); +#endif + real.rwrite[k] = sample; + imaginary.rwrite[k] = 0; + k++; + } + } while (k); + + + +#if PERFORM_FFT_CALCULATION + calculate_fft(0); +#endif + + +} + +/********************************************************************/ +#if HARDWARE_MULTIPLY +void perform_ifft(signed 18 *modified_audio/*, unsigned 6 *ifft_info*/) +#else +void perform_ifft(signed 16 *modified_audio/*, unsigned 6 *ifft_info*/) +#endif +{ + unsigned 6 k; +#if HARDWARE_MULTIPLY + signed 18 p; +#else + signed 24 p; +#endif +#if PERFORM_FFT_CALCULATION + calculate_fft(1); +#endif + + k=0; +//initialize variables for the copying pipeline +#if PERFORM_FFT_CALCULATION + #if HARDWARE_MULTIPLY + p = (real.read[(0@k)+95] << NUMBER_OF_COLUMNS); + #else + p = (real.read[(0@k)+95] >> NUMBER_OF_COLUMNS); + #endif +#else + p = (real.read[(0@k)+95]); +#endif + + do + { + //Copying the array values has been pipelined to prevent parallel access to the + //pcm_audio array. This copying procedure must be finished before another + //sample is read from the audio input. The time available for this loop is + //determined by the sampling rate of 44,1 Khz + par + { +#if PERFORM_FFT_CALCULATION + #if HARDWARE_MULTIPLY + p = (real.read[(0@k)+95] << NUMBER_OF_COLUMNS); + #else + p = (real.read[(0@k)+95] >> NUMBER_OF_COLUMNS); + #endif +#else + p = (real.read[(0@k)+95]); +#endif +#if HARDWARE_MULTIPLY + modified_audio[k] = p ; +#else + modified_audio[k] = (p<-16); +#endif + //ifft_info[k] = (unsigned)(p[15:10]); + k++; + } + } while(k); +} + +/********************************************************************/ +void equalize_audio(unsigned 4 *eq_level, unsigned 7 *fft_info) +{ +#if 1 +#if HARDWARE_MULTIPLY + signed 18 p,q; +#else + signed 24 p,q; +#endif + signed 16 a; + unsigned 8 i, mirror_i, bit, m, n; + unsigned 7 old_value; + unsigned 9 tmp; + + //macro expr equalize_bar = multiply(q,a)[29:6]; + + macro proc equalize_bar(retval) + { + signed result; + multiply(result, q,a); +#if HARDWARE_MULTIPLY + retval = result[23:6]; //drop last 6 bit to compensate the maximum multiplication with 64 from the eq_settings array +#else + retval = result[29:6]; //drop last 6 bit to compensate the maximum multiplication with 64 from the eq_settings array +#endif + } +#if HARDWARE_MULTIPLY + p = real.read[0] - DC_COMPONENT_HARDWARE; +#else + p = real.read[0] - DC_COMPONENT; // remove DC component for calculations +#endif + real.rwrite[0] = p; +// imaginary.rwrite[0] = 0; // remove DC component + + + for(i=0;i<=NUMBER_OF_FREQUENCIES;i++) + { + // set multiplication factor (0..64) for current frequency bar + a = 63;// adjs(eq_settings[eq_level[i<-7]],16); + + // multiply frequency with this factor and divide by 64 (drop 6 LSB's) + q = real.read[i]; + equalize_bar(p); + real.rwrite[i] = p; + + q = imaginary.read[i]; + equalize_bar(p); + imaginary.rwrite[i] = p; + + // the upper part(128..255) of the spectrum is mirrored to the lower part; + // these values need to be adjusted too + if ((i<-7)!=0) // if not in DC component bar + { + mirror_i = (NUMBER_OF_POINTS-1)-i+1; + q = real.read[mirror_i]; + equalize_bar(p); + real.rwrite[mirror_i] = p; + + q = imaginary.read[mirror_i]; + equalize_bar(p); + imaginary.rwrite[mirror_i] = p; + } + } + + //write data to fft_info for display purposes + for(i=0;i>1; + fft_info[i<-7] = (old_value <= (tmp<-7)) ? (tmp<-7) : old_value-1; + } + else + { + old_value = fft_info[i<-7]; +#if HARDWARE_MULTIPLY + fft_info[i<-7] = (old_value<=(unsigned)(p[15:9])) ? (unsigned)(p[15:9]) : old_value-1; +#else + fft_info[i<-7] = (old_value<=(unsigned)(p[21:15])) ? (unsigned)(p[21:15]) : old_value-1; +#endif + } + } + + // add DC component again before inverse FFT calculation is performed +#if HARDWARE_MULTIPLY + p = real.read[0] + DC_COMPONENT_HARDWARE; +#else + p = real.read[0] + DC_COMPONENT; +#endif + real.rwrite[0] = p; +#endif +} diff --git a/FFT_Test/fft_new.hcc b/FFT_Test/fft_new.hcc new file mode 100644 index 0000000..ca81c53 --- /dev/null +++ b/FFT_Test/fft_new.hcc @@ -0,0 +1,271 @@ +#include +#include +#include "fft.hch" +#include "weights256.hch" +#include "config.hch" +#include "debug.hch" + +//Define two multi-port RAMs for FFT calculation; one for real and one for imaginary values +//Extra block RAM settings are defined to make sure read and write actions can be performed +//within one clock-cycle. +mpram +{ + ram signed 32 rwrite[256]; + rom signed 32 read[256]; +} real with {block = "BlockRAM" /*block=4, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +mpram +{ + ram signed 32 rwrite[256]; + rom signed 32 read[256]; +} imaginary with {block = "BlockRAM" /*block=6, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +// multiplication factors for equalizer function +ram signed 7 eq_settings[16] = {0,2,4,7,10,13,16,19,22,26,30,35,41,48,55,63}; + + +/**************************************************************** +* Function: multiply * +* * +* Arguments * +* x,y signed variables * +* * +* Description * +* Just a multiplier. But by doing this in a function the * +* FPGA space needed is reduced. * +* * +* Return Values * +* The result after multiplication * +****************************************************************/ +signed multiply(signed x,signed y) +{ + return((adjs(x,40))*(adjs(y,40))); +} + + +/************************************************************************ +* Function: calculate_fft * +* * +* Arguments * +* select_inverse Boolean that indicates FFT or iFFT calculation * +* * +* Description * +* This routine performs the Fast Fourier Transform for * +* calculation of the frequency spectrum * +* * +************************************************************************/ +void calculate_fft(unsigned 1 select_inverse) +{ + unsigned 4 level; + unsigned 8 point1, point2, k, f, j; + unsigned 9 e, i; + signed 16 weight1,weight2; + signed 32 p,q,r,t; + signed 40 a,b; + +// float u,v,z,c,s,p,q,r,t,w,a; + + // n=1<>1)<-8; + + for(j=1;j<=f;j++) + { + weight1 = weight_re[((1<<(level-1))*(j-1))<-7]; + weight2 = (select_inverse) ? -weight_im[((1<<(level-1))*(j-1))<-7] : weight_im[((1<<(level-1))*(j-1))<-7]; + + for(i=0@j;i<=NUMBER_OF_POINTS;i+=e) + { + point1 = (i<-8)-1; + point2 = ((i<-8)+f)-1; + + p = real.read[point1] + real.read[point2]; + r = real.read[point1] - real.read[point2]; + q = imaginary.read[point1] + imaginary.read[point2]; + t = imaginary.read[point1] - imaginary.read[point2]; + + real.rwrite[point1] = p; + imaginary.rwrite[point1] = q; + + a = multiply(adjs(r,40),adjs(weight1,40)); + b = multiply(adjs(t,40),adjs(weight2,40)); + + real.rwrite[point2]=((a-b)>>FRACBITS)<-32; + + a = multiply(adjs(t,40),adjs(weight1,40)); + b = multiply(adjs(r,40),adjs(weight2,40)); + + imaginary.rwrite[point2]=((a-b)>>FRACBITS)<-32; + } + } + } + + j=1;// Bit reversing start + for(i=1;i>1; + + while(k>1; + } + j+=k; + }// Bit reversing end + +/* if(select_inverse) + { + a=(1<<14)>>NUMBER_OF_COLUMNS; + for(k=0;k<(adju(n,8));k++) + { + real.rwrite[k]*=(0@a); + imaginary.rwrite[k]*=(0@a); + } + }*/ +} + + +/********************************************************************/ + +void perform_fft(signed 16 *pcm_audio) +{ + unsigned 1 select_inverse; + unsigned 8 k; + + // copy audio data to real-array before starting FFT calculation + // and set imaginary values to zero + k=0; + do + par{ + real.rwrite[k] = 0@pcm_audio[k]; + imaginary.rwrite[k]=0; + k++; + } while (k!=0); + + select_inverse=0; + calculate_fft(select_inverse); + +} + +/********************************************************************/ + +void perform_ifft(signed 16 *modified_audio/*, unsigned 6 *ifft_info*/) +{ + unsigned 1 select_inverse; + unsigned 8 k; + signed 32 p; + + select_inverse=1; + calculate_fft(select_inverse); + + k=0; + do + { + // divide samples by number of points + p=(real.read[(k+95)]>>NUMBER_OF_COLUMNS); + + // write data to output buffer & display buffer + modified_audio[k<-6]=(p<-16); + //ifft_info[k]=(unsigned)(p[15:10]); + + print_string("Real["); + // print_hex_value(adju(k,16)); + print_string("]: "); + print_hex_value((unsigned)real.read[k]); + print_eol(); + + k++; + } while(k<64); +} + +/********************************************************************/ + +/*void equalize_audio(unsigned 4 *eq_level, unsigned 7 *fft_info) +{ + signed 24 p,q; + signed 16 a; + unsigned 8 i, mirror_i, bit, m, n; + unsigned 7 old_value; + unsigned 9 tmp; + + macro expr equalize_bar = multiply(q,a)[29:6]; + + //real.rwrite[0] = real.read[0] - DC_COMPONENT; // remove DC component for calculations +// imaginary.rwrite[0] = 0; // remove DC component + + + for(i=0;i<=NUMBER_OF_FREQUENCIES;i++) + { + // set multiplication factor (0..64) for current frequency bar + a = adjs(eq_settings[eq_level[i<-7]],16); + + // multiply frequency with this factor and divide by 64 (drop 6 LSB's) + q = real.read[i]; + real.rwrite[i] = equalize_bar; + + q=imaginary.read[i]; + imaginary.rwrite[i] = equalize_bar; + + // the upper part(128..255) of the spectrum is mirrored to the lower part; + // these values need to be adjusted too + if ((i<-7)!=0) // if not in DC component bar + { + mirror_i = (NUMBER_OF_POINTS-1)-i+1; + q = real.read[mirror_i]; + real.rwrite[mirror_i] = equalize_bar; + + q = imaginary.read[mirror_i]; + imaginary.rwrite[mirror_i] = equalize_bar; + }; + } + + //write data to fft_info for display purposes + for(i=0;i>1; + fft_info[i<-7] = (old_value<=(tmp<-7)) ? (tmp<-7) : old_value-1; + } else { + old_value = fft_info[i<-7]; + fft_info[i<-7] = (old_value<=(unsigned)(p[21:15])) ? (unsigned)(p[21:15]) : old_value-1; + } + } + + // add DC component again before inverse FFT calculation is performed + //real.rwrite[0] = real.read[0] + DC_COMPONENT; +} +*/ \ No newline at end of file diff --git a/FFT_Test/fft_old.hcc b/FFT_Test/fft_old.hcc new file mode 100644 index 0000000..5c106bf --- /dev/null +++ b/FFT_Test/fft_old.hcc @@ -0,0 +1,274 @@ +#include +#include +#include "weights256.hch" +#include "config.hch" +#include "debug.hch" + +/* Define two multi-port RAMs for FFT calculation; one for real and one for imaginary values + * Extra block RAM settings are defined to make sure read and write actions can be performed + * within one clock-cycle. + * Left out extra settings on new board the clock changes TODO !!!! + */ +mpram +{ + ram signed 32 rwrite[256]; + rom signed 32 read[256]; +} real with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +mpram +{ + ram signed 32 rwrite[256]; + rom signed 32 read[256]; +} imaginary with {block = "BlockRAM"/*, westart=2.5, welength=1, rclkpos={1.5}, wclkpos={3}, clkpulselen=0.5*/}; + +// multiplication factors for equalizer function +ram signed 7 eq_settings[16] = {0,2,4,7,10,13,16,19,22,26,30,35,41,48,55,63}; + + +/**************************************************************** +* Function: multiply * +* * +* Arguments * +* x,y signed variables * +* * +* Description * +* Just a multiplier. But by doing this in a function the * +* FPGA space needed is reduced. * +* * +* Return Values * +* The result after multiplication * +****************************************************************/ +signed multiply(signed x,signed y) +{ + return(x*y); +} + + +/******************************************************************* +* Function: calculate_fft * +* * +* Arguments * +* select_inverse Boolean that indicates FFT or iFFT calculation * +* * +* Description * +* This routine performs the Fast Fourier Transform for * +* calculation of the frequency spectrum * +* * +*******************************************************************/ +void calculate_fft(unsigned 1 *select_inverse) +{ + unsigned 4 level; + unsigned 8 point1,point2,j,f,k; + unsigned 9 e,i; + signed 16 weight1,weight2; + signed 32 p,q,r,t; + signed 38 a,b; + + for(level=1;level<=NUMBER_OF_COLUMNS;level++) // count all the columns + { + e=1<<(NUMBER_OF_COLUMNS-level+1); // number of points in each block in this column + f=(e>>1)<-8; // number of butterflies in each block in this column + + for(j=1;j<=f;j++) + // count all the butterflies in each block + //par + { + // Weight factors for real (the same for FFT and iFFT) + weight1 = weight_re[((j-1)<<(level-1))<-7]; + + // Weight factors for imaginary (opposite for FFT and iFFT) + weight2 = (*select_inverse==0) ? -(weight_im[((j-1)<<(level-1))<-7]) : weight_im[((j-1)<<(level-1))<-7]; + + for(i=0@j;i<=NUMBER_OF_POINTS;i+=e) // count all the blocks in this column + { // Butterfly calculation + //par{ + point1 = ((i<-8)-1); + point2 = (((i<-8)+f)-1); + //} + //par{ + + p = real.read[point1]; + p += real.read[point2]; + + r = real.read[point1]; + r -= real.read[point2]; + + q = imaginary.read[point1]; + q += imaginary.read[point2]; + + t = imaginary.read[point1]; + t -= imaginary.read[point2]; + //} + a = multiply(adjs(r,38),adjs(weight1,38)); + b = multiply(adjs(t,38),adjs(weight2,38)); + //par{ + real.rwrite[point2] = ((a-b)>>FRACBITS)<-32; + imaginary.rwrite[point1] = q; + //} + a = multiply(adjs(t,38),adjs(weight1,38)); + b = multiply(adjs(r,38),adjs(weight2,38)); + //par{ + real.rwrite[point1] = p; + imaginary.rwrite[point2] = ((a+b)>>FRACBITS)<-32; + //} + } + } + } + k=0; + do + { + print_string("FFT["); + print_hex_value(adju(k,32)); + print_string("]: "); + print_hex_value((unsigned)(real.read[k])); + print_eol(); + k++; + } + while (k!=0); + // Start bit-reversing samples + j = 0; + for(i = 0;i < NUMBER_OF_POINTS;i++) + { + if(i < (0@j)) + { + // point1 = j-1; + // point2 = (i-1)<-8; + //par + //{ + //seq + //{ + p = real.read[j]; + real.rwrite[j] = real.read[i<-8]; + real.rwrite[i<-8] = p; + //} + //seq + //{ + q = imaginary.read[j]; + imaginary.rwrite[j] = imaginary.read[i<-8]; + imaginary.rwrite[i<-8] = q; + //} + //} + } + + k = NUMBER_OF_POINTS>>1; + + while((j>=k)&&(k>=2)) + { + j -= k; + k = k>>1; + } + j += k; + } // Bit reversing end +} + +/********************************************************************/ + +void perform_fft(signed 16 *pcm_audio) +{ + unsigned 1 select_inverse; + unsigned 8 k; + + // copy audio data to real-array before starting FFT calculation + // and set imaginary values to zero + k=0; + do + //par + { + real.rwrite[k] = (0@pcm_audio[k]); + imaginary.rwrite[k]=0; + k++; + } while (k!=0); + + do + { + print_string("IA["); + print_hex_value(adju(k,32)); + print_string("]: "); + print_hex_value((unsigned)(real.read[k])); + print_eol(); + k++; + } + while (k!=0); + select_inverse=0; + calculate_fft(&select_inverse); + + /* do + { + // print_signed_hex_value(real.read[k],32); + // print_eol(); + k++; + }while(k!=0);*/ +} + +/********************************************************************/ + +void perform_ifft(signed 16 *modified_audio/*, unsigned 6 *ifft_info*/) +{ + unsigned 1 select_inverse; + unsigned 8 k; + signed 32 p; + + select_inverse=1; + calculate_fft(&select_inverse); + + k=0; + do + { + // divide samples by number of points + p=(real.read[(k+95)]>>NUMBER_OF_COLUMNS); + + // write data to output buffer & display buffer + modified_audio[k <- 6] = (p<-16); + //ifft_info[k] = (unsigned)(p[15:10]); + // print_string("MA["); + // print_hex_value(adju(k,16)); + // print_string("]: "); + // print_hex_value((unsigned)(modified_audio[k])); + // print_eol(); + + k++; + } while(k[5:0] != 0); +} + +/********************************************************************/ + +void equalize_audio(unsigned 8 *fft_info) +{ + signed 32 p,q; + signed 38 a; + unsigned 8 i, mirror_i, old_value, m, n; + unsigned 8 bit; + unsigned 9 tmp; + + macro expr equalize_bar = multiply(adjs(q,38),a)[37:6]; + + real.rwrite[0] = real.read[0] - 8470527; // remove DC component for calculations +// imaginary.rwrite[0] = 0; // remove DC component + + //write data to fft_info for display purposes + for(i=0;i>1; + fft_info[i] = (old_value<=(tmp<-8)) ? (tmp<-8) : old_value-1; + } + + // add DC component again before IFFT calculation is performed + real.rwrite[0] = real.read[0] + 8470527; +} + diff --git a/FFT_Test/int_fft.hcc b/FFT_Test/int_fft.hcc new file mode 100644 index 0000000..2fadb6c --- /dev/null +++ b/FFT_Test/int_fft.hcc @@ -0,0 +1,306 @@ +/* fix_fft.c - Fixed-point Fast Fourier Transform */ +/* + fix_fft() perform FFT or inverse FFT + window() applies a Hanning window to the (time) input + fix_loud() calculates the loudness of the signal, for + each freq point. Result is an integer array, + units are dB (values will be negative). + iscale() scale an integer value by (numer/denom). + fix_mpy() perform fixed-point multiplication. + Sinewave[1024] sinewave normalized to 32767 (= 1.0). + Loudampl[100] Amplitudes for lopudnesses from 0 to -99 dB. + Low_pass Low-pass filter, cutoff at sample_freq / 4. + + + All data are fixed-point short integers, in which + -32768 to +32768 represent -1.0 to +1.0. Integer arithmetic + is used for speed, instead of the more natural floating-point. + + For the forward FFT (time -> freq), fixed scaling is + performed to prevent arithmetic overflow, and to map a 0dB + sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq + coefficients; the one in the lower half is reported as 0dB + by fix_loud(). The return value is always 0. + + For the inverse FFT (freq -> time), fixed scaling cannot be + done, as two 0dB coefficients would sum to a peak amplitude of + 64K, overflowing the 32k range of the fixed-point integers. + Thus, the fix_fft() routine performs variable scaling, and + returns a value which is the number of bits LEFT by which + the output must be shifted to get the actual amplitude + (i.e. if fix_fft() returns 3, each value of fr[] and fi[] + must be multiplied by 8 (2**3) for proper scaling. + Clearly, this cannot be done within the fixed-point short + integers. In practice, if the result is to be used as a + filter, the scale_shift can usually be ignored, as the + result will be approximately correctly normalized as is. + + + TURBO C, any memory model; uses inline assembly for speed + and for carefully-scaled arithmetic. + + Written by: Tom Roberts 11/8/89 + Made portable: Malcolm Slaney 12/15/94 malcolm@interval.com + + Timing on a Macintosh PowerBook 180.... (using Symantec C6.0) + fix_fft (1024 points) 8 ticks + fft (1024 points - Using SANE) 112 Ticks + fft (1024 points - Using FPU) 11 + +*/ +#include "debug.hch" + +#define N_WAVE 1024 /* dimension of Sinewave[] */ +#define LOG2_N_WAVE 10 /* log2(N_WAVE) */ + +ram signed 16 Sinewave[1024] = { + 0, 201, 402, 603, 804, 1005, 1206, 1406, + 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, + 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, + 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, + 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, + 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, + 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, + 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, + 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, + 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, + 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, + 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, + 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, + 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, + 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, + 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, + 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, + 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, + 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, + 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, + 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, + 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, + 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, + 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, + 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, + 30851, 30918, 30984, 31049, + 31113, 31175, 31236, 31297, + 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, + 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, + 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, + 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, + 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, + 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766, + 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, + 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, + 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, + 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, + 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, + 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, + 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, + 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, + 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, + 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, + 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, + 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, + 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, + 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, + 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, + 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, + 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, + 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, + 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, + 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, + 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, + 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, + 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, + 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, + 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, + 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, + 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, + 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, + 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, + 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, + 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, + 1607, 1406, 1206, 1005, 804, 603, 402, 201, + 0, -201, -402, -603, -804, -1005, -1206, -1406, + -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011, + -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608, + -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195, + -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766, + -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319, + -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849, + -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353, + -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, + -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268, + -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672, + -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036, + -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357, + -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631, + -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855, + -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027, + -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143, + -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, + -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198, + -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132, + -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001, + -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802, + -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534, + -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195, + -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783, + -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297, + -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, + -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097, + -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382, + -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588, + -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717, + -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766, + -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736, + -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628, + -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441, + -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, + -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833, + -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413, + -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918, + -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349, + -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706, + -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992, + -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208, + -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355, + -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, + -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456, + -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413, + -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311, + -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153, + -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942, + -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680, + -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371, + -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017, + -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, + -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191, + -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724, + -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227, + -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703, + -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156, + -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589, + -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, + -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, + -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, + -1607, -1406, -1206, -1005, -804, -603, -402, -201, +} with {block = "BlockRAM"}; + +/* + fix_fft() - perform fast Fourier transform. + + if n>0 FFT is done, if n<0 inverse FFT is done + fr[n],fi[n] are real,imaginary arrays, INPUT AND RESULT. + size of data = 2**m + set inverse to 0=dft, 1=idft +*/ +int fix_fft(short *fr, short *fi, unsigned 5 m_2, unsigned 1 inverse) +{ + unsigned 5 k; + + signed 16 ms,j,scale, shift; + unsigned 16 mr, i, nn, n, m, l ,istep; + signed 16 qr,qi,tr,ti,wr,wi,t; + unsigned 16 ju; + unsigned 16 temp; + + n = (1 << m_2); + + if(n > N_WAVE) { + return -1; + } + + mr = 0; + + nn = n - 1; + scale = 0; + + /* decimation in time - re-order data */ + for(m=1; m <= nn; ++m) { + l = n; + do { + l >>= 1; + } while (mr +l > nn); + mr = (mr & (l-1)) + l; + + if(mr <= m) continue; + tr = fr[m]; + fr[m] = fr[mr]; + fr[mr] = tr; + ti = fi[m]; + fi[m] = fi[mr]; + fi[mr] = ti; + } + + l = 1; + k = LOG2_N_WAVE -1; + while(l < n) { + if(inverse) { + /* variable scaling, depending upon data */ + shift = 0; + for(i=0; i 16383 || m > 16383) { + shift = 1; + break; + } + } + if(shift) + ++scale; + } else { + /* fixed scaling, for proper normalization - + there will be log2(n) passes, so this + results in an overall factor of 1/n, + distributed to maximize arithmetic accuracy. */ + shift = 1; + } + /* it may not be obvious, but the shift will be performed + on each data point exactly once, during this pass. */ + istep = 0 @ (l << 1); + for(m=0; m>= 1; + wi >>= 1; + } + for(i=m; i < n; i+=istep) { + ju = i + l; + tr = ((wr * fr[ju]) >>15) - ((wi * fi[ju]) >>15); + ti = ((wr * fi[ju]) >>15) + ((wi * fr[ju]) >>15); + qr = fr[i]; + qi = fi[i]; + if(shift) { + qr >>= 1; + qi >>= 1; + } + fr[ju] = qr - tr; + fi[ju] = qi - ti; + fr[i] = qr + tr; + fi[i] = qi + ti; + } + } + --k; + l = istep; + } + + return scale; +} + + + diff --git a/FFT_Test/int_fft.hch b/FFT_Test/int_fft.hch new file mode 100644 index 0000000..69fdc53 --- /dev/null +++ b/FFT_Test/int_fft.hch @@ -0,0 +1 @@ +int fix_fft(short *fr, short *fi, unsigned 5 m_2, unsigned 1 inverse); diff --git a/FFT_Test/main.hcc b/FFT_Test/main.hcc new file mode 100644 index 0000000..088305a --- /dev/null +++ b/FFT_Test/main.hcc @@ -0,0 +1,80 @@ +/**************************************************************** +* * +* Copyright (C) 1991-2003 Celoxica Ltd. All rights reserved. * +* * +***************************************************************** +* * +* Project : PAL * +* Date : 31 JAN 2003 * +* File : reverb.hcc * +* Author : Matthew Aubury (MA) * +* Contributors: * +* * +* Description: * +* Simple audio reverb. * +* * +* Date Version Author Reason for change * +* * +* 29 OCT 2002 1.00 MA Created * +* * +****************************************************************/ +#define PAL_TARGET_CLOCK_RATE 25175000 + + +#include +#include "pal_master.hch" + +#include "runfft.hch" +#include "debug.hch" + +/* + * Forward declarations + */ + +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +/* + * Main program + */ +void main(void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + + } + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,6,6); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + } + } +} diff --git a/FFT_Test/presets.hch b/FFT_Test/presets.hch new file mode 100644 index 0000000..f00336a --- /dev/null +++ b/FFT_Test/presets.hch @@ -0,0 +1,32 @@ +rom unsigned 16 presets[225] = +{ +0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, +0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, +0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, +0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888,0x8888, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xfec9,0x5444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x459c,0xefff,0xffff,0xfedb,0x9765,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444,0x4444, +0x4444,0x4444,0x4444,0x4567,0x9bde,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xfec9,0x5444,0x4444,0x4567,0x9bde,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, +0xffec,0x9521,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, +0x0d0a +} ; \ No newline at end of file diff --git a/FFT_Test/reverb_4000.hcc b/FFT_Test/reverb_4000.hcc new file mode 100644 index 0000000..5562a68 --- /dev/null +++ b/FFT_Test/reverb_4000.hcc @@ -0,0 +1,385 @@ +/**************************************************************** +* * +* Copyright (C) 1991-2003 Celoxica Ltd. All rights reserved. * +* * +***************************************************************** +* * +* Project : PAL * +* Date : 31 JAN 2003 * +* File : reverb.hcc * +* Author : Matthew Aubury (MA) * +* Contributors: * +* * +* Description: * +* Simple audio reverb. * +* * +* Date Version Author Reason for change * +* * +* 29 OCT 2002 1.00 MA Created * +* * +****************************************************************/ +#define PAL_TARGET_CLOCK_RATE 50000000 + + +#include +#include "pal_master.hch" + +#include "debug.hch" + +#include "fft.hch" +/* + * Forward declarations + */ +//static macro proc RunReverb (AudioIn, AudioOut); +static macro proc RunFFT (AudioIn, AudioOut); +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_in with { block = "BlockRAM"}; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_out with { block = "BlockRAM"}; + + +/* + * Main program + */ +void main (void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + //PalSevenSegRequire (1); + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + //PalSevenSegEnable (PalSevenSegCT (0)); + } + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,7,7); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + //RunReverb (AudioIn, AudioOut); + + } + } +} + +#define M 4 +#define N (1< +#include "pal_master.hch" + +#include "debug.hch" + +#include "fft.hch" +/* + * Forward declarations + */ +//static macro proc RunReverb (AudioIn, AudioOut); +static macro proc RunFFT (AudioIn, AudioOut); +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_in with { block = "BlockRAM"}; + +mpram +{ + ram unsigned 16 port1[128]; + ram unsigned 16 port2[128]; +}audio_buffer_out with { block = "BlockRAM"}; + +unsigned 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +unsigned 16 *audioptr_out1,*audioptr_out2; + +/* + * Main program + */ +void main (void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + //PalSevenSegRequire (1); + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + //PalSevenSegEnable (PalSevenSegCT (0)); + } + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,7,7); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + //RunReverb (AudioIn, AudioOut); + + } + } +} + +#define M 4 +#define N (1< +#include "pal_master.hch" + +#include "debug.hch" + +#include "fft.hch" +/* + * Forward declarations + */ +//static macro proc RunReverb (AudioIn, AudioOut); +static macro proc RunFFT (AudioIn, AudioOut); +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_in with { block = "BlockRAM"}; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_out with { block = "BlockRAM"}; + + +/* + * Main program + */ +void main (void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + //PalSevenSegRequire (1); + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + //PalSevenSegEnable (PalSevenSegCT (0)); + } + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,7,7); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + //RunReverb (AudioIn, AudioOut); + + } + } +} + +#define M 4 +#define N (1< +#include "pal_master.hch" + +#include "debug.hch" + +#include "fft.hch" +/* + * Forward declarations + */ +//static macro proc RunReverb (AudioIn, AudioOut); +static macro proc RunFFT (AudioIn, AudioOut); +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +mpram //Multiport block RAM +{ + ram signed 16 write[256]; + rom signed 16 read[256]; +} audio_buffer_in with { block = "BlockRAM"}; + +mpram +{ + ram signed 16 port1[256]; + ram signed 16 port2[256]; +}audio_buffer_out with { block = "BlockRAM"}; + +signed 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +signed 16 *audioptr_out1,*audioptr_out2; +signed 16 *audioptr_temp; + +/* + * Main program + */ +void main (void) +{ + macro expr AudioIn = PalAudioInCT (0); + macro expr AudioOut = PalAudioOutCT (0); + + /* + * Check we've got everything we need + */ + PalVersionRequire (1, 2); + PalAudioInRequire (1); + PalAudioOutRequire (1); + PalDataPortRequire (1); + + + /* + * Run + */ + par + { + PalAudioInRun (AudioIn, ClockRate); + PalAudioOutRun (AudioOut, ClockRate); + PalDataPortRun (PalRS232PortCT(0), PAL_ACTUAL_CLOCK_RATE ); + + + seq + { + par + { + PalAudioInEnable (AudioIn); + PalAudioOutEnable (AudioOut); + PalDataPortEnable (PalRS232PortCT(0)); + } + + RC200AudioInSetInput(RC200AudioInLineIn); + RC200AudioInSetGain(0,7,7); + PalAudioInSetSampleRate (AudioIn, 44100); + PalAudioOutSetSampleRate (AudioOut, 44100); + + RunFFT(AudioIn, AudioOut); + } + } +} + +#define M 4 +#define N (1< +#include "pal_master.hch" + +#include "config.hch" +#include "debug.hch" +#include "fft.hch" +#include "runfft.hch" + +#include "presets.hch" + +/* + * Forward declarations + */ + +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; +#if HARDWARE_MULTIPLY +//input buffer +ram signed 18 audio_buffer_in[256] with { block = "BlockRAM"}; +//output buffer +ram signed 18 audio_buffer_out[128] with { block = "BlockRAM"}; +#else +//input buffer +ram signed 16 audio_buffer_in[256] with { block = "BlockRAM"}; +//output buffer +ram signed 16 audio_buffer_out[128] with { block = "BlockRAM"}; +#endif +//EQ settings for the FFT +ram unsigned 4 EQ_info[128] with { block = "BlockRAM"}; +//EQ settings received from the display +mpram +{ + ram unsigned 4 write[768]; + rom unsigned 4 read[768]; +}EQ_level with { block = "BlockRAM"}; + +mpram +{ + ram unsigned 7 write[256]; + rom unsigned 7 read[256]; +}fft_info with { block = "BlockRAM"}; + +#if HARDWARE_MULTIPLY +signed 18 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +signed 18 *audioptr_out1,*audioptr_out2; +signed 18 *audioptr_temp; +#else +signed 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +signed 16 *audioptr_out1,*audioptr_out2; +signed 16 *audioptr_temp; +#endif +unsigned 3 active_preset; + +shared expr preset_address = (0@(active_preset-1))<<7; + +void LoadPresets() +{ + unsigned 16 temp; + unsigned 10 count; + unsigned 8 index; + + count=0; + do + { + par + { + temp = presets[index]; + index++; + } + par { EQ_level.write[count] = temp[7:4]; count++; } + par { EQ_level.write[count] = temp[3:0]; count++; } + par { EQ_level.write[count] = temp[15:12]; count++; } + par { EQ_level.write[count] = temp[11:8]; count++; } + } while (count<768); + +} + +/* + * FFT routine + */ +macro proc RunFFT (AudioIn, AudioOut) +{ + signed 18 sample; + unsigned 6 sample_count; + unsigned 8 i,cycle; + unsigned 4 eqinfo; + + unsigned 1 FFT_Sync; + macro expr OW = PalAudioOutGetMaxDataWidthCT (); + macro expr IW = PalAudioInGetMaxDataWidthCT (); + signed LeftNew, RightNew; + signed Output_sample; + + ram unsigned 6 input[64]; + active_preset = 3; + + //pointers for double and quadruple buffering: + audioptr_in1=&audio_buffer_in[0]; + audioptr_in2=&audio_buffer_in[64]; + audioptr_in3=&audio_buffer_in[128]; + audioptr_in4=&audio_buffer_in[192]; + + audioptr_out1=&audio_buffer_out[0]; + audioptr_out2=&audio_buffer_out[64]; + + FFT_Sync=0; + + LoadPresets(); + +par +{ + for(;;) + { + if (FFT_Sync) //if 64 samples are read from ADC... + { + par + { + // switch pointers + audioptr_in1 = audioptr_in2; + audioptr_in2 = audioptr_in3; + audioptr_in3 = audioptr_in4; + audioptr_in4 = audioptr_in1; + + audioptr_out1 = audioptr_out2; + audioptr_out2 = audioptr_out1; + FFT_Sync = 0; + } + + // FFT calculation + perform_fft(audioptr_in1); + +#if 1 + for(i=0;i +#include "pal_master.hch" + +#include "debug.hch" +#include "fft.hch" +#include "runfft.hch" + +#include "presets.hch" +#include "config.hch" +/* + * Forward declarations + */ + +static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; + +//input buffer +ram signed 16 audio_buffer_in[256] with { block = "BlockRAM"}; +//output buffer +ram signed 16 audio_buffer_out[128] with { block = "BlockRAM"}; +//EQ settings for the FFT +ram unsigned 4 EQ_info[128] with { block = "BlockRAM"}; +//EQ settings received from the display +mpram +{ + ram unsigned 4 write[768]; + rom unsigned 4 read[768]; +}EQ_level with { block = "BlockRAM"}; + +mpram +{ + ram unsigned 7 write[256]; + rom unsigned 7 read[256]; +}fft_info with { block = "BlockRAM"}; + +signed 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; +signed 16 *audioptr_out1,*audioptr_out2; +signed 16 *audioptr_temp; + +unsigned 3 active_preset; + +shared expr preset_address = (0@(active_preset-1))<<7; + +void LoadPresets() +{ + unsigned 16 temp; + unsigned 10 count; + unsigned 8 index; + + count=0; + do + { + par + { + temp = presets[index]; + index++; + } + par { EQ_level.write[count] = temp[7:4]; count++; } + par { EQ_level.write[count] = temp[3:0]; count++; } + par { EQ_level.write[count] = temp[15:12]; count++; } + par { EQ_level.write[count] = temp[11:8]; count++; } + } while (count<768); + +} + +/* + * FFT routine + */ +static macro proc RunFFT (AudioIn, AudioOut) +{ + unsigned 6 sample_count; + unsigned 8 count, i; +// unsigned 16 scount, temp; + + unsigned 1 FFT_Sync; + macro expr OW = PalAudioOutGetMaxDataWidthCT(); + macro expr IW = PalAudioInGetMaxDataWidthCT(); + signed LeftNew, RightNew; + signed Output_sample; + + //pointers for double and quadruple buffering: + audioptr_in1=&audio_buffer_in[0]; + audioptr_in2=&audio_buffer_in[64]; + audioptr_in3=&audio_buffer_in[128]; + audioptr_in4=&audio_buffer_in[192]; + + audioptr_out1=&audio_buffer_out[0]; + audioptr_out2=&audio_buffer_out[64]; + +audio_buffer_in[0] = 128; +audio_buffer_in[1] = 197; +audio_buffer_in[2] = 244; +audio_buffer_in[3] = 254; +audio_buffer_in[4] = 224; +audio_buffer_in[5] = 164; +audio_buffer_in[6] = 92; +audio_buffer_in[7] = 31; +audio_buffer_in[8] = 1; +audio_buffer_in[9] = 11; +audio_buffer_in[10] = 58; +audio_buffer_in[11] = 127; +audio_buffer_in[12] = 196; +audio_buffer_in[13] = 244; +audio_buffer_in[14] = 254; +audio_buffer_in[15] = 225; +audio_buffer_in[16] = 164; +audio_buffer_in[17] = 92; +audio_buffer_in[18] = 31; +audio_buffer_in[19] = 1; +audio_buffer_in[20] = 11; +audio_buffer_in[21] = 57; +audio_buffer_in[22] = 126; +audio_buffer_in[23] = 196; +audio_buffer_in[24] = 243; +audio_buffer_in[25] = 254; +audio_buffer_in[26] = 225; +audio_buffer_in[27] = 165; +audio_buffer_in[28] = 93; +audio_buffer_in[29] = 32; +audio_buffer_in[30] = 1; +audio_buffer_in[31] = 10; +audio_buffer_in[32] = 57; +audio_buffer_in[33] = 126; +audio_buffer_in[34] = 195; +audio_buffer_in[35] = 243; +audio_buffer_in[36] = 254; +audio_buffer_in[37] = 226; +audio_buffer_in[38] = 165; +audio_buffer_in[39] = 93; +audio_buffer_in[40] = 32; +audio_buffer_in[41] = 1; +audio_buffer_in[42] = 10; +audio_buffer_in[43] = 56; +audio_buffer_in[44] = 125; +audio_buffer_in[45] = 195; +audio_buffer_in[46] = 243; +audio_buffer_in[47] = 255; +audio_buffer_in[48] = 226; +audio_buffer_in[49] = 166; +audio_buffer_in[50] = 94; +audio_buffer_in[51] = 33; +audio_buffer_in[52] = 1; +audio_buffer_in[53] = 10; +audio_buffer_in[54] = 56; +audio_buffer_in[55] = 125; +audio_buffer_in[56] = 194; +audio_buffer_in[57] = 243; +audio_buffer_in[58] = 255; +audio_buffer_in[59] = 226; +audio_buffer_in[60] = 167; +audio_buffer_in[61] = 95; +audio_buffer_in[62] = 33; +audio_buffer_in[63] = 1; +audio_buffer_in[64] = 10; +audio_buffer_in[65] = 55; +audio_buffer_in[66] = 124; +audio_buffer_in[67] = 194; +audio_buffer_in[68] = 242; +audio_buffer_in[69] = 255; +audio_buffer_in[70] = 227; +audio_buffer_in[71] = 167; +audio_buffer_in[72] = 95; +audio_buffer_in[73] = 33; +audio_buffer_in[74] = 1; +audio_buffer_in[75] = 9; +audio_buffer_in[76] = 55; +audio_buffer_in[77] = 123; +audio_buffer_in[78] = 193; +audio_buffer_in[79] = 242; +audio_buffer_in[80] = 255; +audio_buffer_in[81] = 227; +audio_buffer_in[82] = 168; +audio_buffer_in[83] = 96; +audio_buffer_in[84] = 34; +audio_buffer_in[85] = 2; +audio_buffer_in[86] = 9; +audio_buffer_in[87] = 54; +audio_buffer_in[88] = 123; +audio_buffer_in[89] = 193; +audio_buffer_in[90] = 242; +audio_buffer_in[91] = 255; +audio_buffer_in[92] = 227; +audio_buffer_in[93] = 168; +audio_buffer_in[94] = 96; +audio_buffer_in[95] = 34; +audio_buffer_in[96] = 2; +audio_buffer_in[97] = 9; +audio_buffer_in[98] = 54; +audio_buffer_in[99] = 122; +audio_buffer_in[100] = 192; +audio_buffer_in[101] = 242; +audio_buffer_in[102] = 255; +audio_buffer_in[103] = 228; +audio_buffer_in[104] = 169; +audio_buffer_in[105] = 97; +audio_buffer_in[106] = 35; +audio_buffer_in[107] = 2; +audio_buffer_in[108] = 9; +audio_buffer_in[109] = 53; +audio_buffer_in[110] = 122; +audio_buffer_in[111] = 192; +audio_buffer_in[112] = 241; +audio_buffer_in[113] = 255; +audio_buffer_in[114] = 228; +audio_buffer_in[115] = 169; +audio_buffer_in[116] = 97; +audio_buffer_in[117] = 35; +audio_buffer_in[118] = 2; +audio_buffer_in[119] = 9; +audio_buffer_in[120] = 53; +audio_buffer_in[121] = 121; +audio_buffer_in[122] = 191; +audio_buffer_in[123] = 241; +audio_buffer_in[124] = 255; +audio_buffer_in[125] = 228; +audio_buffer_in[126] = 170; +audio_buffer_in[127] = 98; +audio_buffer_in[128] = 35; +audio_buffer_in[129] = 2; +audio_buffer_in[130] = 8; +audio_buffer_in[131] = 53; +audio_buffer_in[132] = 120; +audio_buffer_in[133] = 191; +audio_buffer_in[134] = 241; +audio_buffer_in[135] = 255; +audio_buffer_in[136] = 229; +audio_buffer_in[137] = 170; +audio_buffer_in[138] = 99; +audio_buffer_in[139] = 36; +audio_buffer_in[140] = 2; +audio_buffer_in[141] = 8; +audio_buffer_in[142] = 52; +audio_buffer_in[143] = 120; +audio_buffer_in[144] = 190; +audio_buffer_in[145] = 241; +audio_buffer_in[146] = 255; +audio_buffer_in[147] = 229; +audio_buffer_in[148] = 171; +audio_buffer_in[149] = 99; +audio_buffer_in[150] = 36; +audio_buffer_in[151] = 2; +audio_buffer_in[152] = 8; +audio_buffer_in[153] = 52; +audio_buffer_in[154] = 119; +audio_buffer_in[155] = 190; +audio_buffer_in[156] = 240; +audio_buffer_in[157] = 255; +audio_buffer_in[158] = 230; +audio_buffer_in[159] = 172; +audio_buffer_in[160] = 100; +audio_buffer_in[161] = 37; +audio_buffer_in[162] = 2; +audio_buffer_in[163] = 8; +audio_buffer_in[164] = 51; +audio_buffer_in[165] = 119; +audio_buffer_in[166] = 189; +audio_buffer_in[167] = 240; +audio_buffer_in[168] = 255; +audio_buffer_in[169] = 230; +audio_buffer_in[170] = 172; +audio_buffer_in[171] = 100; +audio_buffer_in[172] = 37; +audio_buffer_in[173] = 2; +audio_buffer_in[174] = 8; +audio_buffer_in[175] = 51; +audio_buffer_in[176] = 118; +audio_buffer_in[177] = 189; +audio_buffer_in[178] = 240; +audio_buffer_in[179] = 255; +audio_buffer_in[180] = 230; +audio_buffer_in[181] = 173; +audio_buffer_in[182] = 101; +audio_buffer_in[183] = 37; +audio_buffer_in[184] = 3; +audio_buffer_in[185] = 7; +audio_buffer_in[186] = 50; +audio_buffer_in[187] = 118; +audio_buffer_in[188] = 188; +audio_buffer_in[189] = 239; +audio_buffer_in[190] = 255; +audio_buffer_in[191] = 231; +audio_buffer_in[192] = 173; +audio_buffer_in[193] = 101; +audio_buffer_in[194] = 38; +audio_buffer_in[195] = 3; +audio_buffer_in[196] = 7; +audio_buffer_in[197] = 50; +audio_buffer_in[198] = 117; +audio_buffer_in[199] = 188; +audio_buffer_in[200] = 239; +audio_buffer_in[201] = 255; +audio_buffer_in[202] = 231; +audio_buffer_in[203] = 174; +audio_buffer_in[204] = 102; +audio_buffer_in[205] = 38; +audio_buffer_in[206] = 3; +audio_buffer_in[207] = 7; +audio_buffer_in[208] = 49; +audio_buffer_in[209] = 116; +audio_buffer_in[210] = 187; +audio_buffer_in[211] = 239; +audio_buffer_in[212] = 255; +audio_buffer_in[213] = 231; +audio_buffer_in[214] = 174; +audio_buffer_in[215] = 103; +audio_buffer_in[216] = 39; +audio_buffer_in[217] = 3; +audio_buffer_in[218] = 7; +audio_buffer_in[219] = 49; +audio_buffer_in[220] = 116; +audio_buffer_in[221] = 187; +audio_buffer_in[222] = 239; +audio_buffer_in[223] = 255; +audio_buffer_in[224] = 232; +audio_buffer_in[225] = 175; +audio_buffer_in[226] = 103; +audio_buffer_in[227] = 39; +audio_buffer_in[228] = 3; +audio_buffer_in[229] = 7; +audio_buffer_in[230] = 48; +audio_buffer_in[231] = 115; +audio_buffer_in[232] = 186; +audio_buffer_in[233] = 238; +audio_buffer_in[234] = 255; +audio_buffer_in[235] = 232; +audio_buffer_in[236] = 175; +audio_buffer_in[237] = 104; +audio_buffer_in[238] = 40; +audio_buffer_in[239] = 3; +audio_buffer_in[240] = 6; +audio_buffer_in[241] = 48; +audio_buffer_in[242] = 115; +audio_buffer_in[243] = 186; +audio_buffer_in[244] = 238; +audio_buffer_in[245] = 255; +audio_buffer_in[246] = 232; +audio_buffer_in[247] = 176; +audio_buffer_in[248] = 104; +audio_buffer_in[249] = 40; +audio_buffer_in[250] = 3; +audio_buffer_in[251] = 6; +audio_buffer_in[252] = 47; +audio_buffer_in[253] = 114; +audio_buffer_in[254] = 185; +audio_buffer_in[255] = 238; + + +perform_fft(audioptr_in1); +perform_ifft(audioptr_out1); +i=0; +do +{ + print_hex_value((unsigned)audio_buffer_in[i]); + print_string(" "); + print_hex_value((unsigned)audioptr_in1[i]); + print_eol(); + i++; +}while(i); +}// end function + diff --git a/FFT_Test/weights256.hch b/FFT_Test/weights256.hch new file mode 100644 index 0000000..c8133eb --- /dev/null +++ b/FFT_Test/weights256.hch @@ -0,0 +1,267 @@ +#define INTBITS 1 +#define FRACBITS 14 + +ram signed 16 weight_re[128] = +{ +16384, +16379, +16364, +16340, +16305, +16261, +16207, +16143, +16069, +15986, +15893, +15791, +15679, +15557, +15426, +15286, +15137, +14978, +14811, +14635, +14449, +14256, +14053, +13842, +13623, +13395, +13160, +12916, +12665, +12406, +12140, +11866, +11585, +11297, +11003, +10702, +10394, +10080, +9760, +9434, +9102, +8765, +8423, +8076, +7723, +7366, +7005, +6639, +6270, +5897, +5520, +5139, +4756, +4370, +3981, +3590, +3196, +2801, +2404, +2006, +1606, +1205, +804, +402, +0, +-402, +-804, +-1205, +-1606, +-2006, +-2404, +-2801, +-3196, +-3590, +-3981, +-4370, +-4756, +-5139, +-5520, +-5897, +-6270, +-6639, +-7005, +-7366, +-7723, +-8076, +-8423, +-8765, +-9102, +-9434, +-9760, +-10080, +-10394, +-10702, +-11003, +-11297, +-11585, +-11866, +-12140, +-12406, +-12665, +-12916, +-13160, +-13395, +-13623, +-13842, +-14053, +-14256, +-14449, +-14635, +-14811, +-14978, +-15137, +-15286, +-15426, +-15557, +-15679, +-15791, +-15893, +-15986, +-16069, +-16143, +-16207, +-16261, +-16305, +-16340, +-16364, +-16379 +}with {block = "BlockRAM"}; //Block 14 = internal FPGA block RAM + +ram signed 16 weight_im[128] = +{ +0, +-402, +-804, +-1205, +-1606, +-2006, +-2404, +-2801, +-3196, +-3590, +-3981, +-4370, +-4756, +-5139, +-5520, +-5897, +-6270, +-6639, +-7005, +-7366, +-7723, +-8076, +-8423, +-8765, +-9102, +-9434, +-9760, +-10080, +-10394, +-10702, +-11003, +-11297, +-11585, +-11866, +-12140, +-12406, +-12665, +-12916, +-13160, +-13395, +-13623, +-13842, +-14053, +-14256, +-14449, +-14635, +-14811, +-14978, +-15137, +-15286, +-15426, +-15557, +-15679, +-15791, +-15893, +-15986, +-16069, +-16143, +-16207, +-16261, +-16305, +-16340, +-16364, +-16379, +-16384, +-16379, +-16364, +-16340, +-16305, +-16261, +-16207, +-16143, +-16069, +-15986, +-15893, +-15791, +-15679, +-15557, +-15426, +-15286, +-15137, +-14978, +-14811, +-14635, +-14449, +-14256, +-14053, +-13842, +-13623, +-13395, +-13160, +-12916, +-12665, +-12406, +-12140, +-11866, +-11585, +-11297, +-11003, +-10702, +-10394, +-10080, +-9760, +-9434, +-9102, +-8765, +-8423, +-8076, +-7723, +-7366, +-7005, +-6639, +-6270, +-5897, +-5520, +-5139, +-4756, +-4370, +-3981, +-3590, +-3196, +-2801, +-2404, +-2006, +-1606, +-1205, +-804, +-402, +}with {block = "BlockRAM"}; //Block 14 = internal FPGA block RAM + -- cgit v0.12