waterfall working at slow update rate on Linux, some visual bugs on stop & restart
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 20 Oct 2012 23:59:33 +0000 (23:59 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 20 Oct 2012 23:59:33 +0000 (23:59 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@786 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/Makefile.linux
fdmdv2/src/fdmdv2_plot.cpp
fdmdv2/src/fdmdv2_plot_waterfall_linux.cpp
fdmdv2/src/fdmdv2_plot_waterfall_linux.h

index 75f92a5598d40071495805bde9a363b8b37f3294..8af2e7b75affaa0635a8934f2c1bbe83e5ba165d 100644 (file)
@@ -32,9 +32,11 @@ dlg_options.o
 
 all: fdmdv2
 
-fdmdv2: $(OBJS)
+fdmdv2: $(OBJS) fdmdv2_main.h
        g++ -o fdmdv2 $(OBJS) $(CPP_FLAGS) $(LIBS)
 
+fdmdv2_main.h: fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h
+
 %.o: %.cpp
        g++ $(CPP_FLAGS) -c $< -o $@
 
index 701017854dd28250dece3f17bc97a16a099a72d4..c95ba7648c4e763aadf1cf8dfec504611795e352 100644 (file)
@@ -106,7 +106,6 @@ void PlotPanel::OnErase(wxEraseEvent& event)
 //-------------------------------------------------------------------------
 void PlotPanel::OnSize(wxSizeEvent& event)
 {
-    printf("PlotPanel::OnSize\n");
     m_rCtrlPrev = m_rCtrl;
     m_rCtrl     = GetClientRect();
     if(m_use_bitmap)
@@ -184,6 +183,7 @@ double PlotPanel::GetZoomFactor(double zf)
 //-------------------------------------------------------------------------
 void PlotPanel::draw(wxAutoBufferedPaintDC& pDC)
 {
+    printf("PlotPanel::draw()");
     wxMemoryDC m_mDC;
     m_mDC.SelectObject(*m_pBmp);
     m_rCtrl  = GetClientRect();
index efd79dafc17e2a4f5c1d7099c6cf821671040d6e..60a5967879da5eb930c309fb05c71be414cfbbed 100644 (file)
 #include <string.h>
 #include "wx/wx.h"
 #include "fdmdv2_main.h"
-#include "fdmdv2_plot_waterfall_linux.h"
 
-/*
-
-  Notes:
-
-  The height h() pixels represents WATERFALL_SECS_Y of data.  Every DT
-  seconds we get a vector of FDMDV_NSPEC spectrum samples which we use
-  to update the last row.  The height of each row is dy pixels, which
-  maps to DT seconds.  We call each dy high rectangle of pixels a
-  block.
-
-*/
-
-extern float g_avmag[];
+extern float g_avmag[]; // magnitude spectrum passed in to draw() 
 
 BEGIN_EVENT_TABLE(PlotWaterfall, PlotPanel)
     EVT_PAINT           (PlotWaterfall::OnPaint)
@@ -49,7 +36,6 @@ BEGIN_EVENT_TABLE(PlotWaterfall, PlotPanel)
     EVT_MOUSEWHEEL      (PlotWaterfall::OnMouseWheelMoved)
     EVT_SIZE            (PlotWaterfall::OnSize)
     EVT_SHOW            (PlotWaterfall::OnShow)
-//    EVT_ERASE_BACKGROUND(PlotWaterfall::OnErase)
 END_EVENT_TABLE()
 
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
@@ -77,38 +63,26 @@ PlotWaterfall::PlotWaterfall(wxFrame* parent): PlotPanel(parent)
     SetLabelSize(10.0);
 }
 
-void PlotWaterfall::InitBitmap(int xsize, int ysize)
-    {
-        // draw some colourful stripes without alpha
-       //printf("m_pBitmap 0x%x\n", (unsigned int)m_pBitmap);
-        wxNativePixelData data(*m_pBitmap);
-        if ( !data )
-        {
-            wxLogError(wxT("InitBitmap: Failed to gain raw access to bitmap data"));
-            return;
-        }
+// When the window size gets set we can work outthe size of the window
+// we plot in and allocate a bit map of the correct size
 
-        wxNativePixelData::Iterator p(data);
-        for ( int y = 0; y < ysize; ++y )
-        {
-            wxNativePixelData::Iterator rowStart = p;
-
-            int r = y < ysize/3 ? 255 : 0,
-                g = (ysize/3 <= y) && (y < 2*(ysize/3)) ? 255 : 0,
-                b = 2*(ysize/3) <= y ? 255 : 0;
-
-            for ( int x = 0; x < xsize; ++x )
-            {
-                p.Red() = r;
-                p.Green() = g;
-                p.Blue() = b;
-                ++p; // same as p.OffsetX(1)
-            }
-
-            p = rowStart;
-            p.OffsetY(data, 1);
-        }
-    }
+void PlotWaterfall::OnSize(wxSizeEvent& event) {
+
+    m_rCtrl  = GetClientRect();
+
+    // m_rGrid is coords of inner window we actually plot to.  We defalte it a bit
+    // to leave room for axis labels.
+
+    m_rGrid  = m_rCtrl;
+    m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
+    //m_rGrid.Offset(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
+    //m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET*2), (PLOT_BORDER + (YBOTTOM_OFFSET*2)));
+    //m_rGrid.Offset(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
+
+    // we want a bit map the size of  m_rGrid
+
+    m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24);
+}
 
 //----------------------------------------------------------------
 // paintEvent()
@@ -125,7 +99,6 @@ void PlotWaterfall::InitBitmap(int xsize, int ysize)
 //----------------------------------------------------------------
 void PlotWaterfall::OnPaint(wxPaintEvent & evt)
 {
-    printf("OnPaint\n");
     wxAutoBufferedPaintDC pdc(this);
     draw(pdc);
 }
@@ -180,91 +153,35 @@ unsigned PlotWaterfall::heatmap(float val, float min, float max)
     return  (b << 16) + (g << 8) + r;
 }
 
-#define PLOT_BOTTOM     0
-#define PLOT_TOP        1
-
-//static long paint_count;
-
 //----------------------------------------------------------------
 // draw()
 //----------------------------------------------------------------
 void PlotWaterfall::draw(wxAutoBufferedPaintDC& pDC)
 {
-    printf("  draw m_pBmp 0x%x\n", (unsigned int)m_pBmp);
-
-    //m_pBitmap = new wxBitmap(SIZE, SIZE, 24);
-    
-    { 
-       wxRect m_rCtrl  = GetClientRect();
-       printf("%d %d\n", m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
-       m_pBitmap = new wxBitmap(m_rCtrl.GetWidth(), m_rCtrl.GetHeight(), 24);
-       InitBitmap(m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
-   }
-    
-    printf("m_pBitmap 0x%x\n", (unsigned int)m_pBitmap);
-
-    wxMemoryDC m_mDC;
-    m_mDC.SelectObject(*m_pBmp);
-    m_rCtrl  = GetClientRect();
-    m_rGrid  = m_rCtrl;
-
-    m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
-    m_rGrid.Offset(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
-
+    printf("PlotWaterfall::draw  m_newdata: %d\n", m_newdata);
     pDC.Clear();
-//    m_mDC.Clear();
-    m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
-//    if(m_firstPass)
-//    {
-//        m_firstPass = false;
-//        m_mDC.FloodFill(0, 0, VERY_LTGREY_COLOR);
-
-        // Draw a filled rectangle with aborder
-//        wxBrush ltGraphBkgBrush = wxBrush(DARK_BLUE_COLOR);
-//        m_mDC.SetBrush(ltGraphBkgBrush);
-//        m_mDC.SetPen(wxPen(BLACK_COLOR, 0));
-//        m_mDC.DrawRectangle(m_rPlot);
-
-//    }
-    wxBrush ltGraphBkgBrush = wxBrush(DARK_BLUE_COLOR);
-    pDC.SetBrush(ltGraphBkgBrush);
-    pDC.SetPen(wxPen(BLACK_COLOR, 0));
-    pDC.DrawRectangle(m_rPlot);
-    drawGraticule(pDC);
 
     if(m_newdata)
     {
-       printf("  m_newdata\n");
         m_newdata = false;
         plotPixelData(pDC);
-//#ifdef _USE_TIMER
-        int t = m_rPlot.GetTop();
-        int l = m_rPlot.GetLeft();
-        int h = m_rPlot.GetHeight();
-        int w = m_rPlot.GetWidth();
-        int t2 = t + 1;
-        int w2 = w - 1;
-        int ht = (h - DATA_LINE_HEIGHT);
-
-       printf("t %d l %d h %d w %d t2 %d w2 %d ht %d\n", t,l,h,w,t2,w2,ht);
-        //drawData();     //  m_mDC, PLOT_BOTTOM);
-       pDC.DrawLine(0,0,100,100);
-       pDC.DrawBitmap( *m_pBitmap, 0, 0);
-       //pDC.DrawBitmap(*m_pBmp, 0, 0, true);
-       pDC.DrawLine(200,200,0,200);
-        //m_mDC.StretchBlit(l, t2, w2, ht, &m_mDC, l, t2 + DATA_LINE_HEIGHT, w2, ht - 2);
-        //pDC.Blit(l, t, w, h, &m_mDC, l, t);                                                   // Scroll Up from Bottom
-//        pDC.StretchBlit(l, (h - t) + 4, w, (-h) + 4, &m_mDC, l, t, w, h);                       // Scroll Down from top
-//        pDC.StretchBlit(l, (h - t) + 4, w, h - 4, &m_mDC, l, t, w, h);                       // Scroll Down from top
-//#endif
-#ifdef TMP
-#endif
-        //drawGraticule(pDC);
+       pDC.DrawBitmap(*m_pBmp, PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER);
+    }
+    else {
+       
+       // no data to plot so just erase to black.  Blue looks nicer
+       // but is same colour as low amplitude signal
+
+       m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
+       wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
+       pDC.SetBrush(ltGraphBkgBrush);
+       pDC.SetPen(wxPen(BLACK_COLOR, 0));
+       pDC.DrawRectangle(m_rPlot);
+       //printf("x %d y %d w %d h %d\n", m_rPlot.x, m_rPlot.y, m_rPlot.width, m_rPlot.height);
     }
-    m_mDC.SetBrush(wxNullBrush);
-    m_mDC.SelectObject(wxNullBitmap);
+    
+    drawGraticule(pDC);
 
-    delete m_pBitmap;
 }
 
 
@@ -322,52 +239,77 @@ void PlotWaterfall::plotPixelData(wxAutoBufferedPaintDC&  dc)
     int         index;
     int         dy;
     int         dy_blocks;
-    int         bytes_in_row_of_blocks;
     int         b;
     int         px;
     int         py;
     int         intensity;
-    unsigned    *last_row;
-    unsigned    *pdest;
-    unsigned    *psrc;
 
-    wxNativePixelData data1(*m_pBitmap);
+    /*
+      Design Notes:
+
+      The height in pixels represents WATERFALL_SECS_Y of data.  Every DT
+      seconds we get a vector of FDMDV_NSPEC spectrum samples which we use
+      to update the last row.  The height of each row is dy pixels, which
+      maps to DT seconds.  We call each dy high rectangle of pixels a
+      block.
+
+    */
 
     // determine dy, the height of one "block"
-    px_per_sec = (float)m_rCtrl.GetHeight() / WATERFALL_SECS_Y;
+    px_per_sec = (float)m_rGrid.GetHeight() / WATERFALL_SECS_Y;
     dy = DT * px_per_sec;
 
     // number of dy high blocks in spectrogram
-    dy_blocks = m_rCtrl.GetHeight()/ dy;
+    dy_blocks = m_rGrid.GetHeight()/ dy;
 
     intensity_per_dB  = (float)256 /(MAX_DB - MIN_DB);
-    spec_index_per_px = (float)FDMDV_NSPEC / (float) m_rCtrl.GetWidth();
-
+    spec_index_per_px = (float)FDMDV_NSPEC / (float) m_rGrid.GetWidth();
+    
+    /*
     printf("h %d w %d px_per_sec %d dy %d dy_blocks %d spec_index_per_px: %f\n", 
-          m_rCtrl.GetHeight(), m_rCtrl.GetWidth(), px_per_sec, 
+          m_rGrid.GetHeight(), m_rGrid.GetWidth(), px_per_sec, 
           dy, dy_blocks, spec_index_per_px);
+    */
 
-    // shift previous bit map up one row of blocks ----------------------------
+    // Shift previous bit map up one row of blocks ----------------------------
+
+    wxNativePixelData data(*m_pBmp);
+    assert(data != NULL);
+    wxNativePixelData::Iterator bitMapStart(data);
+    wxNativePixelData::Iterator p = bitMapStart;
+
+    for(b = 0; b < dy_blocks - 1; b++) {
+       wxNativePixelData::Iterator psrc = bitMapStart;
+       wxNativePixelData::Iterator pdest = bitMapStart;
+       pdest.OffsetY(data, dy * b);
+       psrc.OffsetY(data, dy * (b+1));
+
+       // copy one line of blocks
+
+       for(py = 0; py < dy; py++) {
+           wxNativePixelData::Iterator pdestRowStart = pdest;
+           wxNativePixelData::Iterator psrcRowStart = psrc;
+
+           for(px = 0; px < m_rGrid.GetWidth(); px++) {
+               pdest.Red() = psrc.Red();
+               pdest.Green() = psrc.Green();
+               pdest.Blue() = psrc.Blue();
+               pdest++;
+               psrc++;
+           }
+
+           pdest = pdestRowStart;
+           pdest.OffsetY(data, 1);
+           psrc = psrcRowStart;
+           psrc.OffsetY(data, 1);          
+        }
 
-#ifdef SHIFT_UP
-    bytes_in_row_of_blocks = dy * m_rCtrl.GetWidth() * sizeof(unsigned);
-    for(b = 0; b < dy_blocks - 1; b++)
-    {
-        pdest = (unsigned int *)m_pBitmap + b * m_rCtrl.GetWidth() * dy;
-        psrc  = (unsigned int *)m_pBitmap + (b + 1) * m_rCtrl.GetWidth() * dy;
-        //memcpy(pdest, psrc, bytes_in_row_of_blocks);
     }
-    // create a new row of blocks at bottom
-    last_row = (unsigned int *)m_pBitmap + dy *(dy_blocks - 1)* m_rCtrl.GetWidth();
-#endif
 
-    // Draw last line using latest amplitude data -----------------------------
+    // Draw last line of blocks using latest amplitude data ------------------
 
-    wxNativePixelData data(*m_pBitmap);
-    assert(data != NULL);
-    wxNativePixelData::Iterator p(data);
+    p = bitMapStart;
     p.OffsetY(data, dy *(dy_blocks - 1));
-    printf("Y offset: %d\n", dy *(dy_blocks - 1));
 
     for(py = 0; py < dy; py++)
     {
index 227e35d20858588bd08a2a6a6be9b0785c32b8b6..97c644589a60963121440577c136b5b99e12793e 100644 (file)
@@ -55,13 +55,11 @@ class PlotWaterfall : public PlotPanel
     //    unsigned    *m_pixel_buf;
         unsigned    m_heatmap_lut[256];
         wxMemoryDC  m_mDC;
-        wxBitmap   *m_pBitmap;
 
         unsigned    heatmap(float val, float min, float max);
 
-       void        InitBitmap(int xsize, int ysize);
         void        OnPaint(wxPaintEvent & evt);
-        //void        OnSize(wxSizeEvent& event);
+        void        OnSize(wxSizeEvent& event);
         void        OnShow(wxShowEvent& event);
         void        drawGraticule(wxAutoBufferedPaintDC&  dc);
         void        draw(wxAutoBufferedPaintDC& pdc);