From: baobrien Date: Mon, 23 Mar 2015 01:37:14 +0000 (+0000) Subject: Continued work on 48k comp to 80k real X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=eb32c8cfc0576756503fb68c3dde13ed140bdb7a;p=freetel-svn-tracking.git Continued work on 48k comp to 80k real git-svn-id: https://svn.code.sf.net/p/freetel/code@2088 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/stm32/inc/iir_duc.h b/codec2-dev/stm32/inc/iir_duc.h index e4c921ed..b20b0b5e 100644 --- a/codec2-dev/stm32/inc/iir_duc.h +++ b/codec2-dev/stm32/inc/iir_duc.h @@ -30,7 +30,8 @@ #include "comp.h" void iir_upconv(float modin[],unsigned short dac_out[]); -void upconv_48c_80r(COMP comp_8[],float real_80[],int count); +void iir_upconv_fixp(int modin[], unsigned short dac_out[]); +void upconv_48c_80r(COMP comp_8[],int real_80[],int count); void upconv_8c_80r(COMP comp_8[],float real_80[],int count); #endif diff --git a/codec2-dev/stm32/inc/stm32f4_dacduc.h b/codec2-dev/stm32/inc/stm32f4_dacduc.h index 05dfd238..6a1ba20c 100644 --- a/codec2-dev/stm32/inc/stm32f4_dacduc.h +++ b/codec2-dev/stm32/inc/stm32f4_dacduc.h @@ -31,6 +31,7 @@ #define DUC_N 160 #define DUC_M 25 +#define DUC_48N 96 //This is 3/5th DUC_N #define DAC_DUC_BUF_SZ DUC_M*DUC_N #define DAC_BUF_SZ 2048 diff --git a/codec2-dev/stm32/src/fast_dac_ut.c b/codec2-dev/stm32/src/fast_dac_ut.c index 2e8fa5c2..faa8865c 100644 --- a/codec2-dev/stm32/src/fast_dac_ut.c +++ b/codec2-dev/stm32/src/fast_dac_ut.c @@ -56,7 +56,7 @@ float f4sine[] = {1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0 1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,}; //Intermediate 80k real before tx -float tx_imm[DUC_N]; +int tx_imm[DUC_N]; //Complex input to chain COMP comp_in[DUC_N/10]; @@ -85,25 +85,25 @@ int main(void) { fast_dac_open(2*DAC_DUC_BUF_SZ,2*DAC_BUF_SZ); tstart=tend=tup=cyc=0; //Initalize complex input with signal at zero - for(i=0;iGMSK_TEST_LEN) // cyc=0; - /*if(cyc%10000==0){ - printf("8c80r takes %d uSecs\n",tup-tstart); + if(cyc%10000==0){ + printf("48c80r takes %d uSecs\n",tup-tstart); printf("iir upconvert takes %d uSecs\n",tend-tup); - }*/ + } tstart = TIM_GetCounter(TIM2); - //upconv_8c_80r(&gmsk_test_d[cyc],tx_imm,1); + upconv_48c_80r(comp_in,tx_imm,1); tup = TIM_GetCounter(TIM2); - iir_upconv(tx_imm,outbuf); + iir_upconv_fixp(tx_imm,outbuf); tend = TIM_GetCounter(TIM2); diff --git a/codec2-dev/stm32/src/iir_duc.c b/codec2-dev/stm32/src/iir_duc.c index dfe7f40b..47262f72 100644 --- a/codec2-dev/stm32/src/iir_duc.c +++ b/codec2-dev/stm32/src/iir_duc.c @@ -37,7 +37,7 @@ #define B1MUL 32441 #define B1SMUL -38328 #define B1SHFT 15 // 10 bits gives us plenty of headroom between 31 bits of int and 14 bits of ADC -#define B2MUL 24593 // This actually matches BETA2 exactly with the supplied BETA1 +#define B2MUL 24593 // This actually matches BETA2 exactly with the supplied BETA1 #define B2SHFT 15 // 10 is also the lowest we can go without beta1=1 #define BETA2 (1.0 - (1.0-BETA1)*DUC_M) // B2MUL/(2**B2SHFT) #define IN_SCALE 2.0 //Input scaling factor. Should be as large as the amplitude of the incoming samples @@ -47,7 +47,7 @@ //IIR and FIR filter states. Global for go fast. float f_1,f_2,f; -int n_1,n_2,n; +int n_1,n_2,n,m_1,m_2,m; /* Upconvert and bandpass filter a chunk of spectrum from Fs/M to Fs. We're going for 700khz here. @@ -79,22 +79,62 @@ void iir_upconv(float modin[], unsigned short dac_out[]){ } } +/* + Upconvert and bandpass filter a chunk of spectrum from Fs/M to Fs. We're going for 700khz here. + modin needs to be DUC_N long and dac_out needs to be DUC_N*DUC_M long. This +*/ + +void iir_upconv_fixp(int modin[], unsigned short dac_out[]){ + int i,j,k; + int l; + k=0; + //Iterate through input samples and apply pre-eq FIR, interpolate, and apply BPF IIR + for(i=0;i>4; + m = l+((m_2*B2MUL)>>B2SHFT); + m_2 = m_1; + m_1 = l; //Scale fir output and convert to fixed. + //m = (int)((f/(IN_SCALE))*DAC_SCALE_2); //Scale fir output and convert to fixed + n = m + ((B1SMUL*n_1)>>B1SHFT) - ((B1MUL*n_2)>>B1SHFT); //Apply one cycle of IIR. This feeds the fir-ed sample into the output filter + n_2 = n_1; + n_1 = n; + dac_out[k]=(unsigned short)(n+DAC_SCALE_2); + k++; + //now do the rest of the filtering. Because we're zero-stuffing we can neglect the sample from the fir filter. + for(j=1;j>B1SHFT) - ((B1MUL*n_2)>>B1SHFT); + n_2 = n_1; + n_1 = n; + dac_out[k]=(unsigned short)((n)+DAC_SCALE_2); + } + } +} + #define F48C80R_LEN 25 #define F48C80R_MUL 4096 static int js3 = 0; //Index for downsampling static int js5 = 0; //Index for upsampling -static int w48c80r; //Phase for real to comp conversion +static unsigned int w48c80r; //Phase for real to comp conversion static int ptr_48c80r; //Pointer in fir delay lines static int fir_48c80r[]; //Fir filter coeffs static int fir_48c80r_re[F48C80R_LEN*2]; //Real delay line. Can probably be made much smaller. static int fir_48c80r_im[F48C80R_LEN*2]; //Imag delay line. Can probably be made much smaller. +static int * sel_48c80r[2] = {fir_48c80r_re,fir_48c80r_im}; //Selector used to optimize out branches in inner loops -void upconv_48c_80r(COMP comp_48[],float real_80[],int count){ +/* + Interpolate and shift from 48k complex to 80k real, centered on Fs/4. + comp_8 - Input samples - 8Kc complex - must be DUC_48N*count long + upout - Output samples - must be DUC_N*count long + count - how many chunks of samples must be processed +*/ + +void upconv_48c_80r(COMP comp_48[],int real_80[],int count){ int i,j,k; //Loop counters - float ret; //Temp vars + int ret; //Temp vars int nr,ni; //Temp vars int inidx = 0; //Input index - int outidx = 0; //Output index + int outidx = 0; + int ncs_48c80r[3]; for(i=0;i=F48C80R_LEN) + ptr_48c80r-=F48C80R_LEN; } if(js3==0){ //Downsample by 3 - nr=0;ni=0; - if(w48c80r&0x1){ //Only compute FIR for the line we need - for(k=js5;kreal conversion by hand - case 0:ret=(float)(-ni>>11);break; - case 1:ret=(float)(nr>>11);break; - case 2:ret=(float)(ni>>11);break; - case 3:ret=(float)(-nr>>11);break; - } - real_80[outidx]=ret/8192; //Scale back result; should probably just return int + ni=0; + /*This loop computes the FIR filter. It only computes from either the re or the im delay line, + depending on comp->re phase It also skips all 'zeros' in the delay line */ + for(k=js5;k>14; //Scale back result; should probably just return int outidx++; js3=3; + w48c80r+=3; } - w48c80r++; ptr_48c80r++; - if(ptr_48c80r>=F48C80R_LEN) - ptr_48c80r=0; js3--; js5--; } @@ -273,7 +307,7 @@ void synth_line(float us[], float f, float amp, int n) { } COMP in[48000]; -float s[NIN]; +int s[NIN]; float fout[NIN]; unsigned short todac[NOUT]; @@ -299,11 +333,11 @@ int main(void) { //interpolate from 8k comp to 80k real upconv_48c_80r(in,s,NOUT_BUFS); for(i=0;i