added extended modem stats, hooked up SNR ests to freedv API for 700D
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 1 May 2018 00:40:43 +0000 (00:40 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 1 May 2018 00:40:43 +0000 (00:40 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3542 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/codec2_ofdm.h
codec2-dev/src/freedv_api.c
codec2-dev/src/ofdm.c

index 0d96aaff435ccadfa8bcfab3153ffd15025d9332..82ef549cbe966b95fcbb7ecd8e4d90d706406ac7 100644 (file)
@@ -38,6 +38,7 @@ extern "C" {
 #include <stdbool.h>
     
 #include "comp.h"
+#include "modem_stats.h"
 
 /* Defines */
 
@@ -70,6 +71,7 @@ int ofdm_get_nin(struct OFDM *);
 int ofdm_get_samples_per_frame(void);
 int ofdm_get_max_samples_per_frame(void);
 int ofdm_get_bits_per_frame(struct OFDM *);
+void ofdm_get_demod_stats(struct OFDM *ofdm, struct MODEM_STATS *stats);
 
 /* option setters */
 
index 882e032a60e409322d735547419b286016ef9327..4955d0766c3546059ef58a0b102db5b29c12dc11 100644 (file)
@@ -1627,10 +1627,10 @@ static int freedv_comprx_700(struct freedv *f, COMP demod_in_8kHz[], int *valid)
     [X] in testframe mode count coded and uncoded errors
     [X] freedv getter for modem and interleaver sync
     [X] rms level the same as fdmdv
-    [ ] way to stay in sync and not resync automatically 
-    [ ] SNR est, maybe from pilots, cohpsk have an example?
+    [X] way to stay in sync and not resync automatically 
+    [X] SNR est, maybe from pilots, cohpsk have an example?
     [ ] error pattern support?
-    [ ] work out how to handle return of multiple interleaved frames over time
+    [X] work out how to handle return of multiple interleaved frames over time
     [ ] deal with out of sync returning nin samples, listening to analog audio when out of sync
 */
 
@@ -1687,6 +1687,9 @@ static int freedv_comprx_700d(struct freedv *f, COMP demod_in_8kHz[], int *valid
     
     if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state,"trial") == 0) ) {
         ofdm_demod(ofdm, rx_bits, rxbuf_in);
+        fdmdv_get_demod_stats(f->fdmdv, &f->stats);
+        f->sync = 1;
+        f->snr_est = f->stats.snr_est;
           
         assert((OFDM_NUWBITS+OFDM_NTXTBITS+coded_bits_per_frame) == OFDM_BITSPERFRAME);
 
@@ -1814,11 +1817,12 @@ static int freedv_comprx_700d(struct freedv *f, COMP demod_in_8kHz[], int *valid
     
     /* no valid FreeDV signal - squelch output */
 
-    if (strcmp(ofdm->sync_state_interleaver,"synced")) {
-        //nout = freedv_nin(f);
+    int sync = !strcmp(ofdm->sync_state_interleaver,"synced") || !strcmp(ofdm->sync_state_interleaver,"synced");
+    if (!sync) {
         if (f->squelch_en) {
            *valid = 0;
         }
+        f->snr_est = 0.0;
     }
 
     return nout;
@@ -2254,8 +2258,12 @@ void freedv_get_modem_extended_stats(struct freedv *f, struct MODEM_STATS *stats
     }
     
 #ifndef CORTEX_M4
-    if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_700C))
+    if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_700C)) {
         cohpsk_get_demod_stats(f->cohpsk, stats);
+    }
+    if (f->mode == FREEDV_MODE_700D) {
+        ofdm_get_demod_stats(f->ofdm, stats);
+    }
 #endif
 }
 
index 7877aace636ea8947ad60dc7fa4d5c0857cd0153..18b0646ee6f1f99adc279cba8d2611e2d7a44058 100644 (file)
@@ -439,6 +439,8 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
     ofdm->timing_norm = (OFDM_M + OFDM_NCP) * acc;
 
     //fprintf(stderr, "timing_norm: %f\n", ofdm->timing_norm);
+
+    ofdm->sig_var = ofdm->noise_var = 1.0;
     
     return ofdm; /* Success */
 }
@@ -1136,3 +1138,38 @@ void ofdm_set_sync(struct OFDM *ofdm, int sync_cmd) {
     }            
 }
 
+/*---------------------------------------------------------------------------*\
+
+  FUNCTION....: ofdm_get_demod_stats()
+  AUTHOR......: David Rowe
+  DATE CREATED: May 2018
+
+  Fills stats structure with a bunch of demod information.
+
+\*---------------------------------------------------------------------------*/
+
+void ofdm_get_demod_stats(struct OFDM *ofdm, struct MODEM_STATS *stats)
+{
+    int   c,r;
+
+    stats->Nc = OFDM_NC;
+    assert(stats->Nc <= MODEM_STATS_NC_MAX);
+
+    float snr_est = 10*log10((ofdm->sig_var/ofdm->noise_var)*OFDM_NC*OFDM_RS/3000);
+    stats->snr_est = 0.9*stats->snr_est + 0.1*snr_est;
+
+    stats->sync = !strcpy(ofdm->sync_state, "synced") || !strcpy(ofdm->sync_state, "trial");
+    stats->foff = ofdm->foff_est_hz;
+    stats->rx_timing = ofdm->timing_est;
+    stats->clock_offset = 0.0;               /* TODO: work out sample clock offset */
+
+    assert(OFDM_ROWSPERFRAME <= MODEM_STATS_NR_MAX);
+    stats->nr = OFDM_ROWSPERFRAME;
+    for(c=0; c<OFDM_NC; c++) {
+        for (r=0; r<OFDM_ROWSPERFRAME; r++) {
+            complex float rot = ofdm->rx_np[r*c] *  (cosf(M_PI/4.0) + I*sinf(M_PI/4.0));
+            stats->rx_symbols[r][c].real = crealf(rot);
+            stats->rx_symbols[r][c].imag = cimagf(rot);
+        }
+    }
+}