commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r5209 - in gnuradio/branches/developers/thottelt/inban


From: thottelt
Subject: [Commit-gnuradio] r5209 - in gnuradio/branches/developers/thottelt/inband: gnuradio-core/src/lib/gengen gr-atsc/src/lib mblock/src/lib pmt/src/lib pmt/src/scheme/gnuradio usrp/host/lib/inband usrp/host/lib/legacy
Date: Tue, 1 May 2007 14:16:45 -0600 (MDT)

Author: thottelt
Date: 2007-05-01 14:16:37 -0600 (Tue, 01 May 2007)
New Revision: 5209

Added:
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/getres.cc
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.cc
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.h
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_disconnect.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.h
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.cc
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.h
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/dump_packets.py
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/gen_test_packets.py
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usb_packet.py
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_inband_usb_packet.h
Removed:
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_placeholder.cc
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_placeholder.h
Modified:
   
gnuradio/branches/developers/thottelt/inband/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
   
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_bit_timing_loop.cc
   
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_field_sync_demux.cc
   
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_viterbi_decoder.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/Makefile.am
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_port.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_nop.h
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.cc
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_worker.cc
   
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mbi_runtime_lock.h
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_bitset.mbh
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.cc
   gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.h
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/Makefile.am
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.cc
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.h
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_int.h
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_serialize.cc
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.cc
   gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.h
   
gnuradio/branches/developers/thottelt/inband/pmt/src/scheme/gnuradio/Makefile.am
   gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/Makefile.am
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.cc
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.h
   
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/legacy/usrp_bytesex.h
Log:
sync up 4986:5208 features/inband-usb

Modified: 
gnuradio/branches/developers/thottelt/inband/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
      2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t
      2007-05-01 20:16:37 UTC (rev 5209)
@@ -181,19 +181,19 @@
   /* The triangle wave rises from -PI to 0 and falls from 0 to PI.     */ 
   case GR_TRI_WAVE:    
     for (int i = 0; i < noutput_items; i++){
-      t = (@TYPE@) d_ampl*d_nco.get_phase()/M_PI;
-        if (d_nco.get_phase() < 0)
-          optr[i] = t + d_ampl + d_offset;
-        else
-          optr[i] = -1*t + d_ampl + d_offset;
-        d_nco.step();
+      double t = d_ampl*d_nco.get_phase()/M_PI;
+      if (d_nco.get_phase() < 0)
+       optr[i] = static_cast<@TYPE@>(t + d_ampl + d_offset);
+      else
+       optr[i] = static_cast<@TYPE@>(-1*t + d_ampl + d_offset);
+      d_nco.step();
     }
     break;
        
   /* The saw tooth wave rises from -PI to PI.  */
   case GR_SAW_WAVE:    
     for (int i = 0; i < noutput_items; i++){
-      t = (@TYPE@) d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/2 + d_offset;
+      t = static_cast<@TYPE@>(d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/2 + 
d_offset);
       optr[i] = t;             
       d_nco.step();
     }

Modified: 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_bit_timing_loop.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_bit_timing_loop.cc
        2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_bit_timing_loop.cc
        2007-05-01 20:16:37 UTC (rev 5209)
@@ -54,7 +54,7 @@
 {
   unsigned ninputs = ninput_items_required.size();
   for (unsigned i = 0; i < ninputs; i++)
-    ninput_items_required[i] = noutput_items * d_rx_clock_to_symbol_freq + 
1500 - 1;
+    ninput_items_required[i] = static_cast<int>(noutput_items * 
d_rx_clock_to_symbol_freq) + 1500 - 1;
 
   inputs0_size = noutput_items * d_rx_clock_to_symbol_freq + 1500 - 1;
   inputs0_index = d_next_input;

Modified: 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_field_sync_demux.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_field_sync_demux.cc
       2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_field_sync_demux.cc
       2007-05-01 20:16:37 UTC (rev 5209)
@@ -32,10 +32,12 @@
 #include <atsci_syminfo.h>
 #include <stdio.h>
 #include <assert.h>
-#include <iostream.h>
+#include <iostream>
 
-using std::abs;
+using std::cerr;
+using std::endl;
 
+
 static const int        DEC = ATSC_DATA_SEGMENT_LENGTH; // nominal decimation 
factor
 
 

Modified: 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_viterbi_decoder.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_viterbi_decoder.cc
        2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/gr-atsc/src/lib/atsc_viterbi_decoder.cc
        2007-05-01 20:16:37 UTC (rev 5209)
@@ -27,8 +27,10 @@
 #include <atsc_viterbi_decoder.h>
 #include <gr_io_signature.h>
 #include <atsc_consts.h>
-#include <iostream.h>
+#include <iostream>
 
+using std::cerr;
+using std::endl;
 
 atsc_viterbi_decoder_sptr
 atsc_make_viterbi_decoder()


Property changes on: gnuradio/branches/developers/thottelt/inband/mblock/src/lib
___________________________________________________________________
Name: svn:ignore
   - Makefile
Makefile.in
.la
.lo
.deps
.libs
*.la
*.lo
test_mblock
qa_bitset_mbh.cc
benchmark_send

   + Makefile
Makefile.in
.la
.lo
.deps
.libs
*.la
*.lo
test_mblock
qa_bitset_mbh.cc
benchmark_send
getres


Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/Makefile.am
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/Makefile.am     
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/Makefile.am     
2007-05-01 20:16:37 UTC (rev 5209)
@@ -28,7 +28,8 @@
 lib_LTLIBRARIES = libmblock.la libmblock-qa.la
 
 EXTRA_DIST =                           \
-       README.locking                  
+       README.locking                  \
+       qa_bitset.mbh                   
 
 
 BUILT_SOURCES =                                \
@@ -48,14 +49,18 @@
        mb_mblock_impl.cc               \
        mb_message.cc                   \
        mb_msg_accepter.cc              \
+       mb_msg_accepter_msgq.cc         \
        mb_msg_accepter_smp.cc          \
        mb_msg_queue.cc                 \
        mb_port.cc                      \
        mb_port_simple.cc               \
        mb_protocol_class.cc            \
        mb_runtime.cc                   \
+       mb_runtime_base.cc              \
        mb_runtime_nop.cc               \
        mb_runtime_thread_per_block.cc  \
+       mb_time.cc                      \
+       mb_timer_queue.cc               \
        mb_util.cc                      \
        mb_worker.cc                    
 
@@ -77,12 +82,13 @@
        mb_mblock.h                     \
        mb_message.h                    \
        mb_msg_accepter.h               \
+       mb_msg_accepter_msgq.h          \
        mb_msg_queue.h                  \
        mb_port.h                       \
        mb_port_simple.h                \
        mb_protocol_class.h             \
        mb_runtime.h                    \
-       mb_runtime_nop.h                \
+       mb_time.h                       \
        mb_util.h                       
 
 
@@ -91,13 +97,17 @@
        mb_endpoint.h                   \
        mb_mblock_impl.h                \
        mb_msg_accepter_smp.h           \
+       mb_runtime_base.h               \
+       mb_runtime_nop.h                \
        mb_runtime_thread_per_block.h   \
+       mb_timer_queue.h                \
        mb_worker.h                     \
        mbi_runtime_lock.h              \
        qa_mblock.h                     \
        qa_mblock_prims.h               \
        qa_mblock_send.h                \
-       qa_mblock_sys.h                 
+       qa_mblock_sys.h                 \
+       qa_timeouts.h                   
 
 
 # Build the qa code into its own library
@@ -105,10 +115,12 @@
 libmblock_qa_la_SOURCES =              \
        qa_bitset.cc                    \
        qa_bitset_mbh.cc                \
+       qa_disconnect.cc                \
        qa_mblock.cc                    \
        qa_mblock_prims.cc              \
        qa_mblock_send.cc               \
-       qa_mblock_sys.cc                
+       qa_mblock_sys.cc                \
+       qa_timeouts.cc                  
 
 
 # magic flags

Copied: gnuradio/branches/developers/thottelt/inband/mblock/src/lib/getres.cc 
(from rev 5208, gnuradio/branches/features/inband-usb/mblock/src/lib/getres.cc)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/getres.cc       
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/getres.cc       
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,32 @@
+#include <time.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+  bool ok = true;
+  struct timespec ts;
+  int r;
+
+  r = clock_getres(CLOCK_REALTIME, &ts);
+  if (r != 0){
+    perror("clock_getres(CLOCK_REALTIME, ...)");
+    ok = false;
+  }
+  else
+    printf("clock_getres(CLOCK_REALTIME, ...)  => %11.9f\n",
+          (double) ts.tv_sec + ts.tv_nsec * 1e-9);
+
+
+  r = clock_getres(CLOCK_MONOTONIC, &ts);
+  if (r != 0){
+    perror("clock_getres(CLOCK_MONOTONIC, ...");
+    ok = false;
+  }
+  else
+    printf("clock_getres(CLOCK_MONOTONIC, ...) => %11.9f\n",
+          (double) ts.tv_sec + ts.tv_nsec * 1e-9);
+
+
+  return ok == true ? 0 : 1;
+}  

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.cc    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.cc    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -42,7 +42,9 @@
 mb_mblock::mb_mblock(mb_runtime *runtime,
                     const std::string &instance_name,
                     pmt_t user_arg)
-  : d_impl(mb_mblock_impl_sptr(new mb_mblock_impl(runtime, this, 
instance_name)))
+  : d_impl(mb_mblock_impl_sptr(
+              new mb_mblock_impl(dynamic_cast<mb_runtime_base*>(runtime),
+                                 this, instance_name)))
 {
 }
 
@@ -198,3 +200,30 @@
 {
   d_impl->runtime()->request_shutdown(result);
 }
+
+pmt_t
+mb_mblock::schedule_one_shot_timeout(const mb_time &abs_time, pmt_t user_data)
+{
+  mb_msg_accepter_sptr accepter = impl()->make_accepter(s_sys_port);
+  return d_impl->runtime()->schedule_one_shot_timeout(abs_time, user_data,
+                                                     accepter);
+}
+
+pmt_t
+mb_mblock::schedule_periodic_timeout(const mb_time &first_abs_time,
+                                    const mb_time &delta_time,
+                                    pmt_t user_data)
+{
+  mb_msg_accepter_sptr accepter = impl()->make_accepter(s_sys_port);
+  return d_impl->runtime()->schedule_periodic_timeout(first_abs_time,
+                                                     delta_time,
+                                                     user_data,
+                                                     accepter);
+}
+
+void
+mb_mblock::cancel_timeout(pmt_t handle)
+{
+  d_impl->runtime()->cancel_timeout(handle);
+}
+

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.h     
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock.h     
2007-05-01 20:16:37 UTC (rev 5209)
@@ -24,6 +24,7 @@
 #include <mb_common.h>
 #include <mb_message.h>
 #include <mb_port.h>
