From: drowe67 Date: Tue, 28 May 2013 06:45:26 +0000 (+0000) Subject: cleaned up some unused files X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=e8b24c16254e0ef70a572b89b2bdd24589cf17c5;p=freetel-svn-tracking.git cleaned up some unused files git-svn-id: https://svn.code.sf.net/p/freetel/code@1291 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/fdmdv2/src/Makefile.linux b/fdmdv2/src/Makefile.linux index a7f9e381..23ec27e8 100644 --- a/fdmdv2/src/Makefile.linux +++ b/fdmdv2/src/Makefile.linux @@ -97,7 +97,7 @@ fdmdv2_plot.o \ fdmdv2_plot_scalar.o \ fdmdv2_plot_scatter.o \ fdmdv2_plot_spectrum.o \ -fdmdv2_plot_waterfall_linux.o \ +fdmdv2_plot_waterfall.o \ fdmdv2_pa_wrapper.o \ dlg_audiooptions.o \ dlg_ptt.o \ diff --git a/fdmdv2/src/Makefile.win32 b/fdmdv2/src/Makefile.win32 index 0bdb703e..9c761ce7 100644 --- a/fdmdv2/src/Makefile.win32 +++ b/fdmdv2/src/Makefile.win32 @@ -24,7 +24,7 @@ fdmdv2_plot.o \ fdmdv2_plot_scalar.o \ fdmdv2_plot_scatter.o \ fdmdv2_plot_spectrum.o \ -fdmdv2_plot_waterfall_linux.o \ +fdmdv2_plot_waterfall.o \ fdmdv2_pa_wrapper.o \ dlg_audiooptions.o \ dlg_ptt.o \ diff --git a/fdmdv2/src/fdmdv2_main.h b/fdmdv2/src/fdmdv2_main.h index fa340dc7..6f186a80 100644 --- a/fdmdv2/src/fdmdv2_main.h +++ b/fdmdv2/src/fdmdv2_main.h @@ -63,7 +63,7 @@ #include "fdmdv2_plot.h" #include "fdmdv2_plot_scalar.h" #include "fdmdv2_plot_scatter.h" -#include "fdmdv2_plot_waterfall_linux.h" +#include "fdmdv2_plot_waterfall.h" #include "fdmdv2_plot_spectrum.h" #include "fdmdv2_pa_wrapper.h" #include "sndfile.h" diff --git a/fdmdv2/src/fdmdv2_plot_scatter.cpp b/fdmdv2/src/fdmdv2_plot_scatter.cpp index a85e7320..b9f5f7eb 100644 --- a/fdmdv2/src/fdmdv2_plot_scatter.cpp +++ b/fdmdv2/src/fdmdv2_plot_scatter.cpp @@ -1,6 +1,6 @@ //========================================================================== // Name: fdmdv2_plot_scatter.cpp -// Purpose: Implements a scatter plot derivative of fdmdv2_plot. +// Purpose: A scatter plot derivative of fdmdv2_plot. // Created: June 24, 2012 // Authors: David Rowe, David Witten // diff --git a/fdmdv2/src/fdmdv2_plot_scatter.h b/fdmdv2/src/fdmdv2_plot_scatter.h index bdcbe452..702f6333 100644 --- a/fdmdv2/src/fdmdv2_plot_scatter.h +++ b/fdmdv2/src/fdmdv2_plot_scatter.h @@ -1,6 +1,6 @@ //========================================================================== // Name: fdmdv2_plot_scatter.h -// Purpose: Defines a waterfall plot derivative of fdmdv2_plot. +// Purpose: A scatter plot derivative of fdmdv2_plot. // Created: June 24, 2012 // Authors: David Rowe, David Witten // diff --git a/fdmdv2/src/fdmdv2_plot_waterfall.cpp b/fdmdv2/src/fdmdv2_plot_waterfall.cpp index 01ea6b0e..b65c2083 100644 --- a/fdmdv2/src/fdmdv2_plot_waterfall.cpp +++ b/fdmdv2/src/fdmdv2_plot_waterfall.cpp @@ -2,54 +2,38 @@ // Name: fdmdv2_plot_waterfall.cpp // Purpose: Implements a waterfall plot derivative of fdmdv2_plot. // Created: June 22, 2012 -// Initial author: David Witten -// Derived from: code written by David Rowe +// Authors: David Rowe, David Witten +// // License: // -// Copyright (C) 2012 David Witten -// -// All rights reserved. -// // This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License version 2.1, +// it under the terms of the GNU General Public License version 2.1, // as published by the Free Software Foundation. This program is // distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // -// You should have received a copy of the GNU Lesser General Public License +// You should have received a copy of the GNU General Public License // along with this program; if not, see . // //========================================================================== #include #include "wx/wx.h" #include "fdmdv2_main.h" -#include "fdmdv2_plot_waterfall.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[]; // av mag spec passed in to draw() +void fdmdv2_clickTune(float frequency); // callback to pass new click freq BEGIN_EVENT_TABLE(PlotWaterfall, PlotPanel) EVT_PAINT (PlotWaterfall::OnPaint) EVT_MOTION (PlotWaterfall::OnMouseMove) - EVT_LEFT_DOWN (PlotWaterfall::OnMouseDown) - EVT_LEFT_UP (PlotWaterfall::OnMouseUp) + EVT_LEFT_DOWN (PlotWaterfall::OnMouseLeftDown) + EVT_RIGHT_DOWN (PlotWaterfall::OnMouseRightDown) + EVT_LEFT_UP (PlotWaterfall::OnMouseLeftUp) EVT_MOUSEWHEEL (PlotWaterfall::OnMouseWheelMoved) EVT_SIZE (PlotWaterfall::OnSize) EVT_SHOW (PlotWaterfall::OnShow) -// EVT_ERASE_BACKGROUND(PlotWaterfall::OnErase) END_EVENT_TABLE() //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= @@ -62,18 +46,47 @@ END_EVENT_TABLE() // @brief // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= -PlotWaterfall::PlotWaterfall(wxFrame* parent): PlotPanel(parent) +PlotWaterfall::PlotWaterfall(wxFrame* parent, bool graticule, int colour): PlotPanel(parent) { + for(int i = 0; i < 255; i++) { m_heatmap_lut[i] = heatmap((float)i, 0.0, 255.0); } - m_greyscale = 0; + m_graticule = graticule; + m_colour = colour; m_Bufsz = GetMaxClientSize(); m_newdata = false; m_firstPass = true; m_line_color = 0; SetLabelSize(10.0); + + m_pBmp = NULL; + m_max_mag = MAX_MAG_DB; + m_min_mag = MIN_MAG_DB; +} + +// 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 +void PlotWaterfall::OnSize(wxSizeEvent& event) +{ + // resize bit map + + delete m_pBmp; + + m_rCtrl = GetClientRect(); + + // m_rGrid is coords of inner window we actually plot to. We deflate 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))); + + // we want a bit map the size of m_rGrid + + m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24); + + m_dT = DT; } //---------------------------------------------------------------- @@ -91,8 +104,8 @@ PlotWaterfall::PlotWaterfall(wxFrame* parent): PlotPanel(parent) //---------------------------------------------------------------- void PlotWaterfall::OnPaint(wxPaintEvent & evt) { - wxAutoBufferedPaintDC pdc(this); - draw(pdc); + wxAutoBufferedPaintDC dc(this); + draw(dc); } //---------------------------------------------------------------- @@ -145,218 +158,324 @@ unsigned PlotWaterfall::heatmap(float val, float min, float max) return (b << 16) + (g << 8) + r; } -#define PLOT_BOTTOM 0 -#define PLOT_TOP 1 +bool PlotWaterfall::checkDT(void) +{ + // Check dY is > 1 pixel before proceeding. For small screens + // and large WATERFALL_SECS_Y we might have less than one + // block per pixel. In this case increase m_dT and perform draw + // less often -//static long paint_count; + float px_per_sec = (float)m_rGrid.GetHeight() / WATERFALL_SECS_Y; + float dy = m_dT * px_per_sec; + + if (dy < 1.0) { + m_dT += DT; + return false; + } + else + return true; +} //---------------------------------------------------------------- // draw() //---------------------------------------------------------------- -void PlotWaterfall::draw(wxAutoBufferedPaintDC& pDC) +void PlotWaterfall::draw(wxAutoBufferedPaintDC& dc) { - wxMemoryDC m_mDC; - m_mDC.SelectObject(*m_pBmp); + m_rCtrl = GetClientRect(); - m_rGrid = m_rCtrl; + // m_rGrid is coords of inner window we actually plot to. We deflate 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); - - 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) + + if (m_pBmp == NULL) { - 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); - - drawData(); // m_mDC, PLOT_BOTTOM); - 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 -//#endif - drawGraticule(pDC); + // we want a bit map the size of m_rGrid + m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24); } - m_mDC.SetBrush(wxNullBrush); - m_mDC.SelectObject(wxNullBitmap); -} -//------------------------------------------------------------------------- -// drawData() -//------------------------------------------------------------------------- -void PlotWaterfall::drawData() //wxMemoryDC& pDC) -{ - wxNativePixelData dPix = wxNativePixelData(*m_pBmp, m_rCtrl); - m_pPix = &dPix; - if(m_pPix == NULL) + dc.Clear(); + + if(m_newdata) { - return; + m_newdata = false; + plotPixelData(); + dc.DrawBitmap(*m_pBmp, PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER); + m_dT = DT; } - wxNativePixelData::Iterator p(*m_pPix); - - int w = m_rPlot.GetWidth(); - int h = m_rPlot.GetHeight(); - p.Offset(*m_pPix, XLEFT_OFFSET + 3, h - (DATA_LINE_HEIGHT - 2)); - for(int y = 0; y < DATA_LINE_HEIGHT; ++y) + else { - wxNativePixelData::Iterator rowStart = p; - for(int x = 0; x < (w - 1); ++x, ++p) - { - p.Red() = g_avmag[x]; - p.Green() = g_avmag[x]; - p.Blue() = g_avmag[x]; - } - p = rowStart; - p.OffsetY(*m_pPix, 1); + + // no data to plot so just erase to black. Blue looks nicer + // but is same colour as low amplitude signal + + // Bug on Linux: When Stop is pressed this code doesn't erase + // the lower 25% of the Waterfall Window + + 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); } + drawGraticule(dc); } //------------------------------------------------------------------------- // drawGraticule() //------------------------------------------------------------------------- -void PlotWaterfall::drawGraticule(wxAutoBufferedPaintDC& pDC) +void PlotWaterfall::drawGraticule(wxAutoBufferedPaintDC& dc) { - int p; - char buf[15]; - + int x, y, text_w, text_h; + char buf[15]; wxString s; + float f, time, freq_hz_to_px, time_s_to_py; wxBrush ltGraphBkgBrush; ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT); ltGraphBkgBrush.SetColour(*wxBLACK); - pDC.SetBrush(ltGraphBkgBrush); - pDC.SetPen(wxPen(BLACK_COLOR, 1)); + dc.SetBrush(ltGraphBkgBrush); + dc.SetPen(wxPen(BLACK_COLOR, 1)); - // Vertical gridlines - pDC.SetPen(m_penShortDash); - for(p = (PLOT_BORDER + XLEFT_OFFSET + GRID_INCREMENT); p < ((m_rGrid.GetWidth() - XLEFT_OFFSET) + GRID_INCREMENT); p += GRID_INCREMENT) - { - pDC.DrawLine(p, (m_rGrid.GetHeight() + PLOT_BORDER), p, PLOT_BORDER); - } - // Horizontal gridlines - pDC.SetPen(m_penDotDash); - for(p = (m_rGrid.GetHeight() - GRID_INCREMENT); p > PLOT_BORDER; p -= GRID_INCREMENT) - { - pDC.DrawLine(PLOT_BORDER + XLEFT_OFFSET, (p + PLOT_BORDER), (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), (p + PLOT_BORDER)); - } - // Label the X-Axis - pDC.SetPen(wxPen(GREY_COLOR, 1)); - for(p = GRID_INCREMENT; p < (m_rGrid.GetWidth() - YBOTTOM_OFFSET); p += GRID_INCREMENT) + freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ); + time_s_to_py = (float)m_rGrid.GetHeight()/WATERFALL_SECS_Y; + + // 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()) + + // Check if small screen size means text will overlap + + int textXStep = STEP_F_HZ*freq_hz_to_px; + int textYStep = WATERFALL_SECS_STEP*time_s_to_py; + sprintf(buf, "%4.0fHz", (float)MAX_F_HZ - STEP_F_HZ); + GetTextExtent(buf, &text_w, &text_h); + int overlappedText = (text_w > textXStep) || (text_h > textYStep); + + // Major Vertical gridlines and legend + //dc.SetPen(m_penShortDash); + for(f=STEP_F_HZ; f PLOT_BORDER; p -= GRID_INCREMENT) + + for(f=STEP_MINOR_F_HZ; f max_mag) + { + max_mag = g_avmag[i]; + } } - // create a new row of blocks at bottom - spec_index_per_px = (float)FDMDV_NSPEC / (float) m_rCtrl.GetWidth(); - intensity_per_dB = (float)256 /(MAX_DB - MIN_DB); - last_row = (unsigned int *)m_pBmp + dy *(dy_blocks - 1)* m_rCtrl.GetWidth(); + m_max_mag = BETA*m_max_mag + (1 - BETA)*max_mag; + m_min_mag = max_mag - 20.0; + //printf("max_mag: %f m_max_mag: %f\n", max_mag, m_max_mag); + //intensity_per_dB = (float)256 /(MAX_MAG_DB - MIN_MAG_DB); + intensity_per_dB = (float)256 /(m_max_mag - m_min_mag); + spec_index_per_px = ((float)(MAX_F_HZ)/(float)FDMDV_MAX_F_HZ)*(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_rGrid.GetHeight(), m_rGrid.GetWidth(), px_per_sec, + dy, dy_blocks, spec_index_per_px); + */ + + // Shift previous bit map up one row of blocks ---------------------------- wxNativePixelData data(*m_pBmp); - if(!data) - { - wxMessageBox(wxT("Unable to access Bitmap Data"), wxT("Error")); - return; - } - if(data.GetWidth() < 20 || data.GetHeight() < 20) - { - wxMessageBox(wxT("Bitmap is too small to use"), wxT("Warning")); - return; - } - wxNativePixelData::Iterator p(data); - // we draw a (10, 10)-(20, 20) rect manually using the given r, g, b - p.Offset(data, 10, 10); - for(px = 0; px < m_rCtrl.GetWidth(); px++) + wxNativePixelData::Iterator bitMapStart(data); + wxNativePixelData::Iterator p = bitMapStart; + + for(b = 0; b < dy_blocks - 1; b++) { - index = px * spec_index_per_px; - intensity = intensity_per_dB * (g_avmag[index] - MIN_DB); - if(intensity > 255) - { - intensity = 255; - } - if (intensity < 0) - { - intensity = 0; - } - if(m_greyscale) + 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++) { - for(py = 0; py < dy; py++) + wxNativePixelData::Iterator pdestRowStart = pdest; + wxNativePixelData::Iterator psrcRowStart = psrc; + + for(px = 0; px < m_rGrid.GetWidth(); px++) { - last_row[px + py * m_rCtrl.GetWidth()] = intensity << 8; + 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); } - else + } + + // Draw last line of blocks using latest amplitude data ------------------ + p = bitMapStart; + p.OffsetY(data, dy *(dy_blocks - 1)); + for(py = 0; py < dy; py++) + { + wxNativePixelData::Iterator rowStart = p; + + for(px = 0; px < m_rGrid.GetWidth(); px++) { - for(py = 0; py < dy; py++) - { - last_row[px + py * m_rCtrl.GetWidth()] = m_heatmap_lut[intensity]; + index = px * spec_index_per_px; + assert(index < FDMDV_NSPEC); + + intensity = intensity_per_dB * (g_avmag[index] - m_min_mag); + if(intensity > 255) intensity = 255; + if (intensity < 0) intensity = 0; + //printf("%d %f %d \n", index, g_avmag[index], intensity); + + switch (m_colour) { + case 0: + p.Red() = m_heatmap_lut[intensity] & 0xff; + p.Green() = (m_heatmap_lut[intensity] >> 8) & 0xff; + p.Blue() = (m_heatmap_lut[intensity] >> 16) & 0xff; + break; + case 1: + p.Red() = intensity; + p.Green() = intensity; + p.Blue() = intensity; + break; + case 2: + p.Red() = intensity; + p.Green() = intensity; + if (intensity < 127) + p.Blue() = intensity*2; + else + p.Blue() = 255; + + break; } + ++p; } + p = rowStart; + p.OffsetY(data, 1); } + } + +//------------------------------------------------------------------------- +// OnMouseLeftDown() +//------------------------------------------------------------------------- +void PlotWaterfall::OnMouseLeftDown(wxMouseEvent& event) +{ + m_mouseDown = true; + wxClientDC dc(this); + + wxPoint pt(event.GetLogicalPosition(dc)); + + // map x coord to edges of actual plot + pt.x -= PLOT_BORDER + XLEFT_OFFSET; + pt.y -= PLOT_BORDER; + + // valid click if inside of plot + if ((pt.x >= 0) && (pt.x <= m_rGrid.GetWidth()) && (pt.y >=0)) + { + float freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ); + float clickFreq = (float)pt.x/freq_hz_to_px; + + // communicate back to other threads + fdmdv2_clickTune(clickFreq); + } +} + +//------------------------------------------------------------------------- +// OnMouseRightDown() +//------------------------------------------------------------------------- +void PlotWaterfall::OnMouseRightDown(wxMouseEvent& event) +{ + m_colour++; + if (m_colour == 3) + m_colour = 0; +} + diff --git a/fdmdv2/src/fdmdv2_plot_waterfall.h b/fdmdv2/src/fdmdv2_plot_waterfall.h index 0d5e0226..e5c0e836 100644 --- a/fdmdv2/src/fdmdv2_plot_waterfall.h +++ b/fdmdv2/src/fdmdv2_plot_waterfall.h @@ -2,23 +2,19 @@ // Name: fdmdv2_plot_waterfall.h // Purpose: Defines a waterfall plot derivative of fdmdv2_plot. // Created: June 22, 2012 -// Initial author: David Witten -// Derived from: code written by David Rowe +// Authors: David Rowe, David Witten +// // License: // -// Copyright (C) 2012 David Witten -// -// All rights reserved. -// // This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License version 2.1, +// it under the terms of the GNU General Public License version 2.1, // as published by the Free Software Foundation. This program is // distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // -// You should have received a copy of the GNU Lesser General Public License +// You should have received a copy of the GNU General Public License // along with this program; if not, see . // //========================================================================== @@ -41,21 +37,33 @@ class PlotWaterfall : public PlotPanel { public: - PlotWaterfall(wxFrame* parent); + PlotWaterfall(wxFrame* parent, bool graticule, int colour); ~PlotWaterfall(); + bool checkDT(void); + void setGreyscale(bool greyscale) { m_greyscale = greyscale; } + void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; } protected: unsigned m_heatmap_lut[256]; - wxMemoryDC m_mDC; unsigned heatmap(float val, float min, float max); void OnPaint(wxPaintEvent & evt); + void OnSize(wxSizeEvent& event); void OnShow(wxShowEvent& event); void drawGraticule(wxAutoBufferedPaintDC& dc); - void draw(wxAutoBufferedPaintDC& pdc); - void plotPixelData(wxAutoBufferedPaintDC& dc); - void drawData(); // wxMemoryDC& pDC); + void draw(wxAutoBufferedPaintDC& dc); + void plotPixelData(); + void OnMouseLeftDown(wxMouseEvent& event); + void OnMouseRightDown(wxMouseEvent& event); + + private: + float m_dT; + float m_rxFreq; + bool m_graticule; + float m_min_mag; + float m_max_mag; + int m_colour; DECLARE_EVENT_TABLE() }; diff --git a/fdmdv2/src/fdmdv2_plot_waterfall_linux.cpp b/fdmdv2/src/fdmdv2_plot_waterfall_linux.cpp deleted file mode 100644 index b65c2083..00000000 --- a/fdmdv2/src/fdmdv2_plot_waterfall_linux.cpp +++ /dev/null @@ -1,481 +0,0 @@ -//========================================================================== -// Name: fdmdv2_plot_waterfall.cpp -// Purpose: Implements a waterfall plot derivative of fdmdv2_plot. -// Created: June 22, 2012 -// Authors: David Rowe, David Witten -// -// License: -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2.1, -// as published by the Free Software Foundation. This program is -// distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -// License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, see . -// -//========================================================================== -#include -#include "wx/wx.h" -#include "fdmdv2_main.h" - -extern float g_avmag[]; // av mag spec passed in to draw() -void fdmdv2_clickTune(float frequency); // callback to pass new click freq - -BEGIN_EVENT_TABLE(PlotWaterfall, PlotPanel) - EVT_PAINT (PlotWaterfall::OnPaint) - EVT_MOTION (PlotWaterfall::OnMouseMove) - EVT_LEFT_DOWN (PlotWaterfall::OnMouseLeftDown) - EVT_RIGHT_DOWN (PlotWaterfall::OnMouseRightDown) - EVT_LEFT_UP (PlotWaterfall::OnMouseLeftUp) - EVT_MOUSEWHEEL (PlotWaterfall::OnMouseWheelMoved) - EVT_SIZE (PlotWaterfall::OnSize) - EVT_SHOW (PlotWaterfall::OnShow) -END_EVENT_TABLE() - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= -// Class WaterfallPlot -// -// @class WaterfallPlot -// @author David Witten -// @date $(Date) -// @file $(CurrentFileName).$(CurrentFileExt) -// @brief -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= -PlotWaterfall::PlotWaterfall(wxFrame* parent, bool graticule, int colour): PlotPanel(parent) -{ - - for(int i = 0; i < 255; i++) - { - m_heatmap_lut[i] = heatmap((float)i, 0.0, 255.0); - } - m_graticule = graticule; - m_colour = colour; - m_Bufsz = GetMaxClientSize(); - m_newdata = false; - m_firstPass = true; - m_line_color = 0; - SetLabelSize(10.0); - - m_pBmp = NULL; - m_max_mag = MAX_MAG_DB; - m_min_mag = MIN_MAG_DB; -} - -// 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 -void PlotWaterfall::OnSize(wxSizeEvent& event) -{ - // resize bit map - - delete m_pBmp; - - m_rCtrl = GetClientRect(); - - // m_rGrid is coords of inner window we actually plot to. We deflate 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))); - - // we want a bit map the size of m_rGrid - - m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24); - - m_dT = DT; -} - -//---------------------------------------------------------------- -// paintEvent() -// -// @class $(Name) -// @author $(User) -// @date $(Date) -// @file $(CurrentFileName).$(CurrentFileExt) -// @brief -// -// Called by the system of by wxWidgets when the panel needs -// to be redrawn. You can also trigger this call by calling -// Refresh()/Update(). -//---------------------------------------------------------------- -void PlotWaterfall::OnPaint(wxPaintEvent & evt) -{ - wxAutoBufferedPaintDC dc(this); - draw(dc); -} - -//---------------------------------------------------------------- -// OnShow() -//---------------------------------------------------------------- -void PlotWaterfall::OnShow(wxShowEvent& event) -{ -} - -//---------------------------------------------------------------- -// ~PlotWaterfall() -//---------------------------------------------------------------- -PlotWaterfall::~PlotWaterfall() -{ -} - -//---------------------------------------------------------------- -// heatmap() -// map val to a rgb colour -// from http://eddiema.ca/2011/01/21/c-sharp-heatmaps/ -//---------------------------------------------------------------- -unsigned PlotWaterfall::heatmap(float val, float min, float max) -{ - unsigned r = 0; - unsigned g = 0; - unsigned b = 0; - - val = (val - min) / (max - min); - if(val <= 0.2) - { - b = (unsigned)((val / 0.2) * 255); - } - else if(val > 0.2 && val <= 0.7) - { - b = (unsigned)((1.0 - ((val - 0.2) / 0.5)) * 255); - } - if(val >= 0.2 && val <= 0.6) - { - g = (unsigned)(((val - 0.2) / 0.4) * 255); - } - else if(val > 0.6 && val <= 0.9) - { - g = (unsigned)((1.0 - ((val - 0.6) / 0.3)) * 255); - } - if(val >= 0.5) - { - r = (unsigned)(((val - 0.5) / 0.5) * 255); - } - //printf("%f %x %x %x\n", val, r, g, b); - return (b << 16) + (g << 8) + r; -} - -bool PlotWaterfall::checkDT(void) -{ - // Check dY is > 1 pixel before proceeding. For small screens - // and large WATERFALL_SECS_Y we might have less than one - // block per pixel. In this case increase m_dT and perform draw - // less often - - float px_per_sec = (float)m_rGrid.GetHeight() / WATERFALL_SECS_Y; - float dy = m_dT * px_per_sec; - - if (dy < 1.0) { - m_dT += DT; - return false; - } - else - return true; -} - -//---------------------------------------------------------------- -// draw() -//---------------------------------------------------------------- -void PlotWaterfall::draw(wxAutoBufferedPaintDC& dc) -{ - - m_rCtrl = GetClientRect(); - - // m_rGrid is coords of inner window we actually plot to. We deflate 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))); - - if (m_pBmp == NULL) - { - // we want a bit map the size of m_rGrid - m_pBmp = new wxBitmap(m_rGrid.GetWidth(), m_rGrid.GetHeight(), 24); - } - - dc.Clear(); - - if(m_newdata) - { - m_newdata = false; - plotPixelData(); - dc.DrawBitmap(*m_pBmp, PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER); - m_dT = DT; - } - else - { - - // no data to plot so just erase to black. Blue looks nicer - // but is same colour as low amplitude signal - - // Bug on Linux: When Stop is pressed this code doesn't erase - // the lower 25% of the Waterfall Window - - 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); - } - drawGraticule(dc); -} - -//------------------------------------------------------------------------- -// drawGraticule() -//------------------------------------------------------------------------- -void PlotWaterfall::drawGraticule(wxAutoBufferedPaintDC& dc) -{ - int x, y, text_w, text_h; - char buf[15]; - wxString s; - float f, time, freq_hz_to_px, time_s_to_py; - - wxBrush ltGraphBkgBrush; - ltGraphBkgBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT); - ltGraphBkgBrush.SetColour(*wxBLACK); - dc.SetBrush(ltGraphBkgBrush); - dc.SetPen(wxPen(BLACK_COLOR, 1)); - - freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ); - time_s_to_py = (float)m_rGrid.GetHeight()/WATERFALL_SECS_Y; - - // 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()) - - // Check if small screen size means text will overlap - - int textXStep = STEP_F_HZ*freq_hz_to_px; - int textYStep = WATERFALL_SECS_STEP*time_s_to_py; - sprintf(buf, "%4.0fHz", (float)MAX_F_HZ - STEP_F_HZ); - GetTextExtent(buf, &text_w, &text_h); - int overlappedText = (text_w > textXStep) || (text_h > textYStep); - - // Major Vertical gridlines and legend - //dc.SetPen(m_penShortDash); - for(f=STEP_F_HZ; f max_mag) - { - max_mag = g_avmag[i]; - } - } - - m_max_mag = BETA*m_max_mag + (1 - BETA)*max_mag; - m_min_mag = max_mag - 20.0; - //printf("max_mag: %f m_max_mag: %f\n", max_mag, m_max_mag); - //intensity_per_dB = (float)256 /(MAX_MAG_DB - MIN_MAG_DB); - intensity_per_dB = (float)256 /(m_max_mag - m_min_mag); - spec_index_per_px = ((float)(MAX_F_HZ)/(float)FDMDV_MAX_F_HZ)*(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_rGrid.GetHeight(), m_rGrid.GetWidth(), px_per_sec, - dy, dy_blocks, spec_index_per_px); - */ - - // Shift previous bit map up one row of blocks ---------------------------- - wxNativePixelData data(*m_pBmp); - 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); - } - } - - // Draw last line of blocks using latest amplitude data ------------------ - p = bitMapStart; - p.OffsetY(data, dy *(dy_blocks - 1)); - for(py = 0; py < dy; py++) - { - wxNativePixelData::Iterator rowStart = p; - - for(px = 0; px < m_rGrid.GetWidth(); px++) - { - index = px * spec_index_per_px; - assert(index < FDMDV_NSPEC); - - intensity = intensity_per_dB * (g_avmag[index] - m_min_mag); - if(intensity > 255) intensity = 255; - if (intensity < 0) intensity = 0; - //printf("%d %f %d \n", index, g_avmag[index], intensity); - - switch (m_colour) { - case 0: - p.Red() = m_heatmap_lut[intensity] & 0xff; - p.Green() = (m_heatmap_lut[intensity] >> 8) & 0xff; - p.Blue() = (m_heatmap_lut[intensity] >> 16) & 0xff; - break; - case 1: - p.Red() = intensity; - p.Green() = intensity; - p.Blue() = intensity; - break; - case 2: - p.Red() = intensity; - p.Green() = intensity; - if (intensity < 127) - p.Blue() = intensity*2; - else - p.Blue() = 255; - - break; - } - ++p; - } - p = rowStart; - p.OffsetY(data, 1); - } - -} - -//------------------------------------------------------------------------- -// OnMouseLeftDown() -//------------------------------------------------------------------------- -void PlotWaterfall::OnMouseLeftDown(wxMouseEvent& event) -{ - m_mouseDown = true; - wxClientDC dc(this); - - wxPoint pt(event.GetLogicalPosition(dc)); - - // map x coord to edges of actual plot - pt.x -= PLOT_BORDER + XLEFT_OFFSET; - pt.y -= PLOT_BORDER; - - // valid click if inside of plot - if ((pt.x >= 0) && (pt.x <= m_rGrid.GetWidth()) && (pt.y >=0)) - { - float freq_hz_to_px = (float)m_rGrid.GetWidth()/(MAX_F_HZ-MIN_F_HZ); - float clickFreq = (float)pt.x/freq_hz_to_px; - - // communicate back to other threads - fdmdv2_clickTune(clickFreq); - } -} - -//------------------------------------------------------------------------- -// OnMouseRightDown() -//------------------------------------------------------------------------- -void PlotWaterfall::OnMouseRightDown(wxMouseEvent& event) -{ - m_colour++; - if (m_colour == 3) - m_colour = 0; -} - diff --git a/fdmdv2/src/fdmdv2_plot_waterfall_linux.h b/fdmdv2/src/fdmdv2_plot_waterfall_linux.h deleted file mode 100644 index e5c0e836..00000000 --- a/fdmdv2/src/fdmdv2_plot_waterfall_linux.h +++ /dev/null @@ -1,71 +0,0 @@ -//========================================================================== -// Name: fdmdv2_plot_waterfall.h -// Purpose: Defines a waterfall plot derivative of fdmdv2_plot. -// Created: June 22, 2012 -// Authors: David Rowe, David Witten -// -// License: -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2.1, -// as published by the Free Software Foundation. This program is -// distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -// License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, see . -// -//========================================================================== -#ifndef __FDMDV2_PLOT_WATERFALL__ -#define __FDMDV2_PLOT_WATERFALL__ - -#include "fdmdv2_plot.h" -#include "fdmdv2_defines.h" - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= -// Class PlotWaterfall -// -// @class $(Name) -// @author $(User) -// @date $(Date) -// @file $(CurrentFileName).$(CurrentFileExt) -// @brief -// -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= -class PlotWaterfall : public PlotPanel -{ - public: - PlotWaterfall(wxFrame* parent, bool graticule, int colour); - ~PlotWaterfall(); - bool checkDT(void); - void setGreyscale(bool greyscale) { m_greyscale = greyscale; } - void setRxFreq(float rxFreq) { m_rxFreq = rxFreq; } - - protected: - unsigned m_heatmap_lut[256]; - - unsigned heatmap(float val, float min, float max); - - void OnPaint(wxPaintEvent & evt); - void OnSize(wxSizeEvent& event); - void OnShow(wxShowEvent& event); - void drawGraticule(wxAutoBufferedPaintDC& dc); - void draw(wxAutoBufferedPaintDC& dc); - void plotPixelData(); - void OnMouseLeftDown(wxMouseEvent& event); - void OnMouseRightDown(wxMouseEvent& event); - - private: - float m_dT; - float m_rxFreq; - bool m_graticule; - float m_min_mag; - float m_max_mag; - int m_colour; - - DECLARE_EVENT_TABLE() -}; - -#endif //__FDMDV2_PLOT_WATERFALL__