first pass at eye diagram for 800XA
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 15 Jan 2017 22:35:51 +0000 (22:35 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 15 Jan 2017 22:35:51 +0000 (22:35 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2978 01035d8c-6547-0410-b346-abe4f91aad63

freedv-dev/src/fdmdv2_defines.h
freedv-dev/src/fdmdv2_main.cpp
freedv-dev/src/fdmdv2_plot_scatter.cpp
freedv-dev/src/fdmdv2_plot_scatter.h

index c1f8c3277d8c534421367312d1b0cc86ce7a8a7d..a6878890d2bbee10f31d2b3e296beba1e7822382 100644 (file)
@@ -46,6 +46,7 @@
 // (symbols/frame)/(graphics update period) = symbols/s sent to scatter memory
 // memory (symbols) = secs of memory * symbols/sec
 #define SCATTER_MEM_SYMS_MAX    ((int)(SCATTER_MEM_SECS*((MODEM_STATS_NC_MAX+1)/DT)))
+#define SCATTER_EYE_MEM_ROWS    ((int)(SCATTER_MEM_SECS/DT))
 
 // Waveform plotting constants
 
index 134502e0745c89fe15088bc945b38b3e06332fde..ef69c23b2d4cd66a9d7e35f767397d93f5774c2e 100644 (file)
@@ -967,31 +967,44 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     m_panelSpectrum->m_newdata = true;
     m_panelSpectrum->Refresh();
 
-    /* update scatter plot -----------------------------------------------------------------*/
+    /* update scatter/eye plot ------------------------------------------------------------*/
 
-    for (r=0; r<g_stats.nr; r++) {
+    if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_800XA) {
+        /* FSK Mode - eye diagram ---------------------------------------------------------*/
         
-        if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_1600) {
-            m_panelScatter->add_new_samples(&g_stats.rx_symbols[r][0]);
+        /* add samples row by row */
+
+        int i;
+       for (i=0; i<g_stats.neyetr; i++) {
+            m_panelScatter->add_new_samples_eye(&g_stats.rx_eye[i][0], g_stats.neyesamp);
         }
+    }
+    else {
+        /* PSK Modes - scatter plot -------------------------------------------------------*/
+        for (r=0; r<g_stats.nr; r++) {
         
-        if ((freedv_get_mode(g_pfreedv) == FREEDV_MODE_700B) || (freedv_get_mode(g_pfreedv) == FREEDV_MODE_700C)) {
+            if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_1600) {
+                m_panelScatter->add_new_samples_scatter(&g_stats.rx_symbols[r][0]);
+            }
+        
+            if ((freedv_get_mode(g_pfreedv) == FREEDV_MODE_700B) || (freedv_get_mode(g_pfreedv) == FREEDV_MODE_700C)) {
             
-            /* 
-               FreeDV 700 uses diversity, so combine symbols for
-               scatter plot, as combined symbols are used for
-               demodulation.  Note we need to use a copy of the
-               symbols, as we are not sure when the stats will be
-               updated.
-            */
-
-            COMP rx_symbols_copy[g_Nc/2];
-
-            for(c=0; c<g_Nc/2; c++)
-                rx_symbols_copy[c] = cadd(g_stats.rx_symbols[r][c], g_stats.rx_symbols[r][c+g_Nc/2]);
-            m_panelScatter->add_new_samples(rx_symbols_copy);
-        }
+                /* 
+                   FreeDV 700 uses diversity, so combine symbols for
+                   scatter plot, as combined symbols are used for
+                   demodulation.  Note we need to use a copy of the
+                   symbols, as we are not sure when the stats will be
+                   updated.
+                */
+
+                COMP rx_symbols_copy[g_Nc/2];
+
+                for(c=0; c<g_Nc/2; c++)
+                    rx_symbols_copy[c] = cadd(g_stats.rx_symbols[r][c], g_stats.rx_symbols[r][c+g_Nc/2]);
+                m_panelScatter->add_new_samples_scatter(rx_symbols_copy);
+            }
        
+        }
     }
 
     m_panelScatter->Refresh();
@@ -2431,6 +2444,13 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event)
         g_snr = 0.0;
         g_half_duplex = wxGetApp().m_boolHalfDuplex;
 