+#include <mb_time.h>
 
 
 /*!
@@ -242,6 +243,62 @@
   mb_mblock *parent() const;
 
   /*!
+   * \brief Schedule a "one shot" timeout.
+   *
+   * \param abs_time the absolute time at which the timeout should fire
+   * \param user_data the data passed in the %timeout message.
+   *
+   * When the timeout fires, a message will be sent to the mblock.
+   *
+   * The message will have port_id = %sys-port, signal = %timeout,
+   * data = user_data, metadata = the handle returned from
+   * schedule_one_shot_timeout, pri = MB_PRI_BEST.
+   *
+   * \returns a handle that can be used in cancel_timeout, and is passed
+   * as the metadata field of the generated %timeout message.
+   *
+   * To cancel a pending timeout, call cancel_timeout.
+   */
+  pmt_t
+  schedule_one_shot_timeout(const mb_time &abs_time, pmt_t user_data);
+
+  /*!
+   * \brief Schedule a periodic timeout.
+   *
+   * \param first_abs_time The absolute time at which the first timeout should 
fire.
+   * \param delta_time The relative delay between the first and successive 
timeouts.
+   * \param user_data the data passed in the %timeout message.
+   *
+   * When the timeout fires, a message will be sent to the mblock, and a
+   * new timeout will be scheduled for previous absolute time + delta_time.
+   *
+   * The message will have port_id = %sys-port, signal = %timeout,
+   * data = user_data, metadata = the handle returned from
+   * schedule_one_shot_timeout, pri = MB_PRI_BEST.
+   *
+   * \returns a handle that can be used in cancel_timeout, and is passed
+   * as the metadata field of the generated %timeout message.
+   *
+   * To cancel a pending timeout, call cancel_timeout.
+   */
+  pmt_t
+  schedule_periodic_timeout(const mb_time &first_abs_time,
+                           const mb_time &delta_time,
+                           pmt_t user_data);
+
+  /*!
+   * \brief Attempt to cancel a pending timeout.
+   *
+   * Note that this only stops a future timeout from firing.  It is
+   * possible that a timeout may have already fired and enqueued a
+   * %timeout message, but that that message has not yet been seen by
+   * handle_message.
+   *
+   * \param handle returned from schedule_one_shot_timeout or 
schedule_periodic_timeout.
+   */
+  void cancel_timeout(pmt_t handle);
+
+  /*!
    * \brief Perform a pre-order depth-first traversal of the hierarchy.
    *
    * The traversal stops and returns false if any call to visitor returns 
false.

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.cc   
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.cc   
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -52,7 +52,7 @@
 
 ////////////////////////////////////////////////////////////////////////
 
-mb_mblock_impl::mb_mblock_impl(mb_runtime *runtime, mb_mblock *mb,
+mb_mblock_impl::mb_mblock_impl(mb_runtime_base *runtime, mb_mblock *mb,
                               const std::string &instance_name)
   : d_runtime(runtime), d_mb(mb), d_mb_parent(0), 
     d_instance_name(instance_name), d_class_name("mblock")
@@ -319,19 +319,9 @@
     }
   };
 
-  class nop : public mb_visitor
-  {
-  public:
-    bool operator()(mb_mblock *mblock)
-    {
-      return true;
-    }
-  };
-
   invalidator visitor;
-  nop visitor2;
 
   // Always true, except in early QA code
   if (runtime()->top())
-    runtime()->top()->walk_tree(&visitor2);
+    runtime()->top()->walk_tree(&visitor);
 }

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.h    
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_mblock_impl.h    
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -22,6 +22,7 @@
 #define INCLUDED_MB_MBLOCK_IMPL_H
 
 #include <mb_mblock.h>
+#include <mb_runtime_base.h>
 #include <mb_connection.h>
 #include <mb_msg_queue.h>
 #include <list>
@@ -37,7 +38,7 @@
  */
 class mb_mblock_impl : boost::noncopyable
 {
-  mb_runtime                  *d_runtime;      // pointer to runtime
+  mb_runtime_base             *d_runtime;      // pointer to runtime
   mb_mblock                   *d_mb;           // pointer to our associated 
mblock
   mb_mblock                   *d_mb_parent;    // pointer to our parent
 
@@ -51,7 +52,8 @@
   mb_msg_queue                 d_msgq;         // incoming messages for us
 
 public:
-  mb_mblock_impl(mb_runtime *runtime, mb_mblock *mb, const std::string 
&instance_name);
+  mb_mblock_impl(mb_runtime_base *runtime, mb_mblock *mb,
+                const std::string &instance_name);
   ~mb_mblock_impl();
 
   /*!
@@ -185,10 +187,10 @@
   mb_mblock_sptr component(const std::string &comp_name);
 
   //! Return the runtime instance
-  mb_runtime *runtime() { return d_runtime; }
+  mb_runtime_base *runtime() { return d_runtime; }
 
   //! Set the runtime instance
-  void set_runtime(mb_runtime *runtime) { d_runtime = runtime; }
+  void set_runtime(mb_runtime_base *runtime) { d_runtime = runtime; }
 
   /*
    * Our implementation methods

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.cc   
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.cc   
2007-05-01 20:16:37 UTC (rev 5209)
@@ -23,7 +23,35 @@
 #include <config.h>
 #endif
 #include <mb_message.h>
+#include <stdio.h>
+#include <pmt_pool.h>
 
+static const int CACHE_LINE_SIZE = 64;         // good guess
+
+
+#if MB_MESSAGE_LOCAL_ALLOCATOR
+
+static pmt_pool global_msg_pool(sizeof(mb_message), CACHE_LINE_SIZE);
+
+void *
+mb_message::operator new(size_t size)
+{
+  void *p = global_msg_pool.malloc();
+
+  // fprintf(stderr, "mb_message::new p = %p\n", p);
+  assert((reinterpret_cast<intptr_t>(p) & (CACHE_LINE_SIZE - 1)) == 0);
+  return p;
+}
+
+void
+mb_message::operator delete(void *p, size_t size)
+{
+  global_msg_pool.free(p);
+}
+
+#endif
+
+
 mb_message_sptr
 mb_make_message(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority)
 {
@@ -40,3 +68,16 @@
 {
   // NOP
 }
+
+std::ostream& 
+operator<<(std::ostream& os, const mb_message &msg)
+{
+  os << "<msg: signal=" << msg.signal()
+     << " port_id=" << msg.port_id()
+     << " data=" << msg.data()
+     << " metadata=" << msg.metadata()
+     << " pri=" << msg.priority()
+     << ">";
+  
+  return os;
+}

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.h    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_message.h    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -22,7 +22,10 @@
 #define INCLUDED_MB_MESSAGE_H
 
 #include <mb_common.h>
+#include <iosfwd>
 
+#define MB_MESSAGE_LOCAL_ALLOCATOR 0   // define to 0 or 1
+
 class mb_message;
 typedef boost::shared_ptr<mb_message> mb_message_sptr;
 
@@ -66,6 +69,20 @@
   pmt_t port_id() const { return d_port_id; }
 
   void set_port_id(pmt_t port_id){ d_port_id = port_id; }
+
+#if (MB_MESSAGE_LOCAL_ALLOCATOR)
+  void *operator new(size_t);
+  void operator delete(void *, size_t);
+#endif
 };
 
+std::ostream& operator<<(std::ostream& os, const mb_message &msg);
+
+inline
+std::ostream& operator<<(std::ostream& os, const mb_message_sptr msg)
+{
+  os << *(msg.get());
+  return os;
+}
+
 #endif /* INCLUDED_MB_MESSAGE_H */

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.cc
 (from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_msg_accepter_msgq.cc)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.cc
                         (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.cc
 2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,46 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_msg_accepter_msgq.h>
+#include <mb_message.h>
+
+pmt_t s_sys_port = pmt_intern("%sys-port");
+
+mb_msg_accepter_msgq::mb_msg_accepter_msgq(mb_msg_queue *msgq)
+  : d_msgq(msgq)
+{
+}
+
+mb_msg_accepter_msgq::~mb_msg_accepter_msgq()
+{
+}
+
+void
+mb_msg_accepter_msgq::operator()(pmt_t signal, pmt_t data,
+                                pmt_t metadata, mb_pri_t priority)
+{
+  mb_message_sptr msg = mb_make_message(signal, data, metadata, priority);
+  msg->set_port_id(s_sys_port);
+  d_msgq->insert(msg);
+}

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.h
 (from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_msg_accepter_msgq.h)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.h
                          (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_accepter_msgq.h
  2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,39 @@
+/* -*- 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 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.
+ */
+#ifndef INCLUDED_MB_MSG_ACCEPTER_MSGQ_H
+#define INCLUDED_MB_MSG_ACCEPTER_MSGQ_H
+
+#include <mb_msg_accepter.h>
+#include <mb_msg_queue.h>
+
+/*!
+ * \brief Concrete class that accepts messages and inserts them into a message 
queue.
+ */
+class mb_msg_accepter_msgq : public mb_msg_accepter {
+  mb_msg_queue *d_msgq;
+
+public:
+  mb_msg_accepter_msgq(mb_msg_queue *msgq);
+  ~mb_msg_accepter_msgq();
+  void operator()(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority);
+};
+
+#endif /* INCLUDED_MB_MSG_ACCEPTER_MSGQ_H */

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.cc 
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.cc 
2007-05-01 20:16:37 UTC (rev 5209)
@@ -83,7 +83,7 @@
     }
   }
 
-  return mb_message_sptr();    // equivalent of a zero pointer
+  return mb_message_sptr();            // eqv to a zero pointer
 }
 
 
@@ -109,3 +109,20 @@
   }
 }
 
+mb_message_sptr
+mb_msg_queue::get_highest_pri_msg_timedwait(const mb_time &abs_time)
+{
+  unsigned long secs  = abs_time.d_secs;
+  unsigned long nsecs = abs_time.d_nsecs;
+
+  omni_mutex_lock l(d_mutex);
+
+  while (1){
+    mb_message_sptr msg = get_highest_pri_msg_helper();
+    if (msg)                   // Got one; return it
+      return msg;
+
+    if (!d_not_empty.timedwait(secs, nsecs))   // timed out
+      return mb_message_sptr();                        // eqv to zero pointer
+  }
+}

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.h  
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_msg_queue.h  
2007-05-01 20:16:37 UTC (rev 5209)
@@ -23,6 +23,7 @@
 
 #include <mb_common.h>
 #include <omnithread.h>
+#include <mb_time.h>
 
 /*!
  * \brief priority queue for mblock messages
@@ -63,6 +64,19 @@
    * If the queue is empty, this call blocks until it can return a message.
    */
   mb_message_sptr get_highest_pri_msg();
+
+  /*
+   * \brief Delete highest pri message from the queue and return it.
+   * If the queue is empty, this call blocks until it can return a message
+   * or real-time exceeds the absolute time, abs_time.
+   *
+   * \param abs_time specifies the latest absolute time to wait until.
+   * \sa mb_time::time
+   *
+   * \returns a valid mb_message_sptr, or the equivalent of a zero pointer
+   * if the call timed out while waiting.
+   */
+  mb_message_sptr get_highest_pri_msg_timedwait(const mb_time &abs_time);
 };
 
 #endif /* INCLUDED_MB_MSG_QUEUE_H */

Modified: gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_port.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_port.h       
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_port.h       
2007-05-01 20:16:37 UTC (rev 5209)
@@ -79,8 +79,8 @@
    */
   virtual void
   send(pmt_t signal,
-       pmt_t data = PMT_NIL,
-       pmt_t metadata = PMT_NIL,
+       pmt_t data = PMT_F,
+       pmt_t metadata = PMT_F,
        mb_pri_t priority = MB_PRI_DEFAULT) = 0;
 
   /*

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.cc   
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.cc   
2007-05-01 20:16:37 UTC (rev 5209)
@@ -37,8 +37,3 @@
   // nop
 }
 
-void
-mb_runtime::request_shutdown(pmt_t result)
-{
-  // nop
-}

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.h    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime.h    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -37,13 +37,8 @@
 class mb_runtime : boost::noncopyable,
                   public boost::enable_shared_from_this<mb_runtime>
 {
-  friend class mb_mblock_impl;
-
-  omni_mutex           d_brl;  // big runtime lock (avoid using this if 
possible...)
-
 protected:  
   mb_mblock_sptr       d_top;
-  
 
 public:
   mb_runtime(){}
@@ -66,32 +61,8 @@
                   pmt_t user_arg,
                   pmt_t *result = 0) = 0;
 
-
-  // ----------------------------------------------------------------
-  // Stuff from here down is really private to the implementation...
-  // ----------------------------------------------------------------
-
-  /*!
-   * \brief lock the big runtime lock
-   * \implementation
-   */
-  inline void lock() { d_brl.lock(); }
-
-  /*!
-   * \brief unlock the big runtime lock
-   * \implementation
-   */
-  inline void unlock() { d_brl.unlock(); }
-
-  virtual void request_shutdown(pmt_t result);
-
+  // QA only...
   mb_mblock_sptr top() { return d_top; }
-
-protected:
-  virtual mb_mblock_sptr
-  create_component(const std::string &instance_name,
-                  const std::string &class_name,
-                  pmt_t user_arg) = 0;
 };
 
 #endif /* INCLUDED_MB_RUNTIME_H */

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.cc 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_base.cc)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.cc  
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.cc  
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,57 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_runtime_base.h>
+
+/*
+ * Default nop implementations...
+ */
+
+void
+mb_runtime_base::request_shutdown(pmt_t result)
+{
+}
+
+pmt_t
+mb_runtime_base::schedule_one_shot_timeout(const mb_time &abs_time,
+                                          pmt_t user_data,
+                                          mb_msg_accepter_sptr accepter)
+{
+  return PMT_F;
+}
+
+pmt_t
+mb_runtime_base::schedule_periodic_timeout(const mb_time &first_abs_time,
+                                          const mb_time &delta_time,
+                                          pmt_t user_data,
+                                          mb_msg_accepter_sptr accepter)
+{
+  return PMT_F;
+}
+
+void
+mb_runtime_base::cancel_timeout(pmt_t handle)
+{
+}
+

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.h 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_base.h)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.h   
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_base.h   
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,78 @@
+/* -*- 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 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.
+ */
+
+#ifndef INCLUDED_MB_RUNTIME_BASE_H
+#define INCLUDED_MB_RUNTIME_BASE_H
+
+#include <mb_runtime.h>
+#include <omnithread.h>
+#include <mb_time.h>
+
+/*
+ * \brief This is the runtime class used by the implementation.
+ */
+class mb_runtime_base : public mb_runtime
+{
+  omni_mutex           d_brl;  // big runtime lock (avoid using this if 
possible...)
+
+protected:
+  mb_msg_accepter_sptr  d_accepter;
+
+public:
+
+  /*!
+   * \brief lock the big runtime lock
+   * \implementation
+   */
+  inline void lock() { d_brl.lock(); }
+
+  /*!
+   * \brief unlock the big runtime lock
+   * \implementation
+   */
+  inline void unlock() { d_brl.unlock(); }
+
+  virtual void request_shutdown(pmt_t result);
+
+  virtual mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg) = 0;
+
+  virtual pmt_t
+  schedule_one_shot_timeout(const mb_time &abs_time, pmt_t user_data,
+                           mb_msg_accepter_sptr accepter);
+
+  virtual pmt_t
+  schedule_periodic_timeout(const mb_time &first_abs_time,
+                           const mb_time &delta_time,
+                           pmt_t user_data,
+                           mb_msg_accepter_sptr accepter);
+  virtual void
+  cancel_timeout(pmt_t handle);
+
+  mb_msg_accepter_sptr
+  accepter() { return d_accepter; }
+  
+};
+
+
+#endif /* INCLUDED_MB_RUNTIME_BASE_H */

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_nop.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_nop.h    
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_nop.h    
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -21,7 +21,7 @@
 #ifndef INCLUDED_MB_RUNTIME_NOP_H
 #define INCLUDED_MB_RUNTIME_NOP_H
 
