Verified IIR upconverter, modified fast_dac_ut.c to run upconverter
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 9 Mar 2015 02:54:54 +0000 (02:54 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 9 Mar 2015 02:54:54 +0000 (02:54 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2061 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/dacres.m
codec2-dev/stm32/Makefile
codec2-dev/stm32/inc/stm32f4_dacduc.h
codec2-dev/stm32/src/fast_dac_ut.c
codec2-dev/stm32/src/iir_duc.c
codec2-dev/stm32/src/stm32f4_dacduc.c

index 155a65ae753c964f1bae5e757b3cf564f14990f5..3d179639c0a45efdd8e678ec8019b7af9e12d263 100644 (file)
@@ -17,7 +17,7 @@ t = (0:(fs-1));
 
 beta1 = 0.999;
 b1x = -2*sqrt(beta1)*cos(2*pi*fb/(fs*M))
-beta2 = 1 - (1-0.999)*M;
+beta2 = beta1 - (1-0.999)*M;
 
 s1 = [fs zeros(1,fs-1)];       % noise floor, continuous interferers 
 s2 = 100*4*cos(t*2*pi*f2/fs);  % wanted signal 40dB above interferers
index 7a4ca3994fad2439c8e4a19df29825bccc781d34..5c83e6679896891d2b19902f7d1aecdc33158552 100644 (file)
@@ -158,6 +158,8 @@ dac_ut.elf: $(DAC_UT_SRCS)
 FAST_DAC_UT_SRCS=\
 src/fast_dac_ut.c \
 ../src/fifo.c \
+src/iir_duc.c \
+src/gdb_stdio.c \
 src/stm32f4_dacduc.c \
 src/debugblinky.c \
 src/system_stm32f4xx.c \
@@ -165,7 +167,7 @@ src/startup_stm32f4xx.s \
 src/init.c
 
 fast_dac_ut.elf: $(FAST_DAC_UT_SRCS)
-       $(CC) $(CFLAGS) -O0 $^ -o $@ $(LIBPATHS) $(LIBS)
+       $(CC) $(CFLAGS) -O3 $^ -o $@ $(LIBPATHS) $(LIBS)
        $(OBJCOPY) -O binary fast_dac_ut.elf fast_dac_ut.bin
 
 ADCDAC_UT_SRCS=\
index 580bfcc21f6e3da06d74e6f1be8dc1e0f98fb4c5..ecadf14f4aaf9847e9fb1866cf947b5857395e41 100644 (file)
 #ifndef __STM32F4_DAC__
 #define __STM32F4_DAC__
 
-#define DUC_N 100
+#define DUC_N 160
 #define DUC_M  25
 #define DAC_DUC_BUF_SZ DUC_M*DUC_N
 #define DAC_BUF_SZ 2048
 
-void dac_open(int fifo_sz);
+void fast_dac_open(int fifo_sz);
 int dac1_write(short buf[], int n); /* DAC1 pin PA4 */
 int dac2_write(short buf[], int n); /* DAC2 pin PA5 */
 
index bc19547a34b4b6ac22c48ee046c23cb22c78cfbd..d1848c55eb594c8794b5412b804e6910c8c13b3c 100644 (file)
 */\r
 \r
 #include <assert.h>\r
+#include <stdlib.h>\r
 #include "stm32f4_dacduc.h"\r
+#include "iir_duc.h"\r
+#include "stm32f4xx.h"\r
+#include <stm32f4xx_tim.h>\r
+#include <stm32f4xx_rcc.h>\r
+#include "gdb_stdio.h"\r
 \r
-#define SINE_SAMPLES   60\r
+#define SINE_SAMPLES  32\r
 \r
 \r
 /* 32 sample sine wave which at Fs=16kHz will be 500Hz.  Note samples\r
 short aWave[] = {4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,\r
        4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,4095,0,};\r
 \r
-short aSine[] = {390, 3981, 1410, 841, 4080, 841, 1410, 3981, 390, 2040, 3691, 100, 2671, 3240, 0, 3240, 2671, 100, 3691, 2040, 390, 3981, 1410, 841, 4080, 841, 1410, 3981, 390, 2040, 3691, 100, 2671, 3240, 0, 3240, 2671, 100, 3691, 2040,390, 3981, 1410, 841, 4080, 841, 1410, 3981, 390, 2040, 3691, 100, 2671, 3240, 0, 3240, 2671, 100, 3691, 2040\r
+short aSine[] = {1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1601, 0, 1600, 3200, 1600, 0, 1600, 3200, 1601, 0\r
 };\r
 \r
+//Sine at Fs/4\r
+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,\r
+                -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,\r
+                 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,\r
+                -1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,1,0,-1,0,};\r
+\r
+unsigned short outbuf[DAC_DUC_BUF_SZ];\r
+\r
+void setup_timer()\r
+{\r
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);\r
+\r
+    TIM_TimeBaseInitTypeDef timerInitStructure; \r
+    timerInitStructure.TIM_Prescaler = 84;\r
+    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;\r
+    timerInitStructure.TIM_Period = 0x8FFFFFFF;\r
+    timerInitStructure.TIM_ClockDivision = 0;\r
+    timerInitStructure.TIM_RepetitionCounter = 0;\r
+    TIM_TimeBaseInit(TIM2, &timerInitStructure);\r
+    TIM_Cmd(TIM2, ENABLE);\r
+}\r
+\r
 int main(void) {\r
+    int tstart,tend,cyc;\r
 \r
-    dac_open(4*DAC_DUC_BUF_SZ);\r
-    while (1) {\r
+    memset((void*)outbuf,0,sizeof(short)*DAC_DUC_BUF_SZ);\r
+    setup_timer();\r
+    dac_open(2*DAC_DUC_BUF_SZ,2*DAC_BUF_SZ);\r
 \r
+    tstart=tend=0;\r
+    while (1) {\r
+       cyc++;\r
+       if(cyc%100000==0){\r
+               printf("upconvert takes %d uSecs\n",tend-tstart);\r
+       }\r
         /* keep DAC FIFOs topped up */\r
-\r
-        dac1_write((short*)aWave, SINE_SAMPLES);\r
+       tstart = TIM_GetCounter(TIM2);\r
+       iir_upconv(f4sine,outbuf);\r
+       tend = TIM_GetCounter(TIM2);\r
+       dac1_write((short*)outbuf,DAC_DUC_BUF_SZ);\r
     }\r
    \r
 }\r
