tuner code for downsampling to 10 kHz working OK, ready for tetsing on real signals
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 21 Feb 2015 10:54:44 +0000 (10:54 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 21 Feb 2015 10:54:44 +0000 (10:54 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2043 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/stm32/Makefile
codec2-dev/stm32/src/iir_tuner.c
codec2-dev/stm32/src/stm32f4_adc_tuner.c
codec2-dev/stm32/src/tuner_ut.c

index 8e5d822f691210f82712cbb124c6ed88e18a3813..0ebb6c2ae95e1809d5f30dc54dafbfcfc13353c9 100644 (file)
@@ -354,6 +354,7 @@ fdmdv_dump_rt.elf: $(FDMDV_DUMP_RT_SRCS) src/stm32f4_dac.o src/stm32f4_adc.o
 
 TUNER_UT_SRCS=\
 src/tuner_ut.c \
+gdb_stdio.c \
 ../src/fifo.c \
 src/stm32f4_dac.c \
 src/iir_tuner.c \
index 05e6c209b7875c0261dfadcd55f6f0938dd3e637..334ff778f00b05234a5c7001215b6c537f688cbd 100644 (file)
@@ -9,7 +9,7 @@
 
   Unit testing:
   
-    ~/codec2-dev/stm32$ gcc -D__UNITTEST__ -Iinc src/iir_tuner.c -o iir_tuner -lm -Wal
+    ~/codec2-dev/stm32$ gcc -D__UNITTEST__ -Iinc src/iir_tuner.c -o iir_tuner -lm -Wall
     ~/codec2-dev/stm32$ ./iir_tuner
 
 \*---------------------------------------------------------------------------*/
@@ -56,7 +56,7 @@ float y_2, y_1, z_2, z_1;
    ADC -> signed conversion - IIR BPF - Decimate - FIR Equaliser -> FIFO
 */
 
-void iir_tuner(float dec_buf[], unsigned short adc_buf[]) {
+void iir_tuner(float dec_50[], unsigned short adc_buf[]) {
     int i, j, k;
     float x, y, z;
 
@@ -76,13 +76,30 @@ void iir_tuner(float dec_buf[], unsigned short adc_buf[]) {
            IIR BPF passband response */
 
         z = y + BETA2*z_2;
-        dec_buf[j] = z;
+        dec_50[j] = z;
         z_2 = z_1;
         z_1 = y;
     }
 }
 
 
+/* BPF at 12.5 kHz +/- 2000 Hz, and decimate down to Fs = 10kHz */
+
+static float fir_50_to_10[];
+void iir_tuner_dec_50_to_10(float dec_10[], float dec_50[], int n) {
+    int   i,j,k;
+    float acc;
+
+    for(i=0,k=0; i<n; i+=5,k++) {
+        acc = 0.0;
+        for(j=0; j<IIR_TUNER_DEC_50_10_FILT_MEM; j++)
+            acc += dec_50[i-j]*fir_50_to_10[j];
+        dec_10[k] = acc;
+    }
+        
+}
+
+
 #ifdef __UNITTEST__
 
 #define FS      2000000
@@ -108,9 +125,13 @@ void synth_line(unsigned short us[], float f, float amp, int n) {
 int main(void) {
     float          f1,f2,f3,f4;
     unsigned short s[NIN];
-    float          dec_s[NOUT];
+    float          dec_50[IIR_TUNER_DEC_50_10_FILT_MEM+NOUT];
+    float          dec_10[NOUT/5];
     FILE          *f;
-    int            i,j;
+    int            i,j,k;
+    short          dec_10_short;
+
+    /* test Fs=2E6 unsigned short to Fs=50E3 float tuner/resampler -----------------------*/
 
     f1 = 500E3;
     f2 = f1 + 8E3;       /* wanted */
@@ -123,7 +144,7 @@ int main(void) {
     synth_line(s, f3, 0.05, NIN);
     synth_line(s, f4, 0.1, NIN);
     for(i=0, j=0; i<NIN; i+=ADC_TUNER_BUF_SZ/2, j+=ADC_TUNER_N/2) {
-        iir_tuner(&dec_s[j], &s[i]);
+        iir_tuner(&dec_50[j], &s[i]);
     }
     
     f = fopen("iir_tuner_s.txt", "wt");  assert(f != NULL);
@@ -134,7 +155,29 @@ int main(void) {
 
     f = fopen("iir_tuner.txt", "wt");  assert(f != NULL);
     for(i=0; i<NOUT; i++)
-        fprintf(f, "%f\n", dec_s[i]);
+        fprintf(f, "%f\n", dec_50[i]);
+    fprintf(f, "\n");
+    fclose(f);
+
+    /* test FS=2E6 unsigned short -> Fs=10kHz short ---------------------------------------------*/
+
+    for(i=0; i<NIN; i++)
+        s[i] = 32767;
+    for(i=1; i<NIN; i+=4)
+        s[i] += 32767;
+    for(i=3; i<NIN; i+=4)
+        s[i] -= 32767;
+
+    for(i=0, j=0, k=0; i<NIN; i+=ADC_TUNER_BUF_SZ/2, j+=ADC_TUNER_N/2, k+=(ADC_TUNER_N/2)/5) {
+        iir_tuner(&dec_50[IIR_TUNER_DEC_50_10_FILT_MEM+j], &s[i]);
+        iir_tuner_dec_50_to_10(&dec_10[k], &dec_50[IIR_TUNER_DEC_50_10_FILT_MEM+j], ADC_TUNER_N/2);
+    }
+
+    f = fopen("iir_tuner2.txt", "wt");  assert(f != NULL);
+    for(i=0; i<NOUT/5; i++) {
+        dec_10_short = dec_10[i]/ADC_TUNER_M;
+        fprintf(f, "%d\n", dec_10_short);
+    }
     fprintf(f, "\n");
     fclose(f);
 
@@ -142,3 +185,110 @@ int main(void) {
 }
 
 #endif
+
+/* Band pass FIR filter coefficents centred on Fs/4, used before Fs=50kHz to Fs=10kHz */
+
+static float fir_50_to_10[] = {
+    -1.71502876e-07,
+    -3.93029078e-05,
+    -5.30743362e-04,
+    1.17938704e-04,
+    1.09727519e-03,
+    -1.90605585e-04,
+    -1.61350037e-03,
+    2.37746793e-04,
+    1.86947117e-03,
+    -2.28459776e-04,
+    -1.56457257e-03,
+    1.33627883e-04,
+    4.28669971e-04,
+    5.51555269e-05,
+    1.60217953e-03,
+    -3.09989338e-04,
+    -4.22595074e-03,
+    5.63604865e-04,
+    6.71504730e-03,
+    -7.23797964e-04,
+    -8.02135199e-03,
+    7.03165104e-04,
+    7.05924883e-03,
+    -4.54750532e-04,
+    -3.11212393e-03,
+    2.24463518e-08,
+    -3.75334414e-03,
+    5.63496992e-04,
+    1.24113249e-02,
+    -1.08145162e-03,
+    -2.06694342e-02,
+    1.38572694e-03,
+    2.55955103e-02,
+    -1.34897285e-03,
+    -2.41472078e-02,
+    9.32473244e-04,
+    1.39715800e-02,
+    -2.09763900e-04,
+    5.83111135e-03,
+    -6.44614872e-04,
+    -3.42028021e-02,
+    1.40049434e-03,
+    6.80569757e-02,
+    -1.83898122e-03,
+    -1.02710848e-01,
+    1.82014182e-03,
+    1.32754277e-01,
+    -1.32936318e-03,
+    -1.53163914e-01,
+    4.86473969e-04,
+    1.60393264e-01,
+    4.86473969e-04,
+    -1.53163914e-01,
+    -1.32936318e-03,
+    1.32754277e-01,
+    1.82014182e-03,
+    -1.02710848e-01,
+    -1.83898122e-03,
+    6.80569757e-02,
+    1.40049434e-03,
+    -3.42028021e-02,
+    -6.44614872e-04,
+    5.83111135e-03,
+    -2.09763900e-04,
+    1.39715800e-02,
+    9.32473244e-04,
+    -2.41472078e-02,
+    -1.34897285e-03,
+    2.55955103e-02,
+    1.38572694e-03,
+    -2.06694342e-02,
+    -1.08145162e-03,
+    1.24113249e-02,
+    5.63496992e-04,
+    -3.75334414e-03,
+    2.24463518e-08,
+    -3.11212393e-03,
+    -4.54750532e-04,
+    7.05924883e-03,
+    7.03165104e-04,
+    -8.02135199e-03,
+    -7.23797964e-04,
+    6.71504730e-03,
+    5.63604865e-04,
+    -4.22595074e-03,
+    -3.09989338e-04,
+    1.60217953e-03,
+    5.51555269e-05,
+    4.28669971e-04,
+    1.33627883e-04,
+    -1.56457257e-03,
+    -2.28459776e-04,
+    1.86947117e-03,
+    2.37746793e-04,
+    -1.61350037e-03,
+    -1.90605585e-04,
+    1.09727519e-03,
+    1.17938704e-04,
+    -5.30743362e-04,
+    -3.93029078e-05,
+    -1.71502876e-07
+};
+
index e9b15f843af0666517bc09d23e894f8f7b65c1e0..95505f7ff66958cae062c40074793435cf281469 100644 (file)
@@ -197,15 +197,33 @@ void adc_configure(){
 
 /*
   This function handles DMA Stream interrupt request.
+
+  ADC_TUNER_BUF_SZ = 45 * 160 = 7200, so one interrupt every 7200/2 = 3600 samples
+  or interrupts at a rate of 2E6/3600 = 555.56 Hz.
 */
 
 void DMA2_Stream0_IRQHandler(void) {
     float dec_buf[ADC_TUNER_N/2];
+    int i;
 
-    /* PE0 is asserted high for the duration of this ISR
+    /* PE0 is asserted high for the duration of this ISR */
 
     GPIOE->ODR = (1 << 0);
 
+    //#define DUMMY_SIGNAL
+    #ifdef DUMMY_SIGNAL
+
+    /* Fs/4 sine wave, right in the middle of the pass band ! */
+
+    for(i=0; i<ADC_TUNER_BUF_SZ; i++)
+        adc_buf[i] = 32767;
+    for(i=1; i<ADC_TUNER_BUF_SZ; i+=4)
+        adc_buf[i] += 32767;
+    for(i=3; i<ADC_TUNER_BUF_SZ; i+=4)
+        adc_buf[i] -= 32767;
+
+    #endif
+
     /* Half transfer interrupt */
 
     if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0) != RESET) {
index 308b08e7966e94aefcebf7f72d68aa8efb007d37..153eae4515549f1f64a5faf49336f34a26ef9270 100644 (file)
@@ -4,7 +4,8 @@
   AUTHOR......: David Rowe\r
   DATE CREATED: 20 Feb 2015\r
 \r
-  Unit test for high speed ADC radio tuner.\r
+  Unit test for high speed ADC radio tuner, samples signal centred at\r
+  500kHz using Fs=2 MHz and uploads to host at Fs=10 kHz.\r
 \r
 \*---------------------------------------------------------------------------*/\r
 \r
 */\r
 \r
 #include <assert.h>\r
+#include <stdlib.h>\r
+#include "gdb_stdio.h"\r
 #include "stm32f4_dac.h"\r
 #include "stm32f4_adc_tuner.h"\r
+#include "iir_tuner.h"\r
 #include "sm1000_leds_switches.h"\r
 \r
+#define REC_TIME_SECS 10\r
+#define FS            50000\r
+#define N             10000\r
+\r
+extern int adc_overflow1;\r
+\r
 int main(void) {\r
-    float tuner_out[ADC_TUNER_N];\r
+    float  tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+N/2];\r
+    float  dec_10[(N/2)/5];\r
+    short  dec_10_short[(N/2)/5];\r
+    int    bufs, i, j, fifo_sz;\r
+    FILE  *ftuner;\r
 \r
-    dac_open(4*DAC_BUF_SZ);\r
-    adc_open(4*ADC_TUNER_N);\r
+    ftuner = fopen("tuner.raw", "wb");\r
+    if (ftuner == NULL) {\r
+        printf("Error opening input file: tuner.raw\n\nTerminating....\n");\r
+        exit(1);\r
+    }\r
+    bufs = FS*REC_TIME_SECS/N;\r
+    fifo_sz = ((4*N/ADC_TUNER_N)+1)*ADC_TUNER_N;\r
+    printf("Starting! bufs: %d %d\n", bufs, fifo_sz);\r
\r
+    //dac_open(DAC_BUF_SZ);\r
+    adc_open(fifo_sz);\r
     sm1000_leds_switches_init();\r
 \r
-    while (1) {\r
+    for(i=0; i<bufs; i++) {\r
+\r
+        /* wait for buffer of Fs=50kHz tuner output samples */\r
 \r
-        while(adc1_read((short *)tuner_out, ADC_TUNER_N) == -1);\r
-        \r
+        while(adc1_read((short *)&tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N) == -1);\r
+\r
+        /* The semi-hosting system can only handle Fs=16kHz and below so resample down\r
+           to Fs=10 kHz and convert to shorts */\r
+\r
+        //for(j=0; j<N/2; j++)\r
+        //    tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM+j] = 45.0;\r
+        iir_tuner_dec_50_to_10(dec_10, &tuner_out[IIR_TUNER_DEC_50_10_FILT_MEM], N/2);\r
+        for(j=0; j<IIR_TUNER_DEC_50_10_FILT_MEM; j++)\r
+            tuner_out[j] = tuner_out[j+N/2];\r
+        for(j=0; j<(N/2)/5; j++)\r
+            dec_10_short[j] = dec_10[j]/ADC_TUNER_M;\r
+\r
+        fwrite(dec_10_short, sizeof(short), (N/2)/5, ftuner);\r
+        printf("%d %d\n", i, adc_overflow1);\r
     }\r
-   \r
+\r
+    printf("finished! %d\n", adc_overflow1);\r
+    fclose(ftuner);\r
 }\r
 \r