#define BETA 0.95 // constant for time averaging spectrum data
#define MIN_F_HZ 0 // min freq on Waterfall and Spectrum
#define MAX_F_HZ 4000 // max freq on Waterfall and Spectrum
-#define STEP_F_HZ 500 // freq step on Waterfall and Spectrum graticule
+#define STEP_F_HZ 500 // major (e.g. text legend) freq step on Waterfall and Spectrum graticule
+#define STEP_MINOR_F_HZ 100 // minor (ticks) freq step on Waterfall and Spectrum graticule
#define WATERFALL_SECS_Y 30 // number of seconds respresented by y axis of waterfall
#define WATERFALL_SECS_STEP 5 // graticule y axis steps of waterfall
#define DT 0.1 // time between real time graphing updates
{
// Add Waterfall Plot window
- m_panelWaterfall = new PlotWaterfall((wxFrame*) m_auiNbookCtrl, false);
+ m_panelWaterfall = new PlotWaterfall((wxFrame*) m_auiNbookCtrl, false, 0);
+ m_panelWaterfall->SetToolTip(_("Left click to tune, Right click to toggle mono/colour"));
m_auiNbookCtrl->AddPage(m_panelWaterfall, _("Waterfall"), true, wxNullBitmap);
}
if(wxGetApp().m_show_spect)
{
// Add Spectrum Plot window
m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl);
+ m_panelSpectrum->SetToolTip(_("Left click to tune"));
m_auiNbookCtrl->AddPage(m_panelSpectrum, _("Spectrum"), true, wxNullBitmap);
}
if(wxGetApp().m_show_scatter)
//-------------------------------------------------------------------------
void MainFrame::OnTogBtnRxID(wxCommandEvent& event)
{
+ // empty any junk in rx data FIFO
+ short junk;
+ while(fifo_read(g_rxDataOutFifo,&junk,1) == 0);
event.Skip();
}
BEGIN_EVENT_TABLE(PlotPanel, wxPanel)
EVT_PAINT (PlotPanel::OnPaint)
EVT_MOTION (PlotPanel::OnMouseMove)
- EVT_LEFT_DOWN (PlotPanel::OnMouseDown)
- EVT_LEFT_UP (PlotPanel::OnMouseUp)
+ EVT_LEFT_DOWN (PlotPanel::OnMouseLeftDown)
+ EVT_LEFT_UP (PlotPanel::OnMouseLeftUp)
+ EVT_RIGHT_DOWN (PlotPanel::OnMouseRightDown)
EVT_MOUSEWHEEL (PlotPanel::OnMouseWheelMoved)
EVT_SIZE (PlotPanel::OnSize)
EVT_SHOW (PlotPanel::OnShow)
}
//-------------------------------------------------------------------------
-// OnMouseDown()
+// OnMouseLeftDown()
//-------------------------------------------------------------------------
-void PlotPanel::OnMouseDown(wxMouseEvent& event)
+void PlotPanel::OnMouseLeftDown(wxMouseEvent& event)
+{
+}
+
+//-------------------------------------------------------------------------
+// OnMouseRightDown()
+//-------------------------------------------------------------------------
+void PlotPanel::OnMouseRightDown(wxMouseEvent& event)
{
}
}
//-------------------------------------------------------------------------
-// OnMouseUp()
+// OnMouseLeftUp()
//-------------------------------------------------------------------------
-void PlotPanel::OnMouseUp(wxMouseEvent& event)
+void PlotPanel::OnMouseLeftUp(wxMouseEvent& event)
{
m_mouseDown = false;
}
#define XLEFT_OFFSET 40
#define XLEFT_TEXT_OFFSET 6
#define YBOTTOM_OFFSET 20
-#define YBOTTOM_TEXT_OFFSET 6
+#define YBOTTOM_TEXT_OFFSET 15
#define GRID_INCREMENT 50
#define BLACK_COLOR wxColor(0x00, 0x00, 0x00)
// some useful events
void OnMouseMove(wxMouseEvent& event);
- virtual void OnMouseDown(wxMouseEvent& event);
- void OnMouseUp(wxMouseEvent& event);
+ virtual void OnMouseLeftDown(wxMouseEvent& event);
+ void OnMouseLeftUp(wxMouseEvent& event);
+ virtual void OnMouseRightDown(wxMouseEvent& event);
void OnMouseWheelMoved(wxMouseEvent& event);
void OnClose(wxCloseEvent& event ){ event.Skip(); }
void OnSize( wxSizeEvent& event );
BEGIN_EVENT_TABLE(PlotScalar, PlotPanel)
EVT_PAINT (PlotScalar::OnPaint)
EVT_MOTION (PlotScalar::OnMouseMove)
- EVT_LEFT_DOWN (PlotScalar::OnMouseDown)
- EVT_LEFT_UP (PlotScalar::OnMouseUp)
EVT_MOUSEWHEEL (PlotScalar::OnMouseWheelMoved)
EVT_SIZE (PlotScalar::OnSize)
EVT_SHOW (PlotScalar::OnShow)
BEGIN_EVENT_TABLE(PlotScatter, PlotPanel)
EVT_PAINT (PlotScatter::OnPaint)
EVT_MOTION (PlotScatter::OnMouseMove)
- EVT_LEFT_DOWN (PlotScatter::OnMouseDown)
- EVT_LEFT_UP (PlotScatter::OnMouseUp)
EVT_MOUSEWHEEL (PlotScatter::OnMouseWheelMoved)
EVT_SIZE (PlotScatter::OnSize)
EVT_SHOW (PlotScatter::OnShow)
BEGIN_EVENT_TABLE(PlotSpectrum, PlotPanel)
EVT_MOTION (PlotSpectrum::OnMouseMove)
- EVT_LEFT_DOWN (PlotSpectrum::OnMouseDown)
- EVT_LEFT_UP (PlotSpectrum::OnMouseUp)
+ EVT_LEFT_DOWN (PlotSpectrum::OnMouseLeftDown)
+ EVT_LEFT_UP (PlotSpectrum::OnMouseLeftUp)
EVT_MOUSEWHEEL (PlotSpectrum::OnMouseWheelMoved)
EVT_PAINT (PlotSpectrum::OnPaint)
EVT_SHOW (PlotSpectrum::OnShow)
// Vertical gridlines
- dc.SetPen(m_penShortDash);
for(f=STEP_F_HZ; f<MAX_F_HZ; f+=STEP_F_HZ) {
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
+
+ dc.SetPen(m_penShortDash);
dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
+ dc.SetPen(wxPen(BLACK_COLOR, 1));
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
+
sprintf(buf, "%4.0fHz", f);
GetTextExtent(buf, &text_w, &text_h);
dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
}
+ dc.SetPen(wxPen(BLACK_COLOR, 1));
+ for(f=STEP_MINOR_F_HZ; f<MAX_F_HZ; f+=STEP_MINOR_F_HZ)
+ {
+ x = f*freq_hz_to_px;
+ x += PLOT_BORDER + XLEFT_OFFSET;
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET-5);
+ }
+
// Horizontal gridlines
dc.SetPen(m_penDotDash);
x = m_rxFreq*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
//printf("m_rxFreq %f x %d\n", m_rxFreq, x);
- dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rGrid.GetHeight() + m_rCtrl.GetHeight());
+ dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rCtrl.GetHeight());
}
//-------------------------------------------------------------------------
// OnMouseDown()
//-------------------------------------------------------------------------
-void PlotSpectrum::OnMouseDown(wxMouseEvent& event)
+void PlotSpectrum::OnMouseLeftDown(wxMouseEvent& event)
{
m_mouseDown = true;
wxClientDC dc(this);
void OnShow(wxShowEvent& event);
void drawGraticule(wxAutoBufferedPaintDC& dc);
void draw(wxAutoBufferedPaintDC& dc);
- void OnMouseDown(wxMouseEvent& event);
+ void OnMouseLeftDown(wxMouseEvent& event);
private:
float m_rxFreq;
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)
// @brief
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
-PlotWaterfall::PlotWaterfall(wxFrame* parent, bool greyscale): 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 = greyscale;
+ m_graticule = graticule;
+ m_colour = colour;
m_Bufsz = GetMaxClientSize();
m_newdata = false;
m_firstPass = true;
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
// 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);
+
+ // Major Vertical gridlines and legend
+ //dc.SetPen(m_penShortDash);
for(f=STEP_F_HZ; f<MAX_F_HZ; f+=STEP_F_HZ)
{
x = f*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
- dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
+
+ if (m_graticule)
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
+ else
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
+
sprintf(buf, "%4.0fHz", f);
GetTextExtent(buf, &text_w, &text_h);
- dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
+ dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
}
+ for(f=STEP_MINOR_F_HZ; f<MAX_F_HZ; f+=STEP_MINOR_F_HZ)
+ {
+ x = f*freq_hz_to_px;
+ x += PLOT_BORDER + XLEFT_OFFSET;
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET-5);
+ }
+
// Horizontal gridlines
dc.SetPen(m_penDotDash);
for(time=0; time<=WATERFALL_SECS_Y; time+=WATERFALL_SECS_STEP) {
- y = m_rGrid.GetHeight() - time*time_s_to_py;
- y += PLOT_BORDER;
- dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
- (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
+ y = m_rGrid.GetHeight() - time*time_s_to_py;
+ y += PLOT_BORDER;
+
+ if (m_graticule)
+ dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
+ (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
sprintf(buf, "%3.0fs", time);
GetTextExtent(buf, &text_w, &text_h);
dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
x = m_rxFreq*freq_hz_to_px;
x += PLOT_BORDER + XLEFT_OFFSET;
//printf("m_rxFreq %f x %d\n", m_rxFreq, x);
- dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rGrid.GetHeight() + m_rCtrl.GetHeight());
+ dc.DrawLine(x, m_rGrid.GetHeight()+ PLOT_BORDER, x, m_rCtrl.GetHeight());
}
// number of dy high blocks in spectrogram
dy_blocks = m_rGrid.GetHeight()/ dy;
- intensity_per_dB = (float)256 /(MAX_MAG_DB - MIN_MAG_DB);
+ // update min and max amplitude estimates
+
+ float max_mag = MIN_MAG_DB;
+ for(int i=0; i<FDMDV_NSPEC; i++) {
+ if (g_avmag[i] > 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)FDMDV_NSPEC / (float) m_rGrid.GetWidth();
/*
index = px * spec_index_per_px;
assert(index < FDMDV_NSPEC);
- intensity = intensity_per_dB * (g_avmag[index] - MIN_MAG_DB);
+ 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);
- if (m_greyscale) {
- if (intensity > 200) {
+ 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:
+ if (intensity > 250) {
p.Red() = intensity;
p.Green() = intensity;
- p.Blue() = intensity;
+ p.Blue() = intensity;
}
else {
p.Red() = 0;
p.Green() = 0;
- p.Blue() = intensity;
+ p.Blue() = intensity;
}
- }
- else {
- p.Red() = m_heatmap_lut[intensity] & 0xff;
- p.Green() = (m_heatmap_lut[intensity] >> 8) & 0xff;
- p.Blue() = (m_heatmap_lut[intensity] >> 16) & 0xff;
+
+ break;
}
++p;
}
}
//-------------------------------------------------------------------------
-// OnMouseDown()
+// OnMouseLeftDown()
//-------------------------------------------------------------------------
-void PlotWaterfall::OnMouseDown(wxMouseEvent& event)
+void PlotWaterfall::OnMouseLeftDown(wxMouseEvent& event)
{
m_mouseDown = true;
wxClientDC dc(this);
fdmdv2_clickTune(clickFreq);
}
}
+
+//-------------------------------------------------------------------------
+// OnMouseRightDown()
+//-------------------------------------------------------------------------
+void PlotWaterfall::OnMouseRightDown(wxMouseEvent& event)
+{
+ m_colour++;
+ if (m_colour == 3)
+ m_colour = 0;
+}
+
class PlotWaterfall : public PlotPanel
{
public:
- PlotWaterfall(wxFrame* parent, bool greyscale);
+ PlotWaterfall(wxFrame* parent, bool graticule, int colour);
~PlotWaterfall();
bool checkDT(void);
void setGreyscale(bool greyscale) { m_greyscale = greyscale; }
void drawGraticule(wxAutoBufferedPaintDC& dc);
void draw(wxAutoBufferedPaintDC& dc);
void plotPixelData();
- void OnMouseDown(wxMouseEvent& event);
+ 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()
};
wxStaticBoxSizer* levelSizer;
levelSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Level")), wxVERTICAL);
- m_textLevel = new wxStaticText(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(50,-1), wxALIGN_CENTRE);
+ m_textLevel = new wxStaticText(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(60,-1), wxALIGN_CENTRE);
m_textLevel->SetForegroundColour(wxColour(255,0,0));
levelSizer->Add(m_textLevel, 0, wxALIGN_LEFT, 1);