index d41917173826bb395658fe49fec9b8ae1b214973..d46611312904823674f3d46bbbe5d37a1d53a531 100644 (file)
@@ -8,8 +8,8 @@
 
   Unit testing:
   
-    ~/codec2-dev/stm32$ gcc -D__UNITTEST__ -Iinc src/iir_tuner.c -o iir_tuner -lm -Wall
-    ~/codec2-dev/stm32$ ./iir_tuner
+    ~/codec2-dev/stm32$ gcc -D__UNITTEST__ -Iinc src/iir_duc.c -o iir_duc -lm -Wall
+    ~/codec2-dev/stm32$ ./iir_duc
 
 \*---------------------------------------------------------------------------*/
 
   along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#define BETA1                    .9990234375                   // B1MUL/(2**B1SHFT)
-#define B1MUL                   1023                           
-#define B1SMUL                  1204
-#define B1SHFT                  10                             // 10 bits gives us plenty of headroom between 31 bits of int and 14 bits of ADC
-#define B2MUL                   979                            // This actually matches BETA2 exactly with the supplied BETA1
-#define B2SHFT                  10                             // 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                 1.0                            //Input scaling factor
+#include "stm32f4_dacduc.h"
+#include "iir_duc.h"
+
+#define BETA1                    0.99002                       // B1MUL/(2**B1SHFT)
+#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 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
 #define DAC_SCALE                4096                           //Maximum output to DAC
