Further work on fmfsk C modem, not quite done, still needs deep testing
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 8 Feb 2016 16:53:20 +0000 (16:53 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 8 Feb 2016 16:53:20 +0000 (16:53 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2690 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fmfsk.m
codec2-dev/src/CMakeLists.txt
codec2-dev/src/fmfsk.c
codec2-dev/src/fmfsk_demod.c [new file with mode: 0644]
codec2-dev/src/fmfsk_mod.c
codec2-dev/src/fsk_demod.c
codec2-dev/unittest/CMakeLists.txt
codec2-dev/unittest/tfmfsk.c [new file with mode: 0644]

index 37f748cc81ceac8f309550235d84403edefc86e7..7697fd8e6d215930c1e5511d7eeac51593084205 100644 (file)
@@ -32,16 +32,23 @@ function states = fmfsk_init(Fs,Rb)
     %Current fixed processing buffer size, in non-ME bits
     nbit = 192;
     
+    
     states.Rb = Rb;
     states.Rs = Rb*2;   % Manchester-encoded bitrate
     states.Fs = Fs;
     states.Ts = Fs/states.Rs;
-    states.N = nbit*states.Ts;     
+    states.N = nbit*2*states.Ts;     
+    %states.N
+    %states.N = floor(states.Rs*.080)*states.Ts
+    %states.N
     states.nin = states.N;          % Samples in the next demod cycle
     states.nstash = states.Ts*2;    % How many samples to stash away between proc cycles for timing adjust
     states.nmem =  states.N+(4*states.Ts);
     states.nsym = nbit*2;
     states.nbit = nbit;
+    
+    %tates.nsym = floor(states.Rs*.080);
+    %states.nbit = floor(states.Rb*.080)
     %Old sample memory
     
     states.oldsamps = zeros(1,states.nmem);
@@ -95,16 +102,19 @@ function [rx_bits states] = fmfsk_demod(states,rx)
     ssamps(nold+1:nmem) = rx;
     states.oldsamps = ssamps;
     
-    rx_filt = zeros(1,nsym*Ts);
+    rx_filt = zeros(1,(nsym+1)*Ts);
+    length(rx_filt)
     %Integrate Ts input samples at every offset
     %This is the same thing as filtering with a filter of all ones
     % out to Ts.
     % It's implemented like this for ease of C-porting
     for ii=(1:(nsym+1)*Ts)
         st = ii;
-        en = st+Ts;
+        en = st+Ts-1;
         rx_filt(ii) = sum(ssamps(st:en));
     end
+    
+    length(rx_filt)
  
     % Fine timing estimation ------------------------------------------------------
 
index 1ffbd9b36600a660e772cdad92b2791654ccb1e0..b79d6df3dfee77407c6913aa564251975b3540f2 100644 (file)
@@ -257,6 +257,9 @@ target_link_libraries(cohpsk_mod ${CMAKE_REQUIRED_LIBRARIES} codec2)
 add_executable(fmfsk_mod fmfsk_mod.c)
 target_link_libraries(fmfsk_mod ${CMAKE_REQUIRED_LIBRARIES} codec2)
 
+add_executable(fmfsk_demod fmfsk_demod.c modem_probe.c octave.c)
+target_link_libraries(fmfsk_demod ${CMAKE_REQUIRED_LIBRARIES} codec2)
+
 add_executable(cohpsk_demod cohpsk_demod.c octave.c)
 target_link_libraries(cohpsk_demod ${CMAKE_REQUIRED_LIBRARIES} codec2)
 
index 57229b4aa30b6e6fc9b50259d9ceb9e482a001cb..e9478b50351747f042fea326f9438efa5dc1b2f8 100644 (file)
@@ -31,6 +31,8 @@
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
+#include <stdio.h>
+
 
 #include "fmfsk.h"
 #include "modem_probe.h"
@@ -60,7 +62,7 @@ struct FMFSK * fmfsk_create(int Fs,int Rb){
     fmfsk->Rs = Rb*2;
     fmfsk->Fs = Fs;
     fmfsk->Ts = Fs/fmfsk->Rs;
-    fmfsk->N = nbits*fmfsk->Ts;
+    fmfsk->N = nbits*2*fmfsk->Ts;
     fmfsk->nmem = fmfsk->N+(fmfsk->Ts*4);
     fmfsk->nsym = nbits*2;
     fmfsk->nbit = nbits;
@@ -103,6 +105,28 @@ uint32_t fmfsk_nin(struct FMFSK *fmfsk){
  * float mod_out[] - Buffer for N samples of modulated FMFSK
  * uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
  */
+//void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]){
+//    int i,j;
+//    int Ts = fmfsk->Ts;
+//    int N = fmfsk->N;
+//    
+//    for(i=0;i<N;){
+//        /* Save a manchester-encoded 0 */
+//        if(bits_in[i] == 0){
+//            for(j=0; j<Ts; j++)
+//                fmfsk_out[i++] = -1;
+//            for(j=0; j<Ts; j++)
+//                fmfsk_out[i++] =  1;
+//        } else {
+//        /* Save a manchester-encoded 1 */
+//            for(j=0; j<Ts; j++)
+//                fmfsk_out[i++] =  1;
+//            for(j=0; j<Ts; j++)
+//                fmfsk_out[i++] = -1;
+//        }
+//    }
+//}
+
 void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]){
     int i,j;
     int nbit = fmfsk->nbit;
@@ -112,20 +136,19 @@ void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]){
         /* Save a manchester-encoded 0 */
         if(bits_in[i] == 0){
             for(j=0; j<Ts; j++)
-                fmfsk_out[   j+i*Ts] = -1;
+                fmfsk_out[   j+i*Ts*2] = -1;
             for(j=0; j<Ts; j++)
-                fmfsk_out[Ts+j+i*Ts] =  1;
+                fmfsk_out[Ts+j+i*Ts*2] =  1;
         } else {
         /* Save a manchester-encoded 1 */
             for(j=0; j<Ts; j++)
-                fmfsk_out[   j+i*Ts] =  1;
+                fmfsk_out[   j+i*Ts*2] =  1;
             for(j=0; j<Ts; j++)
-                fmfsk_out[Ts+j+i*Ts] = -1;
+                fmfsk_out[Ts+j+i*Ts*2] = -1;
         }
     }
 }
 
