summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/grc_gr_msdd6000.m47
-rw-r--r--configure.ac2
-rw-r--r--gr-msdd6000/src/Makefile.am31
-rw-r--r--gr-msdd6000/src/README53
-rw-r--r--gr-msdd6000/src/msdd6000.cc146
-rw-r--r--gr-msdd6000/src/msdd6000.h51
-rw-r--r--gr-msdd6000/src/msdd_buffer_copy_behaviors.h38
-rw-r--r--gr-msdd6000/src/msdd_source_base.cc819
-rw-r--r--gr-msdd6000/src/msdd_source_base.h308
-rw-r--r--gr-msdd6000/src/msdd_source_c.cc112
-rw-r--r--gr-msdd6000/src/msdd_source_c.h81
-rw-r--r--gr-msdd6000/src/msdd_source_s.cc130
-rw-r--r--gr-msdd6000/src/msdd_source_s.h91
-rw-r--r--gr-msdd6000/src/msdd_source_simple.cc149
-rw-r--r--gr-msdd6000/src/msdd_source_simple.h52
-rwxr-xr-xgr-msdd6000/src/qa_msdd_source_simple.py45
16 files changed, 2100 insertions, 15 deletions
diff --git a/config/grc_gr_msdd6000.m4 b/config/grc_gr_msdd6000.m4
index 056b084bd..0d5ddd9a2 100644
--- a/config/grc_gr_msdd6000.m4
+++ b/config/grc_gr_msdd6000.m4
@@ -22,10 +22,7 @@ AC_DEFUN([GRC_GR_MSDD6000],[
AC_CONFIG_FILES([\
gr-msdd6000/Makefile \
- gr-msdd6000/src/Makefile \
- gr-msdd6000/src/lib/Makefile \
- gr-msdd6000/src/python/Makefile
- gr-msdd6000/src/python/run_tests
+ gr-msdd6000/src/Makefile
])
dnl Don't do gr-msdd6000 if gnuradio-core skipped
@@ -33,6 +30,6 @@ AC_DEFUN([GRC_GR_MSDD6000],[
GRC_BUILD_CONDITIONAL([gr-msdd6000],[
dnl run_tests is created from run_tests.in. Make it executable.
- AC_CONFIG_COMMANDS([run_tests_msdd6000], [chmod +x gr-msdd6000/src/python/run_tests])
+ AC_CONFIG_COMMANDS([run_tests_msdd6000], [chmod +x gr-msdd6000/src/run_tests])
])
])
diff --git a/configure.ac b/configure.ac
index ea99edddf..4dc4e1873 100644
--- a/configure.ac
+++ b/configure.ac
@@ -257,7 +257,7 @@ GRC_MBLOCK dnl this must come after GRC_PMT
GRC_USRP
GRC_GR_USRP dnl this must come after GRC_USRP
GRC_GR_GCELL dnl this must come after GRC_GCELL and GRC_GNURADIO_CORE
-#GRC_GR_MSDD6000
+GRC_GR_MSDD6000
GRC_GR_AUDIO_ALSA
GRC_GR_AUDIO_JACK
GRC_GR_AUDIO_OSS
diff --git a/gr-msdd6000/src/Makefile.am b/gr-msdd6000/src/Makefile.am
index dbf1271ed..0d1be3c38 100644
--- a/gr-msdd6000/src/Makefile.am
+++ b/gr-msdd6000/src/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2004,2005,2006 Free Software Foundation, Inc.
+# Copyright 2007,2008 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -18,7 +18,7 @@
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
-CCFLAGS = -g
+
include $(top_srcdir)/Makefile.common
# Install this stuff so that it ends up as the gnuradio.howto module
@@ -28,20 +28,33 @@ include $(top_srcdir)/Makefile.common
ourpythondir = $(grpythondir)
ourlibdir = $(grpyexecdir)
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS)
-SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(SWIGGRFLAGS)
+#EXTRA_DIST = run_tests.in
+
+#TESTS = run_tests
+
+
+#INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS)
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \
+ $(WITH_INCLUDES)
-ALL_IFILES = \
- $(LOCAL_IFILES) \
- $(NON_LOCAL_IFILES)
+
+SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) \
+ -I/usr/include $(WITH_SWIG_INCLUDES) $(WITH_INCLUDES)
NON_LOCAL_IFILES = \
- $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i
+ $(GNURADIO_I)
LOCAL_IFILES = \
- $(top_srcdir)/src/msdd/msdd.i
+ $(top_srcdir)/gr-msdd6000/src/msdd.i
+
+
+ALL_IFILES = \
+ $(LOCAL_IFILES) \
+ $(NON_LOCAL_IFILES)
+
# These files are built by SWIG. The first is the C++ glue.
# The second is the python wrapper that loads the _howto shared library
diff --git a/gr-msdd6000/src/README b/gr-msdd6000/src/README
new file mode 100644
index 000000000..82a4fc048
--- /dev/null
+++ b/gr-msdd6000/src/README
@@ -0,0 +1,53 @@
+Softronics/GR Driver Info
+
+Jul 9, 2008
+TJO
+
+
+Tools / Waveforms
+
+ - non_gr_snapshot_tool
+ simple tool to capture
+ fixed length snapshots to a file
+ compile with make and run
+ with ./cap4
+ edit client5.cc variables to
+ set parameters.
+
+ ./plot_psd.py <cap file>
+ and
+ ./spectrogram.py <cap file>
+
+ may be used for analysis
+
+ - python-examples/new_msdd/fft.py
+ A clone of the original usrp_fft.py
+ adapted to work with the new msdd.source_simple
+ source block.
+ run ./new_msdd_fft.py -W
+ for waterfall mode.
+
+
+GNU Radio Blocks,
+
+ - msdd.source_simple
+ this block produces a stream of
+ interleaved complex shorts and
+ currently works with FAPP.LDR
+
+ if you want complex floats,
+ put a gr.interleaved_short_to_complex()
+ block immidiately following.
+
+
+ - msdd.source_s / source_c / source_base
+ These were written with the
+ old TCP based app.ldr protocol
+ and will no longer work.
+ data was never streamed
+ without discontinuities
+ through this method.
+
+
+
+
diff --git a/gr-msdd6000/src/msdd6000.cc b/gr-msdd6000/src/msdd6000.cc
new file mode 100644
index 000000000..a2055877e
--- /dev/null
+++ b/gr-msdd6000/src/msdd6000.cc
@@ -0,0 +1,146 @@
+#include "msdd6000.h"
+
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
+
+void optimize_socket(int socket);
+
+MSDD6000::MSDD6000(char* addr){
+ d_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+ optimize_socket(d_sock);
+
+
+ // set up remote sockaddr
+// int s = inet_aton(addr, &d_adx);
+ d_sockaddr.sin_family = AF_INET;
+ d_sockaddr.sin_port = htons(10000);
+ int s = inet_aton(addr, &d_sockaddr.sin_addr);
+
+ // set up local sockaddr
+ short int port = 10010;
+ d_myadx.s_addr = INADDR_ANY;
+ d_mysockaddr.sin_family = AF_INET;
+ d_mysockaddr.sin_port = htons(port);
+ memcpy(&d_mysockaddr.sin_addr.s_addr, &d_myadx.s_addr, sizeof(in_addr));
+ //d_sockaddr.sin_addr = INADDR_ANY;
+ s = bind(d_sock, (const sockaddr*) &d_mysockaddr, sizeof(d_mysockaddr));
+
+ // set default values
+ d_decim = 2;
+ d_ddc_gain = 2;
+ d_rf_attn = 0;
+ d_state = STATE_STOPPED;
+}
+
+
+void optimize_socket(int socket){
+#define BANDWIDTH 1000000000/8
+#define DELAY 0.5
+ int ret;
+
+ int sock_buf_size = 2*BANDWIDTH*DELAY;
+ char textbuf[512];
+ sprintf(textbuf, "%d", sock_buf_size);
+ printf("sock_buf_size = %d\n", sock_buf_size);
+
+ ret = setsockopt( socket, SOL_SOCKET, SO_SNDBUF,
+ (char *)&sock_buf_size, sizeof(sock_buf_size) );
+
+ ret = setsockopt( socket, SOL_SOCKET, SO_RCVBUF,
+ (char *)&sock_buf_size, sizeof(sock_buf_size) );
+
+ int uid = getuid();
+ if(uid!=0){
+ printf(" ****** COULD NOT OPTIMIZE SYSTEM NETWORK PARAMETERS BECAUSE YOU ARE NOT RUNNING AS ROOT *******\n ****** YOUR MSDD6000 RECIEVER PERFORMANCE IS GOING TO BE TERRIBLE *******\n");
+ return;
+ }
+
+
+ // SET UP SOME SYSTEM WIDE TCP SOCKET PARAMETERS
+ FILE* fd = fopen("/proc/sys/net/core/netdev_max_backlog", "w");
+ fwrite("10000", 1, strlen("10000"), fd);
+ fclose(fd);
+
+ fd = fopen("/proc/sys/net/core/rmem_max", "w");
+ fwrite(textbuf, 1, strlen(textbuf), fd);
+ fclose(fd);
+
+ fd = fopen("/proc/sys/net/core/wmem_max", "w");
+ fwrite(textbuf, 1, strlen(textbuf), fd);
+ fclose(fd);
+
+ // just incase these were rejected before because of max sizes...
+
+ ret = setsockopt( socket, SOL_SOCKET, SO_SNDBUF,
+ (char *)&sock_buf_size, sizeof(sock_buf_size) );
+
+ ret = setsockopt( socket, SOL_SOCKET, SO_RCVBUF,
+ (char *)&sock_buf_size, sizeof(sock_buf_size) );
+
+}
+
+
+void MSDD6000::set_decim(int decim_pow2){
+ DEBUG("SETTING NEW DECIM");
+ d_decim = decim_pow2;
+
+ if(d_state==STATE_STARTED)
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
+}
+
+void MSDD6000::set_rf_attn(int attn){
+ DEBUG("SETTING NEW RF ATTN");
+ d_rf_attn = attn;
+ if(d_state==STATE_STARTED)
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
+}
+
+void MSDD6000::set_ddc_gain(int gain){
+ DEBUG("SETTING NEW DDC GAIN");
+ d_ddc_gain = gain;
+ if(d_state==STATE_STARTED)
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
+}
+
+void MSDD6000::set_fc(int center_mhz, int offset_hz){
+ DEBUG("SETTING NEW FC");
+ d_fc_mhz = center_mhz;
+ d_offset_hz = offset_hz;
+
+ if(d_state==STATE_STARTED)
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
+}
+
+
+void MSDD6000::start(){
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
+ d_state = STATE_STARTED;
+ }
+
+
+void MSDD6000::stop(){
+ // new request with 0 decim tells it to halt
+ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, 0, d_offset_hz);
+ d_state = STATE_STOPPED;
+ }
+
+
+void MSDD6000::send_request(float freq_mhz, float rf_attn, float ddc_gain, float ddc_dec, float ddc_offset_hz){
+ static char buff[512];
+ sprintf(buff, "%f %f %f %f %f\n",freq_mhz, rf_attn, ddc_gain, ddc_dec, ddc_offset_hz);
+ printf("sending: %s\n", buff);
+ int flags = 0;
+ sendto( d_sock, buff, strlen(buff)+1, flags, (const sockaddr*)&d_sockaddr, sizeof(d_sockaddr));
+ }
+
+
+int MSDD6000::read(char* buf, int size){
+ int flags = 0;
+ return recv(d_sock, buf, size, flags);
+ }
+
+
diff --git a/gr-msdd6000/src/msdd6000.h b/gr-msdd6000/src/msdd6000.h
new file mode 100644
index 000000000..94a62e8b0
--- /dev/null
+++ b/gr-msdd6000/src/msdd6000.h
@@ -0,0 +1,51 @@
+#ifndef MSDD6000_H
+#define MSDD6000_H
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <linux/socket.h>
+
+#define DEBUG(A) printf("=debug=> %s\n", A)
+
+#define STATE_STOPPED 0
+#define STATE_STARTED 1
+
+class MSDD6000 {
+ public:
+ MSDD6000(char* addr);
+
+ void set_decim(int decim_pow2);
+ void set_fc(int center_mhz, int offset_hz);
+ void set_ddc_gain(int gain);
+ void set_rf_attn(int attn);
+
+ void set_output(int mode, void* arg);
+
+ void start();
+ void stop();
+
+ void send_request(float,float,float,float,float);
+ int read(char*, int);
+
+ int d_decim;
+ int d_fc_mhz;
+ int d_offset_hz;
+ int d_rf_attn;
+ int d_ddc_gain;
+
+// in_addr d_adx;
+ in_addr d_myadx;
+
+ struct sockaddr_in d_sockaddr;
+ struct sockaddr_in d_mysockaddr;
+
+ int d_sock;
+ int d_state;
+};
+
+
+
+
+
+
+#endif
diff --git a/gr-msdd6000/src/msdd_buffer_copy_behaviors.h b/gr-msdd6000/src/msdd_buffer_copy_behaviors.h
new file mode 100644
index 000000000..398f8ae66
--- /dev/null
+++ b/gr-msdd6000/src/msdd_buffer_copy_behaviors.h
@@ -0,0 +1,38 @@
+#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/msdd_source_base.cc b/gr-msdd6000/src/msdd_source_base.cc
new file mode 100644
index 000000000..79f37b139
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_base.cc
@@ -0,0 +1,819 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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/msdd_source_base.h b/gr-msdd6000/src/msdd_source_base.h
new file mode 100644
index 000000000..1547a22d8
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_base.h
@@ -0,0 +1,308 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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/msdd_source_c.cc b/gr-msdd6000/src/msdd_source_c.cc
new file mode 100644
index 000000000..db1f320ca
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_c.cc
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 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/msdd_source_c.h b/gr-msdd6000/src/msdd_source_c.h
new file mode 100644
index 000000000..57dee2d79
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_c.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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 usrp_standard_rx;
+
+
+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/msdd_source_s.cc b/gr-msdd6000/src/msdd_source_s.cc
new file mode 100644
index 000000000..9395647d2
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_s.cc
@@ -0,0 +1,130 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 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/msdd_source_s.h b/gr-msdd6000/src/msdd_source_s.h
new file mode 100644
index 000000000..6ddcdd065
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_s.h
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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 <stdexcept>
+#include <msdd_buffer_copy_behaviors.h>
+
+class usrp_standard_rx;
+
+
+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/msdd_source_simple.cc b/gr-msdd6000/src/msdd_source_simple.cc
new file mode 100644
index 000000000..4e0c47ba0
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_simple.cc
@@ -0,0 +1,149 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <vector>
+#include <msdd_source_simple.h>
+#include <gr_io_signature.h>
+#include <gr_sync_block.h>
+
+#ifndef FALSE
+#define FALSE (0==1)
+#define TRUE (0==0)
+#endif
+
+
+msdd_source_simple_sptr
+msdd_make_source_simple ( const char *src, unsigned short port_src)
+{
+ return msdd_source_simple_sptr (new msdd_source_simple ( src, port_src));
+}
+
+
+msdd_source_simple::msdd_source_simple (
+ const char *src,
+ unsigned short port_src)
+ : gr_sync_block("MSDD_SOURCE_SIMPLE",
+ gr_make_io_signature (0,0,0),
+ gr_make_io_signature (1, 1, sizeof (short)))
+{
+ rcv = new MSDD6000((char*)src);
+}
+
+int
+msdd_source_simple::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+
+#define BUF_LEN (366*sizeof(short)*2 + 6)
+
+ float* out1 =(float*) output_items[0];
+
+ char buffer[BUF_LEN];
+ rcv->read( &buffer[0], BUF_LEN );
+
+ int seq = *((int*) &buffer[2]);
+
+ if(d_lastseq == -366){
+ // not started case
+ if(seq == 0){
+ d_lastseq = 0;
+ } else {
+ // THROW AWAY SAMPLES WE ARE NOT STARTED YET!
+ return 0;
+ }
+
+ } else {
+ // started case
+ int samples_missed = seq - d_lastseq - 366;
+ if(samples_missed > 0){
+ printf("dropped %d samples.\n", samples_missed);
+ }
+ d_lastseq = seq;
+ }
+
+ if(noutput_items< 366*2){
+ printf("NOT ENOUGH SPACE IN OUTPUT BUFFER!!! >:-(\n");
+ }
+
+ memcpy(&out1[0], &buffer[6], BUF_LEN - 6);
+
+// for(int i = 0; i < 366*2; i++){
+// out1[i] = (float) (*((short*) &buffer[6+2*i]) );
+// }
+
+ return 366*2;
+}
+
+bool msdd_source_simple::set_decim_rate(unsigned int rate)
+{
+ rcv->set_decim(log2(rate));
+ return TRUE;
+}
+
+
+bool msdd_source_simple::set_rx_freq(int channel, double freq)
+{
+ long new_fc = (long)freq;
+ rcv->set_fc( new_fc/1000000, new_fc%1000000);
+ return TRUE;
+}
+
+
+bool msdd_source_simple::set_pga(int which, double gain)
+{
+ if(gain < 0 || gain > 10){
+ printf("GAIN IS OUTSIDE ACCEPTABLE RANGE!\n");
+ return FALSE;
+ }
+ // ok i lied this is not really a pga, its decimation gain
+ rcv->set_ddc_gain((int)gain);
+ return TRUE;
+}
+
+
+msdd_source_simple::~msdd_source_simple ()
+{
+ delete rcv;
+}
+
+
+bool msdd_source_simple::start()
+{
+ rcv->start();
+}
+
+
+bool msdd_source_simple::stop()
+{
+ rcv->stop();
+}
+
+int msdd_source_simple::ninput_bytes_reqd_for_noutput_items(int out){
+ return 0;
+}
+
+long msdd_source_simple::adc_freq(){
+ return 102400000;
+}
+
+int msdd_source_simple::decim_rate(){
+ return pow(2, rcv->d_decim);
+}
+
+
+std::vector<int> msdd_source_simple::gain_range(){
+ static std::vector<int> r;
+ r.push_back(0);
+ r.push_back(12);
+ return r;
+}
+
+std::vector<float> msdd_source_simple::freq_range(){
+ std::vector<float> r;
+ r.push_back(30.0*1000*1000);
+ r.push_back(6.0*1000*1000*1000);
+ return r;
+}
+
diff --git a/gr-msdd6000/src/msdd_source_simple.h b/gr-msdd6000/src/msdd_source_simple.h
new file mode 100644
index 000000000..a5e593831
--- /dev/null
+++ b/gr-msdd6000/src/msdd_source_simple.h
@@ -0,0 +1,52 @@
+#ifndef INCLUDED_MSDD_SOURCE_SIMPLE_H
+#define INCLUDED_MSDD_SOURCE_SIMPLE_H
+
+#include <stdexcept>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <gr_sync_block.h>
+#include <msdd6000.h>
+
+
+class msdd_source_simple;
+typedef boost::shared_ptr<msdd_source_simple> msdd_source_simple_sptr;
+
+
+// public shared_ptr constructor
+
+msdd_source_simple_sptr msdd_make_source_simple ( const char *src, unsigned short port_src);
+
+
+
+class msdd_source_simple : public gr_sync_block {
+ private:
+ friend msdd_source_simple_sptr
+ msdd_make_source_simple ( const char *src, unsigned short port_src);
+
+ MSDD6000* rcv;
+ int d_lastseq;
+
+ protected:
+ msdd_source_simple (const char *src, unsigned short port_src);
+
+ public:
+ ~msdd_source_simple ();
+ int ninput_bytes_reqd_for_noutput_items(int out);
+ bool stop();
+ bool start();
+
+ bool set_decim_rate(unsigned int);
+ bool set_rx_freq(int,double);
+ bool set_pga(int,double);
+
+ int work(int, gr_vector_const_void_star&, gr_vector_void_star&);
+
+ long adc_freq();
+ int decim_rate();
+ std::vector<int> gain_range();
+ std::vector<float> freq_range();
+};
+
+#endif /* INCLUDED_MSDD_SOURCE_C_H */
diff --git a/gr-msdd6000/src/qa_msdd_source_simple.py b/gr-msdd6000/src/qa_msdd_source_simple.py
new file mode 100755
index 000000000..5262fcef0
--- /dev/null
+++ b/gr-msdd6000/src/qa_msdd_source_simple.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+
+from pylab import *;
+#from scipy.fftpack import fftshift;
+
+import math;
+
+from gnuradio import msdd,gr;
+
+
+tb = gr.top_block();
+
+
+src = msdd.source_simple("10.45.4.43",0);
+convert = gr.interleaved_short_to_complex();
+sink = gr.vector_sink_c();
+
+gain = 40;
+
+fc = 2.4e9;
+
+src.set_decim_rate(8);
+#src.set_rx_freq(0,3500000000);
+src.set_rx_freq(0,fc);
+src.set_pga(0,gain);
+
+
+tb.connect(src, convert, sink);
+
+
+tb.start();
+
+v = []
+for i in range(0,10000):
+ b = math.sqrt(i);
+ v.append(b);
+
+tb.stop();
+
+#print sink.data();
+
+data = sink.data();
+
+plot(10*log10(fftshift(fft(sink.data()))));
+show();