+#define DAC_SCALE_2             2040
 
 
+//IIR and FIR filter states. Global for go fast.
+float f_1,f_2,f;
+int   n_1,n_2,n;
+
 /*
    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 
 */
 
-float f_1,f_2,f;
-int   n_1,n_2,n;
-int   dac_temp[DUC_N*DUC_M];                                //Temporary storage for samples before IIR.
-
-void iir_upconv(float modin[],unsigned short dac_out[]){
-   memset((void*)dac_temp,0,sizeof(int)*DUC_N*DUC_M);      //Preset output array for interpolation
-   int i,j,k;
-   int m;
-   k=0;
-   //Iterate through input samples and apply pre-eq FIR, interpolate, and apply BPF IIR
-   for(i=0;i<DUC_N;i++){
-       f = modin[i]+f_2*BETA2;
-       f_1 = modin[i];
-       f_2 = f_1;
-       //m = (int)(f/(IN_SCALE*2))*DAC_SCALE;  //Scale and convert to int. I probably should add more bits here and truncate before DAC.
-       m = (int)((f/(IN_SCALE*2))*DAC_SCALE);  
-       dac_temp[k]= m;
-       for(j=0;j<DUC_M;j++,k++){
-           n = dac_temp[k] - ((B1SMUL*n_1)>>B1SHFT) - ((B1MUL*n_2)>>B1SHFT);
+void iir_upconv(float modin[], unsigned short dac_out[]){
+    int i,j,k;
+    int m;
+    k=0;
+    //Iterate through input samples and apply pre-eq FIR, interpolate, and apply BPF IIR
+    for(i=0;i<DUC_N;i++){
+        f = modin[i]+f_2*BETA2;
+        f_2 = f_1;
+        f_1 = modin[i];                                             //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<DUC_M;j++,k++){
+            n = ((B1SMUL*n_1)>>B1SHFT) - ((B1MUL*n_2)>>B1SHFT);
             n_2 = n_1;
             n_1 = n;
-           dac_out[k]=(unsigned short)(n+DAC_SCALE/2);
-       }
-   }
-
+            dac_out[k]=(unsigned short)((n)+DAC_SCALE_2);
+        }
+    }
 }
 
 
+#ifdef __UNITTEST__
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#define FS     80000
+#define AMP_MAX 1
+
+#define NOUT_BUFS    401
+#define NIN          (NOUT_BUFS*DUC_N)
+#define NOUT         (NIN*DUC_M)
+
+void synth_line(float us[], float f, float amp, int n) {
+    float w, sam;
+    int   i;
+
+    w = 2*M_PI*f/(float)FS;
+
+    for(i=0; i<n; i++) {
+        sam = amp*AMP_MAX*cos(w*i);
+        us[i] += sam;
+    }
+}
+
+float     s[NIN];
+float      fout[NIN];
+unsigned short todac[NOUT];
+
+int main(void) {
+    float          f1,f2,f3;
+    FILE          *f;
+    int            i;
+
+    f1 = 20E3;           /* center of passband */
+    f2 = f1;     /* wanted */
+    f3 = f1 + 7E3;        /* wanted */
+
+
+    for(i=0; i<NIN; i++)
+        s[i] = 0.01;
+    synth_line(s, f2, 0.5, NIN);
+    synth_line(s, f3, 0.5, NIN);
+    for(i=0;i<NOUT_BUFS;i++)
+        iir_upconv(&s[i*(DUC_N)],&todac[i*(DUC_N*DUC_M)]);
+    
+    f = fopen("iir_duc_s.txt", "wt");  assert(f != NULL);
+    for(i=DUC_N; i<NIN; i++)
+        fprintf(f, "%f\n", s[i]);
+    fprintf(f, "\n");
+    fclose(f);
+
+    f = fopen("iir_duc_f.txt", "wt");  assert(f != NULL);
+    for(i=DUC_N; i<NIN; i++)
+        fprintf(f, "%f\n", fout[i]);
+    fprintf(f, "\n");
+    fclose(f);
+
+    f = fopen("iir_duc.txt", "wt");  assert(f != NULL);
+    for(i=DUC_N*DUC_M; i<NOUT; i++)
+        fprintf(f, "%d\n", todac[i]);
+    fprintf(f, "\n");
+    fclose(f);
+
+    return 0;
+}
 
