diff options
-rw-r--r-- | config/grc_gr_msdd6000.m4 | 7 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gr-msdd6000/src/Makefile.am | 31 | ||||
-rw-r--r-- | gr-msdd6000/src/README | 53 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd6000.cc | 146 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd6000.h | 51 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_buffer_copy_behaviors.h | 38 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_base.cc | 819 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_base.h | 308 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_c.cc | 112 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_c.h | 81 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_s.cc | 130 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_s.h | 91 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_simple.cc | 149 | ||||
-rw-r--r-- | gr-msdd6000/src/msdd_source_simple.h | 52 | ||||
-rwxr-xr-x | gr-msdd6000/src/qa_msdd_source_simple.py | 45 |
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(); |