-#include <mb_runtime.h>
+#include <mb_runtime_base.h>
 
 /*!
  * \brief Public constructor (factory) for mb_runtime_nop objects.
@@ -31,7 +31,7 @@
 /*!
  * \brief Concrete runtime that does nothing.  Used only during early QA tests.
  */
-class mb_runtime_nop : public mb_runtime
+class mb_runtime_nop : public mb_runtime_base
 {
 public:
   mb_runtime_nop();

Deleted: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_placeholder.cc

Deleted: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_placeholder.h

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.cc
  2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.cc
  2007-05-01 20:16:37 UTC (rev 5209)
@@ -30,12 +30,20 @@
 #include <mb_worker.h>
 #include <omnithread.h>
 #include <iostream>
+#include <mb_msg_accepter_msgq.h>
 
+
+static pmt_t s_halt = pmt_intern("%halt");
 static pmt_t s_sys_port = pmt_intern("%sys-port");
 static pmt_t s_shutdown = pmt_intern("%shutdown");
-static pmt_t s_halt = pmt_intern("%halt");
+static pmt_t s_request_shutdown = pmt_intern("%request-shutdown");
+static pmt_t s_worker_state_changed = pmt_intern("%worker-state-changed");
+static pmt_t s_timeout = pmt_intern("%timeout");
+static pmt_t s_request_timeout = pmt_intern("%request-timeout");
+static pmt_t s_cancel_timeout = pmt_intern("%cancel-timeout");
+static pmt_t s_send_halt = pmt_intern("send-halt");
+static pmt_t s_exit_now = pmt_intern("exit-now");
 
-
 static void
 send_sys_msg(mb_msg_queue &msgq, pmt_t signal,
             pmt_t data = PMT_F, pmt_t metadata = PMT_F,
@@ -48,10 +56,10 @@
 
 
 mb_runtime_thread_per_block::mb_runtime_thread_per_block()
-  : d_runtime_cond(&d_mutex),
-    d_shutdown_requested(false), d_shutdown_in_progress(false),
+  : d_shutdown_in_progress(false),
     d_shutdown_result(PMT_T)
 {
+  d_accepter = mb_msg_accepter_sptr(new mb_msg_accepter_msgq(&d_msgq));
 }
 
 mb_runtime_thread_per_block::~mb_runtime_thread_per_block()
@@ -66,13 +74,7 @@
 void
 mb_runtime_thread_per_block::request_shutdown(pmt_t result)
 {
-  omni_mutex_lock l1(d_mutex);
-
-  if (!d_shutdown_requested){
-    d_shutdown_result = result;
-    d_shutdown_requested = true;
-    d_runtime_cond.broadcast();
-  }
+  (*accepter())(s_request_shutdown, result, PMT_F, MB_PRI_BEST);
 }
 
 bool
@@ -84,12 +86,14 @@
     *result = PMT_F;
   
   // reset the shutdown state
-  d_shutdown_requested = false;
   d_shutdown_in_progress = false;
   d_shutdown_result = PMT_T;
 
   assert(d_workers.empty());
 
+  while (!d_timer_queue.empty())       // ensure timer queue is empty
+    d_timer_queue.pop();
+
   /*
    * Create the top-level component, and recursively all of its
    * subcomponents.
@@ -114,38 +118,85 @@
 void
 mb_runtime_thread_per_block::run_loop()
 {
-  /*
-   * FIXME probably ought to recode this to use a message queue
-   * and state machine like the rest of the world ;)
-   */
+  while (1){
+    mb_message_sptr msg;
 
-  omni_mutex_lock l1(d_mutex);
+    if (d_timer_queue.empty())                   // Any timeouts pending?
+      msg = d_msgq.get_highest_pri_msg();        // Nope.  Block forever.
 
-  while (1){
+    else {
+      mb_timeout_sptr to = d_timer_queue.top();          // Yep.  Get earliest 
timeout.
 
-    reap_dead_workers();
+      // wait for a msg or the timeout...
+      msg = d_msgq.get_highest_pri_msg_timedwait(to->d_when);
 
-    if (d_workers.empty())     // no work left to do...
-      return;          
+      if (!msg){               // We timed out.
+       d_timer_queue.pop();    // Remove timeout from timer queue.
 
-    if (d_shutdown_requested && !d_shutdown_in_progress){
-      d_shutdown_in_progress = true;
+       // send the %timeout msg
+       (*to->d_accepter)(s_timeout, to->d_user_data, to->handle(), 
MB_PRI_BEST);
 
-      // FIXME state machine, delay before sending %halt
-      send_all_sys_msg(s_shutdown);
+       if (to->d_is_periodic){
+         to->d_when = to->d_when + to->d_delta;        // update time of next 
firing
+         d_timer_queue.push(to);                       // push it back into 
the queue
+       }
+       continue;
+      }
+    }
+
+    pmt_t signal = msg->signal();
+
+    if (pmt_eq(signal, s_worker_state_changed)){       // %worker-state-changed
+      omni_mutex_lock l1(d_workers_mutex);
+      reap_dead_workers();
+      if (d_workers.empty())   // no work left to do...
+       return;
+    }
+    else if (pmt_eq(signal, s_request_shutdown)){      // %request-shutdown
+      if (!d_shutdown_in_progress){
+       d_shutdown_in_progress = true;
+       d_shutdown_result = msg->data();
+
+       // schedule a timeout for ourselves...
+       schedule_one_shot_timeout(mb_time::time(0.100), s_send_halt, 
d_accepter);
+       send_all_sys_msg(s_shutdown);
+      }
+    }
+    else if (pmt_eq(signal, s_request_timeout)){       // %request-timeout
+      mb_timeout_sptr to =
+       boost::any_cast<mb_timeout_sptr>(pmt_any_ref(msg->data()));
+      d_timer_queue.push(to);
+    }
+    else if (pmt_eq(signal, s_cancel_timeout)){                // 
%cancel-timeout
+      d_timer_queue.cancel(msg->data());
+    }
+    else if (pmt_eq(signal, s_timeout)
+            && pmt_eq(msg->data(), s_send_halt)){      // %timeout, send-halt
+
+      // schedule another timeout for ourselves...
+      schedule_one_shot_timeout(mb_time::time(0.100), s_exit_now, d_accepter);
       send_all_sys_msg(s_halt);
+    }
+    else if (pmt_eq(signal, s_timeout)
+            && pmt_eq(msg->data(), s_exit_now)){       // %timeout, exit-now
 
-      continue;
+      // We only get here if we've sent all workers %shutdown followed
+      // by %halt, and one or more of them is still alive.  They must
+      // be blocked in the kernel.  FIXME We could add one more step:
+      // pthread_kill(...) but for now, we'll just ignore them...
+      return;
     }
-
-    d_runtime_cond.wait();     // wait for something to do.
+    else {
+      std::cerr << "mb_runtime_thread_per_block: unhandled msg: " << msg << 
std::endl;
+    }
   }
 }
 
 void
 mb_runtime_thread_per_block::reap_dead_workers()
 {
-  // omni_mutex_lock l1(d_mutex);
+  // Already holding mutex
+  // omni_mutex_lock l1(d_workers_mutex);
 
   for (worker_iter_t wi = d_workers.begin(); wi != d_workers.end(); ){
     bool is_dead;
@@ -178,6 +229,8 @@
 // Create the thread, then create the component in the thread.
 // Return a pointer to the created mblock.
 //
+// Can be invoked from any thread
+//
 mb_mblock_sptr
 mb_runtime_thread_per_block::create_component(const std::string &instance_name,
                                              const std::string &class_name,
@@ -227,7 +280,7 @@
 
   // Add w to the vector of workers, and return the mblock.
   {
-    omni_mutex_lock l(d_mutex);
+    omni_mutex_lock l(d_workers_mutex);
     d_workers.push_back(w);
   }
 
@@ -245,11 +298,52 @@
                                              pmt_t metadata,
                                              mb_pri_t priority)
 {
-  // Already holding lock
-  // omni_mutex_lock l1(d_mutex);
+  omni_mutex_lock l1(d_workers_mutex);
 
   for (worker_iter_t wi = d_workers.begin(); wi != d_workers.end(); ++wi){
     send_sys_msg((*wi)->d_mblock->impl()->msgq(),
                 signal, data, metadata, priority);
   }
 }
+
+//
+// Can be invoked from any thread.
+// Sends a message to the runtime.
+//
+pmt_t
+mb_runtime_thread_per_block::schedule_one_shot_timeout
+  (const mb_time &abs_time,
+   pmt_t user_data,
+   mb_msg_accepter_sptr accepter)
+{
+  mb_timeout_sptr to(new mb_timeout(abs_time, user_data, accepter));
+  (*d_accepter)(s_request_timeout, pmt_make_any(to), PMT_F, MB_PRI_BEST);
+  return to->handle();
+}
+
+//
+// Can be invoked from any thread.
+// Sends a message to the runtime.
+//
+pmt_t
+mb_runtime_thread_per_block::schedule_periodic_timeout
+  (const mb_time &first_abs_time,
+   const mb_time &delta_time,
+   pmt_t user_data,
+   mb_msg_accepter_sptr accepter)
+{
+  mb_timeout_sptr to(new mb_timeout(first_abs_time, delta_time,
+                                   user_data, accepter));
+  (*d_accepter)(s_request_timeout, pmt_make_any(to), PMT_F, MB_PRI_BEST);
+  return to->handle();
+}
+
+//
+// Can be invoked from any thread.
+// Sends a message to the runtime.
+//
+void
+mb_runtime_thread_per_block::cancel_timeout(pmt_t handle)
+{
+  (*d_accepter)(s_cancel_timeout, handle, PMT_F, MB_PRI_BEST);
+}

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.h
   2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_runtime_thread_per_block.h
   2007-05-01 20:16:37 UTC (rev 5209)
@@ -21,8 +21,10 @@
 #ifndef INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H
 #define INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H
 
-#include <mb_runtime.h>
+#include <mb_runtime_base.h>
 #include <mb_worker.h>
+#include <mb_msg_queue.h>
+#include <mb_timer_queue.h>
 
 /*!
  * \brief Concrete runtime that uses a thread per mblock
@@ -30,18 +32,16 @@
  *
  * These are all implementation details.
  */
-class mb_runtime_thread_per_block : public mb_runtime
+class mb_runtime_thread_per_block : public mb_runtime_base
 {
 public:
-  omni_mutex                 d_mutex;
-  omni_condition             d_runtime_cond;  // runtime waits here
-  //std::vector<mb_worker_sptr> d_workers;
+  omni_mutex                 d_workers_mutex;  // hold while manipulating 
d_workers
   std::vector<mb_worker*>     d_workers;
-  bool                       d_shutdown_requested;
   bool                       d_shutdown_in_progress;
   pmt_t                              d_shutdown_result;
+  mb_msg_queue               d_msgq;
+  mb_timer_queue             d_timer_queue;
 
-  //typedef std::vector<mb_worker_sptr>::iterator  worker_iter_t;
   typedef std::vector<mb_worker*>::iterator  worker_iter_t;
 
   mb_runtime_thread_per_block();
@@ -60,13 +60,25 @@
                   const std::string &class_name,
                   pmt_t user_arg);
 
+  pmt_t
+  schedule_one_shot_timeout(const mb_time &abs_time, pmt_t user_data,
+                           mb_msg_accepter_sptr accepter);
+
+  pmt_t
+  schedule_periodic_timeout(const mb_time &first_abs_time,
+                           const mb_time &delta_time,
+                           pmt_t user_data,
+                           mb_msg_accepter_sptr accepter);
+  void
+  cancel_timeout(pmt_t handle);
+
+private:
   void reap_dead_workers();
   void run_loop();
 
   void send_all_sys_msg(pmt_t signal, pmt_t data = PMT_F,
                        pmt_t metadata = PMT_F,
                        mb_pri_t priority = MB_PRI_BEST);
-
 };
 
 #endif /* INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H */

Copied: gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.cc 
(from rev 5208, gnuradio/branches/features/inband-usb/mblock/src/lib/mb_time.cc)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.cc      
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.cc      
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,84 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_time.h>
+#include <omnithread.h>
+#include <math.h>
+#include <assert.h>
+
+
+mb_time::mb_time(double real_secs)
+{
+  double floor_secs = floor(real_secs);
+  d_secs = (long) floor_secs;
+  d_nsecs = (long) ((real_secs - floor_secs) * 1e9);     // always positive
+}
+
+mb_time
+mb_time::time(const mb_time &delta_t)
+{
+  unsigned long        abs_sec, abs_nsec;
+  unsigned long rel_sec  = delta_t.d_secs;
+  unsigned long rel_nsec = delta_t.d_nsecs;
+  
+  omni_thread::get_time(&abs_sec, &abs_nsec, rel_sec, rel_nsec);
+  return mb_time(abs_sec, abs_nsec);
+}
+
+
+mb_time
+operator+(const mb_time &x, const mb_time &y)
+{
+  mb_time r(x.d_secs + y.d_secs, x.d_nsecs + y.d_nsecs);
+  while (r.d_nsecs >= 1000000000){
+    r.d_nsecs -= 1000000000;
+    r.d_secs++;
+  }
+  return r;
+}
+
+mb_time
+operator-(const mb_time &x, const mb_time &y)
+{
+  // assert(!(x < y));
+
+  mb_time r(x.d_secs - y.d_secs, x.d_nsecs - y.d_nsecs);
+  while (r.d_nsecs < 0){
+    r.d_nsecs += 1000000000;
+    r.d_secs--;
+  }
+  return r;
+}
+
+mb_time
+operator+(const mb_time &x, double y)
+{
+  return x + mb_time(y);
+}
+
+mb_time
+operator-(const mb_time &x, double y)
+{
+  return x - mb_time(y);
+}

Copied: gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.h 
(from rev 5208, gnuradio/branches/features/inband-usb/mblock/src/lib/mb_time.h)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.h       
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_time.h       
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,89 @@
+/* -*- 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 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.
+ */
+#ifndef INCLUDED_MB_TIME_H
+#define INCLUDED_MB_TIME_H
+
+struct mb_time {
+  long int d_secs;     // seconds.
+  long int d_nsecs;    // nanoseconds.  Always in [0, 1e9-1]
+
+  mb_time() : d_secs(0), d_nsecs(0) {}
+  mb_time(long secs, long nanosecs=0) : d_secs(secs), d_nsecs(nanosecs) {}
+
+  // N.B., this only makes sense for differences between times.
+  // Double doesn't have enough bits to precisely represent an absolute time.
+  mb_time(double secs);
+
+  // N.B. This only makes sense for differences between times.
+  // Double doesn't have enough bits to precisely represent an absolute time.
+  double double_time() const { return (double)d_secs + d_nsecs * 1e-9; }
+
+  /*!
+   * \brief Return an absolute time suitable for use with
+   * schedule_one_shot_timeout & schedule_periodic_timeout
+   *
+   * The return value is the current time plus the given relative offset.
+   */
+  static mb_time time(const mb_time &relative_offset = mb_time());
+};
+
+
+inline static bool
+operator<(const mb_time &x, const mb_time &y)
+{
+  return ((x.d_secs < y.d_secs)
+         || (x.d_secs == y.d_secs && x.d_nsecs < y.d_nsecs));
+}
+
+inline static bool
+operator>(const mb_time &x, const mb_time &y)
+{
+  return ((x.d_secs > y.d_secs)
+         || (x.d_secs == y.d_secs && x.d_nsecs > y.d_nsecs));
+}
+
+inline static bool
+operator>=(const mb_time &x, const mb_time &y)
+{
+  return ((x.d_secs > y.d_secs)
+         || (x.d_secs == y.d_secs && x.d_nsecs >= y.d_nsecs));
+}
+
+inline static bool
+operator<=(const mb_time &x, const mb_time &y)
+{
+  return ((x.d_secs < y.d_secs)
+         || (x.d_secs == y.d_secs && x.d_nsecs <= y.d_nsecs));
+}
+
+inline static bool
+operator==(const mb_time &x, const mb_time &y)
+{
+  return (x.d_secs == y.d_secs && x.d_nsecs == y.d_nsecs);
+}
+
+
+mb_time operator+(const mb_time &x, const mb_time &y);
+mb_time operator+(const mb_time &x, double y);
+mb_time operator-(const mb_time &x, const mb_time &y);
+mb_time operator-(const mb_time &x, double y);
+
+#endif /* INCLUDED_MB_TIME_H */

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.cc 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_timer_queue.cc)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.cc   
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.cc   
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,63 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_timer_queue.h>
+
+static pmt_t
+make_handle()
+{
+  static long counter = 0;
+  pmt_t n = pmt_from_long(counter++);
+  return pmt_list1(n);         // guaranteed to be a unique object
+}
+
+// one-shot constructor
+mb_timeout::mb_timeout(const mb_time &abs_time,
+                      pmt_t user_data, mb_msg_accepter_sptr accepter)
+  : d_when(abs_time), d_is_periodic(false),
+    d_user_data(user_data), d_handle(make_handle()), d_accepter(accepter)
+{
+}
+
+// periodic constructor
+mb_timeout::mb_timeout(const mb_time &first_abs_time, const mb_time 
&delta_time,
+                      pmt_t user_data, mb_msg_accepter_sptr accepter)
+  : d_when(first_abs_time), d_delta(delta_time), d_is_periodic(true),
+    d_user_data(user_data), d_handle(make_handle()), d_accepter(accepter)
+{
+}
+
+void
+mb_timer_queue::cancel(pmt_t handle)
+{
+  container_type::iterator it;
+
+  for (it = c.begin(); it != c.end();){
+    if (pmt_equal((*it)->handle(), handle))
+      it = c.erase(it);
+    else
+      ++it;
+  }
+  std::make_heap(c.begin(), c.end(), comp);
+}

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.h 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_timer_queue.h)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.h    
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_timer_queue.h    
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,73 @@
+/* -*- 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 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.
+ */
+
+#ifndef INCLUDED_MB_TIMER_QUEUE_H
+#define INCLUDED_MB_TIMER_QUEUE_H
+
+#include <mb_time.h>
+#include <vector>
+#include <queue>
+#include <pmt.h>
+#include <mb_msg_accepter.h>
+
+class mb_timeout {
+public:
+  mb_time              d_when;         // absolute time to fire timeout
+  mb_time              d_delta;        // if periodic, delta_t to next timeout
+  bool                 d_is_periodic;  // true iff this is a periodic timeout
+  pmt_t                        d_user_data;    // data from %timeout msg
+  pmt_t                        d_handle;       // handle for cancellation
+  mb_msg_accepter_sptr d_accepter;     // where to send the message
+
+  // one-shot constructor
+  mb_timeout(const mb_time &abs_time,
+            pmt_t user_data, mb_msg_accepter_sptr accepter);
+
+  // periodic constructor
+  mb_timeout(const mb_time &first_abs_time, const mb_time &delta_time,
+            pmt_t user_data, mb_msg_accepter_sptr accepter);
+
+  pmt_t handle() const { return d_handle; }
+};
+
+typedef boost::shared_ptr<mb_timeout> mb_timeout_sptr;
+
+
+//! Sort criterion for priority_queue
+class timeout_later
+{
+public:
+  bool operator() (const mb_timeout_sptr t1, const mb_timeout_sptr t2)
+  {
+    return t1->d_when > t2->d_when;
+  }
+};
+
+
+class mb_timer_queue : public std::priority_queue<mb_timeout_sptr,
+                                                 std::vector<mb_timeout_sptr>,
+                                                 timeout_later>
+{
+public:
+  void cancel(pmt_t handle);
+};
+
+#endif /* INCLUDED_MB_TIMER_QUEUE_H */

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_worker.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_worker.cc    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mb_worker.cc    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -27,6 +27,7 @@
 #include <mb_exception.h>
 #include <mb_mblock.h>
 #include <mb_gettid.h>
+#include <mb_msg_accepter.h>
 #include <iostream>
 #ifdef HAVE_SCHED_H
 #include <sched.h>
@@ -34,6 +35,10 @@
 
 #define VERBOSE 0              // define to 0 or 1
 
+
+static pmt_t s_worker_state_changed = pmt_intern("%worker-state-changed");
+
+
 mb_worker::mb_worker(mb_runtime_thread_per_block *runtime,
                     mb_mblock_maker_t maker,
                     const std::string &instance_name,
@@ -56,7 +61,7 @@
 static void
 set_affinity(const std::string &instance_name, const std::string &class_name)
 {
-  static int   counter = 0;
+  //static int counter = 0;
   cpu_set_t    mask;
   CPU_ZERO(&mask);
 
@@ -81,12 +86,15 @@
 void
 mb_worker::set_state(worker_state_t state)
 {
-  omni_mutex_lock  l1(d_runtime->d_mutex);     // lock runtime first, then 
worker
-  omni_mutex_lock  l2(d_mutex);
+  {
+    omni_mutex_lock  l2(d_mutex);
 
-  d_state = state;                       // update our state
-  d_state_cond.broadcast();              // Notify everybody who cares...
-  d_runtime->d_runtime_cond.broadcast();
+    d_state = state;                     // update our state
+    d_state_cond.broadcast();            // Notify everybody who cares...
+  }
+
+  // send msg to runtime, telling it something changed.
+  (*d_runtime->accepter())(s_worker_state_changed, PMT_F, PMT_F, MB_PRI_BEST);
 }
 
 void *

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mbi_runtime_lock.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mbi_runtime_lock.h  
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/mbi_runtime_lock.h  
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -48,9 +48,9 @@
  */
 
 class mbi_runtime_lock : boost::noncopyable {
-  mb_runtime   *d_rt;
+  mb_runtime_base      *d_rt;
 public:
-  mbi_runtime_lock(mb_runtime *rt) : d_rt(rt) { d_rt->lock(); }
+  mbi_runtime_lock(mb_runtime_base *rt) : d_rt(rt) { d_rt->lock(); }
   mbi_runtime_lock(mb_mblock_impl *mi) : d_rt(mi->runtime()) { d_rt->lock(); }
   mbi_runtime_lock(mb_mblock *mb) : d_rt(mb->impl()->runtime()) { 
d_rt->lock(); }
   ~mbi_runtime_lock(void) { d_rt->unlock(); }

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_bitset.mbh
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_bitset.mbh   
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_bitset.mbh   
2007-05-01 20:16:37 UTC (rev 5209)
@@ -40,3 +40,22 @@
 
    )
   )
+
+;; ----------------------------------------------------------------
+;; qa-disconnect -- interface to mblock QA code
+;;
+
+(define-protocol-class qa-disconnect-cs
+
+  (:outgoing
+
+   (select-pipe n)
+
+   )
+
+  (:incoming
+
+   (ack n)
+
+   )
+  )

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_disconnect.cc 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/qa_disconnect.cc)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_disconnect.cc    
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_disconnect.cc    
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,238 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_mblock.h>
+#include <mb_protocol_class.h>
+#include <mb_message.h>
+#include <mb_class_registry.h>
+#include <iostream>
+#include <sstream>
+#include <bitset>
+
+static pmt_t s_in = pmt_intern("in");
+static pmt_t s_out = pmt_intern("out");
+static pmt_t s_data = pmt_intern("data");
+static pmt_t s_ack = pmt_intern("ack");
+static pmt_t s_select_pipe = pmt_intern("select-pipe");
+static pmt_t s_long0 = pmt_from_long(0);
+static pmt_t s_sys_port = pmt_intern("%sys-port");
+static pmt_t s_shutdown = pmt_intern("%shutdown");
+
+class qa_disconnect_mux : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+  mb_port_sptr d_cs;
+
+public:
+  qa_disconnect_mux(mb_runtime *runtime, const std::string &instance_name, 
pmt_t user_arg);
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+};
+
+qa_disconnect_mux::qa_disconnect_mux(mb_runtime *runtime,
+                                    const std::string &instance_name,
+                                    pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+  d_cs  = define_port("cs", "qa-disconnect-cs", true, mb_port::EXTERNAL);
+
+  define_component("pipeline0", "qa_bitset8", pmt_from_long(0));
+  define_component("pipeline1", "qa_bitset8", pmt_from_long(8));
+}
+
+void
+qa_disconnect_mux::initial_transition(){}
+
+void
+qa_disconnect_mux::handle_message(mb_message_sptr msg)
+{
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())      // select-pipe on cs
+      && pmt_eq(msg->signal(), s_select_pipe)){                
+
+    long which_pipe = pmt_to_long(pmt_nth(0, msg->data()));
+
+    disconnect_component("pipeline0");
+    disconnect_component("pipeline1");
+
+    switch(which_pipe){
+
+    case 0:
+      connect("self", "in",  "pipeline0", "in");
+      connect("self", "out", "pipeline0", "out");
+      break;
+
+    case 1:
+      connect("self", "in",  "pipeline1", "in");
+      connect("self", "out", "pipeline1", "out");
+      break;
+    }
+
+    d_cs->send(s_ack, msg->data());
+    return;
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_disconnect_mux);
+
+// ------------------------------------------------------------------------
+
+class qa_disconnect_top : public mb_mblock
+{
+  enum state_t {
+    UNINITIALIZED,
+    WAIT_FOR_ACK,
+    WAIT_FOR_DATA
+  };
+
+  state_t      d_state;
+  int          d_msg_number;
+  int          d_nmsgs_to_send;
+
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+  mb_port_sptr d_cs;
+
+  void check_pipe_send_next_msg();
+  void send_next_msg();
+  void select_pipe(int n);
+
+  // alternate pipes every 128 messages
+  static int  which_pipe(int msg_number) { return (msg_number >> 7) & 0x1; }
+  bool time_to_switch() { return (d_msg_number & 0x7f) == 0; }
+  
+public:
+  qa_disconnect_top(mb_runtime *runtime, const std::string &instance_name, 
pmt_t user_arg);
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+};
+
+qa_disconnect_top::qa_disconnect_top(mb_runtime *runtime,
+                                    const std::string &instance_name,
+                                    pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_state(UNINITIALIZED), d_msg_number(0)
+{
+  d_nmsgs_to_send = pmt_to_long(pmt_nth(0, user_arg));
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::INTERNAL);
+  d_out = define_port("out", "qa-bitset", true, mb_port::INTERNAL);
+  d_cs  = define_port("cs", "qa-disconnect-cs", false, mb_port::INTERNAL);
+
+  define_component("mux", "qa_disconnect_mux", PMT_F);
+
+  connect("self", "cs",  "mux", "cs");
+  connect("self", "out", "mux", "in");
+  connect("self", "in",  "mux", "out");
+}
+
+void
+qa_disconnect_top::initial_transition()
+{
+  check_pipe_send_next_msg();
+}
+
+void
+qa_disconnect_top::handle_message(mb_message_sptr msg)
+{
+  if (0)
+    std::cerr << "qa_disconnect_top::handle_msg state = "
+             << d_state << "\n  msg = " << msg << std::endl;
+
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())      // ack on cs
+      && pmt_eq(msg->signal(), s_ack)
+      && d_state == WAIT_FOR_ACK){
+
+    send_next_msg();
+    return;
+  }
+
+  if (pmt_eq(msg->port_id(), d_in->port_symbol())      // data on in
+      && pmt_eq(msg->signal(), s_data)
+      && d_state == WAIT_FOR_DATA){
+
+    /* 
+     * Confirm that msg passed through the pipe that we expect...
+     */
+    static const long expected_mask[2] = { 0x000000ff, 0x0000ff00 };
+
+    long msg_number = pmt_to_long(pmt_car(msg->data()));
+    long mask = pmt_to_long(pmt_cdr(msg->data()));
+
+    if (mask != expected_mask[which_pipe(msg_number)]){
+      fprintf(stderr, "\nqa_disconnect_top: wrong mask in msg_number = 
0x%08lx\n",
+             msg_number);
+      fprintf(stderr, "  expected = 0x%08lx, actual = 0x%08lx\n",
+             expected_mask[which_pipe(msg_number)], mask);
+      shutdown_all(PMT_F);
+      return;
+    }
+
+    if (msg_number == d_nmsgs_to_send - 1){    // we're done (and were 
successful)
+      shutdown_all(PMT_T);
+      return;
+    }
+
+    check_pipe_send_next_msg();
+    return;
+  }
+
+  if (pmt_eq(msg->port_id(), s_sys_port)       // ignore %shutdown on %sys-port
+      && pmt_eq(msg->signal(), s_shutdown))
+    return;
+
+  std::cerr << "qa_disconnect_top: unhandled msg: state = "
+           << d_state << "\n  msg = " << msg << std::endl;
+}
+
+void
+qa_disconnect_top::select_pipe(int n)
+{
+  d_cs->send(s_select_pipe, pmt_list1(pmt_from_long(n)));
+  d_state = WAIT_FOR_ACK;
+}
+
+void
+qa_disconnect_top::send_next_msg()
+{
+  d_state = WAIT_FOR_DATA;
+  if (d_msg_number == d_nmsgs_to_send) // we've sent all we're supposed to
+    return;
+
+  d_out->send(s_data, pmt_cons(pmt_from_long(d_msg_number), s_long0));
+  d_msg_number++;
+}
+
+void
+qa_disconnect_top::check_pipe_send_next_msg()
+{
+  if (time_to_switch())
+    select_pipe(which_pipe(d_msg_number));
+  else
+    send_next_msg();
+}
+
+REGISTER_MBLOCK_CLASS(qa_disconnect_top);

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock.cc    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock.cc    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -28,6 +28,7 @@
 #include <qa_mblock_prims.h>
 #include <qa_mblock_send.h>
 #include <qa_mblock_sys.h>
