summaryrefslogtreecommitdiff
path: root/gr-wxgui/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gr-wxgui/lib')
-rw-r--r--gr-wxgui/lib/CMakeLists.txt77
-rw-r--r--gr-wxgui/lib/gnuradio-wxgui.rc.in54
-rw-r--r--gr-wxgui/lib/histo_sink_f_impl.cc186
-rw-r--r--gr-wxgui/lib/histo_sink_f_impl.h63
-rw-r--r--gr-wxgui/lib/oscope_guts.cc439
-rw-r--r--gr-wxgui/lib/oscope_sink_f_impl.cc83
-rw-r--r--gr-wxgui/lib/oscope_sink_f_impl.h51
-rw-r--r--gr-wxgui/lib/oscope_sink_x.cc161
8 files changed, 1114 insertions, 0 deletions
diff --git a/gr-wxgui/lib/CMakeLists.txt b/gr-wxgui/lib/CMakeLists.txt
new file mode 100644
index 0000000000..c33a7b9a33
--- /dev/null
+++ b/gr-wxgui/lib/CMakeLists.txt
@@ -0,0 +1,77 @@
+# Copyright 2012-2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/../include
+ ${GR_WXGUI_INCLUDE_DIRS}
+ ${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+)
+
+link_directories(${Boost_LIBRARY_DIRS})
+
+if(ENABLE_GR_CTRLPORT)
+ ADD_DEFINITIONS(-DGR_CTRLPORT)
+ include_directories(${ICE_INCLUDE_DIR})
+endif(ENABLE_GR_CTRLPORT)
+
+########################################################################
+# Setup library
+########################################################################
+list(APPEND gr_wxgui_sources
+ histo_sink_f_impl.cc
+ oscope_guts.cc
+ oscope_sink_x.cc
+ oscope_sink_f_impl.cc
+)
+
+#Add Windows DLL resource file if using MSVC
+IF(MSVC)
+ include(${CMAKE_SOURCE_DIR}/cmake/Modules/GrVersion.cmake)
+
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-wxgui.rc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-wxgui.rc
+ @ONLY)
+
+ list(APPEND gr_wxgui_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-wxgui.rc
+ )
+ENDIF(MSVC)
+
+list(APPEND wxgui_libs
+ gnuradio-runtime
+ volk
+ ${Boost_LIBRARIES}
+ ${BLOCKS_LIBRARIES}
+ ${LOG4CPP_LIBRARIES}
+)
+
+add_library(gnuradio-wxgui SHARED ${gr_wxgui_sources})
+
+target_link_libraries(gnuradio-wxgui ${wxgui_libs})
+GR_LIBRARY_FOO(gnuradio-wxgui
+ RUNTIME_COMPONENT "wxgui_runtime"
+ DEVEL_COMPONENT "wxgui_devel")
diff --git a/gr-wxgui/lib/gnuradio-wxgui.rc.in b/gr-wxgui/lib/gnuradio-wxgui.rc.in
new file mode 100644
index 0000000000..126db75091
--- /dev/null
+++ b/gr-wxgui/lib/gnuradio-wxgui.rc.in
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <afxres.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @MAJOR_VERSION@,@API_COMPAT@,@RC_MINOR_VERSION@,@RC_MAINT_VERSION@
+ PRODUCTVERSION @MAJOR_VERSION@,@API_COMPAT@,@RC_MINOR_VERSION@,@RC_MAINT_VERSION@
+ FILEFLAGSMASK 0x3fL
+#ifndef NDEBUG
+ FILEFLAGS 0x0L
+#else
+ FILEFLAGS 0x1L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE VFT2_DRV_INSTALLABLE
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "gnuradio-blocks"
+ VALUE "FileVersion", "@VERSION@"
+ VALUE "InternalName", "gnuradio-blocks.dll"
+ VALUE "LegalCopyright", "Licensed under GPLv3 or any later version"
+ VALUE "OriginalFilename", "gnuradio-blocks.dll"
+ VALUE "ProductName", "gnuradio-blocks"
+ VALUE "ProductVersion", "@VERSION@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ END
diff --git a/gr-wxgui/lib/histo_sink_f_impl.cc b/gr-wxgui/lib/histo_sink_f_impl.cc
new file mode 100644
index 0000000000..9b168de547
--- /dev/null
+++ b/gr-wxgui/lib/histo_sink_f_impl.cc
@@ -0,0 +1,186 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-2011,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "histo_sink_f_impl.h"
+#include <gr_io_signature.h>
+#include <boost/math/special_functions/round.hpp>
+
+namespace gr {
+ namespace wxgui {
+
+ static float get_clean_num(float num)
+ {
+ if(num == 0)
+ return 0;
+ /* extract sign and exponent from num */
+ int sign = (num < 0) ? -1 : 1; num = fabs(num);
+ float exponent = floor(log10(num));
+ /* search for closest number with base 1, 2, 5, 10 */
+ float closest_num = 10*pow(10, exponent);
+ if(fabs(num - 1*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 1*pow(10, exponent);
+ if(fabs(num - 2*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 2*pow(10, exponent);
+ if(fabs(num - 5*pow(10, exponent)) < fabs(num - closest_num))
+ closest_num = 5*pow(10, exponent);
+ return sign*closest_num;
+ }
+
+ histo_sink_f::sptr
+ histo_sink_f::make(gr_msg_queue_sptr msgq)
+ {
+ return gnuradio::get_initial_sptr
+ (new histo_sink_f_impl(msgq));
+ }
+
+ histo_sink_f_impl::histo_sink_f_impl(gr_msg_queue_sptr msgq)
+ : gr_sync_block("histo_sink_f",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(0, 0, 0)),
+ d_msgq(msgq), d_num_bins(11), d_frame_size(1000),
+ d_sample_count(0), d_bins(NULL), d_samps(NULL)
+ {
+ //allocate arrays and clear
+ set_num_bins(d_num_bins);
+ set_frame_size(d_frame_size);
+ }
+
+ histo_sink_f_impl::~histo_sink_f_impl(void)
+ {
+ delete [] d_samps;
+ delete [] d_bins;
+ }
+
+ int
+ histo_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float*)input_items[0];
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ for(unsigned int i = 0; i < (unsigned int)noutput_items; i++) {
+ d_samps[d_sample_count] = in[i];
+ d_sample_count++;
+ /* processed a frame? */
+ if(d_sample_count == d_frame_size) {
+ send_frame();
+ clear();
+ }
+ }
+ return noutput_items;
+ }
+
+ void
+ histo_sink_f_impl::send_frame(void)
+ {
+ /* output queue full, drop the data */
+ if(d_msgq->full_p())
+ return;
+ /* find the minimum and maximum */
+ float minimum = d_samps[0];
+ float maximum = d_samps[0];
+ for(unsigned int i = 0; i < d_frame_size; i++) {
+ if(d_samps[i] < minimum) minimum = d_samps[i];
+ if(d_samps[i] > maximum) maximum = d_samps[i];
+ }
+ minimum = get_clean_num(minimum);
+ maximum = get_clean_num(maximum);
+ if(minimum == maximum || minimum > maximum)
+ return; //useless data or screw up?
+ /* load the bins */
+ int index;
+ float bin_width = (maximum - minimum)/(d_num_bins-1);
+ for(unsigned int i = 0; i < d_sample_count; i++) {
+ index = boost::math::iround((d_samps[i] - minimum)/bin_width);
+ /* ensure the index range in case a small floating point error is involed */
+ if(index < 0)
+ index = 0;
+ if(index >= (int)d_num_bins)
+ index = d_num_bins-1;
+ d_bins[index]++;
+ }
+ /* Build a message to hold the output records */
+ gr_message_sptr msg = gr_make_message(0, minimum, maximum, d_num_bins*sizeof(float));
+ float *out = (float *)msg->msg(); // get pointer to raw message buffer
+ /* normalize the bins and put into message */
+ for(unsigned int i = 0; i < d_num_bins; i++) {
+ out[i] = ((float)d_bins[i])/d_frame_size;
+ }
+ /* send the message */
+ d_msgq->handle(msg);
+ }
+
+ void
+ histo_sink_f_impl::clear(void)
+ {
+ d_sample_count = 0;
+ /* zero the bins */
+ for(unsigned int i = 0; i < d_num_bins; i++) {
+ d_bins[i] = 0;
+ }
+ }
+
+ /**************************************************
+ * Getters
+ **************************************************/
+ unsigned int
+ histo_sink_f_impl::get_frame_size(void)
+ {
+ return d_frame_size;
+ }
+
+ unsigned int
+ histo_sink_f_impl::get_num_bins(void)
+ {
+ return d_num_bins;
+ }
+
+ /**************************************************
+ * Setters
+ **************************************************/
+ void
+ histo_sink_f_impl::set_frame_size(unsigned int frame_size)
+ {
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ d_frame_size = frame_size;
+ /* allocate a new sample array */
+ delete [] d_samps;
+ d_samps = new float[d_frame_size];
+ clear();
+ }
+
+ void
+ histo_sink_f_impl::set_num_bins(unsigned int num_bins) {
+ gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+ d_num_bins = num_bins;
+ /* allocate a new bin array */
+ delete [] d_bins;
+ d_bins = new unsigned int[d_num_bins];
+ clear();
+ }
+
+ } /* namespace wxgui */
+} /* namespace gr */
diff --git a/gr-wxgui/lib/histo_sink_f_impl.h b/gr-wxgui/lib/histo_sink_f_impl.h
new file mode 100644
index 0000000000..98b0fe6706
--- /dev/null
+++ b/gr-wxgui/lib/histo_sink_f_impl.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_HISTO_SINK_F_IMPL_H
+#define INCLUDED_GR_HISTO_SINK_F_IMPL_H
+
+#include <wxgui/histo_sink_f.h>
+
+namespace gr {
+ namespace wxgui {
+
+ class histo_sink_f_impl : public histo_sink_f
+ {
+ private:
+ gr_msg_queue_sptr d_msgq;
+ unsigned int d_num_bins;
+ unsigned int d_frame_size;
+ unsigned int d_sample_count;
+ unsigned int *d_bins;
+ float *d_samps;
+ gr::thread::mutex d_mutex;
+
+ void send_frame(void);
+ void clear(void);
+
+ public:
+ histo_sink_f_impl(gr_msg_queue_sptr msgq);
+ ~histo_sink_f_impl(void);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ unsigned int get_frame_size(void);
+ unsigned int get_num_bins(void);
+
+ void set_frame_size(unsigned int frame_size);
+ void set_num_bins(unsigned int num_bins);
+ };
+
+ } /* namespace wxgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_HISTO_SINK_F_IMPL_H */
diff --git a/gr-wxgui/lib/oscope_guts.cc b/gr-wxgui/lib/oscope_guts.cc
new file mode 100644
index 0000000000..3d1f085a6f
--- /dev/null
+++ b/gr-wxgui/lib/oscope_guts.cc
@@ -0,0 +1,439 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2005,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <wxgui/oscope_guts.h>
+#include <stdexcept>
+#include <stdio.h>
+#include <algorithm>
+#include <unistd.h>
+#include <math.h>
+#include <assert.h>
+
+namespace gr {
+ namespace wxgui {
+
+ /*
+ * Bad performance if it's large, and flaky triggering if it's too small
+ */
+ static const int OUTPUT_RECORD_SIZE = 1024; // Must be power of 2
+
+ /*
+ * For (slow-updated) STRIPCHART triggering, we make the record
+ * size larger, since we potentially want to be able to "see"
+ * hours of data. This works as long as the update rates to a
+ * STRIPCHART are low, which they generally are--that's rather
+ * what a stripchart is all about!
+ */
+ static const int SCHART_MULT = 8;
+
+
+ static inline int
+ wrap_bi(int buffer_index, int mx) // wrap buffer index
+ {
+ return buffer_index & (mx - 1);
+ }
+
+ static inline int
+ incr_bi(int buffer_index, int mx) // increment buffer index
+ {
+ return wrap_bi(buffer_index + 1, mx);
+ }
+
+ static inline int
+ decr_bi(int buffer_index, int mx) // decrement buffer index
+ {
+ return wrap_bi(buffer_index - 1, mx);
+ }
+
+ oscope_guts::oscope_guts(double sample_rate, gr_msg_queue_sptr msgq)
+ : d_nchannels(1),
+ d_msgq(msgq),
+ d_trigger_mode(TRIG_MODE_AUTO),
+ d_trigger_slope(TRIG_SLOPE_POS),
+ d_trigger_channel(0),
+ d_sample_rate(sample_rate),
+ d_update_rate(20),
+ d_trigger_level(0),
+ d_obi(0),
+ d_state(HOLD_OFF),
+ d_decimator_count(0),
+ d_decimator_count_init(1),
+ d_hold_off_count(0),
+ d_hold_off_count_init(OUTPUT_RECORD_SIZE/2-1),
+ d_pre_trigger_count(0),
+ d_post_trigger_count(0),
+ d_post_trigger_count_init(OUTPUT_RECORD_SIZE/2)
+ {
+ for(int i = 0; i < MAX_CHANNELS; i++)
+ d_buffer[i] = 0;
+
+ for(int i = 0; i < MAX_CHANNELS; i++) {
+ d_buffer[i] = new float[OUTPUT_RECORD_SIZE*SCHART_MULT];
+ for(int j = 0; j < OUTPUT_RECORD_SIZE*SCHART_MULT; j++)
+ d_buffer[i][j] = 0.0;
+ }
+
+ // be sure buffer is full before first write
+ enter_hold_off();
+ update_rate_or_decimation_changed();
+ }
+
+ oscope_guts::~oscope_guts()
+ {
+ for(int i = 0; i < MAX_CHANNELS; i++)
+ delete [] d_buffer[i];
+ }
+
+ // MANIPULATORS
+ void
+ oscope_guts::process_sample(const float *channel_data)
+ {
+ d_decimator_count--;
+ if(d_decimator_count > 0)
+ return;
+
+ d_decimator_count = d_decimator_count_init;
+
+ if(d_trigger_mode != TRIG_MODE_STRIPCHART) {
+ for(int i = 0; i < d_nchannels; i++)
+ d_buffer[i][d_obi] = channel_data[i]; // copy data into buffer
+
+ switch(d_state) {
+ case HOLD_OFF:
+ d_hold_off_count--;
+ if(d_hold_off_count <= 0)
+ enter_look_for_trigger ();
+ break;
+
+ case LOOK_FOR_TRIGGER:
+ if(found_trigger())
+ enter_post_trigger();
+ break;
+
+ case POST_TRIGGER:
+ d_post_trigger_count--;
+ if(d_post_trigger_count <= 0) {
+ write_output_records();
+ enter_hold_off();
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ d_obi = incr_bi(d_obi, OUTPUT_RECORD_SIZE);
+ }
+ else {
+ for(int i = 0; i < d_nchannels; i++) {
+ for(int j = (OUTPUT_RECORD_SIZE*SCHART_MULT)-1; j > 0; j--) {
+ d_buffer[i][j] = d_buffer[i][j-1];
+ }
+ d_buffer[i][0] = channel_data[i];
+ }
+ d_trigger_off = 0;
+ write_output_records();
+ }
+ }
+
+ /*
+ * Functions called on state entry
+ */
+
+ void
+ oscope_guts::enter_hold_off()
+ {
+ d_state = HOLD_OFF;
+ d_hold_off_count = d_hold_off_count_init;
+ }
+
+ void
+ oscope_guts::enter_look_for_trigger()
+ {
+ d_pre_trigger_count = 0;
+ d_state = LOOK_FOR_TRIGGER;
+ }
+
+ void
+ oscope_guts::enter_post_trigger()
+ {
+ d_state = POST_TRIGGER;
+ d_post_trigger_count = d_post_trigger_count_init;
+ //ensure that the trigger offset is no more than than half a sample
+ if(d_trigger_off > .5)
+ d_trigger_off -= 1;
+ else
+ d_post_trigger_count--;
+ }
+
+ // ----------------------------------------------------------------
+ // returns true if trigger found
+
+ bool
+ oscope_guts::found_trigger()
+ {
+ int mx = d_trigger_mode == TRIG_MODE_STRIPCHART ? OUTPUT_RECORD_SIZE*SCHART_MULT :
+ OUTPUT_RECORD_SIZE;
+
+ float prev_sample = d_buffer[d_trigger_channel][decr_bi(d_obi, mx)];
+ float new_sample = d_buffer[d_trigger_channel][d_obi];
+
+ switch(d_trigger_mode) {
+
+ case TRIG_MODE_AUTO: //too many samples without a trigger
+ d_pre_trigger_count++;
+ if(d_pre_trigger_count > OUTPUT_RECORD_SIZE/2)
+ return true;
+
+ case TRIG_MODE_NORM: //look for trigger
+ switch(d_trigger_slope) {
+
+ case TRIG_SLOPE_POS: //trigger point in pos slope?
+ if(new_sample < d_trigger_level || prev_sample >= d_trigger_level)
+ return false;
+ break;
+
+ case TRIG_SLOPE_NEG: //trigger point in neg slope?
+ if(new_sample > d_trigger_level || prev_sample <= d_trigger_level)
+ return false;
+ break;
+ }
+
+ //calculate the trigger offset in % sample
+ d_trigger_off = (d_trigger_level - prev_sample)/(new_sample - prev_sample);
+ return true;
+
+ case TRIG_MODE_FREE: //free run mode, always trigger
+ d_trigger_off = 0;
+ return true;
+
+ default:
+ assert(0);
+ return false;
+ }
+ }
+
+ // ----------------------------------------------------------------
+ // write output records (duh!)
+
+ void
+ oscope_guts::write_output_records()
+ {
+ int mx;
+
+ mx = d_trigger_mode == TRIG_MODE_STRIPCHART ?
+ OUTPUT_RECORD_SIZE*SCHART_MULT : OUTPUT_RECORD_SIZE;
+
+ // if the output queue if full, drop the data like its hot.
+ if(d_msgq->full_p())
+ return;
+ // Build a message to hold the output records
+ gr_message_sptr msg =
+ gr_make_message(0, // msg type
+ d_nchannels, // arg1 for other side
+ mx, // arg2 for other side
+ ((d_nchannels * mx) + 1) * sizeof(float)); // sizeof payload
+
+ float *out = (float *)msg->msg(); // get pointer to raw message buffer
+
+ for(int ch = 0; ch < d_nchannels; ch++) {
+ // note that d_obi + 1 points at the oldest sample in the buffer
+ for(int i = 0; i < mx; i++) {
+ out[i] = d_buffer[ch][wrap_bi(d_obi + 1 + i, mx)];
+ }
+ out += mx;
+ }
+ //Set the last sample as the trigger offset:
+ // The non gl scope sink will not look at this last sample.
+ // The gl scope sink will use this last sample as an offset.
+ out[0] = d_trigger_off;
+ d_msgq->handle(msg); // send the msg
+ }
+
+ // ----------------------------------------------------------------
+
+ bool
+ oscope_guts::set_update_rate(double update_rate)
+ {
+ d_update_rate = std::min(std::max (1./10., update_rate), d_sample_rate);
+ update_rate_or_decimation_changed();
+ return true;
+ }
+
+ bool
+ oscope_guts::set_decimation_count(int decimator_count)
+ {
+ decimator_count = std::max(1, decimator_count);
+ d_decimator_count_init = decimator_count;
+ update_rate_or_decimation_changed();
+ return true;
+ }
+
+ bool
+ oscope_guts::set_sample_rate(double sample_rate)
+ {
+ d_sample_rate = sample_rate;
+ return set_update_rate(update_rate());
+ }
+
+ void
+ oscope_guts::update_rate_or_decimation_changed()
+ {
+ d_hold_off_count_init =
+ (int)rint(d_sample_rate / d_update_rate / d_decimator_count_init);
+ }
+
+ bool
+ oscope_guts::set_trigger_channel(int channel)
+ {
+ if(channel >= 0 && channel < d_nchannels) {
+ d_trigger_channel = channel;
+ trigger_changed ();
+ return true;
+ }
+
+ return false;
+ }
+
+ bool
+ oscope_guts::set_trigger_mode(trigger_mode mode)
+ {
+ d_trigger_mode = mode;
+ trigger_changed();
+ return true;
+ }
+
+ bool
+ oscope_guts::set_trigger_slope(trigger_slope slope)
+ {
+ d_trigger_slope = slope;
+ trigger_changed();
+ return true;
+ }
+
+ bool
+ oscope_guts::set_trigger_level(double trigger_level)
+ {
+ d_trigger_level = trigger_level;
+ trigger_changed();
+ return true;
+ }
+
+ bool
+ oscope_guts::set_trigger_level_auto()
+ {
+ // find the level 1/2 way between the min and the max
+
+ float min_v = d_buffer[d_trigger_channel][0];
+ float max_v = d_buffer[d_trigger_channel][0];
+
+ for(int i = 1; i < OUTPUT_RECORD_SIZE; i++) {
+ min_v = std::min (min_v, d_buffer[d_trigger_channel][i]);
+ max_v = std::max (max_v, d_buffer[d_trigger_channel][i]);
+ }
+ return set_trigger_level((min_v + max_v) * 0.5);
+ }
+
+ bool
+ oscope_guts::set_num_channels(int nchannels)
+ {
+ if(nchannels > 0 && nchannels <= MAX_CHANNELS) {
+ d_nchannels = nchannels;
+ return true;
+ }
+ return false;
+ }
+
+ void
+ oscope_guts::trigger_changed()
+ {
+ enter_look_for_trigger();
+ }
+
+ // ACCESSORS
+
+ int
+ oscope_guts::num_channels() const
+ {
+ return d_nchannels;
+ }
+
+ double
+ oscope_guts::sample_rate() const
+ {
+ return d_sample_rate;
+ }
+
+ double
+ oscope_guts::update_rate() const
+ {
+ return d_update_rate;
+ }
+
+ int
+ oscope_guts::get_decimation_count() const
+ {
+ return d_decimator_count_init;
+ }
+
+ int
+ oscope_guts::get_trigger_channel() const
+ {
+ return d_trigger_channel;
+ }
+
+ trigger_mode
+ oscope_guts::get_trigger_mode() const
+ {
+ return d_trigger_mode;
+ }
+
+ trigger_slope
+ oscope_guts::get_trigger_slope() const
+ {
+ return d_trigger_slope;
+ }
+
+ double
+ oscope_guts::get_trigger_level() const
+ {
+ return d_trigger_level;
+ }
+
+ int
+ oscope_guts::get_samples_per_output_record() const
+ {
+ int mx;
+
+ mx = OUTPUT_RECORD_SIZE;
+ if(d_trigger_mode == TRIG_MODE_STRIPCHART) {
+ mx = OUTPUT_RECORD_SIZE*SCHART_MULT;
+ }
+ return mx;
+ }
+
+ } /* namespace wxgui */
+} /* namespace gr */
diff --git a/gr-wxgui/lib/oscope_sink_f_impl.cc b/gr-wxgui/lib/oscope_sink_f_impl.cc
new file mode 100644
index 0000000000..5e578cb8e3
--- /dev/null
+++ b/gr-wxgui/lib/oscope_sink_f_impl.cc
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003-2005,2010,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "oscope_sink_f_impl.h"
+#include <wxgui/oscope_sink_x.h>
+#include <wxgui/oscope_guts.h>
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace wxgui {
+
+ oscope_sink_f::sptr
+ oscope_sink_f::make(double sampling_rate, gr_msg_queue_sptr msgq)
+ {
+ return gnuradio::get_initial_sptr
+ (new oscope_sink_f_impl(sampling_rate, msgq));
+ }
+
+ oscope_sink_f_impl::oscope_sink_f_impl(double sampling_rate, gr_msg_queue_sptr msgq)
+ : oscope_sink_x("oscope_sink_f",
+ gr_make_io_signature(1, oscope_guts::MAX_CHANNELS,
+ sizeof(float)),
+ sampling_rate),
+ d_msgq(msgq)
+ {
+ d_guts = new oscope_guts(d_sampling_rate, d_msgq);
+ }
+
+ oscope_sink_f_impl::~oscope_sink_f_impl()
+ {
+ }
+
+ bool
+ oscope_sink_f_impl::check_topology(int ninputs, int noutputs)
+ {
+ return d_guts->set_num_channels(ninputs);
+ }
+
+ int
+ oscope_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ int ni = input_items.size();
+ float tmp[oscope_guts::MAX_CHANNELS];
+
+ for(int i = 0; i < noutput_items; i++) {
+
+ // FIXME for now, copy the data. Fix later if reqd
+ for(int ch = 0; ch < ni; ch++)
+ tmp[ch] = ((const float*)input_items[ch])[i];
+
+ d_guts->process_sample(tmp);
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace wxgui */
+} /* namespace gr */
diff --git a/gr-wxgui/lib/oscope_sink_f_impl.h b/gr-wxgui/lib/oscope_sink_f_impl.h
new file mode 100644
index 0000000000..6ad28a885f
--- /dev/null
+++ b/gr-wxgui/lib/oscope_sink_f_impl.h
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003-2005,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_OSCOPE_SINK_F_IMPL_H
+#define INCLUDED_GR_OSCOPE_SINK_F_IMPL_H
+
+#include <wxgui/oscope_sink_f.h>
+
+namespace gr {
+ namespace wxgui {
+
+ class oscope_sink_f_impl : public oscope_sink_f
+ {
+ private:
+ gr_msg_queue_sptr d_msgq;
+
+ public:
+ oscope_sink_f_impl(double sampling_rate, gr_msg_queue_sptr msgq);
+ ~oscope_sink_f_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace wxgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_OSCOPE_SINK_F_IMPL_H */
+
diff --git a/gr-wxgui/lib/oscope_sink_x.cc b/gr-wxgui/lib/oscope_sink_x.cc
new file mode 100644
index 0000000000..417442979c
--- /dev/null
+++ b/gr-wxgui/lib/oscope_sink_x.cc
@@ -0,0 +1,161 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <wxgui/oscope_sink_x.h>
+#include <wxgui/oscope_guts.h>
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace wxgui {
+
+ oscope_sink_x::oscope_sink_x(const std::string name,
+ gr_io_signature_sptr input_sig,
+ double sampling_rate)
+ : gr_sync_block(name, input_sig,
+ gr_make_io_signature(0, 0, 0)),
+ d_sampling_rate(sampling_rate), d_guts(0)
+ {
+ }
+
+ oscope_sink_x::~oscope_sink_x()
+ {
+ delete d_guts;
+ }
+
+ // ----------------------------------------------------------------
+
+ bool
+ oscope_sink_x::set_update_rate(double update_rate)
+ {
+ return d_guts->set_update_rate(update_rate);
+ }
+
+ bool
+ oscope_sink_x::set_decimation_count(int decimation_count)
+ {
+ return d_guts->set_decimation_count(decimation_count);
+ }
+
+ bool
+ oscope_sink_x::set_trigger_channel(int channel)
+ {
+ return d_guts->set_trigger_channel(channel);
+ }
+
+ bool
+ oscope_sink_x::set_trigger_mode(trigger_mode mode)
+ {
+ return d_guts->set_trigger_mode(mode);
+ }
+
+ bool
+ oscope_sink_x::set_trigger_slope(trigger_slope slope)
+ {
+ return d_guts->set_trigger_slope(slope);
+ }
+
+ bool
+ oscope_sink_x::set_trigger_level(double trigger_level)
+ {
+ return d_guts->set_trigger_level(trigger_level);
+ }
+
+ bool
+ oscope_sink_x::set_trigger_level_auto()
+ {
+ return d_guts->set_trigger_level_auto();
+ }
+
+ bool
+ oscope_sink_x::set_sample_rate(double sample_rate)
+ {
+ return d_guts->set_sample_rate(sample_rate);
+ }
+
+ bool
+ oscope_sink_x::set_num_channels(int nchannels)
+ {
+ return d_guts->set_num_channels(nchannels);
+ }
+
+ // ACCESSORS
+
+ int
+ oscope_sink_x::num_channels() const
+ {
+ return d_guts->num_channels();
+ }
+
+ double
+ oscope_sink_x::sample_rate() const
+ {
+ return d_guts->sample_rate();
+ }
+
+ double
+ oscope_sink_x::update_rate() const
+ {
+ return d_guts->update_rate();
+ }
+
+ int
+ oscope_sink_x::get_decimation_count() const
+ {
+ return d_guts->get_decimation_count();
+ }
+
+ int
+ oscope_sink_x::get_trigger_channel() const
+ {
+ return d_guts->get_trigger_channel();
+ }
+
+ trigger_mode
+ oscope_sink_x::get_trigger_mode() const
+ {
+ return d_guts->get_trigger_mode();
+ }
+
+ trigger_slope
+ oscope_sink_x::get_trigger_slope() const
+ {
+ return d_guts->get_trigger_slope();
+ }
+
+ double
+ oscope_sink_x::get_trigger_level() const
+ {
+ return d_guts->get_trigger_level();
+ }
+
+ int
+ oscope_sink_x::get_samples_per_output_record() const
+ {
+ return d_guts->get_samples_per_output_record();
+ }
+
+ } /* namespace wxgui */
+} /* namespace gr */