+        if (g_mode == FREEDV_MODE_800XA) {
+            m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_EYE);
+        }
+        else {
+            m_panelScatter->setEyeScatter(PLOT_SCATTER_MODE_SCATTER);
+        }
+
         m_pcallsign = m_callsign;
         memset(m_callsign, 0, sizeof(m_callsign));
         m_checksumGood = m_checksumBad = 0;
@@ -3617,7 +3637,7 @@ void per_frame_rx_processing(
             }
             freq_shift_coh(rx_fdm_offset, rx_fdm, g_RxFreqOffsetHz, freedv_get_modem_sample_rate(g_pfreedv), &g_RxFreqOffsetPhaseRect, nin);
             nout = freedv_comprx(g_pfreedv, output_buf, rx_fdm_offset);
-            printf("nout %d outbuf_buf[0]: %d\n", nout, output_buf[0]);
+            //kprintf("nout %d outbuf_buf[0]: %d\n", nout, output_buf[0]);
             fifo_write(output_fifo, output_buf, nout);
         
             nin = freedv_nin(g_pfreedv);
index 85b2a5730f209571ce881f07742a48f176e96155..12957f44cfcbbeffa644289b00d88879c12a1d67 100644 (file)
@@ -44,14 +44,18 @@ PlotScatter::PlotScatter(wxFrame* parent) : PlotPanel(parent)
         m_mem[i].imag = 0.0;
     }
 
-    m_filter_max_xy = 0.1;
+    m_filter_max_xy = m_filter_max_y = 0.1;
 
     // defaults so we start off with something sensible
 
     Nsym = 14+1;
     scatterMemSyms = ((int)(SCATTER_MEM_SECS*(Nsym/DT)));
     assert(scatterMemSyms <= SCATTER_MEM_SYMS_MAX);
-        
+
+    Ncol = 0;
+    memset(eye_mem, 0, sizeof(eye_mem));
+
+    mode = PLOT_SCATTER_MODE_SCATTER;
 }
 
 // changing number of carriers changes number of symbols to plot
