Merged features/inband-usb -r6431:8293 into trunk.
[debian/gnuradio] / usrp / host / lib / inband / usrp_server.cc
index 1948a43b2945de042bd356d1f39a7a6cfcf28905..6a3643e568804aef7fa505c4e07a0db2b9049507 100644 (file)
@@ -29,6 +29,8 @@
 #include <vector>
 #include <usrp_usb_interface.h>
 #include <string.h>
+#include <fpga_regs_common.h>
+#include <fpga_regs_standard.h>
 
 #include <symbols_usrp_server_cs.h>
 #include <symbols_usrp_channel.h>
@@ -53,13 +55,42 @@ 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),
+  d_fpga_debug(false),
+  d_interp_tx(128),     // these should match the lower level defaults (rx also)
+  d_decim_rx(128),
   d_fake_rx(false)
 {
   if(verbose)
     std::cout << "[USRP_SERVER] Initializing...\n";
 
   // Dictionary for arguments to all of the components
-  pmt_t usrp_dict = user_arg;
+  d_usrp_dict = user_arg;
+  
+  if (pmt_is_dict(d_usrp_dict)) {
+
+    if(pmt_t fpga_debug = pmt_dict_ref(d_usrp_dict, 
+                                      pmt_intern("fpga-debug"), 
+                                      PMT_NIL)) {
+      if(pmt_eqv(fpga_debug, PMT_T)) 
+        d_fpga_debug=true;
+    }
+    
+    // Read the TX interpolations
+    if(pmt_t interp_tx = pmt_dict_ref(d_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 decimation rate
+    if(pmt_t decim_rx = pmt_dict_ref(d_usrp_dict, 
+                                      pmt_intern("decim-rx"), 
+                                      PMT_NIL)) {
+      if(!pmt_eqv(decim_rx, PMT_NIL)) 
+        d_decim_rx = pmt_to_long(decim_rx);
+    }
+  }
   
   // control & status port
   d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL); 
@@ -82,7 +113,7 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
                                mb_port::EXTERNAL));
   }
 
-  define_component("usrp", "usrp_usb_interface", usrp_dict);
+  define_component("usrp", "usrp_usb_interface", d_usrp_dict);
   connect("self", "cs_usrp", "usrp", "cs");
 
   d_defer=false;
@@ -108,6 +139,10 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
   //d_fake_rx=true;
 }
 
+/*!
+ * \brief resets the assigned capacity and owners of each RX and TX channel from
+ * allocations.
+ */
 void
 usrp_server::reset_channels()
 {
@@ -136,6 +171,11 @@ usrp_server::initial_transition()
   // the initial transition
 }
 
