first pass at plot-scalar working to produce timing and frequency offset plots
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 4 Nov 2012 23:11:29 +0000 (23:11 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 4 Nov 2012 23:11:29 +0000 (23:11 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@927 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_plot_scalar.cpp
fdmdv2/src/fdmdv2_plot_scalar.h
fdmdv2/src/fdmdv2_plot_scatter.cpp

index a0b2afdb50ba3b7a66f282e74d12effbdd13e962..00f8208514e73a70cfb8bb9b5b13780d17524365 100644 (file)
@@ -175,13 +175,13 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent)
     if(wxGetApp().m_show_timing)
     {
         // Add Timing Offset window
-        m_panelTimeOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl);
+        m_panelTimeOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -0.5, 0.5, 1, 0.1, "%2.1f");
         m_auiNbookCtrl->AddPage(m_panelTimeOffset, L"Timing \u0394", true, wxNullBitmap);
     }
     if(wxGetApp().m_show_freq)
     {
         // Add Frequency Offset window
-        m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl);
+        m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -200, 200, 1, 50, "%3fHz");
         m_auiNbookCtrl->AddPage(m_panelFreqOffset, L"Frequency \u0394", true, wxNullBitmap);
     }
     wxGetApp().m_strRxInAudio       = pConfig->Read(wxT("/Audio/RxIn"),         wxT("<m_strRxInAudio>"));
@@ -305,8 +305,13 @@ void MainFrame::OnTimer(wxTimerEvent &evt)
     m_panelSpectrum->Refresh();
 
     m_panelScatter->add_new_samples(g_stats.rx_symbols);
-    m_panelScatter->m_newdata = true;
     m_panelScatter->Refresh();
+
+    m_panelTimeOffset->add_new_sample((float)g_stats.rx_timing/FDMDV_NOM_SAMPLES_PER_FRAME);
+    m_panelTimeOffset->Refresh();
+    
+    m_panelFreqOffset->add_new_sample(g_stats.foff);
+    m_panelFreqOffset->Refresh();
 }
 #endif
 
@@ -1109,7 +1114,7 @@ void MainFrame::startRxStream()
 
        m_rxUserdata->infifo2 = fifo_create(4*N48);
 
-        m_rxUserdata->rxinfifo = fifo_create(2 * FDMDV_NOM_SAMPLES_PER_FRAME);
+        m_rxUserdata->rxinfifo = fifo_create(3 * FDMDV_NOM_SAMPLES_PER_FRAME);
         m_rxUserdata->rxoutfifo = fifo_create(2 * codec2_samples_per_frame(g_pCodec2));
 
        // Start sound card 1 ----------------------------------------------------------
index c4d3eb217b0756786284a7dca77d8b4b012fce99..8bc90afbc30f25b45252eb1175371ce9a32e54d7 100644 (file)
@@ -1,6 +1,6 @@
 //==========================================================================
 // Name:            fdmdv2_plot_scalar.cpp
-// Purpose:         Implements a waterfall plot derivative of fdmdv2_plot.
+// Purpose:         Plots scalar amplitude against time
 // Created:         June 22, 2012
 // Initial author:  David Witten
 // Derived from:    code written by David Rowe
@@ -41,25 +41,36 @@ END_EVENT_TABLE()
 //----------------------------------------------------------------
 // PlotScalar()
 //----------------------------------------------------------------
