added log graticule and scale, histograms testing out well
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 21 Feb 2017 21:32:41 +0000 (21:32 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 21 Feb 2017 21:32:41 +0000 (21:32 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3043 01035d8c-6547-0410-b346-abe4f91aad63

freedv-dev/src/fdmdv2_main.cpp
freedv-dev/src/fdmdv2_plot_scalar.cpp
freedv-dev/src/fdmdv2_plot_scalar.h

index 72a3787b104edc117e358bc75cd80a3ad1977cdf..27bb3d09268c3f892c593b0d972c1136d62c5869 100644 (file)
@@ -53,7 +53,7 @@ int                 g_total_bit_errors;
 int                 g_channel_noise;
 float               g_sig_pwr_av = 0.0;
 struct FIFO        *g_error_pattern_fifo;
-short              *g_error_hist;
+short              *g_error_hist, *g_error_histn;
  
 // time averaged magnitude spectrum used for waterfall and spectrum display
 float               g_avmag[MODEM_STATS_NSPEC];
@@ -391,10 +391,11 @@ MainFrame::MainFrame(wxString plugInName, wxWindow *parent) : TopFrame(plugInNam
 
     if(wxGetApp().m_show_test_frame_errors_hist)
     {
-        // Add Test Frame Errors window
-        m_panelTestFrameErrorsHist = new PlotScalar((wxFrame*) m_auiNbookCtrl, 1, 1.0, 1.0/(2*FDMDV_NC_MAX), 0.0, 1.0, 1.0/FDMDV_NC_MAX, 0.1, "%3.2f", 0);
+        // Add Test Frame Historgram window.  1 column for every bit, 2 bits per carrier
+        m_panelTestFrameErrorsHist = new PlotScalar((wxFrame*) m_auiNbookCtrl, 1, 1.0, 1.0/(2*FDMDV_NC_MAX), 0.001, 0.1, 1.0/FDMDV_NC_MAX, 0.1, "%0.0E", 0);
         m_auiNbookCtrl->AddPage(m_panelTestFrameErrorsHist, L"Test Frame Histogram", true, wxNullBitmap);
         m_panelTestFrameErrorsHist->setBarGraph(1);
+        m_panelTestFrameErrorsHist->setLogY(1);
     }
 
     wxGetApp().m_framesPerBuffer = pConfig->Read(wxT("/Audio/framesPerBuffer"), PA_FPB);
@@ -1294,7 +1295,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
                 if (fifo_read(g_error_pattern_fifo, error_pattern, sz_error_pattern) == 0) {
                     int i,b;
 
-                    /* both modes map IQ to alternate bits, but one same carrier */
+                    /* both modes map IQ to alternate bits, but on same carrier */
 
                     if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_1600) {
                         /* FreeDV 1600 mapping from error pattern to two bits on each carrier */
@@ -1330,18 +1331,20 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
                             c = i/4;
                             m_panelTestFrameErrors->add_new_sample(c, c + 0.8*error_pattern[i]);
                             g_error_hist[c] += error_pattern[i];
+                            g_error_histn[c]++;
                             //printf("i: %d c: %d\n", i, c);
                         }
 
-                        int max_hist = 0;
+                        /* calculate BERs and send to plot */
+
+                        float ber[2*FDMDV_NC_MAX];
+                        for(b=0; b<2*FDMDV_NC_MAX; b++) {
+                            ber[b] = 0.0;
+                        }
                         for(b=0; b<g_Nc; b++) {
-                            if (g_error_hist[b] > max_hist) {
-                                max_hist = g_error_hist[b];
-                            }
-                            //printf("%4d ", g_error_hist[b]);
+                            ber[b+1] = (float)g_error_hist[b]/g_error_histn[b];
                         }
-                        printf("\n");
-                        m_panelTestFrameErrorsHist->add_new_short_samples(0, g_error_hist, 2*FDMDV_NC_MAX, max_hist);                
+                        m_panelTestFrameErrorsHist->add_new_samples(0, ber, 2*FDMDV_NC_MAX);
                     }
  
                     m_panelTestFrameErrors->Refresh();       
@@ -1841,8 +1844,10 @@ void MainFrame::OnBerReset(wxCommandEvent& event)
     freedv_set_total_bits(g_pfreedv, 0);
     freedv_set_total_bit_errors(g_pfreedv, 0);
     int i;
-    for(i=0; i<2*g_Nc; i++)
+    for(i=0; i<2*g_Nc; i++) {
         g_error_hist[i] = 0;
+        g_error_histn[i] = 0;
+    }
     
 }
 
@@ -2449,9 +2454,12 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
             freedv_set_callback_error_pattern(g_pfreedv, my_freedv_put_error_pattern, (void*)m_panelTestFrameErrors);
             g_error_pattern_fifo = fifo_create(2*freedv_get_sz_error_pattern(g_pfreedv));
             g_error_hist = new short[FDMDV_NC_MAX*2];
+            g_error_histn = new short[FDMDV_NC_MAX*2];
             int i;
-            for(i=0; i<2*FDMDV_NC_MAX; i++)
+            for(i=0; i<2*FDMDV_NC_MAX; i++) {
                 g_error_hist[i] = 0;
+                g_error_histn[i] = 0;
+            }
 
             assert(g_pfreedv != NULL);
 
@@ -2569,6 +2577,7 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
         else {
             // FreeDV clean up
             delete g_error_hist;
+            delete g_error_histn;
             fifo_destroy(g_error_pattern_fifo);
             freedv_close(g_pfreedv);
             speex_preprocess_state_destroy(g_speex_st);
index 2336f605f277b53ea050aeaad492388e0d2f965c..9a794f53d65deb8278516f30c3cf12eaab2f8dc2 100644 (file)
@@ -61,7 +61,8 @@ PlotScalar::PlotScalar(wxFrame* parent,
     assert(strlen(a_fmt) < 15);
     strcpy(m_a_fmt, a_fmt);
     m_mini = mini;
-    bar_graph = 0;
+    m_bar_graph = 0;
+    m_logy = 0;
 
     // work out number of samples we will store and allocate storage
 
@@ -102,6 +103,22 @@ void PlotScalar::add_new_sample(int channel, float sample)
 //----------------------------------------------------------------
 // add_new_samples()
 //----------------------------------------------------------------
+void  PlotScalar::add_new_samples(int channel, float samples[], int length)
+{
+    int i;
+    int offset = channel*m_samples;
+
+    assert(channel < m_channels);
+
+   for(i = 0; i < m_samples-length; i++)
+        m_mem[offset+i] = m_mem[offset+i+length];
+    for(; i < m_samples; i++)
+       m_mem[offset+i] = *samples++;
+}
+
+//----------------------------------------------------------------
+// add_new_short_samples()
+//----------------------------------------------------------------
 void  PlotScalar::add_new_short_samples(int channel, short samples[], int length, float scale_factor)
 {
     int i;
@@ -184,7 +201,21 @@ void PlotScalar::draw(wxAutoBufferedPaintDC&  dc)
                 y += PLOT_BORDER;
             }
 
-            if (bar_graph) {
+            if (m_bar_graph) {
+
+                if (m_logy) {
+
+                    // can't take log(0)
+
+                    assert(m_a_min > 0.0); 
+                    assert(m_a_max > 0.0);
+
+                    float norm = (log10(a) - log10(m_a_min))/(log10(m_a_max) - log10(m_a_min));
+                    y = m_rGrid.GetHeight()*(1.0 - norm);
+                } else {
+                    y = m_rGrid.GetHeight() - a_to_py * a + m_a_min*a_to_py;
+                }
+
                 // use points to make a bar graph
 
                 int x1, x2, y1;
@@ -254,8 +285,14 @@ void PlotScalar::drawGraticule(wxAutoBufferedPaintDC&  dc)
     // Horizontal gridlines
 
     dc.SetPen(m_penDotDash);
-    for(a=m_a_min; a<m_a_max; a+=m_graticule_a_step) {
-       y = m_rGrid.GetHeight() - a*a_to_py + m_a_min*a_to_py;
+    for(a=m_a_min; a<m_a_max; ) {
+        if (m_logy) {
+            float norm = (log10(a) - log10(m_a_min))/(log10(m_a_max) - log10(m_a_min));
+            y = m_rGrid.GetHeight()*(1.0 - norm);
+        }
+       else {
+            y = m_rGrid.GetHeight() - a*a_to_py + m_a_min*a_to_py;
+        }
        if (m_mini) {
             dc.DrawLine(0, y, m_rGrid.GetWidth(), y);
         }
@@ -269,6 +306,15 @@ void PlotScalar::drawGraticule(wxAutoBufferedPaintDC&  dc)
             GetTextExtent(buf, &text_w, &text_h);
             dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
         }
+
+        if (m_logy) {
+            // m_graticule_a_step ==  0.1 means 10 steps/decade
+            float log10_step_size = floor(log10(a));
+            a += pow(10,log10_step_size);
+        }
+        else {
+            a += m_graticule_a_step;
+        }
    }
 
 
index 11c9f8e2aedf4b0f8c50bbd0c7c1e12220092f96..4b668ff6f74979a698f6d381a6ac168a030e28ee 100644 (file)
@@ -44,8 +44,10 @@ class PlotScalar: public PlotPanel
               );
         ~PlotScalar();
          void add_new_sample(int channel, float sample);
+         void add_new_samples(int channel, float samples[], int length);
          void add_new_short_samples(int channel, short samples[], int length, float scale_factor);
-         void setBarGraph(int abar_graph) { bar_graph = abar_graph; }
+         void setBarGraph(int bar_graph) { m_bar_graph = bar_graph; }
+         void setLogY(int logy) { m_logy = logy; }
 
     protected:
 
@@ -60,7 +62,8 @@ class PlotScalar: public PlotPanel
          int      m_mini;
         int      m_samples;
         float   *m_mem;              
-         int      bar_graph;                 // non zero to plot bar graphs 
+         int      m_bar_graph;                 // non zero to plot bar graphs 
+         int      m_logy;                      // plot graph on log scale
 
          void draw(wxAutoBufferedPaintDC&  dc);
          void drawGraticule(wxAutoBufferedPaintDC&  dc);