Added call to set antenna. Split XCVR into new thing cuz size.
[debian/gnuradio] / usrp2 / host / lib / usrp2_impl.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008,2009 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <usrp2/usrp2.h>
24 #include <usrp2/tune_result.h>
25 #include <usrp2/copiers.h>
26 #include <gruel/inet.h>
27 #include <usrp2_types.h>
28 #include "usrp2_impl.h"
29 #include "usrp2_thread.h"
30 #include "eth_buffer.h"
31 #include "pktfilter.h"
32 #include "control.h"
33 #include "ring.h"
34 #include <stdexcept>
35 #include <iostream>
36 #include <stdio.h>
37 #include <stddef.h>
38 #include <assert.h>
39 #include <string.h>
40
41 #define USRP2_IMPL_DEBUG 0
42 #if USRP2_IMPL_DEBUG
43 #define DEBUG_LOG(x) ::write(2, x, 1)
44 #else
45 #define DEBUG_LOG(x)
46 #endif
47
48 static const int DEFAULT_RX_SCALE = 1024;
49
50 namespace usrp2 {
51
52   static const double DEF_CMD_TIMEOUT = 0.1;
53
54   std::string
55   opcode_to_string(int opcode)
56   {
57     switch(opcode){
58     case OP_EOP: return "OP_EOP";
59     case OP_ID: return "OP_ID";
60     case OP_ID_REPLY: return "OP_ID_REPLY";
61     case OP_BURN_MAC_ADDR: return "OP_BURN_MAC_ADDR";
62     case OP_READ_TIME: return "OP_READ_TIME";
63     case OP_READ_TIME_REPLY: return "OP_READ_TIME_REPLY";
64     case OP_CONFIG_RX_V2: return "OP_CONFIG_RX_V2";
65     case OP_CONFIG_RX_REPLY_V2: return "OP_CONFIG_RX_REPLY_V2";
66     case OP_CONFIG_TX_V2: return "OP_CONFIG_TX_V2";
67     case OP_CONFIG_TX_REPLY_V2: return "OP_CONFIG_TX_REPLY_V2";
68     case OP_START_RX_STREAMING: return "OP_START_RX_STREAMING";
69     case OP_STOP_RX: return "OP_STOP_RX";
70     case OP_CONFIG_MIMO: return "OP_CONFIG_MIMO";
71     case OP_DBOARD_INFO: return "OP_DBOARD_INFO";
72     case OP_DBOARD_INFO_REPLY: return "OP_DBOARD_INFO_REPLY";
73     case OP_SYNC_TO_PPS: return "OP_SYNC_TO_PPS";
74     case OP_PEEK: return "OP_PEEK";
75     case OP_PEEK_REPLY: return "OP_PEEK_REPLY";
76     case OP_SET_TX_LO_OFFSET: return "OP_SET_TX_LO_OFFSET";
77     case OP_SET_TX_LO_OFFSET_REPLY: return "OP_SET_TX_LO_OFFSET_REPLY";
78     case OP_SET_RX_LO_OFFSET: return "OP_SET_RX_LO_OFFSET";
79     case OP_SET_RX_LO_OFFSET_REPLY: return "OP_SET_RX_LO_OFFSET_REPLY";
80     case OP_SYNC_EVERY_PPS: return "OP_SYNC_EVERY_PPS";
81     case OP_SYNC_EVERY_PPS_REPLY: return "OP_SYNC_EVERY_PPS_REPLY";
82
83     default:
84       char buf[64];
85       snprintf(buf, sizeof(buf), "<unknown opcode: %d>", opcode);
86       return buf;
87     }
88   }
89
90
91   /*!
92    * \param p points to fixed header
93    * \param payload_len_in_bytes is length of the fixed hdr and the payload
94    * \param[out] items is set to point to the first uint32 item in the payload
95    * \param[out] nitems is set to the number of uint32 items in the payload
96    * \param[out] md is filled in with the parsed metadata from the frame.
97    */
98   static bool
99   parse_rx_metadata(void *p, size_t payload_len_in_bytes,
100                     uint32_t **items, size_t *nitems_in_uint32s, rx_metadata *md)
101   {
102     if (payload_len_in_bytes < sizeof(u2_fixed_hdr_t))  // invalid format
103       return false;
104
105     // FIXME deal with the fact that (p % 4) == 2
106     //assert((((uintptr_t) p) % 4) == 0);               // must be 4-byte aligned
107
108     u2_fixed_hdr_t *fh = static_cast<u2_fixed_hdr_t *>(p);
109
110     // FIXME unaligned loads!
111     md->word0 = u2p_word0(fh);
112     md->timestamp = u2p_timestamp(fh);
113
114     // FIXME when we've got more info
115     // md->start_of_burst = (md->word0 & XXX) != 0;
116     // md->end_of_burst =   (md->word0 & XXX) != 0;
117     // md->rx_overrun =     (md->word0 & XXX) != 0;
118     md->start_of_burst = 0;
119     md->end_of_burst =   0;
120     md->rx_overrun =     0;
121
122     *items = (uint32_t *)(&fh[1]);
123     size_t nbytes = payload_len_in_bytes - sizeof(u2_fixed_hdr_t);
124     assert((nbytes % sizeof(uint32_t)) == 0);
125     *nitems_in_uint32s = nbytes / sizeof(uint32_t);
126
127     return true;
128   }
129
130
131   usrp2::impl::impl(const std::string &ifc, props *p, size_t rx_bufsize)
132     : d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_thread(0),
133       d_bg_running(false), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0),
134       d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0),
135       d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex),
136       d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0), d_dont_enqueue(true)
137   {
138     if (!d_eth_buf->open(ifc, htons(U2_ETHERTYPE)))
139       throw std::runtime_error("Unable to register USRP2 protocol");
140
141     d_addr = p->addr;
142
143     // Create a packet filter for U2_ETHERTYPE packets sourced from target USRP2
144     u2_mac_addr_t usrp_mac;
145     parse_mac_addr(d_addr, &usrp_mac);
146     d_pf = pktfilter::make_ethertype_inbound_target(U2_ETHERTYPE, (const unsigned char*)&(usrp_mac.addr));
147     if (!d_pf || !d_eth_buf->attach_pktfilter(d_pf))
148       throw std::runtime_error("Unable to attach packet filter.");
149
150     if (USRP2_IMPL_DEBUG)
151       std::cerr << "usrp2 constructor: using USRP2 at " << d_addr << std::endl;
152
153     memset(d_pending_replies, 0, sizeof(d_pending_replies));
154
155     d_bg_thread = new usrp2_thread(this);
156     d_bg_thread->start();
157
158     // In case the USRP2 was left streaming RX
159     // FIXME: only one channel right now
160     stop_rx_streaming(0);
161
162     if (!dboard_info())         // we're hosed
163       throw std::runtime_error("Unable to retrieve daughterboard info");
164
165     if (0){
166       int dbid;
167
168       tx_daughterboard_id(&dbid);
169       fprintf(stderr, "Tx dboard 0x%x\n", dbid);
170       fprintf(stderr, "  freq_min = %g\n", tx_freq_min());
171       fprintf(stderr, "  freq_max = %g\n", tx_freq_max());
172       fprintf(stderr, "  gain_min = %g\n", tx_gain_min());
173       fprintf(stderr, "  gain_max = %g\n", tx_gain_max());
174       fprintf(stderr, "  gain_db_per_step = %g\n", tx_gain_db_per_step());
175
176       rx_daughterboard_id(&dbid);
177       fprintf(stderr, "Rx dboard 0x%x\n", dbid);
178       fprintf(stderr, "  freq_min = %g\n", rx_freq_min());
179       fprintf(stderr, "  freq_max = %g\n", rx_freq_max());
180       fprintf(stderr, "  gain_min = %g\n", rx_gain_min());
181       fprintf(stderr, "  gain_max = %g\n", rx_gain_max());
182       fprintf(stderr, "  gain_db_per_step = %g\n", rx_gain_db_per_step());
183     }
184
185     // Ensure any custom values in hardware are cleared
186     if (!reset_db())
187       std::cerr << "usrp2::ctor reset_db failed\n";
188
189     // default gains to mid point
190     if (!set_tx_gain((tx_gain_min() + tx_gain_max()) / 2))
191       std::cerr << "usrp2::ctor set_tx_gain failed\n";
192
193     if (!set_rx_gain((rx_gain_min() + rx_gain_max()) / 2))
194       std::cerr << "usrp2::ctor set_rx_gain failed\n";
195
196     // default interp and decim
197     if (!set_tx_interp(12))
198       std::cerr << "usrp2::ctor set_tx_interp failed\n";
199
200     if (!set_rx_decim(12))
201       std::cerr << "usrp2::ctor set_rx_decim failed\n";
202
203     // set workable defaults for scaling
204     if (!set_rx_scale_iq(DEFAULT_RX_SCALE, DEFAULT_RX_SCALE))
205       std::cerr << "usrp2::ctor set_rx_scale_iq failed\n";
206   }
207
208   usrp2::impl::~impl()
209   {
210     stop_bg();
211     d_bg_thread = 0; // thread class deletes itself
212     delete d_pf;
213     d_eth_buf->close();
214     delete d_eth_buf;
215
216     if (USRP2_IMPL_DEBUG) {
217       std::cerr << std::endl
218                 << "usrp2 destructor: received " << d_num_rx_frames
219                 << " frames, with " << d_num_rx_missing << " lost ("
220                 << (d_num_rx_frames == 0 ? 0 : (int)(100.0*d_num_rx_missing/d_num_rx_frames))
221                 << "%), totaling " << d_num_rx_bytes
222                 << " bytes" << std::endl;
223     }
224   }
225
226   bool
227   usrp2::impl::parse_mac_addr(const std::string &s, u2_mac_addr_t *p)
228   {
229     p->addr[0] = 0x00;          // Matt's IAB
230     p->addr[1] = 0x50;
231     p->addr[2] = 0xC2;
232     p->addr[3] = 0x85;
233     p->addr[4] = 0x30;
234     p->addr[5] = 0x00;
235
236     int len = s.size();
237
238     switch (len){
239
240     case 5:
241       return sscanf(s.c_str(), "%hhx:%hhx", &p->addr[4], &p->addr[5]) == 2;
242
243     case 17:
244       return sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
245                     &p->addr[0], &p->addr[1], &p->addr[2],
246                     &p->addr[3], &p->addr[4], &p->addr[5]) == 6;
247     default:
248       return false;
249     }
250   }
251
252   void
253   usrp2::impl::init_et_hdrs(u2_eth_packet_t *p, const std::string &dst)
254   {
255     p->ehdr.ethertype = htons(U2_ETHERTYPE);
256     parse_mac_addr(dst, &p->ehdr.dst);
257     memcpy(&p->ehdr.src, d_eth_buf->mac(), 6);
258     p->thdr.flags = 0; // FIXME transport header values?
259     p->thdr.seqno = d_tx_seqno++;
260     p->thdr.ack = 0;
261   }
262
263   void
264   usrp2::impl::init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst,
265                              int word0_flags, int chan, uint32_t timestamp)
266   {
267     init_et_hdrs(p, dst);
268     u2p_set_word0(&p->fixed, word0_flags, chan);
269     u2p_set_timestamp(&p->fixed, timestamp);
270
271     if (chan == CONTROL_CHAN) { // no sequence numbers, back it out
272       p->thdr.seqno = 0;
273       d_tx_seqno--;
274     }
275   }
276
277   void
278   usrp2::impl::init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd)
279   {
280     memset(cmd, 0, sizeof(*cmd));
281     init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
282     cmd->op.opcode = OP_CONFIG_RX_V2;
283     cmd->op.len = sizeof(cmd->op);
284     cmd->op.rid = d_next_rid++;
285     cmd->eop.opcode = OP_EOP;
286     cmd->eop.len = sizeof(cmd->eop);
287   }
288
289   void
290   usrp2::impl::init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd)
291   {
292     memset(cmd, 0, sizeof(*cmd));
293     init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
294     cmd->op.opcode = OP_CONFIG_TX_V2;
295     cmd->op.len = sizeof(cmd->op);
296     cmd->op.rid = d_next_rid++;
297     cmd->eop.opcode = OP_EOP;
298     cmd->eop.len = sizeof(cmd->eop);
299   }
300
301
302   bool
303   usrp2::impl::transmit_cmd(void *cmd_, size_t len_)
304   {
305     const void *cmd = cmd_;
306     int len = len_;
307     unsigned char tmp[64];
308
309     if (len_ < 64){             // pad to minimum ethernet frame size
310       memset(tmp, 0, sizeof(tmp));
311       memcpy(tmp, cmd_, len_);
312       cmd = tmp;
313       len = sizeof(tmp);
314     }
315
316     return d_eth_buf->tx_frame(cmd, len) == eth_buffer::EB_OK;
317   }
318
319   bool
320   usrp2::impl::transmit_cmd_and_wait(void *cmd, size_t len, pending_reply *p, double secs)
321   {
322     d_pending_replies[p->rid()] = p;
323
324     if (!transmit_cmd(cmd, len)){
325       d_pending_replies[p->rid()] = 0;
326       return false;
327     }
328
329     int res = p->wait_for_completion(secs);
330     d_pending_replies[p->rid()] = 0;
331     return res == 1;
332   }
333
334   // ----------------------------------------------------------------
335   //        Background loop: received packet demuxing
336   // ----------------------------------------------------------------
337
338   void
339   usrp2::impl::stop_bg()
340   {
341     d_bg_running = false;
342     d_bg_pending_cond.signal();
343
344     void *dummy_status;
345     d_bg_thread->join(&dummy_status);
346   }
347
348   void
349   usrp2::impl::bg_loop()
350   {
351     d_bg_running = true;
352     while(d_bg_running) {
353       DEBUG_LOG(":");
354       // Receive available frames from ethernet buffer.  Handler will
355       // process control frames, enqueue data packets in channel
356       // rings, and signal blocked API threads
357       int res = d_eth_buf->rx_frames(this, 100); // FIXME magic timeout
358       if (res == eth_buffer::EB_ERROR)
359         break;
360
361       // Wait for user API thread(s) to process all enqueued packets.
362       // The channel ring thread that decrements d_num_enqueued to zero
363       // will signal this thread to continue.
364       {
365         omni_mutex_lock l(d_enqueued_mutex);
366         while(d_num_enqueued > 0 && d_bg_running)
367           d_bg_pending_cond.wait();
368       }
369     }
370     d_bg_running = false;
371   }
372
373   //
374   // passed to eth_buffer::rx_frames
375   //
376   data_handler::result
377   usrp2::impl::operator()(const void *base, size_t len)
378   {
379     u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
380
381     // FIXME unaligned load!
382     int chan = u2p_chan(&pkt->hdrs.fixed);
383
384     if (chan == CONTROL_CHAN) {         // control packets
385       DEBUG_LOG("c");
386       return handle_control_packet(base, len);
387     }
388     else {                              // data packets
389
390       if (d_dont_enqueue)               // toss packet
391         return data_handler::RELEASE;
392
393       return handle_data_packet(base, len);
394     }
395
396     // not reached
397   }
398
399   data_handler::result
400   usrp2::impl::handle_control_packet(const void *base, size_t len)
401   {
402     // point to beginning of payload (subpackets)
403     unsigned char *p = (unsigned char *)base + sizeof(u2_eth_packet_t);
404
405     // FIXME (p % 4) == 2.  Not good.  Must watch for unaligned loads.
406
407     // FIXME iterate over payload, handling more than a single subpacket.
408
409     int opcode = p[0];
410     unsigned int oplen = p[1];
411     unsigned int rid = p[2];
412
413     pending_reply *rp = d_pending_replies[rid];
414     if (rp) {
415       unsigned int buflen = rp->len();
416       if (oplen != buflen) {
417         std::cerr << "usrp2: mismatched command reply length (expected: "
418                   << buflen << " got: " << oplen << "). "
419                   << "op = " << opcode_to_string(opcode) << std::endl;
420       }
421
422       // Copy reply into caller's buffer
423       memcpy(rp->buffer(), p, std::min(oplen, buflen));
424       rp->notify_completion();
425       d_pending_replies[rid] = 0;
426       return data_handler::RELEASE;
427     }
428
429     // TODO: handle unsolicited, USRP2 initiated, or late replies
430     DEBUG_LOG("l");
431     return data_handler::RELEASE;
432   }
433
434   data_handler::result
435   usrp2::impl::handle_data_packet(const void *base, size_t len)
436   {
437     u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
438     d_num_rx_frames++;
439     d_num_rx_bytes += len;
440
441     /* --- FIXME start of fake transport layer handler --- */
442
443     if (d_rx_seqno != -1) {
444       int expected_seqno = (d_rx_seqno + 1) & 0xFF;
445       int seqno = pkt->hdrs.thdr.seqno;
446
447       if (seqno != expected_seqno) {
448         ::write(2, "S", 1); // missing sequence number
449         int missing = seqno - expected_seqno;
450         if (missing < 0)
451           missing += 256;
452
453         d_num_rx_overruns++;
454         d_num_rx_missing += missing;
455       }
456     }
457
458     d_rx_seqno = pkt->hdrs.thdr.seqno;
459
460     /* --- end of fake transport layer handler --- */
461
462     // FIXME unaligned load!
463     unsigned int chan = u2p_chan(&pkt->hdrs.fixed);
464
465     {
466       omni_mutex_lock l(d_channel_rings_mutex);
467
468       if (!d_channel_rings[chan]) {
469         DEBUG_LOG("!");
470         return data_handler::RELEASE;   // discard packet, no channel handler
471       }
472
473       // Strip off ethernet header and transport header and enqueue the rest
474
475       size_t offset = offsetof(u2_eth_samples_t, hdrs.fixed);
476       if (d_channel_rings[chan]->enqueue(&pkt->hdrs.fixed, len-offset)) {
477         inc_enqueued();
478         DEBUG_LOG("+");
479         return data_handler::KEEP;      // channel ring runner will mark frame done
480       }
481       else {
482         DEBUG_LOG("!");
483         return data_handler::RELEASE;   // discard, no room in channel ring
484       }
485       return data_handler::RELEASE;
486     }
487   }
488
489
490   // ----------------------------------------------------------------
491   //                           Receive
492   // ----------------------------------------------------------------
493
494   bool
495   usrp2::impl::set_rx_antenna(int ant){
496     op_config_mimo_cmd cmd;
497     op_generic_t reply;
498
499     memset(&cmd, 0, sizeof(cmd));
500     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
501     cmd.op.opcode = OP_TX_ANTENNA;
502     cmd.op.len = sizeof(cmd.op);
503     cmd.op.rid = d_next_rid++;
504     cmd.op.flags = ant;
505     cmd.eop.opcode = OP_EOP;
506     cmd.eop.len = sizeof(cmd.eop);
507
508     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
509     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
510       return false;
511
512     return true;//ntohx(reply.ok) == 1;
513   }
514
515   bool
516   usrp2::impl::set_rx_gain(double gain)
517   {
518     op_config_rx_v2_cmd cmd;
519     op_config_rx_reply_v2_t reply;
520
521     init_config_rx_v2_cmd(&cmd);
522     cmd.op.valid = htons(CFGV_GAIN);
523     cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
524
525     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
526     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
527       return false;
528
529     bool success = (ntohx(reply.ok) == 1);
530     return success;
531   }
532
533   bool
534   usrp2::impl::set_rx_lo_offset(double frequency)
535   {
536     op_freq_cmd cmd;
537     op_generic_t reply;
538
539     memset(&cmd, 0, sizeof(cmd));
540     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
541     cmd.op.opcode = OP_SET_RX_LO_OFFSET;
542     cmd.op.len = sizeof(cmd.op);
543     cmd.op.rid = d_next_rid++;
544
545     u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
546     cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
547     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
548
549     cmd.eop.opcode = OP_EOP;
550     cmd.eop.len = sizeof(cmd.eop);
551
552     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
553     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
554       return false;
555
556     bool success = (ntohx(reply.ok) == 1);
557     return success;
558   }
559
560   bool
561   usrp2::impl::set_rx_center_freq(double frequency, tune_result *result)
562   {
563     op_config_rx_v2_cmd cmd;
564     op_config_rx_reply_v2_t reply;
565
566     init_config_rx_v2_cmd(&cmd);
567     cmd.op.valid = htons(CFGV_FREQ);
568     u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
569     cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
570     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
571
572     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
573     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
574       return false;
575
576     bool success = (ntohx(reply.ok) == 1);
577     if (result && success) {
578       result->baseband_freq =
579         u2_fxpt_freq_to_double(
580           u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
581                                  ntohl(reply.baseband_freq_lo)));
582
583       result->dxc_freq =
584         u2_fxpt_freq_to_double(
585           u2_fxpt_freq_from_hilo(ntohl(reply.ddc_freq_hi),
586                                  ntohl(reply.ddc_freq_lo)));
587
588       result->residual_freq =
589         u2_fxpt_freq_to_double(
590          u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
591                                 ntohl(reply.residual_freq_lo)));
592
593       result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1);
594     }
595
596     return success;
597   }
598
599   bool
600   usrp2::impl::set_rx_decim(int decimation_factor)
601   {
602     op_config_rx_v2_cmd cmd;
603     op_config_rx_reply_v2_t reply;
604
605     init_config_rx_v2_cmd(&cmd);
606     cmd.op.valid = htons(CFGV_INTERP_DECIM);
607     cmd.op.decim = htonl(decimation_factor);
608
609     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
610     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
611       return false;
612
613     bool success = (ntohx(reply.ok) == 1);
614     if (success)
615       d_rx_decim = decimation_factor;
616     return success;
617   }
618
619   bool
620   usrp2::impl::set_rx_scale_iq(int scale_i, int scale_q)
621   {
622     op_config_rx_v2_cmd cmd;
623     op_config_rx_reply_v2_t reply;
624
625     init_config_rx_v2_cmd(&cmd);
626     cmd.op.valid = htons(CFGV_SCALE_IQ);
627     cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
628
629     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
630     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
631       return false;
632
633     bool success = (ntohx(reply.ok) == 1);
634     return success;
635   }
636
637   bool
638   usrp2::impl::start_rx_streaming(unsigned int channel, unsigned int items_per_frame)
639   {
640     if (channel > MAX_CHAN) {
641       std::cerr << "usrp2: invalid channel number (" << channel
642                 << ")" << std::endl;
643       return false;
644     }
645
646     if (channel > 0) { // until firmware supports multiple streams
647       std::cerr << "usrp2: channel " << channel
648                 << " not implemented" << std::endl;
649       return false;
650     }
651
652     {
653       omni_mutex_lock l(d_channel_rings_mutex);
654       if (d_channel_rings[channel]) {
655         std::cerr << "usrp2: channel " << channel
656                   << " already streaming" << std::endl;
657         return false;
658       }
659
660       if (items_per_frame == 0)
661         items_per_frame = U2_MAX_SAMPLES;               // minimize overhead
662
663       op_start_rx_streaming_cmd cmd;
664       op_generic_t reply;
665
666       memset(&cmd, 0, sizeof(cmd));
667       init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
668       cmd.op.opcode = OP_START_RX_STREAMING;
669       cmd.op.len = sizeof(cmd.op);
670       cmd.op.rid = d_next_rid++;
671       cmd.op.items_per_frame = htonl(items_per_frame);
672       cmd.eop.opcode = OP_EOP;
673       cmd.eop.len = sizeof(cmd.eop);
674
675       d_dont_enqueue = false;
676       bool success = false;
677       pending_reply p(cmd.op.rid, &reply, sizeof(reply));
678       success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
679       success = success && (ntohx(reply.ok) == 1);
680
681       if (success)
682         d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
683       else
684         d_dont_enqueue = true;
685
686       //fprintf(stderr, "usrp2::start_rx_streaming: success = %d\n", success);
687       return success;
688     }
689   }
690
691   bool
692   usrp2::impl::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
693   {
694     if (channel > MAX_CHAN) {
695       std::cerr << "usrp2: invalid channel number (" << channel
696                 << ")" << std::endl;
697       return false;
698     }
699
700     if (channel > 0) { // until firmware supports multiple streams
701       std::cerr << "usrp2: channel " << channel
702                 << " not implemented" << std::endl;
703       return false;
704     }
705
706     {
707       omni_mutex_lock l(d_channel_rings_mutex);
708       if (d_channel_rings[channel]) {
709         std::cerr << "usrp2: channel " << channel
710                   << " already streaming" << std::endl;
711         return false;
712       }
713
714       if (items_per_frame == 0)
715         items_per_frame = U2_MAX_SAMPLES;               // minimize overhead
716
717       op_start_rx_streaming_cmd cmd;
718       op_generic_t reply;
719
720       memset(&cmd, 0, sizeof(cmd));
721       init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time);
722       cmd.op.opcode = OP_START_RX_STREAMING;
723       cmd.op.len = sizeof(cmd.op);
724       cmd.op.rid = d_next_rid++;
725       cmd.op.items_per_frame = htonl(items_per_frame);
726       cmd.eop.opcode = OP_EOP;
727       cmd.eop.len = sizeof(cmd.eop);
728
729       d_dont_enqueue = false;
730       bool success = false;
731       pending_reply p(cmd.op.rid, &reply, sizeof(reply));
732       success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
733       success = success && (ntohx(reply.ok) == 1);
734
735       if (success)
736         d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
737       else
738         d_dont_enqueue = true;
739
740       return success;
741     }
742   }
743
744   bool
745   usrp2::impl::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
746   {
747
748     if (channel > MAX_CHAN) {
749       std::cerr << "usrp2: invalid channel number (" << channel
750                 << ")" << std::endl;
751       return false;
752     }
753
754     if (channel > 0) { // until firmware supports multiple streams
755       std::cerr << "usrp2: channel " << channel
756                 << " not implemented" << std::endl;
757       return false;
758     }
759
760     {
761       omni_mutex_lock l(d_channel_rings_mutex);
762       if (d_channel_rings[channel]) {
763         std::cerr << "usrp2: channel " << channel
764                   << " already streaming" << std::endl;
765         return false;
766       }
767
768       if (items_per_frame == 0)
769         items_per_frame = U2_MAX_SAMPLES;               // minimize overhead
770
771       op_sync_and_start_rx_streaming_cmd cmd;
772       op_generic_t reply;
773
774       memset(&cmd, 0, sizeof(cmd));
775       init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time);
776       cmd.sync_op.opcode = OP_SYNC_TO_PPS;
777       cmd.sync_op.len = sizeof(cmd.sync_op);
778       cmd.sync_op.rid = d_next_rid++;
779       cmd.rx_op.opcode = OP_START_RX_STREAMING;
780       cmd.rx_op.len = sizeof(cmd.rx_op);
781       cmd.rx_op.rid = d_next_rid++;
782       cmd.rx_op.items_per_frame = htonl(items_per_frame);
783       cmd.eop.opcode = OP_EOP;
784       cmd.eop.len = sizeof(cmd.eop);
785
786       d_dont_enqueue = false;
787       bool success = false;
788       pending_reply p(cmd.sync_op.rid, &reply, sizeof(reply));
789       success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
790       success = success && (ntohx(reply.ok) == 1);
791
792       if (success)
793         d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
794       else
795         d_dont_enqueue = true;
796
797       return success;
798     }
799   }
800
801   bool
802   usrp2::impl::stop_rx_streaming(unsigned int channel)
803   {
804     if (channel > MAX_CHAN) {
805       std::cerr << "usrp2: invalid channel number (" << channel
806                 << ")" << std::endl;
807       return false;
808     }
809
810     if (channel > 0) { // until firmware supports multiple streams
811       std::cerr << "usrp2: channel " << channel
812                 << " not implemented" << std::endl;
813       return false;
814     }
815
816     d_dont_enqueue = true;      // no new samples
817     flush_rx_samples(channel);  // dump any we may already have
818
819     op_stop_rx_cmd cmd;
820     op_generic_t reply;
821
822     {
823       omni_mutex_lock l(d_channel_rings_mutex);
824
825       memset(&cmd, 0, sizeof(cmd));
826       init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
827       cmd.op.opcode = OP_STOP_RX;
828       cmd.op.len = sizeof(cmd.op);
829       cmd.op.rid = d_next_rid++;
830       cmd.eop.opcode = OP_EOP;
831       cmd.eop.len = sizeof(cmd.eop);
832
833       bool success = false;
834       pending_reply p(cmd.op.rid, &reply, sizeof(reply));
835       success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
836       success = success && (ntohx(reply.ok) == 1);
837       d_channel_rings[channel].reset();
838       //fprintf(stderr, "usrp2::stop_rx_streaming:  success = %d\n", success);
839       return success;
840     }
841   }
842
843   bool
844   usrp2::impl::rx_samples(unsigned int channel, rx_sample_handler *handler)
845   {
846     if (channel > MAX_CHAN) {
847       std::cerr << "usrp2: invalid channel (" << channel
848                 << " )" << std::endl;
849       return false;
850     }
851
852     if (channel > 0) {
853       std::cerr << "usrp2: channel " << channel
854                 << " not implemented" << std::endl;
855       return false;
856     }
857
858     ring_sptr rp = d_channel_rings[channel];
859     if (!rp){
860       std::cerr << "usrp2: channel " << channel
861                 << " not receiving" << std::endl;
862       return false;
863     }
864
865     // Wait for frames available in channel ring
866     DEBUG_LOG("W");
867     rp->wait_for_not_empty();
868     DEBUG_LOG("s");
869
870     // Iterate through frames and present to user
871     void *p;
872     size_t frame_len_in_bytes;
873     while (rp->dequeue(&p, &frame_len_in_bytes)) {
874       uint32_t         *items;                  // points to beginning of data items
875       size_t            nitems_in_uint32s;
876       rx_metadata       md;
877       if (!parse_rx_metadata(p, frame_len_in_bytes, &items, &nitems_in_uint32s, &md))
878         return false;
879
880       bool want_more = (*handler)(items, nitems_in_uint32s, &md);
881       d_eth_buf->release_frame(p);
882       DEBUG_LOG("-");
883       dec_enqueued();
884
885       if (!want_more)
886         break;
887     }
888     return true;
889   }
890
891   bool
892   usrp2::impl::flush_rx_samples(unsigned int channel)
893   {
894     if (channel > MAX_CHAN) {
895       std::cerr << "usrp2: invalid channel (" << channel
896                 << " )" << std::endl;
897       return false;
898     }
899
900     if (channel > 0) {
901       std::cerr << "usrp2: channel " << channel
902                 << " not implemented" << std::endl;
903       return false;
904     }
905
906     ring_sptr rp = d_channel_rings[channel];
907     if (!rp){
908       return false;
909     }
910
911     // Iterate through frames and drop them
912     void *p;
913     size_t frame_len_in_bytes;
914     while (rp->dequeue(&p, &frame_len_in_bytes)) {
915       d_eth_buf->release_frame(p);
916       dec_enqueued();
917     }
918     return true;
919   }
920
921   // ----------------------------------------------------------------
922   //                            Transmit
923   // ----------------------------------------------------------------
924
925   bool
926   usrp2::impl::set_tx_antenna(int ant){
927     op_config_mimo_cmd cmd;
928     op_generic_t reply;
929
930     memset(&cmd, 0, sizeof(cmd));
931     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
932     cmd.op.opcode = OP_RX_ANTENNA;
933     cmd.op.len = sizeof(cmd.op);
934     cmd.op.rid = d_next_rid++;
935     cmd.op.flags = ant;
936     cmd.eop.opcode = OP_EOP;
937     cmd.eop.len = sizeof(cmd.eop);
938
939     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
940     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
941       return false;
942
943     return true;//ntohx(reply.ok) == 1;
944   }
945
946   bool
947   usrp2::impl::set_tx_gain(double gain)
948   {
949     op_config_tx_v2_cmd cmd;
950     op_config_tx_reply_v2_t reply;
951
952     init_config_tx_v2_cmd(&cmd);
953     cmd.op.valid = htons(CFGV_GAIN);
954     cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
955
956     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
957     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
958       return false;
959
960     bool success = (ntohx(reply.ok) == 1);
961     return success;
962   }
963
964   bool
965   usrp2::impl::set_tx_lo_offset(double frequency)
966   {
967     op_freq_cmd cmd;
968     op_generic_t reply;
969
970     memset(&cmd, 0, sizeof(cmd));
971     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
972     cmd.op.opcode = OP_SET_TX_LO_OFFSET;
973     cmd.op.len = sizeof(cmd.op);
974     cmd.op.rid = d_next_rid++;
975
976     u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
977     cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
978     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
979
980     cmd.eop.opcode = OP_EOP;
981     cmd.eop.len = sizeof(cmd.eop);
982
983     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
984     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
985       return false;
986
987     bool success = (ntohx(reply.ok) == 1);
988     return success;
989   }
990
991   bool
992   usrp2::impl::set_tx_center_freq(double frequency, tune_result *result)
993   {
994     op_config_tx_v2_cmd cmd;
995     op_config_tx_reply_v2_t reply;
996
997     init_config_tx_v2_cmd(&cmd);
998     cmd.op.valid = htons(CFGV_FREQ);
999     u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
1000     cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
1001     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
1002
1003     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1004     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1005       return false;
1006
1007     bool success = (ntohx(reply.ok) == 1);
1008     if (result && success) {
1009       result->baseband_freq =
1010         u2_fxpt_freq_to_double(
1011           u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
1012                                  ntohl(reply.baseband_freq_lo)));
1013
1014       result->dxc_freq =
1015         u2_fxpt_freq_to_double(
1016           u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi),
1017                                  ntohl(reply.duc_freq_lo)));
1018
1019       result->residual_freq =
1020         u2_fxpt_freq_to_double(
1021          u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
1022                                 ntohl(reply.residual_freq_lo)));
1023
1024       result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1);
1025     }
1026
1027     return success;
1028   }
1029
1030   bool
1031   usrp2::impl::set_tx_interp(int interpolation_factor)
1032   {
1033     op_config_tx_v2_cmd cmd;
1034     op_config_tx_reply_v2_t reply;
1035
1036     init_config_tx_v2_cmd(&cmd);
1037     cmd.op.valid = htons(CFGV_INTERP_DECIM);
1038     cmd.op.interp = htonl(interpolation_factor);
1039
1040     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1041     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1042       return false;
1043
1044     bool success = (ntohx(reply.ok) == 1);
1045     if (success) {
1046       d_tx_interp = interpolation_factor;
1047
1048       // Auto-set TX scaling based on interpolation rate
1049       int scale_i, scale_q;
1050       default_tx_scale_iq(d_tx_interp, &scale_i, &scale_q);
1051       return set_tx_scale_iq(scale_i, scale_q);
1052     }
1053
1054     return success;
1055   }
1056
1057   void
1058   usrp2::impl::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q)
1059   {
1060     // Calculate CIC interpolation (i.e., without halfband interpolators)
1061     int i = interpolation_factor;
1062     if (i > 128)
1063       i = i >> 1;
1064     if (i > 128)
1065       i = i >> 1;
1066
1067     // Calculate dsp_core_tx gain absent scale multipliers
1068     float gain = (1.65*i*i*i)/(4096*pow(2, ceil(log2(i*i*i))));
1069
1070     // Calculate closest multiplier constant to reverse gain
1071     int scale = (int)rint(1.0/gain);
1072     // fprintf(stderr, "if=%i i=%i gain=%f scale=%i\n", interpolation_factor, i, gain, scale);
1073
1074     // Both I and Q are identical in this case
1075     if (scale_i)
1076       *scale_i = scale;
1077     if (scale_q)
1078       *scale_q = scale;
1079   }
1080
1081   bool
1082   usrp2::impl::set_tx_scale_iq(int scale_i, int scale_q)
1083   {
1084     op_config_tx_v2_cmd cmd;
1085     op_config_tx_reply_v2_t reply;
1086
1087     init_config_tx_v2_cmd(&cmd);
1088     cmd.op.valid = htons(CFGV_SCALE_IQ);
1089     cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
1090
1091     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1092     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1093       return false;
1094
1095     bool success = (ntohx(reply.ok) == 1);
1096     return success;
1097   }
1098
1099   bool
1100   usrp2::impl::tx_32fc(unsigned int channel,
1101                        const std::complex<float> *samples,
1102                        size_t nsamples,
1103                        const tx_metadata *metadata)
1104   {
1105     uint32_t items[nsamples];
1106     copy_host_32fc_to_u2_16sc(nsamples, samples, items);
1107     return tx_raw(channel, items, nsamples, metadata);
1108   }
1109
1110   bool
1111   usrp2::impl::tx_16sc(unsigned int channel,
1112                        const std::complex<int16_t> *samples,
1113                        size_t nsamples,
1114                        const tx_metadata *metadata)
1115   {
1116 #ifdef WORDS_BIGENDIAN
1117
1118     // Already binary equivalent to 16-bit I/Q on the wire.
1119     // No conversion required.
1120
1121     assert(sizeof(samples[0]) == sizeof(uint32_t));
1122     return tx_raw(channel, (const uint32_t *) samples, nsamples, metadata);
1123
1124 #else
1125
1126     uint32_t items[nsamples];
1127     copy_host_16sc_to_u2_16sc(nsamples, samples, items);
1128     return tx_raw(channel, items, nsamples, metadata);
1129
1130 #endif
1131   }
1132
1133   bool
1134   usrp2::impl::tx_raw(unsigned int channel,
1135                       const uint32_t *items,
1136                       size_t nitems,
1137                       const tx_metadata *metadata)
1138   {
1139     if (nitems == 0)
1140       return true;
1141
1142     // FIXME can't deal with nitems < U2_MIN_SAMPLES (will be fixed in VRT)
1143     // FIXME need to check the MTU instead of assuming 1500 bytes
1144
1145     // fragment as necessary then fire away
1146
1147     size_t nframes = (nitems + U2_MAX_SAMPLES - 1) / U2_MAX_SAMPLES;
1148     size_t last_frame = nframes - 1;
1149     u2_eth_packet_t     hdrs;
1150
1151     size_t n = 0;
1152     for (size_t fn = 0; fn < nframes; fn++){
1153       uint32_t timestamp = 0;
1154       uint32_t flags = 0;
1155
1156       if (fn == 0){
1157         timestamp = metadata->timestamp;
1158         if (metadata->send_now)
1159           flags |= U2P_TX_IMMEDIATE;
1160         if (metadata->start_of_burst)
1161           flags |= U2P_TX_START_OF_BURST;
1162       }
1163       if (fn > 0){
1164         flags |= U2P_TX_IMMEDIATE;
1165       }
1166       if (fn == last_frame){
1167         if (metadata->end_of_burst)
1168           flags |= U2P_TX_END_OF_BURST;
1169       }
1170
1171       init_etf_hdrs(&hdrs, d_addr, flags, channel, timestamp);
1172
1173       // Avoid short packet by splitting last two packets if reqd
1174       size_t i;
1175       if ((nitems - n) > U2_MAX_SAMPLES && (nitems - n) < (U2_MAX_SAMPLES + U2_MIN_SAMPLES))
1176         i = (nitems - n) / 2;
1177       else
1178         i = std::min((size_t) U2_MAX_SAMPLES, nitems - n);
1179
1180       eth_iovec iov[2];
1181       iov[0].iov_base = &hdrs;
1182       iov[0].iov_len = sizeof(hdrs);
1183       iov[1].iov_base = const_cast<uint32_t *>(&items[n]);
1184       iov[1].iov_len = i * sizeof(uint32_t);
1185
1186       size_t total = iov[0].iov_len + iov[1].iov_len;
1187       if (total < 64)
1188         fprintf(stderr, "usrp2::tx_raw: FIXME: short packet: %zd items (%zd bytes)\n", i, total);
1189
1190       if (d_eth_buf->tx_framev(iov, 2) != eth_buffer::EB_OK){
1191         return false;
1192       }
1193
1194       n += i;
1195     }
1196
1197     return true;
1198   }
1199
1200   // ----------------------------------------------------------------
1201   //                       misc commands
1202   // ----------------------------------------------------------------
1203
1204   bool
1205   usrp2::impl::config_mimo(int flags)
1206   {
1207     op_config_mimo_cmd cmd;
1208     op_generic_t reply;
1209
1210     memset(&cmd, 0, sizeof(cmd));
1211     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1212     cmd.op.opcode = OP_CONFIG_MIMO;
1213     cmd.op.len = sizeof(cmd.op);
1214     cmd.op.rid = d_next_rid++;
1215     cmd.op.flags = flags;
1216     cmd.eop.opcode = OP_EOP;
1217     cmd.eop.len = sizeof(cmd.eop);
1218
1219     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1220     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1221       return false;
1222
1223     return ntohx(reply.ok) == 1;
1224   }
1225
1226   bool
1227   usrp2::impl::fpga_master_clock_freq(long *freq)
1228   {
1229     *freq = 100000000L;         // 100 MHz
1230     return true;
1231   }
1232
1233   bool
1234   usrp2::impl::adc_rate(long *rate)
1235   {
1236     return fpga_master_clock_freq(rate);
1237   }
1238
1239   bool
1240   usrp2::impl::dac_rate(long *rate)
1241   {
1242     return fpga_master_clock_freq(rate);
1243   }
1244
1245   bool
1246   usrp2::impl::tx_daughterboard_id(int *dbid)
1247   {
1248     *dbid = d_tx_db_info.dbid;
1249     return true;
1250   }
1251
1252   bool
1253   usrp2::impl::rx_daughterboard_id(int *dbid)
1254   {
1255     *dbid = d_rx_db_info.dbid;
1256     return true;
1257   }
1258
1259
1260   // ----------------------------------------------------------------
1261   //                    low-level commands
1262   // ----------------------------------------------------------------
1263
1264   bool
1265   usrp2::impl::burn_mac_addr(const std::string &new_addr)
1266   {
1267     op_burn_mac_addr_cmd cmd;
1268     op_generic_t reply;
1269
1270     memset(&cmd, 0, sizeof(cmd));
1271     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1272     cmd.op.opcode = OP_BURN_MAC_ADDR;
1273     cmd.op.len = sizeof(cmd.op);
1274     cmd.op.rid = d_next_rid++;
1275     if (!parse_mac_addr(new_addr, &cmd.op.addr))
1276       return false;
1277
1278     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1279     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, 4*DEF_CMD_TIMEOUT))
1280       return false;
1281
1282     bool success = (ntohx(reply.ok) == 1);
1283     return success;
1284   }
1285
1286   static void
1287   fill_dboard_info(db_info *dst, const u2_db_info_t *src)
1288   {
1289     dst->dbid = ntohl(src->dbid);
1290
1291     dst->freq_min =
1292       u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi),
1293                                                     ntohl(src->freq_min_lo)));
1294     dst->freq_max =
1295       u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi),
1296                                                     ntohl(src->freq_max_lo)));
1297
1298     dst->gain_min = u2_fxpt_gain_to_double(ntohs(src->gain_min));
1299     dst->gain_max = u2_fxpt_gain_to_double(ntohs(src->gain_max));
1300     dst->gain_step_size = u2_fxpt_gain_to_double(ntohs(src->gain_step_size));
1301   }
1302
1303   bool
1304   usrp2::impl::dboard_info()
1305   {
1306     op_dboard_info_cmd          cmd;
1307     op_dboard_info_reply_t      reply;
1308
1309     memset(&cmd, 0, sizeof(cmd));
1310     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1311     cmd.op.opcode = OP_DBOARD_INFO;
1312     cmd.op.len = sizeof(cmd.op);
1313     cmd.op.rid = d_next_rid++;
1314     cmd.eop.opcode = OP_EOP;
1315     cmd.eop.len = sizeof(cmd.eop);
1316
1317     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1318     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1319       return false;
1320
1321     bool success = (ntohx(reply.ok) == 1);
1322     if (success){
1323       fill_dboard_info(&d_tx_db_info, &reply.tx_db_info);
1324       fill_dboard_info(&d_rx_db_info, &reply.rx_db_info);
1325     }
1326     return success;
1327   }
1328
1329
1330   bool
1331   usrp2::impl::sync_to_pps()
1332   {
1333     op_generic_cmd cmd;
1334     op_generic_t   reply;
1335
1336     memset(&cmd, 0, sizeof(cmd));
1337     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1338     cmd.op.opcode = OP_SYNC_TO_PPS;
1339     cmd.op.len = sizeof(cmd.op);
1340     cmd.op.rid = d_next_rid++;
1341     cmd.eop.opcode = OP_EOP;
1342     cmd.eop.len = sizeof(cmd.eop);
1343
1344     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1345     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1346       return false;
1347
1348     return ntohx(reply.ok) == 1;
1349   }
1350
1351   bool
1352   usrp2::impl::sync_every_pps(bool enable)
1353   {
1354     op_generic_cmd cmd;
1355     op_generic_t   reply;
1356
1357     memset(&cmd, 0, sizeof(cmd));
1358     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1359     cmd.op.opcode = OP_SYNC_EVERY_PPS;
1360     cmd.op.len = sizeof(cmd.op);
1361     cmd.op.rid = d_next_rid++;
1362     cmd.op.ok = enable ? 1 : 0;
1363     cmd.eop.opcode = OP_EOP;
1364     cmd.eop.len = sizeof(cmd.eop);
1365
1366     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1367     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1368       return false;
1369
1370     return ntohx(reply.ok) == 1;
1371   }
1372
1373   std::vector<uint32_t>
1374   usrp2::impl::peek32(uint32_t addr, uint32_t words)
1375   {
1376     std::vector<uint32_t> result; // zero sized on error return
1377     // fprintf(stderr, "usrp2::peek: addr=%08X words=%u\n", addr, words);
1378
1379     if (addr % 4 != 0) {
1380       fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr);
1381       return result;
1382     }
1383
1384     if (words == 0)
1385       return result;
1386
1387     op_peek_cmd   cmd;
1388     op_generic_t *reply;
1389
1390     int wlen = sizeof(uint32_t);
1391     int rlen = sizeof(op_generic_t);
1392     size_t bytes = words*wlen;
1393
1394     memset(&cmd, 0, sizeof(cmd));
1395     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1396     cmd.op.opcode = OP_PEEK;
1397     cmd.op.len = sizeof(cmd.op);
1398     cmd.op.rid = d_next_rid++;
1399     cmd.eop.opcode = OP_EOP;
1400     cmd.eop.len = sizeof(cmd.eop);
1401
1402     cmd.op.addr = htonl(addr);
1403     cmd.op.bytes = htonl(bytes);
1404
1405     reply = (op_generic_t *)malloc(rlen+bytes);
1406     pending_reply p(cmd.op.rid, reply, rlen+bytes);
1407     if (transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) {
1408       uint32_t nwords = (reply->len-rlen)/sizeof(uint32_t);
1409       uint32_t *data = (uint32_t *)(reply+rlen/wlen);
1410       for (unsigned int i = 0; i < nwords; i++)
1411         result.push_back(ntohl(data[i]));
1412     }
1413
1414     free(reply);
1415     return result;
1416   }
1417
1418   bool
1419   usrp2::impl::poke32(uint32_t addr, const std::vector<uint32_t> &data)
1420   {
1421     if (addr % 4 != 0) {
1422       fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr);
1423       return false;
1424     }
1425
1426     int plen = sizeof(op_poke_cmd);
1427     int wlen = sizeof(uint32_t);
1428     int max_words = (MAX_SUBPKT_LEN-plen)/wlen;
1429     int words = data.size();
1430
1431     if (words > max_words) {
1432       fprintf(stderr, "usrp2::poke32: write size (=%u) exceeds maximum of %u words\n",
1433               words, max_words);
1434       return false;
1435     }
1436
1437     //fprintf(stderr, "usrp2::poke32: addr=%08X words=%u\n", addr, words);
1438
1439     if (words == 0)
1440       return true; // NOP
1441
1442     op_poke_cmd  *cmd;
1443     op_generic_t *eop;
1444
1445     // Allocate, clear, and initialize command packet
1446     int bytes = words*wlen;
1447     int l = plen+bytes+sizeof(*eop); // op_poke_cmd+data+eop
1448     cmd = (op_poke_cmd *)malloc(l);
1449     //fprintf(stderr, "cmd=%p l=%i\n", cmd, l);
1450     memset(cmd, 0, l);
1451     init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
1452     cmd->op.opcode = OP_POKE;
1453     cmd->op.len = sizeof(cmd->op)+bytes;
1454     cmd->op.rid = d_next_rid++;
1455     cmd->op.addr = htonl(addr);
1456
1457     // Copy data from vector into packet space
1458     uint32_t *dest = (uint32_t *)((uint8_t *)cmd+plen);
1459     for (int i = 0; i < words; i++) {
1460       //fprintf(stderr, "%03i@%p\n", i, dest);
1461       *dest++ = htonl(data[i]);
1462     }
1463
1464     // Write end-of-packet subpacket
1465     eop = (op_generic_t *)dest;
1466     eop->opcode = OP_EOP;
1467     eop->len = sizeof(*eop);
1468     //fprintf(stderr, "eop=%p len=%i\n", eop, eop->len);
1469
1470     // Send command to device and retrieve reply
1471     bool ok = false;
1472     op_generic_t reply;
1473     pending_reply p(cmd->op.rid, &reply, sizeof(reply));
1474     if (transmit_cmd_and_wait(cmd, l, &p, DEF_CMD_TIMEOUT))
1475       ok = (ntohx(reply.ok) == 1);
1476
1477     free(cmd);
1478     return ok;
1479   }
1480
1481   bool
1482   usrp2::impl::reset_db()
1483   {
1484     op_generic_cmd cmd;
1485     op_generic_t reply;
1486
1487     memset(&cmd, 0, sizeof(cmd));
1488     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1489     cmd.op.opcode = OP_RESET_DB;
1490     cmd.op.len = sizeof(cmd.op);
1491     cmd.op.rid = d_next_rid++;
1492     cmd.eop.opcode = OP_EOP;
1493     cmd.eop.len = sizeof(cmd.eop);
1494
1495     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1496     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1497       return false;
1498
1499     bool success = (ntohx(reply.ok) == 1);
1500     return success;
1501   }
1502
1503   bool usrp2::impl::set_gpio_ddr(int bank, uint16_t value, uint16_t mask)
1504   {
1505     if (bank != GPIO_TX_BANK && bank != GPIO_RX_BANK) {
1506       fprintf(stderr, "set_gpio_ddr: bank must be one of GPIO_RX_BANK or GPIO_TX_BANK\n");
1507       return false;
1508     }
1509
1510     op_gpio_cmd cmd;
1511     op_generic_t reply;
1512
1513     memset(&cmd, 0, sizeof(cmd));
1514     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1515     cmd.op.opcode = OP_GPIO_SET_DDR;
1516     cmd.op.len = sizeof(cmd.op);
1517     cmd.op.rid = d_next_rid++;
1518     cmd.op.bank = static_cast<uint8_t>(bank);
1519     cmd.op.value = htons(value);
1520     cmd.op.mask = htons(mask);
1521     cmd.eop.opcode = OP_EOP;
1522     cmd.eop.len = sizeof(cmd.eop);
1523
1524     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1525     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1526       return false;
1527
1528     bool success = (ntohx(reply.ok) == 1);
1529     return success;
1530   }
1531
1532   bool usrp2::impl::set_gpio_sels(int bank, std::string sels)
1533   {
1534     if (bank != GPIO_TX_BANK && bank != GPIO_RX_BANK) {
1535       fprintf(stderr, "set_gpio_ddr: bank must be one of GPIO_RX_BANK or GPIO_TX_BANK\n");
1536       return false;
1537     }
1538
1539     if (sels.size() != 16) {
1540       fprintf(stderr, "set_gpio_sels: sels must be exactly 16 bytes\n");
1541       return false;
1542     }
1543
1544     op_gpio_set_sels_cmd cmd;
1545     op_generic_t reply;
1546
1547     memset(&cmd, 0, sizeof(cmd));
1548     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1549     cmd.op.opcode = OP_GPIO_SET_SELS;
1550     cmd.op.len = sizeof(cmd.op);
1551     cmd.op.rid = d_next_rid++;
1552     cmd.op.bank = static_cast<uint8_t>(bank);
1553     memcpy(&cmd.op.sels, sels.c_str(), 16);
1554     cmd.eop.opcode = OP_EOP;
1555     cmd.eop.len = sizeof(cmd.eop);
1556
1557     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1558     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1559       return false;
1560
1561     bool success = (ntohx(reply.ok) == 1);
1562     return success;
1563   }
1564
1565   bool usrp2::impl::write_gpio(int bank, uint16_t value, uint16_t mask)
1566   {
1567     if (bank != GPIO_TX_BANK && bank != GPIO_RX_BANK) {
1568       fprintf(stderr, "set_gpio_ddr: bank must be one of GPIO_RX_BANK or GPIO_TX_BANK\n");
1569       return false;
1570     }
1571
1572     op_gpio_cmd cmd;
1573     op_generic_t reply;
1574
1575     memset(&cmd, 0, sizeof(cmd));
1576     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1577     cmd.op.opcode = OP_GPIO_WRITE;
1578     cmd.op.len = sizeof(cmd.op);
1579     cmd.op.rid = d_next_rid++;
1580     cmd.op.bank = static_cast<uint8_t>(bank);
1581     cmd.op.value = htons(value);
1582     cmd.op.mask = htons(mask);
1583     cmd.eop.opcode = OP_EOP;
1584     cmd.eop.len = sizeof(cmd.eop);
1585
1586     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1587     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1588       return false;
1589
1590     bool success = (ntohx(reply.ok) == 1);
1591     return success;
1592   }
1593
1594   bool usrp2::impl::read_gpio(int bank, uint16_t *value)
1595   {
1596     if (bank != GPIO_TX_BANK && bank != GPIO_RX_BANK) {
1597       fprintf(stderr, "set_gpio_ddr: bank must be one of GPIO_RX_BANK or GPIO_TX_BANK\n");
1598       return false;
1599     }
1600
1601     op_gpio_cmd cmd;
1602     op_gpio_read_reply_t reply;
1603
1604     memset(&cmd, 0, sizeof(cmd));
1605     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1606     cmd.op.opcode = OP_GPIO_READ;
1607     cmd.op.len = sizeof(cmd.op);
1608     cmd.op.rid = d_next_rid++;
1609     cmd.op.bank = static_cast<uint8_t>(bank);
1610     cmd.op.value = 0; // not used
1611     cmd.op.mask = 0;  // not used
1612     cmd.eop.opcode = OP_EOP;
1613     cmd.eop.len = sizeof(cmd.eop);
1614
1615     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1616     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1617       return false;
1618
1619     bool success = (ntohx(reply.ok) == 1);
1620     if (success && (value != NULL))
1621       *value = ntohs(reply.value);
1622
1623     return success;
1624   }
1625
1626   bool usrp2::impl::enable_gpio_streaming(int bank, int enable)
1627   {
1628     if (bank != GPIO_RX_BANK) {
1629       fprintf(stderr, "enable_gpio_streaming: only RX streaming is currently implemented\n");
1630       return false;
1631     }
1632
1633     if ((enable & ~0x03) != 0) {
1634       fprintf(stderr, "enable_gpio_streaming: invalid enable format\n");
1635       return false;
1636     }
1637
1638     op_gpio_cmd cmd;
1639     op_generic_t reply;
1640
1641     memset(&cmd, 0, sizeof(cmd));
1642     init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, -1);
1643     cmd.op.opcode = OP_GPIO_STREAM;
1644     cmd.op.len = sizeof(cmd.op);
1645     cmd.op.rid = d_next_rid++;
1646     cmd.op.bank = static_cast<uint8_t>(bank);
1647     cmd.op.value = htons((uint16_t)enable);
1648     cmd.op.mask = 0;  // not used
1649     cmd.eop.opcode = OP_EOP;
1650     cmd.eop.len = sizeof(cmd.eop);
1651
1652     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
1653     if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
1654       return false;
1655
1656     bool success = (ntohx(reply.ok) == 1);
1657     return success;
1658   }
1659
1660 } // namespace usrp2