diff options
Diffstat (limited to 'gr-msdd6000')
-rw-r--r-- | gr-msdd6000/AUTHORS | 3 | ||||
-rw-r--r-- | gr-msdd6000/Makefile.am | 25 | ||||
-rw-r--r-- | gr-msdd6000/doc/Softronics_Ltd_msdd6000_BlockDiagram.pdf | bin | 0 -> 43889 bytes | |||
-rw-r--r-- | gr-msdd6000/src/Makefile.am | 22 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/Makefile.am | 117 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd.i | 254 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_buffer_copy_behaviors.h | 59 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_base.cc | 817 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_base.h | 307 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_c.cc | 111 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_c.h | 79 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_s.cc | 130 | ||||
-rw-r--r-- | gr-msdd6000/src/lib/msdd_source_s.h | 87 | ||||
-rw-r--r-- | gr-msdd6000/src/python/Makefile.am | 48 | ||||
-rwxr-xr-x | gr-msdd6000/src/python/qa_msdd6000.py | 40 | ||||
-rw-r--r-- | gr-msdd6000/src/python/run_tests.in | 10 | ||||
-rwxr-xr-x | gr-msdd6000/src/python/test_tcp.py | 78 | ||||
-rwxr-xr-x | gr-msdd6000/src/python/test_udp.py | 40 | ||||
-rwxr-xr-x | gr-msdd6000/src/python_test/test_tcp.py | 78 | ||||
-rwxr-xr-x | gr-msdd6000/src/python_test/test_udp.py | 40 |
20 files changed, 2345 insertions, 0 deletions
diff --git a/gr-msdd6000/AUTHORS b/gr-msdd6000/AUTHORS new file mode 100644 index 000000000..683b38b54 --- /dev/null +++ b/gr-msdd6000/AUTHORS @@ -0,0 +1,3 @@ +Charles Clancy +Nate Goergen +n4hy (Bob McGwier) diff --git a/gr-msdd6000/Makefile.am b/gr-msdd6000/Makefile.am new file mode 100644 index 000000000..73f418edc --- /dev/null +++ b/gr-msdd6000/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2008 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 2, 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 $(top_srcdir)/Makefile.common + +SUBDIRS = src + diff --git a/gr-msdd6000/doc/Softronics_Ltd_msdd6000_BlockDiagram.pdf b/gr-msdd6000/doc/Softronics_Ltd_msdd6000_BlockDiagram.pdf Binary files differnew file mode 100644 index 000000000..34356da75 --- /dev/null +++ b/gr-msdd6000/doc/Softronics_Ltd_msdd6000_BlockDiagram.pdf diff --git a/gr-msdd6000/src/Makefile.am b/gr-msdd6000/src/Makefile.am new file mode 100644 index 000000000..923b1c25a --- /dev/null +++ b/gr-msdd6000/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004,2005,2006 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 2, 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. +# + +SUBDIRS = lib python diff --git a/gr-msdd6000/src/lib/Makefile.am b/gr-msdd6000/src/lib/Makefile.am new file mode 100644 index 000000000..00018902b --- /dev/null +++ b/gr-msdd6000/src/lib/Makefile.am @@ -0,0 +1,117 @@ +# +# Copyright 2008 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 2, 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 $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.msdd module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(PYTHON_CPPFLAGS) \ + $(WITH_INCLUDES) \ + $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libmsdd.la + +libmsdd_la_SOURCES = \ + msdd_source_base.cc \ + msdd_source_c.cc \ + msdd_source_s.cc + +# ------------------------------------------------------------------------ +# This is the swig-ish part of the Makefile. +# It builds the msdd module which we'll load into python +# ------------------------------------------------------------------------ + +SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) \ + $(STD_DEFINES_AND_INCLUDES) $(WITH_SWIG_INCLUDES) $(WITH_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +LOCAL_IFILES = \ + $(top_srcdir)/gr-msdd6000/src/lib/msdd.i + + +# These files are built by SWIG. The first is the C++ glue. +# # The second is the python wrapper that loads the _msdd shared library +# # and knows how to call our extensions. +# +# +# +swig_built_sources = \ + msdd.cc \ + msdd.py + +# This gets msdd.py installed in the right place +# +ourpython_PYTHON = \ + msdd.py + + +ourlib_LTLIBRARIES = _msdd.la + +# These are the source files that go into the shared library +_msdd_la_SOURCES = \ + msdd.cc + +# magic flag +_msdd_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library + +_msdd_la_LIBADD = \ + $(GNURADIO_CORE_LA) \ + $(PYTHON_LDFLAGS) \ + libmsdd.la \ + -lstdc++ + +msdd.cc msdd.py: msdd.i $(ALL_FILES) + $(SWIG) $(SWIGCPPPYTHONARGS) -module msdd -o msdd.cc $(LOCAL_IFILES) + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + msdd_buffer_copy_behaviors.h \ + msdd_source_base.h \ + msdd_source_c.h \ + msdd_source_s.h + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc *~ + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/gr-msdd6000/src/lib/msdd.i b/gr-msdd6000/src/lib/msdd.i new file mode 100644 index 000000000..809445c69 --- /dev/null +++ b/gr-msdd6000/src/lib/msdd.i @@ -0,0 +1,254 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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. + */ + +%feature("autodoc", "1"); // generate python docstrings + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ + +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include <stdexcept> +#include "msdd_source_s.h" +#include "msdd_source_c.h" +%} + +// ================================================================ +// abstract classes +// ================================================================ + +// ---------------------------------------------------------------- + +class msdd_source_base : public gr_sync_block { + + protected: + msdd_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + msdd_source_base::msdd_command_type_t opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + /*! + * \brief return number of msdd input bytes required to produce noutput items. + */ + int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; + + /*! + * \brief number of bytes in a low-level sample + */ + unsigned int sizeof_basic_sample() const; + + /*! + * \brief convert between native msdd format and output item format + * + * \param output_items[out] stream(s) of output items + * \param output_index[in] starting index in output_items + * \param output_items_available[in] number of empty items available at item[index] + * \param output_items_produced[out] number of items produced by copy + * \param msdd_buffer[in] source buffer + * \param msdd_buffer_length[in] number of bytes available in \p msdd_buffer + * \param bytes_read[out] number of bytes read from \p msdd_buffer + * + * The copy must consume all bytes available. That is, \p bytes_read must equal + * \p msdd_buffer_length. + */ + virtual void copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int msdd_buffer_length, + int &bytes_read) = 0; + + int readsock(int sockfd, unsigned char* buf, int nbytes); + + void* make_request_packet(unsigned int& size, unsigned int number_samples); + + public: + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + ~msdd_source_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool start(); + bool stop(); + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which D/A [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. + * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain in dB. + * + * \param which which D/A [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + /*! + * \brief open a socket specified by the port and ip address info + * + * Opens a socket, binds to the address, and waits for a connection + * over UDP. If any of these fail, the fuction retuns the error and exits. + */ + bool open(); + + /*! + * \brief Close current socket. + * + * Shuts down read/write on the socket + */ + bool close(); + + /*! + * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () + */ + bool set_decim_rate (unsigned int rate); + + /*! + * \brief set the center frequency of the digital down converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-FIXME, FIXME]. The frequency specified is + * quantized. Use rx_freq to retrieve the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + void set_verbose (bool verbose); + + // ACCESSORS + + unsigned int decim_rate () const; + double rx_freq (int channel) const; + int noverruns () const { return d_noverruns; } + + /*! + * \brief return the msdd's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + bool set_desired_packet_size (int which, unsigned long packet_size); + + unsigned long desired_packet_size (int which) const; + +}; + + +// ================================================================ +// concrete sources +// ================================================================ + + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(msdd,source_s) + +msdd_source_s_sptr +msdd_make_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + +class msdd_source_s : public msdd_source_base { +protected: + msdd_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items); + +public: + ~msdd_source_s (); +}; + + +GR_SWIG_BLOCK_MAGIC(msdd,source_c) + +msdd_source_c_sptr +msdd_make_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + +class msdd_source_c : public msdd_source_base { +protected: + msdd_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items); + +public: + ~msdd_source_c (); +}; diff --git a/gr-msdd6000/src/lib/msdd_buffer_copy_behaviors.h b/gr-msdd6000/src/lib/msdd_buffer_copy_behaviors.h new file mode 100644 index 000000000..26cf24587 --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_buffer_copy_behaviors.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 MSDD_BUFFER_COPY_BEHAVIORS_H_ +#define MSDD_BUFFER_COPY_BEHAVIORS_H_ + +namespace msdd { + + class BufferCopyBehavior + { + public: + virtual void operator() (gr_vector_void_star &a, const void * b, unsigned int output_index, unsigned int nitems) = 0; + virtual ~BufferCopyBehavior() {}; + }; + + template <class Tin, class Tout> + class BufferCopyBehaviorGeneric : public BufferCopyBehavior { + void operator() (gr_vector_void_star &a, const void * b, unsigned int output_index, unsigned int nitems) { + Tout *out(&(reinterpret_cast<Tout *>(a[0]))[output_index]); // sloppy + const Tin *in(reinterpret_cast<const Tin *>(b)); // equisloppy + + for (unsigned int i = 0; i < nitems; ++i) { + out[i] = in[i]; + } + } + }; + + template <class Tin> + class BufferCopyBehaviorComplex : public BufferCopyBehavior { + void operator() (gr_vector_void_star &a, const void * b, unsigned int output_index, unsigned int nitems) { + gr_complex *out(&(reinterpret_cast<gr_complex *>(a[0]))[output_index]); // sloppy + const Tin *in(reinterpret_cast<const Tin *>(b)); // equisloppy + + for (unsigned int i = 0; i < nitems; ++i) { + out[i] = gr_complex (in[4*i+1],in[4*i+3]); + } + } + }; +} + +#endif /*MSDD_BUFFER_COPY_BEHAVIORS_H_*/ diff --git a/gr-msdd6000/src/lib/msdd_source_base.cc b/gr-msdd6000/src/lib/msdd_source_base.cc new file mode 100644 index 000000000..d9cb03e12 --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_base.cc @@ -0,0 +1,817 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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. + */ + +//#define MSDD_DEBUG_TRUE +//#define MSDD_DEBUG2_TRUE + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <msdd_source_base.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <netdb.h> +#include <omnithread.h> +#include <stdexcept> +#include <sys/socket.h> +#include <arpa/inet.h> + +#ifdef MSDD_DEBUG_TRUE +#include <iostream> +#define MSDD_DEBUG(x) std::cout << x << std::endl; +#else +#define MSDD_DEBUG(x) +#endif + + +#ifdef MSDD_DEBUG2_TRUE +#include <iostream> +#define MSDD_DEBUG2(x) std::cout << x << std::endl; +#else +#define MSDD_DEBUG2(x) +#endif + +#include <iostream> + +namespace { + const int OUTPUT_MAX((1 << 15)*8); + const double PGA_MAX(75); + const double PGA_MIN(10); + const double PGA_STEP(.5); + const double DEFAULT_RX_FREQ(2.417e6); + const double DEFAULT_GAIN(32); + const msdd_source_base::msdd_fft_mode_t DEFAULT_FFT_MODE(msdd_source_base::MODE_MAG); + const msdd_source_base::msdd_fft_points_t DEFAULT_FFT_POINTS(msdd_source_base::S8192); + const msdd_source_base::msdd_decimation_t DEFAULT_DECIMATION_RATE(msdd_source_base::D2); +} + +class msdd_source_base::Impl { + +public: + Impl(int opp_mode) : + d_noverruns (0), + d_deci_rate (DEFAULT_DECIMATION_RATE), + d_rx_freq ((unsigned long) DEFAULT_RX_FREQ), + d_gain(DEFAULT_GAIN), + d_verbose (false), + d_updated(false), + d_msdd_command_type((msdd_command_type_t) opp_mode), + d_msdd_fft_mode(DEFAULT_FFT_MODE), + d_desired_sample_size(2^15), + d_fft_points (DEFAULT_FFT_POINTS) + { + } + + int d_noverruns; + msdd_decimation_t d_deci_rate; + unsigned long d_rx_freq; + double d_gain; + bool d_verbose; + bool d_updated; + msdd_command_type_t d_msdd_command_type; + msdd_fft_mode_t d_msdd_fft_mode; + unsigned long d_desired_sample_size; + + int d_socket; // handle to socket + int d_socket_rcv; // handle to socket retuned in the accept call + struct in_addr d_ip_src; // store the source IP address to use + unsigned short d_port_src; // the port number to open for connections to this service + sockaddr_in d_sockaddr_src; // store the source sockaddr data (formatted IP address and port number) + std::auto_ptr<unsigned char> d_temp_buff; // hold buffer between calls + + omni_mutex d_mutex; + msdd_fft_points_t d_fft_points; + + struct msdd_request_fft_packet { + msdd_command_type_t command_type; + int foo_x20; + unsigned int center_freq_mhz; + int offset_freq_hz; + int gain; + msdd_fft_window_type_t window_type; + msdd_fft_points_t fft_points; + msdd_decimation_t decimation; + msdd_fft_mode_t fft_mode; + int number_sets; + } __attribute__((__packed__)); + + struct msdd_request_iq_packet { + msdd_command_type_t command_type; + int foo0x18; + unsigned int center_freq_mhz; + int offset_freq_hz; + int gain; + int number; + msdd_decimation_t decimation; + int number_sets; + } __attribute__((__packed__)); + + void make_request_fft_packet(msdd_request_fft_packet& packet); + + void make_request_iq_packet(msdd_request_iq_packet& packet, unsigned int number_samples); + + msdd_request_fft_packet d_fft_request_packet; // fft request packet + msdd_request_iq_packet d_iq_request_packet; // fft request packet +}; + + +msdd_source_base::msdd_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error) + : gr_sync_block (name, + gr_make_io_signature (0, 0, 0), + output_signature), + pimpl(new Impl(opp_mode)) +{ + int ret (0); + + // Set up the address stucture for the source address and port numbers + // Get the source IP address from the host name + struct hostent *hsrc (gethostbyname(src)); + + if(hsrc) { // if the source was provided as a host namex + pimpl->d_ip_src = *(struct in_addr*)hsrc->h_addr_list[0]; + } + else { // assume it was specified as an IP address + if((ret=inet_aton(src, &pimpl->d_ip_src)) == 0) { // format IP address + perror("Not a valid source IP address or host name"); + throw std::runtime_error("can't initialize source socket"); + } + } + + pimpl->d_port_src = htons(port_src); // format port number + + pimpl->d_sockaddr_src.sin_family = AF_INET; + pimpl->d_sockaddr_src.sin_addr = pimpl->d_ip_src; + pimpl->d_sockaddr_src.sin_port = pimpl->d_port_src; + + pimpl->d_temp_buff.reset(new unsigned char[OUTPUT_MAX + + std::max(sizeof(Impl::msdd_request_iq_packet), + sizeof(Impl::msdd_request_fft_packet))]); // allow it to hold up to payload_size bytes + + set_output_multiple (OUTPUT_MAX / output_signature->sizeof_stream_item (0)); +} + + +bool +msdd_source_base::open() +{ + omni_mutex_lock l(pimpl->d_mutex); // hold mutex for duration of this function + // create socket + MSDD_DEBUG2("MSDD: Before socket ") + pimpl->d_socket = socket(PF_INET, SOCK_STREAM, 0); + if(pimpl->d_socket == -1) { + perror("socket open"); + throw std::runtime_error("can't open socket"); + } + + // Turn on reuse address + int opt_val (1); + if(setsockopt(pimpl->d_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(int)) == -1) { + perror("SO_REUSEADDR"); + throw std::runtime_error("can't set socket option SO_REUSEADDR"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(pimpl->d_socket, SOL_SOCKET, SO_LINGER, (void*)&lngr, sizeof(linger)) == -1) { + perror("SO_LINGER"); + throw std::runtime_error("can't set socket option SO_LINGER"); + } + + // Set a timeout on the receive function to not block indefinitely + // This value can (and probably should) be changed + // timeval timeout; + // timeout.tv_sec = 1; + // timeout.tv_usec = 0; + // if(setsockopt(d_socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout)) == -1) { + // perror("SO_RCVTIMEO"); + // throw std::runtime_error("can't set socket option SO_RCVTIMEO"); + // } + + // bind socket to an address and port number to listen on + MSDD_DEBUG2("MSDD: Before socket bind to " << pimpl->d_sockaddr_src.sin_port) + if(::connect(pimpl->d_socket, (struct sockaddr*)&pimpl->d_sockaddr_src, sizeof(pimpl->d_sockaddr_src)) == -1) { + perror("socket bind"); + throw std::runtime_error("can't bind socket"); + } + + MSDD_DEBUG2("MSDD: Socket open") + pimpl->d_updated = true; + return pimpl->d_socket != 0; +} + +/* read n bytes from a socket descriptor */ +int +msdd_source_base::readsock(int sockfd, unsigned char* buf, int nbytes) { + int nleft (nbytes); + int nread (0); + + while (nleft > 0) { + MSDD_DEBUG2("MSDD: Before socket read: " << nleft) + if ((nread = ::read(sockfd, buf, nleft)) < 0) { + return(nread); /* error, nread < 0 */ + } else if (nread == 0) { + break; + } + + nleft -= nread; + buf += nread; + } + return(nbytes - nleft); +} + +bool +msdd_source_base::close() +{ + omni_mutex_lock l(pimpl->d_mutex); // hold mutex for duration of this function + + if (pimpl->d_socket){ + shutdown(pimpl->d_socket, SHUT_RDWR); + pimpl->d_socket = 0; + } + pimpl->d_updated = true; + + return true; +} + +msdd_source_base::~msdd_source_base () +{ + msdd_source_base::close(); +} + +unsigned int +msdd_source_base::sizeof_basic_sample() const +{ + switch (pimpl->d_msdd_command_type) { + case SAMPLES_REALTIME: + return 4; + case SAMPLES_FFT: + switch (pimpl->d_msdd_fft_mode) { + case MODE_IQ: + case MODE_MAG: + return 4; + case MODE_MAGDB: + return 1; + default: + assert (false); // bad mode + } + default: + assert (false); // bad mode + } +} + +bool +msdd_source_base::start() +{ + return msdd_source_base::open(); +} + +bool +msdd_source_base::stop() +{ + return msdd_source_base::close(); +} + +void* +msdd_source_base::make_request_packet(unsigned int& size, unsigned int number_samples) { + switch (pimpl->d_msdd_command_type) { + case SAMPLES_REALTIME: + pimpl->make_request_iq_packet(pimpl->d_iq_request_packet, number_samples); + size = sizeof (pimpl->d_iq_request_packet); + return &pimpl->d_iq_request_packet; + case SAMPLES_FFT: + pimpl->make_request_fft_packet(pimpl->d_fft_request_packet); + size = sizeof (pimpl->d_fft_request_packet); + return &pimpl->d_fft_request_packet; + default: + assert (false); // bad mode + } +} + +void +msdd_source_base::Impl::make_request_fft_packet(msdd_request_fft_packet& packet) +{ + packet.command_type = SAMPLES_FFT; // FFT samples Command + packet.foo_x20 = 0x20; + packet.center_freq_mhz = d_rx_freq; + packet.offset_freq_hz = 0; + packet.gain = (int) d_gain; // gain + packet.window_type = WINDOW_HANNING; // magic number + packet.fft_points = d_fft_points; + packet.decimation = d_deci_rate; + packet.fft_mode = MODE_MAGDB; + packet.number_sets = 1; +} + +void +msdd_source_base::Impl::make_request_iq_packet(msdd_request_iq_packet& packet, unsigned int number_samples) +{ + packet.command_type = SAMPLES_REALTIME; // FFT samples Command + packet.foo0x18 = 0x18; // magic number + packet.center_freq_mhz = d_rx_freq; + packet.offset_freq_hz = 0; + packet.gain = (int) d_gain; // gain + packet.number = number_samples * 4; + packet.decimation = d_deci_rate; + packet.number_sets = 1; +} + +int +msdd_source_base::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int output_index (0); + int output_items_produced; + int bytes_read; + + unsigned int packet_size; + + MSDD_DEBUG("MSDD: requested items: " << noutput_items) + int noutput_items_desired = std::min (noutput_items, (int) pimpl->d_desired_sample_size); + MSDD_DEBUG("MSDD: desired items: " << noutput_items_desired) + + while (output_index < noutput_items_desired){ + + int nbytes = (pimpl->d_msdd_command_type == SAMPLES_REALTIME) ? + ninput_bytes_reqd_for_noutput_items (noutput_items_desired - output_index) : + ninput_bytes_reqd_for_noutput_items (msdd_source_base::fft_points()); + + void* request_packet = msdd_source_base::make_request_packet(packet_size, noutput_items_desired); + + nbytes = std::min (nbytes, OUTPUT_MAX); + MSDD_DEBUG2("MSDD: payload sizes: nbytes1: " << nbytes ) + + // send request + int result_nbytes = ::write(pimpl->d_socket, request_packet, packet_size); + //assert (result_nbytes == sizeof(msdd_request_packet)); + + // receive ack + result_nbytes = ::read (pimpl->d_socket, (unsigned char*) request_packet, packet_size); + MSDD_DEBUG2("MSDD: response: " << result_nbytes) + //assert (result_nbytes == sizeof(msdd_request_packet)); + + // receive payload + result_nbytes = msdd_source_base::readsock (pimpl->d_socket, pimpl->d_temp_buff.get(), nbytes); + MSDD_DEBUG("MSDD: reading bytes: " << nbytes << " received: " << result_nbytes) + if (result_nbytes > (int) nbytes){ + // fprintf (stderr, "msdd_source: overrun\n"); + fputs ("uO", stderr); + pimpl->d_noverruns++; + result_nbytes = nbytes; // truncate + } + + if (result_nbytes < 0) // We've got a problem. Usually board unplugged or powered down. + return -1; // Indicate we're done. + + if (result_nbytes != nbytes){ // not really an error, but unexpected + fprintf (stderr, "msdd_source: short read. Expected %d, got %d\n", + nbytes, result_nbytes); + } + + copy_from_msdd_buffer (output_items, + output_index, + noutput_items_desired - output_index, // output_items_available + output_items_produced, // [out] + pimpl->d_temp_buff.get(), // usrp_buffer + result_nbytes, + bytes_read); // [out] + + output_index += output_items_produced; + + if (pimpl->d_msdd_command_type == SAMPLES_FFT) break; + } + + MSDD_DEBUG("MSDD: items produced: " << output_items_produced << " index: " << output_index) + + //assert(false); + return output_index; +} + + +bool +msdd_source_base::set_decim_rate (unsigned int rate) +{ + bool result (true); + switch (rate) { + case 1: + pimpl->d_deci_rate = D0; + break; + case 2: + pimpl->d_deci_rate = D1; + break; + case 4: + pimpl->d_deci_rate = D2; + break; + case 8: + pimpl->d_deci_rate = D3; + break; + case 16: + pimpl->d_deci_rate = D4; + break; + case 32: + pimpl->d_deci_rate = D5; + break; + case 64: + pimpl->d_deci_rate = D6; + break; + case 128: + pimpl->d_deci_rate = D7; + break; + case 256: + pimpl->d_deci_rate = D8; + break; + default: + result = false; + } + + return result; +} +// +//bool +//msdd_source_base::set_nchannels (int nchan) +//{ +// // return d_usrp->set_nchannels (nchan); +// return true; +//} +// +//bool +//msdd_source_base::set_mux (int mux) +//{ +// return d_usrp->set_mux (mux); +//} + +bool +msdd_source_base::set_rx_freq (int channel, double freq) +{ + assert (channel == 0); + bool result (false); + + if (freq >= 30e6 && freq <= 6e9) { + pimpl->d_rx_freq = (unsigned long) freq / 1000000; + result = true; + } + + return result; +} + + +unsigned long +msdd_source_base::set_fft_size (int channel, unsigned long fft_size) +{ + assert (channel == 1); + + switch (fft_size) { + case 256: + pimpl->d_fft_points = S256; + break; + case 512: + pimpl->d_fft_points = S512; + break; + case 1024: + pimpl->d_fft_points = S1024; + break; + case 2048: + pimpl->d_fft_points = S2048; + break; + case 4096: + pimpl->d_fft_points = S4096; + break; + case 8192: + pimpl->d_fft_points = S8192; + break; + case 16384: + pimpl->d_fft_points = S16384; + break; + case 32768: + pimpl->d_fft_points = S32768; + break; + } + + return msdd_source_base::fft_points(); +} + +// +//long +//msdd_source_base::fpga_master_clock_freq() const +//{ +// return d_usrp->fpga_master_clock_freq(); +//} +// +//long +//msdd_source_base::converter_rate() const +//{ +// // return d_usrp->converter_rate(); +// return 8; +//} + +unsigned int +msdd_source_base::decim_rate () const +{ + return 1 << pimpl->d_deci_rate; +} +// +//int +//msdd_source_base::nchannels () const +//{ +// return d_usrp->nchannels (); +//} +// +//int +//msdd_source_base::mux () const +//{ +// return d_usrp->mux (); +//} + +double +msdd_source_base::rx_freq (int channel) const +{ + assert (channel == 0); + + return pimpl->d_rx_freq; +} + +unsigned int +msdd_source_base::fft_points() const +{ + return (1 << pimpl->d_fft_points); +} + +int +msdd_source_base::noverruns () const +{ + return pimpl->d_noverruns; +} + +//bool +//msdd_source_base::set_fpga_mode (int mode) +//{ +// return d_usrp->set_fpga_mode (mode); +//} +// +//bool +//msdd_source_base::set_ddc_phase (int channel, int phase) +//{ +// return d_usrp->set_ddc_phase(channel, phase); +//} +// +//bool +//msdd_source_base::set_dc_offset_cl_enable(int bits, int mask) +//{ +// return d_usrp->set_dc_offset_cl_enable(bits, mask); +//} + +void +msdd_source_base::set_verbose (bool verbose) +{ + pimpl->d_verbose = verbose; +} +// +//bool +//msdd_source_base::write_aux_dac (int which_dboard, int which_dac, int value) +//{ +// return d_usrp->write_aux_dac (which_dboard, which_dac, value); +//} +// +//int +//msdd_source_base::read_aux_adc (int which_dboard, int which_adc) +//{ +// return d_usrp->read_aux_adc (which_dboard, which_adc); +//} +// +//bool +//msdd_source_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +//{ +// return d_usrp->write_eeprom (i2c_addr, eeprom_offset, buf); +//} +// +//std::string +//msdd_source_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) +//{ +// return d_usrp->read_eeprom (i2c_addr, eeprom_offset, len); +//} +// +//bool +//msdd_source_base::write_i2c (int i2c_addr, const std::string buf) +//{ +// return d_usrp->write_i2c (i2c_addr, buf); +//} +// +//std::string +//msdd_source_base::read_i2c (int i2c_addr, int len) +//{ +// return d_usrp->read_i2c (i2c_addr, len); +//} +// +bool +msdd_source_base::set_pga (int which, double gain) +{ + if (gain >= PGA_MIN & gain <= PGA_MAX) { + pimpl->d_gain = gain; + return true; + } + return false; +} + +double +msdd_source_base::pga (int which) const +{ + return pimpl->d_gain; +} + +double +msdd_source_base::pga_min () const +{ + return PGA_MIN; +} + +double +msdd_source_base::pga_max () const +{ + return PGA_MAX; +} + +double +msdd_source_base::pga_db_per_step () const +{ + return PGA_STEP; +} + +//int +//msdd_source_base::daughterboard_id (int which) const +//{ +// return d_usrp->daughterboard_id (which); +//} +// +// +//bool +//msdd_source_base::set_adc_offset (int which, int offset) +//{ +// return d_usrp->set_adc_offset (which, offset); +//} +// +//bool +//msdd_source_base::set_dac_offset (int which, int offset, int offset_pin) +//{ +// return d_usrp->set_dac_offset (which, offset, offset_pin); +//} +// +//bool +//msdd_source_base::set_adc_buffer_bypass (int which, bool bypass) +//{ +// return d_usrp->set_adc_buffer_bypass (which, bypass); +//} + +std::string +msdd_source_base::serial_number() +{ + return "SoftTronics MSDD 6000"; +} +// +//bool +//msdd_source_base::_write_oe (int which_dboard, int value, int mask) +//{ +// return d_usrp->_write_oe (which_dboard, value, mask); +//} +// +//bool +//msdd_source_base::write_io (int which_dboard, int value, int mask) +//{ +// return d_usrp->write_io (which_dboard, value, mask); +//} +// +//int +//msdd_source_base::read_io (int which_dboard) +//{ +// return d_usrp->read_io (which_dboard); +//} +// +// +// +// +//// internal routines... +// +//bool +//msdd_source_base::_write_fpga_reg (int regno, int value) +//{ +// return d_usrp->_write_fpga_reg (regno, value); +//} +// +//bool +//msdd_source_base::_write_fpga_reg_masked (int regno, int value, int mask) +//{ +// return d_usrp->_write_fpga_reg_masked (regno, value, mask); +//} +// +//int +//msdd_source_base::_read_fpga_reg (int regno) +//{ +// return d_usrp->_read_fpga_reg (regno); +//} +// +//bool +//msdd_source_base::_write_9862 (int which_codec, int regno, unsigned char value) +//{ +// return d_usrp->_write_9862 (which_codec, regno, value); +//} +// +//int +//msdd_source_base::_read_9862 (int which_codec, int regno) const +//{ +// return d_usrp->_read_9862 (which_codec, regno); +//} +// +//bool +//msdd_source_base::_write_spi (int optional_header, int enables, +// int format, std::string buf) +//{ +// return d_usrp->_write_spi (optional_header, enables, format, buf); +//} +// +//std::string +//msdd_source_base::_read_spi (int optional_header, int enables, int format, int len) +//{ +// return d_usrp->_read_spi (optional_header, enables, format, len); +//} +// +//bool +//msdd_source_base::set_format(unsigned int format) +//{ +// return d_usrp->set_format(format); +//} +// +//unsigned int +//msdd_source_base::format() const +//{ +// return d_usrp->format(); +//} +// +//unsigned int +//msdd_source_base::make_format(int width, int shift, bool want_q, bool bypass_halfband) +//{ +// return usrp_standard_rx::make_format(width, shift, want_q, bypass_halfband); +//} +// +//int +//msdd_source_base::format_width(unsigned int format) +//{ +// return usrp_standard_rx::format_width(format); +//} +// +//int +//msdd_source_base::format_shift(unsigned int format) +//{ +// return usrp_standard_rx::format_shift(format); +//} +// +//bool +//msdd_source_base::format_want_q(unsigned int format) +//{ +// return usrp_standard_rx::format_want_q(format); +//} +// +//bool +//msdd_source_base::format_bypass_halfband(unsigned int format) +//{ +// return usrp_standard_rx::format_bypass_halfband(format); +//} + +bool msdd_source_base::set_desired_packet_size (int which, unsigned long packet_size) { + bool result(false); + + if (pimpl->d_desired_sample_size < 2^32) { // FIXME: find maximum sample request for MSDD check if greater than + pimpl->d_desired_sample_size = packet_size; + } + return result; +} + +unsigned long msdd_source_base::desired_packet_size (int which) const { + return pimpl->d_desired_sample_size; +} diff --git a/gr-msdd6000/src/lib/msdd_source_base.h b/gr-msdd6000/src/lib/msdd_source_base.h new file mode 100644 index 000000000..4a5bde15a --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_base.h @@ -0,0 +1,307 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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_MSDD_SOURCE_BASE_H +#define INCLUDED_MSDD_SOURCE_BASE_H +#include <gr_sync_block.h> +#include <stdexcept> + +/*! + * \brief abstract interface to MSDD 6000 Softronics module Rx path (Rev 1) + */ + +class msdd_source_base : public gr_sync_block { +public: + enum msdd_command_type_t { + COMMAND_STATUS = 0, + SAMPLES_REALTIME = 1, + SAMPLES_FFT = 2, + }; + + enum msdd_fft_window_type_t { + WINDOW_RECTANGLE = 0, + WINDOW_HANNING = 1, + WINDOW_HAMMING = 2, + WINDOW_BLACKMAN = 3 + }; + + enum msdd_fft_mode_t { + MODE_IQ=0, + MODE_MAG=1, + MODE_MAGDB=2 + }; + + enum msdd_decimation_t { + D0=0, + D1=1, + D2=2, + D3=3, + D4=4, + D5=5, + D6=6, + D7=7, + D8=8 + }; + + enum msdd_fft_points_t { + S256=8, + S512=9, + S1024=10, + S2048=11, + S4096=12, + S8192=13, + S16384=14, + S32768=15 + }; + +private: + + class Impl; + friend class Impl; + std::auto_ptr<Impl> pimpl; + +protected: + + msdd_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + /*! + * \brief return number of msdd input bytes required to produce noutput items. + */ + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; + + /*! + * \brief number of bytes in a low-level sample + */ + unsigned int sizeof_basic_sample() const; + + virtual void copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int msdd_buffer_length, + int &bytes_read) = 0; + + int readsock(int sockfd, unsigned char* buf, int nbytes); + + void* make_request_packet(unsigned int& size, unsigned int number_samples); + + unsigned long set_fft_size (int channel, unsigned long fft_size); + +public: + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + ~msdd_source_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool start(); + bool stop(); + + /*! + * \brief open a socket specified by the port and ip address info + * + * Opens a socket, binds to the address, and waits for a connection + * over UDP. If any of these fail, the fuction retuns the error and exits. + */ + bool open(); + + /*! + * \brief Close current socket. + * + * Shuts down read/write on the socket + */ + bool close(); + + /*! + * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () + */ + bool set_decim_rate (unsigned int rate); + //bool set_nchannels (int nchan); + //bool set_mux (int mux); + + /*! + * \brief set the center frequency of the digital down converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-FIXME, FIXME]. The frequency specified is + * quantized. Use rx_freq to retrieve the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + /*! + * \brief + */ + bool set_opp_mode (int channel, msdd_command_type_t mode); + +// +// /*! +// * \brief set fpga special modes +// */ +// bool set_fpga_mode (int mode); + + void set_verbose (bool verbose); +// +// /*! +// * \brief Set the digital down converter phase register. +// * +// * \param channel which ddc channel [0, 3] +// * \param phase 32-bit integer phase value. +// */ +// bool set_ddc_phase(int channel, int phase); +// + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which A/D [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which which A/D [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA setting in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA setting in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + // ACCESSORS + +// long converter_rate() const; + + unsigned int decim_rate () const; +// int nchannels () const; +// int mux () const; + double rx_freq (int channel) const; + unsigned int fft_points() const; + int noverruns () const; + + /*! + * \brief return the msdd's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + +// /*! +// * \brief Enable/disable automatic DC offset removal control loop in FPGA +// * +// * \param bits which control loops to enable +// * \param mask which \p bits to pay attention to +// * +// * If the corresponding bit is set, enable the automatic DC +// * offset correction control loop. +// * +// * <pre> +// * The 4 low bits are significant: +// * +// * ADC0 = (1 << 0) +// * ADC1 = (1 << 1) +// * ADC2 = (1 << 2) +// * ADC3 = (1 << 3) +// * </pre> +// * +// * By default the control loop is enabled on all ADC's. +// */ +// bool set_dc_offset_cl_enable(int bits, int mask); + + /*! + * \brief Specify Rx data format. + * + * \param format format specifier + * + * Rx data format control register + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------+-+-+---------+-------+ + * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | + * +-----------------------------------------+-+-+---------+-------+ + * + * SHIFT specifies arithmetic right shift [0, 15] + * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) + * Q if set deliver both I & Q, else just I + * B if set bypass half-band filter. + * + * Right now the acceptable values are: + * + * B Q WIDTH SHIFT + * 0 1 16 0 + * 0 1 8 8 + * + * More valid combos to come. + * + * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + */ +// bool set_format(unsigned int format); + + /*! + * \brief return current format + */ +// unsigned int format () const; +// +// static unsigned int make_format(int width=16, int shift=0, +// bool want_q=true, bool bypass_halfband=false); +// static int format_width(unsigned int format); +// static int format_shift(unsigned int format); +// static bool format_want_q(unsigned int format); +// static bool format_bypass_halfband(unsigned int format); + + bool set_desired_packet_size (int which, unsigned long packet_size); + + unsigned long desired_packet_size (int which) const; +}; + +#endif /* INCLUDED_MSDD_SOURCE_BASE_H */ diff --git a/gr-msdd6000/src/lib/msdd_source_c.cc b/gr-msdd6000/src/lib/msdd_source_c.cc new file mode 100644 index 000000000..454d9d416 --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_c.cc @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 + +//#define MSDD_DEBUG2_TRUE + +#ifdef MSDD_DEBUG2_TRUE +#include <iostream> +#define MSDD_DEBUG2(x) std::cout << x << std::endl; +#else +#define MSDD_DEBUG2(x) +#endif + +#include <msdd_source_c.h> +#include <gr_io_signature.h> + +namespace { + static const int NBASIC_SAMPLES_PER_ITEM = 2; // I & Q +}; + +msdd_source_c_sptr +msdd_make_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error) +{ + return msdd_source_c_sptr (new msdd_source_c ( + which_board, + opp_mode, + src, + port_src + )); +} + +msdd_source_c::msdd_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error) + : msdd_source_base ("msdd_source_c", + gr_make_io_signature (1, 1, 2 * sizeof (int)), + which_board, opp_mode, src, port_src + ) +{ + + switch (sizeof_basic_sample()) { + case 4: + d_buffer_copy_behavior.reset( + new msdd::BufferCopyBehaviorComplex <short> ()); + break; + default: + assert(false); + } + +} + +msdd_source_c::~msdd_source_c () +{ +} + +int +msdd_source_c::ninput_bytes_reqd_for_noutput_items (int noutput_items) +{ + return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); +} + +/* + * Copy 8 bit fft from mdss buffer into output buffer + */ +void +msdd_source_c::copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int buffer_length, + int &bytes_read) +{ + unsigned nmsdd_bytes_per_item = NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); + + unsigned int nitems = std::min (output_items_available, + (int)(buffer_length / nmsdd_bytes_per_item)); + + (*d_buffer_copy_behavior.get())(output_items, msdd_buffer, output_index, nitems); + + output_items_produced = nitems; + bytes_read = nitems * nmsdd_bytes_per_item; +} diff --git a/gr-msdd6000/src/lib/msdd_source_c.h b/gr-msdd6000/src/lib/msdd_source_c.h new file mode 100644 index 000000000..11aafbb1f --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_c.h @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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_MSDD_SOURCE_C_H +#define INCLUDED_MSDD_SOURCE_C_H + +#include <msdd_source_base.h> +#include <msdd_buffer_copy_behaviors.h> +#include <stdexcept> + +class msdd_source_c; +typedef boost::shared_ptr<msdd_source_c> msdd_source_c_sptr; + +// public shared_ptr constructor + +msdd_source_c_sptr +msdd_make_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + +/*! + * \brief interface to MSDD Rx path + * + * output: 1 stream of short + */ +class msdd_source_c : public msdd_source_base { +private: + friend msdd_source_c_sptr + msdd_make_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + std::auto_ptr<msdd::BufferCopyBehavior> d_buffer_copy_behavior; + +protected: + msdd_source_c (int which_board, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + int ninput_bytes_reqd_for_noutput_items (int noutput_items); + + virtual void copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int buffer_length, + int &bytes_read); + +public: + ~msdd_source_c (); +}; + +#endif /* INCLUDED_MSDD_SOURCE_C_H */ diff --git a/gr-msdd6000/src/lib/msdd_source_s.cc b/gr-msdd6000/src/lib/msdd_source_s.cc new file mode 100644 index 000000000..6a218080f --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_s.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 + +#define MSDD_DEBUG2_TRUE + +#ifdef MSDD_DEBUG2_TRUE +#include <iostream> +#define MSDD_DEBUG2(x) std::cout << x << std::endl; +#else +#define MSDD_DEBUG2(x) +#endif + +#include <msdd_source_s.h> +#include <gr_io_signature.h> + +namespace { + static const int NBASIC_SAMPLES_PER_ITEM = 1; +} + +msdd_source_s_sptr +msdd_make_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error) +{ + return msdd_source_s_sptr (new msdd_source_s (which_board, + decim_rate, + fft_points, + initial_rx_freq, + opp_mode, + src, + port_src + )); +} + + +msdd_source_s::msdd_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error) + : msdd_source_base ("msdd_source_s", + gr_make_io_signature (1, 1, sizeof (int)), + which_board, opp_mode, src, port_src + ) +{ + + switch (sizeof_basic_sample()) { + case 1: + d_buffer_copy_behavior.reset( + new msdd::BufferCopyBehaviorGeneric<short, unsigned char>()); + break; + case 2: + d_buffer_copy_behavior.reset( + new msdd::BufferCopyBehaviorGeneric<short, float>()); + break; + case 4: + d_buffer_copy_behavior.reset( + new msdd::BufferCopyBehaviorGeneric<short, int>()); + break; + default: + assert(false); + } + +} + +msdd_source_s::~msdd_source_s () +{ +} + +int +msdd_source_s::ninput_bytes_reqd_for_noutput_items (int noutput_items) +{ + return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); +} + +void +msdd_source_s::copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int buffer_length, + int &bytes_read) +{ + MSDD_DEBUG2("copy_from_msdd_buffer: output_index: " << output_index << " output_items_available: " << output_items_available << " buflen: " << buffer_length) + + unsigned nmsdd_bytes_per_item + (msdd_source_s::ninput_bytes_reqd_for_noutput_items(1)); + + unsigned int nitems = std::min (output_items_available, + (int)(buffer_length / nmsdd_bytes_per_item)); + + MSDD_DEBUG2("copy_from_msdd_buffer: nmsdd_bytes_per_item: " << nmsdd_bytes_per_item << " nitems: " << nitems) + + (*d_buffer_copy_behavior.get())(output_items, msdd_buffer, output_index, nitems); + + output_items_produced = nitems; + bytes_read = nitems * nmsdd_bytes_per_item; +} diff --git a/gr-msdd6000/src/lib/msdd_source_s.h b/gr-msdd6000/src/lib/msdd_source_s.h new file mode 100644 index 000000000..e32f8ae9b --- /dev/null +++ b/gr-msdd6000/src/lib/msdd_source_s.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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_MSDD_SOURCE_S_H +#define INCLUDED_MSDD_SOURCE_S_H + +#include <msdd_source_base.h> +#include <msdd_buffer_copy_behaviors.h> +#include <stdexcept> + +class msdd_source_s; +typedef boost::shared_ptr<msdd_source_s> msdd_source_s_sptr; + +// public shared_ptr constructor + +msdd_source_s_sptr +msdd_make_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + +/*! + * \brief interface to MSDD Rx path + * + * output: 1 stream of short + */ +class msdd_source_s : public msdd_source_base { +private: + friend msdd_source_s_sptr + msdd_make_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + std::auto_ptr<msdd::BufferCopyBehavior> d_buffer_copy_behavior; + +protected: + msdd_source_s (int which_board, + unsigned int decim_rate, + unsigned int fft_points, + double initial_rx_freq, + int opp_mode, + const char *src, + unsigned short port_src + ) throw (std::runtime_error); + + int ninput_bytes_reqd_for_noutput_items (int noutput_items); + + virtual void copy_from_msdd_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *msdd_buffer, + int buffer_length, + int &bytes_read); +public: + ~msdd_source_s (); +}; + +#endif /* INCLUDED_MSDD_SOURCE_S_H */ diff --git a/gr-msdd6000/src/python/Makefile.am b/gr-msdd6000/src/python/Makefile.am new file mode 100644 index 000000000..38040eb3c --- /dev/null +++ b/gr-msdd6000/src/python/Makefile.am @@ -0,0 +1,48 @@ +# +# Copyright 2008 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 $(top_srcdir)/Makefile.common + +EXAMPLE_FILES = + +EXTRA_DIST = run_tests.in \ + $(EXAMPLE_FILES) + +ourdatadir = $(exampledir)/msdd6000 +ourdata_DATA = $(EXAMPLE_FILES) + +noinst_PYTHON = \ + qa_msdd6000.py \ + test_udp.py \ + test_tcp.py + +TESTS = \ + run_tests + + +# Make example scripts with #! executable +install-data-local: install-ourdataDATA + for i in `find $(ourdatadir) -type f ! -perm 755`; do \ + if head -1 $$i | grep -q '^#!'; then \ + chmod 755 $$i; \ + echo "made executable: $$i"; \ + fi; \ + done diff --git a/gr-msdd6000/src/python/qa_msdd6000.py b/gr-msdd6000/src/python/qa_msdd6000.py new file mode 100755 index 000000000..fdcf7e83d --- /dev/null +++ b/gr-msdd6000/src/python/qa_msdd6000.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2008 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. +# + +from gnuradio import gr, gr_unittest +import msdd + +class qa_usrp (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000_nop (self): + """Just see if we can import the module... + """ + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-msdd6000/src/python/run_tests.in b/gr-msdd6000/src/python/run_tests.in new file mode 100644 index 000000000..28e4c731c --- /dev/null +++ b/gr-msdd6000/src/python/run_tests.in @@ -0,0 +1,10 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gr-msdd6000 \ + @abs_top_builddir@/gr-msdd6000 \ + @srcdir@ diff --git a/gr-msdd6000/src/python/test_tcp.py b/gr-msdd6000/src/python/test_tcp.py new file mode 100755 index 000000000..b02db815d --- /dev/null +++ b/gr-msdd6000/src/python/test_tcp.py @@ -0,0 +1,78 @@ +#!/usr/bin/python + +from socket import * +import string +import time +import struct; +import random; + +myport = random.randint(1025,65535); + +port = 10000 +host = "10.45.4.43" +myaddr = ("10.45.1.229",myport); + +buf = 100000; + +TCPSock = socket(AF_INET,SOCK_STREAM); +#TCPSock = socket(AF_INET,SOCK_DGRAM); +TCPSock.bind(myaddr); +TCPSock.connect((host,port)); + +f_mhz = 2400; +f_hz = 0; +gain = 2; +window = 3; #0=rect, 1=hanning, 2=hamming, 3=blackman +#samples = 0xffffffff; #8-15 fft:(returns 2^number[8-15]) raw:(returns number) +samples = 2; #8-15 fft:(returns 2^number[8-15]) raw:(returns number) +decim = 2; #0-8 +#decim = decim+16; # +16 to use 16bit instead of 32 bit +mode = 1; #0=IQ, 1=MAG, 2=MAGDB +sets = 0xffffffff; +#sets = 1; + +fft_data = struct.pack("<IIIIIIIIII", 0x02, 0x20, f_mhz, f_hz, gain,window, samples, decim, mode,sets); +raw_data = struct.pack("<IIIIIIII", 0x01, 0x18, f_mhz, f_hz, gain,samples, decim,sets); +stat_data = struct.pack("!II", 0x0000, 0x0000) + +data = raw_data; + +#TCPSock.sendto(data, (host,port)) +TCPSock.send(data); + +print "sent" + + + +count = 0; +while(1): + data,addr = TCPSock.recvfrom(buf); + + print "got response" + + print "Data length: %d bytes."%(len(data)); + if(len(data)==12): + a,b,c = struct.unpack("!III",data); + print "%x,%x,%x"%(a,b,c); + + datavector = []; + + for d in data: + a = struct.unpack("<b",d); + datavector.append(a); + + print datavector; + + count = count + 1; + + if(count > 1): + sets = 3; + raw_data_2 = struct.pack("<IIIIIIII", 0x01, 0x18, f_mhz, f_hz, gain,samples, decim,sets); + TCPSock.send(raw_data_2); + + + +TCPSock.close(); + + + diff --git a/gr-msdd6000/src/python/test_udp.py b/gr-msdd6000/src/python/test_udp.py new file mode 100755 index 000000000..da5c39de3 --- /dev/null +++ b/gr-msdd6000/src/python/test_udp.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +from socket import * +import string +import time +import struct; + + +port = 10001 +host = "10.45.4.43" + +myaddr = ("10.45.1.229",10000); + +buf = 1024; + +UDPSock = socket(AF_INET,SOCK_DGRAM); +UDPSock.bind(myaddr); + +f_mhz = 2400; +f_hz = 1; +gain = 3; +samples = 512; +decim = 2; +sets = 16; + + +req_data = struct.pack("<IIIIIIIIII", 0x0001, 0x0002, f_mhz, f_hz, gain, samples, decim, sets); +data = struct.pack("<II", 0x0000, 0x0000); + + + +UDPSock.sendto(stat_data, (host,port)) + + +print "sent" + +data,addr = UDPSock.recvfrom(buf); +print "got response" + + diff --git a/gr-msdd6000/src/python_test/test_tcp.py b/gr-msdd6000/src/python_test/test_tcp.py new file mode 100755 index 000000000..b02db815d --- /dev/null +++ b/gr-msdd6000/src/python_test/test_tcp.py @@ -0,0 +1,78 @@ +#!/usr/bin/python + +from socket import * +import string +import time +import struct; +import random; + +myport = random.randint(1025,65535); + +port = 10000 +host = "10.45.4.43" +myaddr = ("10.45.1.229",myport); + +buf = 100000; + +TCPSock = socket(AF_INET,SOCK_STREAM); +#TCPSock = socket(AF_INET,SOCK_DGRAM); +TCPSock.bind(myaddr); +TCPSock.connect((host,port)); + +f_mhz = 2400; +f_hz = 0; +gain = 2; +window = 3; #0=rect, 1=hanning, 2=hamming, 3=blackman +#samples = 0xffffffff; #8-15 fft:(returns 2^number[8-15]) raw:(returns number) +samples = 2; #8-15 fft:(returns 2^number[8-15]) raw:(returns number) +decim = 2; #0-8 +#decim = decim+16; # +16 to use 16bit instead of 32 bit +mode = 1; #0=IQ, 1=MAG, 2=MAGDB +sets = 0xffffffff; +#sets = 1; + +fft_data = struct.pack("<IIIIIIIIII", 0x02, 0x20, f_mhz, f_hz, gain,window, samples, decim, mode,sets); +raw_data = struct.pack("<IIIIIIII", 0x01, 0x18, f_mhz, f_hz, gain,samples, decim,sets); +stat_data = struct.pack("!II", 0x0000, 0x0000) + +data = raw_data; + +#TCPSock.sendto(data, (host,port)) +TCPSock.send(data); + +print "sent" + + + +count = 0; +while(1): + data,addr = TCPSock.recvfrom(buf); + + print "got response" + + print "Data length: %d bytes."%(len(data)); + if(len(data)==12): + a,b,c = struct.unpack("!III",data); + print "%x,%x,%x"%(a,b,c); + + datavector = []; + + for d in data: + a = struct.unpack("<b",d); + datavector.append(a); + + print datavector; + + count = count + 1; + + if(count > 1): + sets = 3; + raw_data_2 = struct.pack("<IIIIIIII", 0x01, 0x18, f_mhz, f_hz, gain,samples, decim,sets); + TCPSock.send(raw_data_2); + + + +TCPSock.close(); + + + diff --git a/gr-msdd6000/src/python_test/test_udp.py b/gr-msdd6000/src/python_test/test_udp.py new file mode 100755 index 000000000..da5c39de3 --- /dev/null +++ b/gr-msdd6000/src/python_test/test_udp.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +from socket import * +import string +import time +import struct; + + +port = 10001 +host = "10.45.4.43" + +myaddr = ("10.45.1.229",10000); + +buf = 1024; + +UDPSock = socket(AF_INET,SOCK_DGRAM); +UDPSock.bind(myaddr); + +f_mhz = 2400; +f_hz = 1; +gain = 3; +samples = 512; +decim = 2; +sets = 16; + + +req_data = struct.pack("<IIIIIIIIII", 0x0001, 0x0002, f_mhz, f_hz, gain, samples, decim, sets); +data = struct.pack("<II", 0x0000, 0x0000); + + + +UDPSock.sendto(stat_data, (host,port)) + + +print "sent" + +data,addr = UDPSock.recvfrom(buf); +print "got response" + + |