f->modem_sample_rate = 48000;
/* Malloc something to appease freedv_init and freedv_destroy */
f->codec_bits = malloc(1);
+
+ /* Set up the stats */
+ fsk_setup_modem_stats(f->fsk,&(f->stats));
}
if (mode == FREEDV_MODE_2400B) {
float rx_float[f->n_max_modem_samples];
int i;
int nin = freedv_nin(f);
-
assert(nin <= f->n_max_modem_samples);
/* FSK RX happens in real floats, so convert to those and call their demod here */
if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) ){
int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
assert(f != NULL);
COMP rx_fdm[f->n_max_modem_samples];
+ uint8_t vc_bits[2];
+ short vc_bit;
int i;
- int nin = freedv_nin(f);
-
+ int nin = freedv_nin(f);
+ int n_ascii;
+ char ascii_out;
+ float Rs;
+
assert(nin <= f->n_max_modem_samples);
/* FSK RX happens in real floats, so demod for those goes here */
if(f->mode == FREEDV_MODE_2400A){
fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_in);
f->nin = fsk_nin(f->fsk);
- f->stats.snr_est = f->fsk->EbNodB;
- f->stats.clock_offset = f->fsk->ppm;
}else{
fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in);
f->nin = fmfsk_nin(f->fmfsk);
+ f->stats.clock_offset = f->fsk->ppm;
}
- /* TODO: Protocol and varicode bits */
- if(fvhff_deframe_bits(f->deframer,f->packed_codec_bits,NULL,NULL,(uint8_t*)f->tx_bits)){
+ /* TODO: Protocol bits */
+ if(fvhff_deframe_bits(f->deframer,f->packed_codec_bits,NULL,vc_bits,(uint8_t*)f->tx_bits)){
+ /* Decode varicode text */
+ for(i=0; i<2; i++){
+ /* Note: deframe_bits spits out bits in uint8_ts while varicode_decode expects shorts */
+ vc_bit = vc_bits[i];
+ n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, &vc_bit, 1, 1);
+ if (n_ascii && (f->freedv_put_next_rx_char != NULL)) {
+ (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out);
+ }
+ }
/* Decode the codec data */
codec2_decode(f->codec2,speech_out,f->packed_codec_bits);
f->sync = 1;
f->stats.sync = 1;
+
+
} else {
/* Fill with silence */
for(i=0;i<f->n_speech_samples;i++){
fsk->f4_est = 0;
fsk->ppm = 0;
+ fsk->stats = NULL;
+
return fsk;
}
fsk->f4_est = 0;
fsk->ppm = 0;
+ fsk->stats = NULL;
+
return fsk;
}
free(fsk);
}
+void fsk_setup_modem_stats(struct FSK *fsk,struct MODEM_STATS *stats){
+ fsk->stats = stats;
+}
+
/*
* Internal function to estimate the frequencies of the two tones within a block of samples.
for(i=0; i<M; i++){
freqs[i] = (float)(freqi[i])*((float)Fs/(float)Ndft);
}
-
#ifndef DEMOD_ALLOC_STACK
free(fftin);
free(fftout);
int Nmem = fsk->Nmem;
int M = fsk->mode;
int i,j,dc_i,cbuf_i;
- float ft1,ft2;
+ float ft1;
int nstash = fsk->nstash;
COMP *f1_int, *f2_int;
COMP t1,t2;
int using_old_samps;
float *sample_src;
COMP *f1_intbuf,*f2_intbuf;
- float f_est[M];
+ float f_est[M],fc_avg,fc_tx;
float meanebno,stdebno;
/* Accumulate resampled int magnitude for EbNodB estimation */
/* Standard deviation is calculated by algorithm devised by crafty soviets */
#ifdef EST_EBNO
+ /* Accumulate the square of the sampled value */
+ ft1 = tmax[ (tmax[1]>tmax[0]) ];
+ stdebno += ft1;
- ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag);
- ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag);
- ft1 = fabsf(ft1-ft2);
- meanebno += ft1;
-
+ /* Figure the abs value of the max tone */
+ meanebno += sqrtf(ft1);
#endif
/* Soft output goes here */
}
#ifdef EST_EBNO
/* Calculate mean for EbNodB estimation */
meanebno = meanebno/(float)nsym;
- stdebno = 0;
- /* Go back through the data and figure the std dev */
- for(i=0; i<nsym; i++){
- int st = (i+1)*P;
- t1 = fcmult(1-fract,f1_int[st+ low_sample]);
- t1 = cadd(t1,fcmult( fract,f1_int[st+high_sample]));
- t2 = fcmult(1-fract,f2_int[st+ low_sample]);
- t2 = cadd(t2,fcmult( fract,f2_int[st+high_sample]));
-
- /* Accumulate resampled int magnitude for EbNodB estimation */
- ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag);
- ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag);
- ft1 = fabsf(ft1-ft2);
- ft2 = abs(meanebno-ft1);
- stdebno += ft2*ft2;
- }
- /* Finish figuring std. dev. */
- stdebno = sqrtf(stdebno/(float)(nsym-1));
- fsk->EbNodB = 20*log10f((1e-6+meanebno)/(1e-6+stdebno));
+
+ /* Calculate the std. dev for EbNodB estimate */
+ stdebno = (stdebno/(float)nsym) - (meanebno*meanebno);
+ stdebno = sqrt(stdebno);
+
+ fsk->EbNodB = -6+(20*log10f((1e-6+meanebno)/(1e-6+stdebno)));
#else
fsk->EbNodB = 1;
#endif
free(f2_intbuf);
#endif
+ /* Write some statistics out to the stats struct, if present */
+ if( fsk->stats != NULL ){
+ /* Save clock offset in ppm */
+ fsk->stats->clock_offset = fsk->ppm;
+
+ /* Calculate and save SNR from EbNodB estimate */
+ fsk->stats->snr_est = fsk->EbNodB + 10*log10f(((float)Rs)/((float)Rs*M));
+
+ /* Save rx timing */
+ fsk->stats->rx_timing = (float)rx_timing;
+
+ /* Estimate and save frequency offset */
+ fc_avg = (f_est[0]+f_est[1])/2;
+ fc_tx = (fsk->f1_tx+fsk->f1_tx+fsk->fs_tx)/2;
+ fsk->stats->foff = fc_tx-fc_avg;
+
+ fsk->stats->nr = 0;
+ fsk->stats->Nc = 0;
+ }
+
/* Dump some internal samples */
modem_probe_samp_f("t_EbNodB",&(fsk->EbNodB),1);
modem_probe_samp_f("t_ppm",&(fsk->ppm),1);
int Nmem = fsk->Nmem;
int M = fsk->mode;
int i,j,dc_i,cbuf_i;
- float ft1,ft2;
+ float ft1;
int nstash = fsk->nstash;
COMP *f1_int, *f2_int, *f3_int, *f4_int;
COMP t1,t2,t3,t4;
int using_old_samps;
float *sample_src;
COMP *f1_intbuf,*f2_intbuf,*f3_intbuf,*f4_intbuf;
- float f_est[M];
+ float f_est[M],fc_avg,fc_tx;
float meanebno,stdebno;
/* Estimate tone frequencies */
/* Accumulate resampled int magnitude for EbNodB estimation */
/* Standard deviation is calculated by algorithm devised by crafty soviets */
#ifdef EST_EBNO
+ /* Accumulate the square of the sampled value */
+ ft1 = max;
+ stdebno += ft1;
- ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag);
- ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag);
- ft1 = fabsf(ft1-ft2);
- meanebno += ft1;
-
+ /* Figure the abs value of the max tone */
+ meanebno += sqrtf(ft1);
#endif
/* Soft output goes here */
}
- #ifdef EST_EBNO
+ #ifdef EST_EBNO
/* Calculate mean for EbNodB estimation */
meanebno = meanebno/(float)nsym;
- stdebno = 0;
- /* Go back through the data and figure the std dev */
- for(i=0; i<nsym; i++){
- int st = (i+1)*P;
- t1 = fcmult(1-fract,f1_int[st+ low_sample]);
- t1 = cadd(t1,fcmult( fract,f1_int[st+high_sample]));
- t2 = fcmult(1-fract,f2_int[st+ low_sample]);
- t2 = cadd(t2,fcmult( fract,f2_int[st+high_sample]));
-
- /* Accumulate resampled int magnitude for EbNodB estimation */
- ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag);
- ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag);
- ft1 = fabsf(ft1-ft2);
- ft2 = abs(meanebno-ft1);
- stdebno += ft2*ft2;
- }
- /* Finish figuring std. dev. */
- stdebno = sqrtf(stdebno/(float)(nsym-1));
- fsk->EbNodB = 20*log10f((1e-6+meanebno)/(1e-6+stdebno));
+
+ /* Calculate the std. dev for EbNodB estimate */
+ stdebno = (stdebno/(float)nsym) - (meanebno*meanebno);
+ stdebno = sqrt(stdebno);
+
+ fsk->EbNodB = -6+(20*log10f((1e-6+meanebno)/(1e-6+stdebno)));
#else
- fsk->EbNodB = 0;
+ fsk->EbNodB = 1;
#endif
#ifndef DEMOD_ALLOC_STACK
free(f4_intbuf);
#endif
+ /* Write some statistics out to the stats struct, if present */
+ if( fsk->stats != NULL ){
+ /* Save clock offset in ppm */
+ fsk->stats->clock_offset = fsk->ppm;
+
+ /* Calculate and save SNR from EbNodB estimate */
+ fsk->stats->snr_est = fsk->EbNodB + 10*log10f(((float)Rs*2)/((float)Rs*M));
+
+ /* Save rx timing */
+ fsk->stats->rx_timing = (float)rx_timing;
+
+ /* Estimate and save frequency offset */
+ fc_avg = (f_est[0]+f_est[1]+f_est[2]+f_est[3])/4;
+ fc_tx = (fsk->f1_tx+fsk->f1_tx+(fsk->fs_tx*3))/2;
+ fsk->stats->foff = fc_tx-fc_avg;
+
+ fsk->stats->nr = 0;
+ fsk->stats->Nc = 0;
+ }
+
/* Dump some internal samples */
modem_probe_samp_f("t_EbNodB",&(fsk->EbNodB),1);
modem_probe_samp_f("t_ppm",&(fsk->ppm),1);