-//PlotScalar::PlotScalar(wxFrame* parent, int x_max_, int y_max_): PlotPanel(parent)
-PlotScalar::PlotScalar(wxFrame* parent): PlotPanel(parent)
+PlotScalar::PlotScalar(wxFrame* parent, 
+                      float  t_secs,             // time covered by entire x axis in seconds
+                      float  sample_period_secs, // tiem between each sample in seconds
+                      float  a_min,              // min ampltude of samples being plotted
+                      float  a_max,              // max ampltude of samples being plotted
+                      float  graticule_t_step,   // time step of x (time) axis graticule in seconds
+                      float  graticule_a_step,   // step of amplitude axis graticule
+                      const char a_fmt[]         // printf format string for amlitude axis labels
+                      ): PlotPanel(parent)
 {
     int i;
 
-    //align(FL_ALIGN_TOP);
-    //labelsize(10);
+    m_t_secs = t_secs;
+    m_sample_period_secs = sample_period_secs;
+    m_a_min = a_min;
+    m_a_max = a_max;
+    m_graticule_t_step = graticule_t_step;
+    m_graticule_a_step = graticule_a_step;
+    assert(strlen(a_fmt) < 15);
+    strcpy(m_a_fmt, a_fmt);
 
-    m_mem = new float[m_x_max];
+    // work out number of samples we will store and allocate storage
 
-    for(i = 0; i < m_x_max; i++)
+    m_samples = m_t_secs/m_sample_period_secs;
+    m_mem = new float[m_samples];
+
+    for(i = 0; i < m_samples; i++)
     {
         m_mem[i] = 0.0;
     }
-    m_prev_w = 0;
-    m_prev_h = 0;
-    m_prev_x = 0;
-    m_prev_y = 0;
-    m_index = 0;
 }
 
 //----------------------------------------------------------------
@@ -75,23 +86,13 @@ PlotScalar::~PlotScalar()
 //----------------------------------------------------------------
 void PlotScalar::add_new_sample(float sample)
 {
-    m_new_sample = sample;
-}
+    int i;
 
-//----------------------------------------------------------------
-// clip()
-//----------------------------------------------------------------
-int PlotScalar::clip(int y1)
-{
-    if(y1 > (m_rCtrl.GetHeight()/2 - 10))
-    {
-        y1 = m_rCtrl.GetHeight()/2 - 10;
-    }
-    if(y1 < -(m_rCtrl.GetHeight()/2 - 10))
+    for(i = 0; i < m_samples-1; i++)
     {
-        y1 = -(m_rCtrl.GetHeight()/2 - 10);
+        m_mem[i] = m_mem[i+1];
     }
-    return y1;
+    m_mem[m_samples-1] = sample;
 }
 
 //----------------------------------------------------------------
