summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-msdd6000/src/non_gr_snapshot_tool/Makefile13
-rw-r--r--gr-msdd6000/src/non_gr_snapshot_tool/client5.cc128
-rw-r--r--gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.cc146
-rw-r--r--gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.h52
-rwxr-xr-xgr-msdd6000/src/non_gr_snapshot_tool/plot_psd.py48
-rwxr-xr-xgr-msdd6000/src/non_gr_snapshot_tool/spectrogram.py88
-rwxr-xr-xgr-msdd6000/src/python-examples/ofdm/benchmark_ofdm_rx.py184
-rwxr-xr-xgr-msdd6000/src/python-examples/ofdm/gr_plot_ofdm.py268
-rw-r--r--gr-msdd6000/src/python-examples/ofdm/receive_path.py102
9 files changed, 1029 insertions, 0 deletions
diff --git a/gr-msdd6000/src/non_gr_snapshot_tool/Makefile b/gr-msdd6000/src/non_gr_snapshot_tool/Makefile
new file mode 100644
index 000000000..213d68e0b
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/Makefile
@@ -0,0 +1,13 @@
+CCFLAGS = -O3
+LDFLAGS = -lpthread
+FFTW_LDFLAGS = -lfftw3f
+
+
+all:
+ g++ $(CCFLAGS) -c client5.cc
+ g++ $(CCFLAGS) -c msdd6000.cc
+ g++ $(CCFLAGS) -o cap4 client5.o msdd6000.o $(LDFLAGS)
+
+
+clean:
+ rm test.out*
diff --git a/gr-msdd6000/src/non_gr_snapshot_tool/client5.cc b/gr-msdd6000/src/non_gr_snapshot_tool/client5.cc
new file mode 100644
index 000000000..fe753beda
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/client5.cc
@@ -0,0 +1,128 @@
+#include "msdd6000.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+
+#define MSDD_HOST "192.168.1.200"
+int decim = 2;
+float fc = 3500000000.0;
+int gain = 1;
+
+//long target_buf_size = 256*1024*1024; // 2 gig output when converted to floats
+long target_buf_size = 1024*1024;
+#define CHUNK_SIZE (366*2)*sizeof(short)+6
+#define OUTPUT_FILE "CAPTURE_FILE.DAT"
+
+char* buffer;
+long int buffer_size;
+sem_t buf_sem;
+sem_t lock;
+
+long int in_ptr;
+long int out_ptr;
+char** argvg;
+
+
+int main(int argc, char* argv[]){
+
+ int prio = getpriority(PRIO_PROCESS, getpid());
+ printf("prio = %d\n", prio);
+
+ // renice to -20
+ setpriority(PRIO_PROCESS, getpid(), -20);
+
+ prio = getpriority(PRIO_PROCESS, getpid());
+ printf("new prio = %d\n", prio);
+
+
+ argvg = argv;
+
+ // instantiate our reciever instance
+ MSDD6000 rcv((char*)MSDD_HOST);
+
+ // set up desired rcv parameters
+
+ int tune_mhz = long(fc)/1000000;
+ int tune_hz = long(fc)%1000000;
+ printf("mhz = %d hz = %d\n", tune_mhz, tune_hz);
+
+ rcv.set_decim(decim);
+ rcv.set_fc(tune_mhz, tune_hz); // tune frequency in mhz, and ddc fine tuning in hz
+ rcv.set_ddc_gain(gain); // careful, too much gain will cause bit-clipping (this simply chooses which 16 bits to map in 0=high order)
+ rcv.set_rf_attn(10); // adjusted variable attenuator in front of adc (0-32dB i think)
+
+ // send start command
+ rcv.start();
+
+ // allocate our recieve buffer
+
+ buffer_size = ((long)CHUNK_SIZE) * (target_buf_size/CHUNK_SIZE);
+
+ printf("Allocating Intermediate Buffer. %f MB\n", ((float)buffer_size)/(1024.0*1024));
+ buffer = (char*)malloc(buffer_size);
+ in_ptr = out_ptr = 0;
+ printf("malloc returns %x.\n", buffer);
+
+ while(in_ptr + CHUNK_SIZE < buffer_size){
+ rcv.read( &buffer[in_ptr], CHUNK_SIZE );
+ in_ptr+=CHUNK_SIZE;
+ }
+
+ printf("done.\n");
+
+ int lastseq = -1;
+ int discont = 0;
+
+ float fbuf[366*2];
+
+ FILE* fd = fopen(OUTPUT_FILE, "w");
+
+ for(long long i=0;i<buffer_size;i += CHUNK_SIZE){
+ int seq = *((int*) &buffer[i + 2] );
+ if(seq == 0){
+// printf( "seq = %d, lastseq = %d at i = %d\n", seq, lastseq, i);
+ }
+ if(lastseq == -1){
+ if(seq==0){
+// printf("found start... starting...\n");
+ lastseq = seq;
+ }
+ } else {
+ if(seq != lastseq+366){
+// printf("seq gap, %d -> %d\n", lastseq, seq);
+ if(seq==0){
+// printf("stopping at i=%d\n", i);
+ break;
+ } else {
+// printf("this is a bad discontinuity!!! :{\n");
+ discont++;
+ }
+ } else {
+ // this is good data, and we are started
+ for(int j = 0; j<366*2; j++){
+ long ptr = i+6+j*2;
+// printf("%x %x \n", buffer[ptr], buffer[ptr+1]);
+ short int sample_data = (*(( signed short*) &buffer[ptr]));
+// printf("%d\n", sample_data);
+ fbuf[j] = (float) sample_data;
+// printf("%f\n", fbuf[j]);
+
+ }
+ fwrite(fbuf, sizeof(float), 366*2, fd);
+ }
+ lastseq = seq;
+ }
+ }
+
+ fclose(fd);
+
+ printf("total discontinuities = %d\n", discont);
+
+}
+
diff --git a/gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.cc b/gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.cc
new file mode 100644
index 000000000..a2055877e
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/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/non_gr_snapshot_tool/msdd6000.h b/gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.h
new file mode 100644
index 000000000..06fedccf6
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/msdd6000.h
@@ -0,0 +1,52 @@
+#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);
+
+ private:
+ 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/non_gr_snapshot_tool/plot_psd.py b/gr-msdd6000/src/non_gr_snapshot_tool/plot_psd.py
new file mode 100755
index 000000000..66d5ae6e2
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/plot_psd.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+import struct;
+from pylab import *;
+import sys;
+
+#a = fft([1,2,3,4]);
+#print a;
+
+if(len(sys.argv)<2):
+ print "usage ./plot_psd.py <filename>"
+ sys.exit(-1);
+
+filename = sys.argv[1];
+
+#a = open("test.out_002", "r");
+a = open(filename, "r");
+samples = [];
+i_arr = [];
+q_arr = [];
+while(True):
+ d = a.read(1024*1024*4);
+ if(len(d) <= 0):
+ break;
+
+ for i in range(0,(len(d))/8):
+ [s_i, s_q] = struct.unpack_from("<ff", d, i*8);
+ samples.append(complex(s_i, s_q));
+ i_arr.append(s_i);
+ q_arr.append(s_q);
+ break;
+
+fft_data = fftshift(fft(samples));
+for i in range(0,len(fft_data)):
+ if(fft_data[i] == 0):
+ fft_data[i] = 0.01;
+
+plot(20*log10(abs(fft_data)));
+figure();
+subplot(2,1,1);
+plot(i_arr);
+subplot(2,1,2);
+plot(q_arr);
+show();
+
+
+a.close();
+
+
diff --git a/gr-msdd6000/src/non_gr_snapshot_tool/spectrogram.py b/gr-msdd6000/src/non_gr_snapshot_tool/spectrogram.py
new file mode 100755
index 000000000..5ce40de7a
--- /dev/null
+++ b/gr-msdd6000/src/non_gr_snapshot_tool/spectrogram.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+fft_bins = 1024;
+stride = 256;
+
+#filename = "output.dat";
+#decim = 4;
+#Fs = (102.4/decim) * 1e6;
+
+
+from gnuradio import gr;
+from Numeric import *;
+import FFT;
+import numpy.fft;
+from numpy import *;
+from pylab import *;
+import sys;
+
+if len(sys.argv) <2:
+ print "usage: %s <filename> (sample_rate_in_MSPS) (stride_samples)"%(sys.argv[0]);
+ sys.exit(-1);
+
+filename = sys.argv[1];
+fs = 0;
+if(len(sys.argv)>2):
+ fs = float(sys.argv[2])*1000000;
+print "opening %s.\n"%(filename);
+
+if(len(sys.argv)>=4):
+ stride = int(sys.argv[3]);
+ print "using stride = %d"%(stride);
+
+
+tb = gr.top_block();
+src = gr.file_source(gr.sizeof_gr_complex, filename, False)
+sink = gr.vector_sink_c();
+tb.connect(src,sink);
+tb.run();
+
+data = sink.data();
+dataa = array(data);
+datalen = len( data );
+
+time_bins = (datalen - fft_bins) / stride;
+
+print "output vector :: fft_bins = %d, time_bins = %d\n"%(fft_bins,time_bins);
+
+start_idx = 0;
+
+b = numpy.zeros((time_bins, fft_bins), complex);
+l = [];
+
+window = numpy.blackman(fft_bins);
+
+for i in range(0,time_bins):
+
+ time_chunk = take( dataa, range(start_idx,start_idx + fft_bins), 0);
+ time_chunk = time_chunk * window;
+ fft_chunk = numpy.fft.fftshift(numpy.fft.fft(time_chunk));
+ psd = 10*log10(fft_chunk * conj(fft_chunk)+0.001);
+
+ b[i] = psd.real;
+ l.append( psd.real.tolist() );
+
+ start_idx = start_idx + stride;
+
+#c = array(b, 10);
+
+print b[0];
+c = array(b);
+#l = c.tolist();
+print size(l);
+
+x = range(0,time_bins);
+print size(x);
+y = range(0,fft_bins);
+print size(y);
+
+print size(l);
+
+contourf(l);
+#contourf([x,y], l);
+colorbar();
+show();
+
+#print c[1,1];
+
+
diff --git a/gr-msdd6000/src/python-examples/ofdm/benchmark_ofdm_rx.py b/gr-msdd6000/src/python-examples/ofdm/benchmark_ofdm_rx.py
new file mode 100755
index 000000000..deb82e111
--- /dev/null
+++ b/gr-msdd6000/src/python-examples/ofdm/benchmark_ofdm_rx.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, blks2
+from gnuradio import msdd
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import struct, sys
+
+# from current dir
+from receive_path import receive_path
+
+class my_top_block(gr.top_block):
+ def __init__(self, address, callback, options):
+ gr.top_block.__init__(self)
+
+ self._address = address
+ self._rx_freq = options.rx_freq # receiver's center frequency
+ self._rx_gain = options.rx_gain # receiver's gain
+ self._decim = options.decim # Decimating rate for the USRP (prelim)
+
+ if self._rx_freq is None:
+ sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
+ raise SystemExit
+
+ # Set up USRP source
+ self._setup_source()
+
+ #taps = gr.firdes.low_pass(1, 1, 0.4, 0.2)
+ #self.resample = gr.rational_resampler_base_ccf(5, 8, taps)
+ self.resample = blks2.rational_resampler_ccf(5, 8)
+
+ # Set up receive path
+ self.rxpath = receive_path(callback, options)
+
+ self.connect(self.src, self.resample, self.rxpath)
+ #self.connect(self.src, gr.file_sink(gr.sizeof_gr_complex, "receive.dat"))
+ #self.connect(self.resample, gr.file_sink(gr.sizeof_gr_complex, "resampled.dat"))
+
+ def _setup_source(self):
+ # build graph
+ self._port = 10001
+ self.src = msdd.source_c(0, 1, self._address, self._port)
+ self.src.set_decim_rate(self._decim)
+ self.src.set_desired_packet_size(0, 1460)
+
+ self.set_gain(self._rx_gain)
+ self.set_freq(self._rx_freq)
+
+ def set_freq(self, target_freq):
+ """
+ Set the center frequency we're interested in.
+
+ @param target_freq: frequency in Hz
+ @rypte: bool
+ """
+ r = self.src.set_rx_freq(0, target_freq)
+ if r:
+ return True
+ return False
+
+ def set_gain(self, gain):
+ """
+ Sets the analog gain in the USRP
+ """
+ return self.src.set_pga(0, gain)
+
+ def decim(self):
+ return self._decim
+
+ def add_options(normal, expert):
+ """
+ Adds usrp-specific options to the Options Parser
+ """
+ add_freq_option(normal)
+ normal.add_option("", "--rx-gain", type="eng_float", default=32, metavar="GAIN",
+ help="set receiver gain in dB [default=%default].")
+ normal.add_option("-v", "--verbose", action="store_true", default=False)
+
+ expert.add_option("", "--rx-freq", type="eng_float", default=None,
+ help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
+ expert.add_option("-d", "--decim", type="intx", default=128,
+ help="set fpga decimation rate to DECIM [default=%default]")
+ expert.add_option("", "--snr", type="eng_float", default=30,
+ help="set the SNR of the channel in dB [default=%default]")
+
+ # Make a static method to call before instantiation
+ add_options = staticmethod(add_options)
+
+def add_freq_option(parser):
+ """
+ Hackery that has the -f / --freq option set both tx_freq and rx_freq
+ """
+ def freq_callback(option, opt_str, value, parser):
+ parser.values.rx_freq = value
+ parser.values.tx_freq = value
+
+ if not parser.has_option('--freq'):
+ parser.add_option('-f', '--freq', type="eng_float",
+ action="callback", callback=freq_callback,
+ help="set Tx and/or Rx frequency to FREQ [default=%default]",
+ metavar="FREQ")
+
+# /////////////////////////////////////////////////////////////////////////////
+# main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+ global n_rcvd, n_right
+
+ n_rcvd = 0
+ n_right = 0
+
+ def rx_callback(ok, payload):
+ global n_rcvd, n_right
+ n_rcvd += 1
+ (pktno,) = struct.unpack('!H', payload[0:2])
+ if ok:
+ n_right += 1
+ print "ok: %r \t pktno: %d \t n_rcvd: %d \t n_right: %d" % (ok, pktno, n_rcvd, n_right)
+
+ if 0:
+ printlst = list()
+ for x in payload[2:]:
+ t = hex(ord(x)).replace('0x', '')
+ if(len(t) == 1):
+ t = '0' + t
+ printlst.append(t)
+ printable = ''.join(printlst)
+
+ print printable
+ print "\n"
+
+ usage = "usage: %prog [options] host"
+ parser = OptionParser(usage=usage, option_class=eng_option, conflict_handler="resolve")
+ expert_grp = parser.add_option_group("Expert")
+ parser.add_option("","--discontinuous", action="store_true", default=False,
+ help="enable discontinuous")
+
+ my_top_block.add_options(parser, expert_grp)
+ receive_path.add_options(parser, expert_grp)
+ blks2.ofdm_mod.add_options(parser, expert_grp)
+ blks2.ofdm_demod.add_options(parser, expert_grp)
+
+ (options, args) = parser.parse_args ()
+ address = args[0]
+
+ # build the graph
+ tb = my_top_block(address, rx_callback, options)
+
+ #r = gr.enable_realtime_scheduling()
+ #if r != gr.RT_OK:
+ # print "Warning: failed to enable realtime scheduling"
+
+ tb.start() # start flow graph
+ tb.wait() # wait for it to finish
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gr-msdd6000/src/python-examples/ofdm/gr_plot_ofdm.py b/gr-msdd6000/src/python-examples/ofdm/gr_plot_ofdm.py
new file mode 100755
index 000000000..0bca41037
--- /dev/null
+++ b/gr-msdd6000/src/python-examples/ofdm/gr_plot_ofdm.py
@@ -0,0 +1,268 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 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.
+#
+
+import scipy, pylab, math
+import struct, sys
+from pylab import *
+from matplotlib.font_manager import fontManager, FontProperties
+from optparse import OptionParser
+from scipy import fftpack
+from math import log10
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_constellation:
+ def __init__(self, options):
+ derot_file = "ofdm_frame_sink_c.dat"
+ acq_file = "ofdm_frame_acq_c.dat"
+ fft_file = "fft_out_c.dat"
+
+ self.h_derot_file = open(derot_file, "r")
+ self.h_acq_file = open(acq_file, "r")
+ self.h_fft_file = open(fft_file, "r")
+
+ self.occ_tones = options.occ_tones
+ self.fft_size = options.fft_size
+ self.symbol = options.start
+ self.sample_rate = options.sample_rate
+
+ self.axis_font_size = 16
+ self.label_font_size = 18
+ self.title_font_size = 20
+ self.text_size = 22
+
+ # Setup PLOT
+ self.fig = figure(1, figsize=(14, 9), facecolor='w')
+ rcParams['xtick.labelsize'] = self.axis_font_size
+ rcParams['ytick.labelsize'] = self.axis_font_size
+
+ self.text_sym = figtext(0.05, 0.95, ("Symbol: %s" % self.symbol), weight="heavy", size=self.text_size)
+
+ self.make_plots()
+
+ self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True)
+ self.button_left = Button(self.button_left_axes, "<")
+ self.button_left_callback = self.button_left.on_clicked(self.button_left_click)
+
+ self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True)
+ self.button_right = Button(self.button_right_axes, ">")
+ self.button_right_callback = self.button_right.on_clicked(self.button_right_click)
+
+ self.xlim = self.sp_eq.get_xlim()
+
+ self.manager = get_current_fig_manager()
+ #connect('draw_event', self.zoom)
+ connect('key_press_event', self.click)
+ show()
+
+ def get_data(self):
+ self.text_sym.set_text("Symbol: %d" % (self.symbol))
+
+ derot_data = scipy.fromfile(self.h_derot_file, dtype=scipy.complex64, count=self.occ_tones)
+ acq_data = scipy.fromfile(self.h_acq_file, dtype=scipy.complex64, count=self.occ_tones)
+ fft_data = scipy.fromfile(self.h_fft_file, dtype=scipy.complex64, count=self.fft_size)
+ if(len(acq_data) == 0):
+ print "End of File"
+ else:
+ self.acq_data_reals = [r.real for r in acq_data]
+ self.acq_data_imags = [i.imag for i in acq_data]
+ self.derot_data_reals = [r.real for r in derot_data]
+ self.derot_data_imags = [i.imag for i in derot_data]
+
+ self.unequalized_angle = [math.atan2(x.imag, x.real) for x in fft_data]
+ self.equalized_angle = [math.atan2(x.imag, x.real) for x in acq_data]
+ self.derot_equalized_angle = [math.atan2(x.imag, x.real) for x in derot_data]
+
+ self.time = [i*(1/self.sample_rate) for i in range(len(acq_data))]
+ ffttime = [i*(1/self.sample_rate) for i in range(len(fft_data))]
+
+ self.freq = self.get_freq(ffttime, self.sample_rate)
+
+ for i in range(len(fft_data)):
+ if(abs(fft_data[i]) == 0.0):
+ fft_data[i] = complex(1e-6,1e-6)
+ self.fft_data = [20*log10(abs(f)) for f in fft_data]
+
+ def get_freq(self, time, sample_rate, T=1):
+ N = len(time)
+ Fs = 1.0 / (max(time) - min(time))
+ Fn = 0.5 * sample_rate
+ freq = [-Fn + i*Fs for i in range(N)]
+ return freq
+
+ def make_plots(self):
+ self.h_acq_file.seek(8*self.symbol*self.occ_tones, 0)
+ self.h_fft_file.seek(8*self.symbol*self.fft_size, 0)
+ self.h_derot_file.seek(8*self.symbol*self.occ_tones, 0)
+
+ self.get_data()
+
+ # Subplot: constellation of rotated symbols
+ self.sp_const = self.fig.add_subplot(4,1,1, position=[0.15, 0.55, 0.3, 0.35])
+ self.sp_const.set_title(("Constellation"), fontsize=self.title_font_size, fontweight="bold")
+ self.sp_const.set_xlabel("Inphase", fontsize=self.label_font_size, fontweight="bold")
+ self.sp_const.set_ylabel("Qaudrature", fontsize=self.label_font_size, fontweight="bold")
+ self.plot_const = plot(self.acq_data_reals, self.acq_data_imags, 'bo')
+ self.plot_const += plot(self.derot_data_reals, self.derot_data_imags, 'ro')
+ self.sp_const.axis([-2, 2, -2, 2])
+
+ # Subplot: unequalized angle
+ self.sp_uneq = self.fig.add_subplot(4,2,1, position=[0.575, 0.55, 0.3, 0.35])
+ self.sp_uneq.set_title(("Unequalized Angle"), fontsize=self.title_font_size, fontweight="bold")
+ self.sp_uneq.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold")
+ self.sp_uneq.set_ylabel("Angle", fontsize=self.label_font_size, fontweight="bold")
+ uneqscale = range(len(self.unequalized_angle))
+ self.plot_uneq = plot(uneqscale, self.unequalized_angle, 'bo')
+
+ # Subplot: equalized angle
+ self.sp_eq = self.fig.add_subplot(4,1,2, position=[0.15, 0.1, 0.3, 0.35])
+ self.sp_eq.set_title(("Equalized Angle"), fontsize=self.title_font_size, fontweight="bold")
+ self.sp_eq.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold")
+ self.sp_eq.set_ylabel("Angle", fontsize=self.label_font_size, fontweight="bold")
+ eqscale = range(len(self.equalized_angle))
+ self.plot_eq = plot(eqscale, self.equalized_angle, 'bo')
+ self.plot_eq += plot(eqscale, self.derot_equalized_angle, 'ro', markersize=4)
+
+ # Subplot: FFT
+ self.sp_fft = self.fig.add_subplot(4,2,2, position=[0.575, 0.1, 0.3, 0.35])
+ self.sp_fft.set_title(("FFT"), fontsize=self.title_font_size, fontweight="bold")
+ self.sp_fft.set_xlabel("Frequency (MHz)", fontsize=self.label_font_size, fontweight="bold")
+ self.sp_fft.set_ylabel("Power (dBm)", fontsize=self.label_font_size, fontweight="bold")
+ self.plot_fft = plot(self.freq, self.fft_data, '-bo')
+
+ draw()
+
+ def update_plots(self):
+ eqscale = range(len(self.equalized_angle))
+ uneqscale = range(len(self.unequalized_angle))
+ self.plot_eq[0].set_data([eqscale, self.equalized_angle])
+ self.plot_eq[1].set_data([eqscale, self.derot_equalized_angle])
+ self.plot_uneq[0].set_data([uneqscale, self.unequalized_angle])
+ self.sp_eq.set_ylim([-4, 4])
+ self.sp_uneq.set_ylim([-4, 4])
+
+ #self.sp_iq.axis([min(self.time), max(self.time),
+ # 1.5*min([min(self.acq_data_reals), min(self.acq_data_imags)]),
+ # 1.5*max([max(self.acq_data_reals), max(self.acq_data_imags)])])
+
+ self.plot_const[0].set_data([self.acq_data_reals, self.acq_data_imags])
+ self.plot_const[1].set_data([self.derot_data_reals, self.derot_data_imags])
+ self.sp_const.axis([-2, 2, -2, 2])
+
+ self.plot_fft[0].set_data([self.freq, self.fft_data])
+
+ draw()
+
+ def zoom(self, event):
+ newxlim = self.sp_eq.get_xlim()
+ if(newxlim != self.xlim):
+ self.xlim = newxlim
+ r = self.reals[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
+ i = self.imags[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
+
+ self.plot_const[0].set_data(r, i)
+ self.sp_const.axis([-2, 2, -2, 2])
+ self.manager.canvas.draw()
+ draw()
+
+ def click(self, event):
+ forward_valid_keys = [" ", "down", "right"]
+ backward_valid_keys = ["up", "left"]
+
+ if(find(event.key, forward_valid_keys)):
+ self.step_forward()
+
+ elif(find(event.key, backward_valid_keys)):
+ self.step_backward()
+
+ def button_left_click(self, event):
+ self.step_backward()
+
+ def button_right_click(self, event):
+ self.step_forward()
+
+ def step_forward(self):
+ self.symbol += 1
+ self.get_data()
+ self.update_plots()
+
+ def step_backward(self):
+ # Step back in file position
+ self.symbol -= 1
+ if(self.h_acq_file.tell() >= 16*self.occ_tones):
+ self.h_acq_file.seek(-16*self.occ_tones, 1)
+ else:
+ self.symbol = 0
+ self.h_acq_file.seek(-self.h_acq_file.tell(),1)
+
+
+ if(self.h_derot_file.tell() >= 16*self.occ_tones):
+ self.h_derot_file.seek(-16*self.occ_tones, 1)
+ else:
+ self.symbol = 0
+ self.h_derot_file.seek(-self.h_derot_file.tell(),1)
+
+
+ if(self.h_fft_file.tell() >= 16*self.fft_size):
+ self.h_fft_file.seek(-16*self.fft_size, 1)
+ else:
+ self.symbol = 0
+ self.h_fft_file.seek(-self.h_fft_file.tell(),1)
+
+ self.get_data()
+ self.update_plots()
+
+
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+ for l in list_search:
+ if item_in == l:
+ return True
+ return False
+
+def main():
+ usage="%prog: [options]"
+
+ parser = OptionParser(conflict_handler="resolve", usage=usage)
+ parser.add_option("", "--fft-size", type="int", default=512,
+ help="Specify the size of the FFT [default=%default]")
+ parser.add_option("", "--occ-tones", type="int", default=200,
+ help="Specify the number of occupied tones [default=%default]")
+ parser.add_option("-s", "--start", type="int", default=0,
+ help="Specify the starting symbol to plot [default=%default]")
+ parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+ help="Set the sampler rate of the data [default=%default]")
+
+ (options, args) = parser.parse_args ()
+
+ dc = draw_constellation(options)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
+
+
diff --git a/gr-msdd6000/src/python-examples/ofdm/receive_path.py b/gr-msdd6000/src/python-examples/ofdm/receive_path.py
new file mode 100644
index 000000000..11c714aaf
--- /dev/null
+++ b/gr-msdd6000/src/python-examples/ofdm/receive_path.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2006 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gru, blks2
+from gnuradio import usrp
+from gnuradio import eng_notation
+import copy
+import sys
+
+# /////////////////////////////////////////////////////////////////////////////
+# receive path
+# /////////////////////////////////////////////////////////////////////////////
+
+class receive_path(gr.hier_block2):
+ def __init__(self, rx_callback, options):
+
+ gr.hier_block2.__init__(self, "receive_path",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
+
+
+ options = copy.copy(options) # make a copy so we can destructively modify
+
+ self._verbose = options.verbose
+ self._log = options.log
+ self._rx_callback = rx_callback # this callback is fired when there's a packet available
+
+ # receiver
+ self.ofdm_rx = \
+ blks2.ofdm_demod(options, callback=self._rx_callback)
+
+ # Carrier Sensing Blocks
+ alpha = 0.001
+ thresh = 30 # in dB, will have to adjust
+ self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
+
+ self.connect(self, self.ofdm_rx)
+ self.connect(self.ofdm_rx, self.probe)
+
+ # Display some information about the setup
+ if self._verbose:
+ self._print_verbage()
+
+ def carrier_sensed(self):
+ """
+ Return True if we think carrier is present.
+ """
+ #return self.probe.level() > X
+ return self.probe.unmuted()
+
+ def carrier_threshold(self):
+ """
+ Return current setting in dB.
+ """
+ return self.probe.threshold()
+
+ def set_carrier_threshold(self, threshold_in_db):
+ """
+ Set carrier threshold.
+
+ @param threshold_in_db: set detection threshold
+ @type threshold_in_db: float (dB)
+ """
+ self.probe.set_threshold(threshold_in_db)
+
+
+ def add_options(normal, expert):
+ """
+ Adds receiver-specific options to the Options Parser
+ """
+ normal.add_option("-v", "--verbose", action="store_true", default=False)
+ expert.add_option("", "--log", action="store_true", default=False,
+ help="Log all parts of flow graph to files (CAUTION: lots of data)")
+
+ # Make a static method to call before instantiation
+ add_options = staticmethod(add_options)
+
+
+ def _print_verbage(self):
+ """
+ Prints information about the receive path
+ """
+ pass