Added and tested real->real FM modulator
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 11 Sep 2015 02:34:37 +0000 (02:34 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 11 Sep 2015 02:34:37 +0000 (02:34 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2303 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fm.m
codec2-dev/src/codec2_fm.h
codec2-dev/src/fm.c
codec2-dev/src/fm_demod.c

index 765aae12e1e87e855de11fb184f901761a64e2b1..99c68025aaf83807bc21e7dc65f6bbe5d8cd6711 100644 (file)
@@ -291,7 +291,7 @@ end
 
 
 function fm_mod_file(file_name_out)
-  fm_states.Fs = 44400;  
+  fm_states.Fs = 48000;  
   fm_states.fm_max = 3E3;
   fm_states.fd = 5E3;
   fm_states.fc = fm_states.Fs/4;
@@ -412,6 +412,46 @@ function make_coeff_file
   fm_fir_coeff_file(fm_states, "fm_fir_coeff.h")
 endfunction
 
+function test_fm_modulator
+  fm_states.Fs = 48000;  
+  fm_states.fm_max = 3E3;
+  fm_states.fd = 5E3;
+  fm_states.fc = fm_states.Fs/4;
+
+  fm_states.pre_emp = 0;
+  fm_states.de_emp  = 0;
+  fm_states.Ts = 1;
+  fm_states.output_filter = 1;
+  fm_states = analog_fm_init(fm_states);
+  
+  test_t = [1:(fm_states.Fs*10)];
+  test_freq1 = 2*pi*3000/fm_states.Fs;
+  test_freq2 = 2*pi*1000/fm_states.Fs;
+
+  test_sig = .5*sin(test_t*test_freq1) + .5*sin(test_t*test_freq2);
+  %test_sig = zeros(1,length(test_t));
+  %test_sig = ones(1,length(test_t));
+
+  ftsig = fopen("fm_test_sig.raw","wb");
+  fwrite(ftsig,test_sig*16384,"short");
+  fclose(ftsig);
+  
+  system("../fm_test fm_test_sig.raw fm_test_out.raw");
+  ftmod = fopen("fm_test_out.raw","r");
+  test_mod = fread(ftmod,"short")/16384;
+  fclose(ftmod);
+  
+  comp_mod = analog_fm_mod(fm_states,test_sig);
+  
+  figure(1)
+  comp_mod_real = real(comp_mod);
+  size(comp_mod_real)
+  size(test_mod)
+  mod_diff = zeros(1,length(test_mod));
+  mod_diff = rot90(test_mod) .- comp_mod_real;
+  plot(mod_diff);
+  
+endfunction
 
 more off;
 
@@ -420,4 +460,5 @@ more off;
 %fm_demod_file("ssb25_fm_de.raw", "~/Desktop/ssb25db.wav")
 %run_fm_single
 %make_coeff_file
-fm_mod_file("fm_1000.raw");
+%fm_mod_file("fm_1000.raw");
+test_fm_modulator
index 92457ecfff165ceeea74e2814b23072ce6f883df..630ac23fa29d433e1b8d6593d677c5550da22da3 100644 (file)
@@ -37,7 +37,8 @@ struct FM {
     float  fc;               /* setme: carrier frequency            */ 
     COMP  *rx_bb;
     COMP   rx_bb_filt_prev;
-    float *rx_dem_mem;      
+    float *rx_dem_mem;
+    float  tx_phase;
     int    nsam;
     COMP   lo_phase;
 };
@@ -45,6 +46,7 @@ struct FM {
 struct FM *fm_create(int nsam);
 void fm_destroy(struct FM *fm_states);
 void fm_demod(struct FM *fm, float rx_out[], float rx[]);
+void fm_mod(struct FM *fm, float tx_in[], float tx_out[]);
 
 #endif
 
index bdccd8a8b9c91c562dc432777becdb82202e6f96..d63e0999ad5dc9259af111b5efaf2b3cd7ac1987 100644 (file)
@@ -83,6 +83,8 @@ struct FM *fm_create(int nsam)
     fm->lo_phase.real = 1.0;
     fm->lo_phase.imag = 0.0;
 
+    fm->tx_phase = 0;
+
     fm->rx_dem_mem = (float*)malloc(sizeof(float)*(FILT_MEM+nsam));
     assert(fm->rx_dem_mem != NULL);
 
@@ -193,3 +195,63 @@ void fm_demod(struct FM *fm_states, float rx_out[], float rx[])
   fm_states->lo_phase.imag /= mag;     
 
 }
+
+/*---------------------------------------------------------------------------*\
+                                                       
+  FUNCTION....: fm_mod      
+  AUTHOR......: Brady O'Brien                        
+  DATE CREATED: Sept. 10 2015
+
+  Modulate an FM signal from a baseband modulating signal
+
+  struct FM *fm - FM state structure. Can be reused from fm_demod.
+  float tx_in[] - nsam baseband samples to be modulated
+  float tx_out[] - nsam samples in which to place the modulated FM
+
+\*---------------------------------------------------------------------------*/
+
+void fm_mod(struct FM *fm_states, float tx_in[], float tx_out[]){
+  float  Fs = fm_states->Fs;    //Sampling freq
+  float  fc = fm_states->fc;    //Center freq
+  float  wc = 2*M_PI*fc/Fs;     //Center freq in rads/samp
+  float  fd = fm_states->fd;    //Max deviation in cycles/samp
+  float  wd = 2*M_PI*fd/Fs;     //Max deviation in rads/samp
+  int  nsam = fm_states->nsam;  //Samples per batch of modulation
+  float tx_phase = fm_states->tx_phase; //Transmit phase in rads
+  float w;                     //Temp variable for phase of VFO during loop
+  int i;
+  //Go through the samples, spin the oscillator, and generate some FM
+  for(i=0; i<nsam; i++){
+      w = wc + wd*tx_in[i];   //Calculate phase of VFO
+      tx_phase += w;          //Spin TX oscillator
+
+      //TODO: Add pre-emphasis and pre-emph AGC for voice    
+
+      //Make sure tx_phase stays from 0 to 2PI.
+      //If tx_phase goes above 4PI, It's because fc+fd*tx_in[i] is way too large for the sample
+      // rate.
+      if(tx_phase > 2*M_PI)
+          tx_phase -= 2*M_PI;
+
+      tx_out[i] = cosf(tx_phase);
+  }
+  //Save phase back into state struct
+  fm_states->tx_phase = tx_phase;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
index 8042df65ea610844bce0886e2227df4d77bcb738..fd4301bd52110ff07ccc24c02c220ce0a8fe0349 100644 (file)
@@ -38,6 +38,8 @@
 
 #define N 160
 
+#define TEST_MOD
+
 int main(int argc, char *argv[])
 {
     FILE         *fin, *fout;
@@ -68,16 +70,20 @@ int main(int argc, char *argv[])
     }
 
     fm         = fm_create(N);
-    fm->Fs     = 44400.0;
+    fm->Fs     = 48000.0;
     fm->fm_max = 3000.0;
     fm->fd     = 5000.0;
     fm->fc     = fm->Fs/4;
 
     while(fread(buf, sizeof(short), N, fin) == N) {
        for(i=0; i<N; i++) {
-           rx[i] = buf[i];
+           rx[i] = ((float)buf[i])/16384;
         }
+#ifdef TEST_MOD
+       fm_mod(fm, rx, rx_out);
+#else
         fm_demod(fm, rx_out, rx);
+#endif
        for(i=0; i<N; i++) {
            buf[i] = 16384*rx_out[i];
         }