+#endif
 
 
 
index e1b231ab4df5c5c85a456e9441842652ba7753a7..ec683c37779b63be175ced438779cb7633319d4f 100644 (file)
@@ -32,7 +32,7 @@
 #include "codec2_fifo.h"\r
 #include "stm32f4_dacduc.h"\r
 #include "debugblinky.h"\r
-\r
\r
 /* write to these registers for 12 bit left aligned data, as per data sheet \r
    make sure 4 least sig bits set to 0 */\r
 \r
@@ -63,15 +63,15 @@ static void dac2_config(void);
 \r
 int dac_underflow;\r
 \r
-void dac_open(int fifo_size) {\r
+void fast_dac_open(int dac1_fifo_size,int dac2_fifo_size) {\r
 \r
     memset(dac1_buf, 32768, sizeof(short)*DAC_DUC_BUF_SZ);\r
     memset(dac2_buf, 32768, sizeof(short)*DAC_BUF_SZ);\r
 \r
     /* Create fifos */\r
 \r
-    dac1_fifo = fifo_create(fifo_size);\r
-    dac2_fifo = fifo_create(fifo_size);\r
+    dac1_fifo = fifo_create(dac1_fifo_size);\r
+    dac2_fifo = fifo_create(dac2_fifo_size);\r
     assert(dac1_fifo != NULL);\r
     assert(dac2_fifo != NULL);\r
 \r
@@ -134,7 +134,7 @@ static void tim6_config(void)
   /* Time base configuration */\r
 \r
   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); \r
-  TIM_TimeBaseStructure.TIM_Period = 80;          \r
+  TIM_TimeBaseStructure.TIM_Period = 5250;          \r
   TIM_TimeBaseStructure.TIM_Prescaler = 0;       \r
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;    \r
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  \r
@@ -209,7 +209,9 @@ static void dac1_config(void)
 \r
   DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO; \r
   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;\r
-  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;\r
+\r
+  /*External buffering is needed to get nice square samples at Fs=2Mhz. See DM00129215.pdf */\r
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;\r
   DAC_Init(DAC_Channel_1, &DAC_InitStructure);\r
 \r
   /* DMA1_Stream5 channel7 configuration **************************************/\r
@@ -336,14 +338,9 @@ void DMA1_Stream5_IRQHandler(void) {
 \r
     if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5) != RESET) {\r
         /* fill first half from fifo */\r
-       \r
-        if (fifo_read(dac1_fifo, (short*)dac1_buf, DAC_DUC_BUF_SZ/2) == -1) {\r
-            memset(dac1_buf, 0, sizeof(short)*DAC_DUC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }\r
+       fifo_read(dac1_fifo, (short*)dac1_buf, DAC_DUC_BUF_SZ/2);\r
 \r
         /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
         DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);  \r
     }\r
 \r
@@ -351,12 +348,9 @@ void DMA1_Stream5_IRQHandler(void) {
 \r
     if(DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET) {\r
         /* fill second half from fifo */\r
+       fifo_read(dac1_fifo, (short*)(dac1_buf+DAC_DUC_BUF_SZ/2), DAC_DUC_BUF_SZ/2);\r
 \r
-        if (fifo_read(dac1_fifo, (short*)(dac1_buf+DAC_DUC_BUF_SZ/2), DAC_DUC_BUF_SZ/2) == -1) {\r
-            memset(dac1_buf, 0, sizeof(short)*DAC_DUC_BUF_SZ/2);\r
-            dac_underflow++;\r
-        }    /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
-\r
+        /* Clear DMA Stream Transfer Complete interrupt pending bit */\r
         DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);  \r
     }\r
 \r