+#include <qa_timeouts.h>
 
 CppUnit::TestSuite *
 qa_mblock::suite()
@@ -37,6 +38,7 @@
   s->addTest (qa_mblock_prims::suite());
   s->addTest (qa_mblock_send::suite());
   s->addTest (qa_mblock_sys::suite());
+  s->addTest (qa_timeouts::suite());
   
   return s;
 }

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.cc    
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.cc    
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -250,3 +250,22 @@
   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
 }
 
+// ================================================================
+//                       test_disconnect
+// ================================================================
+
+void
+qa_mblock_sys::test_disconnect()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  long nmsgs =        10240;
+  
+  pmt_t arg = pmt_list1(pmt_from_long(nmsgs)); // # of messages to send 
through pipe
+
+
+  rt->run("top", "qa_disconnect_top", arg, &result);
+
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}

Modified: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.h 
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_mblock_sys.h 
2007-05-01 20:16:37 UTC (rev 5209)
@@ -31,12 +31,14 @@
   CPPUNIT_TEST(test_sys_1);
   CPPUNIT_TEST(test_sys_2);
   CPPUNIT_TEST(test_bitset_1);
+  CPPUNIT_TEST(test_disconnect);
   CPPUNIT_TEST_SUITE_END();
 
  private:
   void test_sys_1();
   void test_sys_2();
   void test_bitset_1();