@@ -99,90 +100,113 @@ int PlotScalar::clip(int y1)
 //----------------------------------------------------------------
 void PlotScalar::draw(wxAutoBufferedPaintDC&  dc)
 {
-    float x_scale;
-    float y_scale;
+    float index_to_px;
+    float a_to_py;
     int   i;
-    int   x1;
-    int   y1;
-    int   x2;
-    int   y2;
-    char  label[100];
-    wxPen pen;
+    int   x, y;
+    int   prev_x, prev_y;
+    float a;
 
-    /* detect resizing of window */
-    if((m_rCtrl.GetHeight() != m_prev_h) || (m_rCtrl.GetWidth() != m_prev_w) || (m_x != m_prev_x) || (m_y != m_prev_y))
-    {
-        dc.SetPen(BLACK_COLOR);
-        dc.DrawRectangle(m_x, m_y, m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
-        m_prev_h = m_rCtrl.GetHeight();
-        m_prev_w = m_rCtrl.GetWidth();
-        m_prev_x = m_x;
-        m_prev_y = m_y;
-    }
+    m_rCtrl = GetClientRect();
+    m_rGrid = m_rCtrl;
+    m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
 
-    //fl_push_clip(m_x, m_y, m_w, m_h);
-    x_scale = (float)m_x_max;
-    y_scale = (float)m_rCtrl.GetHeight() /(2.0 * m_y_max);
-
-    // erase last sample
-    dc.SetPen(BLACK_COLOR);
-    x1 = x_scale * m_index + m_x;
-    y1 = y_scale * m_mem[m_index];
-    y1 = clip(y1);
-    y1 = m_y + m_rCtrl.GetHeight()/2 - y1;
-    dc.DrawPoint(x1, y1);
-
-    // draw new sample
-    dc.SetPen(GREEN_COLOR);
-    x1 = x_scale * m_index + m_x;
-    y1 = y_scale * m_new_sample;
-    y1 = clip(y1);
-    y1 = m_y + m_rCtrl.GetHeight()/2 - y1;
-    dc.DrawPoint(x1, y1);
-    m_mem[m_index] = m_new_sample;
-    m_index++;
-    if(m_index >=  m_x_max)
-    {
-        m_index = 0;
-    }
+    // black background
 
-    // y axis graticule
-    m_step = 10;
-    while((2.0 * m_y_max/m_step) > 10)
-    {
-        m_step *= 2.0;
-    }
-    while((2.0 * m_y_max/m_step) < 4)
-    {
-        m_step /= 2.0;
-    }
-    pen = dc.GetPen();
+    dc.Clear();
+    m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
+    wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
+    dc.SetBrush(ltGraphBkgBrush);
+    dc.SetPen(wxPen(BLACK_COLOR, 0));
+    dc.DrawRectangle(m_rPlot);
+
+    index_to_px = (float)m_rGrid.GetWidth()/m_samples;
+    a_to_py = (float)m_rGrid.GetHeight()/(m_a_max - m_a_min);
+
+    wxPen pen;
     pen.SetColour(DARK_GREEN_COLOR);
-    pen.SetStyle(wxPENSTYLE_DOT);
+    pen.SetWidth(1);
     dc.SetPen(pen);
-    for(i =- m_y_max; i < m_y_max; i += m_step)
+
+    // draw all samples
+
+    prev_x = prev_y = 0; // stop warning
+
+    for(i = 0; i < m_samples; i++)
     {
-        x1 = m_x;
-        y1 = m_y + m_rCtrl.GetHeight()/2 - i * y_scale;
-        x2 = m_x + m_rCtrl.GetWidth();
-        y2 = y1;
-        dc.DrawLine(x1, y1, x2, y2);
+        x = index_to_px * i;
+       a = m_mem[i];
+       if (a < m_a_min) a = m_a_min;
+       if (a > m_a_max) a = m_a_max;
+
+       // invert y axis and offset by minimum
+
+        y = m_rGrid.GetHeight() - a_to_py * a + m_a_min*a_to_py;
+
+       // put inside plot window
+
+       x += PLOT_BORDER + XLEFT_OFFSET;
+       y += PLOT_BORDER;
+
+       if (i)
+           dc.DrawLine(x, y, prev_x, prev_y);
+       prev_x = x; prev_y = y;
     }
 
-    // y axis graticule labels
-    pen = dc.GetPen();
-    pen.SetColour(GREEN_COLOR);
-    pen.SetStyle(wxPENSTYLE_DOT);
-    dc.SetPen(pen);
-    for(i =- m_y_max; i < m_y_max; i += m_step)
-    {
-        x1 = m_x;
-        y1 = m_y + m_rCtrl.GetHeight()/2 - i * y_scale;
-        sprintf(label, "%d", i);
-        wxSize sz = dc.GetTextExtent(label);
-        dc.DrawLabel(label,  wxRect(x1, y1, sz.GetWidth(), sz.GetHeight()), wxALIGN_LEFT);
+    drawGraticule(dc);
+}
+
+//-------------------------------------------------------------------------
+// drawGraticule()
+//-------------------------------------------------------------------------
+void PlotScalar::drawGraticule(wxAutoBufferedPaintDC&  dc)
+{
+    float    t, a;
+    int      x, y, text_w, text_h;
+    char     buf[15];
+    wxString s;
+    float    sec_to_px;
+    float    a_to_py;
+
+    wxBrush ltGraphBkgBrush;
+    ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
+    ltGraphBkgBrush.SetColour(*wxBLACK);
+    dc.SetBrush(ltGraphBkgBrush);
+    dc.SetPen(wxPen(BLACK_COLOR, 1));
+
+    sec_to_px = (float)m_rGrid.GetWidth()/m_t_secs;
+    a_to_py = (float)m_rGrid.GetHeight()/(m_a_max - m_a_min);
+
+    // upper LH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER)
+    // lower RH coords of plot area are (PLOT_BORDER + XLEFT_OFFSET + m_rGrid.GetWidth(), 
+    //                                   PLOT_BORDER + m_rGrid.GetHeight())
+
+    // Vertical gridlines
+
+    dc.SetPen(m_penShortDash);
+    for(t=0; t<=m_t_secs; t+=m_graticule_t_step) {
+       x = t*sec_to_px;
+       x += PLOT_BORDER + XLEFT_OFFSET;
+        dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
+        sprintf(buf, "%2.1fs", t);
+       GetTextExtent(buf, &text_w, &text_h);
+        dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
     }
-    //fl_pop_clip();
+
+    // 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;
+       y += PLOT_BORDER;
+       dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y, 
+                   (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
+        sprintf(buf, m_a_fmt, a);
+       GetTextExtent(buf, &text_w, &text_h);
+        dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
+   }
+
+
 }
 
 //----------------------------------------------------------------
index a49862c8e622d4e6244c9fceda5bd4067e6e1fc7..1f69b32d8653aa4e97ec72478d97be5f39f13be7 100644 (file)
@@ -35,22 +35,32 @@ class PlotScalar: public PlotPanel
 {
     public:
 
-        //PlotScalar(wxFrame* parent, int x, int y, int w, int h, int x_max_, int y_max_, const char name[]);
-        PlotScalar(wxFrame* parent);
+    PlotScalar(wxFrame* parent,
+              float t_secs, 
+              float sample_period_secs,
+              float a_min,
+              float a_max,
+              float graticule_t_step,   
+              float graticule_a_step,
+              const char  a_fmt[]
+              );
         ~PlotScalar();
          void add_new_sample(float sample);
 
     protected:
 
-        int    m_x_max;
-        int    m_y_max;
-        float  *m_mem;              /* array of x_max samples */
-        float  m_new_sample;
-        int    m_index;
-        int    m_step;
+        float    m_t_secs;
+        float    m_sample_period_secs;
+        float    m_a_min;
+        float    m_a_max;
+        float    m_graticule_t_step;   
+        float    m_graticule_a_step;
+        char     m_a_fmt[15];
+        int      m_samples;
+        float   *m_mem;              
 
-        int clip(int y1);
         void draw(wxAutoBufferedPaintDC&  dc);
+       void drawGraticule(wxAutoBufferedPaintDC&  dc);
         void OnPaint(wxPaintEvent& event);
         void OnSize(wxSizeEvent& event);
         void OnShow(wxShowEvent& event);
index 4afdde51b5b5ebd121e5f97c1c5baede493426a3..86662dc3fbc7bb2b3f7324fb9d218cf88717e67e 100644 (file)
@@ -43,7 +43,7 @@ END_EVENT_TABLE()
 PlotScatter::PlotScatter(wxFrame* parent) : PlotPanel(parent)
 {
     int i;
-
+    printf("PlotScatter\n");
     for(i=0; i < SCATTER_MEM_SYMS; i++)
     {
         m_mem[i].real = 0.0;
@@ -118,8 +118,6 @@ void PlotScatter::add_new_samples(COMP samples[])
     for(i = 0; i < FDMDV_NSYM; i++)
     {
         m_new_samples[i] = samples[i];
-        //m_new_samples[i].real = 1 - 2*(i%2) + 0.1*(float)rand()/RAND_MAX;
-        //m_new_samples[i].imag = 1 - 2*(i%2) + 0.1*(float)rand()/RAND_MAX;
     }
 }