\*---------------------------------------------------------------------------*/
-void fm_mod(struct FM *fm_states, float tx_in[], float tx_out[]){
+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
// rate.
if(tx_phase > 2*M_PI)
tx_phase -= 2*M_PI;
-
tx_out[i] = cosf(tx_phase);
}
//Save phase back into state struct
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.
#define STD_PROC_BITS 96
+/* Define this to enable EbNodB estimate */
+/* This needs square roots, may take more cpu time than it's worth */
+#define EST_EBNO
/*
* Create a new fmfsk modem instance.
/* Set up demod state */
fmfsk->lodd = 0;
fmfsk->nin = fmfsk->N;
+ fmfsk->snr_mean = 0;
float *oldsamps = malloc(sizeof(float)*fmfsk->nmem);
if(oldsamps == NULL){
int neyeoffset;
float eye_max;
uint8_t mbit;
+ #ifdef EST_EBNO
+ float amp_even = 0, amp_odd = 0, amp_bit, amp_noise;
+ #endif
/* Shift in nin samples */
memcpy(&oldsamps[0] , &oldsamps[nmem-nold], sizeof(float)*nold);
apeven += mdiff;
/* Even stream goes in LSB */
rx_bits[i>>1] |= mbit ? 0x1 : 0x0;
+ #ifdef EST_EBNO
+ amp_even += currv * currv;
+ #endif
}else{
apodd += mdiff;
/* Odd in second-to-LSB */
rx_bits[i>>1] = mbit ? 0x2 : 0x0;
+ #ifdef EST_EBNO
+ amp_odd += currv * currv;
+ #endif
}
}
+ #ifdef EST_EBNO
+ amp_even = sqrt(amp_even);
+ amp_odd = sqrt(amp_odd);
+ #endif
if(apeven>apodd){
/* Zero out odd bits from output bitstream */
for(i=0;i<nbit;i++)
rx_bits[i] &= 0x1;
+ #ifdef EST_EBNO
+ amp_bit = amp_even;
+ amp_noise = amp_odd;
+ #endif
}else{
/* 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;
+ #ifdef EST_EBNO
+ amp_bit = amp_odd;
+ amp_noise = amp_even;
+ #endif
}
/* Save last sample of int stream for next demod round */
/* Zero out all of the other things */
fmfsk->stats->foff = 0;
+
+ #ifdef EST_EBNO
+ amp_bit = fabsf(amp_bit - amp_noise);
+ fmfsk->snr_mean *= .9;
+ fmfsk->snr_mean += (amp_bit+1e-6)/(amp_noise+1e-6);
+ fmfsk->stats->snr_est = 20+20*log10f(fmfsk->snr_mean);
+ #else
fmfsk->stats->snr_est = 0;
+ #endif
/* Collect an eye diagram */
/* Take a sample for the eye diagrams */
/* Stats generated by demod */
float norm_rx_timing; /* RX Timing, used to calculate clock offset */
int ppm; /* Clock offset in parts-per-million */
+ float snr_mean;
/* Modem stat structure */
struct MODEM_STATS * stats;
int n_ascii;
char ascii_out;
- /* DR: 21/11/16 - temp code while porting fsk_demod to complex */
-
- int n = fsk_nin(f->fsk);
- COMP demod_comp[n];
- for(i=0; i<n; i++) {
- demod_comp[i].real = demod_in[i];
- demod_comp[i].imag = 0.0;;
- }
if(f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_800XA){
- fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_comp);
+ /* DR: 21/11/16 - temp code while porting fsk_demod to complex */
+ int n = fsk_nin(f->fsk);
+ COMP demod_comp[n];
+ for(i=0; i<n; i++) {
+ demod_comp[i].real = demod_in[i];
+ demod_comp[i].imag = 0.0;;
+ }
+
+ fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_comp);
f->nin = fsk_nin(f->fsk);
}else{
fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in);