+  void test_disconnect();
 };
 
 #endif /* INCLUDED_QA_MBLOCK_SYS_H */

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.cc 
(from rev 5208, 
gnuradio/branches/features/inband-usb/mblock/src/lib/qa_timeouts.cc)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.cc  
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.cc  
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,292 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_timeouts.h>
+#include <cppunit/TestAssert.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#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 <mb_timer_queue.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+
+
+static pmt_t s_timeout = pmt_intern("%timeout");
+static pmt_t s_done = pmt_intern("done");
+
+
+// ------------------------------------------------------------------------
+// This test exercises the priority queue that we use to implement timeouts
+// ------------------------------------------------------------------------
+void
+qa_timeouts::test_timer_queue()
+{
+  mb_timer_queue       tq;
+  mb_msg_accepter_sptr accepter;
+
+  mb_timeout_sptr      t1000_000 =
+    mb_timeout_sptr(new mb_timeout(mb_time(1000,0), PMT_F, accepter));
+
+  mb_timeout_sptr      t2000_000 =
+    mb_timeout_sptr(new mb_timeout(mb_time(2000,0), PMT_F, accepter));
+                                                                   
+  mb_timeout_sptr      t3000_000 =
+    mb_timeout_sptr(new mb_timeout(mb_time(3000,0), PMT_F, accepter));
+                                                                   
+  mb_timeout_sptr      t3000_125 =
+    mb_timeout_sptr(new mb_timeout(mb_time(3000,125), PMT_F, accepter));
+                                                                   
+  mb_timeout_sptr      t3000_250 =
+    mb_timeout_sptr(new mb_timeout(mb_time(3000,250), PMT_F, accepter));
+                                                                   
+  mb_timeout_sptr      t4000_000 =
+    mb_timeout_sptr(new mb_timeout(mb_time(4000,0), PMT_F, accepter));
+                                                                   
+  // insert in pseudo-random order
+
+  tq.push(t3000_125);
+  tq.push(t1000_000);
+  tq.push(t4000_000);
+  tq.push(t3000_250);
+  tq.push(t2000_000);
+  tq.push(t3000_000);
+
+  CPPUNIT_ASSERT_EQUAL(t1000_000, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t2000_000, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t3000_000, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t3000_125, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t3000_250, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t4000_000, tq.top());
+  tq.pop();
+
+  CPPUNIT_ASSERT(tq.empty());
+
+  // insert in pseudo-random order
+
+  tq.push(t3000_000);
+  tq.push(t4000_000);
+  tq.push(t3000_125);
+  tq.push(t1000_000);
+  tq.push(t2000_000);
+  tq.push(t3000_250);
+
+  tq.cancel(t1000_000->handle());
+
+  CPPUNIT_ASSERT_EQUAL(t2000_000, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t3000_000, tq.top());
+  tq.pop();
+  
+  tq.cancel(t3000_250->handle());
+
+  CPPUNIT_ASSERT_EQUAL(t3000_125, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT_EQUAL(t4000_000, tq.top());
+  tq.pop();
+  
+  CPPUNIT_ASSERT(tq.empty());
+}
+
+// ------------------------------------------------------------------------
+//   Test one-shot timeouts
+// ------------------------------------------------------------------------
+
+// FWIW, on SuSE 10.1 for x86-64, clock_getres returns 0.004 seconds.
+
+#define TIMING_MARGIN 0.010    // seconds
+
+class qa_timeouts_1_top : public mb_mblock
+{
+  int          d_nleft;
+  int          d_nerrors;
+  mb_time      d_t0;
+  
+public:
+  qa_timeouts_1_top(mb_runtime *runtime,
+                   const std::string &instance_name, pmt_t user_arg);
+
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+};
+
+qa_timeouts_1_top::qa_timeouts_1_top(mb_runtime *runtime,
+                                    const std::string &instance_name,
+                                    pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_nleft(0), d_nerrors(0)
+{
+}
+
+void
+qa_timeouts_1_top::initial_transition()
+{
+  d_t0 = mb_time::time();      // now
+
+  schedule_one_shot_timeout(d_t0 + 0.200, pmt_from_double(0.200));
+  schedule_one_shot_timeout(d_t0 + 0.125, pmt_from_double(0.125));
+  schedule_one_shot_timeout(d_t0 + 0.075, pmt_from_double(0.075));
+  schedule_one_shot_timeout(d_t0 + 0.175, pmt_from_double(0.175));
+
+  d_nleft = 4;
+}
+
+void
+qa_timeouts_1_top::handle_message(mb_message_sptr msg)
+{
+  if (pmt_eq(msg->signal(), s_timeout)){
+    mb_time t_now = mb_time::time();
+    double expected_delta_t = pmt_to_double(msg->data());
+    double actual_delta_t = (t_now - d_t0).double_time();
+    double delta = expected_delta_t - actual_delta_t;
+
+    if (fabs(delta) > TIMING_MARGIN){
+      std::cerr << "qa_timeouts_1_top: expected_delta_t = " << expected_delta_t
+               << " actual_delta_t = " << actual_delta_t << std::endl;
+      d_nerrors++;
+    }
+
+    if (--d_nleft <= 0)
+      shutdown_all(d_nerrors == 0 ? PMT_T : PMT_F);
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_timeouts_1_top);
+
+void
+qa_timeouts::test_timeouts_1()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "qa_timeouts_1_top", PMT_F, &result);
+
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+// ------------------------------------------------------------------------
+//   Test periodic timeouts
+// ------------------------------------------------------------------------
+
+class qa_timeouts_2_top : public mb_mblock
+{
+  int          d_nhandled;
+  int          d_nerrors;
+  double       d_delta_t;
+  mb_time      d_t0;
+  
+public:
+  qa_timeouts_2_top(mb_runtime *runtime,
+                   const std::string &instance_name, pmt_t user_arg);
+
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+};
+
+qa_timeouts_2_top::qa_timeouts_2_top(mb_runtime *runtime,
+                                    const std::string &instance_name,
+                                    pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_nhandled(0), d_nerrors(0), d_delta_t(0.075)
+{
+}
+
+void
+qa_timeouts_2_top::initial_transition()
+{
+  d_t0 = mb_time::time();      // now
+
+  schedule_periodic_timeout(d_t0 + d_delta_t, mb_time(d_delta_t), PMT_T);
+}
+
+void
+qa_timeouts_2_top::handle_message(mb_message_sptr msg)
+{
+  static const int NMSGS_TO_HANDLE = 5;
+
+  if (pmt_eq(msg->signal(), s_timeout)
+      && !pmt_eq(msg->data(), s_done)){
+
+    mb_time t_now = mb_time::time();
+
+    d_nhandled++;
+
+    double expected_delta_t = d_delta_t * d_nhandled;
+    double actual_delta_t = (t_now - d_t0).double_time();
+    double delta = expected_delta_t - actual_delta_t;
+
+    if (fabs(delta) > TIMING_MARGIN){
+      std::cerr << "qa_timeouts_2_top: expected_delta_t = " << expected_delta_t
+               << " actual_delta_t = " << actual_delta_t << std::endl;
+      d_nerrors++;
+    }
+
+    if (d_nhandled == NMSGS_TO_HANDLE){
+      cancel_timeout(msg->metadata()); // test cancel_timeout...
+      schedule_one_shot_timeout(d_t0 + (d_delta_t * (d_nhandled + 2)), s_done);
+    }
+  }
+
+  if (pmt_eq(msg->signal(), s_timeout)
+      && pmt_eq(msg->data(), s_done)){
+    if (d_nhandled != NMSGS_TO_HANDLE){
+      std::cerr << "qa_timeouts_2_top: d_nhandled = " << d_nhandled
+               << " expected d_nhandled = " << NMSGS_TO_HANDLE
+               << " (cancel_timeout didn't work)\n";
+      d_nerrors++;
+    }
+    shutdown_all(d_nerrors == 0 ? PMT_T : PMT_F);
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_timeouts_2_top);
+
+void
+qa_timeouts::test_timeouts_2()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  rt->run("top", "qa_timeouts_2_top", PMT_F, &result);
+
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}

Copied: 
gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.h (from 
rev 5208, gnuradio/branches/features/inband-usb/mblock/src/lib/qa_timeouts.h)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.h   
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/mblock/src/lib/qa_timeouts.h   
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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 GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef INCLUDED_QA_TIMEOUTS_H
+#define INCLUDED_QA_TIMEOUTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_timeouts : public CppUnit::TestCase {
+
+  CPPUNIT_TEST_SUITE(qa_timeouts);
+  CPPUNIT_TEST(test_timer_queue);
+  CPPUNIT_TEST(test_timeouts_1);
+  CPPUNIT_TEST(test_timeouts_2);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_timer_queue();
+  void test_timeouts_1();
+  void test_timeouts_2();
+};
+
+#endif /* INCLUDED_QA_TIMEOUTS_H */
+

Modified: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/Makefile.am
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/Makefile.am        
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/Makefile.am        
2007-05-01 20:16:37 UTC (rev 5209)
@@ -21,7 +21,7 @@
 
 include $(top_srcdir)/Makefile.common
 
-INCLUDES = $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+INCLUDES = $(DEFINES) $(OMNITHREAD_INCLUDES) $(BOOST_CFLAGS) 
$(CPPUNIT_INCLUDES) 
 
 TESTS = test_pmt
 
@@ -62,6 +62,7 @@
 libpmt_la_SOURCES =                    \
        pmt.cc                          \
        pmt_io.cc                       \
+       pmt_pool.cc                     \
        pmt_serialize.cc                \
        pmt_unv.cc                      
 
@@ -70,10 +71,12 @@
 
 # link the library against the c++ standard library
 libpmt_la_LIBADD =                     \
+       $(OMNITHREAD_LA)                \
        -lstdc++                        
 
 include_HEADERS =                      \
        pmt.h                           \
+       pmt_pool.h                      \
        pmt_serial_tags.h               
 
 noinst_HEADERS =                       \

Modified: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.cc     
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.cc     
2007-05-01 20:16:37 UTC (rev 5209)
@@ -26,7 +26,34 @@
 #include <vector>
 #include <pmt.h>
 #include "pmt_int.h"
+#include <stdio.h>
+#include <pmt_pool.h>
 
+static const int CACHE_LINE_SIZE = 64;         // good guess
+
+# if (PMT_LOCAL_ALLOCATOR)
+
+static pmt_pool global_pmt_pool(sizeof(pmt_pair), CACHE_LINE_SIZE);
+
+void *
+pmt_base::operator new(size_t size)
+{
+  void *p = global_pmt_pool.malloc();
+
+  // fprintf(stderr, "pmt_base::new p = %p\n", p);
+  assert((reinterpret_cast<intptr_t>(p) & (CACHE_LINE_SIZE - 1)) == 0);
+  return p;
+}
+
+void
+pmt_base::operator delete(void *p, size_t size)
+{
+  global_pmt_pool.free(p);
+}
+
+#endif
+
+
 pmt_base::~pmt_base()
 {
   // nop -- out of line virtual destructor
@@ -108,6 +135,12 @@
   return dynamic_cast<pmt_dict*>(x.get());
 }
 
+static pmt_any *
+_any(pmt_t x)
+{
+  return dynamic_cast<pmt_any*>(x.get());
+}
+
 ////////////////////////////////////////////////////////////////////////////
 //                           Globals
 ////////////////////////////////////////////////////////////////////////////
@@ -173,7 +206,7 @@
   unsigned int h = 0;
   unsigned int g = 0;
 
-  for (std::string::const_iterator p = s.begin(); p != s.end(); p++){
+  for (std::string::const_iterator p = s.begin(); p != s.end(); ++p){
     h = (h << 4) + (*p & 0xff);
     g = h & 0xf0000000;
     if (g){
@@ -603,6 +636,40 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////
+//                                 Any
+////////////////////////////////////////////////////////////////////////////
+
+pmt_any::pmt_any(const boost::any &any) : d_any(any) {}
+
+bool
+pmt_is_any(pmt_t obj)
+{
+  return obj->is_any();
+}
+
+pmt_t
+pmt_make_any(const boost::any &any)
+{
+  return pmt_t(new pmt_any(any));
+}
+
+boost::any
+pmt_any_ref(pmt_t obj)
+{
+  if (!obj->is_any())
+    throw pmt_wrong_type("pmt_any_ref", obj);
+  return _any(obj)->ref();
+}
+
+void
+pmt_any_set(pmt_t obj, const boost::any &any)
+{
+  if (!obj->is_any())
+    throw pmt_wrong_type("pmt_any_set", obj);
+  _any(obj)->set(any);
+}
+
+////////////////////////////////////////////////////////////////////////////
 //                          General Functions
 ////////////////////////////////////////////////////////////////////////////
 
@@ -911,3 +978,20 @@
 {
   return pmt_eq(obj, PMT_EOF);
 }
+
+void
+pmt_dump_sizeof()
+{
+  printf("sizeof(pmt_t)              = %3zd\n", sizeof(pmt_t));
+  printf("sizeof(pmt_base)           = %3zd\n", sizeof(pmt_base));
+  printf("sizeof(pmt_bool)           = %3zd\n", sizeof(pmt_bool));
+  printf("sizeof(pmt_symbol)         = %3zd\n", sizeof(pmt_symbol));
+  printf("sizeof(pmt_integer)        = %3zd\n", sizeof(pmt_integer));
+  printf("sizeof(pmt_real)           = %3zd\n", sizeof(pmt_real));
+  printf("sizeof(pmt_complex)        = %3zd\n", sizeof(pmt_complex));
+  printf("sizeof(pmt_null)           = %3zd\n", sizeof(pmt_null));
+  printf("sizeof(pmt_pair)           = %3zd\n", sizeof(pmt_pair));
+  printf("sizeof(pmt_vector)         = %3zd\n", sizeof(pmt_vector));
+  printf("sizeof(pmt_dict)           = %3zd\n", sizeof(pmt_dict));
+  printf("sizeof(pmt_uniform_vector) = %3zd\n", sizeof(pmt_uniform_vector));
+}

Modified: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.h      
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt.h      
2007-05-01 20:16:37 UTC (rev 5209)
@@ -24,6 +24,7 @@
 #define INCLUDED_PMT_H
 
 #include <boost/shared_ptr.hpp>
+#include <boost/any.hpp>
 #include <complex>
 #include <string>
 #include <stdint.h>
@@ -421,6 +422,28 @@
 
 /*
  * ------------------------------------------------------------------------
+ *   Any (wraps boost::any -- can be used to wrap pretty much anything)
+ *
+ * Cannot be serialized or used across process boundaries.
+ * See http://www.boost.org/doc/html/any.html
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if \p obj is an any
+bool pmt_is_any(pmt_t obj);
+
+//! make an any
+pmt_t pmt_make_any(const boost::any &any);
+
+//! Return underlying boost::any
+boost::any pmt_any_ref(pmt_t obj);
+
+//! Store \p any in \p obj
+void pmt_any_set(pmt_t obj, const boost::any &any);
+
+
+/*
+ * ------------------------------------------------------------------------
  *                       General functions
  * ------------------------------------------------------------------------
  */
@@ -632,4 +655,7 @@
  */
 pmt_t pmt_deserialize(std::streambuf &source);
 
+
+void pmt_dump_sizeof();        // debugging
+
 #endif /* INCLUDED_PMT_H */

Modified: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_int.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_int.h  
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_int.h  
2007-05-01 20:16:37 UTC (rev 5209)
@@ -31,6 +31,8 @@
  * See pmt.h for the public interface
  */
 
+#define PMT_LOCAL_ALLOCATOR 0          // define to 0 or 1
+
 class pmt_base : boost::noncopyable {
 protected:
   pmt_base(){};
@@ -47,6 +49,7 @@
   virtual bool is_pair()    const { return false; }
   virtual bool is_vector()  const { return false; }
   virtual bool is_dict()    const { return false; }
+  virtual bool is_any()     const { return false; }
 
   virtual bool is_uniform_vector() const { return false; }
   virtual bool is_u8vector()  const { return false; }
@@ -62,6 +65,10 @@
   virtual bool is_c32vector() const { return false; }
   virtual bool is_c64vector() const { return false; }
 
+# if (PMT_LOCAL_ALLOCATOR)
+  void *operator new(size_t);
+  void operator delete(void *, size_t);
+#endif
 };
 
 class pmt_bool : public pmt_base
@@ -189,6 +196,20 @@
   pmt_t values() const;
 };
 
+class pmt_any : public pmt_base
+{
+  boost::any   d_any;
+
+public:
+  pmt_any(const boost::any &any);
+  //~pmt_any();
+
+  bool is_any() const { return true; }
+  const boost::any &ref() const { return d_any; }
+  void  set(const boost::any &any) { d_any = any; }
+};
+
+
 class pmt_uniform_vector : public pmt_base
 {
 public:

Copied: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.cc 
(from rev 5208, gnuradio/branches/features/inband-usb/pmt/src/lib/pmt_pool.cc)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.cc        
                        (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.cc        
2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,96 @@
+/* -*- 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 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pmt_pool.h>
+#include <algorithm>
+#include <stdint.h>
+
+static inline size_t
+ROUNDUP(size_t x, size_t stride)
+{
+  return ((((x) + (stride) - 1)/(stride)) * (stride));
+}
+
+pmt_pool::pmt_pool(size_t itemsize, size_t alignment, size_t allocation_size)
+  : d_itemsize(ROUNDUP(itemsize, alignment)),
+    d_alignment(alignment),
+    d_allocation_size(std::max(allocation_size, 16 * itemsize)),
+    d_freelist(0)
+{
+}
+
+pmt_pool::~pmt_pool()
+{
+  for (unsigned int i = 0; i < d_allocations.size(); i++){
+    delete [] d_allocations[i];
+  }
+}
+
+void *
+pmt_pool::malloc()
+{
+  omni_mutex_lock l(d_mutex);
+  item *p;
+
+  if (d_freelist){     // got something?
+    p = d_freelist;
+    d_freelist = p->d_next;
+    return p;
+  }
+
+  // allocate a new chunk
+  char *alloc = new char[d_allocation_size + d_alignment - 1];
+  d_allocations.push_back(alloc);
+
+  // get the alignment we require
+  char *start = (char *)(((uintptr_t)alloc + d_alignment-1) & -d_alignment);
+  char *end = alloc + d_allocation_size + d_alignment - 1;
+  size_t n = (end - start) / d_itemsize;
+
+  // link the new items onto the free list.
+  p = (item *) start;
+  for (size_t i = 0; i < n; i++){
+    p->d_next = d_freelist;
+    d_freelist = p;
+    p = (item *)((char *) p + d_itemsize);
+  }
+
+  // now return the first one
+  p = d_freelist;
+  d_freelist = p->d_next;
+  return p;
+}
+
+void
+pmt_pool::free(void *foo)
+{
+  if (!foo)
+    return;
+
+  omni_mutex_lock l(d_mutex);
+
+  item *p = (item *) foo;
+  p->d_next = d_freelist;
+  d_freelist = p;
+}

Copied: gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.h 
(from rev 5208, gnuradio/branches/features/inband-usb/pmt/src/lib/pmt_pool.h)
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.h         
                (rev 0)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_pool.h 
2007-05-01 20:16:37 UTC (rev 5209)
@@ -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 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.
+ */
+#ifndef INCLUDED_PMT_POOL_H
+#define INCLUDED_PMT_POOL_H
+
+#include <cstddef>
+#include <omnithread.h>
+#include <vector>
+
+/*!
+ * \brief very simple thread-safe fixed-size allocation pool
+ *
+ * FIXME may want to go to global allocation with per-thread free list.
+ * This would eliminate virtually all lock contention.
+ */
+class pmt_pool {
+
+  struct item {
+    struct item        *d_next;
+  };
+  
+  omni_mutex         d_mutex;
+  
+  size_t             d_itemsize;
+  size_t             d_alignment;
+  size_t             d_allocation_size;
+  item              *d_freelist;
+  std::vector<char *> d_allocations;
+
+public:
+  /*!
+   * \param itemsize size in bytes of the items to be allocated.
+   * \param alignment alignment in bytes of all objects to be allocated (must 
be power-of-2).
+   * \param allocation_size number of bytes to allocate at a time from the 
underlying allocator.
+   */
+  pmt_pool(size_t itemsize, size_t alignment = 16, size_t allocation_size = 
4096);
+  ~pmt_pool();
+
+  void *malloc();
+  void free(void *p);
+};
+
+#endif /* INCLUDED_PMT_POOL_H */

Modified: 
gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_serialize.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_serialize.cc   
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/pmt_serialize.cc   
2007-05-01 20:16:37 UTC (rev 5209)
@@ -57,6 +57,7 @@
   return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
 }
 
+#if 0
 // always writes big-endian
 static bool
 serialize_untagged_u64(uint64_t i, std::streambuf &sb)
@@ -70,6 +71,7 @@
   sb.sputc((i >>  8) & 0xff);
   return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
 }
+#endif
 
 // ----------------------------------------------------------------
 // input primitives
@@ -128,6 +130,7 @@
   return t != std::streambuf::traits_type::eof();
 }
 
+#if 0
 // always reads big-endian
 static bool
 deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb)
@@ -156,6 +159,7 @@
   *ip = i;
   return t != std::streambuf::traits_type::eof();
 }
+#endif
 
 /*
  * Write portable byte-serial representation of \p obj to \p sb
@@ -203,7 +207,7 @@
     if (pmt_is_integer(obj)){
       long i = pmt_to_long(obj);
       if (sizeof(long) > 4){
-       if (i < -2147483648 || i > 2147483647)
+       if (i < -2147483647 || i > 2147483647)
          throw pmt_notimplemented("pmt_serialize (64-bit integers)", obj);
       }
       ok = serialize_untagged_u8(PST_INT32, sb);
@@ -241,10 +245,10 @@
 pmt_deserialize(std::streambuf &sb)
 {
   uint8_t      tag;
-  uint8_t      u8;
+  //uint8_t    u8;
   uint16_t     u16;
   uint32_t     u32;
-  uint32_t     u64;
+  //uint32_t   u64;
   static char   tmpbuf[1024];
 
   if (!deserialize_untagged_u8(&tag, sb))

Modified: 
gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.cc
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.cc    
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.cc    
2007-05-01 20:16:37 UTC (rev 5209)
@@ -295,7 +295,58 @@
   CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
 }
 
+// ------------------------------------------------------------------------
+
+// class foo is used in test_any below.
+// It can't be declared in the scope of test_any because of template
+// namespace problems.
+
+class foo {
+public:
+  double       d_double;
+  int          d_int;
+  foo(double d=0, int i=0) : d_double(d), d_int(i) {}
+};
+
+bool operator==(const foo &a, const foo &b)
+{
+  return a.d_double == b.d_double && a.d_int == b.d_int;
+}
+
+std::ostream& operator<<(std::ostream &os, const foo obj)
+{
+  os << "<foo: " << obj.d_double << ", " << obj.d_int << ">";
+  return os;
+}
+
 void
+qa_pmt_prims::test_any()
+{
+  boost::any a0;
+  boost::any a1;
+  boost::any a2;
+
+  a0 = std::string("Hello!");
+  a1 = 42;
+  a2 = foo(3.250, 21);
+
+  pmt_t p0 = pmt_make_any(a0);
+  pmt_t p1 = pmt_make_any(a1);
+  pmt_t p2 = pmt_make_any(a2);
+
+  CPPUNIT_ASSERT_EQUAL(std::string("Hello!"),
+                      boost::any_cast<std::string>(pmt_any_ref(p0)));
+
+  CPPUNIT_ASSERT_EQUAL(42,
+                      boost::any_cast<int>(pmt_any_ref(p1)));
+
+  CPPUNIT_ASSERT_EQUAL(foo(3.250, 21),
+                      boost::any_cast<foo>(pmt_any_ref(p2)));
+}
+
+// ------------------------------------------------------------------------
+
+void
 qa_pmt_prims::test_serialize()
 {
   std::stringbuf sb;           // fake channel

Modified: 
gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.h
===================================================================
--- gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.h     
2007-05-01 16:36:51 UTC (rev 5208)
+++ gnuradio/branches/developers/thottelt/inband/pmt/src/lib/qa_pmt_prims.h     
2007-05-01 20:16:37 UTC (rev 5209)
@@ -38,6 +38,7 @@
   CPPUNIT_TEST(test_equivalence);
   CPPUNIT_TEST(test_misc);
   CPPUNIT_TEST(test_dict);
+  CPPUNIT_TEST(test_any);
   CPPUNIT_TEST(test_io);
   CPPUNIT_TEST(test_serialize);
   CPPUNIT_TEST_SUITE_END();
@@ -53,6 +54,7 @@
   void test_equivalence();
   void test_misc();
   void test_dict();
+  void test_any();
   void test_io();
   void test_serialize();
 };

Modified: 
gnuradio/branches/developers/thottelt/inband/pmt/src/scheme/gnuradio/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/pmt/src/scheme/gnuradio/Makefile.am
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/pmt/src/scheme/gnuradio/Makefile.am
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -21,7 +21,9 @@
 #pkgdatadir = $(datadir)/gnuradio
 
 EXTRA_DIST =                           \
-       gen-serial-tags.scm             
+       gen-serial-tags.scm             \
+       pmt-serial-tags.scm             \
+       pmt-serialize.scm               
 
 
 # really scheme source files

Modified: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/Makefile.am   
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/Makefile.am   
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -24,8 +24,14 @@
        $(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
        $(USRP_INCLUDES) $(BOOST_CFLAGS)
 
-EXTRA_DIST =                           
 
+EXTRA_DIST =                           \
+       usrp_server.mbh                 \
+       dump_packets.py                 \
+       usb_packet.py                   \
+       gen_test_packets.py             
+
+
 noinst_LTLIBRARIES = libinband.la
 
 
@@ -47,6 +53,10 @@
 include_HEADERS =                      \
        usrp_server.h                   
 
+noinst_HEADERS =                       \
+       usrp_inband_usb_packet.h        
+
+
 MOSTLYCLEANFILES = \
        $(BUILT_SOURCES) *~ *.pyc
 

Copied: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/dump_packets.py
 (from rev 5208, 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/dump_packets.py)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/dump_packets.py
                           (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/dump_packets.py
   2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import sys
+import struct
+from optparse import OptionParser
+
+from usb_packet import *
+
+def dump_packet(raw_pkt, outfile, dump_payload):
+    pkt = usb_packet(raw_pkt)
+    outfile.write(pkt.decoded_flags())
+    outfile.write(' chan= %2d  len= %3d timestamp= 0x%08x rssi= % 2d  tag= 
%2d\n' % (
+        pkt.chan(), pkt.payload_len(), pkt.timestamp(), pkt.rssi(), pkt.tag()))
+    if dump_payload:
+        assert pkt.payload_len() % 4 == 0
+        shorts = struct.unpack('<%dh' % (pkt.payload_len() // 2), 
pkt.payload())
+        for i in range(0, len(shorts), 2):
+            outfile.write('  %6d, %6d\n' % (shorts[i], shorts[i+1]))
+        
+
+def dump_packets(infile, outfile, dump_payload):
+    raw_pkt = infile.read(512)
+    while raw_pkt:
+        if len(raw_pkt) != 512:
+            sys.stderr.write("File length is not a multiple of 512 bytes")
+            raise SystemExit, 1
+
+        dump_packet(raw_pkt, outfile, dump_payload)
+        raw_pkt = infile.read(512)
+
+
+def main():
+    parser = OptionParser()
+    parser.add_option('-p', '--dump-payload', action='store_true', 
default=False,
+                      help='dump payload in decimal and hex')
+
+    (options, files) = parser.parse_args()
+    if len(files) == 0:
+        dump_packets(sys.stdin, sys.stdout, options.dump_payload)
+    else:
+        for f in files:
+            dump_packets(open(f, "r"), sys.stdout, options.dump_payload)
+
+
+if __name__ == '__main__':
+    main()

Copied: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/gen_test_packets.py
 (from rev 5208, 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/gen_test_packets.py)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/gen_test_packets.py
                               (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/gen_test_packets.py
       2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+
+import random
+import struct
+from pprint import pprint
+from usb_packet import *
+
+MAX_PAYLOAD = 504
+TIME_NOW = 0xffffffff
+
+
+class sequence_generator(object):
+    def __init__(self):
+        self.i = 0
+    
+    def __call__(self):
+        t = self.i
+        self.i += 1
+        return t
+
+def gen_shuffled_lengths():
+    valid_lengths = range(0, MAX_PAYLOAD+1, 4)  # [0, 4, 8, ... 504]
+    random.shuffle(valid_lengths)
+    return valid_lengths
+
+
+class packet_sequence_generator(object):
+    def __init__(self, channel, lengths):
+        self.next = sequence_generator()
+        self.channel = channel
+        self.lengths = lengths
+
+    def __call__(self, output_file):
+        gen_packet(output_file, self.channel, self.next, self.lengths[0])
+        del self.lengths[0]
+
+
+def gen_packet(output_file, channel, content_generator, payload_len):
+    assert (payload_len % 4) == 0
+    payload = []
+    n_iq = payload_len // 4
+    for n in range(n_iq):
+        payload.append(content_generator())  # I
+        payload.append(content_generator())  # Q
+    for n in range(MAX_PAYLOAD // 4 - n_iq):
+        payload.append(0x0000)
+        payload.append(0xffff)
+
+    assert (len(payload) == MAX_PAYLOAD // 2)
+
+    #print "\npayload_len =", payload_len
+    #pprint(payload)
+
+    output_file.write(make_header(FL_START_OF_BURST|FL_END_OF_BURST,
+                                  channel, payload_len, TIME_NOW))
+    output_file.write(struct.pack('<252h', *payload))
+
+
+def gen_all_valid_packet_lengths_1_channel(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)
+    for i in range(npkts):
+        pkt_gen_0(output_file)
+    
+    assert pkt_gen_0.next() == 16002    # 2*sum(1, 2, ..., 126) == 126 * 127
+
+
+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 = (pkt_gen_0, pkt_gen_1)
+    
+    which_gen = (npkts * [0]) + (npkts * [1])
+    random.shuffle(which_gen)
+    
+    for i in which_gen:
+        pkt_gen[i](output_file)
+    
+    assert pkt_gen_0.next() == 16002    # 2*sum(1, 2, ..., 126) == 126 * 127
+    assert pkt_gen_1.next() == 16002    # 2*sum(1, 2, ..., 126) == 126 * 127
+
+if __name__ == '__main__':
+    
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"))

Copied: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usb_packet.py 
(from rev 5208, 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usb_packet.py)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usb_packet.py 
                            (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usb_packet.py 
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,115 @@
+#
+# 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.
+#
+
+import struct
+
+
+FL_OVERRUN        = 0x80000000
+FL_UNDERRUN       = 0x40000000
+FL_DROPPED        = 0x20000000
+FL_END_OF_BURST   = 0x10000000
+FL_START_OF_BURST = 0x08000000
+
+FL_ALL_FLAGS      = 0xf8000000
+
+FL_OVERRUN_SHIFT = 31
+FL_UNDERRUN_SHIFT = 30
+FL_DROPPED_SHIFT = 29
+FL_END_OF_BURST_SHIFT = 28
+FL_START_OF_BURST_SHIFT = 27
+  
+RSSI_MASK = 0x3f
+RSSI_SHIFT = 21
+
+CHAN_MASK = 0x1f
+CHAN_SHIFT = 16
+
+TAG_MASK = 0xf
+TAG_SHIFT = 9
+
+PAYLOAD_LEN_MASK = 0x1ff
+PAYLOAD_LEN_SHIFT = 0
+
+def make_header(flags, chan, payload_len, timestamp, rssi=0, tag=0):
+    word0 =  ((flags & FL_ALL_FLAGS)
+              | ((rssi & RSSI_MASK) << RSSI_SHIFT)
+              | ((chan & CHAN_MASK) << CHAN_SHIFT)
+              | ((tag & TAG_MASK) << TAG_SHIFT)
+              | ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT))
+    word1 = timestamp
+    return struct.pack('<2I', word0, word1)
+
+
+def _decode(pred, indicator):
+    if pred:
+        return indicator
+    else:
+        return '-'
+
+
+class usb_packet(object):
+    def __init__(self, raw_pkt):
+        assert isinstance(raw_pkt, str) and len(raw_pkt) == 512
+        self._raw_pkt = raw_pkt;
+        (self._word0, self._word1) = struct.unpack('<2I', self._raw_pkt[0:8])
+
+    def timestamp(self):
+        return self._word1
+
+    def rssi(self):
+        return (self._word0 >> RSSI_SHIFT) & RSSI_MASK
+
+    def chan(self):
+        return (self._word0 >> CHAN_SHIFT) & CHAN_MASK
+
+    def tag(self):
+        return (self._word0 >> TAG_SHIFT) & TAG_MASK
+
+    def payload_len(self):
+        return (self._word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK
+
+    def flags(self):
+        return self._word0 & FL_ALL_FLAGS
+
+    def overrun(self):
+        return (self._word0 >> FL_OVERRUN_SHIFT) & 0x1
+
+    def underrun(self):
+        return (self._word0 >> FL_UNDERRUN_SHIFT) & 0x1
+
+    def start_of_burst(self):
+        return (self._word0 >> FL_START_OF_BURST_SHIFT) & 0x1
+
+    def end_of_burst(self):
+        return (self._word0 >> FL_END_OF_BURST_SHIFT) & 0x1
+
+    def dropped(self):
+        return (self._word0 >> FL_DROPPED_SHIFT) & 0x1
+
+    def payload(self):
+        return self._raw_pkt[8:8+self.payload_len()]
+
+    def decoded_flags(self):
+        s = (_decode(self.overrun(), 'O')
+             + _decode(self.underrun(), 'U')
+             + _decode(self.dropped(), 'D')
+             + _decode(self.end_of_burst(), 'E')
+             + _decode(self.start_of_burst(), 'S'))
+        return s

Copied: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_inband_usb_packet.h
 (from rev 5208, 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_inband_usb_packet.h)
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_inband_usb_packet.h
                          (rev 0)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_inband_usb_packet.h
  2007-05-01 20:16:37 UTC (rev 5209)
@@ -0,0 +1,149 @@
+/* -*- 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 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.
+ */
+
+#ifndef INCLUDED_USRP_INBAND_USB_PACKET_H_
+#define INCLUDED_USRP_INBAND_USB_PACKET_H_
+
+#include <usrp_bytesex.h>
+#include <mb_mblock.h>
+
+static const int USB_PKT_SIZE = 512;   // bytes
+static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
+
+class usrp_inband_usb_packet {
+  //
+  // keep raw packet in USRP-endian order
+  //
+  uint32_t           d_word0;
+  uint32_t           d_timestamp;
+  unsigned char          d_payload[MAX_PAYLOAD];
+
+public:
+
+  enum flags {
+    FL_OVERRUN        = 0x80000000,
+    FL_UNDERRUN       = 0x40000000,
+    FL_DROPPED        = 0x20000000,
+    FL_END_OF_BURST   = 0x10000000,
+    FL_START_OF_BURST = 0x08000000,
+
+    FL_ALL_FLAGS      = 0xf8000000
+  };
+
+  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 RSSI_MASK = 0x3f;
+  static const int RSSI_SHIFT = 21;
+
+  static const int CHAN_MASK = 0x1f;
+  static const int CHAN_SHIFT = 16;
+
+  static const int TAG_MASK = 0xf;
+  static const int TAG_SHIFT = 9;
+
+  static const int PAYLOAD_LEN_MASK = 0x1ff;
+  static const int PAYLOAD_LEN_SHIFT = 0;
+
+public:
+  
+  void set_timestamp(uint32_t timestamp){
+    d_timestamp = host_to_usrp_u32(timestamp);
+  }
+
+  void set_end_of_burst() {
+    uint32_t word0 = usrp_to_host_u32(d_word0);
+    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)
+                       | ((tag & TAG_MASK) << TAG_SHIFT)
+                       | ((payload_len & PAYLOAD_LEN_MASK) << 
PAYLOAD_LEN_SHIFT));
+    d_word0 = host_to_usrp_u32(word0);
+  }
+  
+  uint32_t timestamp() const {
+    return usrp_to_host_u32(d_timestamp);
+  }
+
+  int rssi() const {
+    uint32_t word0 = usrp_to_host_u32(d_word0);
+    return (word0 >> RSSI_SHIFT) & RSSI_MASK;
+  }
+
+  int chan() const {
+    uint32_t word0 = usrp_to_host_u32(d_word0);
+    return (word0 >> CHAN_SHIFT) & CHAN_MASK;
+  }
+
+  int tag() const {
+    uint32_t word0 = usrp_to_host_u32(d_word0);
+    return (word0 >> TAG_SHIFT) & TAG_MASK;
+  }
+
+  int payload_len() const {
+    uint32_t word0 = usrp_to_host_u32(d_word0);
+    return (word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK;
+  }
+  
+  int flags() const {
+    return usrp_to_host_u32(d_word0) & FL_ALL_FLAGS;
+  }
+
+  int overrun() const {
+    return (usrp_to_host_u32(d_word0) & FL_OVERRUN) >> FL_OVERRUN_SHIFT;
+  }
+  
+
+  int underrun() const {
+    return (usrp_to_host_u32(d_word0) & FL_UNDERRUN) >> FL_UNDERRUN_SHIFT;
+  }
+
+
+  int start_of_burst() const {
+    return (usrp_to_host_u32(d_word0) & FL_START_OF_BURST) >> 
FL_START_OF_BURST_SHIFT;
+  }
+
+  int end_of_burst() const {
+    return (usrp_to_host_u32(d_word0) & FL_END_OF_BURST) >> 
FL_END_OF_BURST_SHIFT;
+  }
+
+  int dropped() const {
+    return (usrp_to_host_u32(d_word0) & FL_DROPPED) >> FL_DROPPED_SHIFT;
+  }
+
+  unsigned char *payload() { 
+    return d_payload; 
+  }
+
+  static int max_payload() {
+    return MAX_PAYLOAD;
+  }
+
+};
+
+#endif