+/*!
+ * \brief Reads all incoming messages to USRP server from the TX, RX, and the CS
+ * ports.  This drives the state of USRP server and dispatches based on the
+ * message.
+ */
 void
 usrp_server::handle_message(mb_message_sptr msg)
 {
@@ -178,6 +218,9 @@ usrp_server::handle_message(mb_message_sptr msg)
       pmt_t status = pmt_nth(1, data);
       d_cs->send(s_response_open, pmt_list2(invocation_handle, status));
 
+      //reset_all_registers();
+      //initialize_registers();
+
       if(pmt_eqv(status,PMT_T)) {
         d_opened = true;
         d_defer = false;
@@ -209,7 +252,7 @@ usrp_server::handle_message(mb_message_sptr msg)
 
       // Do not report back responses if they were generated from a
       // command packet
-      if(channel == 0x1f)
+      if(channel == CONTROL_CHAN)
         return;
 
       // Find the port through the owner of the channel
@@ -470,7 +513,14 @@ usrp_server::handle_message(mb_message_sptr msg)
   std::cout << "[USRP_SERVER] unhandled msg: " << msg << std::endl;
 }
 
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is a TX port, or to find an index in the d_tx vector which stores
+ * the port.
+ *
+ * \returns -1 if \p port_id is not in the d_tx vector (i.e., it's not a TX
+ * port), otherwise returns an index in the d_tx vector which stores the port.
+ */
 int usrp_server::tx_port_index(pmt_t port_id) {
 
   for(int i=0; i < (int) d_tx.size(); i++) 
@@ -480,7 +530,14 @@ int usrp_server::tx_port_index(pmt_t port_id) {
   return -1;
 }
 
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is an RX port, or to find an index in the d_rx vector which
+ * stores the port.
+ *
+ * \returns -1 if \p port_id is not in the d_rx vector (i.e., it's not an RX
+ * port), otherwise returns an index in the d_rx vector which stores the port.
+ */
 int usrp_server::rx_port_index(pmt_t port_id) {
   
   for(int i=0; i < (int) d_rx.size(); i++) 
@@ -490,8 +547,12 @@ int usrp_server::rx_port_index(pmt_t port_id) {
   return -1;
 }
 
-// Go through all TX and RX channels, sum up the assigned capacity
-// and return it
+/*!
+ * \brief Determines the current total capacity allocated by all RX and TX
+ * channels.
+ *
+ * \returns the total allocated capacity
+ */
 long usrp_server::current_capacity_allocation() {
   long capacity = 0;
 
@@ -504,6 +565,14 @@ long usrp_server::current_capacity_allocation() {
   return capacity;
 }
     
+
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to allocate a channel (cmd-allocate-channel).  The method
+ * checks if the requested capacity exists and if so it will reserve it for the
+ * caller on the channel that is returned via a response-allocate-channel
+ * signal.
+ */
 void 
 usrp_server::handle_cmd_allocate_channel(
                                 mb_port_sptr port, 
@@ -564,9 +633,13 @@ usrp_server::handle_cmd_allocate_channel(
   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.
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to deallocate a channel (cmd-deallocate-channel).  The method
+ * ensures that the sender of the signal owns the channel and that the channel
+ * number is valid.  A response-deallocate-channel signal is sent back with the
+ * result of the deallocation.
+ */
 void 
 usrp_server::handle_cmd_deallocate_channel(
                               mb_port_sptr port, 
@@ -591,8 +664,26 @@ usrp_server::handle_cmd_deallocate_channel(
   return;
 }
 
-void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) {
-
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to transmit a frame (cmd-xmit-raw-frame).  The method
+ * allocates enough memory to support a burst of packets which contain the frame
+ * over the bus of the frame, sets the packet headers, and sends a signal to the
+ * lower block for the data (packets) to be written to the bus.  
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel the frame is to be transmitted on are passed to ensure that the
+ * caller owns the channel.
+ *
+ * The \p data parameter is in the format of a cmd-xmit-raw-frame signal.
+ *
+ * The properties
+ */
+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();
 
@@ -667,7 +758,8 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
               << invocation_handle << std::endl;
     
   // The actual response to the write will be generated by a
-  // s_response_usrp_write
+  // s_response_usrp_write since we cannot determine whether to transmit was
+  // successful until we hear from the lower layers.
   d_cs_usrp->send(s_cmd_usrp_write, 
                   pmt_list3(invocation_handle, 
                             pmt_from_long(channel), 
@@ -676,7 +768,29 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
   return;
 }
 
-void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) 
+/*!
+ * \brief Called by the handle_message() method to parse incoming control/status
+ * signals (cmd-to-control-channel).  
+ * 
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter is in the format of a PMT list, where each element
+ * follows the format of a control/status signal (i.e. op-ping-fixed).
+ *
+ * The method will parse all of the C/S commands included in \p data and place
+ * the commands in to a lower level packet sent to the control channel.  The
+ * method will pack as many commands as possible in t oa single packet, and once
+ * it is fill generate as many lower level packets as needed.
+ *
+ * Anything that needs to be returned to the sender of the signal (i.e. the
+ * value of a register) will be generated by the parse_control_pkt() method as
+ * the responses to the commands are read back from the USRP.
+ */
+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);
@@ -687,7 +801,10 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
 
   size_t psize;
   long payload_len = 0;
-  long channel = 0x1f;
+  long channel = CONTROL_CHAN;
+
+  if(verbose)
+    std::cout << "[USRP_SERVER] Handling " << n_subpkts << " commands\n";
 
   // The design of the following code is optimized for simplicity, not
   // performance.  To performance optimize this code, the total size in bytes
@@ -990,8 +1107,22 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
   return;
 }
 
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is a
+ * command to start reading samples from the USRP (cmd-start-recv-raw-samples).  
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-start-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to receive the samples on.
+ */
 void
-usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+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));
@@ -1032,6 +1163,18 @@ usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<st
   return;
 }
 
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * stop receiving samples from the USRP (cmd-stop-recv-raw-samples).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-stop-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to stop receiving the
+ * samples from.
+ */
 void
 usrp_server::handle_cmd_stop_recv_raw_samples(
                         mb_port_sptr port, 
@@ -1067,7 +1210,22 @@ usrp_server::handle_cmd_stop_recv_raw_samples(
   return;
 }
 
-// Read the packet header, determine the port by the channel owner
+/*!
+ * \brief Called by the handle_message() method when an incoming signal is
+ * generated to USRP server that contains raw samples from the USRP.  This
+ * method generates the response-recv-raw-samples signals that are the result of
+ * a cmd-start-recv-raw-samples signal.
+ *
+ * The raw lower-level packet is extracted from \p data, where the format for \p
+ * data is a PMT list.  The PMT \p data list should contain an invocation handle
+ * as the first element, the status of the lower-level read as the second
+ * element, and a uniform vector representation of the packets as the third
+ * element.  
+ *
+ * The packet contains a channel field that the samples are destined to, and the
+ * method determines where to send the samples based on this channel since each
+ * channel has an associated port which allocated it.
+ */
 void
 usrp_server::handle_response_usrp_read(pmt_t data)
 {
@@ -1106,7 +1264,7 @@ usrp_server::handle_response_usrp_read(pmt_t data)
     return;
   
   // If the packet is a C/S packet, parse it separately
-  if(channel == 0x1f) {
+  if(channel == CONTROL_CHAN) {
     parse_control_pkt(invocation_handle, pkt);
     return;
   }
@@ -1137,14 +1295,28 @@ usrp_server::handle_response_usrp_read(pmt_t data)
                  PMT_T);
 
   d_rx[port]->send(s_response_recv_raw_samples,
-                   pmt_list5(invocation_handle,
+                   pmt_list6(invocation_handle,
                              status,
                              v_samples,
                              pmt_from_long(pkt->timestamp()),
+                             pmt_from_long(channel),
                              properties));
   return;
 }
 
+/*!
+ * \brief Called by handle_response_usrp_read() when the incoming packet has a
+ * channel of CONTROL_CHAN.  This means that the incoming packet contains a
+ * response for a command sent to the control channel, which this method will
+ * parse.
+ *
+ * The \p pkt parameter is a pointer to the full packet (transport_pkt) in
+ * memory.
+ *
+ * Given that all commands sent to the control channel that require responses
+ * will carry an RID (request ID), the method will use the RID passed back with
+ * the response to determine which port the response should be sent on.
+ */
 void
 usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
 {
@@ -1190,6 +1362,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
         return;
 
       pmt_t owner = d_rids[srid].owner;
+      
+      // Return the RID
+      d_rids[srid].owner = PMT_NIL;
 
       // FIXME: should be 1 response for all subpackets here ?
       if((port = tx_port_index(owner)) != -1)
@@ -1225,6 +1400,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
         return;
       
       pmt_t owner = d_rids[srid].owner;
+      
+      // Return the RID
+      d_rids[srid].owner = PMT_NIL;
 
       // FIXME: should be 1 response for all subpackets here ?
       if((port = tx_port_index(owner)) != -1)
@@ -1261,6 +1439,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
         return;
 
       pmt_t owner = d_rids[srid].owner;
+      
+      // Return the RID
+      d_rids[srid].owner = PMT_NIL;
 
       if((port = tx_port_index(owner)) != -1)
         d_tx[port]->send(s_response_from_control_channel,
@@ -1294,6 +1475,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
         return;
 
       pmt_t owner = d_rids[srid].owner;
+      
+      // Return the RID
+      d_rids[srid].owner = PMT_NIL;
 
       if((port = tx_port_index(owner)) != -1)
         d_tx[port]->send(s_response_from_control_channel,
@@ -1317,6 +1501,10 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
   }
 }
 
+/*!
+ * \brief Used to recall all incoming signals that were deferred when USRP
+ * server was in the initialization state.
+ */
 void
 usrp_server::recall_defer_queue()
 {
@@ -1335,6 +1523,25 @@ usrp_server::recall_defer_queue()
   return;
 }
 
+/*!
+ * \brief Commonly called by any method which handles outgoing frames or control
+ * packets to the USRP to check if the port on which the signal was sent owns
+ * the channel the outgoing packet will be associated with.   This helps ensure
+ * that applications do not send data on other application's ports.
+ *
+ * The \p port parameter is the port symbol that the caller wishes to determine
+ * owns the channel specified by \p chan_info.  
+ *
+ * The \p signal_info parameter is a PMT list containing two elements: the
+ * response signal to use if the permissions are invalid, and the invocation
+ * handle that was passed.  This allows the method to generate detailed failure
+ * responses to signals without having to return some sort of structured
+ * information which the caller must then parse and interpret to determine the
+ * failure type.
+ *
+ * \returns true if \p port owns the channel specified by \p chan_info, false
+ * otherwise.
+ */
 bool
 usrp_server::check_valid(mb_port_sptr port,
                          long channel,
@@ -1346,7 +1553,7 @@ usrp_server::check_valid(mb_port_sptr port,
   pmt_t invocation_handle = pmt_nth(1, signal_info);
 
   // not a valid channel number?
-  if(channel >= (long)chan_info.size() && channel != 0x1f) {
+  if(channel >= (long)chan_info.size() && channel != CONTROL_CHAN) {
     port->send(response_signal, 
                pmt_list2(invocation_handle, 
                          s_err_channel_invalid));
@@ -1377,8 +1584,12 @@ usrp_server::check_valid(mb_port_sptr port,
   return true;
 }
 
-// Goes through the vector of RIDs and retreieves an
-// available one for use
+/*!
+ * \brief Finds the next available RID for internal USRP server use with control
+ * and status packets.
+ *
+ * \returns the next valid RID or -1 if no more RIDs are available.
+ */
 long
 usrp_server::next_rid()
 {
@@ -1386,7 +1597,264 @@ usrp_server::next_rid()
     if(pmt_eqv(d_rids[i].owner, PMT_NIL))
       return i;
 
+  if(verbose)
+    std::cout << "[USRP_SERVER] No RIDs left\n";
   return -1;
 }
 
+/*!
+ * \brief Called by handle_message() when USRP server gets a response that the
+ * USRP was opened successfully to initialize the registers using the new
+ * register read/write control packets.
+ */
+void
+usrp_server::initialize_registers()
+{
+  // We use handle_cmd_to_control_channel() to create the register writes using
+  // PMT_NIL as the response port to tell usrp_server not to pass the response
+  // up to any application.
+  if(verbose)
+    std::cout << "[USRP_SERVER] Initializing registers...\n";
+
+  // RX mode to normal (0)
+  set_register(FR_MODE, 0);
+
+  // FPGA debugging?
+  if(d_fpga_debug) {
+    set_register(FR_DEBUG_EN, 1);
+    // FIXME: need to figure out exact register writes to control daughterboard
+    // pins that need to be written to
+  } else {
+    set_register(FR_DEBUG_EN, 0);
+  }
+
+  // Set the transmit sample rate divisor, which is 4-1
+  set_register(FR_TX_SAMPLE_RATE_DIV, 3);
+
+  // Dboard IO buffer and register settings
+  set_register(FR_OE_0, (0xffff << 16) | 0x0000);
+  set_register(FR_IO_0, (0xffff << 16) | 0x0000);
+  set_register(FR_OE_1, (0xffff << 16) | 0x0000);
+  set_register(FR_IO_1, (0xffff << 16) | 0x0000);
+  set_register(FR_OE_2, (0xffff << 16) | 0x0000);
+  set_register(FR_IO_2, (0xffff << 16) | 0x0000);
+  set_register(FR_OE_3, (0xffff << 16) | 0x0000);
+  set_register(FR_IO_3, (0xffff << 16) | 0x0000);
+
+  // zero Tx side Auto Transmit/Receive regs
+  set_register(FR_ATR_MASK_0, 0); 
+  set_register(FR_ATR_TXVAL_0, 0);
+  set_register(FR_ATR_RXVAL_0, 0);
+  set_register(FR_ATR_MASK_1, 0); 
+  set_register(FR_ATR_TXVAL_1, 0);
+  set_register(FR_ATR_RXVAL_1, 0);
+  set_register(FR_ATR_MASK_2, 0);
+  set_register(FR_ATR_TXVAL_2, 0);
+  set_register(FR_ATR_RXVAL_2, 0);
+  set_register(FR_ATR_MASK_3, 0);
+  set_register(FR_ATR_TXVAL_3, 0);
+  set_register(FR_ATR_RXVAL_3, 0);
+
+  // Configure TX mux, this is a hacked value
+  set_register(FR_TX_MUX, 0x00000081);
+
+  // Set the interpolation rate, which is the rate divided by 4, minus 1
+  set_register(FR_INTERP_RATE, (d_interp_tx/4)-1);
+
+  // Apparently this register changes again
+  set_register(FR_TX_MUX, 0x00000981);
+
+  // Set the receive sample rate divisor, which is 2-1
+  set_register(FR_RX_SAMPLE_RATE_DIV, 1);
+
+  // DC offset
+  set_register(FR_DC_OFFSET_CL_EN, 0x0000000f);
+
+  // Reset the DC correction offsets
+  set_register(FR_ADC_OFFSET_0, 0);
+  set_register(FR_ADC_OFFSET_1, 0);
+
+  // Some hard-coded RX configuration
+  set_register(FR_RX_FORMAT, 0x00000300);
+  set_register(FR_RX_MUX, 1);
+
+  // RX decimation rate is divided by two, then subtract 1
+  set_register(FR_DECIM_RATE, (d_decim_rx/2)-1);
+
+  // More hard coding
+  set_register(FR_RX_MUX, 0x000e4e41);
+
+  // Resetting RX registers
+  set_register(FR_RX_PHASE_0, 0);
+  set_register(FR_RX_PHASE_1, 0);
+  set_register(FR_RX_PHASE_2, 0);
+  set_register(FR_RX_PHASE_3, 0);
+  set_register(FR_RX_FREQ_0, 0x28000000);
+  set_register(FR_RX_FREQ_1, 0);
+  set_register(FR_RX_FREQ_2, 0);
+  set_register(FR_RX_FREQ_3, 0);
+
+  // Enable debug bus
+  set_register(FR_DEBUG_EN, 0xf);
+  set_register(FR_OE_0, -1);
+  set_register(FR_OE_1, -1);
+  set_register(FR_OE_2, -1);
+  set_register(FR_OE_3, -1);
+
+  // DEBUGGING
+  //check_register_initialization();
+}
+
+// FIXME: used for debugging to determine if all the registers are actually
+// being set correctly
+void
+usrp_server::check_register_initialization()
+{
+  // RX mode to normal (0)
+  read_register(FR_MODE);
+
+  // FPGA debugging?
+  if(d_fpga_debug) {
+    read_register(FR_DEBUG_EN);
+    // FIXME: need to figure out exact register writes to control daughterboard
+    // pins that need to be written to
+  } else {
+    read_register(FR_DEBUG_EN);
+  }
+
+  // Set the transmit sample rate divisor, which is 4-1
+  read_register(FR_TX_SAMPLE_RATE_DIV);
+
+  // Dboard IO buffer and register settings
+  read_register(FR_OE_0);
+  read_register(FR_IO_0);
+  read_register(FR_OE_1);
+  read_register(FR_IO_1);
+  read_register(FR_OE_2);
+  read_register(FR_IO_2);
+  read_register(FR_OE_3);
+  read_register(FR_IO_3);
+
+  // zero Tx side Auto Transmit/Receive regs
+  read_register(FR_ATR_MASK_0); 
+  read_register(FR_ATR_TXVAL_0);
+  read_register(FR_ATR_RXVAL_0);
+  read_register(FR_ATR_MASK_1); 
+  read_register(FR_ATR_TXVAL_1);
+  read_register(FR_ATR_RXVAL_1);
+  read_register(FR_ATR_MASK_2);
+  read_register(FR_ATR_TXVAL_2);
+  read_register(FR_ATR_RXVAL_2);
+  read_register(FR_ATR_MASK_3);
+  read_register(FR_ATR_TXVAL_3);
+  read_register(FR_ATR_RXVAL_3);
+
+  // Configure TX mux, this is a hacked value
+  read_register(FR_TX_MUX);
+
+  // Set the interpolation rate, which is the rate divided by 4, minus 1
+  read_register(FR_INTERP_RATE);
+
+  // Apparently this register changes again
+  read_register(FR_TX_MUX);
+
+  // Set the receive sample rate divisor, which is 2-1
+  read_register(FR_RX_SAMPLE_RATE_DIV);
+
+  // DC offset
+  read_register(FR_DC_OFFSET_CL_EN);
+
+  // Reset the DC correction offsets
+  read_register(FR_ADC_OFFSET_0);
+  read_register(FR_ADC_OFFSET_1);
+
+  // Some hard-coded RX configuration
+  read_register(FR_RX_FORMAT);
+  read_register(FR_RX_MUX);
+
+  // RX decimation rate is divided by two, then subtract 1
+  read_register(FR_DECIM_RATE);
+
+  // More hard coding
+  read_register(FR_RX_MUX);
+
+  // Resetting RX registers
+  read_register(FR_RX_PHASE_0);
+  read_register(FR_RX_PHASE_1);
+  read_register(FR_RX_PHASE_2);
+  read_register(FR_RX_PHASE_3);
+  read_register(FR_RX_FREQ_0);
+  read_register(FR_RX_FREQ_1);
+  read_register(FR_RX_FREQ_2);
+  read_register(FR_RX_FREQ_3);
+}
+
+/*!
+ * \brief Used to generate FPGA register write commands to reset all of the FPGA
+ * registers to a value of 0.
+ */
+void
+usrp_server::reset_all_registers()
+{
+  for(int i=0; i<64; i++)
+    set_register(i, 0);
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register write.
+ *
+ * The \p reg parameter is the register number that the value \p val will be
+ * written to.
+ */
+void
+usrp_server::set_register(long reg, long val)
+{
+  size_t psize;
+  long payload_len = 0;
+
+  pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+  transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+  
+  pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+  pkt->set_timestamp(0xffffffff);
+
+  pkt->cs_write_reg(reg, val);
+
+  d_cs_usrp->send(s_cmd_usrp_write, 
+                  pmt_list3(PMT_NIL, 
+                            pmt_from_long(CONTROL_CHAN), 
+                            v_packet));
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register read.  This is important to use internally so that
+ * USRP server can bypass the use of RIDs with register reads, as they are not
+ * needed and it would use up the finite number of RIDs available for use for
+ * applications to receive responses.
+ *
+ * The \p reg parameter is the register number that the value should be read
+ * from.
+ */
+void
+usrp_server::read_register(long reg)
+{
+  size_t psize;
+  long payload_len = 0;
+
+  pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+  transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+  
+  pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+  pkt->set_timestamp(0xffffffff);
+
+  pkt->cs_read_reg(0, reg);
+
+  d_cs_usrp->send(s_cmd_usrp_write, 
+                  pmt_list3(PMT_NIL, 
+                            pmt_from_long(CONTROL_CHAN), 
+                            v_packet));
+}
+
 REGISTER_MBLOCK_CLASS(usrp_server);