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;
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;
%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
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;
};
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
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);
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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#define N 160
+#define TEST_MOD
+
int main(int argc, char *argv[])
{
FILE *fin, *fout;
}
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];
}