Modified: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.cc
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.cc
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.cc
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -24,7 +24,10 @@
 #endif
 #include <usrp_server.h>
 #include <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <vector>
 
+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
 //
@@ -58,24 +61,29 @@
   // control & status port
   d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL); 
 
-  // rx ports
+  // ports
   //
   // (if/when we do replicated ports, these will be replaced by a
   //  single replicated port)
-  d_rx0 = define_port("rx0", "usrp-rx", true, mb_port::EXTERNAL);
-  d_rx1 = define_port("rx1", "usrp-rx", true, mb_port::EXTERNAL);
-  d_rx2 = define_port("rx2", "usrp-rx", true, mb_port::EXTERNAL);
-  d_rx3 = define_port("rx3", "usrp-rx", true, mb_port::EXTERNAL);
-  
-  // tx ports
-  //
-  // (if/when we do replicated ports, these will be replaced by a
-  //  single replicated port)
-  d_tx0 = define_port("tx0", "usrp-tx", true, mb_port::EXTERNAL);
-  d_tx1 = define_port("tx1", "usrp-tx", true, mb_port::EXTERNAL);
-  d_tx2 = define_port("tx2", "usrp-tx", true, mb_port::EXTERNAL);
-  d_tx3 = define_port("tx3", "usrp-tx", true, mb_port::EXTERNAL);
-  
+  for(int port=0; port < N_PORTS; port++) {
+    d_tx.push_back(define_port("rx"+port, "usrp-tx", true, mb_port::EXTERNAL));
+    d_rx.push_back(define_port("tx"+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;
+  d_nrx_chan = 2;
+
+  // Initialize capacity on each channel to 0 and to no owner
+  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;
+  }
 }
 
 usrp_server::~usrp_server()
@@ -133,14 +141,215 @@
   }
 
   if (pmt_eq(event, s_cmd_allocate_channel)){
-    // blah blah blah, do something here
+    handle_cmd_allocate_channel(port_id, data);
     return;
   }
