diff options
Diffstat (limited to 'usrp/host/lib/inband/usrp_rx_stub.cc')
-rw-r--r-- | usrp/host/lib/inband/usrp_rx_stub.cc | 181 |
1 files changed, 112 insertions, 69 deletions
diff --git a/usrp/host/lib/inband/usrp_rx_stub.cc b/usrp/host/lib/inband/usrp_rx_stub.cc index 4bdb106b1..1c96b7a7a 100644 --- a/usrp/host/lib/inband/usrp_rx_stub.cc +++ b/usrp/host/lib/inband/usrp_rx_stub.cc @@ -43,7 +43,7 @@ typedef usrp_inband_usb_packet transport_pkt; static const bool verbose = false; -bool usrp_rx_stop; +bool usrp_rx_stop_stub; // Used for the fake control packet response code to send the responses back up // the RX. The TX stub dumps responses in to this queue. @@ -52,15 +52,32 @@ std::queue<pmt_t> d_cs_queue; usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg) : mb_mblock(rt, instance_name, user_arg), d_samples_per_frame((long)(126)), + d_decim_rx(128), d_amplitude(16384), d_disk_write(false) { + + // Information about the rates are passed all the way from the app in the form + // of a dictionary. We use this to read the RX decimation rate and compute + // the approximate number of MS/s as a form of flow control for the stub. + pmt_t usrp_dict = user_arg; + + if (pmt_is_dict(usrp_dict)) { + // Read the RX decimation rate + if(pmt_t decim_rx = pmt_dict_ref(usrp_dict, + pmt_intern("decim-rx"), + PMT_NIL)) { + if(!pmt_eqv(decim_rx, PMT_NIL)) + d_decim_rx = pmt_to_long(decim_rx); + } + } + d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL); // initialize NCO double freq = 100e3; int interp = 32; // 32 -> 4MS/s - double sample_rate = 128e6 / interp; + double sample_rate = 64e6 / interp; d_nco.set_freq(2*M_PI * freq/sample_rate); //d_disk_write = true; @@ -68,7 +85,7 @@ usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt if(d_disk_write) d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out); - usrp_rx_stop = false; + usrp_rx_stop_stub = false; } usrp_rx_stub::~usrp_rx_stub() @@ -80,7 +97,6 @@ usrp_rx_stub::~usrp_rx_stub() void usrp_rx_stub::initial_transition() { - } void @@ -90,94 +106,121 @@ usrp_rx_stub::handle_message(mb_message_sptr msg) pmt_t port_id = msg->port_id(); pmt_t data = msg->data(); + if (pmt_eq(msg->signal(), s_timeout) + && !pmt_eq(msg->data(), s_done)) { + + if(!usrp_rx_stop_stub) + read_and_respond(); + else { // requested to stop + cancel_timeout(msg->metadata()); + usrp_rx_stop_stub=false; + if(verbose) + std::cout << "[USRP_RX_STUB] Stopping RX stub\n"; + } + + } + // Theoretically only have 1 message to ever expect, but // want to make sure its at least what we want - if(pmt_eq(port_id, d_cs->port_symbol())) { + if(pmt_eq(port_id, d_cs->port_symbol()) + && pmt_eqv(event, s_cmd_usrp_rx_start_reading)) { if(verbose) - std::cout << "[USRP_RX_STUB] Starting...\n"; + std::cout << "[USRP_RX_STUB] Starting with decim @ " + << d_decim_rx << std::endl; - if(pmt_eqv(event, s_cmd_usrp_rx_start_reading)) - read_and_respond(data); + start_packet_timer(); } } +// Setup a periodic timer which will drive packet generation void -usrp_rx_stub::read_and_respond(pmt_t data) +usrp_rx_stub::start_packet_timer() { + d_t0 = mb_time::time(); // current time + + // Calculate the inter-packet arrival time. + double samples_per_sec = (64.0/(double)d_decim_rx)*1000000.0; + double frames_per_sec = samples_per_sec / (double)d_samples_per_frame; + double frame_rate = 1.0 / frames_per_sec; + + if(verbose) { + std::cout << "[USRP_RX_STUB] Scheduling periodic packet generator\n"; + std::cout << "\tsamples_per_sec: " << samples_per_sec << std::endl; + std::cout << "\tframes_per_sec: " << frames_per_sec << std::endl; + std::cout << "\tframe_rate: " << frame_rate << std::endl; + } - while(!usrp_rx_stop) { + schedule_periodic_timeout(d_t0 + frame_rate, mb_time(frame_rate), PMT_T); +} - long nsamples_this_frame = d_samples_per_frame; +void +usrp_rx_stub::read_and_respond() +{ - size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q - long channel = 0; - long n_bytes = nshorts*2; - pmt_t uvec = pmt_make_s16vector(nshorts, 0); - size_t ignore; - int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore); + long nsamples_this_frame = d_samples_per_frame; - // fill in the complex sinusoid + size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q + long channel = 0; + long n_bytes = nshorts*2; + pmt_t uvec = pmt_make_s16vector(nshorts, 0); + size_t ignore; + int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore); - for (int i = 0; i < nsamples_this_frame; i++){ + // fill in the complex sinusoid - if (1){ - gr_complex s; - d_nco.sincos(&s, 1, d_amplitude); - // write 16-bit i & q - samples[2*i] = (int16_t) s.real(); - samples[2*i+1] = (int16_t) s.imag(); - } - else { - gr_complex s(d_amplitude, d_amplitude); + for (int i = 0; i < nsamples_this_frame; i++){ - // write 16-bit i & q - samples[2*i] = (int16_t) s.real(); - samples[2*i+1] = (int16_t) s.imag(); - } + if (1){ + gr_complex s; + d_nco.sincos(&s, 1, d_amplitude); + // write 16-bit i & q + samples[2*i] = (int16_t) s.real(); + samples[2*i+1] = (int16_t) s.imag(); } - - if(d_disk_write) - d_ofile.write((const char *)samples, n_bytes); - - pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0); - transport_pkt *pkt = - (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore); + else { + gr_complex s(d_amplitude, d_amplitude); - pkt->set_header(0, channel, 0, n_bytes); - pkt->set_timestamp(0xffffffff); - memcpy(pkt->payload(), samples, n_bytes); - - d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt)); - - // Now lets check the shared CS queue between the TX and RX stub. Each - // element in a queue is a list where the first element is an invocation - // handle and the second element is a PMT u8 vect representation of the - // CS packet response which can just be passed transparently. - while(!d_cs_queue.empty()) { - - pmt_t cs_pkt = d_cs_queue.front(); - d_cs_queue.pop(); - - pmt_t invocation_handle = pmt_nth(0, cs_pkt); - pmt_t v_pkt = pmt_nth(1, cs_pkt); - - d_cs->send(s_response_usrp_rx_read, - pmt_list3(invocation_handle, - PMT_T, - v_pkt)); // Take the front CS pkt - - - if(verbose) - std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n"; + // write 16-bit i & q + samples[2*i] = (int16_t) s.real(); + samples[2*i+1] = (int16_t) s.imag(); } - } - usrp_rx_stop = false; + if(d_disk_write) + d_ofile.write((const char *)samples, n_bytes); + + pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0); + transport_pkt *pkt = + (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore); + + pkt->set_header(0, channel, 0, n_bytes); + pkt->set_timestamp(0xffffffff); + memcpy(pkt->payload(), samples, n_bytes); + + d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt)); - if(verbose) - std::cout << "[USRP_RX_STUB] Got fake RX stop\n"; + // Now lets check the shared CS queue between the TX and RX stub. Each + // element in a queue is a list where the first element is an invocation + // handle and the second element is a PMT u8 vect representation of the + // CS packet response which can just be passed transparently. + while(!d_cs_queue.empty()) { + + pmt_t cs_pkt = d_cs_queue.front(); + d_cs_queue.pop(); + + pmt_t invocation_handle = pmt_nth(0, cs_pkt); + pmt_t v_pkt = pmt_nth(1, cs_pkt); + + d_cs->send(s_response_usrp_rx_read, + pmt_list3(invocation_handle, + PMT_T, + v_pkt)); // Take the front CS pkt + + + if(verbose) + std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n"; + } } |