diff options
Diffstat (limited to 'usrp2/host/lib')
-rw-r--r-- | usrp2/host/lib/Makefile.am | 9 | ||||
-rw-r--r-- | usrp2/host/lib/control.cc | 23 | ||||
-rw-r--r-- | usrp2/host/lib/control.h | 34 | ||||
-rw-r--r-- | usrp2/host/lib/ring.cc | 14 | ||||
-rw-r--r-- | usrp2/host/lib/ring.h | 8 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2.cc | 62 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.cc | 379 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_impl.h | 40 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_thread.cc | 64 | ||||
-rw-r--r-- | usrp2/host/lib/usrp2_thread.h | 47 |
10 files changed, 382 insertions, 298 deletions
diff --git a/usrp2/host/lib/Makefile.am b/usrp2/host/lib/Makefile.am index 772cf1446..cda051bb0 100644 --- a/usrp2/host/lib/Makefile.am +++ b/usrp2/host/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2007,2008 Free Software Foundation, Inc. +# Copyright 2007,2008,2010 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -45,11 +45,9 @@ libusrp2_la_SOURCES = \ rx_sample_handler.cc \ strtod_si.c \ usrp2.cc \ - usrp2_impl.cc \ - usrp2_thread.cc + usrp2_impl.cc libusrp2_la_LIBADD = \ - $(OMNITHREAD_LA) \ $(GRUEL_LA) \ $(BOOST_LDFLAGS) $(BOOST_THREAD_LIB) @@ -63,5 +61,4 @@ noinst_HEADERS = \ pktfilter.h \ ring.h \ usrp2_bytesex.h \ - usrp2_impl.h \ - usrp2_thread.h + usrp2_impl.h
\ No newline at end of file diff --git a/usrp2/host/lib/control.cc b/usrp2/host/lib/control.cc index bb71f79c2..33a95c078 100644 --- a/usrp2/host/lib/control.cc +++ b/usrp2/host/lib/control.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,14 +23,14 @@ #include <config.h> #endif -#include <gnuradio/omni_time.h> #include "control.h" #include <iostream> +#include <gruel/thread.h> namespace usrp2 { pending_reply::pending_reply(unsigned int rid, void *buffer, size_t len) - : d_rid(rid), d_buffer(buffer), d_len(len), d_mutex(), d_cond(&d_mutex), + : d_rid(rid), d_buffer(buffer), d_len(len), d_mutex(), d_cond(), d_complete(false) { } @@ -43,22 +43,23 @@ namespace usrp2 { int pending_reply::wait_for_completion(double secs) { - omni_time abs_timeout = omni_time::time(omni_time(secs)); - omni_mutex_lock l(d_mutex); - while (!d_complete){ - int r = d_cond.timedwait(abs_timeout.d_secs, abs_timeout.d_nsecs); - if (r == 0) // timed out - return 0; + gruel::scoped_lock l(d_mutex); + boost::system_time to(gruel::get_new_timeout(secs)); + + while (!d_complete) { + if (!d_cond.timed_wait(l, to)) + return 0; // timed out } + return 1; } void pending_reply::notify_completion() { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); d_complete = true; - d_cond.signal(); + d_cond.notify_one(); } } // namespace usrp2 diff --git a/usrp2/host/lib/control.h b/usrp2/host/lib/control.h index 8769e4522..3515ba10f 100644 --- a/usrp2/host/lib/control.h +++ b/usrp2/host/lib/control.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ #ifndef INCLUDED_CONTROL_H #define INCLUDED_CONTROL_H -#include <gnuradio/omnithread.h> +#include <gruel/thread.h> #include <usrp2_eth_packet.h> namespace usrp2 { @@ -33,27 +33,35 @@ namespace usrp2 { /*! * OP_CONFIG_RX_V2 command packet */ - struct op_config_rx_v2_cmd + struct op_config_rx_v2_cmd { u2_eth_packet_t h; op_config_rx_v2_t op; op_generic_t eop; }; - struct op_start_rx_streaming_cmd + struct op_start_rx_streaming_cmd { u2_eth_packet_t h; op_start_rx_streaming_t op; op_generic_t eop; }; - + + struct op_sync_and_start_rx_streaming_cmd + { + u2_eth_packet_t h; + op_generic_t sync_op; + op_start_rx_streaming_t rx_op; + op_generic_t eop; + }; + struct op_stop_rx_cmd { u2_eth_packet_t h; op_generic_t op; op_generic_t eop; }; - struct op_config_tx_v2_cmd + struct op_config_tx_v2_cmd { u2_eth_packet_t h; op_config_tx_v2_t op; @@ -67,7 +75,7 @@ namespace usrp2 { op_generic_t eop; }; - struct op_burn_mac_addr_cmd + struct op_burn_mac_addr_cmd { u2_eth_packet_t h; op_burn_mac_addr_t op; @@ -113,20 +121,20 @@ namespace usrp2 { /*! * Control mechanism to allow API calls to block waiting for reply packets - */ + */ class pending_reply { private: unsigned int d_rid; void *d_buffer; size_t d_len; - + // d_mutex is used with d_cond and also protects d_complete - omni_mutex d_mutex; - omni_condition d_cond; + gruel::mutex d_mutex; + gruel::condition_variable d_cond; bool d_complete; - public: + public: /*! * Construct a pending reply from the reply ID, response packet * buffer, and buffer length. @@ -165,7 +173,7 @@ namespace usrp2 { */ size_t len() const { return d_len; } }; - + } // namespace usrp2 #endif /* INCLUDED_CONTROL_H */ diff --git a/usrp2/host/lib/ring.cc b/usrp2/host/lib/ring.cc index 3c45821f8..d0048418c 100644 --- a/usrp2/host/lib/ring.cc +++ b/usrp2/host/lib/ring.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -29,7 +29,7 @@ namespace usrp2 { ring::ring(unsigned int entries) : d_max(entries), d_read_ind(0), d_write_ind(0), d_ring(entries), - d_mutex(), d_not_empty(&d_mutex) + d_mutex(), d_not_empty() { for (unsigned int i = 0; i < entries; i++) { d_ring[i].d_base = 0; @@ -40,15 +40,15 @@ namespace usrp2 { void ring::wait_for_not_empty() { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); while (empty()) - d_not_empty.wait(); + d_not_empty.wait(l); } bool ring::enqueue(void *p, size_t len) { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); if (full()) return false; @@ -56,14 +56,14 @@ namespace usrp2 { d_ring[d_write_ind].d_base = p; inc_write_ind(); - d_not_empty.signal(); + d_not_empty.notify_one(); return true; } bool ring::dequeue(void **p, size_t *len) { - omni_mutex_lock l(d_mutex); + gruel::scoped_lock l(d_mutex); if (empty()) return false; diff --git a/usrp2/host/lib/ring.h b/usrp2/host/lib/ring.h index 19ae9ae97..fd0ad0a9f 100644 --- a/usrp2/host/lib/ring.h +++ b/usrp2/host/lib/ring.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2010 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -21,10 +21,10 @@ #ifndef INCLUDED_RING_H #define INCLUDED_RING_H -#include <gnuradio/omnithread.h> #include <stddef.h> #include <vector> #include <boost/shared_ptr.hpp> +#include <gruel/thread.h> namespace usrp2 { @@ -46,8 +46,8 @@ namespace usrp2 { }; std::vector<ring_desc> d_ring; - omni_mutex d_mutex; - omni_condition d_not_empty; + gruel::mutex d_mutex; + gruel::condition_variable d_not_empty; void inc_read_ind() { diff --git a/usrp2/host/lib/usrp2.cc b/usrp2/host/lib/usrp2.cc index a2a9ecc11..f0ee564be 100644 --- a/usrp2/host/lib/usrp2.cc +++ b/usrp2/host/lib/usrp2.cc @@ -62,7 +62,7 @@ namespace usrp2 { else { if (key == p->key) // found it return usrp2::sptr(p->value); - else + else ++p; // keep looking } } @@ -90,15 +90,15 @@ namespace usrp2 { p.addr[3] = 0x85; p.addr[4] = 0x30; p.addr[5] = 0x00; - + int len = s.size(); switch (len) { - + case 5: if (sscanf(s.c_str(), "%hhx:%hhx", &p.addr[4], &p.addr[5]) != 2) return false; break; - + case 17: if (sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &p.addr[0], &p.addr[1], &p.addr[2], @@ -109,7 +109,7 @@ namespace usrp2 { default: return false; } - + char buf[128]; snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", @@ -148,13 +148,13 @@ namespace usrp2 { { // NOP } - + // Public class destructor. d_impl will auto-delete. usrp2::~usrp2() { // NOP } - + std::string usrp2::mac_addr() { @@ -169,12 +169,17 @@ namespace usrp2 { // Receive - bool + bool + usrp2::set_rx_antenna(int ant){ + return d_impl->set_rx_antenna(ant); + } + + bool usrp2::set_rx_gain(double gain) { return d_impl->set_rx_gain(gain); } - + double usrp2::rx_gain_min() { @@ -204,7 +209,7 @@ namespace usrp2 { { return d_impl->set_rx_center_freq(frequency, result); } - + double usrp2::rx_freq_min() { @@ -222,7 +227,7 @@ namespace usrp2 { { return d_impl->set_rx_decim(decimation_factor); } - + int usrp2::rx_decim() { @@ -234,13 +239,25 @@ namespace usrp2 { { return d_impl->set_rx_scale_iq(scale_i, scale_q); } - + bool usrp2::start_rx_streaming(unsigned int channel, unsigned int items_per_frame) { return d_impl->start_rx_streaming(channel, items_per_frame); } - + + bool + usrp2::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time) + { + return d_impl->start_rx_streaming_at(channel, items_per_frame,time); + } + + bool + usrp2::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time) + { + return d_impl->sync_and_start_rx_streaming_at(channel, items_per_frame, time); + } + bool usrp2::rx_samples(unsigned int channel, rx_sample_handler *handler) { @@ -258,7 +275,7 @@ namespace usrp2 { { return d_impl->rx_overruns(); } - + unsigned int usrp2::rx_missing() { @@ -267,12 +284,17 @@ namespace usrp2 { // Transmit - bool + bool + usrp2::set_tx_antenna(int ant){ + return d_impl->set_tx_antenna(ant); + } + + bool usrp2::set_tx_gain(double gain) { return d_impl->set_tx_gain(gain); } - + double usrp2::tx_gain_min() { @@ -302,7 +324,7 @@ namespace usrp2 { { return d_impl->set_tx_center_freq(frequency, result); } - + double usrp2::tx_freq_min() { @@ -321,7 +343,7 @@ namespace usrp2 { { return d_impl->set_tx_interp(interpolation_factor); } - + int usrp2::tx_interp() { @@ -339,7 +361,7 @@ namespace usrp2 { { return d_impl->set_tx_scale_iq(scale_i, scale_q); } - + bool usrp2::tx_32fc(unsigned int channel, const std::complex<float> *samples, @@ -404,7 +426,7 @@ namespace usrp2 { { return d_impl->rx_daughterboard_id(dbid); } - + // low level methods diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc index 3d0304324..333e2d1e7 100644 --- a/usrp2/host/lib/usrp2_impl.cc +++ b/usrp2/host/lib/usrp2_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,9 +24,10 @@ #include <usrp2/tune_result.h> #include <usrp2/copiers.h> #include <gruel/inet.h> +#include <gruel/realtime.h> +#include <boost/bind.hpp> #include <usrp2_types.h> #include "usrp2_impl.h" -#include "usrp2_thread.h" #include "eth_buffer.h" #include "pktfilter.h" #include "control.h" @@ -106,7 +107,7 @@ namespace usrp2 { //assert((((uintptr_t) p) % 4) == 0); // must be 4-byte aligned u2_fixed_hdr_t *fh = static_cast<u2_fixed_hdr_t *>(p); - + // FIXME unaligned loads! md->word0 = u2p_word0(fh); md->timestamp = u2p_timestamp(fh); @@ -129,15 +130,15 @@ namespace usrp2 { usrp2::impl::impl(const std::string &ifc, props *p, size_t rx_bufsize) - : d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_thread(0), + : d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_running(false), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0), - d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0), - d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex), + d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0), + d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(), d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0), d_dont_enqueue(true) { if (!d_eth_buf->open(ifc, htons(U2_ETHERTYPE))) throw std::runtime_error("Unable to register USRP2 protocol"); - + d_addr = p->addr; // Create a packet filter for U2_ETHERTYPE packets sourced from target USRP2 @@ -146,14 +147,14 @@ namespace usrp2 { d_pf = pktfilter::make_ethertype_inbound_target(U2_ETHERTYPE, (const unsigned char*)&(usrp_mac.addr)); if (!d_pf || !d_eth_buf->attach_pktfilter(d_pf)) throw std::runtime_error("Unable to attach packet filter."); - + if (USRP2_IMPL_DEBUG) std::cerr << "usrp2 constructor: using USRP2 at " << d_addr << std::endl; memset(d_pending_replies, 0, sizeof(d_pending_replies)); - d_bg_thread = new usrp2_thread(this); - d_bg_thread->start(); + // Kick off receive thread + start_bg(); // In case the USRP2 was left streaming RX // FIXME: only one channel right now @@ -199,30 +200,29 @@ namespace usrp2 { if (!set_rx_decim(12)) std::cerr << "usrp2::ctor set_rx_decim failed\n"; - + // set workable defaults for scaling if (!set_rx_scale_iq(DEFAULT_RX_SCALE, DEFAULT_RX_SCALE)) std::cerr << "usrp2::ctor set_rx_scale_iq failed\n"; } - + usrp2::impl::~impl() { stop_bg(); - d_bg_thread = 0; // thread class deletes itself delete d_pf; d_eth_buf->close(); delete d_eth_buf; - + if (USRP2_IMPL_DEBUG) { std::cerr << std::endl - << "usrp2 destructor: received " << d_num_rx_frames + << "usrp2 destructor: received " << d_num_rx_frames << " frames, with " << d_num_rx_missing << " lost (" << (d_num_rx_frames == 0 ? 0 : (int)(100.0*d_num_rx_missing/d_num_rx_frames)) << "%), totaling " << d_num_rx_bytes << " bytes" << std::endl; } } - + bool usrp2::impl::parse_mac_addr(const std::string &s, u2_mac_addr_t *p) { @@ -232,14 +232,14 @@ namespace usrp2 { p->addr[3] = 0x85; p->addr[4] = 0x30; p->addr[5] = 0x00; - + int len = s.size(); - + switch (len){ - + case 5: return sscanf(s.c_str(), "%hhx:%hhx", &p->addr[4], &p->addr[5]) == 2; - + case 17: return sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &p->addr[0], &p->addr[1], &p->addr[2], @@ -248,36 +248,36 @@ namespace usrp2 { return false; } } - + void usrp2::impl::init_et_hdrs(u2_eth_packet_t *p, const std::string &dst) { p->ehdr.ethertype = htons(U2_ETHERTYPE); - parse_mac_addr(dst, &p->ehdr.dst); + parse_mac_addr(dst, &p->ehdr.dst); memcpy(&p->ehdr.src, d_eth_buf->mac(), 6); p->thdr.flags = 0; // FIXME transport header values? p->thdr.seqno = d_tx_seqno++; p->thdr.ack = 0; } - - void + + void usrp2::impl::init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst, int word0_flags, int chan, uint32_t timestamp) { init_et_hdrs(p, dst); u2p_set_word0(&p->fixed, word0_flags, chan); u2p_set_timestamp(&p->fixed, timestamp); - + if (chan == CONTROL_CHAN) { // no sequence numbers, back it out p->thdr.seqno = 0; d_tx_seqno--; } } - + void usrp2::impl::init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd) { - memset(cmd, 0, sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1); cmd->op.opcode = OP_CONFIG_RX_V2; cmd->op.len = sizeof(cmd->op); @@ -289,7 +289,7 @@ namespace usrp2 { void usrp2::impl::init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd) { - memset(cmd, 0, sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1); cmd->op.opcode = OP_CONFIG_TX_V2; cmd->op.len = sizeof(cmd->op); @@ -320,7 +320,7 @@ namespace usrp2 { usrp2::impl::transmit_cmd_and_wait(void *cmd, size_t len, pending_reply *p, double secs) { d_pending_replies[p->rid()] = p; - + if (!transmit_cmd(cmd, len)){ d_pending_replies[p->rid()] = 0; return false; @@ -336,18 +336,24 @@ namespace usrp2 { // ---------------------------------------------------------------- void + usrp2::impl::start_bg() + { + d_rx_tg.create_thread(boost::bind(&usrp2::impl::bg_loop, this)); + } + + void usrp2::impl::stop_bg() { d_bg_running = false; - d_bg_pending_cond.signal(); - - void *dummy_status; - d_bg_thread->join(&dummy_status); + d_bg_pending_cond.notify_one(); // FIXME: check if needed + d_rx_tg.join_all(); } - + void usrp2::impl::bg_loop() { + gruel::enable_realtime_scheduling(); + d_bg_running = true; while(d_bg_running) { DEBUG_LOG(":"); @@ -356,20 +362,20 @@ namespace usrp2 { // rings, and signal blocked API threads int res = d_eth_buf->rx_frames(this, 100); // FIXME magic timeout if (res == eth_buffer::EB_ERROR) - break; + break; // Wait for user API thread(s) to process all enqueued packets. - // The channel ring thread that decrements d_num_enqueued to zero + // The channel ring thread that decrements d_num_enqueued to zero // will signal this thread to continue. { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); while(d_num_enqueued > 0 && d_bg_running) - d_bg_pending_cond.wait(); + d_bg_pending_cond.wait(l); } } d_bg_running = false; } - + // // passed to eth_buffer::rx_frames // @@ -401,11 +407,11 @@ namespace usrp2 { { // point to beginning of payload (subpackets) unsigned char *p = (unsigned char *)base + sizeof(u2_eth_packet_t); - + // FIXME (p % 4) == 2. Not good. Must watch for unaligned loads. // FIXME iterate over payload, handling more than a single subpacket. - + int opcode = p[0]; unsigned int oplen = p[1]; unsigned int rid = p[2]; @@ -417,8 +423,8 @@ namespace usrp2 { std::cerr << "usrp2: mismatched command reply length (expected: " << buflen << " got: " << oplen << "). " << "op = " << opcode_to_string(opcode) << std::endl; - } - + } + // Copy reply into caller's buffer memcpy(rp->buffer(), p, std::min(oplen, buflen)); rp->notify_completion(); @@ -430,26 +436,26 @@ namespace usrp2 { DEBUG_LOG("l"); return data_handler::RELEASE; } - + data_handler::result usrp2::impl::handle_data_packet(const void *base, size_t len) { u2_eth_samples_t *pkt = (u2_eth_samples_t *)base; d_num_rx_frames++; d_num_rx_bytes += len; - + /* --- FIXME start of fake transport layer handler --- */ if (d_rx_seqno != -1) { int expected_seqno = (d_rx_seqno + 1) & 0xFF; - int seqno = pkt->hdrs.thdr.seqno; - + int seqno = pkt->hdrs.thdr.seqno; + if (seqno != expected_seqno) { ::write(2, "S", 1); // missing sequence number int missing = seqno - expected_seqno; if (missing < 0) missing += 256; - + d_num_rx_overruns++; d_num_rx_missing += missing; } @@ -463,15 +469,15 @@ namespace usrp2 { unsigned int chan = u2p_chan(&pkt->hdrs.fixed); { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); if (!d_channel_rings[chan]) { DEBUG_LOG("!"); return data_handler::RELEASE; // discard packet, no channel handler } - + // Strip off ethernet header and transport header and enqueue the rest - + size_t offset = offsetof(u2_eth_samples_t, hdrs.fixed); if (d_channel_rings[chan]->enqueue(&pkt->hdrs.fixed, len-offset)) { inc_enqueued(); @@ -481,7 +487,7 @@ namespace usrp2 { else { DEBUG_LOG("!"); return data_handler::RELEASE; // discard, no room in channel ring - } + } return data_handler::RELEASE; } } @@ -491,7 +497,28 @@ namespace usrp2 { // Receive // ---------------------------------------------------------------- - bool + bool + usrp2::impl::set_rx_antenna(int ant){ + op_config_mimo_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_RX_ANTENNA; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.op.flags = ant; + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) + return false; + + return ntohx(reply.ok) == 1; + } + + bool usrp2::impl::set_rx_gain(double gain) { op_config_rx_v2_cmd cmd; @@ -500,7 +527,7 @@ namespace usrp2 { init_config_rx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_GAIN); cmd.op.gain = htons(u2_double_to_fxpt_gain(gain)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -508,7 +535,7 @@ namespace usrp2 { bool success = (ntohx(reply.ok) == 1); return success; } - + bool usrp2::impl::set_rx_lo_offset(double frequency) { @@ -527,7 +554,7 @@ namespace usrp2 { cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -547,7 +574,7 @@ namespace usrp2 { u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency); cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt)); cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -555,18 +582,18 @@ namespace usrp2 { bool success = (ntohx(reply.ok) == 1); if (result && success) { result->baseband_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi), ntohl(reply.baseband_freq_lo))); result->dxc_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.ddc_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.ddc_freq_hi), ntohl(reply.ddc_freq_lo))); result->residual_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi), ntohl(reply.residual_freq_lo))); result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1); @@ -574,7 +601,7 @@ namespace usrp2 { return success; } - + bool usrp2::impl::set_rx_decim(int decimation_factor) { @@ -584,7 +611,7 @@ namespace usrp2 { init_config_rx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_INTERP_DECIM); cmd.op.decim = htonl(decimation_factor); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -594,7 +621,7 @@ namespace usrp2 { d_rx_decim = decimation_factor; return success; } - + bool usrp2::impl::set_rx_scale_iq(int scale_i, int scale_q) { @@ -604,7 +631,7 @@ namespace usrp2 { init_config_rx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_SCALE_IQ); cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -612,7 +639,7 @@ namespace usrp2 { bool success = (ntohx(reply.ok) == 1); return success; } - + bool usrp2::impl::start_rx_streaming(unsigned int channel, unsigned int items_per_frame) { @@ -629,16 +656,16 @@ namespace usrp2 { } { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); if (d_channel_rings[channel]) { std::cerr << "usrp2: channel " << channel << " already streaming" << std::endl; return false; } - + if (items_per_frame == 0) items_per_frame = U2_MAX_SAMPLES; // minimize overhead - + op_start_rx_streaming_cmd cmd; op_generic_t reply; @@ -650,13 +677,13 @@ namespace usrp2 { cmd.op.items_per_frame = htonl(items_per_frame); cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + d_dont_enqueue = false; bool success = false; pending_reply p(cmd.op.rid, &reply, sizeof(reply)); success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT); success = success && (ntohx(reply.ok) == 1); - + if (success) d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames())); else @@ -666,7 +693,117 @@ namespace usrp2 { return success; } } - + + bool + usrp2::impl::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time) + { + if (channel > MAX_CHAN) { + std::cerr << "usrp2: invalid channel number (" << channel + << ")" << std::endl; + return false; + } + + if (channel > 0) { // until firmware supports multiple streams + std::cerr << "usrp2: channel " << channel + << " not implemented" << std::endl; + return false; + } + + { + gruel::scoped_lock guard(d_channel_rings_mutex); + if (d_channel_rings[channel]) { + std::cerr << "usrp2: channel " << channel + << " already streaming" << std::endl; + return false; + } + + if (items_per_frame == 0) + items_per_frame = U2_MAX_SAMPLES; // minimize overhead + + op_start_rx_streaming_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time); + cmd.op.opcode = OP_START_RX_STREAMING; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.op.items_per_frame = htonl(items_per_frame); + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + d_dont_enqueue = false; + bool success = false; + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT); + success = success && (ntohx(reply.ok) == 1); + + if (success) + d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames())); + else + d_dont_enqueue = true; + + return success; + } + } + + bool + usrp2::impl::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time) + { + + if (channel > MAX_CHAN) { + std::cerr << "usrp2: invalid channel number (" << channel + << ")" << std::endl; + return false; + } + + if (channel > 0) { // until firmware supports multiple streams + std::cerr << "usrp2: channel " << channel + << " not implemented" << std::endl; + return false; + } + + { + gruel::scoped_lock guard(d_channel_rings_mutex); + if (d_channel_rings[channel]) { + std::cerr << "usrp2: channel " << channel + << " already streaming" << std::endl; + return false; + } + + if (items_per_frame == 0) + items_per_frame = U2_MAX_SAMPLES; // minimize overhead + + op_sync_and_start_rx_streaming_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time); + cmd.sync_op.opcode = OP_SYNC_TO_PPS; + cmd.sync_op.len = sizeof(cmd.sync_op); + cmd.sync_op.rid = d_next_rid++; + cmd.rx_op.opcode = OP_START_RX_STREAMING; + cmd.rx_op.len = sizeof(cmd.rx_op); + cmd.rx_op.rid = d_next_rid++; + cmd.rx_op.items_per_frame = htonl(items_per_frame); + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + d_dont_enqueue = false; + bool success = false; + pending_reply p(cmd.sync_op.rid, &reply, sizeof(reply)); + success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT); + success = success && (ntohx(reply.ok) == 1); + + if (success) + d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames())); + else + d_dont_enqueue = true; + + return success; + } + } + bool usrp2::impl::stop_rx_streaming(unsigned int channel) { @@ -689,7 +826,7 @@ namespace usrp2 { op_generic_t reply; { - omni_mutex_lock l(d_channel_rings_mutex); + gruel::scoped_lock l(d_channel_rings_mutex); memset(&cmd, 0, sizeof(cmd)); init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); @@ -698,12 +835,13 @@ namespace usrp2 { cmd.op.rid = d_next_rid++; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + bool success = false; pending_reply p(cmd.op.rid, &reply, sizeof(reply)); success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT); success = success && (ntohx(reply.ok) == 1); d_channel_rings[channel].reset(); + d_rx_seqno = -1; //fprintf(stderr, "usrp2::stop_rx_streaming: success = %d\n", success); return success; } @@ -717,25 +855,25 @@ namespace usrp2 { << " )" << std::endl; return false; } - + if (channel > 0) { std::cerr << "usrp2: channel " << channel << " not implemented" << std::endl; return false; } - + ring_sptr rp = d_channel_rings[channel]; if (!rp){ std::cerr << "usrp2: channel " << channel << " not receiving" << std::endl; return false; } - + // Wait for frames available in channel ring DEBUG_LOG("W"); rp->wait_for_not_empty(); DEBUG_LOG("s"); - + // Iterate through frames and present to user void *p; size_t frame_len_in_bytes; @@ -791,7 +929,28 @@ namespace usrp2 { // Transmit // ---------------------------------------------------------------- - bool + bool + usrp2::impl::set_tx_antenna(int ant){ + op_config_mimo_cmd cmd; + op_generic_t reply; + + memset(&cmd, 0, sizeof(cmd)); + init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1); + cmd.op.opcode = OP_TX_ANTENNA; + cmd.op.len = sizeof(cmd.op); + cmd.op.rid = d_next_rid++; + cmd.op.flags = ant; + cmd.eop.opcode = OP_EOP; + cmd.eop.len = sizeof(cmd.eop); + + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); + if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) + return false; + + return ntohx(reply.ok) == 1; + } + + bool usrp2::impl::set_tx_gain(double gain) { op_config_tx_v2_cmd cmd; @@ -800,7 +959,7 @@ namespace usrp2 { init_config_tx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_GAIN); cmd.op.gain = htons(u2_double_to_fxpt_gain(gain)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -808,7 +967,7 @@ namespace usrp2 { bool success = (ntohx(reply.ok) == 1); return success; } - + bool usrp2::impl::set_tx_lo_offset(double frequency) { @@ -827,7 +986,7 @@ namespace usrp2 { cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -847,7 +1006,7 @@ namespace usrp2 { u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency); cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt)); cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -855,18 +1014,18 @@ namespace usrp2 { bool success = (ntohx(reply.ok) == 1); if (result && success) { result->baseband_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi), ntohl(reply.baseband_freq_lo))); result->dxc_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi), ntohl(reply.duc_freq_lo))); result->residual_freq = - u2_fxpt_freq_to_double( - u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi), + u2_fxpt_freq_to_double( + u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi), ntohl(reply.residual_freq_lo))); result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1); @@ -874,7 +1033,7 @@ namespace usrp2 { return success; } - + bool usrp2::impl::set_tx_interp(int interpolation_factor) { @@ -884,7 +1043,7 @@ namespace usrp2 { init_config_tx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_INTERP_DECIM); cmd.op.interp = htonl(interpolation_factor); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -901,7 +1060,7 @@ namespace usrp2 { return success; } - + void usrp2::impl::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q) { @@ -914,7 +1073,7 @@ namespace usrp2 { // Calculate dsp_core_tx gain absent scale multipliers float gain = (1.65*i*i*i)/(4096*pow(2, ceil(log2(i*i*i)))); - + // Calculate closest multiplier constant to reverse gain int scale = (int)rint(1.0/gain); // fprintf(stderr, "if=%i i=%i gain=%f scale=%i\n", interpolation_factor, i, gain, scale); @@ -935,7 +1094,7 @@ namespace usrp2 { init_config_tx_v2_cmd(&cmd); cmd.op.valid = htons(CFGV_SCALE_IQ); cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff)); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1063,7 +1222,7 @@ namespace usrp2 { cmd.op.flags = flags; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1137,10 +1296,10 @@ namespace usrp2 { dst->dbid = ntohl(src->dbid); dst->freq_min = - u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi), + u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi), ntohl(src->freq_min_lo))); dst->freq_max = - u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi), + u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi), ntohl(src->freq_max_lo))); dst->gain_min = u2_fxpt_gain_to_double(ntohs(src->gain_min)); @@ -1161,7 +1320,7 @@ namespace usrp2 { cmd.op.rid = d_next_rid++; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1188,7 +1347,7 @@ namespace usrp2 { cmd.op.rid = d_next_rid++; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1210,7 +1369,7 @@ namespace usrp2 { cmd.op.ok = enable ? 1 : 0; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1225,7 +1384,7 @@ namespace usrp2 { // fprintf(stderr, "usrp2::peek: addr=%08X words=%u\n", addr, words); if (addr % 4 != 0) { - fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr); + fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr); return result; } @@ -1267,7 +1426,7 @@ namespace usrp2 { usrp2::impl::poke32(uint32_t addr, const std::vector<uint32_t> &data) { if (addr % 4 != 0) { - fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr); + fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr); return false; } @@ -1339,7 +1498,7 @@ namespace usrp2 { cmd.op.rid = d_next_rid++; cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1368,7 +1527,7 @@ namespace usrp2 { cmd.op.mask = htons(mask); cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1401,7 +1560,7 @@ namespace usrp2 { memcpy(&cmd.op.sels, sels.c_str(), 16); cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1430,7 +1589,7 @@ namespace usrp2 { cmd.op.mask = htons(mask); cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1459,7 +1618,7 @@ namespace usrp2 { cmd.op.mask = 0; // not used cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; @@ -1496,7 +1655,7 @@ namespace usrp2 { cmd.op.mask = 0; // not used cmd.eop.opcode = OP_EOP; cmd.eop.len = sizeof(cmd.eop); - + pending_reply p(cmd.op.rid, &reply, sizeof(reply)); if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) return false; diff --git a/usrp2/host/lib/usrp2_impl.h b/usrp2/host/lib/usrp2_impl.h index ed71a6ba3..eee26358e 100644 --- a/usrp2/host/lib/usrp2_impl.h +++ b/usrp2/host/lib/usrp2_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2010 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include <usrp2/usrp2.h> #include <usrp2/data_handler.h> #include <usrp2_eth_packet.h> +#include <gruel/thread.h> #include <boost/scoped_ptr.hpp> #include "control.h" #include "ring.h" @@ -30,7 +31,7 @@ #define MAX_SUBPKT_LEN 252 namespace usrp2 { - + class eth_buffer; class pktfilter; class usrp2_thread; @@ -60,9 +61,10 @@ namespace usrp2 { std::string d_interface_name; pktfilter *d_pf; std::string d_addr; // FIXME: use u2_mac_addr_t instead - usrp2_thread *d_bg_thread; + + boost::thread_group d_rx_tg; volatile bool d_bg_running; // TODO: multistate if needed - + int d_rx_seqno; int d_tx_seqno; int d_next_rid; @@ -72,38 +74,39 @@ namespace usrp2 { unsigned int d_num_rx_bytes; unsigned int d_num_enqueued; - omni_mutex d_enqueued_mutex; - omni_condition d_bg_pending_cond; + gruel::mutex d_enqueued_mutex; + gruel::condition_variable d_bg_pending_cond; // all pending_replies are stack allocated, thus no possibility of leaking these pending_reply *d_pending_replies[NRIDS]; // indexed by 8-bit reply id std::vector<ring_sptr> d_channel_rings; // indexed by 5-bit channel number - omni_mutex d_channel_rings_mutex; + gruel::mutex d_channel_rings_mutex; db_info d_tx_db_info; db_info d_rx_db_info; - int d_tx_interp; // shadow tx interp + int d_tx_interp; // shadow tx interp int d_rx_decim; // shadow rx decim bool d_dont_enqueue; void inc_enqueued() { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); d_num_enqueued++; } - + void dec_enqueued() { - omni_mutex_lock l(d_enqueued_mutex); + gruel::scoped_lock l(d_enqueued_mutex); if (--d_num_enqueued == 0) - d_bg_pending_cond.signal(); + d_bg_pending_cond.notify_one(); } - + static bool parse_mac_addr(const std::string &s, u2_mac_addr_t *p); void init_et_hdrs(u2_eth_packet_t *p, const std::string &dst); void init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst, int word0_flags, int chan, uint32_t timestamp); + void start_bg(); void stop_bg(); void init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd); void init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd); @@ -118,14 +121,13 @@ namespace usrp2 { public: impl(const std::string &ifc, props *p, size_t rx_bufsize); ~impl(); - - void bg_loop(); std::string mac_addr() const { return d_addr; } // FIXME: convert from u2_mac_addr_t std::string interface_name() const { return d_interface_name; } // Rx + bool set_rx_antenna(int ant); bool set_rx_gain(double gain); double rx_gain_min() { return d_rx_db_info.gain_min; } double rx_gain_max() { return d_rx_db_info.gain_max; } @@ -143,6 +145,8 @@ namespace usrp2 { bool write_gpio(int bank, uint16_t value, uint16_t mask); bool read_gpio(int bank, uint16_t *value); bool start_rx_streaming(unsigned int channel, unsigned int items_per_frame); + bool start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time); + bool sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time); bool rx_samples(unsigned int channel, rx_sample_handler *handler); bool flush_rx_samples(unsigned int channel); bool stop_rx_streaming(unsigned int channel); @@ -151,6 +155,7 @@ namespace usrp2 { // Tx + bool set_tx_antenna(int ant); bool set_tx_gain(double gain); double tx_gain_min() { return d_tx_db_info.gain_min; } double tx_gain_max() { return d_tx_db_info.gain_max; } @@ -195,8 +200,11 @@ namespace usrp2 { bool sync_every_pps(bool enable); std::vector<uint32_t> peek32(uint32_t addr, uint32_t words); bool poke32(uint32_t addr, const std::vector<uint32_t> &data); + + // Receive thread, need to be public for boost::bind + void bg_loop(); }; - + } // namespace usrp2 #endif /* INCLUDED_USRP2_IMPL_H */ diff --git a/usrp2/host/lib/usrp2_thread.cc b/usrp2/host/lib/usrp2_thread.cc deleted file mode 100644 index d14770395..000000000 --- a/usrp2/host/lib/usrp2_thread.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "usrp2_thread.h" -#include "usrp2_impl.h" -#include <gruel/realtime.h> -#include <gruel/sys_pri.h> -#include <iostream> - -#define USRP2_THREAD_DEBUG 1 - -namespace usrp2 { - - usrp2_thread::usrp2_thread(usrp2::impl *u2) : - omni_thread(NULL, PRIORITY_HIGH), - d_u2(u2) - { - } - - usrp2_thread::~usrp2_thread() - { - // we don't own this, just forget it - d_u2 = 0; - } - - void - usrp2_thread::start() - { - start_undetached(); - } - - void * - usrp2_thread::run_undetached(void *arg) - { - if (gruel::enable_realtime_scheduling(gruel::sys_pri::usrp2_backend()) != gruel::RT_OK) - std::cerr << "usrp2: failed to enable realtime scheduling" << std::endl; - - // This is the first code to run in the new thread context. - d_u2->bg_loop(); - - return 0; - } - -} // namespace usrp2 - diff --git a/usrp2/host/lib/usrp2_thread.h b/usrp2/host/lib/usrp2_thread.h deleted file mode 100644 index 12723e947..000000000 --- a/usrp2/host/lib/usrp2_thread.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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_USRP2_THREAD_H -#define INCLUDED_USRP2_THREAD_H - -#include <gnuradio/omnithread.h> -#include <usrp2_impl.h> - -namespace usrp2 { - - class usrp2_thread : public omni_thread - { - private: - usrp2::impl *d_u2; - - public: - usrp2_thread(usrp2::impl *u2); - ~usrp2_thread(); - - void start(); - - virtual void *run_undetached(void *arg); - }; - -} // namespace usrp2 - -#endif /* INCLUDED_USRP2_THREAD_H */ |