}
fmfsk->oldsamps = oldsamps;
- fmfsk->stats = NULL;
+
+ fmfsk->stats = (struct MODEM_STATS*)malloc(sizeof(struct MODEM_STATS));
+ if (fmfsk->stats == NULL) {
+ free(oldsamps);
+ free(fmfsk);
+ return NULL;
+ }
return fmfsk;
}
return (uint32_t)fmfsk->nin;
}
-void fmfsk_setup_modem_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats){
- fmfsk->stats = stats;
+void fmfsk_get_demod_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats){
+ /* copy from internal stats, note we can't overwrite stats completely
+ as it has other states rqd by caller, also we want a consistent
+ interface across modem types for the freedv_api.
+ */
+
+ stats->clock_offset = fmfsk->stats->clock_offset;
+ stats->snr_est = fmfsk->stats->snr_est; // TODO: make this SNR not Eb/No
+ stats->rx_timing = fmfsk->stats->rx_timing;
+ stats->foff = fmfsk->stats->foff;
+
+ stats->neyesamp = fmfsk->stats->neyesamp;
+ stats->neyetr = fmfsk->stats->neyetr;
+ memcpy(stats->rx_eye, fmfsk->stats->rx_eye, sizeof(stats->rx_eye));
+
+ /* these fields not used for FSK so set to something sensible */
+
+ stats->sync = 0;
+ stats->nr = fmfsk->stats->nr;
+ stats->Nc = fmfsk->stats->Nc;
}
/*
fmfsk->lodd = lastv;
/* Save demod statistics */
- if(fmfsk->stats != NULL){
- fmfsk->stats->Nc = 0;
- fmfsk->stats->nr = 0;
+ fmfsk->stats->Nc = 0;
+ fmfsk->stats->nr = 0;
- /* Clock offset and RX timing are all we know here */
- fmfsk->stats->clock_offset = fmfsk->ppm;
- fmfsk->stats->rx_timing = (float)rx_timing;
+ /* Clock offset and RX timing are all we know here */
+ fmfsk->stats->clock_offset = fmfsk->ppm;
+ fmfsk->stats->rx_timing = (float)rx_timing;
- /* Zero out all of the other things */
- fmfsk->stats->foff = 0;
+ /* 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
+#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 */
- neyesamp = fmfsk->stats->neyesamp = Ts*4;
- neyeoffset = sample_offset+(Ts*2*28);
+ /* Collect an eye diagram */
+ /* Take a sample for the eye diagrams */
+ neyesamp = fmfsk->stats->neyesamp = Ts*4;
+ neyeoffset = sample_offset+(Ts*2*28);
- fmfsk->stats->neyetr = 8;
- for(k=0; k<fmfsk->stats->neyetr; k++)
- for(j=0; j<neyesamp; j++)
- fmfsk->stats->rx_eye[k][j] = rx_filt[k*neyesamp+neyeoffset+j];
- //fmfsk->stats->rx_eye[k][j] = fmfsk_in[k*neyesamp+neyeoffset+j];
- eye_max = 0;
+ fmfsk->stats->neyetr = 8;
+ for(k=0; k<fmfsk->stats->neyetr; k++)
+ for(j=0; j<neyesamp; j++)
+ fmfsk->stats->rx_eye[k][j] = rx_filt[k*neyesamp+neyeoffset+j];
+ //fmfsk->stats->rx_eye[k][j] = fmfsk_in[k*neyesamp+neyeoffset+j];
+ eye_max = 0;
- /* Normalize eye to +/- 1 */
- for(i=0; i<fmfsk->stats->neyetr; i++)
- for(j=0; j<neyesamp; j++)
- if(fabsf(fmfsk->stats->rx_eye[i][j])>eye_max)
- eye_max = fabsf(fmfsk->stats->rx_eye[i][j]);
+ /* Normalize eye to +/- 1 */
+ for(i=0; i<fmfsk->stats->neyetr; i++)
+ for(j=0; j<neyesamp; j++)
+ if(fabsf(fmfsk->stats->rx_eye[i][j])>eye_max)
+ eye_max = fabsf(fmfsk->stats->rx_eye[i][j]);
- for(i=0; i<fmfsk->stats->neyetr; i++)
- for(j=0; j<neyesamp; j++)
- fmfsk->stats->rx_eye[i][j] = (fmfsk->stats->rx_eye[i][j]/(2*eye_max))+.5;
- }
+ for(i=0; i<fmfsk->stats->neyetr; i++)
+ for(j=0; j<neyesamp; j++)
+ fmfsk->stats->rx_eye[i][j] = (fmfsk->stats->rx_eye[i][j]/(2*eye_max))+.5;
modem_probe_samp_f("t_norm_rx_timing",&norm_rx_timing,1);
modem_probe_samp_f("t_rx_filt",rx_filt,(nsym+1)*Ts);
#ifndef __C2FMFSK_H
#define __C2FMFSK_H
#include <stdint.h>
-#include "comp.h"\r
-#include "modem_stats.h"\r
-\r
-#define FMFSK_SCALE 16383\r
-\r
-/* \r
- * fm-me-2fsk state\r
- */\r
+#include "comp.h"
+#include "modem_stats.h"
+
+#define FMFSK_SCALE 16383
+
+/*
+ * fm-me-2fsk state
+ */
struct FMFSK{
/* Static fmfsk parameters */
int Rb; /* Manchester-encoded bitrate */
void fmfsk_destroy(struct FMFSK *fmfsk);
/*
- * Set a MODEM_STATS struct in which to deposit demod statistics
+ * Deposit demod statistics into a MODEM_STATS struct
*/
-void fmfsk_setup_modem_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats);
+void fmfsk_get_demod_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats);
/*
* Returns the number of samples that must be fed to fmfsk_demod the next
if(argc>5){
if(strcmp(argv[5],"S")==0){
enable_stats = 1;
- fmfsk_setup_modem_stats(fmfsk,&stats);
loop_time = ((float)fmfsk_nin(fmfsk))/((float)Fs);
stats_loop = (int)(.125/loop_time);
stats_ctr = 0;
fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout);
if(enable_stats && stats_ctr <= 0){
+ fmfsk_get_demod_stats(fmfsk,&stats);
fprintf(stderr,"{\"EbNodB\": %2.2f,\t\"ppm\": %d,",stats.snr_est,(int)stats.clock_offset);
fprintf(stderr,"\t\"f1_est\":%.1f,\t\"f2_est\":%.1f",0.0,0.0);
fprintf(stderr,",\t\"eye_diagram\":[");
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) {
f->modem_sample_rate = 48000;
/* Malloc something to appease freedv_init and freedv_destroy */
f->codec_bits = malloc(1);
-
- /* Set up the stats */
- fmfsk_setup_modem_stats(f->fmfsk,&(f->stats));
}
if (mode == FREEDV_MODE_800XA) {
f->n_protocol_bits = 0;
codec2_mode = CODEC2_MODE_700C;
-
- /* Set up the stats */
- fsk_setup_modem_stats(f->fsk,&(f->stats));
}
{
if (f->mode == FREEDV_MODE_1600)
fdmdv_get_demod_stats(f->fdmdv, stats);
- if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA))
- memcpy(stats,&(f->stats),sizeof(struct MODEM_STATS));
+
+ if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_800XA)) {
+ fsk_get_demod_stats(f->fsk, stats);
+ }
+
+ if (f->mode == FREEDV_MODE_2400B) {
+ fmfsk_get_demod_stats(f->fmfsk, stats);
+ }
#ifndef CORTEX_M4
if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_700C))
fsk->ppm = 0;
- fsk->stats = NULL;
-
+ fsk->stats = (struct MODEM_STATS*)malloc(sizeof(struct MODEM_STATS));
+ if(fsk->stats == NULL){
+ free(fsk->fft_est);
+ free(fsk->samp_old);
+ free(fsk->fft_cfg);
+ free(fsk);
+ return NULL;
+ }
+
return fsk;
}
fsk->f_est[i] = 0;
fsk->ppm = 0;
-
- fsk->stats = NULL;
+ fsk->stats = (struct MODEM_STATS*)malloc(sizeof(struct MODEM_STATS));
+ if(fsk->stats == NULL){
+ free(fsk->fft_est);
+ free(fsk->samp_old);
+ free(fsk->fft_cfg);
+ free(fsk);
+ return NULL;
+ }
+
return fsk;
}
void fsk_destroy(struct FSK *fsk){
free(fsk->fft_cfg);
free(fsk->samp_old);
+ free(fsk->stats);
free(fsk);
}
-void fsk_setup_modem_stats(struct FSK *fsk,struct MODEM_STATS *stats){
- fsk->stats = stats;
+void fsk_get_demod_stats(struct FSK *fsk, struct MODEM_STATS *stats){
+ /* copy from internal stats, note we can't overwrite stats completely
+ as it has other states rqd by caller, also we want a consistent
+ interface across modem types for the freedv_api.
+ */
+
+ stats->clock_offset = fsk->stats->clock_offset;
+ stats->snr_est = fsk->stats->snr_est; // TODO: make this SNR not Eb/No
+ stats->rx_timing = fsk->stats->rx_timing;
+ stats->foff = fsk->stats->foff;
+
+ stats->neyesamp = fsk->stats->neyesamp;
+ stats->neyetr = fsk->stats->neyetr;
+ memcpy(stats->rx_eye, fsk->stats->rx_eye, sizeof(stats->rx_eye));
+
+ /* these fields not used for FSK so set to something sensible */
+
+ stats->sync = 0;
+ stats->nr = fsk->stats->nr;
+ stats->Nc = fsk->stats->Nc;
}
/*
fsk->EbNodB = 1;
#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;
+ /* Write some statistics to the stats struct */
+
+ /* Save clock offset in ppm */
+ fsk->stats->clock_offset = fsk->ppm;
- /* Calculate and save SNR from EbNodB estimate */
- fsk->stats->snr_est = .5*fsk->stats->snr_est + .5*fsk->EbNodB;//+ 10*log10f(((float)Rs)/((float)Rs*M));
+ /* Calculate and save SNR from EbNodB estimate */
+ fsk->stats->snr_est = .5*fsk->stats->snr_est + .5*fsk->EbNodB;//+ 10*log10f(((float)Rs)/((float)Rs*M));
- /* Save rx timing */
- fsk->stats->rx_timing = (float)rx_timing;
+ /* 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;
-
- /* Take a sample for the eye diagrams */
- neyesamp = fsk->stats->neyesamp = P*2;
- neyeoffset = high_sample+1+(P*28);
+ /* 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;
+
+ /* Take a sample for the eye diagrams */
+ neyesamp = fsk->stats->neyesamp = P*2;
+ neyeoffset = high_sample+1+(P*28);
- int eye_traces = MODEM_STATS_ET_MAX/M;
+ int eye_traces = MODEM_STATS_ET_MAX/M;
- fsk->stats->neyetr = fsk->mode*eye_traces;
- for( i=0; i<eye_traces; i++){
- for ( m=0; m<M; m++){
- for(j=0; j<neyesamp; j++)
- fsk->stats->rx_eye[i*M+m][j] = cabsolute(f_int[m][neyesamp*i+neyeoffset+j]);
- }
+ fsk->stats->neyetr = fsk->mode*eye_traces;
+ for( i=0; i<eye_traces; i++){
+ for ( m=0; m<M; m++){
+ for(j=0; j<neyesamp; j++)
+ fsk->stats->rx_eye[i*M+m][j] = cabsolute(f_int[m][neyesamp*i+neyeoffset+j]);
}
+ }
- eye_max = 0;
- /* Normalize eye to +/- 1 */
- for(i=0; i<M*eye_traces; i++)
- for(j=0; j<neyesamp; j++)
- if(fabsf(fsk->stats->rx_eye[i][j])>eye_max)
- eye_max = fabsf(fsk->stats->rx_eye[i][j]);
+ eye_max = 0;
+ /* Normalize eye to +/- 1 */
+ for(i=0; i<M*eye_traces; i++)
+ for(j=0; j<neyesamp; j++)
+ if(fabsf(fsk->stats->rx_eye[i][j])>eye_max)
+ eye_max = fabsf(fsk->stats->rx_eye[i][j]);
- for(i=0; i<M*eye_traces; i++)
- for(j=0; j<neyesamp; j++)
- fsk->stats->rx_eye[i][j] = fsk->stats->rx_eye[i][j]/eye_max;
+ for(i=0; i<M*eye_traces; i++)
+ for(j=0; j<neyesamp; j++)
+ fsk->stats->rx_eye[i][j] = fsk->stats->rx_eye[i][j]/eye_max;
- fsk->stats->nr = 0;
- fsk->stats->Nc = 0;
- }
+ fsk->stats->nr = 0;
+ fsk->stats->Nc = 0;
/* Dump some internal samples */
modem_probe_samp_f("t_EbNodB",&(fsk->EbNodB),1);
#include "kiss_fftr.h"
#include "modem_stats.h"
-#define MODE_2FSK 2\r
-#define MODE_4FSK 4\r
+#define MODE_2FSK 2
+#define MODE_4FSK 4
#define MODE_M_MAX 4
-\r
-#define FSK_SCALE 16383\r
-\r
-struct FSK {\r
+
+#define FSK_SCALE 16383
+
+struct FSK {
/* Static parameters set up by fsk_init */\r
int Ndft; /* buffer size for freq offset est fft */\r
int Fs; /* sample freq */
/* Parameters used by mod/demod and driving code */
int nin; /* Number of samples to feed the next demod cycle */
- /* Pointer to modem statistic struct */
+ /* modem statistic struct */
struct MODEM_STATS *stats;
};
void fsk_clear_estimators(struct FSK *fsk);
/*
- * Set a MODEM_STATS struct in which to deposit demod statistics
+ * Fills MODEM_STATS struct with demod statistics
*/
-void fsk_setup_modem_stats(struct FSK *fsk,struct MODEM_STATS *stats);
+void fsk_get_demod_stats(struct FSK *fsk, struct MODEM_STATS *stats);
/*
* Destroy an FSK state struct and free it's memory
}
if(enable_stats){
- fsk_setup_modem_stats(fsk,&stats);
loop_time = ((float)fsk_nin(fsk))/((float)Fs);
stats_loop = (int)(1/(stats_rate*loop_time));
stats_ctr = 0;
}
if(enable_stats && stats_ctr <= 0){
+ fsk_get_demod_stats(fsk,&stats);
/* Print standard 2FSK stats */
fprintf(stderr,"{\"EbNodB\": %2.2f,\t\"ppm\": %d,",stats.snr_est,(int)fsk->ppm);
fprintf(stderr,"\t\"f1_est\":%.1f,\t\"f2_est\":%.1f",fsk->f_est[0],fsk->f_est[1]);