-  if (pmt_eq(event, s_cmd_allocate_channel)){
-    // ...
+
+  if (pmt_eq(event, s_cmd_deallocate_channel)) {
+    handle_cmd_deallocate_channel(port_id, data);
     return;
   }
+    
+  if (pmt_eq(event, s_cmd_xmit_raw_frame)){
+    handle_cmd_xmit_raw_frame(data);
+    return;
+  }
 
  unhandled:
   std::cout << "unhandled msg: " << msg << std::endl;
 }
+
+// Return -1 if it is not an RX port, or an index
+long usrp_server::tx_port_index(pmt_t port_id) {
+
+  std::vector<mb_port_sptr>::iterator tx;
+
+  for(int i=0; i < d_tx.size(); i++) 
+    if(pmt_eq(tx[i]->port_symbol(), port_id))
+      return i;
+
+  return -1;
+}
+
+// Return -1 if it is not an RX port, or an index
+long usrp_server::rx_port_index(pmt_t port_id) {
+  
+  std::vector<mb_port_sptr>::iterator rx;
+
+  for(int i=0; i < d_rx.size(); i++) 
+    if(pmt_eq(rx[i]->port_symbol(), port_id))
+      return i;
+
+  return -1;
+}
+
+// Go through all TX and RX channels, sum up the assigned capacity
+// and return it
+long usrp_server::current_capacity_allocation() {
+  long capacity = 0;
+
+  for(int chan=0; chan < d_ntx_chan; chan++) 
+    capacity += d_chaninfo_tx[chan].assigned_capacity;
+
+  for(int chan=0; chan < d_nrx_chan; chan++)
+    capacity += d_chaninfo_rx[chan].assigned_capacity;
+
+  return capacity;
+}
+    
+void usrp_server::handle_cmd_allocate_channel(pmt_t port_id, 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;
+
+  // 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) {
+      reply_data = pmt_list3(invocation_handle, PMT_F, PMT_NIL);  // no 
capacity available
+      d_tx[port]->send(invocation_handle, reply_data);
+      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(invocation_handle, reply_data);
+        return;
+      }
+    }
+
+    reply_data = pmt_list3(invocation_handle, PMT_F, PMT_NIL);  // no free TX 
chan found
+    d_tx[port]->send(invocation_handle, reply_data);
+    return;
+  }
+  
+  // 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_F, PMT_NIL);  // no 
capacity available
+      d_rx[port]->send(invocation_handle, reply_data);
+      return;
+    }
+
+    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_rx[port]->send(invocation_handle, reply_data);
+        return;
+      }
+    }
+
+    reply_data = pmt_list3(invocation_handle, PMT_F, PMT_NIL);  // no free RX 
chan found
+    d_rx[port]->send(invocation_handle, reply_data);
+    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) {
+
+  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_F);   // not a legit 
channel number
+      d_tx[port]->send(invocation_handle, reply_data);
+      return;
+    }
+
+    if(d_chaninfo_tx[channel].owner != port_id) {
+      reply_data = pmt_list2(invocation_handle, PMT_F);   // not the owner of 
the port
+      d_tx[port]->send(invocation_handle, 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(invocation_handle, reply_data);
+    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_F);   // not a legit 
channel number
+      d_rx[port]->send(invocation_handle, reply_data);
+      return;
+    }
+
+    if(d_chaninfo_rx[channel].owner != port_id) {
+      reply_data = pmt_list2(invocation_handle, PMT_F);   // not the owner of 
the port
+      d_rx[port]->send(invocation_handle, 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(invocation_handle, reply_data);
+    return;
+  }
+
+}
+
+void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
+
+  size_t n_bytes, psize;
+  long max_payload_len = transport_pkt::max_payload();
+
+  pmt_t invocation_handle = pmt_nth(0, 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));
+
+  // 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 = std::ceil(n_bytes / (double)max_payload_len);
+  pmt_t v_packets = pmt_make_u8vector(sizeof(transport_pkt) * n_packets, 0);
+  transport_pkt *pkts = (transport_pkt *) 
pmt_u8vector_writeable_elements(v_packets, psize);
+
+  for(int n=0; n < n_packets; n++) {
+
+    long payload_len = std::min((int)(n_bytes-(n*max_payload_len)), 
(int)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);
+      pkts[n].set_timestamp(timestamp);
+    } else {
+      pkts[n].set_header(0, channel, 0, payload_len);
+      pkts[n].set_timestamp(0xffffffff);
+    }
+
+    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
+
+  // 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)
+}
+

