Merged features/inband-usb r5224:6306 into trunk.
authoreb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 5 Sep 2007 01:43:43 +0000 (01:43 +0000)
committereb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 5 Sep 2007 01:43:43 +0000 (01:43 +0000)
This is work-in-progress on inband signaling for the USRP1.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@6307 221aa14e-8319-0410-a670-987f0aec2ac5

80 files changed:
Makefile.common
pmt/src/lib/pmt.cc
pmt/src/lib/pmt.h
pmt/src/lib/qa_pmt_prims.cc
usrp/fpga/inband_lib/chan_fifo_reader.v
usrp/fpga/inband_lib/channel_demux.v [new file with mode: 0644]
usrp/fpga/inband_lib/channel_ram.v [new file with mode: 0755]
usrp/fpga/inband_lib/cmd_reader.v [new file with mode: 0755]
usrp/fpga/inband_lib/data_packet_fifo.v
usrp/fpga/inband_lib/packet_builder.v [new file with mode: 0755]
usrp/fpga/inband_lib/register_io.v [new file with mode: 0755]
usrp/fpga/inband_lib/rx_buffer_inband.v [new file with mode: 0755]
usrp/fpga/inband_lib/tx_buffer_inband.v
usrp/fpga/inband_lib/tx_packer.v [new file with mode: 0644]
usrp/fpga/inband_lib/usb_fifo_reader.v
usrp/fpga/inband_lib/usb_fifo_writer.v [new file with mode: 0755]
usrp/fpga/inband_lib/usb_packet_fifo2.v [deleted file]
usrp/fpga/megacells/fifo_2k_1clk.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16.bsf [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16.cmp [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16.inc [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16_bb.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_2kx16_inst.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16.bsf [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16.cmp [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16.inc [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16_bb.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_4kx16_inst.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_512.bsf [deleted file]
usrp/fpga/megacells/fifo_512.cmp [deleted file]
usrp/fpga/megacells/fifo_512.inc [deleted file]
usrp/fpga/megacells/fifo_512.v [deleted file]
usrp/fpga/megacells/fifo_512_bb.v [deleted file]
usrp/fpga/toplevel/usrp_inband_usb/config.vh
usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
usrp/host/apps/Makefile.am
usrp/host/apps/read_packets.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_cs.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_ping.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_registers.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_rx.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_timestamps.cc [new file with mode: 0644]
usrp/host/apps/test_usrp_inband_tx.cc [new file with mode: 0644]
usrp/host/apps/ui_nco.h [new file with mode: 0644]
usrp/host/apps/ui_sincos.c [new file with mode: 0644]
usrp/host/apps/ui_sincos.h [new file with mode: 0644]
usrp/host/lib/inband/Makefile.am
usrp/host/lib/inband/fake_usrp.cc [new file with mode: 0644]
usrp/host/lib/inband/fake_usrp.h [new file with mode: 0644]
usrp/host/lib/inband/gen_test_packets.py
usrp/host/lib/inband/qa_inband_usrp_server.cc
usrp/host/lib/inband/qa_inband_usrp_server.h
usrp/host/lib/inband/symbols_usrp_channel.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_interface_cs.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_low_level_cs.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_rx.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_rx_cs.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_server_cs.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_tx.h [new file with mode: 0644]
usrp/host/lib/inband/symbols_usrp_tx_cs.h [new file with mode: 0644]
usrp/host/lib/inband/test_usrp_inband.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_inband_usb_packet.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_inband_usb_packet.h
usrp/host/lib/inband/usrp_interface.mbh [new file with mode: 0644]
usrp/host/lib/inband/usrp_rx.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_rx.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_rx_stub.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_rx_stub.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_server.cc
usrp/host/lib/inband/usrp_server.h
usrp/host/lib/inband/usrp_server.mbh
usrp/host/lib/inband/usrp_tx.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_tx.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_tx_stub.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_tx_stub.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_usb_interface.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_usb_interface.h [new file with mode: 0644]

index 2976e36dcd7b420f89240df7a19febc742ed2c6b..33a3a7c2a869fad71a0ce214d480d28826e7a2a4 100644 (file)
@@ -76,7 +76,9 @@ GNURADIO_I = $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i
 USRP_INCLUDES = -I$(top_srcdir)/usrp/host/lib/legacy \
                -I$(top_srcdir)/usrp/host/lib/inband \
                -I$(top_srcdir)/usrp/firmware/include
-USRP_LA = $(top_builddir)/usrp/host/lib/legacy/libusrp.la
+USRP_LA = \
+       $(top_builddir)/usrp/host/lib/legacy/libusrp.la        \
+       $(top_builddir)/usrp/host/lib/inband/libusrp_inband.la
 
 # How to link the PMT library from inside the tree
 PMT_INCLUDES = -I$(top_srcdir)/pmt/src/lib
index b896adaa2031290be7de61b27dfc58046ba8dc50..b2c04b3906b7a97d1fdae866de70bff990d6e072 100644 (file)
@@ -748,7 +748,19 @@ pmt_length(pmt_t x)
   if (x->is_uniform_vector())
     return _uniform_vector(x)->length();
 
-  // FIXME list length
+  if (x->is_pair() || x->is_null()) {
+    size_t length=0;
+    while (pmt_is_pair(x)){
+      length++;
+      x = pmt_cdr(x);
+    }
+    if (pmt_is_null(x))
+      return length;
+
+    // not a proper list
+    throw pmt_wrong_type("pmt_length", x);
+  }
+
   // FIXME dictionary length (number of entries)
 
   throw pmt_wrong_type("pmt_length", x);
@@ -937,6 +949,18 @@ pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4)
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, PMT_NIL))));
 }
 
+pmt_t
+pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5)
+{
+  return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, PMT_NIL)))));
+}
+
+pmt_t
+pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6)
+{
+  return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, pmt_cons(x6, PMT_NIL))))));
+}
+
 pmt_t
 pmt_caar(pmt_t pair)
 {
index 6aeae773b916913f4f52a41cbfaed95919251f2b..fa368a6a17eec1e27d5ed7f30c965121aba9b9da 100644 (file)
@@ -598,6 +598,18 @@ pmt_t pmt_list3(pmt_t x1, pmt_t x2, pmt_t x3);
  */
 pmt_t pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4);
 
+/*!
+ * \brief Return a list of length 5 containing \p x1, \p x2, \p x3, \p x4, \p x5
+ */
+pmt_t pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5);
+
+/*!
+ * \brief Return a list of length 6 containing \p x1, \p x2, \p x3, \p x4, \p
+ * x5, \p x6
+ */
+pmt_t pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6);
+
+
 /*
  * ------------------------------------------------------------------------
  *                          read / write
index c36a5e97245848e47b27c0d725b7038007e4499e..26b3e26d38bc0a764f40c8fafa08bac6ac400579 100644 (file)
@@ -138,11 +138,17 @@ qa_pmt_prims::test_pairs()
   pmt_t s2 = pmt_string_to_symbol("s2");
   pmt_t s3 = pmt_string_to_symbol("s3");
 
+
+  CPPUNIT_ASSERT_EQUAL((size_t)0, pmt_length(PMT_NIL));
+  CPPUNIT_ASSERT_THROW(pmt_length(s1), pmt_wrong_type);
+  CPPUNIT_ASSERT_THROW(pmt_length(pmt_from_double(42)), pmt_wrong_type);
+
   pmt_t c1 = pmt_cons(s1, PMT_NIL);
   CPPUNIT_ASSERT(pmt_is_pair(c1));
   CPPUNIT_ASSERT(!pmt_is_pair(s1));
   CPPUNIT_ASSERT_EQUAL(s1, pmt_car(c1));
   CPPUNIT_ASSERT_EQUAL(PMT_NIL, pmt_cdr(c1));
+  CPPUNIT_ASSERT_EQUAL((size_t) 1, pmt_length(c1));
 
   pmt_t c3 = pmt_cons(s3, PMT_NIL);
   pmt_t c2 = pmt_cons(s2, c3);
@@ -150,7 +156,9 @@ qa_pmt_prims::test_pairs()
   CPPUNIT_ASSERT_EQUAL(c2, pmt_cdr(c1));
   pmt_set_car(c1, s3);
   CPPUNIT_ASSERT_EQUAL(s3, pmt_car(c1));
-
+  CPPUNIT_ASSERT_EQUAL((size_t)1, pmt_length(c3));
+  CPPUNIT_ASSERT_EQUAL((size_t)2, pmt_length(c2));
+  
   CPPUNIT_ASSERT_THROW(pmt_cdr(PMT_NIL), pmt_wrong_type);
   CPPUNIT_ASSERT_THROW(pmt_car(PMT_NIL), pmt_wrong_type);
   CPPUNIT_ASSERT_THROW(pmt_set_car(s1, PMT_NIL), pmt_wrong_type);
@@ -228,8 +236,6 @@ qa_pmt_prims::test_equivalence()
 void
 qa_pmt_prims::test_misc()
 {
-  CPPUNIT_ASSERT_THROW(pmt_length(PMT_NIL), pmt_wrong_type);
-
   pmt_t k0 = pmt_string_to_symbol("k0");
   pmt_t k1 = pmt_string_to_symbol("k1");
   pmt_t k2 = pmt_string_to_symbol("k2");
index 2b3178da71606fb1a614167d89f55ba7ea453ff2..9392bf1511db06e15aa69a97fe2da465afba6d12 100755 (executable)
 module chan_fifo_reader 
-  ( input       reset,
-    input       tx_clock,
-    input       tx_strobe,
-    input       [31:0]adc_clock,
-    input       [3:0] samples_format,
-    input       [15:0] fifodata,
-    input       pkt_waiting,
-    output  reg rdreq,
-    output  reg skip,
-    output  reg [15:0]tx_q,
-    output  reg [15:0]tx_i,
-    output  reg overrun,
-    output  reg underrun) ;
-    
+  ( reset, tx_clock, tx_strobe, adc_time, samples_format,
+    fifodata, pkt_waiting, rdreq, skip, tx_q, tx_i,
+    underrun, tx_empty, debug, rssi, threshhold) ;
+
+    input   wire                     reset ;
+    input   wire                     tx_clock ;
+    input   wire                     tx_strobe ; //signal to output tx_i and tx_q
+    input   wire              [31:0] adc_time ; //current time
+    input   wire               [3:0] samples_format ;// not useful at this point
+    input   wire              [31:0] fifodata ; //the data input
+    input   wire                     pkt_waiting ; //signal the next packet is ready
+    output  reg                      rdreq ; //actually an ack to the current fifodata
+    output  reg                      skip ; //finish reading current packet
+    output  reg               [15:0] tx_q ; //top 16 bit output of fifodata
+    output  reg               [15:0] tx_i ; //bottom 16 bit output of fifodata
+    output  reg                      underrun ; 
+    output  reg                      tx_empty ; //cause 0 to be the output
+    input      wire                      [31:0] rssi;
+    input      wire                      [31:0] threshhold;
+
+       output wire [14:0] debug;
+       assign debug = {reader_state, trash, skip, timestamp[4:0], adc_time[4:0]};
     // Should not be needed if adc clock rate < tx clock rate
-    `define JITTER        5
+    // Used only to debug
+    `define JITTER                   5
     
     //Samples format
     // 16 bits interleaved complex samples
-    `define QI16         4'b0
+    `define QI16                     4'b0
     
     // States
-   `define IDLE          4'd0
-   `define READ          4'd1
-   `define HEADER1       4'd2
-   `define HEADER2       4'd3
-   `define TIMESTAMP1    4'd4
-   `define TIMESTAMP2    4'd5
-   `define WAIT          4'd6
-   `define WAITSTROBE    4'd7
-   `define SENDWAIT      4'd8
-   `define SEND          4'd9
-   `define FEED          4'd10
-   `define DISCARD       4'd11
+    parameter IDLE           =     3'd0;    
+       parameter HEADER         =     3'd1;
+    parameter TIMESTAMP      =     3'd2;
+    parameter WAIT           =     3'd3;
+    parameter WAITSTROBE     =     3'd4;
+    parameter SEND           =     3'd5;
 
-   // State registers
-   reg[3:0] reader_state;
-   reg[3:0] reader_next_state;
+    // Header format
+    `define PAYLOAD                  8:2
+    `define ENDOFBURST               27
+    `define STARTOFBURST            28
+    `define RSSI_FLAG                           15
+       
+
+    /* State registers */
+    reg                        [2:0] reader_state;
+  
+    reg                        [6:0] payload_len;
+    reg                        [6:0] read_len;
+    reg                       [31:0] timestamp;
+    reg                              burst;
+       reg                                                              trash;
+       reg                                                              rssi_flag;
    
-   //Variables
-   reg[8:0] payload_len;
-   reg[8:0] read_len;
-   reg[31:0] timestamp;
-   reg burst;
-   reg qsample;
-   always @(posedge tx_clock)
-   begin
-       if (reset) 
+    always @(posedge tx_clock)
+    begin
+        if (reset) 
           begin
-             reader_state <= `IDLE;
-             reader_next_state <= `IDLE;
-             rdreq <= 0;
-             skip <= 0;
-             overrun <= 0;
-             underrun <= 0;
-             burst <= 0;
-             qsample <= 1;
-          end
+            reader_state <= IDLE;
+            rdreq <= 0;
+            skip <= 0;
+            underrun <= 0;
+            burst <= 0;
+            tx_empty <= 1;
+            tx_q <= 0;
+            tx_i <= 0;
+                       trash <= 0;
+                       rssi_flag <= 0;
+         end
        else 
-                begin
-           reader_state = reader_next_state;
+                  begin
            case (reader_state)
-               `IDLE:
-                  begin
-                     if (pkt_waiting == 1)
-                       begin
-                          reader_next_state <= `READ;
-                          rdreq <= 1;
-                          underrun <= 0;
-                       end
-                     else if (burst == 1)
+               IDLE:
+               begin
+                               /*
+                                * reset all the variables and wait for a tx_strobe
+                                * it is assumed that the ram connected to this fifo_reader 
+                                * is a short hand fifo meaning that the header to the next packet
+                                * is already available to this fifo_reader when pkt_waiting is on
+                                */
+                   skip <=0;
+                   if (pkt_waiting == 1)
+                     begin
+                        reader_state <= HEADER;
+                        rdreq <= 1;
+                        underrun <= 0;
+                     end
+                   else if (burst == 1)
                         underrun <= 1;
-                  end
-
-                               // Just wait for the fifo data to arrive
-               `READ: 
-                  begin
-                     reader_next_state <= `HEADER1;
-                  end
-                               
-                               // First part of the header
-               `HEADER1:
-                  begin
-                     reader_next_state <= `HEADER2;
-                     
-                     //Check Start burst flag
-                     if (fifodata[3] == 1)
-                        burst <= 1;
                         
-                     if (fifodata[4] == 1)
-                        burst <= 0;
-                  end
+                   if (tx_strobe == 1)
+                       tx_empty <= 1 ;
+               end
 
-                               // Read payload length
-               `HEADER2:
-                  begin
-                     payload_len <= (fifodata & 16'h1FF);
-                     read_len <= 9'd0;
-                     reader_next_state <= `TIMESTAMP1;
-                  end
+                                  /* Process header */
+               HEADER:
+               begin
+                   if (tx_strobe == 1)
+                       tx_empty <= 1 ;
+                   
+                   rssi_flag <= fifodata[`RSSI_FLAG]&fifodata[`STARTOFBURST];
+                   //Check Start/End burst flag
+                   if  (fifodata[`STARTOFBURST] == 1 
+                       && fifodata[`ENDOFBURST] == 1)
+                       burst <= 0;
+                   else if (fifodata[`STARTOFBURST] == 1)
+                       burst <= 1;
+                   else if (fifodata[`ENDOFBURST] == 1)
+                       burst <= 0;
 
-               `TIMESTAMP1: 
-                  begin
-                     timestamp <= {fifodata, 16'b0};
-                     rdreq <= 0;
-                     reader_next_state <= `TIMESTAMP2;
-                  end
-                               
-               `TIMESTAMP2:
-                  begin
-                     timestamp <= timestamp + fifodata;
-                     reader_next_state <= `WAIT;
-                  end
+                                       if (trash == 1 && fifodata[`STARTOFBURST] == 0)
+                                       begin
+                                               skip <= 1;
+                                               reader_state <= IDLE;
+                                               rdreq <= 0;
+                                       end 
+                    else
+                                       begin   
+                               payload_len <= fifodata[`PAYLOAD] ;
+                               read_len <= 0;
+                        rdreq <= 1;
+                                               reader_state <= TIMESTAMP;
+                                       end
+               end
+
+               TIMESTAMP: 
+               begin
+                   timestamp <= fifodata;
+                   reader_state <= WAIT;
+                   if (tx_strobe == 1)
+                       tx_empty <= 1 ;
+                   rdreq <= 0;
+               end
                                
-                               // Decide if we wait, send or discard samples
-               `WAIT: 
-                  begin
-                   // Wait a little bit more
-                     if (timestamp > adc_clock + `JITTER)
-                        reader_next_state <= `WAIT;
+                                  // Decide if we wait, send or discard samples
+               WAIT: 
+               begin
+                   if (tx_strobe == 1)
+                       tx_empty <= 1 ;
+                          
                    // Let's send it
-                   else if ((timestamp < adc_clock + `JITTER 
-                           && timestamp > adc_clock)
-                           || timestamp == 32'hFFFFFFFF)
-                      begin
-                         reader_next_state <= `WAITSTROBE;
-                      end
+                   if ((timestamp <= adc_time + `JITTER 
+                             && timestamp > adc_time)
+                             || timestamp == 32'hFFFFFFFF)
+                                       begin
+                                               if (rssi <= threshhold || rssi_flag == 0)
+                                                 begin
+                                                   trash <= 0;
+                            reader_state <= WAITSTROBE; 
+                          end
+                                               else
+                                                   reader_state <= WAIT;
+                                       end
+                   // Wait a little bit more
+                   else if (timestamp > adc_time + `JITTER)
+                       reader_state <= WAIT; 
                    // Outdated
-                   else if (timestamp < adc_clock)
-                      begin
-                         reader_next_state <= `DISCARD;
-                         skip <= 1;
+                   else if (timestamp < adc_time)
+                     begin
+                                               trash <= 1;
+                        reader_state <= IDLE;
+                        skip <= 1;
                      end
-                 end
+               end
                  
-            // Wait for the transmit chain to be ready
-               `WAITSTROBE:
-                  begin
-                      // If end of payload...
-                     if (read_len == payload_len)
+               // Wait for the transmit chain to be ready
+               WAITSTROBE:
+               begin
+                   // If end of payload...
+                   if (read_len == payload_len)
+                     begin
+                       reader_state <= IDLE;
+                       skip <= 1;
+                       if (tx_strobe == 1)
+                           tx_empty <= 1 ;
+                     end  
+                   else if (tx_strobe == 1)
+                     begin
+                       reader_state <= SEND;
+                       rdreq <= 1;
+                     end
+               end
+               
+                                  // Send the samples to the tx_chain
+               SEND:
+               begin
+                   reader_state <= WAITSTROBE; 
+                   read_len <= read_len + 7'd1;
+                   tx_empty <= 0;
+                   rdreq <= 0;
+                   
+                   case(samples_format)
+                       `QI16:
                         begin
-                           reader_next_state <= `DISCARD;
-                           skip <= (payload_len < 508);
+                            tx_i <= fifodata[15:0];
+                            tx_q <= fifodata[31:16];
                         end
-                          
-                      if (tx_strobe == 1)
-                         reader_next_state <= `SENDWAIT;
-                  end
-               
-               `SENDWAIT:
-                  begin
-                     rdreq <= 1;
-                     reader_next_state <= `SEND; 
-                  end
-               
-                               // Send the samples to the tx_chain
-               `SEND:
-                  begin
-                     reader_next_state <= `WAITSTROBE; 
-                     rdreq <= 0;
-                     read_len <= read_len + 2;
-                     case(samples_format)
-                        `QI16:
-                           begin
-                              tx_q <= qsample ? fifodata : 16'bZ;
-                              tx_i <= ~qsample ? fifodata : 16'bZ;
-                              qsample <= ~ qsample;
-                           end  
+                        
+                        // Assume 16 bits complex samples by default
                         default:
-                           begin
-                               // Assume 16 bits complex samples by default
-                              $display ("Error unknown samples format");
-                              tx_q <= qsample ? fifodata : 16'bZ;
-                              tx_i <= ~qsample ? fifodata : 16'bZ;
-                              qsample <= ~ qsample;
-                           end 
-                     endcase
-                  end
-
-               `DISCARD:
-                  begin
-                     skip <= 0;
-                     reader_next_state <= `IDLE;
-                  end
+                        begin
+                            tx_i <= fifodata[15:0];
+                            tx_q <= fifodata[31:16];
+                        end 
+                   endcase
+               end
                
                default:
-                  begin
-                     $display ("Error unknown state");
-                     reader_state <= `IDLE;
-                     reader_next_state <= `IDLE;
-                  end
+               begin
+                                       //error handling
+                   reader_state <= IDLE;
+               end
            endcase
        end
    end
  
-endmodule
\ No newline at end of file
+endmodule
diff --git a/usrp/fpga/inband_lib/channel_demux.v b/usrp/fpga/inband_lib/channel_demux.v
new file mode 100644 (file)
index 0000000..d46be93
--- /dev/null
@@ -0,0 +1,78 @@
+module channel_demux
+ #(parameter NUM_CHAN = 2, parameter CHAN_WIDTH = 2) (     //usb Side
+                       input [31:0]usbdata_final,
+                       input WR_final, 
+                       
+                       // TX Side
+                       input reset,
+                       input txclk,
+                       output reg [CHAN_WIDTH:0] WR_channel,
+                       output reg [31:0] ram_data,
+                       output reg [CHAN_WIDTH:0] WR_done_channel );
+/* Parse header and forward to ram */
+       reg [2:0]reader_state;
+       reg [4:0]channel ;
+       reg [6:0]read_length ;
+       
+        // States
+    parameter IDLE             =       3'd0;
+    parameter HEADER   =       3'd1;
+    parameter WAIT             =       3'd2;
+    parameter FORWARD  =       3'd3;
+       
+       `define CHANNEL 20:16
+       `define PKT_SIZE 127
+       wire [4:0] true_channel;
+       assign true_channel = (usbdata_final[`CHANNEL] == 5'h1f) ?
+                                                       NUM_CHAN : (usbdata_final[`CHANNEL]);
+       
+       always @(posedge txclk)
+       begin
+           if (reset)
+             begin
+              reader_state <= IDLE;
+              WR_channel <= 0;
+              WR_done_channel <= 0;
+             end
+             else
+               case (reader_state)
+               IDLE: begin
+                   if (WR_final)
+                       reader_state <= HEADER; 
+                   end
+              
+            // Store channel and forware header
+               HEADER: begin
+                   channel <= true_channel;
+                   WR_channel[true_channel] <= 1;
+                   ram_data <= usbdata_final;
+                               read_length <= 7'd0 ;
+                               
+                reader_state <= WAIT;
+               end
+              
+               WAIT: begin
+                  WR_channel[channel] <= 0;
+       
+                          if (read_length == `PKT_SIZE)
+                      reader_state <= IDLE;
+                  else if (WR_final)
+                      reader_state <= FORWARD;
+               end
+              
+               FORWARD: begin
+                  WR_channel[channel] <= 1;
+                  ram_data <= usbdata_final;
+                  read_length <= read_length + 7'd1;
+                  
+                  reader_state <= WAIT;
+               end
+       
+                       default:
+               begin
+                                       //error handling
+                   reader_state <= IDLE;
+               end
+              endcase
+          end
+endmodule
diff --git a/usrp/fpga/inband_lib/channel_ram.v b/usrp/fpga/inband_lib/channel_ram.v
new file mode 100755 (executable)
index 0000000..40e0efc
--- /dev/null
@@ -0,0 +1,114 @@
+module channel_ram 
+       ( // System
+       input txclk,
+       input reset,
+       
+       // USB side
+       input [31:0] datain, 
+       input WR, 
+       input WR_done,
+       output have_space,
+
+       // Reader side
+       output [31:0] dataout,
+       input RD,
+       input RD_done,
+       output packet_waiting);
+       
+       reg [6:0] wr_addr, rd_addr;
+       reg [1:0] which_ram_wr, which_ram_rd;
+       reg [2:0] nb_packets;
+       
+       reg [31:0] ram0 [0:127];
+       reg [31:0] ram1 [0:127];
+       reg [31:0] ram2 [0:127];
+       reg [31:0] ram3 [0:127];
+       
+       reg [31:0] dataout0;
+       reg [31:0] dataout1;
+       reg [31:0] dataout2;
+       reg [31:0] dataout3;
+       
+       wire wr_done_int;
+       wire rd_done_int;
+       wire [6:0] rd_addr_final;
+       wire [1:0] which_ram_rd_final;
+       
+       // USB side
+       always @(posedge txclk)
+               if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
+                       
+       always @(posedge txclk)
+               if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
+
+       always @(posedge txclk)
+               if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
+
+       always @(posedge txclk)
+               if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
+
+   assign wr_done_int = ((WR && (wr_addr == 7'd127)) || WR_done);
+   
+       always @(posedge txclk)
+               if(reset)
+                       wr_addr <= 0;
+               else if (WR_done)
+                       wr_addr <= 0;
+               else if (WR) 
+                       wr_addr <= wr_addr + 7'd1;
+               
+       always @(posedge txclk)
+               if(reset)
+                       which_ram_wr <= 0;
+               else if (wr_done_int) 
+                       which_ram_wr <= which_ram_wr + 2'd1;
+       
+       assign have_space = (nb_packets < 3'd3);
+               
+       // Reader side
+       // short hand fifo
+       // rd_addr_final is what rd_addr is going to be next clock cycle
+       // which_ram_rd_final is what which_ram_rd is going to be next clock cycle
+       always @(posedge txclk)  dataout0 <= ram0[rd_addr_final];
+       always @(posedge txclk)  dataout1 <= ram1[rd_addr_final];
+       always @(posedge txclk)  dataout2 <= ram2[rd_addr_final];
+       always @(posedge txclk)  dataout3 <= ram3[rd_addr_final];
+       
+       assign dataout = (which_ram_rd_final[1]) ? 
+                                               (which_ram_rd_final[0] ? dataout3 : dataout2) :
+                                               (which_ram_rd_final[0] ? dataout1 : dataout0);
+
+       //RD_done is the only way to signal the end of one packet
+       assign rd_done_int = RD_done;   
+
+       always @(posedge txclk)
+               if (reset)
+                       rd_addr <= 0;
+               else if (RD_done)
+                       rd_addr <= 0;
+               else if (RD) rd_addr <= rd_addr + 7'd1;
+                       
+       assign rd_addr_final = (reset|RD_done) ? (6'd0) : 
+                               ((RD)?(rd_addr+7'd1):rd_addr); 
+       always @(posedge txclk)
+          if (reset)
+                       which_ram_rd <= 0;
+               else if (rd_done_int)
+                       which_ram_rd <= which_ram_rd + 2'd1;
+
+       assign which_ram_rd_final = (reset) ? (2'd0):
+                              ((rd_done_int) ? (which_ram_rd + 2'd1) : which_ram_rd);
+                               
+       //packet_waiting is set to zero if rd_done_int is high
+       //because there is no guarantee that nb_packets will be pos.
+       assign packet_waiting = (nb_packets != 0) & (~rd_done_int);
+       
+       always @(posedge txclk)
+               if (reset)
+                       nb_packets <= 0;
+               else if (wr_done_int & ~rd_done_int)
+                       nb_packets <= nb_packets + 3'd1;
+               else if (rd_done_int & ~wr_done_int)
+                       nb_packets <= nb_packets - 3'd1;
+                       
+endmodule
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/cmd_reader.v b/usrp/fpga/inband_lib/cmd_reader.v
new file mode 100755 (executable)
index 0000000..7604321
--- /dev/null
@@ -0,0 +1,292 @@
+module cmd_reader(
+               //System
+               input reset,
+               input txclk,
+               input [31:0] adc_time,
+               //FX2 Side
+               output reg skip,
+               output reg rdreq,
+               input [31:0] fifodata,
+               input pkt_waiting,
+               //Rx side
+               input rx_WR_enabled,
+               output reg [15:0] rx_databus,
+               output reg rx_WR,
+               output reg rx_WR_done,
+               //register io
+               input wire [31:0] reg_data_out,
+               output reg [31:0] reg_data_in,
+               output reg [6:0] reg_addr,
+               output reg [1:0] reg_io_enable,
+               output wire [14:0] debug                
+       );
+       
+       // States
+    parameter IDLE                             =       4'd0;
+       parameter HEADER                        =       4'd1;
+       parameter TIMESTAMP                     =       4'd2;
+    parameter WAIT             =   4'd3;
+       parameter TEST                          =       4'd4;
+       parameter SEND                          =       4'd5;
+       parameter PING                          =       4'd6;
+       parameter WRITE_REG                     =       4'd7;
+       parameter WRITE_REG_MASKED      =       4'd8;
+       parameter READ_REG                      =   4'd9;
+       parameter DELAY                         =       4'd14;          
+
+       `define OP_PING_FIXED                           8'd0
+       `define OP_PING_FIXED_REPLY                     8'd1
+       `define OP_WRITE_REG                            8'd2
+       `define OP_WRITE_REG_MASKED                     8'd3
+       `define OP_READ_REG                                     8'd4
+       `define OP_READ_REG_REPLY                       8'd5
+       `define OP_DELAY                                        8'd12
+       
+       reg [6:0]       payload;
+       reg [6:0]       payload_read;
+       reg [3:0]       state;
+       reg [15:0]  high;
+       reg [15:0]      low;
+       reg                     pending;
+       reg [31:0]  value0;
+       reg [31:0]      value1;
+       reg [31:0]      value2;
+       reg [1:0]   lines_in;
+       reg [1:0]       lines_out;
+       reg [1:0]       lines_out_total;
+       
+       `define JITTER                      5
+       `define OP_CODE                                         31:24
+       `define PAYLOAD                                         8:2
+       
+       wire [7:0] ops;
+       assign ops = value0[`OP_CODE];
+       assign debug = {state[3:0], lines_out[1:0], pending, rx_WR, rx_WR_enabled, value0[2:0], ops[2:0]};
+       
+       always @(posedge txclk)
+               if (reset)
+                 begin
+                       pending <= 0;
+                   state <= IDLE;
+                       skip <= 0;
+                       rdreq <= 0;
+                       rx_WR <= 0;
+                       reg_io_enable <= 0;
+                       reg_data_in <= 0;
+                       reg_addr <= 0;
+                 end
+               else case (state)
+                       IDLE : begin
+                               payload_read <= 0;
+                               skip <= 0;
+                               lines_in <= 0;
+                               if (pkt_waiting)
+                                 begin
+                                       state <= HEADER;
+                                       rdreq <= 1;
+                                 end
+                       end
+                       
+                       HEADER : begin
+                               payload <= fifodata[`PAYLOAD];
+                               state <= TIMESTAMP;
+                       end
+                       
+                       TIMESTAMP : begin
+                               value0 <= fifodata;
+                               state <= WAIT;
+                               rdreq <= 0;
+                       end
+                       
+                       WAIT : begin
+                                       // Let's send it
+                   if ((value0 <= adc_time + `JITTER 
+                             && value0 > adc_time)
+                             || value0 == 32'hFFFFFFFF)
+                       state <= TEST;
+                   // Wait a little bit more
+                   else if (value0 > adc_time + `JITTER)
+                       state <= WAIT; 
+                   // Outdated
+                   else if (value0 < adc_time)
+                     begin
+                        state <= IDLE;
+                        skip <= 1;
+                     end
+                       end
+                       
+                       TEST : begin
+                               reg_io_enable <= 0;
+                               rx_WR <= 0;
+                               rx_WR_done <= 1;
+                               if (payload_read == payload)
+                                       begin
+                                               skip <= 1;
+                                               state <= IDLE;
+                                               rdreq <= 0;
+                                       end
+                               else
+                                       begin
+                                               value0 <= fifodata;
+                                               lines_in <= 2'd1;
+                                               rdreq <= 1;
+                                               payload_read <= payload_read + 7'd1;
+                                               lines_out <= 0;
+                                               case (fifodata[`OP_CODE])
+                                                       `OP_PING_FIXED: begin
+                                                               state <= PING;
+                                                       end
+                                                       `OP_WRITE_REG: begin
+                                                               state <= WRITE_REG;
+                                                               pending <= 1;
+                                                       end
+                                                       `OP_WRITE_REG_MASKED: begin
+                                                               state <= WRITE_REG_MASKED;
+                                                               pending <= 1;
+                                                       end
+                                                       `OP_READ_REG: begin
+                                                               state <= READ_REG;
+                                                       end
+                                                       `OP_DELAY: begin
+                                                               state <= DELAY;
+                                                       end
+                                                       default: begin
+                                                       //error, skip this packet
+                                                               skip <= 1;
+                                                               state <= IDLE;
+                                                       end
+                                               endcase
+                                       end
+                       end
+                       
+                       SEND: begin
+                               rdreq <= 0;
+                               rx_WR_done <= 0;
+                               if (pending)
+                                       begin
+                                               rx_WR <= 1;
+                                               rx_databus <= high;
+                                               pending <= 0;
+                                               if (lines_out == lines_out_total)
+                                                       state <= TEST;
+                                               else case (ops)
+                                                       `OP_READ_REG: begin
+                                                               state <= READ_REG;
+                                                       end
+                                                       default: begin
+                                                               state <= TEST;
+                                                       end
+                                               endcase
+                                       end
+                               else
+                                       begin
+                                               if (rx_WR_enabled)
+                                               begin
+                                                       rx_WR <= 1;
+                                                       rx_databus <= low;
+                                                       pending <= 1;
+                                                       lines_out <= lines_out + 2'd1;
+                                               end
+                                               else
+                                                       rx_WR <= 0;
+                                       end
+                       end
+                       
+                       PING: begin
+                               rx_WR <= 0;
+                               rdreq <= 0;
+                               rx_WR_done <= 0;
+                               lines_out_total <= 2'd1;
+                               pending <= 0;
+                               state <= SEND;
+                               high <= {`OP_PING_FIXED_REPLY, 8'd2};
+                               low <= value0[15:0];    
+                       end
+                       
+                       READ_REG: begin
+                               rx_WR <= 0;
+                               rx_WR_done <= 0;
+                               rdreq <= 0;
+                               lines_out_total <= 2'd2;
+                               pending <= 0;
+                               state <= SEND;
+                               if (lines_out == 0)
+                                       begin
+                                               high <= {`OP_READ_REG_REPLY, 8'd6};
+                                               low <= value0[15:0];
+                                               reg_io_enable <= 2'd3;
+                                               reg_addr <= value0[6:0];
+                                       end
+                               else
+                                       begin           
+                                               high <= reg_data_out[31:16];
+                                               low <= reg_data_out[15:0];
+                                       end
+                       end
+                       
+                       WRITE_REG: begin
+                               rx_WR <= 0;
+                               if (pending)
+                                       pending <= 0;
+                               else
+                                       begin
+                                               if (lines_in == 2'd1)
+                                               begin
+                                                       payload_read <= payload_read + 7'd1;
+                                                       lines_in <= lines_in + 2'd1;
+                                                       value1 <= fifodata;
+                                                       rdreq <= 0;
+                                               end
+                                               else
+                                               begin
+                                                       reg_io_enable <= 2'd2;
+                                                       reg_data_in <= value1;
+                                                       reg_addr <= value0[6:0];
+                                                       state <= TEST;
+                                               end
+                                       end
+                       end
+                       
+                       WRITE_REG_MASKED: begin
+                               rx_WR <= 0;
+                               if (pending)
+                                       pending <= 0;
+                               else
+                                       begin
+                                               if (lines_in == 2'd1)
+                                               begin
+                                                       rdreq <= 1;
+                                                       payload_read <= payload_read + 7'd1;
+                                                       lines_in <= lines_in + 2'd1;
+                                                       value1 <= fifodata;
+                                               end
+                                               else if (lines_in == 2'd2)
+                                               begin
+                                                       rdreq <= 0;
+                                                       payload_read <= payload_read + 7'd1;
+                                                       lines_in <= lines_in + 2'd1;
+                                                       value2 <= fifodata;
+                                               end
+                                               else
+                                               begin
+                                                       reg_io_enable <= 2'd2;
+                                                       reg_data_in <= (value1 & value2);
+                                                       reg_addr <= value0[6:0];
+                                                       state <= TEST;
+                                               end
+                                       end
+                       end
+                       
+                       DELAY : begin
+                               rdreq <= 0;
+                               value1 <= value1 + 32'd1;
+                               if (value0[15:0] == value1[15:0])
+                                       state <= TEST;
+                       end
+                       
+                       default : begin
+                               //error state handling
+                               state <= IDLE;
+                       end
+               endcase
+endmodule
\ No newline at end of file
index 5b37b14eaa74379c6de08cd0cd8d8a0342931217..a9bcbdae7b6d6576604b0bd767ae543aa0f45dfb 100755 (executable)
 module data_packet_fifo 
   ( input       reset,
     input       clock,
-    input       [15:0]ram_data_in,
+    input       [31:0]ram_data_in,
     input       write_enable,
     output  reg have_space,
-    output  reg [15:0]ram_data_out,
+    output  reg [31:0]ram_data_out,
     output  reg pkt_waiting,
+       output  reg     isfull,
+       output  reg [1:0]usb_ram_packet_out,
+       output  reg [1:0]usb_ram_packet_in,
     input       read_enable,
     input       pkt_complete,
     input       skip_packet) ;
 
     /* Some parameters for usage later on */
-    parameter DATA_WIDTH = 16 ;
+    parameter DATA_WIDTH = 32 ;
+    parameter PKT_DEPTH = 128 ;
     parameter NUM_PACKETS = 4 ;
 
     /* Create the RAM here */
-    reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
+    reg [DATA_WIDTH-1:0] usb_ram [PKT_DEPTH*NUM_PACKETS-1:0] ;
 
     /* Create the address signals */
-    reg [7:0] usb_ram_offset_out ;
-    reg [1:0] usb_ram_packet_out ;
-    reg [7:0] usb_ram_offset_in ;
-    reg [1:0] usb_ram_packet_in ;
+    reg [6:0] usb_ram_offset_out ;
+    //reg [1:0] usb_ram_packet_out ;
+    reg [6:0] usb_ram_offset_in ;
+    //reg [1:0] usb_ram_packet_in ;
 
-    wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
-    wire [7-2+NUM_PACKETS:0] usb_ram_ain ;
-    reg isfull;
+    wire [6-2+NUM_PACKETS:0] usb_ram_aout ;
+    wire [6-2+NUM_PACKETS:0] usb_ram_ain ;
+    //reg isfull;
 
     assign usb_ram_aout = {usb_ram_packet_out, usb_ram_offset_out} ;
     assign usb_ram_ain = {usb_ram_packet_in, usb_ram_offset_in} ;
     
     // Check if there is one full packet to process
-    always @(usb_ram_ain, usb_ram_aout)
+    always @(usb_ram_ain, usb_ram_aout, isfull)
     begin
-        if (reset)
-            pkt_waiting <= 0;
-        else if (usb_ram_ain >= usb_ram_aout)
-            pkt_waiting <= usb_ram_ain - usb_ram_aout >= 256;
+        if (usb_ram_ain == usb_ram_aout)
+            pkt_waiting <= isfull ;
+        else if (usb_ram_ain > usb_ram_aout)
+            pkt_waiting <= (usb_ram_ain - usb_ram_aout) >= PKT_DEPTH;
         else
-            pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
+            pkt_waiting <= (usb_ram_ain + 10'b1000000000 - usb_ram_aout) >= PKT_DEPTH;
     end
-
     // Check if there is room
-    always @(usb_ram_ain, usb_ram_aout)
+    always @(usb_ram_ain, usb_ram_aout, isfull)
     begin
-        if (reset)
-            have_space <= 1;
-        else if (usb_ram_ain == usb_ram_aout)
+        if (usb_ram_ain == usb_ram_aout)
             have_space <= ~isfull;   
         else if (usb_ram_ain > usb_ram_aout)
-            have_space <= (usb_ram_ain - usb_ram_aout) <= 256 * (NUM_PACKETS - 1);
+            have_space <= ((usb_ram_ain - usb_ram_aout) <= PKT_DEPTH * (NUM_PACKETS - 1))? 1'b1 : 1'b0;
         else
-            have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
+            have_space <= (usb_ram_aout - usb_ram_ain) >= PKT_DEPTH;
     end
 
-    /* RAM Write Address process */
-    always @(posedge clock)
-    begin
-        if( reset )
-          begin
-            usb_ram_offset_in <= 0 ;
-            usb_ram_packet_in <= 0 ;
-          end
-        else
-            if( pkt_complete )
-              begin
-                usb_ram_packet_in <= usb_ram_packet_in + 1;  
-                usb_ram_offset_in <= 0;
-              end
-            else if( write_enable ) 
-              begin
-                if (usb_ram_offset_in == 8'b11111111)
-                  begin
-                    usb_ram_offset_in <= 0;
-                    usb_ram_packet_in <= usb_ram_packet_in + 1;    
-                  end
-                else
-                    usb_ram_offset_in <= usb_ram_offset_in + 1 ;
-                    if (usb_ram_ain + 1 == usb_ram_aout)
-                       isfull <= 1;
-              end
-    end
 
-    /* RAM Writing process */
+
+    /* RAM Writing/Reading process */
     always @(posedge clock)
     begin
         if( write_enable ) 
           begin
             usb_ram[usb_ram_ain] <= ram_data_in ;
           end
+               ram_data_out <= usb_ram[usb_ram_aout] ;
     end
 
-    /* RAM Read Address process */
+    /* RAM Write/Read Address process */
     always @(posedge clock)
     begin
         if( reset ) 
           begin
             usb_ram_packet_out <= 0 ;
             usb_ram_offset_out <= 0 ;
+                       usb_ram_offset_in <= 0 ;
+            usb_ram_packet_in <= 0 ;
             isfull <= 0;
           end
         else
+                 begin
             if( skip_packet )
               begin
                 usb_ram_packet_out <= usb_ram_packet_out + 1 ;
                 usb_ram_offset_out <= 0 ;
+                isfull <= 0;
               end
-            else if(read_enable) begin
-                if( usb_ram_offset_out == 8'b11111111 )
+            else if(read_enable) 
+                         begin
+                if( usb_ram_offset_out == 7'b1111111 )
                   begin
+                    isfull <= 0 ;
                     usb_ram_offset_out <= 0 ;
                     usb_ram_packet_out <= usb_ram_packet_out + 1 ;
                   end
                 else
                     usb_ram_offset_out <= usb_ram_offset_out + 1 ;  
-            end 
-            if (usb_ram_ain == usb_ram_aout)
-               isfull <= 0;                    
-    end
-
-    /* RAM Reading Process */
-    always @(posedge clock)
-    begin
-        ram_data_out <= usb_ram[usb_ram_aout] ;
+              end
+                       if( pkt_complete )
+              begin
+                usb_ram_packet_in <= usb_ram_packet_in + 1 ;
+                usb_ram_offset_in <= 0 ;
+                if ((usb_ram_packet_in + 2'b1) == usb_ram_packet_out)
+                    isfull <= 1 ;
+              end
+            else if( write_enable ) 
+              begin
+                if (usb_ram_offset_in == 7'b1111111)
+                    usb_ram_offset_in <= 7'b1111111 ;    
+                else
+                    usb_ram_offset_in <= usb_ram_offset_in + 1 ;
+              end
+                 end
     end
 
 endmodule
diff --git a/usrp/fpga/inband_lib/packet_builder.v b/usrp/fpga/inband_lib/packet_builder.v
new file mode 100755 (executable)
index 0000000..2052934
--- /dev/null
@@ -0,0 +1,132 @@
+module packet_builder #(parameter NUM_CHAN = 1)(
+    // System
+    input rxclk,
+    input reset,
+        input [31:0] adctime,
+        input [3:0] channels,
+    // ADC side
+    input [15:0]chan_fifodata,
+    input [NUM_CHAN:0]chan_empty,
+    input [9:0]chan_usedw,
+    output reg [3:0]rd_select,
+    output reg chan_rdreq,
+    // FX2 side
+    output reg WR,
+    output reg [15:0]fifodata,
+    input have_space, 
+       input wire [31:0]rssi_0, input wire [31:0]rssi_1, input wire [31:0]rssi_2,
+       input wire [31:0]rssi_3, output wire [7:0] debugbus);
+    
+    
+    // States
+    `define IDLE                     3'd0
+    `define HEADER1                  3'd1
+       `define HEADER2                                  3'd2
+    `define TIMESTAMP                3'd3
+       `define FORWARD                                  3'd4
+       
+    `define MAXPAYLOAD 504
+    
+    `define PAYLOAD_LEN 8:0
+    `define TAG 12:9
+    `define MBZ 15:13
+    
+    `define CHAN 4:0
+    `define RSSI 10:5
+    `define BURST 12:11
+    `define DROPPED 13
+    `define UNDERRUN 14
+    `define OVERRUN 15
+    
+    reg [2:0] state;
+    reg [8:0] read_length;
+    reg [8:0] payload_len;
+    reg tstamp_complete;
+    reg [3:0] check_next;
+       wire [8:0] chan_used;
+    wire [31:0] true_rssi;
+
+       assign debugbus = {state, chan_empty[0], chan_empty[1], check_next[0],
+                                               have_space, rd_select[0]};
+       assign chan_used = chan_usedw[8:0];
+       assign true_rssi = (rd_select[1]) ? ((rd_select[0]) ? rssi_3:rssi_2) :
+                                                       ((rd_select[0]) ? rssi_1:rssi_0);       
+    always @(posedge rxclk)
+    begin
+        if (reset)
+          begin
+            WR <= 0;
+            rd_select <= 0;
+            chan_rdreq <= 0;
+            tstamp_complete <= 0;
+            check_next <= 0;
+            state <= `IDLE;
+          end
+        else case (state)
+            `IDLE: begin
+                               if (have_space)
+                                 begin
+                                       if(~chan_empty[check_next])
+                                     begin
+                               state <= #1 `HEADER1;
+                                               rd_select <= #1 check_next;
+                                         end
+                                       check_next <= #1 (check_next == channels ? 4'd0 : check_next + 4'd1);
+                                 end   
+            end
+            
+            `HEADER1: begin
+                fifodata[`PAYLOAD_LEN] <= #1 (chan_used > 9'd252
+                                           ? 9'd252 : chan_used << 1);
+                payload_len <= #1 (chan_used > 9'd252
+                                ? 9'd252 : chan_used << 1);
+                fifodata[`TAG] <= #1 0;
+                fifodata[`MBZ] <= #1 0;
+                WR <= #1 1;
+                
+                state <= #1 `HEADER2;
+                read_length <= #1 0;
+            end
+            
+            `HEADER2: begin
+                fifodata[`CHAN] <= #1 (check_next == 4'd0 ? 5'h1f : {1'd0, check_next - 4'd1});
+                fifodata[`RSSI] <= #1 true_rssi[5:0];
+                fifodata[`BURST] <= #1 0;
+                fifodata[`DROPPED] <= #1 0;
+                fifodata[`UNDERRUN] <= #1 0;
+                fifodata[`OVERRUN] <= #1 0;
+                
+                state <= #1 `TIMESTAMP;
+            end
+            
+            `TIMESTAMP: begin
+                fifodata <= #1 (tstamp_complete ? adctime[31:16] : adctime[15:0]);
+                tstamp_complete <= #1 ~tstamp_complete;
+                
+                if (~tstamp_complete)
+                    chan_rdreq <= #1 1;
+                
+                state <= #1 (tstamp_complete ? `FORWARD : `TIMESTAMP);
+            end
+            
+            `FORWARD: begin
+                read_length <= #1 read_length + 9'd2;
+                fifodata <= #1 (read_length >= payload_len ? 16'hDEAD : chan_fifodata);
+                
+                if (read_length >= `MAXPAYLOAD)
+                  begin
+                    WR <= #1 0;
+                    state <= #1 `IDLE;
+                  end
+                else if (read_length == payload_len - 4)
+                    chan_rdreq <= #1 0;
+            end
+            
+            default: begin
+                               //handling error state
+                state <= `IDLE;
+            end
+            endcase
+    end
+endmodule
+
diff --git a/usrp/fpga/inband_lib/register_io.v b/usrp/fpga/inband_lib/register_io.v
new file mode 100755 (executable)
index 0000000..63a2654
--- /dev/null
@@ -0,0 +1,60 @@
+module register_io
+       (input clk, input reset, input wire [1:0] enable, input wire [6:0] addr, 
+        input wire [31:0] datain, output reg [31:0] dataout, output wire [15:0] debugbus,
+        input wire [31:0] rssi_0, input wire [31:0] rssi_1,
+        input wire [31:0] rssi_2, input wire [31:0] rssi_3, output wire [31:0] threshhold);
+        
+       reg strobe;
+       wire [31:0] out[7:0];
+       assign debugbus = {clk, enable, addr[2:0], datain[4:0], dataout[4:0]};
+       assign threshhold = out[1];
+       
+       always @(*)
+        if (reset | ~enable[1])
+           begin
+             strobe <= 0;
+                    dataout <= 0;
+                  end
+               else
+                  begin
+                if (enable[0])
+                  begin
+                    //read
+                 if (addr == 7'd9)
+                       dataout <= rssi_0;
+                 else if (addr == 7'd10)
+                       dataout <= rssi_1;
+                 else if (addr == 7'd11)
+                       dataout <= rssi_2;
+                 else if (addr == 7'd12)
+                       dataout <= rssi_3;
+                 else
+                       dataout <= out[addr[2:0]];
+                    strobe <= 0;
+               end
+             else
+               begin
+                 //write
+                    dataout <= dataout;
+                 strobe <= 1;
+               end
+          end
+
+       //register declarations
+    setting_reg #(0) setting_reg0(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[0]));
+    setting_reg #(1) setting_reg1(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[1]));
+    setting_reg #(2) setting_reg2(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[2]));
+    setting_reg #(3) setting_reg3(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[3]));
+    setting_reg #(4) setting_reg4(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[4]));
+    setting_reg #(5) setting_reg5(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[5]));
+    setting_reg #(6) setting_reg6(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[6]));
+    setting_reg #(7) setting_reg7(.clock(clk),.reset(reset),
+    .strobe(strobe),.addr(addr),.in(datain),.out(out[7]));
+endmodule      
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/rx_buffer_inband.v b/usrp/fpga/inband_lib/rx_buffer_inband.v
new file mode 100755 (executable)
index 0000000..c23ce09
--- /dev/null
@@ -0,0 +1,175 @@
+//`include "../../firmware/include/fpga_regs_common.v"\r
+//`include "../../firmware/include/fpga_regs_standard.v"\r
+module rx_buffer_inband\r
+  ( input usbclk,\r
+    input bus_reset,\r
+    input reset,  // DSP side reset (used here), do not reset registers\r
+    input reset_regs, //Only reset registers\r
+    output [15:0] usbdata,\r
+    input RD,\r
+    output wire have_pkt_rdy,\r
+    output reg rx_overrun,\r
+    input wire [3:0] channels,\r
+    input wire [15:0] ch_0,\r
+    input wire [15:0] ch_1,\r
+    input wire [15:0] ch_2,\r
+    input wire [15:0] ch_3,\r
+    input wire [15:0] ch_4,\r
+    input wire [15:0] ch_5,\r
+    input wire [15:0] ch_6,\r
+    input wire [15:0] ch_7,\r
+    input rxclk,\r
+    input rxstrobe,\r
+    input clear_status,\r
+    input [6:0] serial_addr, \r
+    input [31:0] serial_data, \r
+    input serial_strobe,\r
+    output wire [15:0] debugbus,\r
+       \r
+       //Connection with tx_inband\r
+       input rx_WR,\r
+       input [15:0] rx_databus,\r
+       input rx_WR_done,\r
+       output reg rx_WR_enabled,\r
+       //signal strength\r
+       input wire [31:0] rssi_0, input wire [31:0] rssi_1,\r
+       input wire [31:0] rssi_2, input wire [31:0] rssi_3\r
+    );\r
+    \r
+    parameter NUM_CHAN = 1;\r
+    genvar i ;\r
+    \r
+    // FX2 Bug Fix\r
+    reg [8:0] read_count;\r
+    always @(negedge usbclk)\r
+        if(bus_reset)\r
+            read_count <= #1 9'd0;\r
+        else if(RD & ~read_count[8])\r
+            read_count <= #1 read_count + 9'd1;\r
+        else\r
+            read_count <= #1 RD ? read_count : 9'b0;\r
+       \r
+       // Time counter\r
+       reg [31:0] adctime;\r
+       always @(posedge rxclk)\r
+               if (reset)\r
+                       adctime <= 0;\r
+               else if (rxstrobe)\r
+                       adctime <= adctime + 1;\r
+     \r
+    // USB side fifo\r
+    wire [11:0] rdusedw;\r
+    wire [11:0] wrusedw;\r
+    wire [15:0] fifodata;\r
+    wire WR;\r
+    wire have_space;\r
+\r
+    fifo_4kx16_dc      rx_usb_fifo (\r
+            .aclr ( reset ),\r
+            .data ( fifodata ),\r
+            .rdclk ( ~usbclk ),\r
+            .rdreq ( RD & ~read_count[8] ),\r
+            .wrclk ( rxclk ),\r
+            .wrreq ( WR ),\r
+            .q ( usbdata ),\r
+            .rdempty (  ),\r
+            .rdusedw ( rdusedw ),\r
+            .wrfull (  ),\r
+            .wrusedw ( wrusedw ) );\r
+    \r
+     assign have_pkt_rdy = (rdusedw >= 12'd256);\r
+        assign have_space = (wrusedw < 12'd760);\r
+        \r
+        // Rx side fifos\r
+        wire chan_rdreq;\r
+        wire [15:0] chan_fifodata;\r
+        wire [9:0] chan_usedw;\r
+        wire [NUM_CHAN:0] chan_empty;\r
+        wire [3:0] rd_select;\r
+        wire [NUM_CHAN:0] rx_full;\r
+        \r
+        packet_builder #(NUM_CHAN) rx_pkt_builer (\r
+            .rxclk ( rxclk ),\r
+            .reset ( reset ),\r
+                 .adctime ( adctime ),\r
+                 .channels ( 4'd1 ), \r
+            .chan_rdreq ( chan_rdreq ),\r
+            .chan_fifodata ( chan_fifodata ),\r
+            .chan_empty ( chan_empty ),\r
+            .rd_select ( rd_select ),\r
+            .chan_usedw ( chan_usedw ),\r
+            .WR ( WR ),\r
+            .fifodata ( fifodata ),\r
+            .have_space ( have_space ),\r
+                .rssi_0(rssi_0), .rssi_1(rssi_1),\r
+               .rssi_2(rssi_2),.rssi_3(rssi_3), .debugbus(debug));\r
+        \r
+        // Detect overrun\r
+        always @(posedge rxclk)\r
+        if(reset)\r
+            rx_overrun <= 1'b0;\r
+        else if(rx_full[0])\r
+            rx_overrun <= 1'b1;\r
+        else if(clear_status)\r
+            rx_overrun <= 1'b0;\r
+\r
+       reg [6:0] test;\r
+       always @(posedge rxclk)\r
+               if (reset)\r
+                       test <= 0;\r
+               else\r
+                       test <= test + 7'd1;\r
+               \r
+        // TODO write this genericly\r
+        wire [15:0]ch[NUM_CHAN:0];\r
+        assign ch[0] = ch_0;\r
+        \r
+        wire cmd_empty;\r
+        always @(posedge rxclk)\r
+        if(reset)\r
+            rx_WR_enabled <= 1;\r
+               else if(cmd_empty)\r
+            rx_WR_enabled <= 1;\r
+        else if(rx_WR_done)\r
+            rx_WR_enabled <= 0;\r
+\r
+       wire [15:0] dataout [0:NUM_CHAN];\r
+       wire [9:0]  usedw       [0:NUM_CHAN];\r
+       \r
+        generate for (i = 0 ; i < NUM_CHAN; i = i + 1)\r
+     begin : generate_channel_fifos\r
+               wire rdreq;\r
+\r
+               assign rdreq = (rd_select == i) & chan_rdreq;\r
+               assign chan_empty[i] = usedw[i] < 10'd126;\r
+               \r
+        fifo_2kx16     rx_chan_fifo (\r
+                .aclr ( reset ),\r
+                .clock ( rxclk ),\r
+                .data ( ch[i] ),\r
+                .rdreq ( rdreq ),\r
+                        .wrreq ( ~rx_full[i] & rxstrobe),\r
+                .empty (  ),\r
+                .full ( rx_full[i] ),\r
+                .q ( dataout[i]),\r
+             .usedw ( usedw[i] )\r
+               );\r
+     end\r
+     endgenerate\r
+       wire [7:0] debug;\r
+        fifo_2kx16 rx_cmd_fifo (\r
+                .aclr ( reset ),\r
+                .clock ( rxclk ),\r
+                .data ( rx_databus ),\r
+                .rdreq ( (rd_select == NUM_CHAN) & chan_rdreq ),\r
+                        .wrreq ( rx_WR & rx_WR_enabled),\r
+                .empty ( cmd_empty),\r
+                .full ( rx_full[NUM_CHAN] ),\r
+                .q ( dataout[NUM_CHAN]),\r
+             .usedw ( usedw[NUM_CHAN] )\r
+       );      \r
+       assign chan_empty[NUM_CHAN] = cmd_empty | rx_WR_enabled;\r
+       assign chan_fifodata    = dataout[rd_select];\r
+       assign chan_usedw               = usedw[rd_select];\r
+    assign debugbus = {wrusedw, have_space, RD, read_count[8], rxclk};\r
+endmodule\r
index 56c07807ae27b8142dd88cf1effed237f4d7dc8e..af7ed394a722c1af8ffc5e85f07ebddc5faeb9ea 100755 (executable)
 module tx_buffer_inband
-  ( input usbclk,
-    input bus_reset,  // Used here for the 257-Hack to fix the FX2 bug
-    input reset,  // standard DSP-side reset
-    input [15:0] usbdata,
-    input wire WR,
-    output wire have_space,
-    output reg tx_underrun,
-    input wire [3:0] channels,
-    output [15:0] tx_i_0,
-    output [15:0] tx_q_0,
-    output [15:0] tx_i_1,
-    output [15:0] tx_q_1,
-    //NOT USED
-    output reg [15:0] tx_i_2,
-    output reg [15:0] tx_q_2,
-    output reg [15:0] tx_i_3,
-    output reg [15:0] tx_q_3,
-    input txclk,
-    input txstrobe,
-    input clear_status,
-    output wire tx_empty,
-    output [11:0] debugbus
-    );
+  ( usbclk, bus_reset, reset, usbdata, WR, have_space, 
+    tx_underrun, channels, tx_i_0, tx_q_0, tx_i_1, tx_q_1,
+    tx_i_2, tx_q_2, tx_i_3, tx_q_3, txclk, txstrobe,
+    clear_status, tx_empty, debugbus, 
+       rx_databus, rx_WR, rx_WR_done, rx_WR_enabled, reg_io_enable,
+       reg_data_in, reg_data_out, reg_addr, rssi_0, rssi_1, rssi_2, 
+    rssi_3, threshhold
+   );
 
-   wire [15:0] tx_data_bus;
+       //CHAN_WIDTH is the width of the channel
+       //NUM_CHAN is the number of data channel (index from 0 to NUM_CHAN-1)
+       //index NUM_CHAN is reserved for command
+       
+       parameter CHAN_WIDTH =          2 ;
+    parameter NUM_CHAN  =      2 ;
+       /* Debug paramters */
+    parameter STROBE_RATE_0 =   8'd1 ;
+    parameter STROBE_RATE_1 =   8'd2 ;
+    
+    input   wire                usbclk ;
+    input   wire                bus_reset ; // Used here for the 257-Hack to fix the FX2 bug
+    input   wire                reset ; // standard DSP-side reset
+    input   wire         [15:0] usbdata ;
+    input   wire                WR ;
+    input   wire                txclk ;
+    input   wire                txstrobe ;
+       input   wire                            rx_WR_enabled;
+    /* Not used yet */
+    input   wire          [3:0] channels ;
+    input   wire                clear_status ;
+    /*register io*/
+    input   wire          [31:0]reg_data_out;
+    // rssi
+    input      wire              [31:0]rssi_0;
+    input      wire              [31:0]rssi_1;
+    input      wire              [31:0]rssi_2;
+    input      wire              [31:0]rssi_3;
+    input      wire              [31:0]threshhold;
 
-   wire WR_chan_0;
-   wire chan_0_done;
-   wire OR0;
-   wire UR0;
-   
-   wire WR_chan_1;
-   wire chan_1_done;
-   wire OR1;
-   wire UR1;
-   
-   // NOT USED yet
-   wire WR_cmd;
-   wire cmd_done;
-   
-   //EXTERNAL REGISTER
-   //TODO: increment it
-   reg [31:0] time_counter;
-   reg [7:0] txstrobe_rate_0;
-   reg [7:0] txstrobe_rate_1;
-   
-   
-   //Usb block
-   wire [15:0] tupf_fifodata;
-   wire tupf_pkt_waiting;
-   wire tupf_rdreq;
-   wire tupf_skip;
-   wire tupf_have_space;
+    output  wire                have_space ;
+    output  wire                tx_underrun ;
+    output  wire                tx_empty ;
+    output  wire         [15:0] tx_i_0 ;
+    output  wire         [15:0] tx_q_0 ;
+    output  wire         [15:0] tx_i_1 ;
+    output  wire         [15:0] tx_q_1 ;
+    output  wire         [15:0] debugbus ;
+    /* Not used yet */
+    output  wire         [15:0] tx_i_2 ;
+    output  wire         [15:0] tx_q_2 ;
+    output  wire         [15:0] tx_i_3 ;
+    output  wire         [15:0] tx_q_3 ;
+
+       output  wire             [15:0] rx_databus ;
+       output  wire                            rx_WR;
+       output  wire                            rx_WR_done;
+    /* reg_io */
+    output  wire         [31:0] reg_data_in;
+    output  wire         [6:0]  reg_addr;
+    output  wire         [1:0]  reg_io_enable;
+
+    /* To generate channel readers */
+    genvar i ;
+    
+    /* These will eventually be external register */
+    reg                  [31:0] adc_time ;
+    wire                  [7:0] txstrobe_rate [CHAN_WIDTH-1:0] ;
+    wire                                [31:0] rssi [3:0];
+    assign rssi[0] = rssi_0;
+    assign rssi[1] = rssi_1;
+    assign rssi[2] = rssi_2;
+    assign rssi[3] = rssi_3;
    
-   usb_packet_fifo2 tx_usb_packet_fifo 
-     (  .reset         (reset),
-        .usb_clock     (usbclk), 
-        .fpga_clock    (txclk),
-        .write_data    (usbdata),
-        .write_enable  (WR),
-        .read_data     (tupf_fifodata),
-        .pkt_waiting   (tupf_pkt_waiting),
-        .read_enable   (tupf_rdreq), 
-        .skip_packet   (tupf_skip),
-        .have_space    (tupf_have_space),
-        .tx_empty      (tx_empty)
-       );
+       always @(posedge txclk)
+               if (reset)
+                       adc_time <= 0;
+               else if (txstrobe)
+                       adc_time <= adc_time + 1;
+
+
+    /* Connections between tx_usb_fifo_reader and
+       cnannel/command processing blocks */
+    wire                 [31:0] tx_data_bus ;
+    wire           [CHAN_WIDTH:0] chan_WR ;
+    wire           [CHAN_WIDTH:0] chan_done ;
+    
+    /* Connections between data block and the
+       FX2/TX chains */
+    wire           [CHAN_WIDTH:0] chan_underrun ;
+    wire           [CHAN_WIDTH:0] chan_txempty ;
    
-       usb_fifo_reader tx_usb_packet_reader (
-               .reset(reset),
-               .tx_clock(txclk),
-               .tx_data_bus(tx_data_bus),
-      .WR_chan_0(WR_chan_0),
-      .WR_chan_1(WR_chan_1),
-      .WR_cmd(WR_cmd),
-      .chan_0_done(chan_0_done),
-      .chan_1_done(chan_1_done),
-      .cmd_done(cmd_done),
-      .rdreq(tupf_rdreq),
-      .skip(tupf_skip),
-      .pkt_waiting(tupf_pkt_waiting),
-      .fifodata(tupf_fifodata)
+    /* Conections between tx_data_packet_fifo and
+       its reader + strobe generator */
+    wire                 [31:0] chan_fifodata [CHAN_WIDTH:0] ;
+    wire                        chan_pkt_waiting [CHAN_WIDTH:0] ;
+    wire                        chan_rdreq [CHAN_WIDTH:0] ;
+    wire                        chan_skip [CHAN_WIDTH:0] ;
+    wire           [CHAN_WIDTH:0] chan_have_space ;
+    wire                        chan_txstrobe [CHAN_WIDTH-1:0] ;
+
+       wire                            [14:0]  debug;
+    
+    /* Outputs to transmit chains */
+    wire                 [15:0] tx_i [CHAN_WIDTH-1:0] ;
+    wire                 [15:0] tx_q [CHAN_WIDTH-1:0] ;
+    
+       /* TODO: Figure out how to write this genericly */
+    assign have_space = chan_have_space[0] & chan_have_space[1];
+    assign tx_empty = chan_txempty[0] & chan_txempty[1] ;
+    assign tx_underrun = chan_underrun[0] | chan_underrun[1] ;
+    assign tx_i_0 = chan_txempty[0] ? 16'b0 : tx_i[0] ;
+    assign tx_q_0 = chan_txempty[0] ? 16'b0 : tx_q[0] ;
+    assign tx_i_1 = chan_txempty[1] ? 16'b0 : tx_i[1] ;
+    assign tx_q_1 = chan_txempty[1] ? 16'b0 : tx_q[1] ;
+        
+    /* Debug statement */
+    assign txstrobe_rate[0] = STROBE_RATE_0 ;
+    assign txstrobe_rate[1] = STROBE_RATE_1 ;
+       assign tx_q_2 = 16'b0 ;
+       assign tx_i_2 = 16'b0 ;
+       assign tx_q_3 = 16'b0 ;
+       assign tx_i_3 = 16'b0 ;
+       assign tx_i_3 = 16'b0 ;
+       
+       assign debugbus = {debug, txclk};
+
+       wire [31:0] usbdata_final;
+       wire            WR_final;
+
+       tx_packer tx_usb_packer
+       (
+                               .bus_reset                      (bus_reset),
+                               .usbclk                         (usbclk),
+                               .WR_fx2                         (WR),
+                               .usbdata                        (usbdata),
+                               .reset                          (reset),
+                               .txclk                          (txclk),
+                               .usbdata_final          (usbdata_final),
+                               .WR_final                       (WR_final)
+       );
+       
+       channel_demux channel_demuxer
+       (
+                               .usbdata_final          (usbdata_final),
+                               .WR_final                       (WR_final),
+                               .reset                          (reset),
+                               .txclk                          (txclk),
+                .WR_channel         (chan_WR),
+                .WR_done_channel    (chan_done),
+                .ram_data           (tx_data_bus)                              
        );
+       
+    generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+    begin : generate_channel_readers
+        channel_ram tx_data_packet_fifo 
+            (      .reset               (reset),
+                   .txclk               (txclk), 
+                   .datain              (tx_data_bus),
+                   .WR                  (chan_WR[i]),
+                   .WR_done             (chan_done[i]),
+                   .have_space          (chan_have_space[i]),
+                   .dataout             (chan_fifodata[i]),
+                   .packet_waiting      (chan_pkt_waiting[i]),
+                   .RD                  (chan_rdreq[i]),
+                   .RD_done             (chan_skip[i])
+             );
 
+        chan_fifo_reader tx_chan_reader 
+           (       .reset               (reset),
+                   .tx_clock            (txclk),
+                   .tx_strobe           (txstrobe),
+                   .adc_time            (adc_time),
+                   .samples_format      (4'b0),
+                   .tx_q                (tx_q[i]),
+                   .tx_i                (tx_i[i]),
+                   .underrun            (chan_underrun[i]),
+                   .skip               (chan_skip[i]),
+                   .rdreq               (chan_rdreq[i]),
+                   .fifodata            (chan_fifodata[i]),
+                   .pkt_waiting         (chan_pkt_waiting[i]),
+                   .tx_empty            (chan_txempty[i]),
+                   .rssi                               (rssi[i]),
+                   .threshhold                 (threshhold)
+            );     
+        
+    end
+    endgenerate
 
-   //Channel 0 block
-   wire [15:0] tdpf_fifodata_0;
-   wire tdpf_pkt_waiting_0;
-   wire tdpf_rdreq_0;
-   wire tdpf_skip_0;
-   wire tdpf_have_space_0;
-   wire txstrobe_chan_0;
 
-   data_packet_fifo tx_data_packet_fifo_0 
-     (  .reset(reset),
-        .clock(txclk), 
-        .ram_data_in(tx_data_bus),
-        .write_enable(WR_chan_0),
-        .ram_data_out(tdpf_fifodata_0),
-        .pkt_waiting(tdpf_pkt_waiting_0),
-        .read_enable(tdpf_rdreq_0),
-        .pkt_complete(chan_0_done), 
-        .skip_packet(tdpf_skip_0),
-        .have_space(tdpf_have_space_0)
-       );
-   
-   strobe_gen strobe_gen_0
-    (   .clock(txclk),
-        .reset(reset),
-        .enable(1'b1),
-        .rate(txstrobe_rate_0),
-        .strobe_in(txstrobe),
-        .strobe(txstrobe_chan_0) 
-       );
-   
-   chan_fifo_reader tx_chan_0_reader (
-      .reset(reset),
-      .tx_clock(txclk),
-      .tx_strobe(txstrobe),
-      //.tx_strobe(txstrobe_chan_0),
-      .adc_clock(time_counter),
-      .samples_format(4'b0),
-      .tx_q(tx_q_0),
-      .tx_i(tx_i_0),
-      .overrun(OR0),
-      .underrun(UR0),
-      .skip(tdpf_skip_0),
-      .rdreq(tdpf_rdreq_0),
-      .fifodata(tdpf_fifodata_0),
-      .pkt_waiting(tdpf_pkt_waiting_0)
-   );  
-   
-   
-   //Channel 1 block
-   wire [15:0] tdpf_fifodata_1;
-   wire tdpf_pkt_waiting_1;
-   wire tdpf_rdreq_1;
-   wire tdpf_skip_1;
-   wire tdpf_have_space_1;
-   wire txstrobe_chan_1;
-   
-   data_packet_fifo tx_data_packet_fifo_1 
-     (  .reset(reset),
-        .clock(txclk), 
-        .ram_data_in(tx_data_bus),
-        .write_enable(WR_chan_1),
-        .ram_data_out(tdpf_fifodata_1),
-        .pkt_waiting(tdpf_pkt_waiting_1),
-        .read_enable(tdpf_rdreq_1),
-        .pkt_complete(chan_1_done), 
-        .skip_packet(tdpf_skip_1),
-        .have_space(tdpf_have_space_1)
-       );
-   
-   strobe_gen strobe_gen_1
-    (   .clock(txclk),
-        .reset(reset),
-        .enable(1'b1),
-        .rate(txstrobe_rate_1),
-        .strobe_in(txstrobe),
-        .strobe(txstrobe_chan_1) 
-       );
-   
-   chan_fifo_reader tx_chan_1_reader (
-      .reset(reset),
-      .tx_clock(txclk),
-      .tx_strobe(txstrobe),
-      //.tx_strobe(txstrobe_chan_1),
-      .adc_clock(time_counter),
-      .samples_format(4'b0),
-      .tx_q(tx_q_1),
-      .tx_i(tx_i_1),
-      .overrun(OR1),
-      .underrun(UR1),
-      .skip(tdpf_skip_1),
-      .rdreq(tdpf_rdreq_1),
-      .fifodata(tdpf_fifodata_1),
-      .pkt_waiting(tdpf_pkt_waiting_1)
-   );
+       channel_ram tx_cmd_packet_fifo 
+            (      .reset               (reset),
+                   .txclk               (txclk), 
+                   .datain              (tx_data_bus),
+                   .WR                  (chan_WR[NUM_CHAN]),
+                   .WR_done             (chan_done[NUM_CHAN]),
+                   .have_space          (chan_have_space[NUM_CHAN]),
+                   .dataout             (chan_fifodata[NUM_CHAN]),
+                   .packet_waiting      (chan_pkt_waiting[NUM_CHAN]),
+                   .RD                  (chan_rdreq[NUM_CHAN]),
+                   .RD_done             (chan_skip[NUM_CHAN])
+             );
+
+
+       cmd_reader tx_cmd_reader
+               (               .reset                                  (reset),
+                               .txclk                                  (txclk),
+                               .adc_time                               (adc_time),
+                               .skip                                   (chan_skip[NUM_CHAN]),
+                               .rdreq                                  (chan_rdreq[NUM_CHAN]),
+                               .fifodata                               (chan_fifodata[NUM_CHAN]),
+                               .pkt_waiting                    (chan_pkt_waiting[NUM_CHAN]),
+                               .rx_databus                             (rx_databus),
+                               .rx_WR                                  (rx_WR),
+                               .rx_WR_done                             (rx_WR_done),
+                               .rx_WR_enabled                  (rx_WR_enabled),
+                               .reg_data_in                    (reg_data_in),
+                               .reg_data_out                   (reg_data_out),
+                               .reg_addr                               (reg_addr),
+                               .reg_io_enable                  (reg_io_enable),
+                               .debug                                  (debug)
+               );
+                               
+               
    
 endmodule // tx_buffer
 
diff --git a/usrp/fpga/inband_lib/tx_packer.v b/usrp/fpga/inband_lib/tx_packer.v
new file mode 100644 (file)
index 0000000..2f19b21
--- /dev/null
@@ -0,0 +1,119 @@
+module tx_packer
+   (     //FX2 Side
+                       input bus_reset, 
+                       input usbclk, 
+                       input WR_fx2, 
+                       input [15:0]usbdata,
+                       
+                       // TX Side
+                       input reset,
+                       input txclk,
+                       output reg [31:0] usbdata_final,
+                       output reg WR_final);
+
+       reg [8:0] write_count;
+
+       /* Fix FX2 bug */
+       always @(posedge usbclk)
+       begin
+       if(bus_reset)        // Use bus reset because this is on usbclk
+                       write_count <= #1 0;
+       else if(WR_fx2 & ~write_count[8])
+               write_count <= #1 write_count + 9'd1;
+       else
+               write_count <= #1 WR_fx2 ? write_count : 9'b0;
+       end
+       
+       reg WR_fx2_fixed;
+       reg [15:0]usbdata_fixed;
+       
+       always @(posedge usbclk) 
+       begin
+          WR_fx2_fixed <= WR_fx2 & ~write_count[8];
+          usbdata_fixed <= usbdata;
+       end
+
+       /* Used to convert 16 bits bus_data to the 32 bits wide fifo */
+    reg                             word_complete ;
+    reg     [15:0]                             usbdata_delayed ;
+    reg                             writing ;
+       wire    [31:0]                                  usbdata_packed ;    
+       wire                                                    WR_packed ;
+   
+    always @(posedge usbclk)
+    begin
+        if (bus_reset)
+          begin
+            word_complete <= 0 ;
+            writing <= 0 ;
+          end
+        else if (WR_fx2_fixed)
+          begin
+            writing <= 1 ;
+            if (word_complete)
+                word_complete <= 0 ;
+            else
+              begin
+                usbdata_delayed <= usbdata_fixed ;
+                word_complete <= 1 ;
+              end
+          end
+        else
+            writing <= 0 ;
+       end
+    
+       assign usbdata_packed = {usbdata_fixed, usbdata_delayed} ;
+    assign WR_packed = word_complete & writing ;
+
+       /* Make sure data are sync with usbclk */
+       reg [31:0]usbdata_usbclk;
+       reg WR_usbclk; 
+    
+    always @(posedge usbclk)
+    begin
+       if (WR_packed)
+               usbdata_usbclk <= usbdata_packed;
+        WR_usbclk <= WR_packed;
+    end
+
+       /* Cross clock boundaries */
+       reg [31:0] usbdata_tx ;
+       reg WR_tx;
+    reg WR_1;
+    reg WR_2;
+  
+       always @(posedge txclk) usbdata_tx <= usbdata_usbclk;
+
+    always @(posedge txclk) 
+       if (reset)
+               WR_1 <= 0;
+       else
+                       WR_1 <= WR_usbclk;
+
+    always @(posedge txclk) 
+       if (reset)
+                       WR_2 <= 0;
+       else
+               WR_2 <= WR_1;
+
+       always @(posedge txclk)
+       begin
+               if (reset)
+                       WR_tx <= 0;
+               else
+                  WR_tx <= WR_1 & ~WR_2;
+       end
+       
+       always @(posedge txclk)
+       begin
+          if (reset)
+             WR_final <= 0;
+          else
+          begin
+             WR_final <= WR_tx; 
+             if (WR_tx)
+                usbdata_final <= usbdata_tx;
+          end
+       end
+
+endmodule
index 170c70fd497ee304f73e2b03b60e6209099ba7b5..d002d90ff7c73275ce0f0f1c1fff538eae124ff1 100755 (executable)
-module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset,
-      rdreq, skip, done_chan, WR_chan, tx_data_bus);
+module usb_fifo_reader (
+      input usbclk,
+      input bus_reset, 
+      input RD,
+      output rdreq,
+      );
       
-    /* Module parameters */
-    parameter                       NUM_CHAN      =   2 ;
-    parameter                       WIDTH         =   32 ;
+    // FX2 Bug Fix
+    reg [8:0] read_count;
+    always @(negedge usbclk)
+        if(bus_reset)
+            read_count <= #1 9'd0;
+        else if(RD & ~read_count[8])
+            read_count <= #1 read_count + 9'd1;
+        else
+            read_count <= #1 RD ? read_count : 9'b0;
+            
+    assign rdreq = RD & ~read_count[8];
     
-    input   wire                    tx_clock ;
-    input   wire                    reset ;
-    input   wire       [WIDTH-1:0]  fifodata ;
-    input   wire                    pkt_waiting ;
-    output  reg                     rdreq ;
-    output  reg                     skip ;
-    output  reg        [NUM_CHAN:0] done_chan ;
-    output  reg        [NUM_CHAN:0] WR_chan ;
-    output  reg        [WIDTH-1:0]  tx_data_bus ;
-     
-   
-   
-    /* States definition */
-    `define IDLE                      3'd0
-    `define WAIT                      3'd1
-    `define READ_HEADER               3'd2
-    `define FORWARD_DATA              3'd3
-    `define SKIP_REST                 3'd4
-   
-    /* Channel Ids */
-    `define TXCHAN0                   5'h0
-    `define TXCHAN1                   5'h1
-    `define TXCMD                     5'h1F
-   
-    /* Local registers */
-    reg                      [2:0]    reader_state ;
-    reg                      [2:0]    reader_next_state ;
-    reg                      [4:0]    channel ;
-    reg                      [8:0]    pkt_length ;
-    reg                      [8:0]    read_length ;
     
-    /* State Machine */
-    always @(posedge tx_clock)
-    begin
-        if (reset) 
-                 begin
-                     reader_state <= `IDLE ;
-            reader_next_state <= `IDLE ;
-            rdreq <= 0 ;
-            skip <= 0 ;
-            WR_chan <= {NUM_CHAN+1{1'b0}} ;
-            done_chan <= {NUM_CHAN+1{1'b0}} ;
-          end
-        else 
-                 begin
-            reader_state = reader_next_state ;
-            
-            case(reader_state)
-            `IDLE: 
-                               begin
-                                   reader_next_state <= pkt_waiting ? `WAIT : `IDLE ;
-                rdreq <= pkt_waiting ;
-            end
-     
-            /* Wait for the fifo's data to show up */
-            `WAIT:
-            begin
-                              reader_next_state <= `READ_HEADER ;
-            end
-               
-            `READ_HEADER: 
-                          begin
-                reader_next_state <= `FORWARD_DATA ;
-                  
-                /* Read header fields */
-                channel <= (fifodata & 32'h1F0000) ;
-                pkt_length <= (fifodata & 16'h1FF) + 4 ;
-                read_length <= 9'd0 ;
-                  
-                /* Forward data */
-                case (channel)
-                    `TXCHAN0: WR_chan[0] <= 1 ;
-                    `TXCHAN1: WR_chan[1] <= 1 ;
-                    `TXCMD:   WR_chan[2] <= 1 ;
-                    default:  WR_chan <= 1 ;
-                endcase
-                tx_data_bus <= fifodata ;
-            end
-               
-            `FORWARD_DATA:
-                          begin
-                read_length <= read_length + 4 ;
-                  
-                // If end of payload...
-                if (read_length == pkt_length)
-                                   begin
-                    reader_next_state <= `SKIP_REST ;
-                    /* If the packet is 512 bytes, don't skip */
-                    skip <= pkt_length < 506 ;
-                     
-                    /* Data pushing done */
-                    WR_chan <= {NUM_CHAN+1{1'b0}} ;
-                    
-                    /* Notify next block */
-                    case (channel)
-                       `TXCHAN0: done_chan[0] <= 1 ;
-                       `TXCHAN1: done_chan[1] <= 1 ;
-                       `TXCMD:   done_chan[2] <= 1 ;
-                       default:  done_chan[0] <= 1 ;
-                    endcase
-                end
-                else if (read_length == pkt_length - 4)
-                    rdreq <= 0 ;
-                    
-                /* Forward data */
-                tx_data_bus <= fifodata ;
-            end
-               
-            `SKIP_REST: 
-                          begin
-                              reader_next_state <= pkt_waiting ? `READ_HEADER : `IDLE ;
-                done_chan <= {NUM_CHAN+1{1'b0}} ;
-                rdreq <= pkt_waiting ;
-                skip <= 0 ;
-            end
-                
-            default: 
-                          begin
-                reader_state <= `IDLE;
-                reader_next_state <= `IDLE;
-            end
-            endcase
-        end
-    end  
 endmodule
        
    
diff --git a/usrp/fpga/inband_lib/usb_fifo_writer.v b/usrp/fpga/inband_lib/usb_fifo_writer.v
new file mode 100755 (executable)
index 0000000..abe1dd5
--- /dev/null
@@ -0,0 +1,183 @@
+
+module usb_fifo_writer
+   #(parameter BUS_WIDTH = 16,
+     parameter NUM_CHAN = 2,
+     parameter FIFO_WIDTH = 32)
+   (     //FX2 Side
+                       input bus_reset, 
+                       input usbclk, 
+                       input WR_fx2, 
+                       input [15:0]usbdata,
+                       
+                       // TX Side
+                       input reset,
+                       input txclk,
+                       output reg [NUM_CHAN:0] WR_channel,
+                       output reg [FIFO_WIDTH-1:0] ram_data,
+                       output reg [NUM_CHAN:0] WR_done_channel );
+   
+
+       reg [8:0] write_count;
+
+       /* Fix FX2 bug */
+       always @(posedge usbclk)
+       if(bus_reset)        // Use bus reset because this is on usbclk
+                       write_count <= #1 0;
+       else if(WR_fx2 & ~write_count[8])
+               write_count <= #1 write_count + 9'd1;
+       else
+               write_count <= #1 WR_fx2 ? write_count : 9'b0;
+
+       reg WR_fx2_fixed;
+       reg [15:0]usbdata_fixed;
+       
+       always @(posedge usbclk) 
+       begin
+          WR_fx2_fixed <= WR_fx2 & ~write_count[8];
+          usbdata_fixed <= usbdata;
+       end
+
+       /* Used to convert 16 bits bus_data to the 32 bits wide fifo */
+    reg                             word_complete ;
+    reg     [BUS_WIDTH-1:0]         usbdata_delayed ;
+    reg                             writing ;
+       wire    [FIFO_WIDTH-1:0]                usbdata_packed ;    
+       wire                                                    WR_packed ;
+   
+    always @(posedge usbclk)
+    begin
+        if (bus_reset)
+          begin
+            word_complete <= 0 ;
+            writing <= 0 ;
+          end
+        else if (WR_fx2_fixed)
+          begin
+            writing <= 1 ;
+            if (word_complete)
+                word_complete <= 0 ;
+            else
+              begin
+                usbdata_delayed <= usbdata_fixed ;
+                word_complete <= 1 ;
+              end
+          end
+        else
+            writing <= 0 ;
+       end
+    
+       assign usbdata_packed = {usbdata_fixed, usbdata_delayed} ;
+    assign WR_packed = word_complete & writing ;
+
+       /* Make sure data are sync with usbclk */
+       reg [31:0]usbdata_usbclk;
+       reg WR_usbclk; 
+    
+    always @(posedge usbclk)
+    begin
+       if (WR_packed)
+               usbdata_usbclk <= usbdata_packed;
+        WR_usbclk <= WR_packed;
+    end
+
+       /* Cross clock boundaries */
+       reg [FIFO_WIDTH-1:0] usbdata_tx ;
+       reg WR_tx;
+    reg WR_1;
+    reg WR_2;
+       reg [31:0] usbdata_final;
+       reg WR_final;
+   
+       always @(posedge txclk) usbdata_tx <= usbdata_usbclk;
+
+    always @(posedge txclk) 
+       if (reset)
+               WR_1 <= 0;
+       else
+                       WR_1 <= WR_usbclk;
+
+    always @(posedge txclk) 
+       if (reset)
+                       WR_2 <= 0;
+       else
+               WR_2 <= WR_1;
+
+       always @(posedge txclk)
+       begin
+               if (reset)
+                       WR_tx <= 0;
+               else
+                  WR_tx <= WR_1 & ~WR_2;
+       end
+       
+       always @(posedge txclk)
+       begin
+          if (reset)
+             WR_final <= 0;
+          else
+          begin
+             WR_final <= WR_tx; 
+             if (WR_tx)
+                usbdata_final <= usbdata_tx;
+          end
+       end
+            
+       /* Parse header and forward to ram */
+       reg [3:0]reader_state;
+       reg [4:0]channel ;
+       reg [9:0]read_length ;
+       
+       parameter IDLE = 4'd0;
+       parameter HEADER = 4'd1;
+       parameter WAIT = 4'd2;
+       parameter FORWARD = 4'd3;
+       
+       `define CHANNEL 20:16
+       `define PKT_SIZE 512
+       
+       always @(posedge txclk)
+       begin
+           if (reset)
+             begin
+              reader_state <= 0;
+              WR_channel <= 0;
+              WR_done_channel <= 0;
+             end
+             else
+               case (reader_state)
+               IDLE: begin
+                   if (WR_final)
+                       reader_state <= HEADER; 
+                   end
+              
+            // Store channel and forware header
+               HEADER: begin
+                   channel <= (usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL]) ;
+                   WR_channel[(usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL])] <= 1;
+                               //channel <= usbdata_final[`CHANNEL] ;
+                   //WR_channel[usbdata_final[`CHANNEL]] <= 1;
+                   ram_data <= usbdata_final;
+                               read_length <= 10'd4 ;
+                               
+                reader_state <= WAIT;
+               end
+              
+               WAIT: begin
+                  WR_channel[channel] <= 0;
+       
+                          if (read_length == `PKT_SIZE)
+                      reader_state <= IDLE;
+                  else if (WR_final)
+                      reader_state <= FORWARD;
+               end
+              
+               FORWARD: begin
+                  WR_channel[channel] <= 1;
+                  ram_data <= usbdata_final;
+                  read_length <= read_length + 10'd4;
+                  
+                  reader_state <= WAIT;
+               end
+              endcase
+       end
+endmodule  
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/usb_packet_fifo2.v b/usrp/fpga/inband_lib/usb_packet_fifo2.v
deleted file mode 100755 (executable)
index d815e4e..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-`default_nettype none
-
-module usb_packet_fifo2(reset, usb_clock, fpga_clock, write_enable, write_data, 
-        read_enable, skip_packet, read_data, have_space, pkt_waiting, tx_empty) ;
-    
-    /* Module parameters */
-    parameter                       LOG2_N          =   2 ;
-    parameter                       BUS_WIDTH       =   16 ;
-    parameter                       FIFO_WIDTH      =   32 ;
-
-    input   wire                    reset;
-    input   wire                    usb_clock ;
-    input   wire                    fpga_clock ;
-    input   wire                    write_enable ;
-    input   wire    [BUS_WIDTH-1:0] write_data ;
-    input   wire                    read_enable ;
-    input   wire                    skip_packet ;
-    output  wire   [FIFO_WIDTH-1:0] read_data ;
-    output  wire                    have_space ;
-    output  wire                    pkt_waiting ;
-    output  wire                    tx_empty;
-
-    
-    /* Variable for generate statement */
-    genvar i ;
-    
-    /* Local wires for FIFO connections */
-    wire                      [2**LOG2_N-1:0]     fifo_resets ;
-    reg                       [2**LOG2_N-1:0]     fifo_we ;
-    wire                      [2**LOG2_N-1:0]     fifo_re ;
-    reg                       [FIFO_WIDTH-1:0]    fifo_wdata[2**LOG2_N-1:0] ;
-    wire                      [FIFO_WIDTH-1:0]    fifo_rdata[2**LOG2_N-1:0] ;
-    wire                      [2**LOG2_N-1:0]     fifo_rempty ;
-    wire                      [2**LOG2_N-1:0]     fifo_rfull ;
-    wire                      [2**LOG2_N-1:0]     fifo_wempty ;
-    wire                      [2**LOG2_N-1:0]     fifo_wfull ;
-    
-    /* FIFO Select for read and write ports */
-    reg     [LOG2_N-1:0]            fifo_rselect ;
-    reg     [LOG2_N-1:0]            fifo_wselect ;
-    
-    /* Used to convert 16 bits usbdata to the 32 bits wide fifo */
-    reg                             word_complete ;
-    reg     [BUS_WIDTH-1:0]         write_data_delayed ;
-    
-    /* Assign have_space to empty flag of currently selected write FIFO */
-    assign have_space = fifo_wempty[fifo_wselect] ;
-    
-    /* Assign pkt_waiting to full flag of currently selected read FIFO */
-    assign pkt_waiting = fifo_rfull[fifo_rselect] ;
-    
-    /* Assign the read_data to the output of the currently selected FIFO */
-    assign read_data = fifo_rdata[fifo_rselect] ;
-    
-    /* Figure out if we're all empty */
-    assign tx_empty = !(~fifo_rempty) ;
-    
-    /* Increment fifo_rselect here */
-    always @(posedge fpga_clock)
-    begin
-        if (reset)
-            fifo_rselect <= {2**LOG2_N{1'b0}} ;
-        
-        if (fifo_rempty[fifo_rselect])
-            fifo_rselect <= fifo_rselect + 1 ;
-            
-        if (skip_packet)
-            fifo_rselect <= fifo_rselect + 1 ;
-    end
-    
-    /* Increment fifo_wselect and pack data into 32 bits block  */
-    always @(posedge usb_clock, reset)
-    begin
-        if (reset)
-          begin
-            fifo_wselect <= {2**LOG2_N{1'b0}} ;
-            word_complete <= 0;
-          end
-            
-        if (fifo_wfull[fifo_wselect])
-            fifo_wselect <= fifo_wselect + 1 ;
-            
-        if (write_enable)
-          begin
-            word_complete <= ~word_complete ;
-            
-            if (word_complete)
-                fifo_wdata[fifo_wselect] <= {write_data_delayed, write_data} ;
-            else
-                write_data_delayed <= write_data ;
-              
-            /* Avoid to continue to write in the previous fifo when we have 
-               just swichted to the next one */ 
-            fifo_we[fifo_wselect-1] <= 0 ;
-            
-            fifo_we[fifo_wselect] <= write_enable & word_complete ;
-          end
-    end
-    
-    /* Generate all the single packet FIFOs */
-    generate
-        for( i = 0 ; i < 2**LOG2_N ; i = i + 1 )
-        begin : generate_single_packet_fifos
-            assign fifo_re[i] = (fifo_rselect == i) ? read_enable : 1'b0 ;
-            assign fifo_resets[i] = (fifo_rselect == i) ? skip_packet : 1'b0 ;
-            fifo_512 single_packet_fifo(.wrclk  ( usb_clock      ),
-                                        .rdclk  ( fpga_clock     ),
-                                        .aclr   ( fifo_resets[i] ), 
-                                        .wrreq  ( fifo_we[i]     ),
-                                        .data   ( fifo_wdata[i]  ),
-                                        .rdreq  ( fifo_re[i]     ),
-                                        .q      ( fifo_rdata[i]  ),
-                                        .rdfull ( fifo_rfull[i]  ),
-                                        .rdempty( fifo_rempty[i] ),
-                                        .wrfull ( fifo_wfull[i]  ),
-                                        .wrempty( fifo_wempty[i] ) ) ;
-        end
-    endgenerate
-endmodule 
\ No newline at end of file
diff --git a/usrp/fpga/megacells/fifo_2k_1clk.v b/usrp/fpga/megacells/fifo_2k_1clk.v
new file mode 100755 (executable)
index 0000000..095615b
--- /dev/null
@@ -0,0 +1,167 @@
+// megafunction wizard: %LPM_FIFO+%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: scfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_2k_1clk.v\r
+// Megafunction Name(s):\r
+//                     scfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+\r
+// synopsys translate_off\r
+`timescale 1 ps / 1 ps\r
+// synopsys translate_on\r
+module fifo_2k_1clk (\r
+       aclr,\r
+       clock,\r
+       data,\r
+       rdreq,\r
+       wrreq,\r
+       empty,\r
+       full,\r
+       q,\r
+       usedw);\r
+\r
+       input     aclr;\r
+       input     clock;\r
+       input   [15:0]  data;\r
+       input     rdreq;\r
+       input     wrreq;\r
+       output    empty;\r
+       output    full;\r
+       output  [15:0]  q;\r
+       output  [9:0]  usedw;\r
+\r
+       wire [9:0] sub_wire0;\r
+       wire  sub_wire1;\r
+       wire [15:0] sub_wire2;\r
+       wire  sub_wire3;\r
+       wire [9:0] usedw = sub_wire0[9:0];\r
+       wire  empty = sub_wire1;\r
+       wire [15:0] q = sub_wire2[15:0];\r
+       wire  full = sub_wire3;\r
+\r
+       scfifo  scfifo_component (\r
+                               .rdreq (rdreq),\r
+                               .aclr (aclr),\r
+                               .clock (clock),\r
+                               .wrreq (wrreq),\r
+                               .data (data),\r
+                               .usedw (sub_wire0),\r
+                               .empty (sub_wire1),\r
+                               .q (sub_wire2),\r
+                               .full (sub_wire3)\r
+                               // synopsys translate_off\r
+                               ,\r
+                               .almost_empty (),\r
+                               .sclr (),\r
+                               .almost_full ()\r
+                               // synopsys translate_on\r
+                               );\r
+       defparam\r
+               scfifo_component.add_ram_output_register = "OFF",\r
+               scfifo_component.intended_device_family = "Cyclone",\r
+               scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",\r
+               scfifo_component.lpm_numwords = 1024,\r
+               scfifo_component.lpm_showahead = "OFF",\r
+               scfifo_component.lpm_type = "scfifo",\r
+               scfifo_component.lpm_width = 16,\r
+               scfifo_component.lpm_widthu = 10,\r
+               scfifo_component.overflow_checking = "ON",\r
+               scfifo_component.underflow_checking = "ON",\r
+               scfifo_component.use_eab = "ON";\r
+\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "0"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "1024"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "16"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr\r
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock\r
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]\r
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty\r
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full\r
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: usedw 0 0 10 0 OUTPUT NODEFVAL usedw[9..0]\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0\r
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0\r
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0\r
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0\r
+// Retrieval info: CONNECT: usedw 0 0 10 0 @usedw 0 0 10 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_waveforms.html FALSE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_2kx16.bsf b/usrp/fpga/megacells/fifo_2kx16.bsf
new file mode 100755 (executable)
index 0000000..1067991
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+WARNING: Do NOT edit the input and output ports in this file in a text\r
+editor if you plan to continue editing the block that represents it in\r
+the Block Editor! File corruption is VERY likely to occur.\r
+*/\r
+/*\r
+Copyright (C) 1991-2006 Altera Corporation\r
+Your use of Altera Corporation's design tools, logic functions \r
+and other software and tools, and its AMPP partner logic \r
+functions, and any output files any of the foregoing \r
+(including device programming or simulation files), and any \r
+associated documentation or information are expressly subject \r
+to the terms and conditions of the Altera Program License \r
+Subscription Agreement, Altera MegaCore Function License \r
+Agreement, or other applicable license agreement, including, \r
+without limitation, that your use is for the sole purpose of \r
+programming logic devices manufactured by Altera and sold by \r
+Altera or its authorized distributors.  Please refer to the \r
+applicable agreement for further details.\r
+*/\r
+(header "symbol" (version "1.1"))\r
+(symbol\r
+       (rect 0 0 160 144)\r
+       (text "fifo_2kx16" (rect 51 1 119 17)(font "Arial" (font_size 10)))\r
+       (text "inst" (rect 8 128 25 140)(font "Arial" ))\r
+       (port\r
+               (pt 0 32)\r
+               (input)\r
+               (text "data[15..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))\r
+               (text "data[15..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))\r
+               (line (pt 0 32)(pt 16 32)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 0 56)\r
+               (input)\r
+               (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))\r
+               (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))\r
+               (line (pt 0 56)(pt 16 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 72)\r
+               (input)\r
+               (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))\r
+               (text "rdreq" (rect 20 66 44 79)(font "Arial" (font_size 8)))\r
+               (line (pt 0 72)(pt 16 72)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 96)\r
+               (input)\r
+               (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))\r
+               (text "clock" (rect 26 90 49 103)(font "Arial" (font_size 8)))\r
+               (line (pt 0 96)(pt 16 96)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 120)\r
+               (input)\r
+               (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))\r
+               (text "aclr" (rect 20 114 37 127)(font "Arial" (font_size 8)))\r
+               (line (pt 0 120)(pt 16 120)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 32)\r
+               (output)\r
+               (text "q[15..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))\r
+               (text "q[15..0]" (rect 105 26 141 39)(font "Arial" (font_size 8)))\r
+               (line (pt 160 32)(pt 144 32)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 160 56)\r
+               (output)\r
+               (text "full" (rect 0 0 16 14)(font "Arial" (font_size 8)))\r
+               (text "full" (rect 127 50 142 63)(font "Arial" (font_size 8)))\r
+               (line (pt 160 56)(pt 144 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 72)\r
+               (output)\r
+               (text "empty" (rect 0 0 34 14)(font "Arial" (font_size 8)))\r
+               (text "empty" (rect 112 66 141 79)(font "Arial" (font_size 8)))\r
+               (line (pt 160 72)(pt 144 72)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 88)\r
+               (output)\r
+               (text "usedw[10..0]" (rect 0 0 75 14)(font "Arial" (font_size 8)))\r
+               (text "usedw[10..0]" (rect 77 82 136 95)(font "Arial" (font_size 8)))\r
+               (line (pt 160 88)(pt 144 88)(line_width 3))\r
+       )\r
+       (drawing\r
+               (text "16 bits x 2048 words" (rect 58 116 144 128)(font "Arial" ))\r
+               (line (pt 16 16)(pt 144 16)(line_width 1))\r
+               (line (pt 144 16)(pt 144 128)(line_width 1))\r
+               (line (pt 144 128)(pt 16 128)(line_width 1))\r
+               (line (pt 16 128)(pt 16 16)(line_width 1))\r
+               (line (pt 16 108)(pt 144 108)(line_width 1))\r
+               (line (pt 16 90)(pt 22 96)(line_width 1))\r
+               (line (pt 22 96)(pt 16 102)(line_width 1))\r
+       )\r
+)\r
diff --git a/usrp/fpga/megacells/fifo_2kx16.cmp b/usrp/fpga/megacells/fifo_2kx16.cmp
new file mode 100755 (executable)
index 0000000..96c34d8
--- /dev/null
@@ -0,0 +1,29 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+component fifo_2kx16\r
+       PORT\r
+       (\r
+               aclr            : IN STD_LOGIC ;\r
+               clock           : IN STD_LOGIC ;\r
+               data            : IN STD_LOGIC_VECTOR (15 DOWNTO 0);\r
+               rdreq           : IN STD_LOGIC ;\r
+               wrreq           : IN STD_LOGIC ;\r
+               empty           : OUT STD_LOGIC ;\r
+               full            : OUT STD_LOGIC ;\r
+               q               : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);\r
+               usedw           : OUT STD_LOGIC_VECTOR (10 DOWNTO 0)\r
+       );\r
+end component;\r
diff --git a/usrp/fpga/megacells/fifo_2kx16.inc b/usrp/fpga/megacells/fifo_2kx16.inc
new file mode 100755 (executable)
index 0000000..3d72c66
--- /dev/null
@@ -0,0 +1,30 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+FUNCTION fifo_2kx16 \r
+(\r
+       aclr,\r
+       clock,\r
+       data[15..0],\r
+       rdreq,\r
+       wrreq\r
+)\r
+\r
+RETURNS (\r
+       empty,\r
+       full,\r
+       q[15..0],\r
+       usedw[10..0]\r
+);\r
diff --git a/usrp/fpga/megacells/fifo_2kx16.v b/usrp/fpga/megacells/fifo_2kx16.v
new file mode 100755 (executable)
index 0000000..eb22976
--- /dev/null
@@ -0,0 +1,167 @@
+// megafunction wizard: %FIFO%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: scfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_2kx16.v\r
+// Megafunction Name(s):\r
+//                     scfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+\r
+// synopsys translate_off\r
+`timescale 1 ps / 1 ps\r
+// synopsys translate_on\r
+module fifo_2kx16 (\r
+       aclr,\r
+       clock,\r
+       data,\r
+       rdreq,\r
+       wrreq,\r
+       empty,\r
+       full,\r
+       q,\r
+       usedw);\r
+\r
+       input     aclr;\r
+       input     clock;\r
+       input   [15:0]  data;\r
+       input     rdreq;\r
+       input     wrreq;\r
+       output    empty;\r
+       output    full;\r
+       output  [15:0]  q;\r
+       output  [10:0]  usedw;\r
+\r
+       wire [10:0] sub_wire0;\r
+       wire  sub_wire1;\r
+       wire [15:0] sub_wire2;\r
+       wire  sub_wire3;\r
+       wire [10:0] usedw = sub_wire0[10:0];\r
+       wire  empty = sub_wire1;\r
+       wire [15:0] q = sub_wire2[15:0];\r
+       wire  full = sub_wire3;\r
+\r
+       scfifo  scfifo_component (\r
+                               .rdreq (rdreq),\r
+                               .aclr (aclr),\r
+                               .clock (clock),\r
+                               .wrreq (wrreq),\r
+                               .data (data),\r
+                               .usedw (sub_wire0),\r
+                               .empty (sub_wire1),\r
+                               .q (sub_wire2),\r
+                               .full (sub_wire3)\r
+                               // synopsys translate_off\r
+                               ,\r
+                               .almost_empty (),\r
+                               .sclr (),\r
+                               .almost_full ()\r
+                               // synopsys translate_on\r
+                               );\r
+       defparam\r
+               scfifo_component.add_ram_output_register = "OFF",\r
+               scfifo_component.intended_device_family = "Cyclone",\r
+               scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",\r
+               scfifo_component.lpm_numwords = 2048,\r
+               scfifo_component.lpm_showahead = "OFF",\r
+               scfifo_component.lpm_type = "scfifo",\r
+               scfifo_component.lpm_width = 16,\r
+               scfifo_component.lpm_widthu = 11,\r
+               scfifo_component.overflow_checking = "ON",\r
+               scfifo_component.underflow_checking = "ON",\r
+               scfifo_component.use_eab = "ON";\r
+\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "0"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "2048"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "16"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr\r
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock\r
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]\r
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty\r
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full\r
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: usedw 0 0 11 0 OUTPUT NODEFVAL usedw[10..0]\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0\r
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0\r
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0\r
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0\r
+// Retrieval info: CONNECT: usedw 0 0 11 0 @usedw 0 0 11 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_2kx16_bb.v b/usrp/fpga/megacells/fifo_2kx16_bb.v
new file mode 100755 (executable)
index 0000000..507bac0
--- /dev/null
@@ -0,0 +1,122 @@
+// megafunction wizard: %FIFO%VBB%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: scfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_2kx16.v\r
+// Megafunction Name(s):\r
+//                     scfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+module fifo_2kx16 (\r
+       aclr,\r
+       clock,\r
+       data,\r
+       rdreq,\r
+       wrreq,\r
+       empty,\r
+       full,\r
+       q,\r
+       usedw);\r
+\r
+       input     aclr;\r
+       input     clock;\r
+       input   [15:0]  data;\r
+       input     rdreq;\r
+       input     wrreq;\r
+       output    empty;\r
+       output    full;\r
+       output  [15:0]  q;\r
+       output  [10:0]  usedw;\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "0"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "2048"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "16"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr\r
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock\r
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]\r
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty\r
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full\r
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: usedw 0 0 11 0 OUTPUT NODEFVAL usedw[10..0]\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0\r
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0\r
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0\r
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0\r
+// Retrieval info: CONNECT: usedw 0 0 11 0 @usedw 0 0 11 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_2kx16_inst.v b/usrp/fpga/megacells/fifo_2kx16_inst.v
new file mode 100755 (executable)
index 0000000..6185c6f
--- /dev/null
@@ -0,0 +1,11 @@
+fifo_2kx16     fifo_2kx16_inst (\r
+       .aclr ( aclr_sig ),\r
+       .clock ( clock_sig ),\r
+       .data ( data_sig ),\r
+       .rdreq ( rdreq_sig ),\r
+       .wrreq ( wrreq_sig ),\r
+       .empty ( empty_sig ),\r
+       .full ( full_sig ),\r
+       .q ( q_sig ),\r
+       .usedw ( usedw_sig )\r
+       );\r
diff --git a/usrp/fpga/megacells/fifo_4kx16.bsf b/usrp/fpga/megacells/fifo_4kx16.bsf
new file mode 100755 (executable)
index 0000000..4d988c5
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+WARNING: Do NOT edit the input and output ports in this file in a text\r
+editor if you plan to continue editing the block that represents it in\r
+the Block Editor! File corruption is VERY likely to occur.\r
+*/\r
+/*\r
+Copyright (C) 1991-2006 Altera Corporation\r
+Your use of Altera Corporation's design tools, logic functions \r
+and other software and tools, and its AMPP partner logic \r
+functions, and any output files any of the foregoing \r
+(including device programming or simulation files), and any \r
+associated documentation or information are expressly subject \r
+to the terms and conditions of the Altera Program License \r
+Subscription Agreement, Altera MegaCore Function License \r
+Agreement, or other applicable license agreement, including, \r
+without limitation, that your use is for the sole purpose of \r
+programming logic devices manufactured by Altera and sold by \r
+Altera or its authorized distributors.  Please refer to the \r
+applicable agreement for further details.\r
+*/\r
+(header "symbol" (version "1.1"))\r
+(symbol\r
+       (rect 0 0 160 144)\r
+       (text "fifo_4kx16" (rect 51 1 119 17)(font "Arial" (font_size 10)))\r
+       (text "inst" (rect 8 128 25 140)(font "Arial" ))\r
+       (port\r
+               (pt 0 32)\r
+               (input)\r
+               (text "data[15..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))\r
+               (text "data[15..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))\r
+               (line (pt 0 32)(pt 16 32)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 0 56)\r
+               (input)\r
+               (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))\r
+               (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))\r
+               (line (pt 0 56)(pt 16 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 72)\r
+               (input)\r
+               (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))\r
+               (text "rdreq" (rect 20 66 44 79)(font "Arial" (font_size 8)))\r
+               (line (pt 0 72)(pt 16 72)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 96)\r
+               (input)\r
+               (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))\r
+               (text "clock" (rect 26 90 49 103)(font "Arial" (font_size 8)))\r
+               (line (pt 0 96)(pt 16 96)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 120)\r
+               (input)\r
+               (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))\r
+               (text "aclr" (rect 20 114 37 127)(font "Arial" (font_size 8)))\r
+               (line (pt 0 120)(pt 16 120)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 32)\r
+               (output)\r
+               (text "q[15..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))\r
+               (text "q[15..0]" (rect 105 26 141 39)(font "Arial" (font_size 8)))\r
+               (line (pt 160 32)(pt 144 32)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 160 56)\r
+               (output)\r
+               (text "full" (rect 0 0 16 14)(font "Arial" (font_size 8)))\r
+               (text "full" (rect 127 50 142 63)(font "Arial" (font_size 8)))\r
+               (line (pt 160 56)(pt 144 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 72)\r
+               (output)\r
+               (text "empty" (rect 0 0 34 14)(font "Arial" (font_size 8)))\r
+               (text "empty" (rect 112 66 141 79)(font "Arial" (font_size 8)))\r
+               (line (pt 160 72)(pt 144 72)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 88)\r
+               (output)\r
+               (text "usedw[11..0]" (rect 0 0 75 14)(font "Arial" (font_size 8)))\r
+               (text "usedw[11..0]" (rect 77 82 136 95)(font "Arial" (font_size 8)))\r
+               (line (pt 160 88)(pt 144 88)(line_width 3))\r
+       )\r
+       (drawing\r
+               (text "16 bits x 4096 words" (rect 58 116 144 128)(font "Arial" ))\r
+               (line (pt 16 16)(pt 144 16)(line_width 1))\r
+               (line (pt 144 16)(pt 144 128)(line_width 1))\r
+               (line (pt 144 128)(pt 16 128)(line_width 1))\r
+               (line (pt 16 128)(pt 16 16)(line_width 1))\r
+               (line (pt 16 108)(pt 144 108)(line_width 1))\r
+               (line (pt 16 90)(pt 22 96)(line_width 1))\r
+               (line (pt 22 96)(pt 16 102)(line_width 1))\r
+       )\r
+)\r
diff --git a/usrp/fpga/megacells/fifo_4kx16.cmp b/usrp/fpga/megacells/fifo_4kx16.cmp
new file mode 100755 (executable)
index 0000000..7bc6941
--- /dev/null
@@ -0,0 +1,29 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+component fifo_4kx16\r
+       PORT\r
+       (\r
+               aclr            : IN STD_LOGIC ;\r
+               clock           : IN STD_LOGIC ;\r
+               data            : IN STD_LOGIC_VECTOR (15 DOWNTO 0);\r
+               rdreq           : IN STD_LOGIC ;\r
+               wrreq           : IN STD_LOGIC ;\r
+               empty           : OUT STD_LOGIC ;\r
+               full            : OUT STD_LOGIC ;\r
+               q               : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);\r
+               usedw           : OUT STD_LOGIC_VECTOR (11 DOWNTO 0)\r
+       );\r
+end component;\r
diff --git a/usrp/fpga/megacells/fifo_4kx16.inc b/usrp/fpga/megacells/fifo_4kx16.inc
new file mode 100755 (executable)
index 0000000..db5d4f2
--- /dev/null
@@ -0,0 +1,30 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+FUNCTION fifo_4kx16 \r
+(\r
+       aclr,\r
+       clock,\r
+       data[15..0],\r
+       rdreq,\r
+       wrreq\r
+)\r
+\r
+RETURNS (\r
+       empty,\r
+       full,\r
+       q[15..0],\r
+       usedw[11..0]\r
+);\r
diff --git a/usrp/fpga/megacells/fifo_4kx16.v b/usrp/fpga/megacells/fifo_4kx16.v
new file mode 100755 (executable)
index 0000000..c5ecfba
--- /dev/null
@@ -0,0 +1,167 @@
+// megafunction wizard: %FIFO%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: scfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_4kx16.v\r
+// Megafunction Name(s):\r
+//                     scfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+\r
+// synopsys translate_off\r
+`timescale 1 ps / 1 ps\r
+// synopsys translate_on\r
+module fifo_4kx16 (\r
+       aclr,\r
+       clock,\r
+       data,\r
+       rdreq,\r
+       wrreq,\r
+       empty,\r
+       full,\r
+       q,\r
+       usedw);\r
+\r
+       input     aclr;\r
+       input     clock;\r
+       input   [15:0]  data;\r
+       input     rdreq;\r
+       input     wrreq;\r
+       output    empty;\r
+       output    full;\r
+       output  [15:0]  q;\r
+       output  [11:0]  usedw;\r
+\r
+       wire [11:0] sub_wire0;\r
+       wire  sub_wire1;\r
+       wire [15:0] sub_wire2;\r
+       wire  sub_wire3;\r
+       wire [11:0] usedw = sub_wire0[11:0];\r
+       wire  empty = sub_wire1;\r
+       wire [15:0] q = sub_wire2[15:0];\r
+       wire  full = sub_wire3;\r
+\r
+       scfifo  scfifo_component (\r
+                               .rdreq (rdreq),\r
+                               .aclr (aclr),\r
+                               .clock (clock),\r
+                               .wrreq (wrreq),\r
+                               .data (data),\r
+                               .usedw (sub_wire0),\r
+                               .empty (sub_wire1),\r
+                               .q (sub_wire2),\r
+                               .full (sub_wire3)\r
+                               // synopsys translate_off\r
+                               ,\r
+                               .almost_empty (),\r
+                               .sclr (),\r
+                               .almost_full ()\r
+                               // synopsys translate_on\r
+                               );\r
+       defparam\r
+               scfifo_component.add_ram_output_register = "OFF",\r
+               scfifo_component.intended_device_family = "Cyclone",\r
+               scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",\r
+               scfifo_component.lpm_numwords = 4096,\r
+               scfifo_component.lpm_showahead = "OFF",\r
+               scfifo_component.lpm_type = "scfifo",\r
+               scfifo_component.lpm_width = 16,\r
+               scfifo_component.lpm_widthu = 12,\r
+               scfifo_component.overflow_checking = "ON",\r
+               scfifo_component.underflow_checking = "ON",\r
+               scfifo_component.use_eab = "ON";\r
+\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "0"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "4096"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "16"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr\r
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock\r
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]\r
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty\r
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full\r
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: usedw 0 0 12 0 OUTPUT NODEFVAL usedw[11..0]\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0\r
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0\r
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0\r
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0\r
+// Retrieval info: CONNECT: usedw 0 0 12 0 @usedw 0 0 12 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_4kx16_bb.v b/usrp/fpga/megacells/fifo_4kx16_bb.v
new file mode 100755 (executable)
index 0000000..d41e9f0
--- /dev/null
@@ -0,0 +1,122 @@
+// megafunction wizard: %FIFO%VBB%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: scfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_4kx16.v\r
+// Megafunction Name(s):\r
+//                     scfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+module fifo_4kx16 (\r
+       aclr,\r
+       clock,\r
+       data,\r
+       rdreq,\r
+       wrreq,\r
+       empty,\r
+       full,\r
+       q,\r
+       usedw);\r
+\r
+       input     aclr;\r
+       input     clock;\r
+       input   [15:0]  data;\r
+       input     rdreq;\r
+       input     wrreq;\r
+       output    empty;\r
+       output    full;\r
+       output  [15:0]  q;\r
+       output  [11:0]  usedw;\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "0"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "4096"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "16"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr\r
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock\r
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]\r
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty\r
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full\r
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: usedw 0 0 12 0 OUTPUT NODEFVAL usedw[11..0]\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0\r
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0\r
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0\r
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0\r
+// Retrieval info: CONNECT: usedw 0 0 12 0 @usedw 0 0 12 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_4kx16_inst.v b/usrp/fpga/megacells/fifo_4kx16_inst.v
new file mode 100755 (executable)
index 0000000..eb260ac
--- /dev/null
@@ -0,0 +1,11 @@
+fifo_4kx16     fifo_4kx16_inst (\r
+       .aclr ( aclr_sig ),\r
+       .clock ( clock_sig ),\r
+       .data ( data_sig ),\r
+       .rdreq ( rdreq_sig ),\r
+       .wrreq ( wrreq_sig ),\r
+       .empty ( empty_sig ),\r
+       .full ( full_sig ),\r
+       .q ( q_sig ),\r
+       .usedw ( usedw_sig )\r
+       );\r
diff --git a/usrp/fpga/megacells/fifo_512.bsf b/usrp/fpga/megacells/fifo_512.bsf
deleted file mode 100755 (executable)
index a955b56..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*\r
-WARNING: Do NOT edit the input and output ports in this file in a text\r
-editor if you plan to continue editing the block that represents it in\r
-the Block Editor! File corruption is VERY likely to occur.\r
-*/\r
-/*\r
-Copyright (C) 1991-2006 Altera Corporation\r
-Your use of Altera Corporation's design tools, logic functions \r
-and other software and tools, and its AMPP partner logic \r
-functions, and any output files any of the foregoing \r
-(including device programming or simulation files), and any \r
-associated documentation or information are expressly subject \r
-to the terms and conditions of the Altera Program License \r
-Subscription Agreement, Altera MegaCore Function License \r
-Agreement, or other applicable license agreement, including, \r
-without limitation, that your use is for the sole purpose of \r
-programming logic devices manufactured by Altera and sold by \r
-Altera or its authorized distributors.  Please refer to the \r
-applicable agreement for further details.\r
-*/\r
-(header "symbol" (version "1.1"))\r
-(symbol\r
-       (rect 0 0 160 184)\r
-       (text "fifo_512" (rect 58 1 109 17)(font "Arial" (font_size 10)))\r
-       (text "inst" (rect 8 168 25 180)(font "Arial" ))\r
-       (port\r
-               (pt 0 32)\r
-               (input)\r
-               (text "data[31..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))\r
-               (text "data[31..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))\r
-               (line (pt 0 32)(pt 16 32)(line_width 3))\r
-       )\r
-       (port\r
-               (pt 0 56)\r
-               (input)\r
-               (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))\r
-               (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))\r
-               (line (pt 0 56)(pt 16 56)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 0 72)\r
-               (input)\r
-               (text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))\r
-               (text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))\r
-               (line (pt 0 72)(pt 16 72)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 0 104)\r
-               (input)\r
-               (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))\r
-               (text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))\r
-               (line (pt 0 104)(pt 16 104)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 0 120)\r
-               (input)\r
-               (text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))\r
-               (text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))\r
-               (line (pt 0 120)(pt 16 120)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 0 160)\r
-               (input)\r
-               (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))\r
-               (text "aclr" (rect 20 154 37 167)(font "Arial" (font_size 8)))\r
-               (line (pt 0 160)(pt 16 160)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 160 40)\r
-               (output)\r
-               (text "wrfull" (rect 0 0 33 14)(font "Arial" (font_size 8)))\r
-               (text "wrfull" (rect 113 34 138 47)(font "Arial" (font_size 8)))\r
-               (line (pt 160 40)(pt 144 40)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 160 56)\r
-               (output)\r
-               (text "wrempty" (rect 0 0 50 14)(font "Arial" (font_size 8)))\r
-               (text "wrempty" (rect 98 50 137 63)(font "Arial" (font_size 8)))\r
-               (line (pt 160 56)(pt 144 56)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 160 96)\r
-               (output)\r
-               (text "q[31..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))\r
-               (text "q[31..0]" (rect 105 90 141 103)(font "Arial" (font_size 8)))\r
-               (line (pt 160 96)(pt 144 96)(line_width 3))\r
-       )\r
-       (port\r
-               (pt 160 120)\r
-               (output)\r
-               (text "rdfull" (rect 0 0 28 14)(font "Arial" (font_size 8)))\r
-               (text "rdfull" (rect 117 114 141 127)(font "Arial" (font_size 8)))\r
-               (line (pt 160 120)(pt 144 120)(line_width 1))\r
-       )\r
-       (port\r
-               (pt 160 136)\r
-               (output)\r
-               (text "rdempty" (rect 0 0 46 14)(font "Arial" (font_size 8)))\r
-               (text "rdempty" (rect 102 130 140 143)(font "Arial" (font_size 8)))\r
-               (line (pt 160 136)(pt 144 136)(line_width 1))\r
-       )\r
-       (drawing\r
-               (text "32 bits x 128 words" (rect 63 156 144 168)(font "Arial" ))\r
-               (line (pt 16 16)(pt 144 16)(line_width 1))\r
-               (line (pt 144 16)(pt 144 168)(line_width 1))\r
-               (line (pt 144 168)(pt 16 168)(line_width 1))\r
-               (line (pt 16 168)(pt 16 16)(line_width 1))\r
-               (line (pt 16 84)(pt 144 84)(line_width 1))\r
-               (line (pt 16 148)(pt 144 148)(line_width 1))\r
-               (line (pt 16 66)(pt 22 72)(line_width 1))\r
-               (line (pt 22 72)(pt 16 78)(line_width 1))\r
-               (line (pt 16 114)(pt 22 120)(line_width 1))\r
-               (line (pt 22 120)(pt 16 126)(line_width 1))\r
-       )\r
-)\r
diff --git a/usrp/fpga/megacells/fifo_512.cmp b/usrp/fpga/megacells/fifo_512.cmp
deleted file mode 100755 (executable)
index 86fc078..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
---Copyright (C) 1991-2006 Altera Corporation\r
---Your use of Altera Corporation's design tools, logic functions \r
---and other software and tools, and its AMPP partner logic \r
---functions, and any output files any of the foregoing \r
---(including device programming or simulation files), and any \r
---associated documentation or information are expressly subject \r
---to the terms and conditions of the Altera Program License \r
---Subscription Agreement, Altera MegaCore Function License \r
---Agreement, or other applicable license agreement, including, \r
---without limitation, that your use is for the sole purpose of \r
---programming logic devices manufactured by Altera and sold by \r
---Altera or its authorized distributors.  Please refer to the \r
---applicable agreement for further details.\r
-\r
-\r
-component fifo_512\r
-       PORT\r
-       (\r
-               aclr            : IN STD_LOGIC  := '0';\r
-               data            : IN STD_LOGIC_VECTOR (31 DOWNTO 0);\r
-               rdclk           : IN STD_LOGIC ;\r
-               rdreq           : IN STD_LOGIC ;\r
-               wrclk           : IN STD_LOGIC ;\r
-               wrreq           : IN STD_LOGIC ;\r
-               q               : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);\r
-               rdempty         : OUT STD_LOGIC ;\r
-               rdfull          : OUT STD_LOGIC ;\r
-               wrempty         : OUT STD_LOGIC ;\r
-               wrfull          : OUT STD_LOGIC \r
-       );\r
-end component;\r
diff --git a/usrp/fpga/megacells/fifo_512.inc b/usrp/fpga/megacells/fifo_512.inc
deleted file mode 100755 (executable)
index 9ae1e3a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---Copyright (C) 1991-2006 Altera Corporation\r
---Your use of Altera Corporation's design tools, logic functions \r
---and other software and tools, and its AMPP partner logic \r
---functions, and any output files any of the foregoing \r
---(including device programming or simulation files), and any \r
---associated documentation or information are expressly subject \r
---to the terms and conditions of the Altera Program License \r
---Subscription Agreement, Altera MegaCore Function License \r
---Agreement, or other applicable license agreement, including, \r
---without limitation, that your use is for the sole purpose of \r
---programming logic devices manufactured by Altera and sold by \r
---Altera or its authorized distributors.  Please refer to the \r
---applicable agreement for further details.\r
-\r
-\r
-FUNCTION fifo_512 \r
-(\r
-       aclr,\r
-       data[31..0],\r
-       rdclk,\r
-       rdreq,\r
-       wrclk,\r
-       wrreq\r
-)\r
-\r
-RETURNS (\r
-       q[31..0],\r
-       rdempty,\r
-       rdfull,\r
-       wrempty,\r
-       wrfull\r
-);\r
diff --git a/usrp/fpga/megacells/fifo_512.v b/usrp/fpga/megacells/fifo_512.v
deleted file mode 100755 (executable)
index b034b4d..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-// megafunction wizard: %LPM_FIFO+%\r
-// GENERATION: STANDARD\r
-// VERSION: WM1.0\r
-// MODULE: dcfifo \r
-\r
-// ============================================================\r
-// File Name: fifo_512.v\r
-// Megafunction Name(s):\r
-//                     dcfifo\r
-// ============================================================\r
-// ************************************************************\r
-// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
-//\r
-// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
-// ************************************************************\r
-\r
-\r
-//Copyright (C) 1991-2006 Altera Corporation\r
-//Your use of Altera Corporation's design tools, logic functions \r
-//and other software and tools, and its AMPP partner logic \r
-//functions, and any output files any of the foregoing \r
-//(including device programming or simulation files), and any \r
-//associated documentation or information are expressly subject \r
-//to the terms and conditions of the Altera Program License \r
-//Subscription Agreement, Altera MegaCore Function License \r
-//Agreement, or other applicable license agreement, including, \r
-//without limitation, that your use is for the sole purpose of \r
-//programming logic devices manufactured by Altera and sold by \r
-//Altera or its authorized distributors.  Please refer to the \r
-//applicable agreement for further details.\r
-\r
-\r
-// synopsys translate_off\r
-`timescale 1 ps / 1 ps\r
-// synopsys translate_on\r
-module fifo_512 (\r
-       aclr,\r
-       data,\r
-       rdclk,\r
-       rdreq,\r
-       wrclk,\r
-       wrreq,\r
-       q,\r
-       rdempty,\r
-       rdfull,\r
-       wrempty,\r
-       wrfull);\r
-\r
-       input     aclr;\r
-       input   [31:0]  data;\r
-       input     rdclk;\r
-       input     rdreq;\r
-       input     wrclk;\r
-       input     wrreq;\r
-       output  [31:0]  q;\r
-       output    rdempty;\r
-       output    rdfull;\r
-       output    wrempty;\r
-       output    wrfull;\r
-\r
-       wire  sub_wire0;\r
-       wire  sub_wire1;\r
-       wire  sub_wire2;\r
-       wire  sub_wire3;\r
-       wire [31:0] sub_wire4;\r
-       wire  rdfull = sub_wire0;\r
-       wire  rdempty = sub_wire1;\r
-       wire  wrfull = sub_wire2;\r
-       wire  wrempty = sub_wire3;\r
-       wire [31:0] q = sub_wire4[31:0];\r
-\r
-       dcfifo  dcfifo_component (\r
-                               .wrclk (wrclk),\r
-                               .rdreq (rdreq),\r
-                               .aclr (aclr),\r
-                               .rdclk (rdclk),\r
-                               .wrreq (wrreq),\r
-                               .data (data),\r
-                               .rdfull (sub_wire0),\r
-                               .rdempty (sub_wire1),\r
-                               .wrfull (sub_wire2),\r
-                               .wrempty (sub_wire3),\r
-                               .q (sub_wire4)\r
-                               // synopsys translate_off\r
-                               ,\r
-                               .rdusedw (),\r
-                               .wrusedw ()\r
-                               // synopsys translate_on\r
-                               );\r
-       defparam\r
-               dcfifo_component.add_ram_output_register = "OFF",\r
-               dcfifo_component.clocks_are_synchronized = "FALSE",\r
-               dcfifo_component.intended_device_family = "Cyclone",\r
-               dcfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",\r
-               dcfifo_component.lpm_numwords = 128,\r
-               dcfifo_component.lpm_showahead = "OFF",\r
-               dcfifo_component.lpm_type = "dcfifo",\r
-               dcfifo_component.lpm_width = 32,\r
-               dcfifo_component.lpm_widthu = 7,\r
-               dcfifo_component.overflow_checking = "ON",\r
-               dcfifo_component.underflow_checking = "ON",\r
-               dcfifo_component.use_eab = "ON";\r
-\r
-\r
-endmodule\r
-\r
-// ============================================================\r
-// CNX file retrieval info\r
-// ============================================================\r
-// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
-// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
-// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
-// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
-// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
-// Retrieval info: PRIVATE: Clock NUMERIC "4"\r
-// Retrieval info: PRIVATE: Depth NUMERIC "128"\r
-// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
-// Retrieval info: PRIVATE: Full NUMERIC "1"\r
-// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
-// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
-// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
-// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
-// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
-// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
-// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
-// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
-// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
-// Retrieval info: PRIVATE: Width NUMERIC "32"\r
-// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsFull NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
-// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"\r
-// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
-// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"\r
-// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
-// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
-// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
-// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"\r
-// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
-// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
-// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"\r
-// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
-// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"\r
-// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"\r
-// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"\r
-// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
-// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
-// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
-// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr\r
-// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]\r
-// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]\r
-// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk\r
-// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty\r
-// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull\r
-// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
-// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk\r
-// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty\r
-// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull\r
-// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
-// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0\r
-// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0\r
-// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
-// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
-// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0\r
-// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0\r
-// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0\r
-// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0\r
-// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0\r
-// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0\r
-// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
-// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_512_bb.v b/usrp/fpga/megacells/fifo_512_bb.v
deleted file mode 100755 (executable)
index b118031..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-// megafunction wizard: %LPM_FIFO+%VBB%\r
-// GENERATION: STANDARD\r
-// VERSION: WM1.0\r
-// MODULE: dcfifo \r
-\r
-// ============================================================\r
-// File Name: fifo_512.v\r
-// Megafunction Name(s):\r
-//                     dcfifo\r
-// ============================================================\r
-// ************************************************************\r
-// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
-//\r
-// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
-// ************************************************************\r
-\r
-//Copyright (C) 1991-2006 Altera Corporation\r
-//Your use of Altera Corporation's design tools, logic functions \r
-//and other software and tools, and its AMPP partner logic \r
-//functions, and any output files any of the foregoing \r
-//(including device programming or simulation files), and any \r
-//associated documentation or information are expressly subject \r
-//to the terms and conditions of the Altera Program License \r
-//Subscription Agreement, Altera MegaCore Function License \r
-//Agreement, or other applicable license agreement, including, \r
-//without limitation, that your use is for the sole purpose of \r
-//programming logic devices manufactured by Altera and sold by \r
-//Altera or its authorized distributors.  Please refer to the \r
-//applicable agreement for further details.\r
-\r
-module fifo_512 (\r
-       aclr,\r
-       data,\r
-       rdclk,\r
-       rdreq,\r
-       wrclk,\r
-       wrreq,\r
-       q,\r
-       rdempty,\r
-       rdfull,\r
-       wrempty,\r
-       wrfull);\r
-\r
-       input     aclr;\r
-       input   [31:0]  data;\r
-       input     rdclk;\r
-       input     rdreq;\r
-       input     wrclk;\r
-       input     wrreq;\r
-       output  [31:0]  q;\r
-       output    rdempty;\r
-       output    rdfull;\r
-       output    wrempty;\r
-       output    wrfull;\r
-\r
-endmodule\r
-\r
-// ============================================================\r
-// CNX file retrieval info\r
-// ============================================================\r
-// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
-// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
-// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
-// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
-// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
-// Retrieval info: PRIVATE: Clock NUMERIC "4"\r
-// Retrieval info: PRIVATE: Depth NUMERIC "128"\r
-// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
-// Retrieval info: PRIVATE: Full NUMERIC "1"\r
-// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
-// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
-// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
-// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
-// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
-// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
-// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
-// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
-// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
-// Retrieval info: PRIVATE: Width NUMERIC "32"\r
-// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsFull NUMERIC "1"\r
-// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
-// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"\r
-// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
-// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"\r
-// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
-// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
-// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
-// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"\r
-// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
-// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
-// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"\r
-// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
-// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"\r
-// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"\r
-// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"\r
-// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
-// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
-// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
-// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr\r
-// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]\r
-// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]\r
-// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk\r
-// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty\r
-// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull\r
-// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
-// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk\r
-// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty\r
-// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull\r
-// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
-// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0\r
-// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0\r
-// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
-// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
-// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0\r
-// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0\r
-// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0\r
-// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0\r
-// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0\r
-// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0\r
-// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
-// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE\r
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE\r
index 2d192943932c44c9a17dfeec6b9f1a379284dae2..3291dc10b8db49abab55152c8ede3dcd22570dde 100644 (file)
@@ -1,4 +1,4 @@
-// -*- verilog -*-
+       // -*- verilog -*-
 //
 //  USRP - Universal Software Radio Peripheral
 //
index 8296a453e05a5f446091d2cb21f1dde85adbdbd2..6b4764078acfd3104507aed3f4a0a7ea62d99f7d 100644 (file)
@@ -372,11 +372,16 @@ set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk
 set_instance_assignment -name PARTITION_HIERARCHY no_file_for_top_partition -to | -section_id Top
 set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
 set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN "100 ps"
+set_global_assignment -name VERILOG_FILE ../../inband_lib/channel_demux.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/tx_packer.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/cmd_reader.v
+set_global_assignment -name VERILOG_FILE ../../megacells/fifo_2k_1clk.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/packet_builder.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/rx_buffer_inband.v
+set_global_assignment -name VERILOG_FILE ../../sdr_lib/atr_delay.v
+set_global_assignment -name VERILOG_FILE ../../megacells/fifo_1k.v
 set_global_assignment -name VERILOG_FILE ../../inband_lib/tx_buffer_inband.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_packet_fifo.v
 set_global_assignment -name VERILOG_FILE ../../inband_lib/chan_fifo_reader.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/data_packet_fifo.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_fifo_reader.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_dec_shifter.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/rssi.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v
@@ -412,4 +417,6 @@ set_global_assignment -name VERILOG_FILE usrp_inband_usb.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v
-set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
\ No newline at end of file
+set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/channel_ram.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/register_io.v
\ No newline at end of file
index cc7490c5a12b1dd2130be692e463e30244f5b9c0..3bfdda56ba4f1c72ec19d35493aa682fd29cac06 100644 (file)
@@ -19,7 +19,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
 //
-`define IN_BAND
+`define TX_IN_BAND
+`define RX_IN_BAND
 
 `include "config.vh"
 `include "../../../firmware/include/fpga_regs_common.v"
@@ -115,6 +116,12 @@ module usrp_inband_usb
    reg [15:0] debug_counter;
    reg [15:0] loopback_i_0,loopback_q_0;
    
+
+   //Connection RX inband <-> TX inband
+   wire rx_WR;
+   wire [15:0] rx_databus;
+   wire rx_WR_done;
+   wire rx_WR_enabled;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Transmit Side
 `ifdef TX_ON
@@ -123,7 +130,17 @@ module usrp_inband_usb
    assign      bb_tx_i1 = ch2tx;
    assign      bb_tx_q1 = ch3tx;
    
-`ifdef IN_BAND
+wire [6:0] reg_addr;
+wire [31:0] reg_data_out;
+wire [31:0] reg_data_in;
+wire [1:0] reg_io_enable;
+wire [31:0] rssi_threshhold;
+register_io register_control
+(.clk(clk64),.reset(1'b0),.enable(reg_io_enable),.addr(reg_addr),.datain(reg_data_in),
+ .dataout(reg_data_out),.rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2), 
+ .rssi_3(rssi_3), .threshhold(rssi_threshhold));
+
+`ifdef TX_IN_BAND
        tx_buffer_inband tx_buffer
      ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
        .usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun),
@@ -135,7 +152,17 @@ module usrp_inband_usb
        .txclk(clk64),.txstrobe(strobe_interp),
        .clear_status(clear_status),
        .tx_empty(tx_empty),
-       .debugbus(tx_debugbus) );
+          .rx_WR(rx_WR),
+          .rx_databus(rx_databus), 
+          .rx_WR_done(rx_WR_done),
+          .rx_WR_enabled(rx_WR_enabled),
+          .reg_addr(reg_addr),
+          .reg_data_out(reg_data_out),
+          .reg_data_in(reg_data_in),
+          .reg_io_enable(reg_io_enable),
+          .debugbus(tx_debugbus),
+          .rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2), 
+       .rssi_3(rssi_3), .threshhold(rssi_threshhold));
 `else
    tx_buffer tx_buffer
      ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
@@ -147,8 +174,7 @@ module usrp_inband_usb
        .tx_i_3(),.tx_q_3(),
        .txclk(clk64),.txstrobe(strobe_interp),
        .clear_status(clear_status),
-       .tx_empty(tx_empty),
-       .debugbus(tx_debugbus) );
+       .tx_empty(tx_empty));
 `endif
 
  `ifdef TX_EN_0
@@ -226,7 +252,6 @@ module usrp_inband_usb
 
    wire [15:0] ddc0_in_i,ddc0_in_q,ddc1_in_i,ddc1_in_q,ddc2_in_i,ddc2_in_q,ddc3_in_i,ddc3_in_q;
    wire [31:0] rssi_0,rssi_1,rssi_2,rssi_3;
-   
    adc_interface adc_interface(.clock(clk64),.reset(rx_dsp_reset),.enable(1'b1),
                               .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
                               .rx_a_a(rx_a_a),.rx_b_a(rx_b_a),.rx_a_b(rx_a_b),.rx_b_b(rx_b_b),
@@ -234,9 +259,9 @@ module usrp_inband_usb
                               .ddc0_in_i(ddc0_in_i),.ddc0_in_q(ddc0_in_q),
                               .ddc1_in_i(ddc1_in_i),.ddc1_in_q(ddc1_in_q),
                               .ddc2_in_i(ddc2_in_i),.ddc2_in_q(ddc2_in_q),
-                              .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan) );
-   
-   rx_buffer rx_buffer
+                              .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan));
+   `ifdef RX_IN_BAND
+   rx_buffer_inband rx_buffer
      ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset),
        .reset_regs(rx_dsp_reset),
        .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun),
@@ -248,7 +273,27 @@ module usrp_inband_usb
        .rxclk(clk64),.rxstrobe(hb_strobe),
        .clear_status(clear_status),
        .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
-       .debugbus(rx_debugbus) );
+          .rx_WR(rx_WR),
+          .rx_databus(rx_databus),
+          .rx_WR_done(rx_WR_done),
+          .rx_WR_enabled(rx_WR_enabled),
+          .debugbus(rx_debugbus),
+          .rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2), .rssi_3(rssi_3));
+   `else
+   rx_buffer rx_buffer
+     ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset),
+       .reset_regs(rx_dsp_reset),
+       .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun),
+       .channels(rx_numchan),
+       .ch_0(ch0rx),.ch_1(ch1rx),
+       .ch_2(ch2rx),.ch_3(ch3rx),
+       .ch_4(ch4rx),.ch_5(ch5rx),
+       .ch_6(ch6rx),.ch_7(ch7rx),
+       .rxclk(clk64),.rxstrobe(hb_strobe),
+       .clear_status(clear_status),
+       .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe)/*,
+       .debugbus(rx_debugbus)*/);
+   `endif
    
  `ifdef RX_EN_0
    rx_chain #(`FR_RX_FREQ_0,`FR_RX_PHASE_0) rx_chain_0
@@ -305,7 +350,6 @@ module usrp_inband_usb
    assign      capabilities[3] =   `RX_CAP_HB;
    assign      capabilities[2:0] = `RX_CAP_NCHAN;
 
-
    serial_io serial_io
      ( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI),
        .enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO),
@@ -326,7 +370,7 @@ module usrp_inband_usb
        .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim),
        .tx_empty(tx_empty),
        //.debug_0(rx_a_a),.debug_1(ddc0_in_i),
-       .debug_0(rx_debugbus),.debug_1(ddc0_in_i),
+       .debug_0(tx_debugbus),.debug_1(tx_debugbus),
        .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,tx_underrun,rx_overrun,decim_rate}),
        .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) );
    
index f920ce59a2220f8f78158e3f86416388667a1b41..e0f5b8cf4c18569f6fe34b7f4fa5fb0a641aa847 100644 (file)
 
 include $(top_srcdir)/Makefile.common
 
-INCLUDES = $(USRP_INCLUDES) $(BOOST_CFLAGS)
+INCLUDES =     \
+       $(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
+       $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+
 
 bin_PROGRAMS =                         \
        usrper                          \
@@ -29,11 +32,20 @@ bin_PROGRAMS =                              \
 
 noinst_PROGRAMS =                      \
        check_order_quickly             \
+       test_usrp_inband_cs             \
+       test_usrp_inband_ping           \
+       test_usrp_inband_registers      \
+       test_usrp_inband_rx             \
+       test_usrp_inband_tx             \
+       test_usrp_inband_timestamps     \
        test_usrp_standard_rx           \
-       test_usrp_standard_tx           
+       test_usrp_standard_tx           \
+       read_packets
 
 noinst_HEADERS =                       \
-       time_stuff.h
+       time_stuff.h                    \
+       ui_nco.h                        \
+       ui_sincos.h                     
 
 noinst_PYTHON =                                \
        burn-db-eeprom                  \
@@ -53,3 +65,24 @@ usrper_LDADD                         = $(USRP_LA)
 
 usrp_cal_dc_offset_SOURCES     = usrp_cal_dc_offset.cc
 usrp_cal_dc_offset_LDADD       = $(USRP_LA)
+
+test_usrp_inband_cs_SOURCES    = test_usrp_inband_cs.cc time_stuff.c ui_sincos.c
+test_usrp_inband_cs_LDADD      = $(USRP_LA)
+
+test_usrp_inband_ping_SOURCES  = test_usrp_inband_ping.cc time_stuff.c
+test_usrp_inband_ping_LDADD    = $(USRP_LA)
+
+test_usrp_inband_tx_SOURCES    = test_usrp_inband_tx.cc time_stuff.c ui_sincos.c
+test_usrp_inband_tx_LDADD      = $(USRP_LA)
+
+test_usrp_inband_timestamps_SOURCES    = test_usrp_inband_timestamps.cc time_stuff.c ui_sincos.c
+test_usrp_inband_timestamps_LDADD      = $(USRP_LA)
+
+test_usrp_inband_registers_SOURCES     = test_usrp_inband_registers.cc time_stuff.c ui_sincos.c
+test_usrp_inband_registers_LDADD       = $(USRP_LA)
+
+test_usrp_inband_rx_SOURCES    = test_usrp_inband_rx.cc time_stuff.c ui_sincos.c
+test_usrp_inband_rx_LDADD      = $(USRP_LA)
+
+read_packets_SOURCES = read_packets.cc
+read_packets_LDADD = $(USRP_LA)
diff --git a/usrp/host/apps/read_packets.cc b/usrp/host/apps/read_packets.cc
new file mode 100644 (file)
index 0000000..92d8baf
--- /dev/null
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <mb_class_registry.h>
+#include <vector>
+#include <usrp_usb_interface.h>
+#include <fstream>
+
+typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
+
+int main(int argc, char *argv[]) {
+
+  if(argc !=2) {
+    std::cout << "Usage: ./read_packets <data_file>\n";
+    return -1;
+  }
+
+  std::ifstream infile;
+  std::ofstream outfile;  
+
+  unsigned int pkt_size = transport_pkt::max_pkt_size();
+  unsigned int pkt_num=0;
+
+  transport_pkt *pkt;
+  char pkt_data[pkt_size];          // allocate the number of bytes for a single packet
+
+  pkt = (transport_pkt *)pkt_data;  // makes operations cleaner to read
+
+  // Open the file and read the packets, dumping information
+  infile.open(argv[1], std::ios::binary|std::ios::in);
+  if(!infile.is_open())
+    exit(-1);
+
+  //outfile.open("dump.dat",std::ios::out|std::ios::binary);  
+
+  // read 1 packet in to the memory
+  infile.read(pkt_data, pkt_size);
+
+  while(!infile.eof()) {
+  
+    printf("Packet %u\n", pkt_num);
+
+    if(pkt->start_of_burst())
+      printf("\tstart of burst\n");
+      
+    if(pkt->end_of_burst())
+      printf("\tend of burst\n");
+    
+//    if(pkt->carrier_sense())
+//      printf("\tcarrier sense\n");
+
+    printf("\tchannel: \t0x%x\n", pkt->chan());
+    printf("\ttimestamp: \t0x%x\n", pkt->timestamp());
+    //printf("\ttimestamp: \t%u\n", pkt->timestamp());
+    printf("\tlength: \t%u\n", pkt->payload_len());
+    printf("\trssi: \t%u\n", pkt->rssi());
+
+    printf("\tpayload: \n");
+    for(int i=0; i < pkt->payload_len(); i++)
+    //for(int i=0; i < pkt->max_payload(); i++)
+    {
+      printf("\t%d\t0x%x\n", i, *(pkt->payload()+i));
+      //outfile.write((const char*)(pkt->payload()+i),1);
+      //printf("\t\t0x%x\n", pkt->payload()+i);
+
+    }
+    printf("\n\n");
+
+    pkt_num++;
+  
+    // read 1 packet in to the memory
+    infile.read(pkt_data, pkt_size);
+
+  }
+
+  infile.close();
+  //outfile.close();
+
+}
diff --git a/usrp/host/apps/test_usrp_inband_cs.cc b/usrp/host/apps/test_usrp_inband_cs.cc
new file mode 100644 (file)
index 0000000..1d70341
--- /dev/null
@@ -0,0 +1,478 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+
+#define NBPING  10
+
+static bool verbose = false;
+
+class test_usrp_cs : public mb_mblock
+{
+  mb_port_sptr         d_tx;
+  mb_port_sptr         d_rx;
+  mb_port_sptr         d_cs;
+  pmt_t                d_tx_chan;      // returned tx channel handle
+  pmt_t                d_rx_chan;      // returned tx channel handle
+
+  struct timeval times[NBPING];
+
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNEL,
+    TRANSMITTING,
+    CLOSING_CHANNEL,
+    CLOSING_USRP,
+  };
+
+  state_t      d_state;
+  long         d_nsamples_to_send;
+  long         d_nsamples_xmitted;
+  long         d_nframes_xmitted;
+  long         d_samples_per_frame;
+  bool         d_done_sending;
+
+  // for generating sine wave output
+  ui_nco<float,float>  d_nco;
+  double               d_amplitude;
+
+ public:
+  test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_cs();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void open_usrp();
+  void close_usrp();
+  void allocate_channel();
+  void send_packets();
+  void enter_receiving();
+  void enter_transmitting();
+  void build_and_send_ping();
+  void build_and_send_next_frame();
+  void handle_xmit_response(pmt_t invocation_handle);
+  void enter_closing_channel();
+};
+
+test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_tx_chan(PMT_NIL),
+    d_rx_chan(PMT_NIL),
+    d_state(INIT), d_nsamples_to_send((long) 40e6),
+    d_nsamples_xmitted(0),
+    d_nframes_xmitted(0),
+    //d_samples_per_frame((long)(126)),
+    //d_samples_per_frame((long)(126 * 3.5)),  // non-full packet
+    d_samples_per_frame((long)(126 * 4)),      // full packet
+    d_done_sending(false),
+    d_amplitude(16384)
+{ 
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_CS] Initializing...\n";
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  
+  //bool fake_usrp_p = true;
+  bool fake_usrp_p = false;
+
+  // Test the TX side
+
+  pmt_t usrp_dict = pmt_make_dict();
+
+  if(fake_usrp_p) {
+    pmt_dict_set(usrp_dict, 
+                 pmt_intern("fake-usrp"),
+                            PMT_T);
+  }
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("boe.rbf"));
+
+  define_component("server", "usrp_server", usrp_dict);
+
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+  // initialize NCO
+  double freq = 100e3;
+  int interp = 32;                         // 32 -> 4MS/s
+  double sample_rate = 128e6 / interp; 
+  d_nco.set_freq(2*M_PI * freq/sample_rate);
+
+  // FIXME need to somehow set the interp rate in the USRP.
+  // for now, we'll have the low-level code hardwire it.
+}
+
+test_usrp_cs::~test_usrp_cs()
+{
+}
+
+void
+test_usrp_cs::initial_transition()
+{
+  open_usrp();
+}
+
+void
+test_usrp_cs::handle_message(mb_message_sptr msg)
+{
+  pmt_t        event = msg->signal();
+  pmt_t data = msg->data();
+  pmt_t port_id = msg->port_id();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+  
+  //std::cout << msg << std::endl;
+
+  switch(d_state){
+  case OPENING_USRP:
+    if (pmt_eq(event, s_response_open)){
+      status = pmt_nth(1, data);
+      if (pmt_eq(status, PMT_T)){
+        allocate_channel();
+        return;
+      }
+      else {
+        error_msg = "failed to open usrp:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+    
+  case ALLOCATING_CHANNEL:
+    if (pmt_eq(event, s_response_allocate_channel)){
+
+      if(pmt_eq(d_tx->port_symbol(), port_id)) {
+        status = pmt_nth(1, data);
+        d_tx_chan = pmt_nth(2, data);
+
+        if (pmt_eq(status, PMT_T)){
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_CS] Received allocation for TX\n";
+
+          if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
+            enter_receiving();
+            enter_transmitting();
+          }
+          return;
+        }
+        else {
+          error_msg = "failed to allocate channel:";
+          goto bail;
+        }
+      }
+      
+      if(pmt_eq(d_rx->port_symbol(), port_id)) {
+        status = pmt_nth(1, data);
+        d_rx_chan = pmt_nth(2, data);
+
+        if (pmt_eq(status, PMT_T)){
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_CS] Received allocation for TX\n";
+          
+          if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
+            enter_receiving();
+            enter_transmitting();
+          }
+          return;
+        }
+        else {
+          error_msg = "failed to allocate channel:";
+          goto bail;
+        }
+      }
+    }
+    goto unhandled;
+
+  case TRANSMITTING:
+    if (pmt_eq(event, s_response_xmit_raw_frame)){
+      handle = pmt_nth(0, data);
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        handle_xmit_response(handle);
+        return;
+      }
+      else {
+        error_msg = "bad response-xmit-raw-frame:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_CHANNEL:
+    if (pmt_eq(event, s_response_deallocate_channel)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        close_usrp();
+        return;
+      }
+      else {
+        error_msg = "failed to deallocate channel:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_USRP:
+    if (pmt_eq(event, s_response_close)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        shutdown_all(PMT_T);
+        return;
+      }
+      else {
+        error_msg = "failed to close USRP:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  default:
+    goto unhandled;
+  }
+  return;
+
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ unhandled:
+  if(verbose)
+    std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+              << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_cs::open_usrp()
+{
+  pmt_t which_usrp = pmt_from_long(0);
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
+  d_state = OPENING_USRP;
+}
+
+void
+test_usrp_cs::close_usrp()
+{
+  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+  d_state = CLOSING_USRP;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_CS] Closing USRP\n";
+}
+
+void
+test_usrp_cs::allocate_channel()
+{
+  long capacity = (long) 16e6;
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_state = ALLOCATING_CHANNEL;
+}
+
+void
+test_usrp_cs::enter_receiving()
+{
+  d_rx->send(s_cmd_start_recv_raw_samples,
+             pmt_list2(PMT_F,
+                       d_rx_chan));
+}
+
+void
+test_usrp_cs::enter_transmitting()
+{
+  d_state = TRANSMITTING;
+  d_nsamples_xmitted = 0;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_CS] Beginning transmission\n";
+
+  sleep(1);
+
+//  build_and_send_next_frame();       // fire off 4 to start pipeline
+
+  build_and_send_ping();
+  build_and_send_ping();
+  build_and_send_ping();
+  
+}
+
+void
+test_usrp_cs::build_and_send_ping()
+{
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
+                                                    pmt_list2(pmt_from_long(0),
+                                                              pmt_from_long(0))))));
+
+  std::cout << "[TEST_USRP_INBAND_CS] Ping sent" << std::endl;
+}
+
+void
+test_usrp_cs::build_and_send_next_frame()
+{
+  // allocate the uniform vector for the samples
+  // FIXME perhaps hold on to this between calls
+
+#if 1
+  long nsamples_this_frame =
+    std::min(d_nsamples_to_send - d_nsamples_xmitted,
+            d_samples_per_frame);
+#else
+  long nsamples_this_frame = d_samples_per_frame;
+#endif
+
+  if (nsamples_this_frame == 0){
+    d_done_sending = true;
+    return;
+  }
+    
+
+  size_t nshorts = 2 * nsamples_this_frame;    // 16-bit I & Q
+  pmt_t uvec = pmt_make_s16vector(nshorts, 0);
+  size_t ignore;
+  int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
+
+  // fill in the complex sinusoid
+
+  for (int i = 0; i < nsamples_this_frame; i++){
+
+    if (1){
+      gr_complex s;
+      d_nco.sincos(&s, 1, d_amplitude);
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+    else {
+      gr_complex s(d_amplitude, d_amplitude);
+
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+  }
+
+  pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
+  d_tx->send(s_cmd_xmit_raw_frame,
+            pmt_list4(pmt_from_long(d_nframes_xmitted),  // invocation-handle
+                      d_tx_chan,                         // channel
+                      uvec,                              // the samples
+                      timestamp));
+
+  d_nsamples_xmitted += nsamples_this_frame;
+  d_nframes_xmitted++;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_CS] Transmitted frame\n";
+}
+
+
+void
+test_usrp_cs::handle_xmit_response(pmt_t handle)
+{
+  if (d_done_sending &&
+      pmt_to_long(handle) == (d_nframes_xmitted - 1)){
+    // We're done sending and have received all responses
+    enter_closing_channel();
+  }
+
+  //build_and_send_next_frame();
+}
+
+void
+test_usrp_cs::enter_closing_channel()
+{
+  d_state = CLOSING_CHANNEL;
+  
+  d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_CS] Closing channel\n";
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_cs);
+
+
+// ----------------------------------------------------------------
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_cs", PMT_F, &result);
+}
diff --git a/usrp/host/apps/test_usrp_inband_ping.cc b/usrp/host/apps/test_usrp_inband_ping.cc
new file mode 100644 (file)
index 0000000..a68f492
--- /dev/null
@@ -0,0 +1,376 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+// Include the symbols needed for communication with USRP server
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+
+static bool verbose = false;
+
+class test_usrp_inband_ping : public mb_mblock
+{
+
+  mb_port_sptr  d_tx;   // Ports connected to the USRP server
+  mb_port_sptr  d_rx;
+  mb_port_sptr  d_cs;
+
+  pmt_t   d_tx_chan;    // Returned channel from TX allocation
+  pmt_t   d_rx_chan;    // Returned channel from RX allocation
+
+  pmt_t   d_which_usrp; // The USRP to use for the test
+
+  long    d_warm_msgs;  // The number of messages to 'warm' the USRP
+  long    d_warm_recvd; // The number of msgs received in the 'warm' state
+
+  // Keep track of current state
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNELS,
+    WARMING_USRP,
+    PINGING,
+    CLOSING_CHANNELS,
+    CLOSING_USRP,
+  };
+  state_t d_state;
+
+ public:
+  test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_inband_ping();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void opening_usrp();
+  void allocating_channels();
+  void enter_warming_usrp();
+  void enter_pinging();
+  void build_and_send_ping();
+  void closing_channels();
+  void closing_usrp();
+};
+
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_inband_ping", PMT_F, &result);
+}
+
+
+test_usrp_inband_ping::test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+  d_tx_chan(PMT_NIL),
+  d_rx_chan(PMT_NIL),
+  d_which_usrp(pmt_from_long(0)),
+  d_state(INIT)
+{
+  
+  // A dictionary is used to pass parameters to the USRP
+  pmt_t usrp_dict = pmt_make_dict();
+
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("fixed1.rbf"));
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Create an instance of USRP server and connect ports
+  define_component("server", "usrp_server", usrp_dict);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+}
+
+test_usrp_inband_ping::~test_usrp_inband_ping()
+{
+}
+
+void
+test_usrp_inband_ping::initial_transition()
+{
+  opening_usrp();
+}
+
+// Handle message reads all incoming messages from USRP server which will be
+// initialization and ping responses.  We perform actions based on the current
+// state and the event (ie, ping response)
+void
+test_usrp_inband_ping::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t data = msg->data();
+  pmt_t port_id = msg->port_id();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+
+  // Dispatch based on state
+  switch(d_state) {
+
+    //----------------------------- OPENING_USRP ----------------------------//
+    // We only expect a response from opening the USRP which should be succesful
+    // or failed.
+    case OPENING_USRP:
+      
+      if(pmt_eq(event, s_response_open)) {
+
+        status = pmt_nth(1, data);          // failed/succes
+        
+        if(pmt_eq(status, PMT_T)) {
+          allocating_channels();
+          return;
+        }
+        else {
+          error_msg = "failed to open usrp:";
+          goto bail;
+        }
+
+      }
+
+      goto unhandled;   // all other messages not handled in this state
+      
+    
+    //----------------------- ALLOCATING CHANNELS --------------------//
+    // When allocating channels, we need to wait for 2 responses from
+    // USRP server: one for TX and one for RX.  Both are initialized to
+    // NIL so we know to continue to the next state once both are set.
+    case ALLOCATING_CHANNELS:
+
+      // A TX allocation response
+      if(pmt_eq(event, s_response_allocate_channel)
+          && pmt_eq(d_tx->port_symbol(), port_id)) 
+      {
+        status = pmt_nth(1, data);
+        
+        // If successful response, extract the channel
+        if(pmt_eq(status, PMT_T)) {
+          
+          d_tx_chan = pmt_nth(2, data);
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
+                      << " on channel " << d_tx_chan << std::endl;
+
+          // If the RX has also been allocated already, we can continue
+          if(!pmt_eqv(d_rx_chan, PMT_NIL)) 
+            enter_warming_usrp();
+
+          return;
+        }
+        else {  // TX allocation failed
+          error_msg = "failed to allocate TX channel:";
+          goto bail;
+        }
+      }
+      
+      // A RX allocation response
+      if(pmt_eq(event, s_response_allocate_channel)
+          && pmt_eq(d_rx->port_symbol(), port_id)) 
+      {
+        status = pmt_nth(1, data);
+        
+        // If successful response, extract the channel
+        if(pmt_eq(status, PMT_T)) {
+          
+          d_rx_chan = pmt_nth(2, data);
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
+                      << " on channel " << d_rx_chan << std::endl;
+
+          // If the TX has also been allocated already, we can continue
+          if(!pmt_eqv(d_tx_chan, PMT_NIL)) 
+            enter_warming_usrp();
+
+          return;
+        }
+        else {  // RX allocation failed
+          error_msg = "failed to allocate RX channel:";
+          goto bail;
+        }
+      }
+
+      goto unhandled;
+
+    //----------------------- WARMING USRP --------------------//
+    // The FX2 seems to need some amount of data to be buffered
+    // before it begins reading.  We use this state to simply
+    // warm up the USRP before benchmarking pings.
+    case WARMING_USRP:
+
+      // We really don't care about the responses from the
+      // control channel in the warming stage, but once we receive
+      // the proper number of responses we switch states.
+      if(pmt_eq(event, s_response_from_control_channel)
+          && pmt_eq(d_rx->port_symbol(), port_id))
+      {
+        d_warm_recvd++;
+
+        if(d_warm_recvd > d_warm_msgs)
+          enter_pinging();
+
+        return;
+      }
+
+      goto unhandled;
+
+    case PINGING:
+      goto unhandled;
+
+    case CLOSING_CHANNELS:
+      goto unhandled;
+
+    case CLOSING_USRP:
+      goto unhandled;
+
+    case INIT:
+      goto unhandled;
+
+  }
+ // An error occured, print it, and shutdown all m-blocks
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ // Received an unhandled message for a specific state
+ unhandled:
+  if(verbose)
+    std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+              << "in state "<< d_state << std::endl;
+
+}
+
+
+// Sends a command to USRP server to open up a connection to the
+// specified USRP, which is defaulted to USRP 0 on the system
+void
+test_usrp_inband_ping::opening_usrp()
+{
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_PING] Opening USRP " 
+              << d_which_usrp << std::endl;
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
+  d_state = OPENING_USRP;
+}
+
+// RX and TX channels must be allocated so that the USRP server can
+// properly share bandwidth across multiple USRPs.  No commands will be
+// successful to the USRP through the USRP server on the TX or RX channels until
+// a bandwidth allocation has been received.
+void
+test_usrp_inband_ping::allocating_channels()
+{
+  d_state = ALLOCATING_CHANNELS;
+
+  long capacity = (long) 16e6;
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+}
+
+// The USRP needs some amount of initial data to pass a buffering point such
+// that it begins to pull and read data from the FX2.  We send an arbitrary
+// amount of data to start the pipeline, which are just pings.
+void
+test_usrp_inband_ping::enter_warming_usrp()
+{
+  d_state = WARMING_USRP;
+
+  for(int i=0; i < d_warm_msgs; i++)
+    build_and_send_ping();
+}
+
+void
+test_usrp_inband_ping::enter_pinging()
+{
+  d_state = PINGING;
+  
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_PING] Running ping tests\n";
+
+}
+
+// Pings are sent over the TX channel using the signal 'cmd-to-control-channel'
+// to the USRP server.  Within this message there can be infinite subpackets
+// stored as a list (the second parameter) and sent.  The only subpacket we send
+// is a ping, interpreted by the 'op-ping-fixed' signal.
+void
+test_usrp_inband_ping::build_and_send_ping()
+{
+  
+  d_tx->send(s_cmd_to_control_channel,    // USRP server signal
+             pmt_list2(PMT_NIL,           // invocation handle 
+                       pmt_list1(pmt_list3(s_op_ping_fixed, 
+                                           pmt_from_long(0), 
+                                           pmt_from_long(0)))));
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_PING] Ping!!" << std::endl;
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_ping);
diff --git a/usrp/host/apps/test_usrp_inband_registers.cc b/usrp/host/apps/test_usrp_inband_registers.cc
new file mode 100644 (file)
index 0000000..922b621
--- /dev/null
@@ -0,0 +1,436 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+// Include the symbols needed for communication with USRP server
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+
+static bool verbose = true;
+
+class test_usrp_inband_registers : public mb_mblock
+{
+
+  mb_port_sptr  d_tx;   // Ports connected to the USRP server
+  mb_port_sptr  d_rx;
+  mb_port_sptr  d_cs;
+
+  pmt_t   d_tx_chan;    // Returned channel from TX allocation
+  pmt_t   d_rx_chan;    // Returned channel from RX allocation
+
+  pmt_t   d_which_usrp; // The USRP to use for the test
+
+  long    d_warm_msgs;  // The number of messages to 'warm' the USRP
+  long    d_warm_recvd; // The number of msgs received in the 'warm' state
+
+  // Keep track of current state
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNELS,
+    WRITE_REGISTER,
+    READ_REGISTER,
+    CLOSING_CHANNELS,
+    CLOSING_USRP,
+  };
+  state_t d_state;
+
+ public:
+  test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_inband_registers();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void opening_usrp();
+  void allocating_channels();
+  void write_register();
+  void read_register();
+  void closing_channels();
+  void closing_usrp();
+  void enter_receiving();
+  void build_and_send_ping();
+};
+
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_inband_registers", PMT_F, &result);
+}
+
+
+test_usrp_inband_registers::test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+  d_tx_chan(PMT_NIL),
+  d_rx_chan(PMT_NIL),
+  d_which_usrp(pmt_from_long(0)),
+  d_state(INIT)
+{
+  
+  // A dictionary is used to pass parameters to the USRP
+  pmt_t usrp_dict = pmt_make_dict();
+
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("boe2.rbf"));
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Create an instance of USRP server and connect ports
+  define_component("server", "usrp_server", usrp_dict);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+}
+
+test_usrp_inband_registers::~test_usrp_inband_registers()
+{
+}
+
+void
+test_usrp_inband_registers::initial_transition()
+{
+  opening_usrp();
+}
+
+// Handle message reads all incoming messages from USRP server which will be
+// initialization and ping responses.  We perform actions based on the current
+// state and the event (ie, ping response)
+void
+test_usrp_inband_registers::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t data = msg->data();
+  pmt_t port_id = msg->port_id();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+
+  // Dispatch based on state
+  switch(d_state) {
+
+    //----------------------------- OPENING_USRP ----------------------------//
+    // We only expect a response from opening the USRP which should be succesful
+    // or failed.
+    case OPENING_USRP:
+      
+      if(pmt_eq(event, s_response_open)) {
+
+        status = pmt_nth(1, data);          // failed/succes
+        
+        if(pmt_eq(status, PMT_T)) {
+          allocating_channels();
+          return;
+        }
+        else {
+          error_msg = "failed to open usrp:";
+          goto bail;
+        }
+
+      }
+
+      goto unhandled;   // all other messages not handled in this state
+      
+    
+    //----------------------- ALLOCATING CHANNELS --------------------//
+    // When allocating channels, we need to wait for 2 responses from
+    // USRP server: one for TX and one for RX.  Both are initialized to
+    // NIL so we know to continue to the next state once both are set.
+    case ALLOCATING_CHANNELS:
+
+      // A TX allocation response
+      if(pmt_eq(event, s_response_allocate_channel)
+          && pmt_eq(d_tx->port_symbol(), port_id)) 
+      {
+        status = pmt_nth(1, data);
+        
+        // If successful response, extract the channel
+        if(pmt_eq(status, PMT_T)) {
+          
+          d_tx_chan = pmt_nth(2, data);
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
+                      << " on channel " << d_tx_chan << std::endl;
+
+          // If the RX has also been allocated already, we can continue
+          if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
+            enter_receiving();
+            write_register();
+          }
+
+          return;
+        }
+        else {  // TX allocation failed
+          error_msg = "failed to allocate TX channel:";
+          goto bail;
+        }
+      }
+      
+      // A RX allocation response
+      if(pmt_eq(event, s_response_allocate_channel)
+          && pmt_eq(d_rx->port_symbol(), port_id)) 
+      {
+        status = pmt_nth(1, data);
+        
+        // If successful response, extract the channel
+        if(pmt_eq(status, PMT_T)) {
+          
+          d_rx_chan = pmt_nth(2, data);
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
+                      << " on channel " << d_rx_chan << std::endl;
+
+          // If the TX has also been allocated already, we can continue
+          if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
+            enter_receiving();
+            write_register();
+          }
+
+          return;
+        }
+        else {  // RX allocation failed
+          error_msg = "failed to allocate RX channel:";
+          goto bail;
+        }
+      }
+
+      goto unhandled;
+
+    //-------------------------- WRITE REGISTER ----------------------------//
+    // In the write register state, we do not expect to receive any messages
+    // since the write does not directly generate a response until the USRP
+    // responds.
+    case WRITE_REGISTER:
+      goto unhandled;
+
+    //-------------------------- READ REGISTER ----------------------------//
+    // In the read register state, we only expect a read register response back
+    // that has the value we expect to have in it.  We read the response, ensure
+    // that the read was successful and display the register value.
+    case READ_REGISTER:
+
+      if(pmt_eq(event, s_response_from_control_channel)
+          && pmt_eq(d_tx->port_symbol(), port_id))
+      {
+        status = pmt_nth(1, data);
+
+        // If the read was successful, we extract the subpacket information
+        if(pmt_eq(status, PMT_T)) {
+          
+          pmt_t subp = pmt_nth(2, data);      // subpacket should be the read reg reply
+
+          pmt_t subp_sig  = pmt_nth(0, subp);
+          pmt_t subp_data = pmt_nth(1, subp);
+
+          if(!pmt_eqv(subp_sig, s_op_read_reg_reply)) {
+            error_msg = "received improper subpacket when expecting reg reply.";
+            goto bail;
+          }
+
+          pmt_t rid     = pmt_nth(0, subp_data);
+          pmt_t reg_num = pmt_nth(1, subp_data);
+          pmt_t reg_val = pmt_nth(2, subp_data);
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_REGISTERS] Received read reg reply "
+                      << "("
+                      << "RID: " << rid << ", " 
+                      << "Reg: " << reg_num << ", "
+                      << "Val: " << reg_val
+                      << ")\n";
+          
+          // read_register();  FIX ME STATE TRANSITION
+          return;
+
+        } else {  // bail on unsuccessful write
+          error_msg = "failed to write to register.";
+          goto bail;
+        }
+      }
+      goto unhandled;
+
+    case CLOSING_CHANNELS:
+      goto unhandled;
+
+    case CLOSING_USRP:
+      goto unhandled;
+
+    case INIT:
+      goto unhandled;
+
+  }
+ // An error occured, print it, and shutdown all m-blocks
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ // Received an unhandled message for a specific state
+ unhandled:
+  if(verbose && !pmt_eq(event, s_response_recv_raw_samples))
+    std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+              << "in state "<< d_state << std::endl;
+
+}
+
+
+// Sends a command to USRP server to open up a connection to the
+// specified USRP, which is defaulted to USRP 0 on the system
+void
+test_usrp_inband_registers::opening_usrp()
+{
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_PING] Opening USRP " 
+              << d_which_usrp << std::endl;
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
+  d_state = OPENING_USRP;
+}
+
+// RX and TX channels must be allocated so that the USRP server can
+// properly share bandwidth across multiple USRPs.  No commands will be
+// successful to the USRP through the USRP server on the TX or RX channels until
+// a bandwidth allocation has been received.
+void
+test_usrp_inband_registers::allocating_channels()
+{
+  d_state = ALLOCATING_CHANNELS;
+
+  long capacity = (long) 16e6;
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+}
+
+// After allocating the channels, a write register command will be sent to the
+// USRP.
+void
+test_usrp_inband_registers::write_register()
+{
+  d_state = WRITE_REGISTER;
+
+  long reg = 0;
+
+  d_tx->send(s_cmd_to_control_channel,    // C/S packet
+             pmt_list2(PMT_NIL,           // invoc handle
+                       pmt_list1(
+                            pmt_list2(s_op_write_reg, 
+                                      pmt_list2(
+                                      pmt_from_long(reg), 
+                                      pmt_from_long(0xbeef))))));
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to " 
+              << reg << std::endl;
+
+  read_register();  // immediately transition to read the register
+}
+
+// Temporary: for testing pings
+void
+test_usrp_inband_registers::build_and_send_ping()
+{
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
+                                                    pmt_list2(pmt_from_long(0),
+                                                              pmt_from_long(0))))));
+
+  std::cout << "[TEST_USRP_INBAND_CS] Ping sent" << std::endl;
+}
+
+// After writing to the register, we want to read the value back and ensure that
+// it is the same value that we wrote.
+void
+test_usrp_inband_registers::read_register()
+{
+  d_state = READ_REGISTER;
+
+  long reg = 9;
+
+  d_tx->send(s_cmd_to_control_channel,    // C/S packet
+             pmt_list2(PMT_NIL,           // invoc handle
+                       pmt_list1(
+                            pmt_list2(s_op_read_reg, 
+                                      pmt_list2(
+                                      pmt_from_long(0),   // rid 
+                                      pmt_from_long(reg))))));
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_REGISTERS] Reading from register " 
+              << reg << std::endl;
+}
+
+// Used to enter the receiving state
+void
+test_usrp_inband_registers::enter_receiving()
+{
+  d_rx->send(s_cmd_start_recv_raw_samples,
+             pmt_list2(PMT_F,
+                       d_rx_chan));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_registers);
diff --git a/usrp/host/apps/test_usrp_inband_rx.cc b/usrp/host/apps/test_usrp_inband_rx.cc
new file mode 100644 (file)
index 0000000..4820c2d
--- /dev/null
@@ -0,0 +1,356 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+// Signal set for the USRP server
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
+static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
+static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
+static pmt_t s_cmd_xmit_raw_frame  = pmt_intern("cmd-xmit-raw-frame");
+static pmt_t s_cmd_max_capacity  = pmt_intern("cmd-max-capacity");
+static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
+static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
+static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
+static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
+static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+
+static bool verbose = false;
+
+class test_usrp_rx : public mb_mblock
+{
+  mb_port_sptr         d_rx;
+  mb_port_sptr         d_cs;
+  pmt_t                d_rx_chan;      // returned tx channel handle
+
+  bool d_disk_write;
+
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNEL,
+    RECEIVING,
+    CLOSING_CHANNEL,
+    CLOSING_USRP,
+  };
+
+  state_t      d_state;
+
+  std::ofstream d_ofile;
+
+ public:
+  test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_rx();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void open_usrp();
+  void close_usrp();
+  void allocate_channel();
+  void send_packets();
+  void enter_receiving();
+  void build_and_send_next_frame();
+  void handle_response_recv_raw_samples(pmt_t invocation_handle);
+  void enter_closing_channel();
+};
+
+test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+  d_disk_write(false)
+{ 
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  
+  //bool fake_usrp_p = true;
+  bool fake_usrp_p = false;
+  
+  d_disk_write = true;
+
+  // Test the TX side
+
+  // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
+  pmt_t usrp_dict = pmt_make_dict();
+
+  if(fake_usrp_p)
+    pmt_dict_set(usrp_dict, 
+                 pmt_intern("fake-usrp"),
+                            PMT_T);
+  
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("tmac6.rbf"));
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+
+  define_component("server", "usrp_server", usrp_dict);
+
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+  if(d_disk_write)
+    d_ofile.open("pdump_rx.dat",std::ios::binary|std::ios::out);
+}
+
+test_usrp_rx::~test_usrp_rx()
+{
+  if(d_disk_write)
+    d_ofile.close();
+}
+
+void
+test_usrp_rx::initial_transition()
+{
+  open_usrp();
+}
+
+void
+test_usrp_rx::handle_message(mb_message_sptr msg)
+{
+  pmt_t        event = msg->signal();
+  pmt_t data = msg->data();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+  
+  switch(d_state){
+  case OPENING_USRP:
+    if (pmt_eq(event, s_response_open)){
+      status = pmt_nth(1, data);
+      if (pmt_eq(status, PMT_T)){
+        allocate_channel();
+        return;
+      }
+      else {
+        error_msg = "failed to open usrp:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+    
+  case ALLOCATING_CHANNEL:
+    if (pmt_eq(event, s_response_allocate_channel)){
+      status = pmt_nth(1, data);
+      d_rx_chan = pmt_nth(2, data);
+
+      if (pmt_eq(status, PMT_T)){
+        enter_receiving();
+        return;
+      }
+      else {
+        error_msg = "failed to allocate channel:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case RECEIVING:
+    if (pmt_eq(event, s_response_recv_raw_samples)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        handle_response_recv_raw_samples(data);
+        return;
+      }
+      else {
+        error_msg = "bad response-xmit-raw-frame:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_CHANNEL:
+    if (pmt_eq(event, s_response_deallocate_channel)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        close_usrp();
+        return;
+      }
+      else {
+        error_msg = "failed to deallocate channel:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_USRP:
+    if (pmt_eq(event, s_response_close)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        shutdown_all(PMT_T);
+        return;
+      }
+      else {
+        error_msg = "failed to close USRP:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  default:
+    goto unhandled;
+  }
+  return;
+
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ unhandled:
+  std::cout << "test_usrp_inband_rx: unhandled msg: " << msg
+           << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_rx::open_usrp()
+{
+  pmt_t which_usrp = pmt_from_long(0);
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
+  d_state = OPENING_USRP;
+}
+
+void
+test_usrp_rx::close_usrp()
+{
+  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+  d_state = CLOSING_USRP;
+}
+
+void
+test_usrp_rx::allocate_channel()
+{
+  long capacity = (long) 16e6;
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_state = ALLOCATING_CHANNEL;
+}
+
+void
+test_usrp_rx::enter_receiving()
+{
+  d_state = RECEIVING;
+
+  d_rx->send(s_cmd_start_recv_raw_samples,
+             pmt_list2(PMT_F,
+                       d_rx_chan));
+}
+
+void
+test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t v_samples = pmt_nth(2, data);
+  pmt_t timestamp = pmt_nth(3, data);
+  pmt_t properties = pmt_nth(4, data);
+
+  size_t n_bytes;
+  
+  const char *samples = (const char *) pmt_uniform_vector_elements(v_samples, n_bytes);
+
+  if(d_disk_write)
+    d_ofile.write(samples, n_bytes);
+
+  if(verbose)
+    std::cout << ".";
+
+  if (pmt_is_dict(properties)) {
+    // Read the RSSI
+    if(pmt_t rssi = pmt_dict_ref(properties, 
+                                 pmt_intern("rssi"), 
+                                 PMT_NIL)) {
+      if(!pmt_eqv(rssi, PMT_NIL)) 
+        std::cout << "RSSI: " << rssi << std::endl;
+    }
+  }
+  
+
+}
+
+void
+test_usrp_rx::enter_closing_channel()
+{
+  d_state = CLOSING_CHANNEL;
+  
+  d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_rx);
+
+
+// ----------------------------------------------------------------
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_rx", PMT_F, &result);
+}
diff --git a/usrp/host/apps/test_usrp_inband_timestamps.cc b/usrp/host/apps/test_usrp_inband_timestamps.cc
new file mode 100644 (file)
index 0000000..d48c2a7
--- /dev/null
@@ -0,0 +1,508 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+
+#define NBPING  10
+
+static bool verbose = true;
+bool bskip = false;
+long bstep = 10000;
+long bcurr = 0;
+long incr = 0x500;
+long ptime = 0x000;
+
+class test_usrp_inband_timestamps : public mb_mblock
+{
+  mb_port_sptr         d_tx;
+  mb_port_sptr         d_rx;
+  mb_port_sptr         d_cs;
+  pmt_t                d_tx_chan;      // returned tx channel handle
+  pmt_t                d_rx_chan;      // returned tx channel handle
+
+  struct timeval times[NBPING];
+
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNEL,
+    TRANSMITTING,
+    CLOSING_CHANNEL,
+    CLOSING_USRP,
+  };
+
+  state_t      d_state;
+  long         d_nsamples_to_send;
+  long         d_nsamples_xmitted;
+  long         d_nframes_xmitted;
+  long         d_samples_per_frame;
+  bool         d_done_sending;
+
+  // for generating sine wave output
+  ui_nco<float,float>  d_nco;
+  double               d_amplitude;
+
+ public:
+  test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_inband_timestamps();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void open_usrp();
+  void close_usrp();
+  void allocate_channel();
+  void send_packets();
+  void enter_receiving();
+  void enter_transmitting();
+  void build_and_send_ping();
+  void build_and_send_next_frame();
+  void handle_xmit_response(pmt_t invocation_handle);
+  void enter_closing_channel();
+};
+
+test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_tx_chan(PMT_NIL),
+    d_rx_chan(PMT_NIL),
+    d_state(INIT), d_nsamples_to_send((long) 40e6),
+    d_nsamples_xmitted(0),
+    d_nframes_xmitted(0),
+    //d_samples_per_frame((long)(126)),
+    d_samples_per_frame((long)(126 * 2)),      // non-full packet
+    //d_samples_per_frame((long)(126 * 3.5)),  // non-full packet
+    //d_samples_per_frame((long)(126 * 4)),    // full packet
+    d_done_sending(false),
+    d_amplitude(16384)
+{ 
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Initializing...\n";
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  
+  bool fake_usrp_p = false;
+
+  // Test the TX side
+
+  pmt_t usrp_dict = pmt_make_dict();
+
+  if(fake_usrp_p) {
+    pmt_dict_set(usrp_dict, 
+                 pmt_intern("fake-usrp"),
+                            PMT_T);
+  }
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("tmac5.rbf"));
+
+  define_component("server", "usrp_server", usrp_dict);
+
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+  // initialize NCO
+  double freq = 100e3;
+  int interp = 32;                         // 32 -> 4MS/s
+  double sample_rate = 128e6 / interp; 
+  d_nco.set_freq(2*M_PI * freq/sample_rate);
+
+}
+
+test_usrp_inband_timestamps::~test_usrp_inband_timestamps()
+{
+}
+
+void
+test_usrp_inband_timestamps::initial_transition()
+{
+  open_usrp();
+}
+
+void
+test_usrp_inband_timestamps::handle_message(mb_message_sptr msg)
+{
+  pmt_t        event = msg->signal();
+  pmt_t data = msg->data();
+  pmt_t port_id = msg->port_id();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+  
+  //std::cout << msg << std::endl;
+
+  switch(d_state){
+  case OPENING_USRP:
+    if (pmt_eq(event, s_response_open)){
+      status = pmt_nth(1, data);
+      if (pmt_eq(status, PMT_T)){
+        allocate_channel();
+        return;
+      }
+      else {
+        error_msg = "failed to open usrp:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+    
+  case ALLOCATING_CHANNEL:
+    if (pmt_eq(event, s_response_allocate_channel)){
+
+      if(pmt_eq(d_tx->port_symbol(), port_id)) {
+        status = pmt_nth(1, data);
+        d_tx_chan = pmt_nth(2, data);
+
+        if (pmt_eq(status, PMT_T)){
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
+
+          if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
+            enter_receiving();
+            enter_transmitting();
+          }
+          return;
+        }
+        else {
+          error_msg = "failed to allocate channel:";
+          goto bail;
+        }
+      }
+      
+      if(pmt_eq(d_rx->port_symbol(), port_id)) {
+        status = pmt_nth(1, data);
+        d_rx_chan = pmt_nth(2, data);
+
+        if (pmt_eq(status, PMT_T)){
+
+          if(verbose)
+            std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Received allocation for TX\n";
+          
+          if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
+            enter_receiving();
+            enter_transmitting();
+          }
+          return;
+        }
+        else {
+          error_msg = "failed to allocate channel:";
+          goto bail;
+        }
+      }
+    }
+    goto unhandled;
+
+  case TRANSMITTING:
+    if (pmt_eq(event, s_response_xmit_raw_frame)){
+      handle = pmt_nth(0, data);
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        handle_xmit_response(handle);
+        return;
+      }
+      else {
+        error_msg = "bad response-xmit-raw-frame:";
+        goto bail;
+      }
+    }
+
+    if (pmt_eq(event, s_response_from_control_channel)) {
+      std::cout << "ping response!\n";
+    }
+    goto unhandled;
+
+  case CLOSING_CHANNEL:
+    if (pmt_eq(event, s_response_deallocate_channel)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        close_usrp();
+        return;
+      }
+      else {
+        error_msg = "failed to deallocate channel:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_USRP:
+    if (pmt_eq(event, s_response_close)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+        shutdown_all(PMT_T);
+        return;
+      }
+      else {
+        error_msg = "failed to close USRP:";
+        goto bail;
+      }
+    }
+    goto unhandled;
+
+  default:
+    goto unhandled;
+  }
+  return;
+
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ unhandled:
+  if(verbose && 0)
+    std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+              << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_inband_timestamps::open_usrp()
+{
+  pmt_t which_usrp = pmt_from_long(0);
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
+  d_state = OPENING_USRP;
+}
+
+void
+test_usrp_inband_timestamps::close_usrp()
+{
+  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+  d_state = CLOSING_USRP;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing USRP\n";
+}
+
+void
+test_usrp_inband_timestamps::allocate_channel()
+{
+  long capacity = (long) 16e6;
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_state = ALLOCATING_CHANNEL;
+}
+
+void
+test_usrp_inband_timestamps::enter_receiving()
+{
+  d_rx->send(s_cmd_start_recv_raw_samples,
+             pmt_list2(PMT_F,
+                       d_rx_chan));
+}
+
+void
+test_usrp_inband_timestamps::enter_transmitting()
+{
+  d_state = TRANSMITTING;
+  d_nsamples_xmitted = 0;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Beginning transmission\n";
+
+  sleep(1);
+
+  build_and_send_next_frame();
+  build_and_send_next_frame();
+  build_and_send_next_frame();
+  build_and_send_next_frame();
+
+}
+
+void
+test_usrp_inband_timestamps::build_and_send_ping()
+{
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
+                                                    pmt_list2(pmt_from_long(0),
+                                                              pmt_from_long(0))))));
+  if(verbose && 0)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Ping sent" << std::endl;
+}
+
+void
+test_usrp_inband_timestamps::build_and_send_next_frame()
+{
+  // allocate the uniform vector for the samples
+  // FIXME perhaps hold on to this between calls
+
+#if 0
+  long nsamples_this_frame =
+    std::min(d_nsamples_to_send - d_nsamples_xmitted,
+            d_samples_per_frame);
+#else
+  long nsamples_this_frame = d_samples_per_frame;
+#endif
+
+  if (nsamples_this_frame == 0){
+    d_done_sending = true;
+    return;
+  }
+    
+
+  size_t nshorts = 2 * nsamples_this_frame;    // 16-bit I & Q
+  pmt_t uvec = pmt_make_s16vector(nshorts, 0);
+  size_t ignore;
+  int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
+
+  // fill in the complex sinusoid
+
+  for (int i = 0; i < nsamples_this_frame; i++){
+
+    if (1){
+      gr_complex s;
+      d_nco.sincos(&s, 1, d_amplitude);
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+    else {
+      gr_complex s(d_amplitude, d_amplitude);
+
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+  }
+
+  pmt_t timestamp;
+
+  if(bskip) {
+    timestamp = pmt_from_long(0x0);    // throw away  
+    bcurr++;
+    if(bcurr == bstep) {
+      bskip = false;
+      bcurr = 0;
+    }
+  } else {
+    timestamp = pmt_from_long(0xffffffff);     // NOW
+    timestamp = pmt_from_long(ptime);
+    ptime += incr;
+    bcurr++;
+    if(bcurr == bstep) {
+      //bskip = true;
+      bcurr = 0;
+    }
+  }
+
+  std::cout << bskip << " -- " << bcurr << std::endl;
+
+  d_tx->send(s_cmd_xmit_raw_frame,
+            pmt_list4(pmt_from_long(d_nframes_xmitted),  // invocation-handle
+                      d_tx_chan,                         // channel
+                      uvec,                              // the samples
+                      timestamp));
+
+  d_nsamples_xmitted += nsamples_this_frame;
+  d_nframes_xmitted++;
+
+  if(verbose && 0)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Transmitted frame\n";
+  
+  //build_and_send_next_frame();
+}
+
+
+void
+test_usrp_inband_timestamps::handle_xmit_response(pmt_t handle)
+{
+  if (d_done_sending &&
+      pmt_to_long(handle) == (d_nframes_xmitted - 1)){
+    // We're done sending and have received all responses
+    enter_closing_channel();
+  }
+
+  build_and_send_next_frame();
+  //build_and_send_ping();
+}
+
+void
+test_usrp_inband_timestamps::enter_closing_channel()
+{
+  d_state = CLOSING_CHANNEL;
+  
+  d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing channel\n";
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_timestamps);
+
+
+// ----------------------------------------------------------------
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_inband_timestamps", PMT_F, &result);
+}
diff --git a/usrp/host/apps/test_usrp_inband_tx.cc b/usrp/host/apps/test_usrp_inband_tx.cc
new file mode 100644 (file)
index 0000000..18d3621
--- /dev/null
@@ -0,0 +1,409 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+
+static bool verbose = false;
+
+class test_usrp_tx : public mb_mblock
+{
+  mb_port_sptr         d_tx;
+  mb_port_sptr         d_cs;
+  pmt_t                d_tx_chan;      // returned tx channel handle
+
+  enum state_t {
+    INIT,
+    OPENING_USRP,
+    ALLOCATING_CHANNEL,
+    TRANSMITTING,
+    CLOSING_CHANNEL,
+    CLOSING_USRP,
+  };
+
+  state_t      d_state;
+  long         d_nsamples_to_send;
+  long         d_nsamples_xmitted;
+  long         d_nframes_xmitted;
+  long         d_samples_per_frame;
+  bool         d_done_sending;
+
+  // for generating sine wave output
+  ui_nco<float,float>  d_nco;
+  double               d_amplitude;
+
+ public:
+  test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_tx();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void open_usrp();
+  void close_usrp();
+  void allocate_channel();
+  void send_packets();
+  void enter_transmitting();
+  void build_and_send_next_frame();
+  void handle_xmit_response(pmt_t invocation_handle);
+  void enter_closing_channel();
+};
+
+test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_state(INIT), d_nsamples_to_send((long) 40e6),
+    d_nsamples_xmitted(0),
+    d_nframes_xmitted(0),
+    //d_samples_per_frame((long)(126)),
+    //d_samples_per_frame((long)(126 * 3.5)),  // non-full packet
+    d_samples_per_frame((long)(126 * 4)),      // full packet
+    d_done_sending(false),
+    d_amplitude(16384)
+{ 
+  // std::cout << "[TEST_USRP_TX] Initializing...\n";
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  
+  //bool fake_usrp_p = true;
+  bool fake_usrp_p = false;
+
+  // Test the TX side
+
+  pmt_t usrp_dict = pmt_make_dict();
+
+  if(fake_usrp_p) {
+    pmt_dict_set(usrp_dict, 
+                 pmt_intern("fake-usrp"),
+                            PMT_T);
+  }
+  
+  // Specify the RBF to use
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rbf"),
+               pmt_intern("boe3.rbf"));
+
+  // Set TX and RX interpolations
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-tx"),
+               pmt_from_long(128));
+
+  pmt_dict_set(usrp_dict,
+               pmt_intern("interp-rx"),
+               pmt_from_long(16));
+  
+  pmt_dict_set(usrp_dict,
+               pmt_intern("rf-freq"),
+               pmt_from_long(10e6));
+
+  define_component("server", "usrp_server", usrp_dict);
+
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "cs", "server", "cs");
+
+  // initialize NCO
+  double freq = 100e3;
+  int interp = 32;                         // 32 -> 4MS/s
+  double sample_rate = 128e6 / interp; 
+  d_nco.set_freq(2*M_PI * freq/sample_rate);
+
+  // FIXME need to somehow set the interp rate in the USRP.
+  // for now, we'll have the low-level code hardwire it.
+}
+
+test_usrp_tx::~test_usrp_tx()
+{
+}
+
+void
+test_usrp_tx::initial_transition()
+{
+  open_usrp();
+}
+
+void
+test_usrp_tx::handle_message(mb_message_sptr msg)
+{
+  pmt_t        event = msg->signal();
+  pmt_t data = msg->data();
+
+  pmt_t handle = PMT_F;
+  pmt_t status = PMT_F;
+  std::string error_msg;
+  
+  //std::cout << msg << std::endl;
+
+  switch(d_state){
+  case OPENING_USRP:
+    if (pmt_eq(event, s_response_open)){
+      status = pmt_nth(1, data);
+      if (pmt_eq(status, PMT_T)){
+       allocate_channel();
+       return;
+      }
+      else {
+       error_msg = "failed to open usrp:";
+       goto bail;
+      }
+    }
+    goto unhandled;
+    
+  case ALLOCATING_CHANNEL:
+    if (pmt_eq(event, s_response_allocate_channel)){
+      status = pmt_nth(1, data);
+      d_tx_chan = pmt_nth(2, data);
+
+      if (pmt_eq(status, PMT_T)){
+       enter_transmitting();
+       return;
+      }
+      else {
+       error_msg = "failed to allocate channel:";
+       goto bail;
+      }
+    }
+    goto unhandled;
+
+  case TRANSMITTING:
+    if (pmt_eq(event, s_response_xmit_raw_frame)){
+      handle = pmt_nth(0, data);
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+       handle_xmit_response(handle);
+       return;
+      }
+      else {
+       error_msg = "bad response-xmit-raw-frame:";
+       goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_CHANNEL:
+    if (pmt_eq(event, s_response_deallocate_channel)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+       close_usrp();
+       return;
+      }
+      else {
+       error_msg = "failed to deallocate channel:";
+       goto bail;
+      }
+    }
+    goto unhandled;
+
+  case CLOSING_USRP:
+    if (pmt_eq(event, s_response_close)){
+      status = pmt_nth(1, data);
+
+      if (pmt_eq(status, PMT_T)){
+       shutdown_all(PMT_T);
+       return;
+      }
+      else {
+       error_msg = "failed to close USRP:";
+       goto bail;
+      }
+    }
+    goto unhandled;
+
+  default:
+    goto unhandled;
+  }
+  return;
+
+ bail:
+  std::cerr << error_msg << data
+           << "status = " << status << std::endl;
+  shutdown_all(PMT_F);
+  return;
+
+ unhandled:
+  std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+           << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_tx::open_usrp()
+{
+  pmt_t which_usrp = pmt_from_long(0);
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
+  d_state = OPENING_USRP;
+}
+
+void
+test_usrp_tx::close_usrp()
+{
+  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+  d_state = CLOSING_USRP;
+}
+
+void
+test_usrp_tx::allocate_channel()
+{
+  long capacity = (long) 16e6;
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+  d_state = ALLOCATING_CHANNEL;
+}
+
+void
+test_usrp_tx::enter_transmitting()
+{
+  d_state = TRANSMITTING;
+  d_nsamples_xmitted = 0;
+  
+  // FIXME: carrier sense hack
+//  d_tx->send(s_cmd_to_control_channel,    // C/S packet
+//             pmt_list2(PMT_NIL,           // invoc handle
+//                       pmt_list1(
+//                            pmt_list2(s_op_write_reg, 
+//                                      pmt_list2(
+//                                      pmt_from_long(1), 
+//                                      pmt_from_long(0))))));
+
+  build_and_send_next_frame(); // fire off 4 to start pipeline
+  build_and_send_next_frame();
+  build_and_send_next_frame();
+  build_and_send_next_frame();
+}
+
+void
+test_usrp_tx::build_and_send_next_frame()
+{
+  // allocate the uniform vector for the samples
+  // FIXME perhaps hold on to this between calls
+
+#if 1
+  long nsamples_this_frame =
+    std::min(d_nsamples_to_send - d_nsamples_xmitted,
+            d_samples_per_frame);
+#else
+  long nsamples_this_frame = d_samples_per_frame;
+#endif
+
+  if (nsamples_this_frame == 0){
+    d_done_sending = true;
+    return;
+  }
+    
+
+  size_t nshorts = 2 * nsamples_this_frame;    // 16-bit I & Q
+  pmt_t uvec = pmt_make_s16vector(nshorts, 0);
+  size_t ignore;
+  int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
+
+  // fill in the complex sinusoid
+
+  for (int i = 0; i < nsamples_this_frame; i++){
+
+    if (1){
+      gr_complex s;
+      d_nco.sincos(&s, 1, d_amplitude);
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+    else {
+      gr_complex s(d_amplitude, d_amplitude);
+
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
+    }
+  }
+
+  pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
+  d_tx->send(s_cmd_xmit_raw_frame,
+            pmt_list4(pmt_from_long(d_nframes_xmitted),  // invocation-handle
+                      d_tx_chan,                         // channel
+                      uvec,                              // the samples
+                      timestamp));
+
+  d_nsamples_xmitted += nsamples_this_frame;
+  d_nframes_xmitted++;
+
+  if(verbose)
+    std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
+}
+
+
+void
+test_usrp_tx::handle_xmit_response(pmt_t handle)
+{
+  if (d_done_sending &&
+      pmt_to_long(handle) == (d_nframes_xmitted - 1)){
+    // We're done sending and have received all responses
+    enter_closing_channel();
+  }
+
+  build_and_send_next_frame();
+}
+
+void
+test_usrp_tx::enter_closing_channel()
+{
+  d_state = CLOSING_CHANNEL;
+  
+  d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_tx);
+
+
+// ----------------------------------------------------------------
+
+int
+main (int argc, char **argv)
+{
+  // handle any command line args here
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "test_usrp_tx", PMT_F, &result);
+}
diff --git a/usrp/host/apps/ui_nco.h b/usrp/host/apps/ui_nco.h
new file mode 100644 (file)
index 0000000..e6d7814
--- /dev/null
@@ -0,0 +1,202 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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_UI_NCO_H
+#define INCLUDED_UI_NCO_H
+
+
+#include <vector>
+#include <ui_sincos.h>
+#include <cmath>
+
+#include <complex>
+typedef std::complex<float>                    gr_complex;
+
+
+/*!
+ * \brief base class template for Numerically Controlled Oscillator (NCO)
+ */
+
+
+//FIXME  Eventually generalize this to fixed point
+
+template<class o_type, class i_type> 
+class ui_nco {
+public:
+  ui_nco () : phase (0), phase_inc(0) {}
+
+  virtual ~ui_nco () {}
+
+  // radians
+  void set_phase (double angle) {
+    phase = angle;
+  }
+
+  void adjust_phase (double delta_phase) {
+    phase += delta_phase;
+  }
+
+
+  // angle_rate is in radians / step
+  void set_freq (double angle_rate){
+    phase_inc = angle_rate;
+  }
+
+  // angle_rate is a delta in radians / step
+  void adjust_freq (double delta_angle_rate)
+  {
+    phase_inc += delta_angle_rate;
+  }
+
+  // increment current phase angle
+
+  void step () 
+  { 
+    phase += phase_inc; 
+    if (fabs (phase) > M_PI){
+      
+      while (phase > M_PI)
+       phase -= 2*M_PI;
+
+      while (phase < -M_PI)
+       phase += 2*M_PI;
+    }
+  }
+
+  void step (int n)
+  {
+    phase += phase_inc * n;
+    if (fabs (phase) > M_PI){
+      
+      while (phase > M_PI)
+       phase -= 2*M_PI;
+
+      while (phase < -M_PI)
+       phase += 2*M_PI;
+    }
+  }
+
+  // units are radians / step
+  double get_phase () const { return phase; }
+  double get_freq () const { return phase_inc; }
+
+  // compute sin and cos for current phase angle
+  void sincos (float *sinx, float *cosx) const;
+
+  // compute cos or sin for current phase angle
+  float cos () const { return std::cos (phase); }
+  float sin () const { return std::sin (phase); }
+
+  // compute a block at a time
+  void sin (float *output, int noutput_items, double ampl = 1.0);
+  void cos (float *output, int noutput_items, double ampl = 1.0);
+  void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
+  void sin (short *output, int noutput_items, double ampl = 1.0);
+  void cos (short *output, int noutput_items, double ampl = 1.0);
+  void sin (int *output, int noutput_items, double ampl = 1.0);
+  void cos (int *output, int noutput_items, double ampl = 1.0);
+
+protected:
+  double phase;
+  double phase_inc;
+};
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
+{
+  ui_sincosf (phase, sinx, cosx);
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (float)(sin () * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (float)(cos () * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (short)(sin() * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (short)(cos () * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (int)(sin () * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    output[i] = (int)(cos () * ampl);
+    step ();
+  }
+}
+
+template<class o_type, class i_type> 
+void
+ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
+{
+  for (int i = 0; i < noutput_items; i++){
+    float cosx, sinx;
+    sincos (&sinx, &cosx);
+    output[i] = gr_complex(cosx * ampl, sinx * ampl);
+    step ();
+  }
+}
+
+#endif /* INCLUDED_UI_NCO_H */
+
diff --git a/usrp/host/apps/ui_sincos.c b/usrp/host/apps/ui_sincos.c
new file mode 100644 (file)
index 0000000..36ca89c
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE            // ask for GNU extensions if available
+
+#include <ui_sincos.h>
+#include <math.h>
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOS)
+
+void
+ui_sincos (double x, double *sinx, double *cosx)
+{
+  sincos (x, sinx, cosx);
+}
+
+#else
+
+void
+ui_sincos (double x, double *sinx, double *cosx)
+{
+  *sinx = sin (x);
+  *cosx = cos (x);
+}
+
+#endif
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOSF)
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+  sincosf (x, sinx, cosx);
+}
+
+#elif defined (HAVE_SINF) && defined (HAVE_COSF)
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+  *sinx = sinf (x);
+  *cosx = cosf (x);
+}
+
+#else
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+  *sinx = sin (x);
+  *cosx = cos (x);
+}
+
+#endif
diff --git a/usrp/host/apps/ui_sincos.h b/usrp/host/apps/ui_sincos.h
new file mode 100644 (file)
index 0000000..d2d6e4b
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004 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_UI_SINCOS_H
+#define INCLUDED_UI_SINCOS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+// compute sine and cosine at the same time
+
+void ui_sincos (double x, double *sin, double *cos);
+void ui_sincosf (float x, float *sin, float *cos);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* INCLUDED_UI_SINCOS_H */
index 017c5c48980babe0a4f9734007fc40719eaa4f26..76e769fbe8611d4fb6c6b7db1d9fdc9dd5da56d7 100644 (file)
@@ -22,46 +22,74 @@ include $(top_srcdir)/Makefile.common
 
 INCLUDES =     \
        $(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
-       $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+       $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES) \
+       -I$(srcdir)/../../apps
 
 TESTS = test_inband
 
 EXTRA_DIST =                           \
-       usrp_server.mbh                 
+       usrp_server.mbh                 \
+       usrp_interface.mbh 
+
 
 lib_LTLIBRARIES =                      \
        libusrp_inband.la               \
-       libusrp_inband-qa.la                    
+       libusrp_inband-qa.la
 
 
 # ------------------------------------------------------------------------
 # Build the inband library
 
 BUILT_SOURCES =                                \
-       usrp_server_mbh.cc
+       usrp_server_mbh.cc              \
+       usrp_interface_mbh.cc 
 
 usrp_server_mbh.cc : usrp_server.mbh
        $(COMPILE_MBH) $(srcdir)/usrp_server.mbh usrp_server_mbh.cc
 
+usrp_interface_mbh.cc : usrp_interface.mbh
+       $(COMPILE_MBH) usrp_interface.mbh usrp_interface_mbh.cc
+
 libusrp_inband_la_SOURCES =            \
        $(BUILT_SOURCES)                \
-       usrp_server.cc
+       ../../apps/ui_sincos.c          \
+       usrp_inband_usb_packet.cc       \
+       usrp_rx.cc                      \
+       usrp_rx_stub.cc                 \
+       usrp_server.cc                  \
+       usrp_tx.cc                      \
+       usrp_tx_stub.cc                 \
+       usrp_usb_interface.cc           
 
 libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
 
 libusrp_inband_la_LIBADD =             \
        $(MBLOCK_LA)                    \
+       ../legacy/libusrp.la            \
        -lstdc++
 
-
 include_HEADERS =                      \
-       usrp_server.h                   
+       usrp_inband_usb_packet.h        \
+       usrp_rx.h                       \
+       usrp_rx_stub.h                  \
+       usrp_server.h                   \
+       usrp_tx.h                       \
+       usrp_tx_stub.h                  \
+       usrp_usb_interface.h            
 
 noinst_HEADERS =                       \
+       fake_usrp.h                     \
        qa_inband.h                     \
        qa_inband_packet_prims.h        \
        qa_inband_usrp_server.h         \
-       usrp_inband_usb_packet.h        
+       symbols_usrp_channel.h          \
+       symbols_usrp_interface_cs.h     \
+       symbols_usrp_low_level_cs.h     \
+       symbols_usrp_rx.h               \
+       symbols_usrp_rx_cs.h            \
+       symbols_usrp_server_cs.h        \
+       symbols_usrp_tx.h               \
+       symbols_usrp_tx_cs.h            
 
 
 # ------------------------------------------------------------------------
@@ -79,17 +107,22 @@ libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
 libusrp_inband_qa_la_LIBADD =          \
        libusrp_inband.la               \
        $(CPPUNIT_LIBS)                 \
+       ../legacy/libusrp.la            \
+       libusrp_inband.la               \
        -lstdc++
 
 # ------------------------------------------------------------------------
 
 noinst_PROGRAMS =                      \
-       test_inband
+       test_inband                     \
+       test_usrp_inband
 
 test_inband_SOURCES = test_inband.cc
 test_inband_LDADD   = libusrp_inband-qa.la
 
+test_usrp_inband_SOURCES = test_usrp_inband.cc
+test_usrp_inband_LDADD = libusrp_inband-qa.la
+
 
 MOSTLYCLEANFILES = \
        $(BUILT_SOURCES) *~ *.pyc
-
diff --git a/usrp/host/lib/inband/fake_usrp.cc b/usrp/host/lib/inband/fake_usrp.cc
new file mode 100644 (file)
index 0000000..8a66d5c
--- /dev/null
@@ -0,0 +1,135 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <fake_usrp.h>
+#include <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <mb_class_registry.h>
+#include <vector>
+
+typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
+
+fake_usrp::fake_usrp()
+{
+  std::cout << "[fake_usrp] Initializing...\n";
+}
+
+fake_usrp::~fake_usrp() {}
+
+long
+fake_usrp::write_bus(transport_pkt *pkts, long n_bytes)
+{
+  std::cout << "[fake_usrp] Bytes over bus: " << n_bytes << "\n";
+
+  // I'm assuming that a control packet cannot exist in a burst of data packets,
+  // therefore i read only the first packet's channel in the current burst
+  if(pkts[0].chan() == 0x1f) {
+    return control_block(pkts, n_bytes);
+  } else {
+    return data_block(pkts, n_bytes);
+  }
+
+}
+
+long
+fake_usrp::data_block(transport_pkt *pkts, long n_bytes)
+{
+  std::cout << "[fake_usrp] Entering data block\n";
+
+  // Infer the number of packets from the byte count to do logical tests
+  long n_pkts = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
+  
+  std::cout << "[fake_usrp] Number of packets: " << n_pkts << "\n";
+
+  // The first packet should have the start of burst, and the last packet should have end of burst
+  if(pkts[0].start_of_burst() && pkts[n_pkts-1].end_of_burst()) {
+    std::cout << "[fake_usrp] Correct burst flags set\n";
+  } else {
+    std::cout << "[fake_usrp] Incorrect burst flags set!\n";
+    return 0;
+  }
+
+  // All other flags should be set to 0 (e.g., overrun should not be set yet) on ALL packets
+  for(int i=0; i < n_pkts; i++) {
+    if(pkts[i].overrun()) {
+      std::cout << "[fake_usrp] Incorrect set of overrun flag on transmit\n";
+      return 0;
+    } else if(pkts[i].underrun()) {
+      std::cout << "[fake_usrp] Incorrect set of underrun flag on transmit\n";
+      return 0;
+    } else if(pkts[i].dropped()) {
+      std::cout << "[fake_usrp] Incorrect set of drop flag on transmit\n";
+      return 0;
+    } 
+  }
+  std::cout << "[fake_usrp] Correct overrun, underrun, and drop flags on transmit (initialized to 0)\n";
+  
+  // The first packet should have a timestamp, other packets should have "NOW"
+  if(pkts[0].timestamp() != 0xffffffff) {
+    std::cout << "[fake_usrp] Correct timestamp on first packet\n";
+  } else {
+    std::cout << "[fake_usrp] Initial packet should not have the 0xffffffff timestamp\n";
+    return 0;
+  }
+
+  // Check that all of the other packets include the NOW timestamp
+  int check_stamps=1;
+  for(int i=1; i < n_pkts; i++)           // start at 1 to skip the first packet
+    if(pkts[i].timestamp() != 0xffffffff) 
+      check_stamps=0;
+
+  if(check_stamps) {
+    std::cout << "[fake_usrp] Correct NOW timestamps (0xffffffff) on intermediate burst packets\n";
+  } else {
+    std::cout << "[fake_usrp] Incorrect timestamps on intermediate burst packets\n";
+    return 0;
+  }
+
+  // Since we are being transparent about samples, we do not ensure the payload is correct, however
+  // it should be the case that if there are >1 packets, all packets except the last packet should
+  // have a full payload size
+  if(n_pkts > 1) {
+    int check_size=1;
+    for(int i=0; i < n_pkts-1; i++)
+      if(pkts[i].payload_len() != transport_pkt::max_payload())
+        check_size=0;
+
+    if(check_size) {
+      std::cout << "[fake_usrp] Correct payload size sanity check on packets\n";
+    } else {
+      std::cout << "[fake_usrp] Failed payload size sanity check\n";
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+long
+fake_usrp::control_block(transport_pkt *pkts, long n_bytes)
+{
+  std::cout << "[fake_usrp] Entering control block\n";
+
+  return 1;
+}
diff --git a/usrp/host/lib/inband/fake_usrp.h b/usrp/host/lib/inband/fake_usrp.h
new file mode 100644 (file)
index 0000000..818c5a5
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_FAKE_USRP_H
+#define INCLUDED_FAKE_USRP_H
+
+#include <usrp_inband_usb_packet.h>
+typedef usrp_inband_usb_packet transport_pkt;
+
+/*!
+ * \brief Implements a fake USRP for testing without hardware
+ */
+class fake_usrp
+{
+ public:
+  fake_usrp();
+  ~fake_usrp();
+  long write_bus(transport_pkt *pkts, long n_bytes);
+
+ protected:
+  long data_block(transport_pkt *pkts, long n_bytes);
+  long control_block(transport_pkt *pkts, long n_bytes);
+};
+
+#endif /* INCLUDED_FAKE_USRP_H */
+
index 1e22722d2444667389dc4601d8a624fe6361207f..2ee6463847b8f8b5b772ef6ba5c65ee6b1f6979c 100755 (executable)
@@ -70,7 +70,7 @@ def gen_all_valid_packet_lengths_2_channels(output_file):
     lengths = gen_shuffled_lengths()
     npkts = len(lengths)                # number of packets we'll generator on each stream
     pkt_gen_0 = packet_sequence_generator(0, lengths)
-    pkt_gen_1 = packet_sequence_generator(1, gen_shuffled_lengths())
+    pkt_gen_1 = packet_sequence_generator(0x1f, gen_shuffled_lengths())
     pkt_gen = (pkt_gen_0, pkt_gen_1)
     
     which_gen = (npkts * [0]) + (npkts * [1])
@@ -83,5 +83,6 @@ def gen_all_valid_packet_lengths_2_channels(output_file):
     assert pkt_gen_1.next() == 16002    # 2*sum(1, 2, ..., 126) == 126 * 127
 
 if __name__ == '__main__':
+    random.seed(0)
     gen_all_valid_packet_lengths_1_channel(open("all_valid_packet_lengths_1_channel.dat", "w"))
     gen_all_valid_packet_lengths_2_channels(open("all_valid_packet_lengths_2_channels.dat", "w"))
index 324d9ee1179152aa4f5e6652b60c9437cc2cb542..b01e74e002cdbe9b0afc9b88a5620f30da72174a 100644 (file)
@@ -23,6 +23,7 @@
 #include <config.h>
 #endif
 
+#include <usrp_inband_usb_packet.h>
 #include <qa_inband_usrp_server.h>
 #include <cppunit/TestAssert.h>
 #include <stdio.h>
 #include <mb_class_registry.h>
 #include <vector>
 #include <iostream>
+#include <pmt.h>
 
-static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
-static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
-static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
-static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
-static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
-static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
-static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
-static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
-static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
-static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
-static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
-static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
-static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
-static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
 
+typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
+
+static bool verbose = false;
 
 // ----------------------------------------------------------------------------------------------
 
@@ -82,16 +78,20 @@ qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name
   : mb_mblock(runtime, instance_name, user_arg)
 { 
   d_nrecvd=0;
-  d_nmsgs_to_recv = 7;
+  d_nmsgs_to_recv = 6;
   d_nstatus=0;
-  d_nstatus_to_recv = 3;
+  d_nstatus_to_recv = 50;
   
   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
 
   // Test the TX side
-  define_component("server", "usrp_server", PMT_F);
+  define_component("server", "usrp_server", usrp_server_dict);
   connect("self", "tx0", "server", "tx0");
   connect("self", "rx0", "server", "rx0");
   connect("self", "cs", "server", "cs");
@@ -103,42 +103,86 @@ qa_alloc_top::~qa_alloc_top(){}
 void
 qa_alloc_top::initial_transition()
 {
+  // Allocations should fail before open
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel, 
+                                 s_err_usrp_not_opened), 
+                       pmt_from_long(1)));
+
+  d_rx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel,
+                                 s_err_usrp_not_opened), 
+                       pmt_from_long(1)));
+
   // Retrieve information about the USRP, then run tests
-  d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
-  d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
-  d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open, PMT_T), 
+             pmt_from_long(0)));
+
+  d_cs->send(s_cmd_max_capacity, 
+             pmt_list1(pmt_list2(s_response_max_capacity, PMT_T)));
+  
+  d_cs->send(s_cmd_ntx_chan, 
+             pmt_list1(pmt_list2(s_response_ntx_chan, PMT_T)));
+  
+  d_cs->send(s_cmd_nrx_chan, 
+             pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
 }
 
 void
 qa_alloc_top::run_tests()
 {
-  std::cout << "[qa_alloc_top] Starting tests...\n";
+  if(verbose)
+    std::cout << "[qa_alloc_top] Starting tests...\n";
+
   // should be able to allocate 1 byte
-  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(PMT_T, pmt_from_long(1)));
   
   // should not be able to allocate max capacity after 100 bytes were allocated
-  d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));  
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(s_err_requested_capacity_unavailable, 
+                       pmt_from_long(d_max_capacity)));  
   
-  // keep allocating a little more until all of the channels are used and test the error response
-  // we start at 1 since we've already allocated 1 channel
+  // keep allocating a little more until all of the channels are used and test
+  // the error response we start at 1 since we've already allocated 1 channel
   for(int i=1; i < d_ntx_chan; i++) {
+
+    if(verbose)
+      std::cout << "[qa_alloc_top] Sent allocation request...\n";
+  
     d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+
     d_nmsgs_to_recv++;
   }
-  d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
+
+  // No more channels after allocating all of them is expected
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(s_err_channel_unavailable, 
+                       pmt_from_long(1)));
 
   // test out the same on the RX side
   d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
-  d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));  
+
+  d_rx->send(s_cmd_allocate_channel, 
+             pmt_list2(s_err_requested_capacity_unavailable, 
+                       pmt_from_long(d_max_capacity)));  
 
   for(int i=1; i < d_nrx_chan; i++) {
+    
     d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    
     d_nmsgs_to_recv++;
   }
-  d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
 
-  // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes allocated
-  d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
+  d_rx->send(s_cmd_allocate_channel, 
+             pmt_list2(s_err_channel_unavailable, 
+             pmt_from_long(1)));
+
+  // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes
+  // allocated
+  d_cs->send(s_cmd_current_capacity_allocation, 
+             pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
 }
 
 void
@@ -154,16 +198,22 @@ qa_alloc_top::handle_message(mb_message_sptr msg)
   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
       
     if(pmt_eq(msg->signal(), s_response_max_capacity)) {
-      d_max_capacity = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+      d_max_capacity = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_alloc_top] USRP has max capacity of " 
+                  << d_max_capacity << "\n";
     }
     else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
-      d_ntx_chan = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+      d_ntx_chan = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_alloc_top] USRP tx channels: " 
+                  << d_ntx_chan << "\n";
     }
     else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
-      d_nrx_chan = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+      d_nrx_chan = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_alloc_top] USRP rx channels: " 
+                  << d_nrx_chan << "\n";
     }
     else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
       check_message(msg);
@@ -171,6 +221,8 @@ qa_alloc_top::handle_message(mb_message_sptr msg)
     
     d_nstatus++;
 
+    check_message(msg);
+
     if(d_nstatus==d_nstatus_to_recv)
       run_tests();
   }
@@ -180,18 +232,26 @@ void
 qa_alloc_top::check_message(mb_message_sptr msg)
 {
   pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
 
-  pmt_t expected_result = pmt_nth(0, data);
-  pmt_t result = pmt_nth(1, data);
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
   
   d_nrecvd++;
 
 
-  if(!pmt_eqv(expected_result, result)) {
-    std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+    if(verbose)
+      std::cout << "Got: " << status << " Expected: " << e_status << "\n";
     shutdown_all(PMT_F);
+    return;
   } else {
-    std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
+    if(verbose)
+      std::cout << "[qa_alloc_top] Received expected response for message " 
+                << d_nrecvd << " (" << event << ")\n";
   }
 
   if(d_nrecvd == d_nmsgs_to_recv)
@@ -242,16 +302,20 @@ qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_
   d_ndealloc_recvd=0;
   d_ndealloc_to_recv = 0;
   d_nalloc_recvd=0;
-  d_nalloc_to_recv = 0;
+  d_nalloc_to_recv = 0;   // auto-set
   d_nstatus=0;
-  d_nstatus_to_recv = 3;
+  d_nstatus_to_recv = 4;
   
   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
 
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
   // Test the TX side
-  define_component("server", "usrp_server", PMT_F);
+  define_component("server", "usrp_server", usrp_server_dict);
   connect("self", "tx0", "server", "tx0");
   connect("self", "rx0", "server", "rx0");
   connect("self", "cs", "server", "cs");
@@ -262,26 +326,46 @@ qa_dealloc_top::~qa_dealloc_top(){}
 void
 qa_dealloc_top::initial_transition()
 {
+
+  if(verbose)
+    std::cout << "[qa_dealloc_top] Initializing...\n";
+
   // Retrieve information about the USRP, then run tests
-  d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
-  d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
-  d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open,PMT_T), 
+             pmt_from_long(0)));
+
+  d_cs->send(s_cmd_max_capacity, 
+             pmt_list1(pmt_list2(s_response_max_capacity,PMT_T)));
+
+  d_cs->send(s_cmd_ntx_chan, 
+             pmt_list1(pmt_list2(s_response_ntx_chan,PMT_T)));
+
+  d_cs->send(s_cmd_nrx_chan, 
+             pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
 }
 
 void
 qa_dealloc_top::allocate_max()
 {
-  std::cout << "[qa_dealloc_top] Max allocating...\n";
 
   // Keep allocating until we hit the maximum number of channels
   for(int i=0; i < d_ntx_chan; i++) {
-    d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_tx->send(s_cmd_allocate_channel, 
+               pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T),
+               pmt_from_long(1)));  // 1 byte is good enough
+
     d_nalloc_to_recv++;
   }
+
   for(int i=0; i < d_nrx_chan; i++) {
-    d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_rx->send(s_cmd_allocate_channel, 
+               pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), 
+               pmt_from_long(1)));
+
     d_nalloc_to_recv++;
   }
+
 }
 
 void
@@ -289,40 +373,103 @@ qa_dealloc_top::deallocate_all() {
   
   // Deallocate all of the channels that were allocated from allocate_max()
   for(int i=0; i < (int)d_tx_chans.size(); i++) {
-    d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_tx_chans[i])));
+
+    if(verbose)
+      std::cout << "[qa_dealloc_top] Trying to dealloc TX " 
+                << d_tx_chans[i] << std::endl;
+
+    d_tx->send(s_cmd_deallocate_channel, 
+               pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), 
+               pmt_from_long(d_tx_chans[i])));
+
     d_ndealloc_to_recv++;
   }
+
+  // Deallocate the RX side now
   for(int i=0; i < (int)d_rx_chans.size(); i++) {
-    d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_rx_chans[i])));
+
+    if(verbose)
+      std::cout << "[qa_dealloc_top] Trying to dealloc RX " 
+                << d_tx_chans[i] << std::endl;
+
+    d_rx->send(s_cmd_deallocate_channel, 
+               pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), 
+               pmt_from_long(d_rx_chans[i])));
+
     d_ndealloc_to_recv++;
   }
 
-  // Should get permission denied errors trying to re-dealloc the channels, as we no
-  // longer have permission to them after deallocating
+  // Should get permission denied errors trying to re-dealloc the channels, as
+  // we no longer have permission to them after deallocating
   for(int i=0; i < (int)d_tx_chans.size(); i++) {
-    d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_tx_chans[i])));
+
+    d_tx->send(s_cmd_deallocate_channel, 
+               pmt_list2(pmt_list2(s_response_deallocate_channel,
+                             s_err_channel_permission_denied), 
+                         pmt_from_long(d_tx_chans[i])));
+
     d_ndealloc_to_recv++;
   }
+
+  // Same for RX
   for(int i=0; i < (int)d_rx_chans.size(); i++) {
-    d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_rx_chans[i])));
+
+    d_rx->send(s_cmd_deallocate_channel, 
+               pmt_list2(pmt_list2(s_response_deallocate_channel,
+                             s_err_channel_permission_denied), 
+                         pmt_from_long(d_rx_chans[i])));
+  
     d_ndealloc_to_recv++;
   }
 
-  // Try to deallocate a channel that doesn't exist on both sides, the last element in the vectors
-  // is the highest channel number, so we take that plus 1
+  // Try to deallocate a channel that doesn't exist on both sides, the last
+  // element in the vectors is the highest channel number, so we take that plus
+  // 1
   d_ndealloc_to_recv+=2;
-  d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
-  d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
+  d_tx->send(s_cmd_deallocate_channel, 
+             pmt_list2(pmt_list2(s_response_deallocate_channel,
+                                 s_err_channel_invalid), 
+                       pmt_from_long(d_rx_chans.back()+1)));
+
+  d_rx->send(s_cmd_deallocate_channel, 
+             pmt_list2(pmt_list2(s_response_deallocate_channel,
+                                 s_err_channel_invalid), 
+                       pmt_from_long(d_rx_chans.back()+1)));
 
 
   // The used capacity should be back to 0 now that we've deallocated everything
-  d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(0)));
+  d_cs->send(s_cmd_current_capacity_allocation,
+             pmt_list1(pmt_list2(s_response_current_capacity_allocation,
+                                 PMT_T)));
 }
 
 void
 qa_dealloc_top::handle_message(mb_message_sptr msg)
 {
   pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+  
+  if(pmt_eq(event, pmt_intern("%shutdown")))
+    return;
+
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
+
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+    if(verbose)
+      std::cout << "Got: " << status << " Expected: " << e_status << "\n";
+    shutdown_all(PMT_F);
+    return;
+  } else {
+    if(verbose)
+      std::cout << "[qa_alloc_top] Received expected response for message " 
+                << d_ndealloc_recvd
+      << " (" << event << ")\n";
+  }
+
   if (pmt_eq(msg->port_id(), d_tx->port_symbol())
        || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
     
@@ -330,34 +477,32 @@ qa_dealloc_top::handle_message(mb_message_sptr msg)
       check_allocation(msg);
     }
     
-    if(pmt_eq(msg->signal(), s_response_deallocate_channel)){
-      check_deallocation(msg);
-    }
   }
   
   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
       
     if(pmt_eq(msg->signal(), s_response_max_capacity)) {
-      d_max_capacity = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_dealloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+      d_max_capacity = pmt_to_long(pmt_nth(2, data));
     }
     else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
-      d_ntx_chan = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_dealloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+      d_ntx_chan = pmt_to_long(pmt_nth(2, data));
     }
     else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
-      d_nrx_chan = pmt_to_long(pmt_nth(1, data));
-      std::cout << "[qa_dealloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+      d_nrx_chan = pmt_to_long(pmt_nth(2, data));
     }
     else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
-      // the final command is a capacity check which should be 0, then we shutdown
-      pmt_t expected_result = pmt_nth(0, data);
-      pmt_t result = pmt_nth(1, data);
+      // the final command is a capacity check which should be 0, then we
+      // shutdown
+      pmt_t expected_result = pmt_from_long(0);
+      pmt_t result = pmt_nth(2, data);
 
-      if(pmt_eqv(expected_result, result))
+      if(pmt_eqv(expected_result, result)) {
         shutdown_all(PMT_T);
-      else
+        return;
+      } else {
         shutdown_all(PMT_F);
+        return;
+      }
     }
     
     d_nstatus++;
@@ -367,72 +512,833 @@ qa_dealloc_top::handle_message(mb_message_sptr msg)
   }
 }
 
+
 void
-qa_dealloc_top::check_deallocation(mb_message_sptr msg)
+qa_dealloc_top::check_allocation(mb_message_sptr msg)
 {
   pmt_t data = msg->data();
+  pmt_t event = msg->signal();
 
-  pmt_t expected_result = pmt_nth(0, data);
-  pmt_t result = pmt_nth(1, data);
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t channel = pmt_nth(2, data);
 
-  d_ndealloc_recvd++;
+  d_nalloc_recvd++;
 
-  if(!pmt_eqv(expected_result, result)) {
-    std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+  if(!pmt_eqv(status, PMT_T)) {
     shutdown_all(PMT_F);
+    return;
   } else {
-    std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
+    // store all of the allocate channel numbers
+    if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
+      d_tx_chans.push_back(pmt_to_long(channel));
+    if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
+      d_rx_chans.push_back(pmt_to_long(channel));
   }
+
+  if(d_nalloc_recvd == d_nalloc_to_recv) {
+
+    if(verbose) {
+      std::cout << "[qa_dealloc_top] Allocated TX channels: ";
+      for(int i=0; i < (int)d_tx_chans.size(); i++)
+        std::cout << d_tx_chans[i] << " ";
+
+      std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
+      for(int i=0; i < (int)d_rx_chans.size(); i++)
+        std::cout << d_rx_chans[i] << " ";
+      std::cout << "\n";
+    }
+
+    deallocate_all();   // once we've allocated all of our channels, try to
+                        // dealloc them
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_dealloc_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_open_close_top : public mb_mblock
+{
+  mb_port_sptr d_cs;
+  
+  long d_max_capacity;
+
+  long d_nmsg_to_recv;
+  long d_nmsg_recvd;
+
+ public:
+  qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_open_close_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_cs(mb_message_sptr msg);
+  void run_tests();
+};
+
+qa_open_close_top::qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+
+  d_nmsg_to_recv=7;
+  d_nmsg_recvd=0;
+  
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
+  // Test the TX side
+  define_component("server", "usrp_server", usrp_server_dict);
+  connect("self", "cs", "server", "cs");
 }
 
+qa_open_close_top::~qa_open_close_top(){}
+
 void
-qa_dealloc_top::check_allocation(mb_message_sptr msg)
+qa_open_close_top::initial_transition()
+{
+  run_tests();
+}
+
+void
+qa_open_close_top::run_tests()
+{
+  // std::cout << "[qa_open_close_top] Starting tests\n";
+
+  // A close before an open should fail
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close, 
+                                              s_err_usrp_already_closed)));
+  
+  // Perform an open, and a second open which should fail
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open,PMT_T), 
+                       pmt_from_long(0)));
+
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open,
+                                 s_err_usrp_already_opened), 
+                       pmt_from_long(0)));
+
+  // A close should now be successful since the interface is open
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+  // But, a second close should fail
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,
+                                              s_err_usrp_already_closed)));
+  
+  // Just to be thorough, try an open and close again
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open,PMT_T), 
+                       pmt_from_long(0)));
+
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+  
+}
+
+
+void
+qa_open_close_top::handle_message(mb_message_sptr msg)
 {
   pmt_t data = msg->data();
 
-  pmt_t invocation_handle = pmt_nth(0, data);
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+      check_cs(msg);
+  }
+
+  d_nmsg_recvd++;
+
+  if(d_nmsg_to_recv == d_nmsg_recvd)
+    shutdown_all(PMT_T);
+}
+
+void
+qa_open_close_top::check_cs(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+
+  pmt_t expected = pmt_nth(0, data);
   pmt_t status = pmt_nth(1, data);
-  pmt_t channel = pmt_nth(2, data);
+
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
+
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+
+    if(verbose)
+      std::cout << "[qa_open_close_top] FAILED check_cs... Got: " << status
+                << " Expected: " << e_status
+                << " for event " << event << "\n";
+
+    shutdown_all(PMT_F);
+  } else {
+    if(verbose)
+      std::cout << "[qa_open_close_top] Received expected CS response (" 
+                << event << ")\n";
+  }
+
+}
+
+REGISTER_MBLOCK_CLASS(qa_open_close_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_tx_top : public mb_mblock
+{
+  mb_port_sptr d_tx;
+  mb_port_sptr d_rx;
+  mb_port_sptr d_cs;
   
-  d_nalloc_recvd++;
+  long d_max_capacity;
+  long d_ntx_chan, d_nrx_chan;
+
+  long d_tx_chan;
+  long d_rx_chan;
+
+  long d_nmsg_to_recv;
+  long d_nmsg_recvd;
+
+ public:
+  qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_tx_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_allocation(mb_message_sptr msg);
+  void check_deallocation(mb_message_sptr msg);
+  void check_xmit(mb_message_sptr msg);
+  void check_cs(mb_message_sptr msg);
+  void run_tests();
+};
 
-  if(pmt_eqv(status, PMT_F)) {
-    std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
+qa_tx_top::qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+
+  d_nmsg_to_recv=10;
+  d_nmsg_recvd=0;
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
+  // Test the TX side
+  define_component("server", "usrp_server", usrp_server_dict);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+}
+
+qa_tx_top::~qa_tx_top(){}
+
+void
+qa_tx_top::initial_transition()
+{
+  run_tests();
+}
+
+void
+qa_tx_top::run_tests()
+{
+  if(verbose)
+   std::cout << "[qa_tx_top] Starting tests\n";
+
+  // A transmit before an open should fail
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame, 
+                                 s_err_usrp_not_opened), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+                       pmt_from_long(0)));
+  
+  // Now open
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open,PMT_T), 
+                       pmt_from_long(0)));
+
+  // Try to transmit on a channel that we have no allocation for
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+                                 s_err_channel_permission_denied), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
+                       pmt_from_long(0)));
+
+  // Get a channel allocation and send on it, we assume 0 (FIXME) until 'defer'
+  // is implemented for simplicity
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
+                       pmt_from_long(1)));
+
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame, PMT_T), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
+                       pmt_from_long(0)));
+
+  // Close should be successful
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+  // After closing, a new transmit raw frame should fail again
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame, 
+                                 s_err_usrp_not_opened), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
+                       pmt_from_long(0)));
+
+  // Reopen and retry before getting an allocation, the first xmit should fail,
+  // after we allocate it should work again
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open, PMT_T), 
+                       pmt_from_long(0)));
+
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+                                 s_err_channel_permission_denied), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
+                       pmt_from_long(0)));
+
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
+                       pmt_from_long(1)));
+
+  d_tx->send(s_cmd_xmit_raw_frame, 
+             pmt_list4(pmt_list2(s_response_xmit_raw_frame,PMT_T), 
+                       pmt_from_long(0), 
+                       pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
+                       pmt_from_long(0)));
+
+  // A final close which should be successful
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+  
+}
+
+
+void
+qa_tx_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+  
+  if(pmt_eq(event, pmt_intern("%shutdown")))
+    return;
+
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
+
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+    if(verbose)
+      std::cout << "[qa_xmit_top] Got: " << status 
+                << " Expected: " << e_status 
+                << "For signal: " << event << "\n";
     shutdown_all(PMT_F);
+    return;
   } else {
+    if(verbose)
+      std::cout << "[qa_xmit_top] Received expected response for message " 
+                << d_nmsg_recvd
+      << " (" << event << ")\n";
+  }
+
+  if (pmt_eq(msg->port_id(), d_tx->port_symbol())
+       || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
+    
+    if(pmt_eq(msg->signal(), s_response_allocate_channel)) 
+      check_allocation(msg);
+    
+  }
+  
+  d_nmsg_recvd++;
+
+  if(d_nmsg_to_recv == d_nmsg_recvd){
+    shutdown_all(PMT_T);
+    return;
+  }
+}
+
+void
+qa_tx_top::check_allocation(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+  
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t channel = pmt_nth(2, data);
+
+  if(pmt_eqv(status, PMT_T)) {
     // store all of the allocate channel numbers
     if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
-      d_tx_chans.push_back(pmt_to_long(channel));
+      d_tx_chan = pmt_to_long(channel);
     if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
-      d_rx_chans.push_back(pmt_to_long(channel));
+      d_rx_chan = pmt_to_long(channel);
   }
+}
 
-  if(d_nalloc_recvd == d_nalloc_to_recv) {
+REGISTER_MBLOCK_CLASS(qa_tx_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_rx_top : public mb_mblock
+{
+  mb_port_sptr d_rx;
+  mb_port_sptr d_cs;
+  
+  long d_max_capacity;
+  long d_ntx_chan, d_nrx_chan;
+
+  long d_rx_chan;
+
+  long d_got_response_recv;
+
+  long d_nmsg_to_recv;
+  long d_nmsg_recvd;
+
+ public:
+  qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_rx_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_allocation(mb_message_sptr msg);
+  void check_deallocation(mb_message_sptr msg);
+  void check_xmit(mb_message_sptr msg);
+  void check_cs(mb_message_sptr msg);
+  void run_tests();
+};
+
+qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_got_response_recv(false)
+{ 
+
+  d_nmsg_to_recv=12;
+  d_nmsg_recvd=0;
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"), PMT_T);
+
+  // Test the TX side
+  define_component("server", "usrp_server", usrp_server_dict);
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+}
+
+qa_rx_top::~qa_rx_top(){}
+
+void
+qa_rx_top::initial_transition()
+{
+  run_tests();
+}
+
+void
+qa_rx_top::run_tests()
+{
+  if(verbose)
+    std::cout << "[qa_rx_top] Starting tests\n";
+
+  d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0)));
+
+  d_rx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), 
+             pmt_from_long(1)));
+
+  d_rx->send(s_cmd_start_recv_raw_samples, 
+             pmt_list2(PMT_NIL, 
+                       pmt_from_long(0)));
+
+  // A small sleep is used to ensure, if working properly, a recv
+  // response comes through successfully before the close gets
+  // through
+  usleep(1000);
+
+  d_rx->send(s_cmd_stop_recv_raw_samples, 
+             pmt_list2(PMT_NIL, 
+                       pmt_from_long(0)));
+
+  d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+  
+}
+
+
+void
+qa_rx_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+  
+  if(pmt_eq(event, pmt_intern("%shutdown")))
+    return;
+  
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  
+  // For testing RX, an invocation handle is not generated by the stub,
+  // therefore the same approach for testing is not used.  We simply
+  // expect all responses to be true.
+  if(pmt_eq(event, s_response_recv_raw_samples)) {
+    if(!pmt_eqv(status, PMT_T)) {
+      if(verbose)
+        std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
+      shutdown_all(PMT_F);
+      return;
+    }
+    else {
+      if(verbose)
+        std::cout << "[qa_rx_top] Received expected response for message " 
+                  << d_nmsg_recvd
+                  << " (" << event << ")\n";
+
+      // All we want is 1 response receive!  Can't guarantee exact numbers
+      d_got_response_recv = true;
+    }
+    return;
+  }
+
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
+
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+   if(verbose)
+      std::cout << "Got: " << status << " Expected: " << e_status << "\n";
+    shutdown_all(PMT_F);
+    return;
+  } else {
+    if(verbose)
+      std::cout << "[qa_rx_top] Received expected response for message " 
+                << d_nmsg_recvd
+      << " (" << event << ")\n";
+  }
+
+  if (pmt_eq(msg->port_id(), d_rx->port_symbol())) {
+    
+    if(pmt_eq(msg->signal(), s_response_allocate_channel)) 
+      check_allocation(msg);
+
+  }
+
+  // We stop when we get a close, we are successful if we
+  // got a response from recv, fail if we never got a recv response
+  if(pmt_eq(msg->signal(), s_response_close)) {
     
-    std::cout << "[qa_dealloc_top] Allocated TX channels: ";
-    for(int i=0; i < (int)d_tx_chans.size(); i++)
-      std::cout << d_tx_chans[i] << " ";
+    if(d_got_response_recv) {
+      shutdown_all(PMT_T);
+      return;
+    }
+    else {
+      shutdown_all(PMT_F);
+      if(verbose)
+        std::cout << "[qa_rx_top] No response message before close\n";
+      return;
+    }
+
+  }
+    
+  
+  d_nmsg_recvd++;
+
+}
 
-    std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
-    for(int i=0; i < (int)d_rx_chans.size(); i++)
-      std::cout << d_rx_chans[i] << " ";
-    std::cout << "\n";
 
-    deallocate_all();   // once we've allocated all of our channels, try to dealloc them
+void
+qa_rx_top::check_allocation(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+  
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t channel = pmt_nth(2, data);
+
+  if(pmt_eqv(status, PMT_T)) {
+    // store all of the allocate channel numbers
+    if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
+      d_rx_chan = pmt_to_long(channel);
   }
 }
 
-REGISTER_MBLOCK_CLASS(qa_dealloc_top);
+REGISTER_MBLOCK_CLASS(qa_rx_top);
+
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_cs_top : public mb_mblock
+{
+  mb_port_sptr d_tx;
+  mb_port_sptr d_rx;
+  mb_port_sptr d_cs;
+
+  long d_nmsgs_to_recv;
+  long d_nrecvd;
+
+  long d_max_capacity;
+  long d_ntx_chan, d_nrx_chan;
+
+  long d_nstatus;
+  long d_nstatus_to_recv;
+
+ public:
+  qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_cs_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_message(mb_message_sptr msg);
+  void run_tests();
+};
+
+qa_cs_top::qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+  d_nrecvd=0;
+  d_nmsgs_to_recv = 8;
+  d_nstatus=0;
+  d_nstatus_to_recv = 50;
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  // Use the stub with the usrp_server
+  pmt_t usrp_server_dict = pmt_make_dict();
+  pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
+  // Test the TX side
+  define_component("server", "usrp_server", usrp_server_dict);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+}
+
+qa_cs_top::~qa_cs_top(){}
+
+void
+qa_cs_top::initial_transition()
+{
+  run_tests();
+}
+
+void
+qa_cs_top::run_tests()
+{
+  if(verbose)
+    std::cout << "[qa_cs_top] Starting tests...\n";
+  
+  // Retrieve information about the USRP, then run tests
+  d_cs->send(s_cmd_open, 
+             pmt_list2(pmt_list2(s_response_open, PMT_T), 
+             pmt_from_long(0)));
+
+  // should be able to allocate 1 byte
+  d_tx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
+                       pmt_from_long(1)));
+  
+  d_rx->send(s_cmd_allocate_channel, 
+             pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
+                       pmt_from_long(1)));
+  
+  // Need to start receiving to read from the USRP to get C/S responses
+  d_rx->send(s_cmd_start_recv_raw_samples, 
+             pmt_list2(PMT_NIL, 
+                       pmt_from_long(0)));
+
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                       pmt_list1(
+                            pmt_list2(s_op_ping_fixed, 
+                                      pmt_list2(pmt_from_long(3), 
+                                      pmt_from_long(0))))));
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                       pmt_list1(
+                            pmt_list2(s_op_write_reg, 
+                                      pmt_list2(
+                                      pmt_from_long(0x3), 
+                                      pmt_from_long(0x4))))));
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                       pmt_list1(
+                            pmt_list2(s_op_write_reg_masked, 
+                                      pmt_list3(
+                                      pmt_from_long(0x3), 
+                                      pmt_from_long(0x4),
+                                      pmt_from_long(0x5))))));
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                       pmt_list1(
+                            pmt_list2(s_op_read_reg, 
+                                      pmt_list2(pmt_from_long(0), 
+                                      pmt_from_long(0x6))))));
+  
+  d_tx->send(s_cmd_to_control_channel,
+             pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                       pmt_list1(
+                            pmt_list2(s_op_delay, 
+                                      pmt_list1(pmt_from_long(0x7))))));
+
+  pmt_t subpackets = pmt_list5(
+                        pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(0), pmt_from_long(0))),
+                        pmt_list2(s_op_delay, pmt_list1(pmt_from_long(0x7))),
+                        pmt_list2(s_op_write_reg_masked, pmt_list3(pmt_from_long(3),
+                                                                   pmt_from_long(4),
+                                                                   pmt_from_long(5))),
+                        pmt_list2(s_op_write_reg, pmt_list2(pmt_from_long(3),
+                                                            pmt_from_long(4))),
+                        pmt_list2(s_op_read_reg, pmt_list2(pmt_from_long(0),
+                                                           pmt_from_long(6)))
+                     );
+
+  d_tx->send(s_cmd_to_control_channel, 
+              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                        subpackets));
+
+  pmt_t i2c_data = pmt_make_u8vector(8, 0xff);
+
+  subpackets = pmt_list2(
+                        pmt_list2(s_op_i2c_write, 
+                                  pmt_list2(pmt_from_long(8), i2c_data)),
+                        pmt_list2(s_op_i2c_read,
+                                  pmt_list3(pmt_from_long(0), pmt_from_long(9), pmt_from_long(1)))
+
+                     );
+
+  d_tx->send(s_cmd_to_control_channel, 
+              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+                        subpackets));
+  
+}
+
+void
+qa_cs_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+
+  if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
+       || pmt_eq(msg->port_id(), d_rx->port_symbol()))
+       && pmt_eq(msg->signal(), s_response_allocate_channel))
+    check_message(msg);
+
+  if (pmt_eq(msg->port_id(), d_tx->port_symbol())
+      && pmt_eq(msg->signal(), s_response_from_control_channel))
+    check_message(msg);
+  
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+      
+    if(pmt_eq(msg->signal(), s_response_max_capacity)) {
+      d_max_capacity = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_cs_top] USRP has max capacity of " 
+                  << d_max_capacity << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
+      d_ntx_chan = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_cs_top] USRP tx channels: " 
+                  << d_ntx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
+      d_nrx_chan = pmt_to_long(pmt_nth(2, data));
+      if(verbose)
+        std::cout << "[qa_cs_top] USRP rx channels: " 
+                  << d_nrx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
+      check_message(msg);
+    }
+    
+    d_nstatus++;
+
+    check_message(msg);
+
+    if(d_nstatus==d_nstatus_to_recv)
+      run_tests();
+  }
+}
+
+void
+qa_cs_top::check_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  pmt_t event = msg->signal();
+
+  pmt_t expected = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+
+  pmt_t e_event = pmt_nth(0, expected);
+  pmt_t e_status = pmt_nth(1, expected);
+  
+  d_nrecvd++;
+
+
+  if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+    if(verbose)
+      std::cout << "[qa_cs_top] Got: " << status << " Expected: " << e_status << "\n";
+    shutdown_all(PMT_F);
+    return;
+  } else {
+    if(verbose)
+      std::cout << "[qa_cs_top] Received expected response for message " 
+                << d_nrecvd << " (" << event << ")\n";
+  }
+
+  if(d_nrecvd == d_nmsgs_to_recv)
+    shutdown_all(PMT_T);
+}
+
+REGISTER_MBLOCK_CLASS(qa_cs_top);
 
 // ----------------------------------------------------------------------------------------------
 
+void 
+qa_inband_usrp_server::test_open_close()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  // std::cout << "\n\n----------------------------\n";
+  // std::cout << "    RUNNING OPEN/CLOSE TESTS  \n";
+
+  rt->run("top", "qa_open_close_top", PMT_F, &result);
+
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
 void 
 qa_inband_usrp_server::test_chan_allocation()
 {
   mb_runtime_sptr rt = mb_make_runtime();
   pmt_t result = PMT_T;
 
-  rt->run("top", "qa_alloc_top", PMT_F, &result);
+  // std::cout << "\n\n----------------------------\n";
+  // std::cout << "    RUNNING ALLOCATION TESTS  \n";
+
+  rt->run("qa_alloc_top", "qa_alloc_top", PMT_F, &result);
   
   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
 }
@@ -443,13 +1349,52 @@ qa_inband_usrp_server::test_chan_deallocation()
   mb_runtime_sptr rt = mb_make_runtime();
   pmt_t result = PMT_T;
 
-  rt->run("top", "qa_dealloc_top", PMT_F, &result);
+  // std::cout << "\n\n----------------------------\n";
+  // std::cout << "  RUNNING DEALLOCATION TESTS  \n";
+
+  rt->run("qa_dealloc_top", "qa_dealloc_top", PMT_F, &result);
+  
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_tx()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  // std::cout << "\n\n-----------------\n";
+  // std::cout << "  RUNNING TX TESTS  \n";
+
+  rt->run("top", "qa_tx_top", PMT_F, &result);
+  
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_rx()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  // std::cout << "\n\n-----------------\n";
+  // std::cout << "  RUNNING RX TESTS  \n";
+
+  rt->run("top", "qa_rx_top", PMT_F, &result);
   
   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
 }
 
 void
-qa_inband_usrp_server::test_fragmentation()
+qa_inband_usrp_server::test_cs()
 {
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  // std::cout << "\n\n-----------------\n";
+  // std::cout << "  RUNNING CS TESTS  \n";
+
+  rt->run("top", "qa_cs_top", PMT_F, &result);
   
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
 }
index 91cf7d87c51fad3676597f87601fa67944d0cf76..5db57c3ed41cbe1a12641134bc5bd024a80eb520 100644 (file)
 class qa_inband_usrp_server : public CppUnit::TestCase {
 
   CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
+  CPPUNIT_TEST(test_open_close);
   CPPUNIT_TEST(test_chan_allocation);
   CPPUNIT_TEST(test_chan_deallocation);
-  CPPUNIT_TEST(test_fragmentation);
+  CPPUNIT_TEST(test_tx);
+  CPPUNIT_TEST(test_rx);
+  CPPUNIT_TEST(test_cs);
   CPPUNIT_TEST_SUITE_END();
 
  private:
   void test_chan_allocation();
   void test_chan_deallocation();
-  void test_fragmentation();
+  void test_open_close();
+  void test_tx();
+  void test_rx();
+  void test_cs();
 };
 
 #endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_channel.h b/usrp/host/lib/inband/symbols_usrp_channel.h
new file mode 100644 (file)
index 0000000..a0114cf
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_CHANNEL_H
+#define INCLUDED_SYMBOLS_USRP_CHANNEL_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+
+// Incoming
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+
+// Errors
+static pmt_t s_err_requested_capacity_unavailable = pmt_intern("err-requested-capacity-unavailable");
+static pmt_t s_err_channel_unavailable = pmt_intern("err-channel-unavailable");
+static pmt_t s_err_channel_invalid = pmt_intern("err-channel-invalid");
+static pmt_t s_err_channel_permission_denied = pmt_intern("err-channel-permission-denied");
+
+#endif /* INCLUDED_SYMBOLS_USRP_CHANNEL_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_interface_cs.h b/usrp/host/lib/inband/symbols_usrp_interface_cs.h
new file mode 100644 (file)
index 0000000..72c8fcc
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
+#define INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_open = pmt_intern("cmd-usrp-open");
+static pmt_t s_cmd_usrp_close = pmt_intern("cmd-usrp-close");
+static pmt_t s_cmd_usrp_ntx_chan = pmt_intern("cmd-usrp-ntx-chan");
+static pmt_t s_cmd_usrp_nrx_chan = pmt_intern("cmd-usrp-nrx-chan");
+static pmt_t s_cmd_usrp_write = pmt_intern("cmd-usrp-write");
+static pmt_t s_cmd_usrp_start_reading = pmt_intern("cmd-usrp-start-reading");
+static pmt_t s_cmd_usrp_stop_reading = pmt_intern("cmd-usrp-stop-reading");
+
+// Incoming
+static pmt_t s_response_usrp_open = pmt_intern("response-usrp-open");
+static pmt_t s_response_usrp_close = pmt_intern("response-usrp-close");
+static pmt_t s_response_usrp_ntx_chan = pmt_intern("response-usrp-ntx-chan");
+static pmt_t s_response_usrp_nrx_chan = pmt_intern("response-usrp-nrx-chan");
+static pmt_t s_response_usrp_write = pmt_intern("response-usrp-write");
+static pmt_t s_response_usrp_read = pmt_intern("response-usrp-read");
+
+#endif /* INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_low_level_cs.h b/usrp/host/lib/inband/symbols_usrp_low_level_cs.h
new file mode 100644 (file)
index 0000000..a726060
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
+#define INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
+
+// Incoming
+static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
+
+// Subpackets
+static pmt_t s_op_ping_fixed = pmt_intern("op-ping-fixed");
+static pmt_t s_op_ping_fixed_reply = pmt_intern("op-ping-fixed-reply");
+static pmt_t s_op_write_reg = pmt_intern("op-write-reg");
+static pmt_t s_op_write_reg_masked = pmt_intern("op-write-reg-masked");
+static pmt_t s_op_read_reg = pmt_intern("op-read-reg");
+static pmt_t s_op_read_reg_reply = pmt_intern("op-read-reg-reply");
+static pmt_t s_op_i2c_write = pmt_intern("op-i2c-write");
+static pmt_t s_op_i2c_read = pmt_intern("op-i2c-read");
+static pmt_t s_op_i2c_read_reply = pmt_intern("op-i2c-read-reply");
+static pmt_t s_op_spi_write = pmt_intern("op-spi-write");
+static pmt_t s_op_spi_read = pmt_intern("op-spi-read");
+static pmt_t s_op_spi_read_reply = pmt_intern("op-spi-read-reply");
+static pmt_t s_op_delay = pmt_intern("op-delay");
+
+#endif /* INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_rx.h b/usrp/host/lib/inband/symbols_usrp_rx.h
new file mode 100644 (file)
index 0000000..07d58a3
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_RX_H
+#define INCLUDED_SYMBOLS_USRP_RX_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
+static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
+
+// Incoming
+static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
+
+// Errors
+static pmt_t s_err_already_receiving = pmt_intern("err-already-receiving");
+
+#endif /* INCLUDED_SYMBOLS_USRP_RX_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_rx_cs.h b/usrp/host/lib/inband/symbols_usrp_rx_cs.h
new file mode 100644 (file)
index 0000000..bf4f033
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_RX_CS_H
+#define INCLUDED_SYMBOLS_USRP_RX_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_rx_start_reading = pmt_intern("cmd-usrp-rx-start-reading");
+
+// Incoming
+static pmt_t s_response_usrp_rx_read = pmt_intern("response-usrp-rx-read");
+
+#endif /* INCLUDED_SYMBOLS_USRP_RX_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_server_cs.h b/usrp/host/lib/inband/symbols_usrp_server_cs.h
new file mode 100644 (file)
index 0000000..e612e24
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_SERVER_CS_H
+#define INCLUDED_SYMBOLS_USRP_SERVER_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_cmd_max_capacity  = pmt_intern("cmd-max-capacity");
+static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
+static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
+static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
+
+// Incoming
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
+static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
+static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+
+// Errors
+static pmt_t s_err_usrp_not_opened = pmt_intern("err-usrp-not-opened");
+static pmt_t s_err_usrp_already_opened = pmt_intern("err-usrp-already-opened");
+static pmt_t s_err_usrp_already_closed = pmt_intern("err-usrp-already-closed");
+
+#endif /* INCLUDED_SYMBOLS_USRP_SERVER_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_tx.h b/usrp/host/lib/inband/symbols_usrp_tx.h
new file mode 100644 (file)
index 0000000..4e58e2c
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_TX_H
+#define INCLUDED_SYMBOLS_USRP_TX_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_xmit_raw_frame  = pmt_intern("cmd-xmit-raw-frame");
+
+// Incoming
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+
+#endif /* INCLUDED_SYMBOLS_USRP_TX_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_tx_cs.h b/usrp/host/lib/inband/symbols_usrp_tx_cs.h
new file mode 100644 (file)
index 0000000..d02ef1d
--- /dev/null
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_SYMBOLS_USRP_TX_CS_H
+#define INCLUDED_SYMBOLS_USRP_TX_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_tx_write = pmt_intern("cmd-usrp-tx-write");
+
+// Incoming
+static pmt_t s_response_usrp_tx_write = pmt_intern("response-usrp-tx-write");
+
+#endif /* INCLUDED_SYMBOLS_USRP_TX_CS_H */
diff --git a/usrp/host/lib/inband/test_usrp_inband.cc b/usrp/host/lib/inband/test_usrp_inband.cc
new file mode 100644 (file)
index 0000000..dd8d46f
--- /dev/null
@@ -0,0 +1,297 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_protocol_class.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include "usrp_standard.h"
+
+typedef usrp_inband_usb_packet transport_pkt; 
+
+// Signal set for the USRP server
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
+static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
+static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
+static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
+static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
+static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
+static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+static pmt_t s_cmd_xmit_raw_frame  = pmt_intern("cmd-xmit-raw-frame");
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+
+bool loopback_p = false;
+bool counting_p = false;
+bool fake_usrp_p = false;
+char *prog_name;
+
+static void
+set_progname (char *path)
+{
+  char *p = strrchr (path, '/');
+  if (p != 0)
+    prog_name = p+1;
+  else
+    prog_name = path;
+}
+
+static void
+usage()
+{
+  fprintf (stderr, "usage: %s [-l]\n", prog_name);
+  fprintf (stderr, "  [-l] digital loopback in FPGA\n");
+  fprintf (stderr, "  [-c] counting in FPGA\n");
+  fprintf (stderr, "  [-f] fake usrp\n");
+
+  exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+  int ch;
+
+  set_progname(argv[0]);
+
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  while ((ch = getopt(argc, argv, "flc")) != EOF) {
+    switch(ch) {
+    
+      case 'l':
+        loopback_p = true;
+        break;
+
+      case 'c':
+        counting_p = true;
+        break;
+      
+      case 'f':
+        fake_usrp_p = true;
+        break;
+
+      default:
+        usage();
+    }
+  }
+
+
+  std::cout << "[test_usrp_inband] Starting...\n";
+
+  rt->run("top", "test_usrp_inband_top", PMT_F, &result);
+}
+
+class test_usrp_inband_top : public mb_mblock
+{
+  mb_port_sptr d_tx;
+  mb_port_sptr d_cs;
+
+  long d_tx_chan;
+
+ public:
+  test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~test_usrp_inband_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void open_usrp();
+  void close_usrp();
+  void check_message(mb_message_sptr msg);
+  void allocate_channel();
+  void send_packets();
+};
+
+test_usrp_inband_top::test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+  std::cout << "[TEST_USRP_INBAND_TOP] Initializing...\n";
+  
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+  
+  // Test the TX side
+
+  // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
+  pmt_t usrp_server_dict = pmt_make_dict();
+
+  if(fake_usrp_p)
+    pmt_dict_set(usrp_server_dict, pmt_intern("usrp-interface"), pmt_intern("usrp_usb_interface_stub"));
+
+  define_component("server", "usrp_server", usrp_server_dict);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "cs", "server", "cs");
+}
+
+test_usrp_inband_top::~test_usrp_inband_top()
+{
+}
+
+void
+test_usrp_inband_top::initial_transition()
+{
+  open_usrp();
+}
+
+void
+test_usrp_inband_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();         // the "name" of the message
+  pmt_t port_id = msg->port_id();      // which port it came in on
+  pmt_t data = msg->data();
+  pmt_t metadata = msg->metadata();
+  pmt_t status;
+
+  if (pmt_eq(port_id, d_cs->port_symbol())) {  // message came in on our control/status port
+
+    //---------- OPEN RESPONSE ----------//
+    if (pmt_eq(event, s_response_open)) {
+      status = pmt_nth(1, data);
+
+      if(pmt_eq(status, PMT_T)) {
+        std::cout << "[TEST_USRP_INBAND_TOP] Success opening USRP\n";
+      }
+      else {
+        std::cout << "[TEST_USRP_INBAND_TOP] Received error message opening USRP\n";
+        shutdown_all(PMT_F);
+      }
+
+      allocate_channel();
+
+      return;
+    }
+    //--------- CLOSE RESPONSE -----------//
+    else if (pmt_eq(event, s_response_close)) {
+      status = pmt_nth(1, data);
+      
+      if(pmt_eq(status, PMT_T)) {
+        std::cout << "[TEST_USRP_INBAND_TOP] Successfully closed USRP\n";
+      }
+      else {
+        std::cout << "[TEST_USRP_INBAND_TOP] Received error message closing USRP\n";
+        shutdown_all(PMT_F);
+      }
+
+      shutdown_all(PMT_T);
+
+      return;
+    }
+  }
+    
+  if (pmt_eq(port_id, d_tx->port_symbol())) {
+
+    //---------- ALLOCATE RESPONSE ---------//
+    if(pmt_eq(event, s_response_allocate_channel)) {
+      status = pmt_nth(1, data);
+      pmt_t channel = pmt_nth(2, data);
+
+      if(pmt_eq(status, PMT_T)) {
+        d_tx_chan = pmt_to_long(channel);
+        std::cout << "[TEST_USRP_INBAND_TOP] Received allocation on channel " << d_tx_chan << "\n";
+      }
+      else {
+        std::cout << "[TEST_USRP_INBAND_TOP] Error allocating channel\n";
+        shutdown_all(PMT_F);
+      }
+      
+      send_packets();
+
+      return;
+    }
+    //----------- XMIT RESPONSE ------------//
+    else if(pmt_eq(event, s_response_xmit_raw_frame)) {
+      status = pmt_nth(1, data);
+
+      if(pmt_eq(status, PMT_T)) {
+        std::cout << "[TEST_USRP_INBAND_TOP] Transmission successful\n";
+      }
+      else {
+        std::cout << "[TEST_USRP_INBAND_TOP] Failed transmission\n";
+        shutdown_all(PMT_F);
+      }
+
+      close_usrp();
+
+      return;
+    }
+  }
+
+  std::cout << "[TEST_USRP_INBAND_TOP] Received unhandled message: " << event << "\n";
+}
+
+void
+test_usrp_inband_top::allocate_channel()
+{
+  std::cout << "[TEST_USRP_INBAND_TOP] Requesting channel allocation...\n";
+  
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+}
+
+void
+test_usrp_inband_top::send_packets()
+{
+  std::cout << "[TEST_USRP_INBAND_TOP] Sending single packet..\n";
+  d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_from_long(1), pmt_from_long(d_tx_chan), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0)));
+  
+}
+
+void
+test_usrp_inband_top::open_usrp()
+{
+  pmt_t usrp = pmt_from_long(0);
+
+  long rx_mode = 0;
+
+  if(loopback_p)
+    rx_mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK;
+  if(counting_p)
+    rx_mode |= usrp_standard_rx::FPGA_MODE_COUNTING;
+
+  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, usrp));
+}
+
+void
+test_usrp_inband_top::close_usrp()
+{
+  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_top);
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.cc b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
new file mode 100644 (file)
index 0000000..b8befa4
--- /dev/null
@@ -0,0 +1,749 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <usrp_inband_usb_packet.h>
+
+#include <usrp_bytesex.h>
+#include <iostream>
+#include <stdio.h>
+
+bool usrp_inband_usb_packet::align32()
+{
+  int p_len = payload_len();
+
+  int bytes_needed = 4 - (p_len % 4);
+
+  if(bytes_needed == 4)
+    return true;
+
+  // If the room left in the packet is less than the number of bytes
+  // needed, return false to indicate no room to align
+  if((MAX_PAYLOAD - p_len) < bytes_needed)
+    return false;
+    
+  p_len += bytes_needed;
+
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = p_len;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
+{
+  if(!align32())
+    return false;
+  
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t ping = ( 
+      ((OP_PING_FIXED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | (ping_val & CS_PINGVAL_MASK)
+
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(ping);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+
+bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val) 
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t ping = ( 
+      ((OP_PING_FIXED_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | ((ping_val & CS_PINGVAL_MASK) << CS_PINGVAL_SHIFT)
+
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(ping);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_WRITEREG_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word0 = 0;
+
+  // Build the first word which includes the register number
+  word0 = (
+      ((OP_WRITE_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_WRITEREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+  );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word0);
+
+  // The second word is solely the register value to be written
+  // FIXME: should this be unsigned?
+  payload += 1; 
+  *payload = host_to_usrp_u32((uint32_t) val);
+  
+  // Rebuild the header to update the payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREG_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long mask)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_WRITEREGMASKED_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word0 = 0;
+
+  // Build the first word which includes the register number
+  word0 = (
+      ((OP_WRITE_REG_MASKED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_WRITEREGMASKED_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+  );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word0);
+
+  // Skip over the first word and write the register value
+  payload += 1;
+  *payload = host_to_usrp_u32((uint32_t) val);
+
+  // Skip over the register value and write the mask
+  payload += 1;
+  *payload = host_to_usrp_u32((uint32_t) mask);
+  
+  // Rebuild the header to update the payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREGMASKED_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_READREG_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t read_reg = ( 
+      ((OP_READ_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_READREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(read_reg);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREG_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_val)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_READREGREPLY_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word0 = ( 
+      ((OP_READ_REG_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_READREGREPLY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word0);
+
+  // Hop to the next word and write the reg value
+  payload += 1;
+  *payload = host_to_usrp_u32((uint32_t) reg_val); 
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREGREPLY_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_delay(long ticks)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_DELAY_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t delay = ( 
+      ((OP_DELAY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_DELAY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((ticks & CS_DELAY_MASK) << CS_DELAY_SHIFT)
+
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(delay);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_DELAY_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  int i2c_len = data_len + 2;   // 2 bytes between mbz and addr
+
+  if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word0 = 0;
+
+  word0 = (
+      ((OP_I2C_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+  );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+   *payload = host_to_usrp_u32(word0);
+
+   // Jump over the first word and write the data
+   // FIXME: Should the data be changed to usrp byte order?
+   payload += 1;
+   memcpy(payload, i2c_data, data_len);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_I2CREAD_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word0 = 0;
+  
+  word0 = ( 
+      ((OP_I2C_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_I2CREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word0);
+
+  // Jump a word and write the number of bytes to read
+  payload += 1;
+  uint32_t word1 = 
+    (n_bytes & CS_I2CREADBYTES_MASK) << CS_I2CREADBYTES_SHIFT;
+  *payload = host_to_usrp_u32(word1);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_I2CREAD_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  int i2c_len = i2c_data_len + 2;
+
+  if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN)) 
+    return false;
+  
+  uint32_t word0 = 0;
+  
+  word0 = ( 
+      ((OP_I2C_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+    );
+
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word0);
+
+  // Jump a word and write the actual data
+  payload += 1;
+  memcpy(payload, i2c_data, i2c_data_len);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  int spi_len = spi_data_len + 6;
+
+  if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word = 0;
+
+  // First word contains the opcode and length, then mbz
+  word = (
+      ((OP_SPI_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+    );
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  payload += 1;
+
+  // Second word contains the enables, format, and optional tx bytes
+  word = 0;
+  word = (
+      ((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
+    | ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
+    | ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
+    );
+  payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  payload += 1;
+  memcpy(payload, spi_data, spi_data_len);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  if((MAX_PAYLOAD - p_len) < (CS_SPIREAD_LEN + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word = 0;
+
+  // First word contains the opcode, length, and RID
+  word = (
+      ((OP_SPI_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((CS_SPIREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    );
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  payload += 1;
+
+  // Second word contains the enables, format, and optional tx bytes
+  word = 0;
+  word = (
+      ((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
+    | ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
+    | ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
+    );
+  payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  payload += 1;
+
+  // The third word contains the number of bytes
+  word = 0;
+  word = (
+      ((n_bytes & CS_SPINBYTES_MASK) << CS_SPINBYTES_SHIFT)
+    );
+  payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + CS_SPIREAD_LEN;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+  
+  return true;
+}
+
+bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len)
+{
+  if(!align32())
+    return false;
+
+  int p_len = payload_len();
+
+  int spi_len = spi_data_len + 2;
+
+  if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
+    return false;
+
+  uint32_t word = 0;
+
+  // First word contains the opcode, length, and RID
+  word = (
+      ((OP_SPI_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+    | ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+    | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+    );
+  uint32_t *payload = (uint32_t *) (d_payload + p_len);
+  *payload = host_to_usrp_u32(word);
+
+  // Jump a word and write the actual data
+  payload += 1;
+  memcpy(payload, spi_data, spi_data_len);
+
+  // Update payload length
+  int h_flags = flags();
+  int h_chan = chan();
+  int h_tag = tag();
+  int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
+
+  set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+  return true;
+}
+
+// Takes an offset to the beginning of a subpacket and extracts the
+// length of the subpacket
+int usrp_inband_usb_packet::cs_len(int payload_offset) {
+  uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
+  return (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
+}
+
+// The following method takes an offset within the packet payload to extract
+// a control/status subpacket and construct a pmt response which includes the
+// proper signal and arguments specified by usrp-low-level-cs.  The USRP
+// server could therefore use this to read subpackets and pass them responses
+// back up to the application.  It's arguable that only reply packets should
+// be parsed here, however we parse others for use in debugging or failure
+// reporting on the transmit side of packets.
+pmt_t usrp_inband_usb_packet::read_subpacket(int payload_offset) {
+
+  uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
+  uint32_t opcode = (subpkt >> CS_OPCODE_SHIFT) & CS_OPCODE_MASK;
+  uint32_t len = (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
+
+  switch(opcode) {
+    
+    case OP_PING_FIXED_REPLY:
+    {
+      pmt_t rid     = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
+      return pmt_list3(s_op_ping_fixed_reply, rid, pingval);
+    }
+
+    case OP_READ_REG_REPLY:
+    {
+      pmt_t rid     = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+      // To get the register value we just read the next 32 bits
+      uint32_t val  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      pmt_t reg_val = pmt_from_long(val);
+
+      return pmt_list4(s_op_read_reg_reply, rid, reg_num, reg_val);
+    }
+
+    case OP_I2C_READ_REPLY:
+    {
+      pmt_t rid       = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t i2c_addr  = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+
+      // Make a u8 vector to dump the data from the packet into
+      size_t i2c_data_len;
+      pmt_t i2c_data  = pmt_make_u8vector(len - 2, 0);   // skip rid+mbz+addr = 2 bytes
+      uint8_t *w_data  = 
+          (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, i2c_data_len);
+
+      memcpy(w_data, d_payload + payload_offset + 4, i2c_data_len);  // skip first word
+
+      return pmt_list4(s_op_i2c_read_reply, rid, i2c_addr, i2c_data);
+    }
+
+    case OP_SPI_READ_REPLY:
+    {
+      pmt_t rid       = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      
+      // Make a u8 vector to dump the data from the packet into
+      size_t spi_data_len;
+      pmt_t spi_data  = pmt_make_u8vector(len - 2, 0);   // skip rid+mbz+addr = 2 bytes
+      uint8_t *w_data  = 
+          (uint8_t *) pmt_u8vector_writeable_elements(spi_data, spi_data_len);
+
+      memcpy(w_data, d_payload + payload_offset + 4, spi_data_len);  // skip first word
+
+      return pmt_list3(s_op_spi_read_reply, rid, spi_data);
+    }
+
+    case OP_PING_FIXED:
+    {
+      pmt_t rid     = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
+      return pmt_list3(s_op_ping_fixed, rid, pingval);
+    }
+
+    case OP_WRITE_REG:
+    {
+      pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+      // To get the register value we just read the next 32 bits
+      uint32_t val  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      pmt_t reg_val = pmt_from_long(val);
+
+      return pmt_list3(s_op_write_reg, reg_num, reg_val);
+    }
+
+    case OP_WRITE_REG_MASKED:
+    {
+      pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+      // To get the register value we just read the next 32 bits
+      uint32_t val  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      pmt_t reg_val = pmt_from_long(val);
+
+      // The mask is the next 32 bits
+      uint32_t mask  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
+      pmt_t reg_mask = pmt_from_long(mask);
+
+      return pmt_list4(s_op_write_reg_masked, reg_num, reg_val, reg_mask);
+    }
+
+    case OP_READ_REG:
+    {
+      pmt_t rid     = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+      return pmt_list3(s_op_read_reg, rid, reg_num);
+    }
+
+    case OP_I2C_WRITE:
+    {
+      pmt_t i2c_addr    = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+
+      // The length includes an extra 2 bytes for storing the mbz and addr
+      pmt_t i2c_data    = pmt_make_u8vector(len-2, 0);
+
+      // Get a writeable address to copy the data from the packet
+      size_t ignore;
+      uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, ignore);
+      memcpy(w_data, d_payload + payload_offset + 4, len-2);
+
+      
+      return pmt_list3(s_op_i2c_write, i2c_addr, i2c_data);
+    }
+
+    case OP_I2C_READ:
+    {
+      pmt_t rid       = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+      pmt_t i2c_addr  = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+      
+      // The number of bytes is in the next word
+      uint32_t bytes  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      bytes = (bytes >> CS_I2CREADBYTES_SHIFT) & CS_I2CREADBYTES_MASK;
+      pmt_t i2c_bytes = pmt_from_long(bytes);
+
+      return pmt_list4(s_op_i2c_read, rid, i2c_addr, i2c_bytes);
+    }
+
+    case OP_SPI_WRITE:
+    {
+      // Nothing interesting in the first word, skip to the next
+      uint32_t word  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      pmt_t enables   = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
+      pmt_t format    = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
+      pmt_t opt       = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
+
+      // From the next word and on is data
+      size_t spi_data_len;
+      pmt_t spi_data  = pmt_make_u8vector(len - 6, 0);   // skip rid+mbz+addr = 2 bytes
+      uint8_t *w_data  = 
+          (uint8_t *) pmt_u8vector_writeable_elements(spi_data, spi_data_len);
+
+      memcpy(w_data, d_payload + payload_offset + 8, spi_data_len);  // skip first 2 words
+
+      return pmt_list5(s_op_spi_write, enables, format, opt, spi_data);
+    }
+
+    case OP_SPI_READ:
+    {
+      // Read the RID from the first word, the rest is mbz
+      pmt_t rid       = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+
+      // Continue at the next word...
+      uint32_t word  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+      pmt_t enables   = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
+      pmt_t format    = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
+      pmt_t opt       = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
+
+      // The number of bytes is the only thing to read in the next word
+      word  = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
+      pmt_t n_bytes   = pmt_from_long((word >> CS_SPINBYTES_SHIFT) & CS_SPINBYTES_MASK);
+
+      return pmt_list6(s_op_spi_read, rid, enables, format, opt, n_bytes);
+    }
+
+    case OP_DELAY:
+    {
+      pmt_t ticks = pmt_from_long((subpkt >> CS_DELAY_SHIFT) & CS_DELAY_MASK);
+
+      return pmt_list2(s_op_delay, ticks);
+    }
+    
+    default:
+      return PMT_NIL;
+
+  }
+}
+
index e22b567fa9c20f5ed3f1dec6b93683f52d19a8c2..9290f55ae568ea81f43e270360ab5ae94e6765ef 100644 (file)
 
 #include <usrp_bytesex.h>
 #include <mb_mblock.h>
+#include <pmt.h>
+#include <iostream>
+
+#include <symbols_usrp_low_level_cs.h>
 
 static const int USB_PKT_SIZE = 512;   // bytes
 static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
@@ -38,12 +42,28 @@ class usrp_inband_usb_packet {
 
 public:
 
+  enum opcodes {
+    OP_PING_FIXED         = 0x00,
+    OP_PING_FIXED_REPLY   = 0x01,
+    OP_WRITE_REG          = 0x02,
+    OP_WRITE_REG_MASKED   = 0x03,
+    OP_READ_REG           = 0x04,
+    OP_READ_REG_REPLY     = 0x05,
+    OP_I2C_WRITE          = 0x06,
+    OP_I2C_READ           = 0x07,
+    OP_I2C_READ_REPLY     = 0x08,
+    OP_SPI_WRITE          = 0x09,
+    OP_SPI_READ           = 0x0a,
+    OP_SPI_READ_REPLY     = 0x0b,
+    OP_DELAY              = 0x0c
+  };
+
   enum flags {
     FL_OVERRUN        = 0x80000000,
     FL_UNDERRUN       = 0x40000000,
     FL_DROPPED        = 0x20000000,
-    FL_END_OF_BURST   = 0x10000000,
-    FL_START_OF_BURST = 0x08000000,
+    FL_START_OF_BURST = 0x10000000,
+    FL_END_OF_BURST   = 0x08000000,
 
     FL_ALL_FLAGS      = 0xf8000000
   };
@@ -51,8 +71,8 @@ public:
   static const int FL_OVERRUN_SHIFT = 31;
   static const int FL_UNDERRUN_SHIFT = 30;
   static const int FL_DROPPED_SHIFT = 29;
-  static const int FL_END_OF_BURST_SHIFT = 28;
-  static const int FL_START_OF_BURST_SHIFT = 27;
+  static const int FL_END_OF_BURST_SHIFT = 27;
+  static const int FL_START_OF_BURST_SHIFT = 28;
   
   static const int RSSI_MASK = 0x3f;
   static const int RSSI_SHIFT = 21;
@@ -66,6 +86,50 @@ public:
   static const int PAYLOAD_LEN_MASK = 0x1ff;
   static const int PAYLOAD_LEN_SHIFT = 0;
 
+  // Fixed size for opcode and length fields
+  static const int CS_FIXED_LEN = 2;
+
+  static const int CS_OPCODE_MASK = 0xff;
+  static const int CS_OPCODE_SHIFT = 24;
+
+  static const int CS_LEN_MASK = 0xff;
+  static const int CS_LEN_SHIFT = 16;
+
+  static const int CS_RID_MASK = 0x3f;
+  static const int CS_RID_SHIFT = 10;
+
+  static const int CS_PING_LEN = 2;
+  static const int CS_PINGVAL_MASK = 0x3ff;
+  static const int CS_PINGVAL_SHIFT = 0;
+
+  static const int CS_WRITEREG_LEN = 6;
+  static const int CS_WRITEREGMASKED_LEN = 10;
+  static const int CS_READREG_LEN = 2;
+  static const int CS_READREGREPLY_LEN = 6;
+  static const int CS_REGNUM_MASK = 0x3ff;
+  static const int CS_REGNUM_SHIFT = 0;
+
+  static const int CS_DELAY_LEN = 2;
+  static const int CS_DELAY_MASK = 0xffff;
+  static const int CS_DELAY_SHIFT = 0;
+
+  static const int CS_I2CADDR_MASK = 0x7f;
+  static const int CS_I2CADDR_SHIFT = 0;
+
+  static const int CS_I2CREAD_LEN = 3;
+  static const int CS_I2CREADBYTES_MASK = 0x7f;
+  static const int CS_I2CREADBYTES_SHIFT = 24;
+
+  static const int CS_SPIOPT_MASK = 0xffff;
+  static const int CS_SPIOPT_SHIFT = 0;
+  static const int CS_SPIFORMAT_MASK = 0xff;
+  static const int CS_SPIFORMAT_SHIFT = 16;
+  static const int CS_SPIENABLES_MASK = 0xff;
+  static const int CS_SPIENABLES_SHIFT = 24;
+  static const int CS_SPIREAD_LEN = 7;
+  static const int CS_SPINBYTES_MASK = 0xff;
+  static const int CS_SPINBYTES_SHIFT = 24;
+
 public:
   
   void set_timestamp(uint32_t timestamp){
@@ -77,7 +141,7 @@ public:
     word0 |= 1<<FL_END_OF_BURST_SHIFT;
     d_word0 = host_to_usrp_u32(word0);
   }
-
+  
   void set_header(int flags, int chan, int tag, int payload_len){
     uint32_t word0 =  ((flags & FL_ALL_FLAGS)
                        | ((chan & CHAN_MASK) << CHAN_SHIFT)
@@ -144,6 +208,27 @@ public:
     return MAX_PAYLOAD;
   }
 
+  static int max_pkt_size() {
+    return USB_PKT_SIZE;
+  }
+
+  // C/S methods
+  bool align32();
+  bool cs_ping(long rid, long ping_val);
+  bool cs_ping_reply(long rid, long ping_val);
+  bool cs_write_reg(long reg_num, long val);
+  bool cs_write_reg_masked(long reg_num, long val, long mask);
+  bool cs_read_reg(long rid, long reg_num);
+  bool cs_read_reg_reply(long rid, long reg_num, long reg_val);
+  bool cs_delay(long ticks);
+  bool cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len);
+  bool cs_i2c_read(long rid, long i2c_addr, long n_bytes);
+  bool cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len);
+  bool cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len);
+  bool cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes);
+  bool cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len);
+  int cs_len(int payload_offset);
+  pmt_t read_subpacket(int payload_offset);
 };
 
 #endif
diff --git a/usrp/host/lib/inband/usrp_interface.mbh b/usrp/host/lib/inband/usrp_interface.mbh
new file mode 100644 (file)
index 0000000..ad0f78b
--- /dev/null
@@ -0,0 +1,88 @@
+;; -*- scheme -*- ; not really, but tells emacs how to format this
+;;
+;; Copyright 2007 Free Software Foundation, Inc.
+;; 
+;; This file is part of GNU Radio
+;; 
+;; GNU Radio is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;
+
+;; ----------------------------------------------------------------
+;;              This is an mblock header file
+;;
+;; The format is very much a work-in-progress.
+;; It'll be compiled to C++.
+;; ----------------------------------------------------------------
+
+;; ----------------------------------------------------------------
+;; usrp-interface-cs
+;;
+;; Handles interaction between the usrp_sever and the USB interface
+
+(define-protocol-class usrp-interface-cs
+
+  (:outgoing
+   (cmd-usrp-open invocation-handle which-usrp)
+   (cmd-usrp-close invocation-handle)
+   (cmd-usrp-ntx-chan invocation-handle)
+   (cmd-usrp-nrx-chan invocation-handle)
+   (cmd-usrp-write invocation-handle channel data)
+   (cmd-usrp-start-reading invocation-handle channel)
+   )
+
+  (:incoming
+   (response-usrp-open invocation-handle status)
+   (response-usrp-close invocation-handle status)
+   (response-usrp-ntx-chan invocation-handle ntx-chan)
+   (response-usrp-nrx-chan invocation-handle nrx-chan)
+   (response-usrp-write invocation-handle status channel)
+   (response-usrp-read invocation-handle status data)
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; usrp-tx-cs
+;;
+;; Handles interaction between the USB interface and TX interface
+
+(define-protocol-class usrp-tx-cs
+
+  (:outgoing
+   (cmd-usrp-tx-write invocation-handle channel data tx-handle)
+   )
+
+  (:incoming
+   (response-usrp-tx-write invocation-handle status channel)
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; usrp-rx-cs
+;;
+;; Handles interaction between the USB interface and RX interface
+
+(define-protocol-class usrp-rx-cs
+
+  (:outgoing
+   (cmd-usrp-rx-start-reading invocation-handle rx-handle)
+   (cmd-usrp-rx-stop-reading invocation-handle)
+   )
+
+  (:incoming
+   (response-usrp-rx-read invocation-handle status data)
+
+   ;; There is currently no response to a stop reading
+   )
+  )
diff --git a/usrp/host/lib/inband/usrp_rx.cc b/usrp/host/lib/inband/usrp_rx.cc
new file mode 100644 (file)
index 0000000..7344a6e
--- /dev/null
@@ -0,0 +1,142 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <usrp_rx.h>
+
+#include <usrp_standard.h>
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include <stdio.h>
+
+#include <symbols_usrp_rx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+usrp_rx::usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+    d_disk_write(false)
+{
+  d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
+  
+  //d_disk_write=true;
+  
+  if(d_disk_write) {
+    d_ofile.open("rx_data.dat",std::ios::binary|std::ios::out);
+    d_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
+  }
+
+}
+
+usrp_rx::~usrp_rx() 
+{
+  if(d_disk_write) {
+    d_ofile.close();
+    d_cs_ofile.close();
+  }
+}
+
+void 
+usrp_rx::initial_transition()
+{
+  
+}
+
+void
+usrp_rx::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t port_id = msg->port_id();
+  pmt_t data = msg->data(); 
+
+  // Theoretically only have 1 message to ever expect, but
+  // want to make sure its at least what we want
+  if(pmt_eq(port_id, d_cs->port_symbol())) {
+    
+    if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
+      read_and_respond(data);
+  }
+}
+
+void
+usrp_rx::read_and_respond(pmt_t data)
+{
+  size_t ignore;
+  bool underrun;
+  unsigned int n_read;
+  unsigned int pkt_size = sizeof(transport_pkt);
+
+  pmt_t invocation_handle = pmt_nth(0, data);
+
+  // Need the handle to the RX port to send responses, this is passed
+  // by the USRP interface m-block
+  d_urx = 
+    boost::any_cast<usrp_standard_rx *>(pmt_any_ref(pmt_nth(1, data)));
+
+  if(verbose)
+    std::cout << "[usrp_rx] Waiting for packets..\n";
+
+  // Read by 512 which is packet size and send them back up
+  while(1) {
+
+    pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
+    transport_pkt *pkt = 
+      (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+
+    n_read = d_urx->read(pkt, pkt_size, &underrun);
+
+    if(n_read != pkt_size) {
+      std::cerr << "[usrp_rx] Error reading packet, shutting down\n";
+      d_cs->send(s_response_usrp_rx_read, 
+                 pmt_list3(PMT_NIL, PMT_F, PMT_NIL));
+      return;
+    }
+
+    if(underrun)
+      std::cout << "[usrp_rx] Underrun\n";
+
+    d_cs->send(s_response_usrp_rx_read, 
+               pmt_list3(PMT_NIL, PMT_T, v_pkt));
+    if(verbose)
+      std::cout << "[usrp_rx] Read 1 packet\n";
+    
+    if(d_disk_write) {
+      if(pkt->chan() == 0x1f)
+        d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
+      else
+        d_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
+
+      d_cs_ofile.flush();
+      d_ofile.flush();
+    }
+  }
+}
+
+REGISTER_MBLOCK_CLASS(usrp_rx);
diff --git a/usrp/host/lib/inband/usrp_rx.h b/usrp/host/lib/inband/usrp_rx.h
new file mode 100644 (file)
index 0000000..e1a90a7
--- /dev/null
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP_RX_H
+#define INCLUDED_USRP_RX_H
+
+#include <mb_mblock.h>
+#include <fstream>
+
+class usrp_standard_rx;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_rx : public mb_mblock
+{
+  mb_port_sptr         d_cs;
+  usrp_standard_rx     *d_urx;
+  
+  bool d_disk_write;
+  std::ofstream d_ofile;
+  std::ofstream d_cs_ofile;
+  
+ public:
+  usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+  ~usrp_rx();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ private:
+  void read_and_respond(pmt_t data);
+  void read_data();
+};
+  
+
+#endif /* INCLUDED_USRP_RX_H */
+
diff --git a/usrp/host/lib/inband/usrp_rx_stub.cc b/usrp/host/lib/inband/usrp_rx_stub.cc
new file mode 100644 (file)
index 0000000..bf78ddf
--- /dev/null
@@ -0,0 +1,183 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <usrp_rx_stub.h>
+
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_standard.h"
+#include <stdio.h>
+#include "ui_nco.h"
+#include <fstream>
+
+#include <symbols_usrp_rx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+bool usrp_rx_stop;
+
+// Used for the fake control packet response code to send the responses back up
+// the RX.  The TX stub dumps responses in to this queue.
+std::queue<pmt_t> d_cs_queue;
+
+usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+    d_samples_per_frame((long)(126)),
+    d_amplitude(16384),
+    d_disk_write(false)
+{
+  d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
+  
+  // initialize NCO
+  double freq = 100e3;
+  int interp = 32;                         // 32 -> 4MS/s
+  double sample_rate = 128e6 / interp; 
+  d_nco.set_freq(2*M_PI * freq/sample_rate);
+
+  //d_disk_write = true;
+  
+  if(d_disk_write)
+    d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
+  
+  usrp_rx_stop = false;
+}
+
+usrp_rx_stub::~usrp_rx_stub() 
+{
+  if(d_disk_write)
+    d_ofile.close();
+}
+
+void 
+usrp_rx_stub::initial_transition()
+{
+  
+}
+
+void
+usrp_rx_stub::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t port_id = msg->port_id();
+  pmt_t data = msg->data(); 
+
+  // Theoretically only have 1 message to ever expect, but
+  // want to make sure its at least what we want
+  if(pmt_eq(port_id, d_cs->port_symbol())) {
+
+    if(verbose)
+      std::cout << "[USRP_RX_STUB] Starting...\n";
+    
+    if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
+      read_and_respond(data);
+  }
+}
+
+void
+usrp_rx_stub::read_and_respond(pmt_t data)
+{
+
+  while(!usrp_rx_stop) {
+
+    long nsamples_this_frame = d_samples_per_frame;
+
+    size_t nshorts = 2 * nsamples_this_frame;  // 16-bit I & Q
+    long channel = 0;
+    long n_bytes = nshorts*2;
+    pmt_t uvec = pmt_make_s16vector(nshorts, 0);
+    size_t ignore;
+    int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
+
+    // fill in the complex sinusoid
+
+    for (int i = 0; i < nsamples_this_frame; i++){
+
+      if (1){
+        gr_complex s;
+        d_nco.sincos(&s, 1, d_amplitude);
+        // write 16-bit i & q
+        samples[2*i] =   (int16_t) s.real();
+        samples[2*i+1] = (int16_t) s.imag();
+      }
+      else {
+        gr_complex s(d_amplitude, d_amplitude);
+
+        // write 16-bit i & q
+        samples[2*i] =   (int16_t) s.real();
+        samples[2*i+1] = (int16_t) s.imag();
+      }
+    }
+    
+    if(d_disk_write)
+      d_ofile.write((const char *)samples, n_bytes);
+  
+    pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
+    transport_pkt *pkt =
+      (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+
+    pkt->set_header(0, channel, 0, n_bytes);
+    pkt->set_timestamp(0xffffffff);
+    memcpy(pkt->payload(), samples, n_bytes);
+    
+    d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
+
+    // Now lets check the shared CS queue between the TX and RX stub.  Each
+    // element in a queue is a list where the first element is an invocation
+    // handle and the second element is a PMT u8 vect representation of the
+    // CS packet response which can just be passed transparently.
+    while(!d_cs_queue.empty()) {
+      
+      pmt_t cs_pkt = d_cs_queue.front();
+      d_cs_queue.pop();
+
+      pmt_t invocation_handle = pmt_nth(0, cs_pkt);
+      pmt_t v_pkt = pmt_nth(1, cs_pkt);
+
+      d_cs->send(s_response_usrp_rx_read,   
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           v_pkt));  // Take the front CS pkt
+
+      
+      if(verbose)
+        std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
+    }
+
+  }
+  
+  usrp_rx_stop = false;
+
+  if(verbose)
+    std::cout << "[USRP_RX_STUB] Got fake RX stop\n";
+
+}
+
+REGISTER_MBLOCK_CLASS(usrp_rx_stub);
diff --git a/usrp/host/lib/inband/usrp_rx_stub.h b/usrp/host/lib/inband/usrp_rx_stub.h
new file mode 100644 (file)
index 0000000..483af5b
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP_RX_STUB_H
+#define INCLUDED_USRP_RX_STUB_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+#include "ui_nco.h"
+#include <fstream>
+#include <queue>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+extern bool usrp_rx_stop;   // used to communicate a 'stop' to the RX stub
+extern std::queue<pmt_t> d_cs_queue;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_rx_stub : public mb_mblock
+{
+ public:
+
+  mb_port_sptr d_cs;
+  usrp_standard_rx* d_urx;
+  
+  long         d_samples_per_frame;
+  
+  // for generating sine wave output
+  ui_nco<float,float>  d_nco;
+  double               d_amplitude;
+
+  bool d_disk_write;
+
+  std::ofstream d_ofile;
+  
+ public:
+  usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+  ~usrp_rx_stub();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ private:
+  void read_and_respond(pmt_t data);
+  void read_data();
+};
+  
+
+#endif /* INCLUDED_USRP_RX_H */
+
index 800bf0e15ec38133b2d33c3e5aed3eb0583ce1d3..760397dc7549ebc46d2e361ef39d6fe0de4c21ea 100644 (file)
 #include <usrp_inband_usb_packet.h>
 #include <mb_class_registry.h>
 #include <vector>
+#include <usrp_usb_interface.h>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_interface_cs.h>
+static pmt_t s_shutdown = pmt_intern("%shutdown");
 
 typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
 
-// FIXME We should machine generate these by a simple preprocessor run over this file
-//
-// These are all the messages that we expect to receive.
-//
-// We "intern" these here (make them into symbols) so that our
-// comparisions below are effectively pointer comparisons.
-
-static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
-static pmt_t s_cmd_close = pmt_intern("cmd-close");
-static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
-static pmt_t s_cmd_open = pmt_intern("cmd-open");
-static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
-static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
-static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
-static pmt_t s_cmd_xmit_raw_frame  = pmt_intern("cmd-xmit-raw-frame");
-static pmt_t s_cmd_max_capacity  = pmt_intern("cmd-max-capacity");
-static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
-static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
-static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
-static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
-static pmt_t s_response_close = pmt_intern("response-close");
-static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
-static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
-static pmt_t s_response_open = pmt_intern("response-open");
-static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
-static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
-static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
-static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
-static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
-static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+const static bool verbose = false;
 
 static std::string
 str(long x)
@@ -70,36 +50,75 @@ str(long x)
 }
 
 usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
-  : mb_mblock(rt, instance_name, user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+  d_fake_rx(false)
 {
-  // define our ports
 
+  // Dictionary for arguments to all of the components
+  pmt_t usrp_dict = user_arg;
+  
   // control & status port
   d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL); 
+  d_cs_usrp = define_port("cs_usrp", "usrp-interface-cs", false, mb_port::INTERNAL);   
 
   // ports
   //
   // (if/when we do replicated ports, these will be replaced by a
   //  single replicated port)
   for(int port=0; port < N_PORTS; port++) {
-    d_tx.push_back(define_port("tx"+str(port), "usrp-tx", true, mb_port::EXTERNAL));
-    d_rx.push_back(define_port("rx"+str(port), "usrp-rx", true, mb_port::EXTERNAL));
+
+    d_tx.push_back(define_port("tx"+str(port), 
+                               "usrp-tx", 
+                               true, 
+                               mb_port::EXTERNAL));
+
+    d_rx.push_back(define_port("rx"+str(port), 
+                               "usrp-rx", 
+                               true, 
+                               mb_port::EXTERNAL));
   }
 
-  // FIXME ... initializing to 2 channels on each for now, eventually we should
-  // query the FPGA to get these values
-  d_ntx_chan = 2;
+  define_component("usrp", "usrp_usb_interface", usrp_dict);
+  connect("self", "cs_usrp", "usrp", "cs");
+
+  d_defer=false;
+  d_opened=false;
+
+  // FIXME: needs to be returned from open, if we want to use this
   d_nrx_chan = 2;
+  d_ntx_chan = 2;
 
   // Initialize capacity on each channel to 0 and to no owner
+  // Also initialize the USRP standard tx/rx pointers to NULL
+  for(int chan=0; chan < d_ntx_chan; chan++)
+    d_chaninfo_tx.push_back(channel_info());
+
+  for(int chan=0; chan < d_nrx_chan; chan++)
+    d_chaninfo_rx.push_back(channel_info());
+
+  d_rx_chan_mask = 0;
+
+  for(int i=0; i < D_MAX_RID; i++) 
+    d_rids.push_back(rid_info());
+
+  //d_fake_rx=true;
+}
+
+void
+usrp_server::reset_channels()
+{
+
   for(int chan=0; chan < d_ntx_chan; chan++) {
     d_chaninfo_tx[chan].assigned_capacity = 0;
     d_chaninfo_tx[chan].owner = PMT_NIL;
   }
+
   for(int chan=0; chan < d_nrx_chan; chan++) {
     d_chaninfo_rx[chan].assigned_capacity = 0;
     d_chaninfo_rx[chan].owner = PMT_NIL;
   }
+
+  d_rx_chan_mask = 0;
 }
 
 usrp_server::~usrp_server()
@@ -119,78 +138,328 @@ usrp_server::handle_message(mb_message_sptr msg)
   pmt_t event = msg->signal();         // the "name" of the message
   pmt_t port_id = msg->port_id();      // which port it came in on
   pmt_t data = msg->data();
-  pmt_t metadata = msg->metadata();
   pmt_t invocation_handle;
-  pmt_t reply_data;
+  pmt_t metadata = msg->metadata();
   pmt_t status;
 
-  if (1){
+  long port;
+
+  if (pmt_eq(event, s_shutdown))       // ignore (for now)
+    return;
+
+  invocation_handle = pmt_nth(0, data);
+
+  if (0){
     std::cout << "[USRP_SERVER] event: " << event << std::endl;
     std::cout << "[USRP_SERVER] port_id: " << port_id << std::endl;
   }
 
-  // It would be nice if this were all table driven, and we could
-  // compute our state transition as f(current_state, port_id, signal)
+  // It would be nice if this were all table driven, and we could compute our
+  // state transition as f(current_state, port_id, signal)
+  
+  // A message from the USRP CS, which should *only* be responses
+  //
+  // It is important that this set come before checking messages of any other
+  // components.  This is since we always want to listen to the low level USRP
+  // server, even if we aren't initialized we are waiting for responses to
+  // become initialized.  Likewise, after the usrp_server is "closed", we still
+  // want to pass responses back from the low level.
 
-  if (pmt_eq(port_id, d_cs->port_symbol())){   // message came in on our control/status port
+  //---------------- USRP RESPONSE ---------------//
+  if (pmt_eq(port_id, d_cs_usrp->port_symbol())) { 
+    
+    //-------------- USRP OPEN ------------------//
+    if(pmt_eq(event, s_response_usrp_open)) {
+      // pass the response back over the regular CS port
+      pmt_t status = pmt_nth(1, data);
+      d_cs->send(s_response_open, pmt_list2(invocation_handle, status));
 
-    if (pmt_eq(event, s_cmd_open)){
-      // extract args from data
-      invocation_handle = pmt_nth(0, data);
-      long which_usrp = pmt_to_long(pmt_nth(1, data)); // integer usrp id, usually 0
+      if(pmt_eqv(status,PMT_T)) {
+        d_opened = true;
+        d_defer = false;
+        recall_defer_queue();
+      }
+
+      return;
+    }
+    //------------- USRP CLOSE -------------------//
+    else if (pmt_eq(event, s_response_usrp_close)) {
+      pmt_t status = pmt_nth(1, data);
+      d_cs->send(s_response_close, pmt_list2(invocation_handle, status));
+
+      if(pmt_eqv(status,PMT_T)) {
+        d_opened = false;
+        d_defer = false;
+        reset_channels();
+        recall_defer_queue();
+      }
       
-      // Do the right thing....
-      // build a reply
-      (void) which_usrp;       // avoid unused warning
+      return;
+    }
+    //--------------- USRP WRITE --------------//
+    else if (pmt_eq(event, s_response_usrp_write)) {
+      
+      pmt_t status = pmt_nth(1, data);
+      long channel = pmt_to_long(pmt_nth(2, data));
+      long port;
+
+      // Do not report back responses if they were generated from a
+      // command packet
+      if(channel == 0x1f)
+        return;
+
+      // Find the port through the owner of the channel
+      if((port = tx_port_index(d_chaninfo_tx[channel].owner)) !=-1 )
+        d_tx[port]->send(s_response_xmit_raw_frame, 
+                         pmt_list2(invocation_handle, status));
+      return;
+    }
+    //--------------- USRP READ ---------------//
+    else if (pmt_eq(event, s_response_usrp_read)) {
+
+      pmt_t status = pmt_nth(1, data);
+
+      if(!pmt_eqv(status, PMT_T)) {
+        std::cerr << "[USRP_SERVER] Error receiving packet\n";
+        return;
+      }
+      else {
+        handle_response_usrp_read(data);
+        return;
+      }
+    }
+
+    goto unhandled;
+  }
+
+  // Checking for defer on all other messages
+  if(d_defer) {
+    if (verbose)
+      std::cout << "[USRP_SERVER] Received msg while deferring (" 
+                << msg->signal() << ")\n";
+    d_defer_queue.push(msg);
+    return;
+  }
+  
+  //--------- CONTROL / STATUS ------------//
+  if (pmt_eq(port_id, d_cs->port_symbol())){
+    
+    //----------- OPEN -----------//
+    if (pmt_eq(event, s_cmd_open)){
 
-      // if everything OK
-      status = PMT_T;
-      reply_data = pmt_list2(invocation_handle, status);
+      // Reject if already open
+      if(d_opened) {
+        d_cs->send(s_response_open, pmt_list2(invocation_handle, s_err_usrp_already_opened));
+        return;
+      }
 
-      //  ...and send it
-      d_cs->send(s_response_open, reply_data);
+      // the parameters are the same to the low level interface, so we just pass 'data' along
+      d_cs_usrp->send(s_cmd_usrp_open, data);
+
+      d_defer = true;
+      
       return;
     }
+    //---------- CLOSE -----------//
     else if (pmt_eq(event, s_cmd_close)){
-      // ...
+      
+      if(!d_opened) { 
+        d_cs->send(s_response_close, pmt_list2(invocation_handle, s_err_usrp_already_closed));
+        return;
+      }
+      
+      d_defer = true;
+      d_cs_usrp->send(s_cmd_usrp_close, pmt_list1(invocation_handle));
+
+      return;
     }
+    //---------- MAX CAPACITY ----------//
     else if (pmt_eq(event, s_cmd_max_capacity)) {
-      invocation_handle = pmt_nth(0, data);
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(max_capacity()));
-      d_cs->send(s_response_max_capacity, reply_data);
+      
+      if(!d_opened) { 
+        d_cs->send(s_response_max_capacity, 
+                   pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+        return;
+      }
+
+      d_cs->send(s_response_max_capacity, 
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           pmt_from_long(max_capacity())));
       return;
     }
+    //---------- NTX CHAN --------------//
     else if (pmt_eq(event, s_cmd_ntx_chan)) {
-      invocation_handle = pmt_nth(0, data);
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(d_ntx_chan));
-      d_cs->send(s_response_ntx_chan, reply_data);
+
+      if(!d_opened) { 
+        d_cs->send(s_response_ntx_chan, 
+                   pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+        return;
+      }
+
+      d_cs->send(s_response_ntx_chan, 
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           pmt_from_long(d_ntx_chan)));
+      return;
     }
+    //---------- NRX CHAN -----------//
     else if (pmt_eq(event, s_cmd_nrx_chan)) {
-      invocation_handle = pmt_nth(0, data);
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(d_nrx_chan));
-      d_cs->send(s_response_nrx_chan, reply_data);
-    }
+
+      if(!d_opened) { 
+        d_cs->send(s_response_nrx_chan, 
+                   pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+        return;
+      }
+
+      d_cs->send(s_response_nrx_chan, 
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           pmt_from_long(d_nrx_chan)));
+      return;
+    }  
+    //--------- ALLOCATION? -----------//
     else if (pmt_eq(event, s_cmd_current_capacity_allocation)) {
-      invocation_handle = pmt_nth(0, data);
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(current_capacity_allocation()));
-      d_cs->send(s_response_current_capacity_allocation, reply_data);
+      
+      if(!d_opened) { 
+        d_cs->send(s_response_current_capacity_allocation, 
+                   pmt_list3(invocation_handle, 
+                             s_err_usrp_not_opened, 
+                             pmt_from_long(0)));
+        return;
+      }
+      
+      d_cs->send(s_response_current_capacity_allocation, 
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           pmt_from_long(current_capacity_allocation())));
+      return;
     }
     goto unhandled;
   }
+  
+  //-------------- TX ---------------//
+  if ((port = tx_port_index(port_id)) != -1) {
+    
+    //------------ ALLOCATE (TX) ----------------//
+    if (pmt_eq(event, s_cmd_allocate_channel)){
+      
+      if(!d_opened) { 
+        d_tx[port]->send(s_response_allocate_channel, 
+                          pmt_list3(invocation_handle, 
+                                    s_err_usrp_not_opened, 
+                                    pmt_from_long(0)));
+        return;
+      }
+        
+      handle_cmd_allocate_channel(d_tx[port], d_chaninfo_tx, data);
+      return;
+    }
+  
+    //----------- DEALLOCATE (TX) ---------------//
+    if (pmt_eq(event, s_cmd_deallocate_channel)) {
+    
+      if(!d_opened) {
+        d_tx[port]->send(s_response_deallocate_channel, 
+                         pmt_list3(invocation_handle, 
+                                   s_err_usrp_not_opened, 
+                                   pmt_from_long(0)));
+        return;
+      }
 
-  if (pmt_eq(event, s_cmd_allocate_channel)){
-    handle_cmd_allocate_channel(port_id, data);
-    return;
-  }
+      handle_cmd_deallocate_channel(d_tx[port], d_chaninfo_tx, data);
+      return;
+    }
+  
+    //-------------- XMIT RAW FRAME -----------------/
+    if (pmt_eq(event, s_cmd_xmit_raw_frame)){
 
-  if (pmt_eq(event, s_cmd_deallocate_channel)) {
-    handle_cmd_deallocate_channel(port_id, data);
-    return;
+      if(!d_opened) { 
+        d_tx[port]->send(s_response_xmit_raw_frame, 
+                         pmt_list2(invocation_handle, s_err_usrp_not_opened));
+        return;
+      }
+      
+      handle_cmd_xmit_raw_frame(d_tx[port], d_chaninfo_tx, data);
+      return;
+    }
+    
+    //-------------- CONTROL PACKET -----------------/
+    if (pmt_eq(event, s_cmd_to_control_channel)) {
+      
+      if(!d_opened) { 
+        d_tx[port]->send(s_response_xmit_raw_frame, 
+                         pmt_list2(invocation_handle, s_err_usrp_not_opened));
+        return;
+      }
+      
+      handle_cmd_to_control_channel(d_tx[port], d_chaninfo_tx, data);
+      return;
+
+    }
+
+    goto unhandled;
   }
+
+  //-------------- RX ---------------//
+  if ((port = rx_port_index(port_id)) != -1) {
     
-  if (pmt_eq(event, s_cmd_xmit_raw_frame)){
-    handle_cmd_xmit_raw_frame(data);
-    return;
+    //------------ ALLOCATE (RX) ----------------//
+    if (pmt_eq(event, s_cmd_allocate_channel)) {
+      
+      if(!d_opened) { 
+        d_rx[port]->send(s_response_allocate_channel, 
+                          pmt_list3(invocation_handle, 
+                                    s_err_usrp_not_opened, 
+                                    pmt_from_long(0)));
+        return;
+      }
+        
+      handle_cmd_allocate_channel(d_rx[port], d_chaninfo_rx, data);
+      return;
+    }
+  
+    //----------- DEALLOCATE (RX) ---------------//
+    if (pmt_eq(event, s_cmd_deallocate_channel)) {
+    
+      if(!d_opened) {
+        d_rx[port]->send(s_response_deallocate_channel, 
+                         pmt_list3(invocation_handle, 
+                                   s_err_usrp_not_opened, 
+                                   pmt_from_long(0)));
+        return;
+      }
+
+      handle_cmd_deallocate_channel(d_rx[port], d_chaninfo_rx, data);
+      return;
+    }
+  
+    //-------------- START RECV ----------------//
+    if (pmt_eq(event, s_cmd_start_recv_raw_samples)) {
+    
+      if(!d_opened) {
+        d_rx[port]->send(s_response_recv_raw_samples,
+                         pmt_list2(invocation_handle, s_err_usrp_not_opened));
+        return;
+      }
+
+      handle_cmd_start_recv_raw_samples(d_rx[port], d_chaninfo_rx, data);
+      return;
+    }
+    
+    //-------------- STOP RECV ----------------//
+    if (pmt_eq(event, s_cmd_stop_recv_raw_samples)) {
+    
+      if(!d_opened) 
+        return;
+
+      // FIX ME : no response for stopping? even if error? (permissions)
+      handle_cmd_stop_recv_raw_samples(d_rx[port], d_chaninfo_rx, data);
+
+      return;
+    }
+
+    goto unhandled;
   }
 
  unhandled:
@@ -231,128 +500,94 @@ long usrp_server::current_capacity_allocation() {
   return capacity;
 }
     
-void usrp_server::handle_cmd_allocate_channel(pmt_t port_id, pmt_t data) {
-
+void 
+usrp_server::handle_cmd_allocate_channel(
+                                mb_port_sptr port, 
+                                std::vector<struct channel_info> &chan_info,
+                                pmt_t data)
+{
   pmt_t invocation_handle = pmt_nth(0, data);
   long rqstd_capacity = pmt_to_long(pmt_nth(1, data));
-  long chan, port;
-  pmt_t reply_data;
+  long chan;
 
-  // If it's a TX port, allocate on a free channel, else check if it's a RX port
-  // and allocate.
-  if((port = tx_port_index(port_id)) != -1) {
+  // Check capacity exists
+  if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
 
-    // Check capacity exists
-    if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
-      reply_data = pmt_list3(invocation_handle, pmt_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL);  // no capacity available
-      d_tx[port]->send(s_response_allocate_channel, reply_data);
-      return;
-    }
+    // no capacity available
+    port->send(s_response_allocate_channel, 
+               pmt_list3(invocation_handle, 
+                         s_err_requested_capacity_unavailable, 
+                         PMT_NIL));
+    return;
+  }
 
-    // Find a free channel, assign the capacity and respond
-    for(chan=0; chan < d_ntx_chan; chan++) {
-      if(d_chaninfo_tx[chan].owner == PMT_NIL) {
-        d_chaninfo_tx[chan].owner = port_id;
-        d_chaninfo_tx[chan].assigned_capacity = rqstd_capacity;
-        reply_data = pmt_list3(invocation_handle, PMT_T, pmt_from_long(chan));
-        d_tx[port]->send(s_response_allocate_channel, reply_data);
-        return;
-      }
-    }
+  // Find a free channel, assign the capacity and respond
+  for(chan=0; chan < (long)chan_info.size(); chan++) {
 
-    std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
+    if(verbose)
+      std::cout << "[USRP_SERVER] Checking chan: " << chan
+                << " owner " << chan_info[chan].owner
+                << " size " << chan_info.size()
+                << std::endl;
 
-    reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL);  // no free TX chan found
-    d_tx[port]->send(s_response_allocate_channel, reply_data);
-    return;
-  }
+    if(chan_info[chan].owner == PMT_NIL) {
   
-  // Repeat the same process on the RX side if the port was not determined to be TX
-  if((port = rx_port_index(port_id)) != -1) {
-    
-    if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
-      reply_data = pmt_list3(invocation_handle, pmt_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL);  // no capacity available
-      d_rx[port]->send(s_response_allocate_channel, reply_data);
+      chan_info[chan].owner = port->port_symbol();
+      chan_info[chan].assigned_capacity = rqstd_capacity;
+      
+      port->send(s_response_allocate_channel, 
+                 pmt_list3(invocation_handle, 
+                           PMT_T, 
+                           pmt_from_long(chan)));
+
+      if(verbose)
+        std::cout << "[USRP_SERVER] Assigning channel: " << chan 
+                  << " to " << chan_info[chan].owner
+                  << std::endl;
       return;
     }
+  
+  }
 
-    for(chan=0; chan < d_nrx_chan; chan++) {
-      if(d_chaninfo_rx[chan].owner == PMT_NIL) {
-        d_chaninfo_rx[chan].owner = port_id;
-        d_chaninfo_rx[chan].assigned_capacity = rqstd_capacity;
-        reply_data = pmt_list3(invocation_handle, PMT_T, pmt_from_long(chan));
-        d_rx[port]->send(s_response_allocate_channel, reply_data);
-        return;
-      }
-    }
+  if (verbose)
+    std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
 
-    std::cout << "[USRP_SERVER] Couldnt find a RX chan\n";
-    reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL);  // no free RX chan found
-    d_rx[port]->send(s_response_allocate_channel, reply_data);
-    return;
-  }
+  // no free TX chan found
+  port->send(s_response_allocate_channel, 
+             pmt_list3(invocation_handle, 
+                       s_err_channel_unavailable, 
+                       PMT_NIL));
+  return;
 }
 
 // Check the port type and deallocate assigned capacity based on this, ensuring
-// that the owner of the method invocation is the owner of the port and that
-// the channel number is valid.
-void usrp_server::handle_cmd_deallocate_channel(pmt_t port_id, pmt_t data) {
+// that the owner of the method invocation is the owner of the port and that the
+// channel number is valid.
+void 
+usrp_server::handle_cmd_deallocate_channel(
+                              mb_port_sptr port, 
+                              std::vector<struct channel_info> &chan_info, 
+                              pmt_t data)
+{
 
   pmt_t invocation_handle = pmt_nth(0, data); 
   long channel = pmt_to_long(pmt_nth(1, data));
-  long port;
-  pmt_t reply_data;
-  
-  // Check that the channel number is valid, and that the calling port is the owner
-  // of the channel, and if so remove the assigned capacity.
-  if((port = tx_port_index(port_id)) != -1) {
-  
-    if(channel >= d_ntx_chan) {
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(CHANNEL_INVALID));   // not a legit channel number
-      d_tx[port]->send(s_response_deallocate_channel, reply_data);
-      return;
-    }
 
-    if(d_chaninfo_tx[channel].owner != port_id) {
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED));   // not the owner of the port
-      d_tx[port]->send(s_response_deallocate_channel, reply_data);
-      return;
-    }
-
-    d_chaninfo_tx[channel].assigned_capacity = 0;
-    d_chaninfo_tx[channel].owner = PMT_NIL;
-
-    reply_data = pmt_list2(invocation_handle, PMT_T);
-    d_tx[port]->send(s_response_deallocate_channel, reply_data);
+  // Ensure the channel is valid and the caller owns the port
+  if(!check_valid(port, channel, chan_info,
+                  pmt_list2(s_response_deallocate_channel, invocation_handle)))
     return;
-  }
-
-  // Repeated process on the RX side
-  if((port = rx_port_index(port_id)) != -1) {
   
-    if(channel >= d_nrx_chan) {
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(CHANNEL_INVALID));   // not a legit channel number
-      d_rx[port]->send(s_response_deallocate_channel, reply_data);
-      return;
-    }
-
-    if(d_chaninfo_rx[channel].owner != port_id) {
-      reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED));   // not the owner of the port
-      d_rx[port]->send(s_response_deallocate_channel, reply_data);
-      return;
-    }
-
-    d_chaninfo_rx[channel].assigned_capacity = 0;
-    d_chaninfo_rx[channel].owner = PMT_NIL;
-
-    reply_data = pmt_list2(invocation_handle, PMT_T);
-    d_rx[port]->send(s_response_deallocate_channel, reply_data);
-    return;
-  }
+  chan_info[channel].assigned_capacity = 0;
+  chan_info[channel].owner = PMT_NIL;
 
+  port->send(s_response_deallocate_channel, 
+             pmt_list2(invocation_handle, 
+                       PMT_T));
+  return;
 }
 
-void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
+void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) {
 
   size_t n_bytes, psize;
   long max_payload_len = transport_pkt::max_payload();
@@ -361,10 +596,18 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
   long channel = pmt_to_long(pmt_nth(1, data));
   const void *samples = pmt_uniform_vector_elements(pmt_nth(2, data), n_bytes);
   long timestamp = pmt_to_long(pmt_nth(3, data));
+  
+  // Ensure the channel is valid and the caller owns the port
+  if(!check_valid(port, channel, chan_info,
+                  pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+    return;
+  
+  // Determine the number of packets to allocate contiguous memory for
+  // bursting over the USB and get a pointer to the memory to be used in
+  // building the packets
+  long n_packets = 
+    static_cast<long>(std::ceil(n_bytes / (double)max_payload_len));
 
-  // Determine the number of packets to allocate contiguous memory for bursting over the
-  // USB and get a pointer to the memory to be used in building the packets
-  long n_packets = static_cast<long>(std::ceil(n_bytes / (double)max_payload_len));
   pmt_t v_packets = pmt_make_u8vector(sizeof(transport_pkt) * n_packets, 0);
 
   transport_pkt *pkts =
@@ -372,7 +615,8 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
 
   for(int n=0; n < n_packets; n++) {
 
-    long payload_len = std::min((long)(n_bytes-(n*max_payload_len)), (long)max_payload_len);
+    long payload_len = 
+      std::min((long)(n_bytes-(n*max_payload_len)), (long)max_payload_len);
   
     if(n == 0) { // first packet gets start of burst flag and timestamp
       pkts[n].set_header(pkts[n].FL_START_OF_BURST, channel, 0, payload_len);
@@ -382,14 +626,740 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
       pkts[n].set_timestamp(0xffffffff);
     }
 
-    memcpy(pkts[n].payload(), (uint8_t *)samples+(max_payload_len * n), payload_len);
+    memcpy(pkts[n].payload(), 
+           (uint8_t *)samples+(max_payload_len * n), 
+           payload_len);
+  
+  }
+
+
+  pkts[n_packets-1].set_end_of_burst(); // set the last packet's end of burst
+
+  if (verbose)
+    std::cout << "[USRP_SERVER] Received raw frame invocation: " 
+              << invocation_handle << std::endl;
+    
+  // The actual response to the write will be generated by a
+  // s_response_usrp_write
+  d_cs_usrp->send(s_cmd_usrp_write, 
+                  pmt_list3(invocation_handle, 
+                            pmt_from_long(channel), 
+                            v_packets));
+
+  return;
+}
+
+void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) 
+{
+
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t subpackets = pmt_nth(1, data);
+
+  long n_subpkts = pmt_length(subpackets);
+  long curr_subpkt = 0;
+
+  size_t psize;
+  long payload_len = 0;
+  long channel = 0x1f;
+
+  // The design of the following code is optimized for simplicity, not
+  // performance.  To performance optimize this code, the total size in bytes
+  // needed for all of the CS packets is needed to allocate contiguous memory
+  // which contains the USB packets for bursting over the bus.  However to do
+  // this the packets subpackets would need to be parsed twice and their sizes
+  // would need to be determined.
+  //
+  // The approach taken is to keep parsing the subpackets and putting them in to
+  // USB packets.  Once the USB packet is full, a write is sent for it and
+  // another packet is created.
+  //
+  // The subpacket creation methods will return false if the subpacket will not
+  // fit in to the current USB packet.  In these cases a new USB packet is
+  // created and the old is sent.
+  
+  new_packet:
+    // This code needs to become "smart" and only make a new packet when full
+    pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+    transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+    payload_len = 0;
+    
+    pkt->set_header(0, channel, 0, payload_len);
+    pkt->set_timestamp(0xffffffff);
+
+  while(curr_subpkt < n_subpkts) {
+
+    pmt_t subp = pmt_nth(curr_subpkt, subpackets);
+    pmt_t subp_cmd = pmt_nth(0, subp);
+    pmt_t subp_data = pmt_nth(1, subp);
+
+    //--------- PING FIXED --------------//
+    if(pmt_eq(subp_cmd, s_op_ping_fixed)) {
+
+      long urid     = pmt_to_long(pmt_nth(0, subp_data));
+      long pingval  = pmt_to_long(pmt_nth(1, subp_data));
+
+      // USRP server sets request ID's to keep track of which application gets
+      // what response back.  To allow a full 6-bits for an RID to the user, we
+      // keep a mapping and replace the RID's as the packets go in and out.  If
+      // there are no RID's available, the command is thrown away silently. 
+      long srid;
+      if((srid = next_rid()) == -1)
+        goto subpkt_bail;
+
+      // We use a vector to store the owner of the ping request and will use it
+      // to send the request on any RX port they own. 
+      d_rids[srid].owner = port->port_symbol();
+      d_rids[srid].user_rid = urid;
+        
+      // Adds a ping after the previous command in the pkt
+      if(!pkt->cs_ping(srid, pingval))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+
+        // Return the RID
+        d_rids[srid].owner = PMT_NIL;
+
+        goto new_packet;
+      }
+
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received ping command request"
+                  << " assigning RID " << srid << std::endl;
+
+    }
+  
+    //----------- WRITE REG ---------------//
+    if(pmt_eq(subp_cmd, s_op_write_reg)) {
+      
+      long reg_num = pmt_to_long(pmt_nth(0, subp_data));
+      long val = pmt_to_long(pmt_nth(1, subp_data));
+
+      if(!pkt->cs_write_reg(reg_num, val))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received write register request "
+                  << "("
+                  << "Reg: " << reg_num << ", "
+                  << "Val: " << val
+                  << ")\n";
+    }
+    
+    //------- WRITE REG MASKED ----------//
+    if(pmt_eq(subp_cmd, s_op_write_reg_masked)) {
+      
+      long reg_num = pmt_to_long(pmt_nth(0, subp_data));
+      long val = pmt_to_long(pmt_nth(1, subp_data));
+      long mask = pmt_to_long(pmt_nth(2, subp_data));
+
+      if(!pkt->cs_write_reg_masked(reg_num, val, mask))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received write register masked request\n";
+    }
+    
+    //------------ READ REG --------------//
+    if(pmt_eq(subp_cmd, s_op_read_reg)) {
+      
+      long urid     = pmt_to_long(pmt_nth(0, subp_data));
+      long reg_num  = pmt_to_long(pmt_nth(1, subp_data));
+
+      long srid;
+      if((srid = next_rid()) == -1)
+        goto subpkt_bail;
+
+      d_rids[srid].owner = port->port_symbol();
+      d_rids[srid].user_rid = urid;
+
+      if(!pkt->cs_read_reg(srid, reg_num))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+
+        // Return the rid
+        d_rids[srid].owner = PMT_NIL;
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received read register request"
+                  << " assigning RID " << srid << std::endl;
+    }
+    
+    //------------ DELAY --------------//
+    if(pmt_eq(subp_cmd, s_op_delay)) {
+
+      long ticks = pmt_to_long(pmt_nth(0, subp_data));
+
+      if(!pkt->cs_delay(ticks))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received delay request of "
+                  << ticks << " ticks\n";
+    }
+
+    //--------- I2C WRITE -----------//
+    // FIXME: could check that byte count does not exceed 2^8 which
+    // is the max length in the subpacket for # of bytes to read.
+    if(pmt_eq(subp_cmd, s_op_i2c_write)) {
+      
+      long i2c_addr = pmt_to_long(pmt_nth(0, subp_data));
+      pmt_t data = pmt_nth(1, subp_data);
+
+      // Get a readable address to the data which also gives us the length
+      size_t data_len;
+      uint8_t *i2c_data = (uint8_t *) pmt_u8vector_writeable_elements(data, data_len);
+
+      // Make the USB packet
+      if(!pkt->cs_i2c_write(i2c_addr, i2c_data, data_len))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received I2C write\n";
+    }
+  
+    //----------- I2C Read -------------//
+    if(pmt_eq(subp_cmd, s_op_i2c_read)) {
+      
+      long urid       = pmt_to_long(pmt_nth(0, subp_data));
+      long i2c_addr   = pmt_to_long(pmt_nth(1, subp_data));
+      long i2c_bytes  = pmt_to_long(pmt_nth(2, subp_data));
+
+      long srid;
+      if((srid = next_rid()) == -1)
+        goto subpkt_bail;
+      
+      d_rids[srid].owner = port->port_symbol();
+      d_rids[srid].user_rid = urid;
+
+      if(!pkt->cs_i2c_read(srid, i2c_addr, i2c_bytes))
+      {
+        
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+
+        d_rids[srid].owner = PMT_NIL;
+
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received I2C read\n";
+    }
+    
+    //--------- SPI WRITE -----------//
+    if(pmt_eq(subp_cmd, s_op_spi_write)) {
+      
+      long enables = pmt_to_long(pmt_nth(0, subp_data));
+      long format = pmt_to_long(pmt_nth(1, subp_data));
+      long opt = pmt_to_long(pmt_nth(2, subp_data));
+      pmt_t data = pmt_nth(3, subp_data);
+
+      // Get a readable address to the data which also gives us the length
+      size_t data_len;
+      uint8_t *spi_data = (uint8_t *) pmt_u8vector_writeable_elements(data, data_len);
+
+      // Make the USB packet
+      if(!pkt->cs_spi_write(enables, format, opt, spi_data, data_len))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received SPI write\n";
+    }
+    
+    //--------- SPI READ -----------//
+    if(pmt_eq(subp_cmd, s_op_spi_read)) {
+      
+      long urid     = pmt_to_long(pmt_nth(0, subp_data));
+      long enables  = pmt_to_long(pmt_nth(1, subp_data));
+      long format   = pmt_to_long(pmt_nth(2, subp_data));
+      long opt      = pmt_to_long(pmt_nth(3, subp_data));
+      long n_bytes  = pmt_to_long(pmt_nth(4, subp_data));
+      
+      long srid;
+      if((srid = next_rid()) == -1)
+        goto subpkt_bail;
+
+      d_rids[srid].owner = port->port_symbol();
+      d_rids[srid].user_rid = urid;
+
+      // Make the USB packet
+      if(!pkt->cs_spi_read(srid, enables, format, opt, n_bytes))
+      {
+        d_cs_usrp->send(s_cmd_usrp_write, 
+                        pmt_list3(invocation_handle, 
+                                  pmt_from_long(channel), 
+                                  v_packet));
+        
+        // Return the rid
+        d_rids[srid].owner = PMT_NIL;
+
+        goto new_packet;
+      }
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Received SPI read\n";
+    }
+
+  subpkt_bail:
+    curr_subpkt++;
+
+  }
+
+
+  // If the current packets length is > 0, we know there are subpackets that
+  // need to be sent out still.
+  if(pkt->payload_len() > 0)
+    d_cs_usrp->send(s_cmd_usrp_write, 
+                    pmt_list3(invocation_handle, 
+                              pmt_from_long(channel), 
+                              v_packet));
+
+  return;
+}
+
+void
+usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  long channel = pmt_to_long(pmt_nth(1, data));
+
+  // Ensure the channel is valid and the caller owns the port
+  if(!check_valid(port, channel, chan_info,
+                  pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+    return;
+
+  // Already started receiving samples? (another start before a stop)
+  // Check the RX channel bitmask.
+  if(d_rx_chan_mask & (1 << channel)) {
+    port->send(s_response_recv_raw_samples,
+               pmt_list5(invocation_handle,
+                         s_err_already_receiving,
+                         PMT_NIL,
+                         PMT_NIL,
+                         PMT_NIL));
+    return;
+  }
+
+  // We only need to generate a 'start reading' command down to the
+  // low level interface if no other channel is already reading
+  //
+  // We carry this over the CS interface because the lower level
+  // interface does not care about the channel, we only demux it
+  // at the usrp_server on responses.
+  if(d_rx_chan_mask == 0) {
+    
+    if(verbose)
+      std::cout << "[USRP_SERVER] Sending read request down to start recv\n";
+
+    d_cs_usrp->send(s_cmd_usrp_start_reading, pmt_list1(invocation_handle));
+  }
+
+  d_rx_chan_mask |= 1<<channel;
+  
+  return;
+}
+
+void
+usrp_server::handle_cmd_stop_recv_raw_samples(
+                        mb_port_sptr port, 
+                        std::vector<struct channel_info> &chan_info, 
+                        pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  long channel = pmt_to_long(pmt_nth(1, data));
+
+  // FIX ME : we have no responses to send an error...
+  // Ensure the channel is valid and the caller owns the port
+  //if(!check_valid(port, channel, chan_info,
+  //                pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+  //  return;
+
+  // Remove this hosts bit from the receiver mask
+  d_rx_chan_mask &= ~(1<<channel);
+
+  // We only need to generate a 'start reading' command down to the
+  // low level interface if no other channel is already reading
+  //
+  // We carry this over the CS interface because the lower level
+  // interface does not care about the channel, we only demux it
+  // at the usrp_server on responses.
+  if(d_rx_chan_mask == 0) {
+    
+    if(verbose)
+      std::cout << "[USRP_SERVER] Sending stop reading request down\n";
+
+    d_cs_usrp->send(s_cmd_usrp_stop_reading, pmt_list1(invocation_handle));
+  }
+  
+  return;
+}
+
+// Read the packet header, determine the port by the channel owner
+void
+usrp_server::handle_response_usrp_read(pmt_t data)
+{
+
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t v_pkt = pmt_nth(2, data);
+
+  size_t n_bytes;
+  size_t ignore;
+
+  if (d_fake_rx) {
+
+    pmt_t pkt = pmt_nth(2, data);
+
+    d_rx[0]->send(s_response_recv_raw_samples,
+                  pmt_list5(PMT_F,
+                            PMT_T,
+                            pkt,
+                            pmt_from_long(0xffff),
+                            PMT_NIL));
+
+    return;
+  }
+
+  // Extract the packet and return appropriately
+  transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, n_bytes);
+
+  // The channel is used to find the port to pass the samples on
+  long channel = pkt->chan();
+  long payload_len = pkt->payload_len();
+  long port;
+
+  // Ignore packets which seem to have incorrect size or size 0
+  if(payload_len > pkt->max_payload() || payload_len == 0)
+    return;
+  
+  // If the packet is a C/S packet, parse it separately
+  if(channel == 0x1f) {
+    parse_control_pkt(invocation_handle, pkt);
+    return;
+  }
+
+  if((port = rx_port_index(d_chaninfo_rx[channel].owner)) == -1)
+    return; // Don't know where to send the sample... possibility on abrupt close
+    
+  pmt_t v_samples = pmt_make_u8vector(payload_len, 0);
+  uint8_t *samples = pmt_u8vector_writeable_elements(v_samples, ignore);
+  
+  memcpy(samples, pkt->payload(), payload_len);
+
+  // Build a properties dictionary to store things such as the RSSI
+  pmt_t properties =  pmt_make_dict();
+
+  pmt_dict_set(properties,
+               pmt_intern("rssi"),
+               pmt_from_long(pkt->rssi()));
+
+  if(pkt->overrun())
+    pmt_dict_set(properties,
+                 pmt_intern("overrun"),
+                 PMT_T);
+
+  if(pkt->underrun())
+    pmt_dict_set(properties,
+                 pmt_intern("underrun"),
+                 PMT_T);
+
+  d_rx[port]->send(s_response_recv_raw_samples,
+                   pmt_list5(invocation_handle,
+                             status,
+                             v_samples,
+                             pmt_from_long(pkt->timestamp()),
+                             properties));
+  return;
+}
+
+void
+usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
+{
+
+  long payload_len = pkt->payload_len();
+  long curr_payload = 0;
+  long port;
+  
+  // We dispatch based on the control packet type, however we can extract the
+  // opcode and the length immediately which is consistent in all responses.
+  //
+  // Since each control packet can have multiple responses, we keep reading the
+  // lengths of each subpacket until we reach the payload length.  
+  while(curr_payload < payload_len) {
+
+    pmt_t sub_packet = pkt->read_subpacket(curr_payload);
+    pmt_t op_symbol = pmt_nth(0, sub_packet);
+
+    int len = pkt->cs_len(curr_payload);
+
+    if(verbose)
+      std::cout << "[USRP_SERVER] Parsing subpacket " 
+                << op_symbol << " ... length " << len << std::endl;
+
+    //----------------- PING RESPONSE ------------------//
+    if(pmt_eq(op_symbol, s_op_ping_fixed_reply)) {
+
+      long srid     = pmt_to_long(pmt_nth(1, sub_packet));
+      pmt_t pingval = pmt_nth(2, sub_packet);
+
+      long urid = d_rids[srid].user_rid;
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Found ping response "
+                  << "("
+                  << "URID: " << urid << ", "
+                  << "SRID: " << srid << ", "
+                  << "VAL: " << pingval 
+                  << ")\n";
+      
+      // Do some bounds checking incase of bogus/corrupt responses
+      if(srid > D_MAX_RID)
+        return;
+
+      pmt_t owner = d_rids[srid].owner;
+
+      // FIXME: should be 1 response for all subpackets here ?
+      if((port = tx_port_index(owner)) != -1)
+        d_tx[port]->send(s_response_from_control_channel,
+                         pmt_list4(invocation_handle,
+                                   PMT_T,
+                                   pmt_list2(s_op_ping_fixed_reply, // subp
+                                             pmt_list2(pmt_from_long(urid), 
+                                                       pingval)),
+                                   pmt_from_long(pkt->timestamp())));
+    }
+    
+    //----------------- READ REG RESPONSE ------------------//
+    else if(pmt_eq(op_symbol, s_op_read_reg_reply)) {
+
+      long srid     = pmt_to_long(pmt_nth(1, sub_packet));
+      pmt_t reg_num = pmt_nth(2, sub_packet);
+      pmt_t reg_val = pmt_nth(3, sub_packet);
+
+      long urid = d_rids[srid].user_rid;
+      
+      if(verbose)
+        std::cout << "[USRP_SERVER] Found read register response "
+                  << "("
+                  << "URID: " << urid << ", "
+                  << "SRID: " << srid << ", "
+                  << "REG: " << reg_num << ", "
+                  << "VAL: " << reg_val 
+                  << ")\n";
+
+      // Do some bounds checking to avoid seg faults
+      if(srid > D_MAX_RID)
+        return;
+      
+      pmt_t owner = d_rids[srid].owner;
+
+      // FIXME: should be 1 response for all subpackets here ?
+      if((port = tx_port_index(owner)) != -1)
+        d_tx[port]->send(s_response_from_control_channel,
+                         pmt_list4(invocation_handle,
+                                   PMT_T,
+                                   pmt_list2(s_op_read_reg_reply, // subp
+                                             pmt_list3(pmt_from_long(urid), 
+                                                       reg_num, 
+                                                       reg_val)),
+                                   pmt_from_long(pkt->timestamp())));
+    }
+
+    //------------------ I2C READ REPLY -------------------//
+    else if(pmt_eq(op_symbol, s_op_i2c_read_reply)) {
+
+      long srid       = pmt_to_long(pmt_nth(1, sub_packet));
+      pmt_t i2c_addr  = pmt_nth(2, sub_packet);
+      pmt_t i2c_data  = pmt_nth(3, sub_packet);
+
+      long urid = d_rids[srid].user_rid;
+
+      if(verbose)
+        std::cout << "[USRP_SERVER] Found i2c read reply "
+                  << "("
+                  << "URID: " << urid << ", "
+                  << "SRID: " << srid << ", "
+                  << "Addr: " << i2c_addr << ", "
+                  << "Data: " << i2c_data
+                  << ")\n";
+      
+      // Do some bounds checking to avoid seg faults
+      if(srid > D_MAX_RID)
+        return;
+
+      pmt_t owner = d_rids[srid].owner;
+
+      if((port = tx_port_index(owner)) != -1)
+        d_tx[port]->send(s_response_from_control_channel,
+                         pmt_list4(invocation_handle,
+                                   PMT_T,
+                                   pmt_list2(s_op_i2c_read_reply,
+                                             pmt_list3(pmt_from_long(urid), 
+                                                       i2c_addr,
+                                                       i2c_data)),
+                                   pmt_from_long(pkt->timestamp())));
+    }
+
+    //------------------ SPI READ REPLY -------------------//
+    else if(pmt_eq(op_symbol, s_op_spi_read_reply)) {
+      
+      long srid       = pmt_to_long(pmt_nth(1, sub_packet));
+      pmt_t spi_data  = pmt_nth(2, sub_packet);
+      
+      long urid = d_rids[srid].user_rid;
+
+      if(verbose)
+        std::cout << "[USRP_SERVER] Found SPI read reply "
+                  << "("
+                  << "URID: " << urid << ", "
+                  << "SRID: " << srid << ", "
+                  << "Data: " << spi_data
+                  << ")\n";
+
+      // Bounds check the RID
+      if(srid > D_MAX_RID)
+        return;
+
+      pmt_t owner = d_rids[srid].owner;
+
+      if((port = tx_port_index(owner)) != -1)
+        d_tx[port]->send(s_response_from_control_channel,
+                         pmt_list4(invocation_handle,
+                                   PMT_T,
+                                   pmt_list2(s_op_spi_read_reply,
+                                             pmt_list2(pmt_from_long(urid), 
+                                                       spi_data)),
+                                   pmt_from_long(pkt->timestamp())));
+    }
+
+    // Each subpacket has an unaccounted for 2 bytes which is the opcode
+    // and the length field
+    curr_payload += len + 2;
+    
+    // All subpackets are 32-bit aligned
+    int align_offset = 4 - (curr_payload % 4);
+
+    if(align_offset != 4)
+      curr_payload += align_offset;
+  }
+}
+
+void
+usrp_server::recall_defer_queue()
+{
+
+  std::vector<mb_message_sptr> recall;
+
+  while(!d_defer_queue.empty()) {
+    recall.push_back(d_defer_queue.front());
+    d_defer_queue.pop();
   }
 
-  pkts[n_packets-1].set_end_of_burst();   // set the last packet's end of burst
+  // Parse the messages that were queued while waiting for an open response
+  for(int i=0; i < (int)recall.size(); i++) 
+    handle_message(recall[i]);
+
+  return;
+}
+
+bool
+usrp_server::check_valid(mb_port_sptr port,
+                         long channel,
+                         std::vector<struct channel_info> &chan_info,
+                         pmt_t signal_info)
+{
 
-  // interface with the USRP to send the USB packet, since the memory is
-  // contiguous, this should be a serious of memory copies to the bus, each being
-  // USB_PKT_SIZE * MAX_PACKET_BURST bytes worth of data (given a full burst)
+  pmt_t response_signal = pmt_nth(0, signal_info);
+  pmt_t invocation_handle = pmt_nth(1, signal_info);
+
+  // not a valid channel number?
+  if(channel >= (long)chan_info.size() && channel != 0x1f) {
+    port->send(response_signal, 
+               pmt_list2(invocation_handle, 
+                         s_err_channel_invalid));
+
+    if(verbose)
+      std::cout << "[USRP_SERVER] Invalid channel number for event " 
+                << response_signal << std::endl;
+    return false;
+  }
+  
+  // not the owner of the port?
+  if(chan_info[channel].owner != port->port_symbol()) {
+    port->send(response_signal, 
+               pmt_list2(invocation_handle, 
+                         s_err_channel_permission_denied));
+    
+    if(verbose)
+      std::cout << "[USRP_SERVER] Invalid permissions"
+                << " for " << response_signal
+                << " from " << port->port_symbol()
+                << " proper owner is " << chan_info[channel].owner
+                << " on channel " << channel
+                << " invocation " << invocation_handle
+                << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+// Goes through the vector of RIDs and retreieves an
+// available one for use
+long
+usrp_server::next_rid()
+{
+  for(int i = 0; i < D_MAX_RID; i++)
+    if(pmt_eqv(d_rids[i].owner, PMT_NIL))
+      return i;
+
+  return -1;
 }
 
 REGISTER_MBLOCK_CLASS(usrp_server);
index d2819cd664dd6ada1e3ec26a129fe77c6467e880..81dceb1f4f1df99627059554e2286f52631ae359 100644 (file)
 
 #include <mb_mblock.h>
 #include <vector>
+#include <queue>
+#include <fstream>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
 
 /*!
- * \brief Implements the lowest-level mblock interface to the USRP
+ * \brief Implements the lowest-level mblock usb_interface to the USRP
  */
 class usrp_server : public mb_mblock
 {
 public:
 
-  enum error_codes {
-    RQSTD_CAPACITY_UNAVAIL = 0,
-    CHANNEL_UNAVAIL = 1,
-    CHANNEL_INVALID = 2,
-    PERMISSION_DENIED = 3
-  };
-
   // our ports
   enum port_types {
     RX_PORT = 0,
@@ -46,19 +44,49 @@ public:
   static const int N_PORTS = 4;
   std::vector<mb_port_sptr> d_tx, d_rx;
   mb_port_sptr d_cs;
+  mb_port_sptr d_cs_usrp;
 
   static const int D_USB_CAPACITY = 32 * 1024 * 1024;
   static const int D_MAX_CHANNELS = 16;
   long d_ntx_chan;
   long d_nrx_chan;
 
+  // Keep track of the request IDs
+  struct rid_info {
+    pmt_t owner;
+    long user_rid;
+
+    rid_info() {
+      owner = PMT_NIL;
+      user_rid = 0;
+    }
+  };
+
+  static const long D_MAX_RID = 64;
+  std::vector<rid_info> d_rids;
+  
   struct channel_info {
-    long assigned_capacity;  // the capacity currently assignedby the channel
+    long assigned_capacity;   // the capacity currently assignedby the channel
     pmt_t owner;              // port ID of the owner of the channel
+
+    channel_info() {
+      assigned_capacity = 0;
+      owner = PMT_NIL;
+    }
   };
 
-  struct channel_info d_chaninfo_tx[D_MAX_CHANNELS];
-  struct channel_info d_chaninfo_rx[D_MAX_CHANNELS];
+  long d_rx_chan_mask;    // A bitmask representing the channels in the
+                          // receiving state
+
+  std::vector<struct channel_info> d_chaninfo_tx;
+  std::vector<struct channel_info> d_chaninfo_rx;
+
+  std::queue<mb_message_sptr> d_defer_queue;
+
+  bool d_defer;
+  bool d_opened;
+
+  bool d_fake_rx;
 
 public:
   usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
@@ -71,12 +99,21 @@ protected:
   static int max_capacity() { return D_USB_CAPACITY; }
 
 private:
-  void handle_cmd_allocate_channel(pmt_t port_id, pmt_t data);
-  void handle_cmd_deallocate_channel(pmt_t port_id, pmt_t data);
-  void handle_cmd_xmit_raw_frame(pmt_t data);
+  void handle_cmd_allocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+  void handle_cmd_deallocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+  void handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+  void handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+  void handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+  void handle_cmd_stop_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
   int rx_port_index(pmt_t port_id);
   int tx_port_index(pmt_t port_id);
   long current_capacity_allocation();
+  void recall_defer_queue();
+  void reset_channels();
+  void handle_response_usrp_read(pmt_t data);
+  bool check_valid(mb_port_sptr port, long channel, std::vector<struct channel_info> &chan_info, pmt_t signal_info);
+  void parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt);
+  long next_rid();
 };
 
 #endif /* INCLUDED_USRP_SERVER_H */
index e96c3f1acac7f66f275949f46d7bd691755474ac..06ec4b996a99337ab3d98187e0112c34b80aa2e9 100644 (file)
@@ -40,9 +40,8 @@
 ;; mechanism to match asynchronous responses with the commands that
 ;; generated them.
 ;;
-;; status is either #t, indicating success, or a pair containing
-;; (status-code . message), where status-code is a symbol and message
-;; is a string.
+;; status is either #t, indicating success, or a symbol indicating an error.
+;; All symbol's names shall begin with %error-
 
 
 ;; ----------------------------------------------------------------
 
   (:incoming
 
-   (response-from-control-channel invocation-handle status list-of-subpackets)
+   (response-from-control-channel invocation-handle status list-of-subpackets timestamp)
 
    )
   )
   (:incoming
    (response-open invocation-handle status)
    (response-close invocation-handle status)
-   (response-max-capacity invocation-handle capacity)
-   (response-ntx-chan invocation-handle ntx-chan)
-   (response-nrx-chan invocation-handle nrx-chan)
-   (response-current-capacity-allocation invocation-handle capacity)
+   (response-max-capacity invocation-handle status capacity)
+   (response-ntx-chan invocation-handle status ntx-chan)
+   (response-nrx-chan invocation-handle status nrx-chan)
+   (response-current-capacity-allocation invocation-handle status capacity)
    )
   )
diff --git a/usrp/host/lib/inband/usrp_tx.cc b/usrp/host/lib/inband/usrp_tx.cc
new file mode 100644 (file)
index 0000000..a7a5e4a
--- /dev/null
@@ -0,0 +1,138 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <usrp_tx.h>
+#include <iostream>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include <usrp_standard.h>
+#include <stdio.h>
+
+#include <symbols_usrp_tx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+usrp_tx::usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+    d_disk_write(false)
+{
+  d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
+  
+  //d_disk_write=true;
+  
+  if(d_disk_write) {
+    d_ofile.open("tx_data.dat",std::ios::binary|std::ios::out);
+    d_cs_ofile.open("tx_cs.dat",std::ios::binary|std::ios::out);
+  }
+}
+
+usrp_tx::~usrp_tx() 
+{
+  if(d_disk_write) {
+    d_ofile.close();
+    d_cs_ofile.close();
+  }
+}
+
+void 
+usrp_tx::initial_transition()
+{
+  
+}
+
+void
+usrp_tx::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t port_id = msg->port_id();
+  pmt_t data = msg->data(); 
+
+  // Theoretically only have 1 message to ever expect, but
+  // want to make sure its at least what we want
+  if(pmt_eq(port_id, d_cs->port_symbol())) {
+    
+    if(pmt_eqv(event, s_cmd_usrp_tx_write))
+      write(data);
+  }
+}
+
+void
+usrp_tx::write(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t channel = pmt_nth(1, data);
+  pmt_t v_packets = pmt_nth(2, data);
+  d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
+
+  size_t n_bytes;
+  bool underrun;  // this will need to go, as it is taken care of in the packet headers
+
+  transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writeable_elements(v_packets, n_bytes);
+
+  int ret = d_utx->write (pkts, n_bytes, &underrun);
+  
+  if (0 && underrun)
+    fprintf(stderr, "uU");
+
+  if (ret == (int) n_bytes) {
+    if (verbose)
+      std::cout << "[usrp_server] Write of " << n_bytes << " successful\n";
+    // need to respond with the channel so the USRP server knows who to forward the result of
+    // the write to by looking up the owner of the channel
+    d_cs->send(s_response_usrp_tx_write,
+              pmt_list3(invocation_handle, PMT_T, channel));
+  }
+  else {
+    if (verbose)
+      std::cout << "[usrp_server] Error writing " << n_bytes << " bytes to USB bus\n";
+    d_cs->send(s_response_usrp_tx_write,
+              pmt_list3(invocation_handle, PMT_F, channel));
+  }
+    
+  long n_packets = 
+    static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
+
+  for(int i=0; i < n_packets; i++) {
+    
+    if(d_disk_write) {
+      if(pkts[i].chan() == 0x1f)
+        d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
+      else
+        d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
+
+      d_cs_ofile.flush();
+      d_ofile.flush();
+    }
+  }
+
+
+  return;
+}
+
+REGISTER_MBLOCK_CLASS(usrp_tx);
diff --git a/usrp/host/lib/inband/usrp_tx.h b/usrp/host/lib/inband/usrp_tx.h
new file mode 100644 (file)
index 0000000..546a26a
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP_TX_H
+#define INCLUDED_USRP_TX_H
+
+#include <mb_mblock.h>
+#include <fstream>
+
+class usrp_standard_tx;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_tx : public mb_mblock
+{
+  mb_port_sptr         d_cs;
+  usrp_standard_tx     *d_utx;
+  
+  bool d_disk_write;
+  std::ofstream d_ofile;
+  std::ofstream d_cs_ofile;
+  
+ public:
+  usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+  ~usrp_tx();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ private:
+  void write(pmt_t data);
+};
+  
+
+#endif /* INCLUDED_USRP_TX_H */
+
diff --git a/usrp/host/lib/inband/usrp_tx_stub.cc b/usrp/host/lib/inband/usrp_tx_stub.cc
new file mode 100644 (file)
index 0000000..7a98763
--- /dev/null
@@ -0,0 +1,344 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_tx_stub.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_standard.h"
+#include <stdio.h>
+#include <fstream>
+#include <usrp_rx_stub.h>
+
+#include <symbols_usrp_tx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+usrp_tx_stub::usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+    d_disk_write(false)
+{
+  d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
+  
+  //d_disk_write=true;
+  
+  if(d_disk_write) {
+    d_ofile.open("tx_stub_data.dat",std::ios::binary|std::ios::out);
+    d_cs_ofile.open("tx_stub_cs.dat",std::ios::binary|std::ios::out);
+  }
+}
+
+usrp_tx_stub::~usrp_tx_stub() 
+{
+  if(d_disk_write) {
+    d_ofile.close();
+    d_cs_ofile.close();
+  }
+}
+
+void 
+usrp_tx_stub::initial_transition()
+{
+  
+}
+
+void
+usrp_tx_stub::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();
+  pmt_t port_id = msg->port_id();
+  pmt_t data = msg->data(); 
+
+  // Theoretically only have 1 message to ever expect, but
+  // want to make sure its at least what we want
+  if(pmt_eq(port_id, d_cs->port_symbol())) {
+    
+    if(pmt_eqv(event, s_cmd_usrp_tx_write)) 
+      write(data);
+  }
+}
+
+void
+usrp_tx_stub::write(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t channel = pmt_nth(1, data);
+  pmt_t v_packets = pmt_nth(2, data);
+  d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
+
+  size_t n_bytes;
+
+  transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writeable_elements(v_packets, n_bytes);
+  long n_packets = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
+  
+  // Parse the packets looking for C/S packets and dump them to a disk if
+  // necessary
+  for(long i=0; i<n_packets; i++) {
+
+    if(d_disk_write) {
+      if(pkts[i].chan() == 0x1f)
+        d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
+      else
+        d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
+
+      d_cs_ofile.flush();
+      d_ofile.flush();
+    }
+
+    if(pkts[i].chan() == 0x1f)
+      parse_cs(invocation_handle, pkts[i]);
+  }
+
+  d_cs->send(s_response_usrp_tx_write,
+       pmt_list3(invocation_handle, PMT_T, channel));
+
+  return;
+}
+
+void
+usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
+{
+  
+  long payload_len = pkt.payload_len();
+  long curr_payload = 0;
+      
+  size_t ignore;
+
+  // There is the possibility that the responses for a single USB packet full of
+  // CS packets will not fit back in a single USB packet, considering some
+  // responses are greater than their commands (read registers).
+ new_packet:
+  pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
+  
+  transport_pkt *q_pkt =
+    (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+      
+  q_pkt->set_header(0, 0x1f, 0, 0);
+  q_pkt->set_timestamp(0xffffffff);
+
+  // We dispatch based on the control packet type, however we can extract the
+  // opcode and the length immediately which is consistent in all responses.
+  //
+  // Since each control packet can have multiple responses, we keep reading the
+  // lengths of each subpacket until we reach the payload length.  
+  while(curr_payload < payload_len) {
+
+    pmt_t sub_packet = pkt.read_subpacket(curr_payload);
+    pmt_t op_symbol = pmt_nth(0, sub_packet);
+
+    int len = pkt.cs_len(curr_payload);
+      
+    if(verbose)
+      std::cout << "[USRP_TX_STUB] Parsing subpacket " 
+                << op_symbol << " ... length " << len << std::endl;
+
+    //----------------- PING FIXED ------------------//
+    if(pmt_eq(op_symbol, s_op_ping_fixed)) {
+
+      long rid = pmt_to_long(pmt_nth(1, sub_packet));
+      long pingval = pmt_to_long(pmt_nth(2, sub_packet));
+
+      // Generate a reply and put it in the queue for the RX stub to read
+      if(!q_pkt->cs_ping_reply(rid, pingval))
+        goto new_packet;
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Generated ping response "
+                  << "("
+                  << "RID: " << rid << ", "
+                  << "VAL: " << pingval 
+                  << ")\n";
+    }
+
+    //----------------- READ REG ------------------//
+    if(pmt_eq(op_symbol, s_op_read_reg)) {
+
+      long rid = pmt_to_long(pmt_nth(1, sub_packet));
+      long reg_num = pmt_to_long(pmt_nth(2, sub_packet));
+      long reg_val = 0xdeef;
+
+      // Generate a reply and put it in the queue for the RX stub to read
+      if(!q_pkt->cs_read_reg_reply(rid, reg_num, reg_val))
+        goto new_packet;
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Generated read register response "
+                  << "("
+                  << "RID: " << rid << ", "
+                  << "REG: " << reg_num << ", "
+                  << "VAL: " << reg_val
+                  << ")\n";
+    }
+    
+    //----------------- DELAY ------------------//
+    if(pmt_eq(op_symbol, s_op_delay)) {
+
+      long ticks = pmt_to_long(pmt_nth(1, sub_packet));
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received delay command "
+                  << "("
+                  << "Ticks: " << ticks
+                  << ")\n";
+    }
+
+    //----------------- WRITE REG ------------------//
+    if(pmt_eq(op_symbol, s_op_write_reg)) {
+
+      pmt_t reg_num = pmt_nth(1, sub_packet);
+      pmt_t reg_val = pmt_nth(2, sub_packet);
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received write register command "
+                  << "("
+                  << "RegNum: " << reg_num << ", "
+                  << "Val: " << reg_val
+                  << ")\n";
+    }
+    
+    //----------------- WRITE REG MASK ---------------//
+    if(pmt_eq(op_symbol, s_op_write_reg_masked)) {
+
+      pmt_t reg_num = pmt_nth(1, sub_packet);
+      pmt_t reg_val = pmt_nth(2, sub_packet);
+      pmt_t mask    = pmt_nth(3, sub_packet);
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received write register command "
+                  << "("
+                  << "RegNum: " << reg_num << ", "
+                  << "Val: " << reg_val << ", "
+                  << "Mask: " << mask
+                  << ")\n";
+    }
+
+    //---------------- I2C WRITE ------------------//
+    if(pmt_eq(op_symbol, s_op_i2c_write)) {
+      pmt_t i2c_addr  = pmt_nth(1, sub_packet);
+      pmt_t i2c_data  = pmt_nth(2, sub_packet);
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received i2c write command "
+                  << "("
+                  << "Addr: " << i2c_addr << ", "
+                  << "Data: " << i2c_data
+                  << ")\n";
+    }
+
+    //---------------- I2C READ ------------------//
+    if(pmt_eq(op_symbol, s_op_i2c_read)) {
+      long rid       = pmt_to_long(pmt_nth(1, sub_packet));
+      long i2c_addr  = pmt_to_long(pmt_nth(2, sub_packet));
+      long i2c_bytes = pmt_to_long(pmt_nth(3, sub_packet));
+
+      // Create data to place as a response, filled with 0xff
+      size_t ignore;
+      pmt_t i2c_data = pmt_make_u8vector(i2c_bytes, 0xff);
+      uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, ignore);
+
+      // Generate a reply and put it in the queue for the RX stub to read
+      if(!q_pkt->cs_i2c_read_reply(rid, i2c_addr, w_data, i2c_bytes))
+        goto new_packet;
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received i2c read "
+                  << "("
+                  << "RID: " << rid << ", "
+                  << "Addr: " << i2c_addr << ", "
+                  << "Bytes: " << i2c_bytes
+                  << ")\n";
+    }
+    
+    //---------------- SPI WRITE ------------------//
+    if(pmt_eq(op_symbol, s_op_spi_write)) {
+      long enables  = pmt_to_long(pmt_nth(1, sub_packet));
+      long format   = pmt_to_long(pmt_nth(2, sub_packet));
+      long opt      = pmt_to_long(pmt_nth(3, sub_packet));
+      pmt_t data    = pmt_nth(4, sub_packet);
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received spi write command "
+                  << "("
+                  << "Enables: " << enables << ", "
+                  << "Format: " << format << ", "
+                  << "Options: " << opt << ", "
+                  << "Data: " << data
+                  << ")\n";
+    }
+
+    //---------------- SPI READ ------------------//
+    if(pmt_eq(op_symbol, s_op_spi_read)) {
+      long rid      = pmt_to_long(pmt_nth(1, sub_packet));
+      long enables  = pmt_to_long(pmt_nth(2, sub_packet));
+      long format   = pmt_to_long(pmt_nth(3, sub_packet));
+      long opt      = pmt_to_long(pmt_nth(4, sub_packet));
+      long n_bytes  = pmt_to_long(pmt_nth(5, sub_packet));
+
+      // Create data to place as a fake response
+      size_t ignore;
+      pmt_t spi_data = pmt_make_u8vector(n_bytes, 0xff);
+      uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(spi_data, ignore);
+
+      // Generate a reply and put it in the queue for the RX stub to read
+      if(!q_pkt->cs_spi_read_reply(rid, w_data, n_bytes))
+        goto new_packet;
+
+      if(verbose)
+        std::cout << "[USRP_TX_STUB] Received spi read command "
+                  << "("
+                  << "RID: " << rid << ", "
+                  << "Enables: " << enables << ", "
+                  << "Format: " << format << ", "
+                  << "Options: " << opt << ", "
+                  << "Bytes: " << n_bytes
+                  << ")\n";
+      
+    }
+
+    // Each subpacket has an unaccounted for 2 bytes which is the opcode
+    // and the length field
+    curr_payload += len + 2;
+
+    // All subpackets are 32-bit aligned
+    int align_offset = 4 - (curr_payload % 4);
+
+    if(align_offset != 4)
+      curr_payload += align_offset;
+
+  }
+
+  // If the packet has data in the payload, it needs queued
+  if(q_pkt->payload_len() > 0)
+    d_cs_queue.push(pmt_list2(invocation_handle, v_pkt));
+
+  return;
+}
+
+REGISTER_MBLOCK_CLASS(usrp_tx_stub);
diff --git a/usrp/host/lib/inband/usrp_tx_stub.h b/usrp/host/lib/inband/usrp_tx_stub.h
new file mode 100644 (file)
index 0000000..52294be
--- /dev/null
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP_TX_STUB_H
+#define INCLUDED_USRP_TX_STUB_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+#include <fstream>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_tx_stub : public mb_mblock
+{
+ public:
+
+  mb_port_sptr d_cs;
+  usrp_standard_tx* d_utx;
+  
+  std::ofstream d_ofile;
+  std::ofstream d_cs_ofile;
+
+  bool d_disk_write;
+
+ public:
+  usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+  ~usrp_tx_stub();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ private:
+  void write(pmt_t data);
+  void parse_cs(pmt_t invocation_handle, transport_pkt pkt);
+};
+  
+
+#endif /* INCLUDED_USRP_TX_STUB_H */
+
diff --git a/usrp/host/lib/inband/usrp_usb_interface.cc b/usrp/host/lib/inband/usrp_usb_interface.cc
new file mode 100644 (file)
index 0000000..b2ccba8
--- /dev/null
@@ -0,0 +1,431 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <usrp_usb_interface.h>
+
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_rx.h"
+#include <usrp_rx_stub.h>
+#include "usrp_tx.h"
+#include "usrp_standard.h"
+#include <stdio.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+#include <symbols_usrp_interface_cs.h>
+#include <symbols_usrp_tx_cs.h>
+#include <symbols_usrp_rx_cs.h>
+static pmt_t s_shutdown = pmt_intern("%shutdown");
+
+static const bool verbose = false;
+
+
+
+// need to take number of TX and RX channels as parameter
+usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg),
+  d_fpga_debug(false),
+  d_fake_usrp(false),
+  d_interp_tx(16),
+  d_interp_rx(16),
+  d_rf_freq(10e6),
+  d_rbf("inband_tx_rx.rbf")
+{
+  // Dictionary for arguments to all of the components
+  pmt_t usrp_dict = user_arg;
+  
+  // Default TX/RX interface
+  std::string tx_interface = "usrp_tx";
+  std::string rx_interface = "usrp_rx";
+  
+  if (pmt_is_dict(usrp_dict)) {
+
+    // The 'fake-usrp' key enables the TX and RX stubs if PMT_T
+    if(pmt_t fake_usrp = pmt_dict_ref(usrp_dict, 
+                                      pmt_intern("fake-usrp"), 
+                                      PMT_NIL)) {
+      if(pmt_eqv(fake_usrp, PMT_T)) {
+        tx_interface = "usrp_tx_stub";
+        rx_interface = "usrp_rx_stub";
+        d_fake_usrp=true;
+      }
+    }
+
+    // Read the TX interpolations
+    if(pmt_t interp_tx = pmt_dict_ref(usrp_dict, 
+                                      pmt_intern("interp-tx"), 
+                                      PMT_NIL)) {
+      if(!pmt_eqv(interp_tx, PMT_NIL)) 
+        d_interp_tx = pmt_to_long(interp_tx);
+    }
+    
+    // Read the RX interpolations
+    if(pmt_t interp_rx = pmt_dict_ref(usrp_dict, 
+                                      pmt_intern("interp-rx"), 
+                                      PMT_NIL)) {
+      if(!pmt_eqv(interp_rx, PMT_NIL)) 
+        d_interp_rx = pmt_to_long(interp_rx);
+    }
+
+    // Read the RBF
+    if(pmt_t rbf = pmt_dict_ref(usrp_dict, 
+                                pmt_intern("rbf"), 
+                                PMT_NIL)) {
+      if(!pmt_eqv(rbf, PMT_NIL)) 
+        d_rbf = pmt_symbol_to_string(rbf);
+    }
+
+    // The RF center frequency
+    if(pmt_t rf_freq = pmt_dict_ref(usrp_dict, 
+                                pmt_intern("rf-freq"), 
+                                PMT_NIL)) {
+      if(!pmt_eqv(rf_freq, PMT_NIL)) 
+        d_rf_freq = pmt_to_long(rf_freq);
+    }
+  }
+  
+  if (verbose) {
+    std::cout << "[USRP_USB_INTERFACE] Setting USRP RBF to " 
+              << d_rbf << std::endl;
+    
+    std::cout << "[USRP_USB_INTERFACE] Setting TX interpolation to " 
+              << d_interp_tx << std::endl;
+          
+    std::cout << "[USRP_USB_INTERFACE] Setting RX interpolation to " 
+              << d_interp_rx << std::endl;
+
+    std::cout << "[USRP_USB_INTERFACE] Using TX interface: " 
+              << tx_interface << "\n";
+
+    std::cout << "[USRP_USB_INTERFACE] Using RX interface: " 
+              << rx_interface << "\n";
+
+  }
+
+  d_cs = define_port("cs", "usrp-interface-cs", true, mb_port::EXTERNAL);      
+  d_rx_cs = define_port("rx_cs", "usrp-rx-cs", false, mb_port::INTERNAL);      
+  d_tx_cs = define_port("tx_cs", "usrp-tx-cs", false, mb_port::INTERNAL);      
+
+  // Connect to TX and RX
+  define_component("tx", tx_interface, PMT_F);
+  define_component("rx", rx_interface, PMT_F);
+  connect("self", "rx_cs", "rx", "cs");
+  connect("self", "tx_cs", "tx", "cs");
+  
+  // FIX ME: the code should query the FPGA to retrieve the number of channels and such
+  d_ntx_chan = 2;
+  d_nrx_chan = 2;
+
+  d_utx = NULL;
+  d_urx = NULL;
+  
+  d_fpga_debug=true;   // WARNING: DO NOT ENABLE WITH D'BOARDS OTHER THAN BASIC TX/RX
+
+}
+
+usrp_usb_interface::~usrp_usb_interface() 
+{ 
+
+}
+
+void 
+usrp_usb_interface::initial_transition()
+{
+
+}
+
+void
+usrp_usb_interface::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();         // the "name" of the message
+  pmt_t port_id = msg->port_id();      // which port it came in on
+  pmt_t data = msg->data();
+  pmt_t invocation_handle;
+
+  if (pmt_eq(event, s_shutdown))       // ignore (for now)
+    return;
+
+  //------------- CONTROL / STATUS -------------//
+  if (pmt_eq(port_id, d_cs->port_symbol())) {  
+
+    //------------ OPEN --------------//
+    if (pmt_eq(event, s_cmd_usrp_open)){
+      handle_cmd_open(data);
+      return;
+    }
+    //----------- CLOSE -------------//
+    else if (pmt_eq(event, s_cmd_usrp_close)) {
+      handle_cmd_close(data);
+      return;
+    }
+    //---------- NTX CHAN ----------//
+    else if (pmt_eq(event, s_cmd_usrp_ntx_chan)) {
+      invocation_handle = pmt_nth(0, data);
+      d_cs->send(s_response_usrp_ntx_chan, 
+                 pmt_list2(invocation_handle, 
+                           pmt_from_long(d_ntx_chan)));
+      return;
+    }
+    //---------- NRX CHAN ----------//
+    else if (pmt_eq(event, s_cmd_usrp_nrx_chan)) {
+      invocation_handle = pmt_nth(0, data);
+      d_cs->send(s_response_usrp_nrx_chan, 
+                 pmt_list2(invocation_handle, 
+                           pmt_from_long(d_nrx_chan)));
+      return;
+    }
+    //------------ WRITE -----------//
+    else if(pmt_eq(event, s_cmd_usrp_write)) {
+      handle_cmd_write(data);
+      return;
+    }
+    //-------- START READING --------//
+    else if(pmt_eq(event, s_cmd_usrp_start_reading)) {
+      handle_cmd_start_reading(data);
+      return;
+    }
+    //-------- STOP READING --------//
+    else if(pmt_eq(event, s_cmd_usrp_stop_reading)) {
+      handle_cmd_stop_reading(data);
+      return;
+    }
+
+    goto unhandled;
+  }
+
+  //---------------- RX ------------------//
+  if (pmt_eq(port_id, d_rx_cs->port_symbol())) {       
+
+    // Relay reads back up
+    if(pmt_eq(event, s_response_usrp_rx_read))  {
+      d_cs->send(s_response_usrp_read, data);
+      return;
+    }
+
+    goto unhandled;
+  }
+  
+  //---------------- TX ------------------//
+  if (pmt_eq(port_id, d_tx_cs->port_symbol())) {       
+
+    if(pmt_eq(event, s_response_usrp_tx_write))  {
+
+      pmt_t invocation_handle = pmt_nth(0, data);
+      pmt_t status = pmt_nth(1, data);
+      pmt_t channel = pmt_nth(2, data);
+
+      d_cs->send(s_response_usrp_write,
+                 pmt_list3(invocation_handle,
+                           status,
+                           channel));
+
+      return;
+    }
+
+    goto unhandled;
+  }
+
+ unhandled:
+  std::cout << "[USRP_USB_INTERFACE] unhandled msg: " << msg << std::endl;
+}
+
+void
+usrp_usb_interface::handle_cmd_open(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  long which_usrp = pmt_to_long(pmt_nth(1, data));
+  pmt_t reply_data;
+  if(d_fake_usrp) {
+    d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
+    return;
+  }
+
+  if (verbose)
+    std::cout << "[USRP_USB_INTERFACE] Handling open request for USRP " << which_usrp << "\n";
+
+  // Open up a standard RX and TX for communication with the USRP
+   
+  d_utx = usrp_standard_tx::make(which_usrp,
+                                d_interp_tx,
+                                1,                     // 1 channel
+                                -1,          // mux
+                                4096,        // USB block size
+                                16,          // nblocks for async transfers
+                                d_rbf
+                                );
+  
+  if(d_utx==0) {
+    if (verbose)
+      std::cout << "[USRP_USB_INTERFACE] Failed to open TX\n";
+    reply_data = pmt_list2(invocation_handle, PMT_F);
+    d_cs->send(s_response_usrp_open, reply_data);
+    return;
+  }
+
+  if(!d_utx->set_tx_freq (0,d_rf_freq)) {  // try setting center freq to 0
+    if (verbose)
+      std::cout << "[USRP_USB_INTERFACE] Failed to set center frequency on TX\n";
+    reply_data = pmt_list2(invocation_handle, PMT_F);
+    d_cs->send(s_response_usrp_open, reply_data);
+    return;
+  }
+
+  d_utx->start();
+
+  if (verbose)
+    std::cout << "[USRP_USB_INTERFACE] Setup TX channel\n";
+
+  d_urx =
+    usrp_standard_rx::make (which_usrp,
+                           d_interp_rx,                
+                           1,                  // nchan
+                           -1,           // mux
+                           0,            // set blank mode to start
+                           4096,         // USB block size
+                           16,           // number of blocks for async transfers
+          d_rbf);
+
+  if(!d_urx) {
+    if (verbose)
+      std::cout << "[usrp_server] Failed to open RX\n";
+    reply_data = pmt_list2(invocation_handle, PMT_F);
+    d_cs->send(s_response_usrp_open, reply_data);
+    return;
+  }
+
+  if(!d_urx->set_rx_freq (0, d_rf_freq)) {
+    if (verbose)
+      std::cout << "[usrp_server] Failed to set center frequency on RX\n";
+    reply_data = pmt_list2(invocation_handle, PMT_F);
+    d_cs->send(s_response_usrp_open, reply_data);
+    return;
+  }
+
+  if(d_fpga_debug) {
+    d_utx->_write_fpga_reg(FR_DEBUG_EN,0xf);
+    d_utx->_write_oe(0, 0xffff, 0xffff);
+    d_urx->_write_oe(0, 0xffff, 0xffff);
+    d_utx->_write_oe(1, 0xffff, 0xffff);
+    d_urx->_write_oe(1, 0xffff, 0xffff);
+
+//    while(1){
+//      for(int i=0; i<0xffff; i++) 
+//        d_urx->write_io(0, i, 0xffff);
+//    }
+  }
+  
+  if (verbose)
+    std::cout << "[USRP_USB_INTERFACE] Setup RX channel\n";
+
+  d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
+}
+
+void
+usrp_usb_interface::handle_cmd_write(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t channel = pmt_nth(1, data);
+  pmt_t pkts = pmt_nth(2, data);
+
+  pmt_t tx_handle = pmt_make_any(d_utx);
+
+  d_tx_cs->send(s_cmd_usrp_tx_write, 
+                pmt_list4(invocation_handle, 
+                          channel,
+                          pkts,
+                          tx_handle));
+
+  return;
+}
+
+void
+usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  
+  if(verbose)
+    std::cout << "[USRP_USB_INTERFACE] Starting RX...\n";
+
+  if(!d_fake_usrp)
+    d_urx->start();
+
+  pmt_t rx_handle = pmt_make_any(d_urx);
+
+  d_rx_cs->send(s_cmd_usrp_rx_start_reading, pmt_list2(PMT_NIL, rx_handle));
+
+  return;
+}
+
+void
+usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+  
+  if(!d_fake_usrp) {
+    if(verbose)
+      std::cout << "[USRP_USB_INTERFACE] Stopping RX...\n";
+    d_urx->stop();
+  }
+  else {
+    if(verbose)
+      std::cout << "[USRP_USB_INTERFACE] Stopping fake RX...\n";
+    usrp_rx_stop = true;  // extern to communicate with stub to wait
+  }
+
+  return;
+}
+
+void
+usrp_usb_interface::handle_cmd_close(pmt_t data)
+{
+  pmt_t invocation_handle = pmt_nth(0, data);
+
+  if(d_fake_usrp) {
+    d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
+    return;
+  }
+  
+  if (verbose)
+    std::cout << "[USRP_USB_INTERFACE] Handling close request for USRP\n";
+
+  delete d_utx;
+  d_utx = 0;
+
+  delete d_urx;
+  d_urx = 0;
+
+  d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
+
+  shutdown_all(PMT_T);
+}
+
+
+REGISTER_MBLOCK_CLASS(usrp_usb_interface);
diff --git a/usrp/host/lib/inband/usrp_usb_interface.h b/usrp/host/lib/inband/usrp_usb_interface.h
new file mode 100644 (file)
index 0000000..42cda7a
--- /dev/null
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_USRP_USB_INTERFACE_H
+#define INCLUDED_USRP_USB_INTERFACE_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_usb_interface : public mb_mblock
+{
+ public:
+
+  usrp_standard_tx* d_utx;
+  usrp_standard_rx* d_urx;
+  
+  mb_port_sptr d_cs;
+  mb_port_sptr  d_rx_cs;
+  mb_port_sptr  d_tx_cs;
+  
+  long d_ntx_chan;
+  long d_nrx_chan;
+
+  long d_fpga_debug;
+
+  bool d_fake_usrp;
+
+  long d_interp_tx;
+  long d_interp_rx;
+
+  long d_rf_freq;
+
+  std::string d_rbf;
+
+ public:
+  usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+  ~usrp_usb_interface();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ private:
+  void handle_cmd_open(pmt_t data);
+  void handle_cmd_close(pmt_t data);
+  void handle_cmd_write(pmt_t data);
+  void handle_cmd_start_reading(pmt_t data);
+  void handle_cmd_stop_reading(pmt_t data);
+};
+  
+
+#endif /* INCLUDED_USRP_USB_INTERFACE_H */