-
 /*
  * Demodulate some number of FMFSK samples. The number of samples to be 
  *  demodulated can be found by calling fmfsk_nin().
@@ -161,13 +184,13 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
     memcpy(&oldsamps[nold], &fmfsk_in[0]        , sizeof(float)*nin );
     
     /* Allocate memory for filtering */
-    float *rx_filt = alloca(sizeof(float)*nsym*Ts);
+    float *rx_filt = alloca(sizeof(float)*(nsym+1)*Ts);
     
     /* Integrate over Ts input symbols at every offset */
     for(i=0; i<(nsym+1)*Ts; i++){
         t=0;
         /* Integrate over some samples */
-        for(j=i;j<i+Ts;j++){
+        for(j=i;j<i+Ts-1;j++){
             t += oldsamps[j];
         }
         rx_filt[i] = t;
@@ -188,7 +211,10 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
     dphi_ft.real = cos(2*M_PI*(float)Rs/(float)Fs);
     dphi_ft.imag = sin(2*M_PI*(float)Rs/(float)Fs);
     
-    for(i=0; i<nsym*Ts; i++){
+    x.real = 0;
+    x.imag = 0;
+    
+    for(i=0; i<(nsym+1)*Ts; i++){
         /* Apply non-linearity */
         t = rx_filt[i]*rx_filt[i];
         
@@ -200,9 +226,10 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
     }
     
     /* Figure out the normalized RX timing, using David's magic number */
-    norm_rx_timing =  atan2f(x.imag,x.real)/(2*M_PI) - .042;
+    norm_rx_timing =  atan2f(x.imag,x.real)/(2*M_PI) - .42;
     rx_timing = (int)lroundf(norm_rx_timing*(float)Ts);
     
+    fprintf(stderr,"norm_rx_timing: %f rx_timing:%d\n",norm_rx_timing,rx_timing);
     /* Figure out how far offset the sample points are */
     sample_offset = (Ts/2)+Ts+rx_timing-1;
     
@@ -225,31 +252,35 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
         currv = rx_filt[sample_offset+(i*Ts)];
         mdiff = lastv - currv;
         mbit = mdiff>0 ? 1 : 0;
+        lastv = currv;
         
+        mdiff = mdiff>0 ? mdiff : 0-mdiff;
+        //printf("md %f\n",mdiff);
         /* Put bit in it's stream */
-        if((i&2)==1){
+        if((i%2)==1){
             apeven += mdiff;
             /* Even stream goes in LSB */
             rx_bits[i>>1] |= mbit ? 0x1 : 0x0;
         }else{
             apodd += mdiff;
             /* Odd in second-to-LSB */
-            rx_bits[i>>1] |= mbit ? 0x2 : 0x0;
+            rx_bits[i>>1]  = mbit ? 0x2 : 0x0;
         }
     }
-    
     if(apeven>apodd){
+        fprintf(stderr,"even has it\n");
         /* Zero out odd bits from output bitstream */
         for(i=0;i<nbit;i++)
             rx_bits[i] &= 0x1;
     }else{
+        fprintf(stderr,"it's odd\n");
         /* Shift odd bits into LSB and even bits out of existence */
         for(i=0;i<nbit;i++)
             rx_bits[i] = (rx_bits[i]&0x2)>>1;
     }
     
     /* Save last sample of int stream for next demod round */
-    fmfsk->lodd = rx_filt[sample_offset+((nsym-1)*Ts)];
+    fmfsk->lodd = lastv;
     
     modem_probe_samp_f("t_norm_rx_timing",&norm_rx_timing,1);
     modem_probe_samp_f("t_rx_filt",rx_filt,nsym*Ts);
diff --git a/codec2-dev/src/fmfsk_demod.c b/codec2-dev/src/fmfsk_demod.c
new file mode 100644 (file)
index 0000000..6bd45a8
--- /dev/null
@@ -0,0 +1,114 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: fsk_demod.c
+  AUTHOR......: Brady O'Brien
+  DATE CREATED: 8 January 2016
+
+  C test driver for fsk_demod in fsk.c. Reads in a stream of 32 bit cpu endian
+  floats and writes out the detected bits
+   
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2016 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include "fmfsk.h"
+
+#define MODEMPROBE_ENABLE
+#include "modem_probe.h"
+#include "codec2_fdmdv.h"
+
+int main(int argc,char *argv[]){
+    struct FMFSK *fmfsk;
+    int Fs,Rb;
+    FILE *fin,*fout;
+    uint8_t *bitbuf;
+    int16_t *rawbuf;
+    float *modbuf;
+    int i,t;
+    
+    if(argc<4){
+        fprintf(stderr,"usage: %s SampleFreq BitRate InputModemRawFile OutputOneBitPerCharFile [OctaveLogFile]\n",argv[0]);
+        exit(1);
+    }
+    
+    /* Extract parameters */
+    Fs = atoi(argv[1]);
+    Rb = atoi(argv[2]);
+    
+    /* Open files */
+    if(strcmp(argv[3],"-")==0){
+       fin = stdin;
+    }else{
+       fin = fopen(argv[3],"r");
+    }
+       
+    if(strcmp(argv[4],"-")==0){
+       fout = stdout;
+    }else{
+       fout = fopen(argv[4],"w");
+    }
+
+    
+    if(argc>4)
+       modem_probe_init("fmfsk2",argv[5]);
+       
+    /* set up FSK */
+    fmfsk = fmfsk_create(Fs,Rb);
+    
+    if(fin==NULL || fout==NULL || fmfsk==NULL){
+        fprintf(stderr,"Couldn't open test vector files\n");
+        goto cleanup;
+    }
+    
+    /* allocate buffers for processing */
+    bitbuf = (uint8_t*)alloca(sizeof(uint8_t)*fmfsk->nbit);
+    rawbuf = (int16_t*)alloca(sizeof(int16_t)*(fmfsk->N+fmfsk->Ts*2));
+    modbuf = (float*)alloca(sizeof(float)*(fmfsk->N+fmfsk->Ts*2));
+    
+    /* Demodulate! */
+    while( fread(rawbuf,sizeof(int16_t),fmfsk_nin(fmfsk),fin) == fmfsk_nin(fmfsk) ){
+       for(i=0;i<fmfsk_nin(fmfsk);i++){
+           modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
+       }
+       
+       modem_probe_samp_f("t_d_sampin",modbuf,fmfsk_nin(fmfsk));
+        fmfsk_demod(fmfsk,bitbuf,modbuf);
+        
+       for(i=0;i<fmfsk->nbit;i++){
+           t = (int)bitbuf[i];
+           modem_probe_samp_i("t_d_bitout",&t,1);
+       }
+        
+       fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout);
+        
+        if(fin == stdin || fout == stdin){
+           fflush(fin);
+           fflush(fout);
+       }
+    }
+    
+    modem_probe_close();
+    cleanup:
+    fclose(fin);
+    fclose(fout);
+    fmfsk_destroy(fmfsk);
+    exit(0);
+}
+
index 69a632f76174469d9cc1121d5061f4d8e2c96c44..ae739821da12cf1a5fe5c2871fc41e46863af643 100644 (file)
@@ -81,14 +81,14 @@ int main(int argc,char *argv[]){
     while( fread(bitbuf,sizeof(uint8_t),fmfsk->nbit,fin) == fmfsk->nbit ){
         fmfsk_mod(fmfsk,modbuf,bitbuf);
         for(i=0; i<fmfsk->N; i++){
-                       rawbuf[i] = (int16_t)(modbuf[i]*(float)FDMDV_SCALE);
-               }
+           rawbuf[i] = (int16_t)(modbuf[i]*(float)FDMDV_SCALE);
+       }
         fwrite(rawbuf,sizeof(int16_t),fmfsk->N,fout);
         
-               if(fin == stdin || fout == stdin){
-                       fflush(fin);
-                       fflush(fout);
-               }
+       if(fin == stdin || fout == stdin){
+           fflush(fin);
+           fflush(fout);
+       }
     }
     
     cleanup:
index cf0cecfc0f21af0bdbdcb9af441a7d95a5a1c983..83055b0060e9e1d72128e9b9cbfd264a84261d95 100644 (file)
@@ -85,21 +85,21 @@ int main(int argc,char *argv[]){
     
     /* Demodulate! */
     while( fread(rawbuf,sizeof(int16_t),fsk_nin(fsk),fin) == fsk_nin(fsk) ){
-               for(i=0;i<fsk_nin(fsk);i++){
-                       modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
-               }
-               modem_probe_samp_f("t_d_sampin",modbuf,fsk_nin(fsk));
+       for(i=0;i<fsk_nin(fsk);i++){
+           modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
+       }
+       modem_probe_samp_f("t_d_sampin",modbuf,fsk_nin(fsk));
         fsk_demod(fsk,bitbuf,modbuf);
         for(i=0;i<fsk->Nbits;i++){
-                       t = (int)bitbuf[i];
-                       modem_probe_samp_i("t_d_bitout",&t,1);
-               }
+           t = (int)bitbuf[i];
+           modem_probe_samp_i("t_d_bitout",&t,1);
+       }
         fwrite(bitbuf,sizeof(uint8_t),fsk->Nbits,fout);
         
         if(fin == stdin || fout == stdin){
-                       fflush(fin);
-                       fflush(fout);
-               }
+           fflush(fin);
+           fflush(fout);
+       }
     }
     
     modem_probe_close();
index accc7a83f99bb2e0dc3d3752dcb4f6db4b9b57f4..732ac7d8243e531270429198f08cbfed11165ca5 100644 (file)
@@ -66,6 +66,9 @@ target_link_libraries(t16_8_short codec2)
 add_executable(tfsk tfsk.c ../src/kiss_fft.c ../src/kiss_fftr.c ../src/octave.c ../src/modem_probe.c)
 target_link_libraries(tfsk m)
 
+add_executable(tfmfsk tfmfsk.c ../src/octave.c ../src/modem_probe.c)
+target_link_libraries(tfmfsk m)
+
 #add_executable(t48_8 t48_8.c ../src/fdmdv.c ../src/kiss_fft.c)
 #target_link_libraries(t48_8 codec2)
 
diff --git a/codec2-dev/unittest/tfmfsk.c b/codec2-dev/unittest/tfmfsk.c
new file mode 100644 (file)
index 0000000..877e639
--- /dev/null
@@ -0,0 +1,196 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: tfmfsk.c
+  AUTHOR......: Brady O'Brien
+  DATE CREATED: 8 February 2016
+
+  C test driver for fmfsk_mod and fmfsk_demod in fmfsk.c. Reads a file with input
+  bits/rf and spits out modulated/demoduladed samples and a dump of internal
+  state. To run unit test, see octave/tfmfsk.m
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2016 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#define MODEMPROBE_ENABLE
+
+#include "modem_probe.h"
+#include <stdio.h>
+
+/* Note: This is a dirty hack to force fsk.c to compile with modem probing enabled */
+#include "fmfsk.c"
+
+#define ST_BITS 10000
+#define ST_FS 48000
+#define ST_RS 2400
+#define ST_EBNO 8
+
+#define TEST_SELF_FULL 1    /* No-arg self test */
+#define TEST_MOD 2          /* Test modulator using in and out file */
+#define TEST_DEMOD 3        /* Test demodulator using in and out file */
+
+
+int main(int argc,char *argv[]){
+    struct FMFSK *fmfsk;
+    int Fs,Rs;
+    FILE *fin,*fout;
+
+    uint8_t *bitbuf = NULL;
+    float *modbuf = NULL;
+    uint8_t *bitbufp;
+    float *modbufp;
+
+    size_t bitbufsize = 0;
+    size_t modbufsize = 0;
+
+    int test_type;
+    
+    int i;
+    
+    fin = NULL;
+    fout = NULL;
+    
+    /* Set up full self-test */
+    if(argc == 1){
+        test_type = TEST_SELF_FULL;
+        modem_probe_init("fmfsk","fmfsk_tfmfsk_log.txt");
+        Fs = ST_FS;
+        Rs = ST_RS;
+    } else if (argc<7){
+    /* Not running any test */
+        printf("Usage: %s [(M|D) SampleRate BitRate InputFile OutputFile OctaveLogFile]\n",argv[0]);
+        exit(1);
+    } else {
+    /* Running stim-drivin test */
+        /* Mod test */
+        if(strcmp(argv[1],"M")==0 || strcmp(argv[1],"m")==0) {
+            test_type = TEST_MOD;
+        /* Demod test */
+        } else if(strcmp(argv[1],"D")==0 || strcmp(argv[1],"d")==0) {
+            test_type = TEST_DEMOD;
+        } else {
+            printf("Must specify mod or demod test with M or D\n");
+            exit(1);
+        }
+        /* Extract parameters */
+        Fs = atoi(argv[2]);
+        Rs = atoi(argv[3]);
+        
+        /* Open files */
+        fin = fopen(argv[4],"r");
+        fout = fopen(argv[5],"w");
+        
+        if(fin == NULL || fout == NULL){
+            printf("Couldn't open test vector files\n");
+            exit(1);
+        }
+        /* Init modem probing */
+        modem_probe_init("fmfsk",argv[6]);
+        
+    }
+    
+       srand(1);
+    
+    /* set up FSK */
+    fmfsk = fmfsk_create(Fs,Rs);
+    /* Modulate! */
+    if(test_type == TEST_MOD || test_type == TEST_SELF_FULL){
+        /* Generate random bits for self test */
+        if(test_type == TEST_SELF_FULL){
+            bitbufsize = ST_BITS;
+            bitbuf = (uint8_t*) malloc(sizeof(uint8_t)*ST_BITS);
+            for(i=0; i<ST_BITS; i++){
+                /* Generate a randomish bit */
+                bitbuf[i] = (uint8_t)(rand()&0x01);
+            }
+        } else { /* Load bits from a file */
+            /* Figure out how many bits are in the input file */
+            fseek(fin, 0L, SEEK_END);
+            bitbufsize = ftell(fin);
+            fseek(fin, 0L, SEEK_SET);
+            bitbuf = malloc(sizeof(uint8_t)*bitbufsize);
+            i = 0;
+            /* Read in some bits */
+            bitbufp = bitbuf;
+            while( fread(bitbufp,sizeof(uint8_t),fmfsk->nbit,fin) == fmfsk->nbit){
+                i++;
+                bitbufp+=fmfsk->nbit;
+                /* Make sure we don't break the buffer */
+                if(i*fmfsk->nbit > bitbufsize){
+                    bitbuf = realloc(bitbuf,sizeof(uint8_t)*(bitbufsize+fmfsk->nbit));
+                    bitbufsize += fmfsk->nbit;
+                }
+            }
+        }
+        /* Allocate modulation buffer */
+        modbuf = (float*)malloc(sizeof(float)*(bitbufsize/fmfsk->nbit)*fmfsk->N*4);
+        modbufsize = (bitbufsize/fmfsk->nbit)*fmfsk->N;
+        /* Do the modulation */
+        modbufp = modbuf;
+        bitbufp = bitbuf;
+        while( bitbufp < bitbuf+bitbufsize){
+            fmfsk_mod(fmfsk, modbufp, bitbufp);
+            modbufp += fmfsk->N;
+            bitbufp += fmfsk->nbit;
+        }
+        /* For a mod-only test, write out the result */
+        if(test_type == TEST_MOD){
+            fwrite(modbuf,sizeof(float),modbufsize,fout);
+            free(modbuf);
+        }
+        /* Free bit buffer */
+        free(bitbuf);
+    }
+    
+    /* Add channel imp here */
+    
+    
+    /* Now test the demod */
+    if(test_type == TEST_DEMOD || test_type == TEST_SELF_FULL){
+        free(modbuf);
+        modbuf = malloc(sizeof(float)*(fmfsk->N+fmfsk->Ts*2));
+        bitbuf = malloc(sizeof(uint8_t)*fmfsk->nbit);
+        /* Demod-only test */
+        if(test_type == TEST_DEMOD){
+            while( fread(modbuf,sizeof(float),fmfsk_nin(fmfsk),fin) == fmfsk_nin(fmfsk) ){
+                fmfsk_demod(fmfsk,bitbuf,modbuf);
+                fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout);
+            }
+        }
+        /* Demod after channel imp. and mod */
+        else{
+            bitbufp = bitbuf;
+            modbufp = modbuf;
+            while( modbufp < modbuf + modbufsize){
+                fmfsk_demod(fmfsk,bitbuf,modbuf);
+                modbufp += fmfsk_nin(fmfsk);
+            }
+        }
+        free(bitbuf);
+    }
+    
+    modem_probe_close();
+    if(test_type == TEST_DEMOD || test_type == TEST_MOD){
+        fclose(fin);
+        fclose(fout);
+    }
+    fmfsk_destroy(fmfsk);
+    exit(0);
+}
+