Modified: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.h 
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/inband/usrp_server.h 
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -22,31 +22,51 @@
 #define INCLUDED_USRP_SERVER_H
 
 #include <mb_mblock.h>
+#include <vector>
 
 /*!
  * \brief Implements the lowest-level mblock interface to the USRP
  */
 class usrp_server : public mb_mblock
 {
+public:
+
   // our ports
+  enum port_types {
+    RX_PORT = 0,
+    TX_PORT = 1
+  };
+  static const int N_PORTS = 4;
+  std::vector<mb_port_sptr> d_tx, d_rx;
   mb_port_sptr d_cs;
-  mb_port_sptr d_rx0;
-  mb_port_sptr d_rx1;
-  mb_port_sptr d_rx2;
-  mb_port_sptr d_rx3;
-  mb_port_sptr d_tx0;
-  mb_port_sptr d_tx1;
-  mb_port_sptr d_tx2;
-  mb_port_sptr d_tx3;
 
-  // add more stuff here...
+  static const int D_USB_CAPACITY = 32 * 1024 * 1024;
+  static const int D_MAX_CHANNELS = 16;
+  long d_ntx_chan;
+  long d_nrx_chan;
 
+  struct channel_info {
+    long assigned_capacity;  // the capacity currently assignedby the channel
+    pmt_t owner;              // port ID of the owner of the channel
+  };
+
+  struct channel_info d_chaninfo_tx[D_MAX_CHANNELS];
+  struct channel_info d_chaninfo_rx[D_MAX_CHANNELS];
+
 public:
   usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t 
user_arg);
   ~usrp_server();
 
   void initial_transition();
   void handle_message(mb_message_sptr msg);
+
+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);
+  long rx_port_index(pmt_t port_id);
+  long tx_port_index(pmt_t port_id);
+  long current_capacity_allocation();
 };
 
 #endif /* INCLUDED_USRP_SERVER_H */

Modified: 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/legacy/usrp_bytesex.h
===================================================================
--- 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/legacy/usrp_bytesex.h
    2007-05-01 16:36:51 UTC (rev 5208)
+++ 
gnuradio/branches/developers/thottelt/inband/usrp/host/lib/legacy/usrp_bytesex.h
    2007-05-01 20:16:37 UTC (rev 5209)
@@ -38,11 +38,30 @@
 {
   return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
 }
+
+static inline unsigned int
+bswap32 (unsigned int x)
+{
+  return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) \
+        | (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24));
+}
 #endif
 
 
 #ifdef WORDS_BIGENDIAN
 
+static inline unsigned int
+host_to_usrp_u32 (unsigned int x)
+{
+  return bswap_32(x);
+}
+
+static inline unsigned int
+usrp_to_host_u32 (unsigned int x)
+{
+  return bswap_32(x);
+}
+
 static inline short int
 host_to_usrp_short (short int x)
 {
@@ -57,6 +76,18 @@
 
 #else
 
+static inline unsigned int
+host_to_usrp_u32 (unsigned int x)
+{
+  return x;
+}
+
+static inline unsigned int
+usrp_to_host_u32 (unsigned int x)
+{
+  return x;
+}
+
 static inline short int
 host_to_usrp_short (short int x)
 {





reply via email to

[Prev in Thread] Current Thread [Next in Thread]