@@ -69,7 +73,7 @@ void PlotScatter::draw(wxAutoBufferedPaintDC& dc)
 {
     float x_scale;
     float y_scale;
-    int   i;
+    int   i,j;
     int   x;
     int   y;
     wxColour sym_to_colour[] = {wxColor(0,0,255), 
@@ -109,52 +113,114 @@ void PlotScatter::draw(wxAutoBufferedPaintDC& dc)
     wxPen pen;
     pen.SetWidth(1); // note this is ignored by DrawPoint
 
-    // automatically scale, first measure the maximum value
-
-    float max_xy = 1E-12;
-    float real,imag;
-    for(i=0; i< scatterMemSyms; i++) {
-        real = fabs(m_mem[i].real);
-        imag = fabs(m_mem[i].imag);
-        if (real > max_xy)
-            max_xy = real;
-        if (imag > max_xy)
-            max_xy = imag;
-    }
+    if (mode == PLOT_SCATTER_MODE_SCATTER) {
 
-    // smooth it out and set a lower limit to prevent didev by 0 issues
+        // automatically scale, first measure the maximum value
 
-    m_filter_max_xy = BETA*m_filter_max_xy + (1 - BETA)*2.5*max_xy;
-    if (m_filter_max_xy < 0.001)
-        m_filter_max_xy = 0.001;
+        float max_xy = 1E-12;
+        float real,imag;
+        for(i=0; i< scatterMemSyms; i++) {
+            real = fabs(m_mem[i].real);
+            imag = fabs(m_mem[i].imag);
+            if (real > max_xy)
+                max_xy = real;
+            if (imag > max_xy)
+                max_xy = imag;
+        }
 
-    // quantise to log steps to prevent scatter scaling bobbing about too
-    // much as scaling varies
+        // smooth it out and set a lower limit to prevent divide by 0 issues
 
-    float quant_m_filter_max_xy = exp(floor(0.5+log(m_filter_max_xy)));
-    //printf("max_xy: %f m_filter_max_xy: %f quant_m_filter_max_xy: %f\n", max_xy, m_filter_max_xy, quant_m_filter_max_xy);
+        m_filter_max_xy = BETA*m_filter_max_xy + (1 - BETA)*2.5*max_xy;
+        if (m_filter_max_xy < 0.001)
+            m_filter_max_xy = 0.001;
 
-    x_scale = (float)m_rGrid.GetWidth()/quant_m_filter_max_xy;
-    y_scale = (float)m_rGrid.GetHeight()/quant_m_filter_max_xy;
+        // quantise to log steps to prevent scatter scaling bobbing about too
+        // much as scaling varies
 
-    // draw all samples
+        float quant_m_filter_max_xy = exp(floor(0.5+log(m_filter_max_xy)));
+        //printf("max_xy: %f m_filter_max_xy: %f quant_m_filter_max_xy: %f\n", max_xy, m_filter_max_xy, quant_m_filter_max_xy);
 
-    for(i = 0; i < scatterMemSyms; i++)
-    {
-        x = x_scale * m_mem[i].real + m_rGrid.GetWidth()/2;
-        y = y_scale * m_mem[i].imag + m_rGrid.GetHeight()/2;
-       x += PLOT_BORDER + XLEFT_OFFSET;
-       y += PLOT_BORDER;
-        pen.SetColour(sym_to_colour[i%Nsym]);
+        x_scale = (float)m_rGrid.GetWidth()/quant_m_filter_max_xy;
+        y_scale = (float)m_rGrid.GetHeight()/quant_m_filter_max_xy;
+
+        // draw all samples
+
+        for(i = 0; i < scatterMemSyms; i++) {
+            x = x_scale * m_mem[i].real + m_rGrid.GetWidth()/2;
+            y = y_scale * m_mem[i].imag + m_rGrid.GetHeight()/2;
+            x += PLOT_BORDER + XLEFT_OFFSET;
+            y += PLOT_BORDER;
+            pen.SetColour(sym_to_colour[i%Nsym]);
+            dc.SetPen(pen);
+            dc.DrawPoint(x, y);
+        }
+    }
+
+    if (mode == PLOT_SCATTER_MODE_EYE) {
+
+        pen.SetColour(DARK_GREEN_COLOR);
+        pen.SetWidth(1);
         dc.SetPen(pen);
-       dc.DrawPoint(x, y);
+
+        // automatically scale, first measure the maximum Y value
+
+        float max_y = 1E-12;
+        float min_y = 1E+12;
+        for(i=0; i<SCATTER_EYE_MEM_ROWS; i++) {
+            for(j=0; j<Ncol; j++) {
+                if (eye_mem[i][j] > max_y) {
+                    max_y = eye_mem[i][j];
+                }
+                if (eye_mem[i][j] < min_y) {
+                    min_y = eye_mem[i][j];
+                }
+            }
+        }
+        // smooth it out and set a lower limit to prevent divide by 0 issues
+
+        m_filter_max_y = BETA*m_filter_max_y + (1 - BETA)*2.5*max_y;
+        if (m_filter_max_y < 0.001)
+            m_filter_max_y = 0.001;
+
+        // quantise to log steps to prevent scatter scaling bobbing about too
+        // much as scaling varies
+
+        float quant_m_filter_max_y = exp(floor(0.5+log(m_filter_max_y)));
+        //printf("min_y: %4.3f max_y: %4.3f quant_m_filter_max_y: %4.3f\n", min_y, max_y, quant_m_filter_max_y);
+
+        x_scale = (float)m_rGrid.GetWidth()/Ncol;
+        y_scale = (float)m_rGrid.GetHeight()/quant_m_filter_max_y;
+        //printf("GetWidth(): %d GetHeight(): %d\n", m_rGrid.GetWidth(), m_rGrid.GetHeight());
+
+        // plot eye traces row by row
+
+        int prev_x, prev_y;
+        prev_x = prev_y = 0;
+        for(i=0; i<SCATTER_EYE_MEM_ROWS; i++) {
+            //printf("row: ");
+            for(j=0; j<Ncol; j++) {
+                x = x_scale * j;
+                y = m_rGrid.GetHeight()*0.75 - y_scale * eye_mem[i][j];
+               //printf("%4d,%4d  ", x, y);
+                x += PLOT_BORDER + XLEFT_OFFSET;
+                y += PLOT_BORDER;
+                pen.SetColour(sym_to_colour[i%4]);
+                dc.SetPen(pen);
+                if (j)
+                    dc.DrawLine(x, y, prev_x, prev_y);
+                prev_x = x; prev_y = y;
+            }
+            //printf("\n");
+        }
+        
     }
 }
 
 //----------------------------------------------------------------
 // add_new_samples()
 //----------------------------------------------------------------
-void PlotScatter::add_new_samples(COMP samples[])
+void PlotScatter::add_new_samples_scatter(COMP samples[])
 {
     int i,j;
 
@@ -173,6 +239,31 @@ void PlotScatter::add_new_samples(COMP samples[])
     }
 }
 
+/* add a row of eye samples, updating buffer */
+
+void PlotScatter::add_new_samples_eye(float samples[], int n)
+{
+    int i,j;
+
+    Ncol = n; /* this should be constant for a given modem config */
+
+    assert(n <= PLOT_SCATTER_EYE_MAX_SAMPLES_ROW);
+
+    // eye traces are arrnaged in rows, shift memory of traces
+
+    for(i=0; i<SCATTER_EYE_MEM_ROWS-1; i++) {
+        for(j=0; j<Ncol; j++) {
+            eye_mem[i][j] = eye_mem[i+1][j];
+        }
+    }
+
+    // new samples in last row
+
+    for(j=0; j<Ncol; j++) {
+        eye_mem[SCATTER_EYE_MEM_ROWS-1][j] = samples[j];
+    }
+}
+
 //----------------------------------------------------------------
 // OnPaint()
 //----------------------------------------------------------------
@@ -196,4 +287,3 @@ void PlotScatter::OnSize(wxSizeEvent& event)
 void PlotScatter::OnShow(wxShowEvent& event)
 {
 }
-
index c512cb55a2e15cf1d84e52390dfa9473fbe21983..b5e3352909de5f6564b4cd0e2d00232d4dcb1475 100644 (file)
 #include "fdmdv2_plot.h"
 #include "fdmdv2_defines.h"
 
+#define PLOT_SCATTER_MODE_SCATTER            0
+#define PLOT_SCATTER_MODE_EYE                1
+#define PLOT_SCATTER_EYE_MAX_SAMPLES_ROW    80
+
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
 // Class PlotScatter
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
@@ -33,12 +37,16 @@ class PlotScatter : public PlotPanel
     public:
         PlotScatter(wxFrame* parent);
         ~PlotScatter(){};
-       void add_new_samples(COMP samples[]);
+       void add_new_samples_scatter(COMP samples[]);
+       void add_new_samples_eye(float samples[], int n);
        void setNc(int Nc);
+        void setEyeScatter(int eye_mode) {mode = eye_mode;}
 
     protected:
+        int  mode;
         COMP m_mem[SCATTER_MEM_SYMS_MAX];
         COMP m_new_samples[MODEM_STATS_NC_MAX+1];
+        float eye_mem[SCATTER_EYE_MEM_ROWS][PLOT_SCATTER_EYE_MAX_SAMPLES_ROW];
 
         void draw(wxAutoBufferedPaintDC&  dc);
         void OnPaint(wxPaintEvent& event);
@@ -49,8 +57,9 @@ class PlotScatter : public PlotPanel
 
     private:
         int   Nsym;
+        int   Ncol;
         int   scatterMemSyms;
-        float m_filter_max_xy;
+        float m_filter_max_xy, m_filter_max_y;
 };
 
 #endif //__FDMDV2_PLOT_SCATTER__