Merged r6329:6428 of features/inband-usb + distcheck fixes into trunk.
[debian/gnuradio] / usrp / host / lib / inband / usrp_rx_stub.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <usrp_rx_stub.h>
27
28 #include <iostream>
29 #include <vector>
30 #include <usb.h>
31 #include <mb_class_registry.h>
32 #include <usrp_inband_usb_packet.h>
33 #include <fpga_regs_common.h>
34 #include "usrp_standard.h"
35 #include <stdio.h>
36 #include <ui_nco.h>
37 #include <fstream>
38
39 #include <symbols_usrp_rx_cs.h>
40
41 typedef usrp_inband_usb_packet transport_pkt;
42
43 static const bool verbose = false;
44
45 bool usrp_rx_stop;
46
47 // Used for the fake control packet response code to send the responses back up
48 // the RX.  The TX stub dumps responses in to this queue.
49 std::queue<pmt_t> d_cs_queue;
50
51 usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
52   : mb_mblock(rt, instance_name, user_arg),
53     d_samples_per_frame((long)(126)),
54     d_amplitude(16384),
55     d_disk_write(false)
56 {
57   d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
58   
59   // initialize NCO
60   double freq = 100e3;
61   int interp = 32;                          // 32 -> 4MS/s
62   double sample_rate = 128e6 / interp;  
63   d_nco.set_freq(2*M_PI * freq/sample_rate);
64
65   //d_disk_write = true;
66   
67   if(d_disk_write)
68     d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
69   
70   usrp_rx_stop = false;
71 }
72
73 usrp_rx_stub::~usrp_rx_stub() 
74 {
75   if(d_disk_write)
76     d_ofile.close();
77 }
78
79 void 
80 usrp_rx_stub::initial_transition()
81 {
82   
83 }
84
85 void
86 usrp_rx_stub::handle_message(mb_message_sptr msg)
87 {
88   pmt_t event = msg->signal();
89   pmt_t port_id = msg->port_id();
90   pmt_t data = msg->data(); 
91
92   // Theoretically only have 1 message to ever expect, but
93   // want to make sure its at least what we want
94   if(pmt_eq(port_id, d_cs->port_symbol())) {
95
96     if(verbose)
97       std::cout << "[USRP_RX_STUB] Starting...\n";
98     
99     if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
100       read_and_respond(data);
101   }
102 }
103
104 void
105 usrp_rx_stub::read_and_respond(pmt_t data)
106 {
107
108   while(!usrp_rx_stop) {
109
110     long nsamples_this_frame = d_samples_per_frame;
111
112     size_t nshorts = 2 * nsamples_this_frame;   // 16-bit I & Q
113     long channel = 0;
114     long n_bytes = nshorts*2;
115     pmt_t uvec = pmt_make_s16vector(nshorts, 0);
116     size_t ignore;
117     int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
118
119     // fill in the complex sinusoid
120
121     for (int i = 0; i < nsamples_this_frame; i++){
122
123       if (1){
124         gr_complex s;
125         d_nco.sincos(&s, 1, d_amplitude);
126         // write 16-bit i & q
127         samples[2*i] =   (int16_t) s.real();
128         samples[2*i+1] = (int16_t) s.imag();
129       }
130       else {
131         gr_complex s(d_amplitude, d_amplitude);
132
133         // write 16-bit i & q
134         samples[2*i] =   (int16_t) s.real();
135         samples[2*i+1] = (int16_t) s.imag();
136       }
137     }
138     
139     if(d_disk_write)
140       d_ofile.write((const char *)samples, n_bytes);
141   
142     pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
143     transport_pkt *pkt =
144       (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
145
146     pkt->set_header(0, channel, 0, n_bytes);
147     pkt->set_timestamp(0xffffffff);
148     memcpy(pkt->payload(), samples, n_bytes);
149     
150     d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
151
152     // Now lets check the shared CS queue between the TX and RX stub.  Each
153     // element in a queue is a list where the first element is an invocation
154     // handle and the second element is a PMT u8 vect representation of the
155     // CS packet response which can just be passed transparently.
156     while(!d_cs_queue.empty()) {
157       
158       pmt_t cs_pkt = d_cs_queue.front();
159       d_cs_queue.pop();
160
161       pmt_t invocation_handle = pmt_nth(0, cs_pkt);
162       pmt_t v_pkt = pmt_nth(1, cs_pkt);
163
164       d_cs->send(s_response_usrp_rx_read,   
165                  pmt_list3(invocation_handle, 
166                            PMT_T, 
167                            v_pkt));  // Take the front CS pkt
168
169       
170       if(verbose)
171         std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
172     }
173
174   }
175   
176   usrp_rx_stop = false;
177
178   if(verbose)
179     std::cout << "[USRP_RX_STUB] Got fake RX stop\n";
180
181 }
182
183 REGISTER_MBLOCK_CLASS(usrp_rx_stub);