Merged features/inband -r4812:5218 into trunk. This group of changes
authoreb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 2 May 2007 04:08:47 +0000 (04:08 +0000)
committereb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 2 May 2007 04:08:47 +0000 (04:08 +0000)
includes:

 * working stand-alone mblock code
 * work-in-progress on usrp inband signaling

usrp now depends on mblock, and guile is a dependency.

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

203 files changed:
Makefile.common
config/grc_mblock.m4
config/grc_pmt.m4
config/grc_usrp.m4
configure.ac
gnuradio-core/src/python/bin/Makefile.am
mblock/README
mblock/src/Makefile.am
mblock/src/lib/Makefile.am
mblock/src/lib/benchmark_send.cc [new file with mode: 0644]
mblock/src/lib/getres.cc [new file with mode: 0644]
mblock/src/lib/mb_class_registry.cc [new file with mode: 0644]
mblock/src/lib/mb_class_registry.h [new file with mode: 0644]
mblock/src/lib/mb_exception.cc
mblock/src/lib/mb_exception.h
mblock/src/lib/mb_gettid.cc [new file with mode: 0644]
mblock/src/lib/mb_gettid.h [new file with mode: 0644]
mblock/src/lib/mb_mblock.cc
mblock/src/lib/mb_mblock.h
mblock/src/lib/mb_mblock_impl.cc
mblock/src/lib/mb_mblock_impl.h
mblock/src/lib/mb_message.cc
mblock/src/lib/mb_message.h
mblock/src/lib/mb_msg_accepter_msgq.cc [new file with mode: 0644]
mblock/src/lib/mb_msg_accepter_msgq.h [new file with mode: 0644]
mblock/src/lib/mb_msg_queue.cc
mblock/src/lib/mb_msg_queue.h
mblock/src/lib/mb_port.cc
mblock/src/lib/mb_port.h
mblock/src/lib/mb_port_simple.cc
mblock/src/lib/mb_port_simple.h
mblock/src/lib/mb_protocol_class.cc
mblock/src/lib/mb_protocol_class.h
mblock/src/lib/mb_runtime.cc
mblock/src/lib/mb_runtime.h
mblock/src/lib/mb_runtime_base.cc [new file with mode: 0644]
mblock/src/lib/mb_runtime_base.h [new file with mode: 0644]
mblock/src/lib/mb_runtime_nop.cc
mblock/src/lib/mb_runtime_nop.h
mblock/src/lib/mb_runtime_placeholder.cc [deleted file]
mblock/src/lib/mb_runtime_placeholder.h [deleted file]
mblock/src/lib/mb_runtime_thread_per_block.cc [new file with mode: 0644]
mblock/src/lib/mb_runtime_thread_per_block.h [new file with mode: 0644]
mblock/src/lib/mb_runtime_thread_per_mblock.cc [deleted file]
mblock/src/lib/mb_runtime_thread_per_mblock.h [deleted file]
mblock/src/lib/mb_time.cc [new file with mode: 0644]
mblock/src/lib/mb_time.h [new file with mode: 0644]
mblock/src/lib/mb_timer_queue.cc [new file with mode: 0644]
mblock/src/lib/mb_timer_queue.h [new file with mode: 0644]
mblock/src/lib/mb_worker.cc [new file with mode: 0644]
mblock/src/lib/mb_worker.h [new file with mode: 0644]
mblock/src/lib/mbi_runtime_lock.h
mblock/src/lib/qa_bitset.cc [new file with mode: 0644]
mblock/src/lib/qa_bitset.mbh [new file with mode: 0644]
mblock/src/lib/qa_disconnect.cc [new file with mode: 0644]
mblock/src/lib/qa_mblock.cc
mblock/src/lib/qa_mblock_prims.cc
mblock/src/lib/qa_mblock_send.cc
mblock/src/lib/qa_mblock_sys.cc [new file with mode: 0644]
mblock/src/lib/qa_mblock_sys.h [new file with mode: 0644]
mblock/src/lib/qa_timeouts.cc [new file with mode: 0644]
mblock/src/lib/qa_timeouts.h [new file with mode: 0644]
mblock/src/scheme/Makefile.am [new file with mode: 0644]
mblock/src/scheme/gnuradio/Makefile.am [new file with mode: 0644]
mblock/src/scheme/gnuradio/compile-mbh.scm [new file with mode: 0755]
omnithread/omnithread.h
omnithread/posix.cc
pmt/src/Makefile.am
pmt/src/lib/Makefile.am
pmt/src/lib/pmt.cc
pmt/src/lib/pmt.h
pmt/src/lib/pmt_int.h
pmt/src/lib/pmt_pool.cc [new file with mode: 0644]
pmt/src/lib/pmt_pool.h [new file with mode: 0644]
pmt/src/lib/pmt_serialize.cc [new file with mode: 0644]
pmt/src/lib/qa_pmt_prims.cc
pmt/src/lib/qa_pmt_prims.h
pmt/src/scheme/Makefile.am [new file with mode: 0644]
pmt/src/scheme/gnuradio/Makefile.am [new file with mode: 0644]
pmt/src/scheme/gnuradio/gen-serial-tags.scm [new file with mode: 0755]
pmt/src/scheme/gnuradio/macros-etc.scm [new file with mode: 0644]
pmt/src/scheme/gnuradio/pmt-serial-tags.scm [new file with mode: 0644]
pmt/src/scheme/gnuradio/pmt-serialize.scm [new file with mode: 0644]
usrp/doc/inband-signaling-usb-host
usrp/fpga/inband_lib/chan_fifo_reader.v [new file with mode: 0755]
usrp/fpga/inband_lib/data_packet_fifo.v [new file with mode: 0755]
usrp/fpga/inband_lib/tx_buffer_inband.v [new file with mode: 0755]
usrp/fpga/inband_lib/usb_fifo_reader.v [new file with mode: 0755]
usrp/fpga/inband_lib/usb_packet_fifo.v [new file with mode: 0755]
usrp/fpga/inband_lib/usb_packet_fifo2.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_512.bsf [new file with mode: 0755]
usrp/fpga/megacells/fifo_512.cmp [new file with mode: 0755]
usrp/fpga/megacells/fifo_512.inc [new file with mode: 0755]
usrp/fpga/megacells/fifo_512.v [new file with mode: 0755]
usrp/fpga/megacells/fifo_512_bb.v [new file with mode: 0755]
usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
usrp/host/apps/Makefile.am
usrp/host/lib/Makefile.am
usrp/host/lib/README_OSX [deleted file]
usrp/host/lib/ad9862.h [deleted file]
usrp/host/lib/check_data.py [deleted file]
usrp/host/lib/circular_buffer.h [deleted file]
usrp/host/lib/circular_linked_list.h [deleted file]
usrp/host/lib/darwin_libusb.h [deleted file]
usrp/host/lib/dump_data.py [deleted file]
usrp/host/lib/dxc-io-assignments.gnumeric [deleted file]
usrp/host/lib/fusb.cc [deleted file]
usrp/host/lib/fusb.h [deleted file]
usrp/host/lib/fusb_darwin.cc [deleted file]
usrp/host/lib/fusb_darwin.h [deleted file]
usrp/host/lib/fusb_generic.cc [deleted file]
usrp/host/lib/fusb_generic.h [deleted file]
usrp/host/lib/fusb_linux.cc [deleted file]
usrp/host/lib/fusb_linux.h [deleted file]
usrp/host/lib/fusb_ra_wb.cc [deleted file]
usrp/host/lib/fusb_ra_wb.h [deleted file]
usrp/host/lib/fusb_sysconfig_darwin.cc [deleted file]
usrp/host/lib/fusb_sysconfig_generic.cc [deleted file]
usrp/host/lib/fusb_sysconfig_linux.cc [deleted file]
usrp/host/lib/fusb_sysconfig_ra_wb.cc [deleted file]
usrp/host/lib/fusb_sysconfig_win32.cc [deleted file]
usrp/host/lib/fusb_win32.cc [deleted file]
usrp/host/lib/fusb_win32.h [deleted file]
usrp/host/lib/gen_usrp_dbid.py [deleted file]
usrp/host/lib/inband/Makefile.am [new file with mode: 0644]
usrp/host/lib/inband/dump_packets.py [new file with mode: 0755]
usrp/host/lib/inband/gen_test_packets.py [new file with mode: 0755]
usrp/host/lib/inband/qa_inband.cc [new file with mode: 0644]
usrp/host/lib/inband/qa_inband.h [new file with mode: 0644]
usrp/host/lib/inband/qa_inband_packet_prims.cc [new file with mode: 0644]
usrp/host/lib/inband/qa_inband_packet_prims.h [new file with mode: 0644]
usrp/host/lib/inband/qa_inband_usrp_server.cc [new file with mode: 0644]
usrp/host/lib/inband/qa_inband_usrp_server.h [new file with mode: 0644]
usrp/host/lib/inband/test_inband.cc [new file with mode: 0644]
usrp/host/lib/inband/usb_packet.py [new file with mode: 0644]
usrp/host/lib/inband/usrp_inband_usb_packet.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_server.cc [new file with mode: 0644]
usrp/host/lib/inband/usrp_server.h [new file with mode: 0644]
usrp/host/lib/inband/usrp_server.mbh [new file with mode: 0644]
usrp/host/lib/legacy/Makefile.am [new file with mode: 0644]
usrp/host/lib/legacy/README_OSX [new file with mode: 0644]
usrp/host/lib/legacy/ad9862.h [new file with mode: 0644]
usrp/host/lib/legacy/check_data.py [new file with mode: 0755]
usrp/host/lib/legacy/circular_buffer.h [new file with mode: 0644]
usrp/host/lib/legacy/circular_linked_list.h [new file with mode: 0644]
usrp/host/lib/legacy/darwin_libusb.h [new file with mode: 0644]
usrp/host/lib/legacy/dump_data.py [new file with mode: 0755]
usrp/host/lib/legacy/fusb.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb.h [new file with mode: 0644]
usrp/host/lib/legacy/fusb_darwin.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_darwin.h [new file with mode: 0644]
usrp/host/lib/legacy/fusb_generic.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_generic.h [new file with mode: 0644]
usrp/host/lib/legacy/fusb_linux.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_linux.h [new file with mode: 0644]
usrp/host/lib/legacy/fusb_ra_wb.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_ra_wb.h [new file with mode: 0644]
usrp/host/lib/legacy/fusb_sysconfig_darwin.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_sysconfig_generic.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_sysconfig_linux.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_sysconfig_ra_wb.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_sysconfig_win32.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_win32.cc [new file with mode: 0644]
usrp/host/lib/legacy/fusb_win32.h [new file with mode: 0644]
usrp/host/lib/legacy/gen_usrp_dbid.py [new file with mode: 0755]
usrp/host/lib/legacy/md5.c [new file with mode: 0644]
usrp/host/lib/legacy/md5.h [new file with mode: 0644]
usrp/host/lib/legacy/mld_threads.h [new file with mode: 0644]
usrp/host/lib/legacy/rate_to_regval.h [new file with mode: 0644]
usrp/host/lib/legacy/std_paths.h.in [new file with mode: 0644]
usrp/host/lib/legacy/usrp_basic.cc [new file with mode: 0644]
usrp/host/lib/legacy/usrp_basic.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_bytesex.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_config.cc [new file with mode: 0644]
usrp/host/lib/legacy/usrp_config.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_dbid.dat [new file with mode: 0644]
usrp/host/lib/legacy/usrp_local_sighandler.cc [new file with mode: 0644]
usrp/host/lib/legacy/usrp_local_sighandler.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_prims.cc [new file with mode: 0644]
usrp/host/lib/legacy/usrp_prims.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_slots.h [new file with mode: 0644]
usrp/host/lib/legacy/usrp_standard.cc [new file with mode: 0644]
usrp/host/lib/legacy/usrp_standard.h [new file with mode: 0644]
usrp/host/lib/md5.c [deleted file]
usrp/host/lib/md5.h [deleted file]
usrp/host/lib/mld_threads.h [deleted file]
usrp/host/lib/rate_to_regval.h [deleted file]
usrp/host/lib/std_paths.h.in [deleted file]
usrp/host/lib/usrp_basic.cc [deleted file]
usrp/host/lib/usrp_basic.h [deleted file]
usrp/host/lib/usrp_bytesex.h [deleted file]
usrp/host/lib/usrp_config.cc [deleted file]
usrp/host/lib/usrp_config.h [deleted file]
usrp/host/lib/usrp_dbid.dat [deleted file]
usrp/host/lib/usrp_local_sighandler.cc [deleted file]
usrp/host/lib/usrp_local_sighandler.h [deleted file]
usrp/host/lib/usrp_prims.cc [deleted file]
usrp/host/lib/usrp_prims.h [deleted file]
usrp/host/lib/usrp_slots.h [deleted file]
usrp/host/lib/usrp_standard.cc [deleted file]
usrp/host/lib/usrp_standard.h [deleted file]
usrp/host/swig/Makefile.am

index 35ff203954eacf26c3dc4bda1feaa0ab1688cfeb..3906542b5ad5495eae1e27200c0f0c76c0fce66f 100644 (file)
@@ -73,14 +73,19 @@ GNURADIO_CORE_LA = $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core.la
 GNURADIO_I = $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i
 
 # How to link in the USRP library from inside the tree
-USRP_INCLUDES = -I$(top_srcdir)/usrp/host/lib \
+USRP_INCLUDES = -I$(top_srcdir)/usrp/host/lib/legacy \
+               -I$(top_srcdir)/usrp/host/lib/inband \
                -I$(top_srcdir)/usrp/firmware/include
-USRP_LA = $(top_builddir)/usrp/host/lib/libusrp.la
+USRP_LA = $(top_builddir)/usrp/host/lib/legacy/libusrp.la
 
 # How to link the PMT library from inside the tree
 PMT_INCLUDES = -I$(top_srcdir)/pmt/src/lib
 PMT_LA = $(top_builddir)/pmt/src/lib/libpmt.la
 
+# How to link the mblock library from inside the tree
+MBLOCK_INCLUDES = -I$(top_srcdir)/mblock/src/lib
+MBLOCK_LA = $(top_builddir)/mblock/src/lib/libmblock.la
+
 # This used to be set in configure.ac but is now defined here for all 
 # Makefiles when this fragment is included.
 STD_DEFINES_AND_INCLUDES=$(DEFINES) $(OMNITHREAD_INCLUDES) $(GNURADIO_INCLUDES) $(BOOST_CFLAGS)
@@ -88,3 +93,6 @@ STD_DEFINES_AND_INCLUDES=$(DEFINES) $(OMNITHREAD_INCLUDES) $(GNURADIO_INCLUDES)
 # Fix for BSD make not defining $(RM).  We define it now in configure.ac
 # using AM_PATH_PROG, but now here have to add a -f to be like GNU make
 RM=$(RM_PROG) -f
+
+RUN_GUILE = GUILE_LOAD_PATH="@abs_top_srcdir@/pmt/src/scheme:@abs_top_srcdir@/mblock/src/scheme" @GUILE@ -e main -s
+COMPILE_MBH = $(RUN_GUILE) $(top_srcdir)/mblock/src/scheme/gnuradio/compile-mbh.scm
index 6e4bc4afe1cfbfc89c66f09ce09ad060e42011cf..d5020a65b49618a766a6abf08febe369e31e65c1 100644 (file)
@@ -24,7 +24,9 @@ AC_DEFUN([GRC_MBLOCK],[
        mblock/Makefile \
        mblock/doc/Makefile \
        mblock/src/Makefile \
-       mblock/src/lib/Makefile
+       mblock/src/lib/Makefile \
+       mblock/src/scheme/Makefile \
+       mblock/src/scheme/gnuradio/Makefile \
     ])
 
     passed=yes
@@ -48,6 +50,12 @@ AC_DEFUN([GRC_MBLOCK],[
        fi
     done
 
+    AC_PATH_PROG(GUILE,guile)
+    if test "$GUILE" = "" ; then
+      AC_MSG_RESULT([Component mblock requires guile, which was not found.])
+      passed=no
+    fi
+
     GRC_BUILD_CONDITIONAL([mblock],[
         dnl run_tests is created from run_tests.in.  Make it executable.
        dnl AC_CONFIG_COMMANDS([run_tests_mblock], [chmod +x mblock/src/python/run_tests])
index 57d912bfd7ffd86a5c33bf0e7641e0feb6889a99..5e2487190f0589655028bb82f49908de2a0c8b63 100644 (file)
@@ -24,10 +24,18 @@ AC_DEFUN([GRC_PMT],[
        pmt/Makefile \
        pmt/doc/Makefile \
        pmt/src/Makefile \
-       pmt/src/lib/Makefile
+       pmt/src/lib/Makefile \
+       pmt/src/scheme/Makefile \
+       pmt/src/scheme/gnuradio/Makefile \
     ])
 
     passed=yes
+    AC_PATH_PROG(GUILE,guile)
+    if test "$GUILE" = "" ; then
+      AC_MSG_RESULT([Component pmt requires guile, which was not found.])
+      passed=no
+    fi
+
     GRC_BUILD_CONDITIONAL([pmt],[
         dnl run_tests is created from run_tests.in.  Make it executable.
        dnl AC_CONFIG_COMMANDS([run_tests_pmt], [chmod +x pmt/src/python/run_tests])
index a7c0cf138ca2e025b7130c02ef4b182d42e2dce5..e0fe60f47018e50aa228aac23bcd8e01ba8e3ad6 100644 (file)
@@ -30,7 +30,9 @@ AC_DEFUN([GRC_USRP],[
         usrp/host/Makefile \
         usrp/host/misc/Makefile \
         usrp/host/lib/Makefile \
-        usrp/host/lib/std_paths.h \
+        usrp/host/lib/inband/Makefile \
+        usrp/host/lib/legacy/Makefile \
+        usrp/host/lib/legacy/std_paths.h \
         usrp/host/swig/Makefile \
         usrp/host/apps/Makefile \
         usrp/firmware/Makefile \
@@ -54,6 +56,16 @@ AC_DEFUN([GRC_USRP],[
     AC_CHECK_FUNCS([sigaction snprintf])
 
     passed=yes
+    # Don't do usrp if mblock skipped
+    # There *has* to be a better way to check if a value is in a string
+    for dir in $skipped_dirs
+    do
+       if test "$dir" = "mblock"; then
+           AC_MSG_RESULT([Component usrp requires mblock, which is not being built.])
+           passed=no
+       fi
+    done
+
     USRP_LIBUSB([],[passed=no;AC_MSG_RESULT([Unable to configure USB dependency.])])
     USRP_SET_FUSB_TECHNIQUE([],[passed=no;AC_MSG_RESULT([Unable to set fast USB technique.])])
     USRP_SDCC([2.4.0],[],[passed=no;AC_MSG_RESULT([Unable to find firmware compiler.])])
index 418c78c013fec4599d9b561161fe45498bf89e5d..22aaa2a01aaacfc191991b1879b1245649600c87 100644 (file)
@@ -114,7 +114,7 @@ AC_HEADER_STDC
 AC_HEADER_SYS_WAIT
 AC_CHECK_HEADERS(fcntl.h limits.h strings.h time.h sys/ioctl.h sys/time.h unistd.h)
 AC_CHECK_HEADERS(linux/ppdev.h sys/mman.h sys/select.h sys/types.h)
-AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h signal.h)
+AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h signal.h sys/syscall.h)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
@@ -131,6 +131,7 @@ AC_FUNC_VPRINTF
 AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize sysconf])
 AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler])
 AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask])
+AC_CHECK_FUNCS([sched_setaffinity])
 
 AC_CHECK_LIB(m, sincos, [AC_DEFINE([HAVE_SINCOS],[1],[Define to 1 if your system has `sincos'.])])
 AC_CHECK_LIB(m, sincosf,[AC_DEFINE([HAVE_SINCOSF],[1],[Define to 1 if your system has `sincosf'.])])
@@ -198,6 +199,8 @@ AC_ARG_ENABLE(
 build_dirs="config"
 GRC_OMNITHREAD                 dnl must come before gnuradio-core and mblock
 GRC_GNURADIO_CORE
+GRC_PMT
+GRC_MBLOCK                     dnl this must come after GRC_PMT
 GRC_USRP
 GRC_GR_USRP                    dnl this must come after GRC_USRP
 GRC_GR_AUDIO_ALSA
@@ -216,8 +219,6 @@ GRC_GR_TRELLIS
 GRC_GR_VIDEO_SDL
 GRC_GR_QTGUI
 GRC_GR_WXGUI
-GRC_PMT
-GRC_MBLOCK                     dnl this must come after GRC_PMT
 GRC_GR_SOUNDER                 dnl this must come after GRC_USRP
 GRC_GNURADIO_EXAMPLES          dnl must come last
 
index 296132ec72fd9f6de66671cca49f1770f87c22e0..d4df51273fd06d9232aeee11cba18873c935cf33 100644 (file)
@@ -24,7 +24,7 @@ include $(top_srcdir)/Makefile.common
 
 EXTRA_DIST = microtune.py
 
-bin_SCRIPTS =                  \
+noinst_SCRIPTS =               \
        microtune.py            
 
 CLEANFILES = *.pyc
index ca91edfaaf6524fdcbe138bcb13f2e92c6471fd2..130073afe56ec603028d66ca9a4dbc4271dbbd75 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2006 Free Software Foundation, Inc.
+# Copyright 2006,2007 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -20,3 +20,5 @@
 # 
 
 The "Message block" implementation, a work in progress...
+
+http://gnuradio.org/trac/wiki/MessageBlocks
index bcbab24558b43d41056ed04b6d65850bb7c21f80..c6c2fcc751dad2b45bbb38141e3329bfcee62f75 100644 (file)
@@ -19,4 +19,4 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-SUBDIRS = lib
+SUBDIRS = lib scheme
index 6273e16d2d2b96d29f59b0b66b5a160d46118fc0..604f97246a4de2b6f8beefdfcce5fa03ba09c99d 100644 (file)
@@ -28,28 +28,41 @@ TESTS = test_mblock
 lib_LTLIBRARIES = libmblock.la libmblock-qa.la
 
 EXTRA_DIST =                           \
-       README.locking                  
+       README.locking                  \
+       qa_bitset.mbh                   
 
 
+BUILT_SOURCES =                                \
+       qa_bitset_mbh.cc                
+
+qa_bitset_mbh.cc : qa_bitset.mbh
+       $(COMPILE_MBH) qa_bitset.mbh qa_bitset_mbh.cc
+
 # These are the source files that go into the mblock shared library
 libmblock_la_SOURCES =                 \
+       mb_class_registry.cc            \
        mb_connection.cc                \
        mb_endpoint.cc                  \
        mb_exception.cc                 \
+       mb_gettid.cc                    \
        mb_mblock.cc                    \
        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_placeholder.cc       \
-       mb_runtime_thread_per_mblock.cc \
-       mb_util.cc                      
+       mb_runtime_thread_per_block.cc  \
+       mb_time.cc                      \
+       mb_timer_queue.cc               \
+       mb_util.cc                      \
+       mb_worker.cc                    
 
 
 # magic flags
@@ -62,19 +75,20 @@ libmblock_la_LIBADD =                       \
        -lstdc++                        
 
 include_HEADERS =                      \
+       mb_class_registry.h             \
        mb_common.h                     \
        mb_exception.h                  \
+       mb_gettid.h                     \
        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_runtime_placeholder.h        \
-       mb_runtime_thread_per_mblock.h  \
+       mb_time.h                       \
        mb_util.h                       
 
 
@@ -83,18 +97,30 @@ noinst_HEADERS =                    \
        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_send.h                \
+       qa_mblock_sys.h                 \
+       qa_timeouts.h                   
 
 
 # Build the qa code into its own library
 
 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_send.cc               \
+       qa_mblock_sys.cc                \
+       qa_timeouts.cc                  
 
 
 # magic flags
@@ -107,9 +133,14 @@ libmblock_qa_la_LIBADD =           \
        -lstdc++                        
 
 
-noinst_PROGRAMS        = test_mblock
+noinst_PROGRAMS        =                       \
+       test_mblock                     \
+       benchmark_send                  
 
 test_mblock_SOURCES = test_mblock.cc
 test_mblock_LDADD   = libmblock-qa.la
 
+benchmark_send_SOURCES = benchmark_send.cc
+benchmark_send_LDADD   = libmblock-qa.la
+
 CLEANFILES = $(BUILT_SOURCES) *.pyc
diff --git a/mblock/src/lib/benchmark_send.cc b/mblock/src/lib/benchmark_send.cc
new file mode 100644 (file)
index 0000000..c9ebe57
--- /dev/null
@@ -0,0 +1,45 @@
+/* -*- 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.
+ */
+
+#include <mb_runtime.h>
+#include <iostream>
+
+int
+main(int argc, char **argv)
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  long nmsgs =      1000000;
+  long batch_size =     100;
+
+  pmt_t arg = pmt_list2(pmt_from_long(nmsgs),  // # of messages to send through pipe
+                       pmt_from_long(batch_size));
+
+  rt->run("top", "qa_bitset_top", arg, &result);
+
+  if (!pmt_equal(PMT_T, result)){
+    std::cerr << "benchmark_send: incorrect result";
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/mblock/src/lib/getres.cc b/mblock/src/lib/getres.cc
new file mode 100644 (file)
index 0000000..c05ba79
--- /dev/null
@@ -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;
+}  
diff --git a/mblock/src/lib/mb_class_registry.cc b/mblock/src/lib/mb_class_registry.cc
new file mode 100644 (file)
index 0000000..9eee936
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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_class_registry.h>
+#include <map>
+
+static std::map<std::string, mb_mblock_maker_t>        s_registry;
+
+bool
+mb_class_registry::register_maker(const std::string &name, mb_mblock_maker_t maker)
+{
+  s_registry[name] = maker;
+  return true;
+}
+
+bool
+mb_class_registry::lookup_maker(const std::string &name, mb_mblock_maker_t *maker)
+{
+  if (s_registry.count(name) == 0){  // not registered
+    *maker = (mb_mblock_maker_t) 0;
+    return false;
+  }
+
+  *maker = s_registry[name];
+  return true;
+}
diff --git a/mblock/src/lib/mb_class_registry.h b/mblock/src/lib/mb_class_registry.h
new file mode 100644 (file)
index 0000000..b6e63d3
--- /dev/null
@@ -0,0 +1,51 @@
+/* -*- 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_CLASS_REGISTRY_H
+#define INCLUDED_MB_CLASS_REGISTRY_H
+
+#include <mb_common.h>
+
+//! conceptually, pointer to constructor
+typedef mb_mblock_sptr (*mb_mblock_maker_t)(mb_runtime *runtime,
+                                           const std::string &instance_name,
+                                           pmt_t user_arg);
+
+/*
+ * \brief Maintain mapping between mblock class_name and factory (maker)
+ */
+class mb_class_registry : public boost::noncopyable {
+public:
+  static bool register_maker(const std::string &name, mb_mblock_maker_t maker);
+  static bool lookup_maker(const std::string &name, mb_mblock_maker_t *maker);
+};
+
+template<class mblock>
+mb_mblock_sptr mb_mblock_maker(mb_runtime *runtime,
+                              const std::string &instance_name,
+                              pmt_t user_arg)
+{
+  return mb_mblock_sptr(new mblock(runtime, instance_name, user_arg));
+}
+
+#define REGISTER_MBLOCK_CLASS(name) \
+  bool __RBC__ ## name = mb_class_registry::register_maker(#name, &mb_mblock_maker<name>)
+
+#endif /* INCLUDED_MB_CLASS_REGISTRY_H */
index 4d4ca70b1256c32636d05c28634c51d21a766060..23dfbd9fe68c67b667e7dbd2818d8a10a0532056 100644 (file)
@@ -38,6 +38,11 @@ mbe_not_implemented::mbe_not_implemented(mb_mblock *mb, const std::string &msg)
 {
 }
 
+mbe_no_such_class::mbe_no_such_class(mb_mblock *mb, const std::string &class_name)
+  : mbe_base(mb, "No such class: " + class_name)
+{
+}
+
 mbe_no_such_component::mbe_no_such_component(mb_mblock *mb, const std::string &component_name)
   : mbe_base(mb, "No such component: " + component_name)
 {
@@ -85,3 +90,17 @@ mbe_invalid_port_type::mbe_invalid_port_type(mb_mblock *mb,
   : mbe_base(mb, "Invalid port type for connection: " + mb_util::join_names(comp_name, port_name))
 {
 }
+
+mbe_mblock_failed::mbe_mblock_failed(mb_mblock *mb,
+                                    const std::string &msg)
+  : mbe_base(mb, "Message block failed: " + msg)
+{
+}
+
+mbe_terminate::mbe_terminate()
+{
+}
+
+mbe_exit::mbe_exit()
+{
+}
index 40abd1c962402256f89fb2b5500b62ebf23d760a..183f7089c31bf0c598bae84044661d94cf41ca8a 100644 (file)
@@ -38,6 +38,11 @@ public:
   mbe_not_implemented(mb_mblock *mb, const std::string &msg);
 };
 
+class mbe_no_such_class : public mbe_base
+{
+public:
+  mbe_no_such_class(mb_mblock *, const std::string &class_name);
+};
 
 class mbe_no_such_component : public mbe_base
 {
@@ -57,6 +62,7 @@ public:
   mbe_no_such_port(mb_mblock *, const std::string &port_name);
 };
 
+
 class mbe_duplicate_port : public mbe_base
 {
 public:
@@ -87,6 +93,26 @@ public:
                        const std::string &port_name);
 };
 
+class mbe_mblock_failed : public mbe_base
+{
+public:
+  mbe_mblock_failed(mb_mblock *, const std::string &msg);
+};
+
 
 
+// not derived from mbe_base to simplify try/catch
+class mbe_terminate
+{
+public:
+  mbe_terminate();
+};
+
+// not derived from mbe_base to simplify try/catch
+class mbe_exit
+{
+public:
+  mbe_exit();
+};
+
 #endif /* INCLUDED_MB_EXCEPTION_H */
diff --git a/mblock/src/lib/mb_gettid.cc b/mblock/src/lib/mb_gettid.cc
new file mode 100644 (file)
index 0000000..4f6b3a5
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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_gettid.h>
+
+#define NEED_STUB
+
+#if defined(HAVE_SYS_SYSCALL_H) && defined(HAVE_UNISTD_H) 
+
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#if defined(SYS_gettid)
+#undef NEED_STUB
+
+int mb_gettid()
+{
+  return syscall(SYS_gettid);
+}
+
+#endif
+#endif
+
+#if defined(NEED_STUB)
+
+int
+mb_gettid()
+{
+  return 0;
+}
+
+#endif
diff --git a/mblock/src/lib/mb_gettid.h b/mblock/src/lib/mb_gettid.h
new file mode 100644 (file)
index 0000000..d06276f
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- 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.
+ */
+
+/*!
+ * \brief Return Linux taskid, or 0 if not available
+ */
+int mb_gettid();
+
index 9b8658f2187e8e64b814205d219c13da920491cd..afff1a928dbc032aa775e905cf95c3b07857cc95 100644 (file)
 
 #include <mb_mblock.h>
 #include <mb_mblock_impl.h>
+#include <mb_runtime.h>
+#include <mb_exception.h>
+#include <iostream>
 
 
+static pmt_t s_sys_port = pmt_intern("%sys-port");
+static pmt_t s_halt = pmt_intern("%halt");
+
 mb_visitor::~mb_visitor()
 {
   // nop base case for virtual destructor.
 }
 
 
-mb_mblock::mb_mblock()
-  : d_impl(mb_mblock_impl_sptr(new mb_mblock_impl(this)))
+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(dynamic_cast<mb_runtime_base*>(runtime),
+                                 this, instance_name)))
 {
 }
 
 mb_mblock::~mb_mblock()
 {
-  disconnect_all();
-
-  // FIXME more?
 }
 
 
 void
-mb_mblock::init_fsm()
+mb_mblock::initial_transition()
 {
   // default implementation does nothing
 }
@@ -58,6 +65,36 @@ mb_mblock::handle_message(mb_message_sptr msg)
   // default implementation does nothing
 }
 
+
+void
+mb_mblock::main_loop()
+{
+  while (1){
+    mb_message_sptr msg;
+    try {
+      while (1){
+       msg = impl()->msgq().get_highest_pri_msg();
+
+       // check for %halt from %sys-port
+       if (pmt_eq(msg->port_id(), s_sys_port) && pmt_eq(msg->signal(), s_halt))
+         exit();
+
+       handle_message(msg);
+      }
+    }
+    catch (pmt_exception e){
+      std::cerr << "\nmb_mblock::main_loop: ignored pmt_exception: "
+               << e.what()
+               << "\nin mblock instance \"" << instance_name()
+               << "\" while handling message:"
+               << "\n    port_id = " << msg->port_id()
+               << "\n     signal = " << msg->signal()
+               << "\n       data = " << msg->data()
+               << "\n  metatdata = " << msg->metadata() << std::endl;
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////
 //           Forward other methods to implementation class            //
 ////////////////////////////////////////////////////////////////////////
@@ -74,9 +111,11 @@ mb_mblock::define_port(const std::string &port_name_string,
 
 void
 mb_mblock::define_component(const std::string &component_name,
-                           mb_mblock_sptr component)
+                           const std::string &class_name,
+                           pmt_t user_arg)
+               
 {
-  d_impl->define_component(component_name, component);
+  d_impl->define_component(component_name, class_name, user_arg);
 }
 
 void
@@ -97,7 +136,7 @@ mb_mblock::disconnect(const std::string &comp_name1, const std::string &port_nam
 }
 
 void
-mb_mblock::disconnect_component(const std::string component_name)
+mb_mblock::disconnect_component(const std::string &component_name)
 {
   d_impl->disconnect_component(component_name);
 }
@@ -115,9 +154,9 @@ mb_mblock::nconnections() const
 }
 
 bool
-mb_mblock::walk_tree(mb_visitor *visitor, const std::string &path)
+mb_mblock::walk_tree(mb_visitor *visitor)
 {
-  return d_impl->walk_tree(visitor, path);
+  return d_impl->walk_tree(visitor);
 }
 
 std::string
@@ -127,7 +166,7 @@ mb_mblock::instance_name() const
 }
 
 void
-mb_mblock::set_instance_name(const std::string name)
+mb_mblock::set_instance_name(const std::string &name)
 {
   d_impl->set_instance_name(name);
 }
@@ -139,7 +178,7 @@ mb_mblock::class_name() const
 }
 
 void
-mb_mblock::set_class_name(const std::string name)
+mb_mblock::set_class_name(const std::string &name)
 {
   d_impl->set_class_name(name);
 }
@@ -149,3 +188,42 @@ mb_mblock::parent() const
 {
   return d_impl->mblock_parent();
 }
+
+void
+mb_mblock::exit()
+{
+  throw mbe_exit();    // adios...
+}
+
+void
+mb_mblock::shutdown_all(pmt_t result)
+{
+  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);
+}
+
index 594920f9162a95b15a530f60f3bc98eb0377e4a3..6d471c3dbf09e7eda6c98aa31e703ed424ce3fdb 100644 (file)
@@ -24,6 +24,7 @@
 #include <mb_common.h>
 #include <mb_message.h>
 #include <mb_port.h>
+#include <mb_time.h>
 
 
 /*!
@@ -34,7 +35,7 @@ class mb_visitor
 {
 public:
   virtual ~mb_visitor();
-  virtual bool operator()(mb_mblock *mblock, const std::string &path) = 0;
+  virtual bool operator()(mb_mblock *mblock) = 0;
 };
 
 // ----------------------------------------------------------------------
@@ -52,6 +53,7 @@ private:
 
   friend class mb_runtime;
   friend class mb_mblock_impl;
+  friend class mb_worker;
 
 protected:
   /*!
@@ -59,22 +61,29 @@ protected:
    *
    * Initializing all mblocks in the system is a 3 step procedure.
    *
-   * The top level mblock's constructor is run.  That constructor (a)
-   * registers all of its ports using define_port, (b) constructs and
-   * registers any subcomponents it may have via the define_component
-   * method, and then (c) issues connect calls to wire its
-   * subcomponents together.
+   * The top level mblock's constructor is run.  That constructor 
+   * (a) registers all of its ports using define_port, (b) registers any
+   * subcomponents it may have via the define_component method, and
+   * then (c) issues connect calls to wire its subcomponents together.
+   *
+   * \param runtime the runtime associated with this mblock
+   * \param instance_name specify the name of this instance
+   *        (for debugging, NUMA mapping, etc)
+   * \param user_arg argument passed by user to constructor
+   *        (ignored by the mb_mblock base class)
    */
-  mb_mblock();
+  mb_mblock(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
 
 public:
   /*!
    * \brief Called by the runtime system to execute the initial
    * transition of the finite state machine.
    *
-   * Override this to initialize your finite state machine.
+   * This method is called by the runtime after all blocks are
+   * constructed and before the first message is delivered.  Override
+   * this to initialize your finite state machine.
    */
-  virtual void init_fsm();
+  virtual void initial_transition();
 
 protected:
   /*!
@@ -113,11 +122,13 @@ protected:
    * names and identities of our sub-component mblocks.
    *
    * \param component_name  The name of the sub-component (must be unique with this mblock).
-   * \param component       The sub-component instance.
+   * \param class_name      The class of the instance that is to be created.
+   * \param user_arg The argument to pass to the constructor of the component.
    */
   void
   define_component(const std::string &component_name,
-                  mb_mblock_sptr component);
+                  const std::string &class_name,
+                  pmt_t user_arg = PMT_NIL);
 
   /*!
    * \brief connect endpoint_1 to endpoint_2
@@ -160,7 +171,7 @@ protected:
    * \param component_name component to disconnect
    */
   void
-  disconnect_component(const std::string component_name);
+  disconnect_component(const std::string &component_name);
 
   /*!
    * \brief disconnect all connections to all components
@@ -175,8 +186,47 @@ protected:
   nconnections() const;
 
   //! Set the class name
-  void set_class_name(const std::string name);
+  void set_class_name(const std::string &name);
+
+  /*!
+   * \brief Tell runtime that we are done.
+   *
+   * This method does not return.
+   */
+  void exit();
 
+  /*!
+   * \brief Ask runtime to execute the shutdown procedure for all blocks.
+   * 
+   * \param result sets value of \p result output argument of runtime->run(...)
+   *
+   * The runtime first sends a maximum priority %shutdown message to
+   * all blocks.  All blocks should handle the %shutdown message,
+   * perform whatever clean up is required, and call this->exit();
+   *
+   * After a period of time (~100ms), any blocks which haven't yet
+   * called this->exit() are sent a maximum priority %halt message.
+   * %halt is detected in main_loop, and this->exit() is called.
+   *
+   * After an additional period of time (~100ms), any blocks which
+   * still haven't yet called this->exit() are sent a SIG<FOO> (TBD)
+   * signal, which will blow them out of any blocking system calls and
+   * raise an mbe_terminate exception.  The default top-level
+   * runtime-provided exception handler will call this->exit() to
+   * finish the process.
+   *
+   * runtime->run(...) returns when all blocks have called exit.
+   */
+  void shutdown_all(pmt_t result);
+
+  /*!
+   * \brief main event dispatching loop
+   *
+   * Although it is possible to override this, the default implementation
+   * should work for virtually all cases.
+   */
+  virtual void main_loop();
+  
 public:
   virtual ~mb_mblock();
 
@@ -187,18 +237,74 @@ public:
   std::string class_name() const;
 
   //! Set the instance name of this block.
-  void set_instance_name(const std::string name);
+  void set_instance_name(const std::string &name);
   
   //! Return the parent of this mblock, or 0 if we're the top-level block.
   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.
    */
   bool
-  walk_tree(mb_visitor *visitor, const std::string &path="top");
+  walk_tree(mb_visitor *visitor);
 
 
   //! \implementation
index 1a9e501463bbe7f49e001ef6112f6f5b0bcebb95..02cbb548db5fb9d730dedfd5e10d94f7fe7fea96 100644 (file)
@@ -30,8 +30,8 @@
 #include <mb_exception.h>
 #include <mb_util.h>
 #include <mb_msg_accepter_smp.h>
-#include <mb_runtime_placeholder.h>
 #include <mbi_runtime_lock.h>
+#include <iostream>
 
 
 static pmt_t s_self = pmt_intern("self");
@@ -52,9 +52,10 @@ mb_mblock_impl::comp_is_defined(const std::string &name)
 
 ////////////////////////////////////////////////////////////////////////
 
-mb_mblock_impl::mb_mblock_impl(mb_mblock *mb)
-  : d_mb(mb), d_mb_parent(0), d_runtime(mb_runtime_placeholder::singleton()),
-    d_instance_name("<unknown>"), d_class_name("mblock")
+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")
 {
 }
 
@@ -85,15 +86,28 @@ mb_mblock_impl::define_port(const std::string &port_name,
 
 void
 mb_mblock_impl::define_component(const std::string &name,
-                                mb_mblock_sptr component)
+                                const std::string &class_name,
+                                pmt_t user_arg)
 {
-  mbi_runtime_lock     l(this);
+  {
+    mbi_runtime_lock   l(this);
+
+    if (comp_is_defined(name)) // check for duplicate name
+      throw mbe_duplicate_component(d_mb, name);
+  }
 
-  if (comp_is_defined(name))   // check for duplicate name
-    throw mbe_duplicate_component(d_mb, name);
+  // We ask the runtime to create the component so that it can worry about
+  // mblock placement on a NUMA machine or on a distributed multicomputer
 
-  component->d_impl->d_mb_parent = d_mb;     // set component's parent link
-  d_comp_map[name] = component;
+  mb_mblock_sptr component =
+    d_runtime->create_component(instance_name() + "/" + name,
+                               class_name, user_arg);
+  {
+    mbi_runtime_lock   l(this);
+
+    component->d_impl->d_mb_parent = d_mb;     // set component's parent link
+    d_comp_map[name] = component;
+  }
 }
 
 void
@@ -125,6 +139,7 @@ mb_mblock_impl::disconnect(const std::string &comp_name1,
   mbi_runtime_lock     l(this);
 
   d_conn_table.disconnect(comp_name1, port_name1, comp_name2, port_name2);
+  invalidate_all_port_caches();
 }
 
 void
@@ -133,6 +148,7 @@ mb_mblock_impl::disconnect_component(const std::string component_name)
   mbi_runtime_lock     l(this);
 
   d_conn_table.disconnect_component(component_name);
+  invalidate_all_port_caches();
 }
 
 void
@@ -141,6 +157,7 @@ mb_mblock_impl::disconnect_all()
   mbi_runtime_lock     l(this);
 
   d_conn_table.disconnect_all();
+  invalidate_all_port_caches();
 }
 
 int
@@ -220,26 +237,25 @@ mb_mblock_impl::endpoints_are_compatible(const mb_endpoint &ep0,
 }
 
 bool
-mb_mblock_impl::walk_tree(mb_visitor *visitor, const std::string &path)
+mb_mblock_impl::walk_tree(mb_visitor *visitor)
 {
-  if (!(*visitor)(d_mb, path))
+  if (!(*visitor)(d_mb))
     return false;
 
   mb_comp_map_t::iterator it;
   for (it = d_comp_map.begin(); it != d_comp_map.end(); ++it)
-    if (!(it->second->walk_tree(visitor, path + "/" + it->first)))
+    if (!(it->second->walk_tree(visitor)))
       return false;
 
   return true;
 }
 
 mb_msg_accepter_sptr
-mb_mblock_impl::make_accepter(const std::string port_name)
+mb_mblock_impl::make_accepter(pmt_t port_name)
 {
   // FIXME this should probably use some kind of configurable factory
   mb_msg_accepter *ma =
-    new mb_msg_accepter_smp(d_mb->shared_from_this(),
-                           pmt_intern(port_name));
+    new mb_msg_accepter_smp(d_mb->shared_from_this(), port_name);
 
   return mb_msg_accepter_sptr(ma);
 }
@@ -281,3 +297,31 @@ mb_mblock_impl::set_class_name(const std::string &name)
   d_class_name = name;
 }
 
+/*
+ * This is the "Big Hammer" port cache invalidator.
+ * It invalidates _all_ of the port caches in the entire mblock tree.
+ * It's overkill, but was simple to code.
+ */
+void
+mb_mblock_impl::invalidate_all_port_caches()
+{
+  class invalidator : public mb_visitor
+  {
+  public:
+    bool operator()(mb_mblock *mblock)
+    {
+      mb_mblock_impl_sptr impl = mblock->impl();
+      mb_port_map_t::iterator it = impl->d_port_map.begin();
+      mb_port_map_t::iterator end = impl->d_port_map.end();
+      for (; it != end; ++it)
+       it->second->invalidate_cache();
+      return true;
+    }
+  };
+
+  invalidator visitor;
+
+  // Always true, except in early QA code
+  if (runtime()->top())
+    runtime()->top()->walk_tree(&visitor);
+}
index fc0fa69435afd6850111c624346f2e95c16c5151..03ad414ea6ddceb814596e2651c1e2fe4f1cbbfe 100644 (file)
@@ -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,9 +38,9 @@ typedef std::map<std::string, mb_mblock_sptr> mb_comp_map_t;
  */
 class mb_mblock_impl : boost::noncopyable
 {
+  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
-  mb_runtime                  *d_runtime;      // pointer to runtime
 
   std::string                  d_instance_name;    // hierarchical name
   std::string                  d_class_name;       // name of this (derived) class
@@ -51,7 +52,8 @@ class mb_mblock_impl : boost::noncopyable
   mb_msg_queue                 d_msgq;         // incoming messages for us
 
 public:
-  mb_mblock_impl(mb_mblock *mb);
+  mb_mblock_impl(mb_runtime_base *runtime, mb_mblock *mb,
+                const std::string &instance_name);
   ~mb_mblock_impl();
 
   /*!
@@ -79,11 +81,13 @@ public:
    * names and identities of our sub-component mblocks.
    *
    * \param component_name  The name of the sub-component (must be unique with this mblock).
-   * \param component       The sub-component instance.
+   * \param class_name      The class of the instance that is to be created.
+   * \param user_arg The argument to pass to the constructor of the component.
    */
   void
   define_component(const std::string &component_name,
-                  mb_mblock_sptr component);
+                  const std::string &class_name,
+                  pmt_t user_arg);
 
   /*!
    * \brief connect endpoint_1 to endpoint_2
@@ -141,10 +145,10 @@ public:
   nconnections();
 
   bool
-  walk_tree(mb_visitor *visitor, const std::string &path="");
+  walk_tree(mb_visitor *visitor);
   
   mb_msg_accepter_sptr
-  make_accepter(const std::string port_name);
+  make_accepter(pmt_t port_name);
 
   mb_msg_queue &
   msgq() { return d_msgq; }
@@ -183,10 +187,10 @@ public:
   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
@@ -210,6 +214,12 @@ private:
   endpoints_are_compatible(const mb_endpoint &ep0,
                           const mb_endpoint &ep1);
 
+  /*!
+   * \brief walk mblock tree and invalidate all port resolution caches.
+   * \implementation
+   */
+  void
+  invalidate_all_port_caches();
 };
 
 
index 23803726a4200c18426935ba96afdbab5b98d72a..14e3499242d0a44c29da540514d872efc039af45 100644 (file)
 #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 @@ mb_message::~mb_message()
 {
   // 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;
+}
index 95440f8b74aa2481029e8a2b7882172d485a48b7..6132866e2d5fa32ff5a717bb7a953644fd940223 100644 (file)
@@ -22,6 +22,9 @@
 #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 @@ public:
   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 */
diff --git a/mblock/src/lib/mb_msg_accepter_msgq.cc b/mblock/src/lib/mb_msg_accepter_msgq.cc
new file mode 100644 (file)
index 0000000..990491f
--- /dev/null
@@ -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);
+}
diff --git a/mblock/src/lib/mb_msg_accepter_msgq.h b/mblock/src/lib/mb_msg_accepter_msgq.h
new file mode 100644 (file)
index 0000000..f598c73
--- /dev/null
@@ -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 */
index 79e245ad60267076298c4a050e481258afd37547..c687e87605c6e31d47c25e6e9142a6d0fa4fc789 100644 (file)
@@ -83,7 +83,7 @@ mb_msg_queue::get_highest_pri_msg_helper()
     }
   }
 
-  return mb_message_sptr();    // equivalent of a zero pointer
+  return mb_message_sptr();            // eqv to a zero pointer
 }
 
 
@@ -109,3 +109,20 @@ mb_msg_queue::get_highest_pri_msg()
   }
 }
 
+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
+  }
+}
index 7977b7d80d188c8a0f08f2ebcc288b83ffcfa475..4f805ea8f0ac025df9fe38b3a7de559bee7a6114 100644 (file)
@@ -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 @@ public:
    * 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 */
index b265db2dc5a4a8aec7b0e4bbfe90ca3dfe8dc8f2..28bb402d89e2c42b93c6d007a2119d36ac463afb 100644 (file)
@@ -31,7 +31,8 @@ mb_port::mb_port(mb_mblock *mblock,
                 const std::string &protocol_class_name,
                 bool conjugated,
                 mb_port::port_type_t port_type)
-  : d_port_name(port_name), d_conjugated(conjugated), d_port_type(port_type),
+  : d_port_name(port_name), d_port_symbol(pmt_intern(port_name)),
+    d_conjugated(conjugated), d_port_type(port_type),
     d_mblock(mblock)
 {
   pmt_t pc = mb_protocol_class_lookup(pmt_intern(protocol_class_name));
index 3c3e963687edbb23ce6e34e868967f7742441e58..3fdd25aff4ad31d66ed1d36aaaa3990aba91f6c9 100644 (file)
@@ -40,6 +40,7 @@ public:
 private:
 
   std::string          d_port_name;
+  pmt_t                        d_port_symbol;          // the port_name as a pmt symbol
   pmt_t                        d_protocol_class;
   bool                 d_conjugated;
   port_type_t          d_port_type;
@@ -58,6 +59,7 @@ protected:
 
 public:
   std::string  port_name() const { return d_port_name; }
+  pmt_t                port_symbol() const { return d_port_symbol; }
   pmt_t                protocol_class() const { return d_protocol_class; }
   bool          conjugated() const { return d_conjugated; }
   port_type_t  port_type() const { return d_port_type; }
@@ -77,9 +79,15 @@ public:
    */
   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;
+
+  /*
+   * \brief Invalidate any cached peer resolutions
+   * \implementation
+   */
+  virtual void invalidate_cache() = 0;
 };
 
 #endif /* INCLUDED_MB_PORT_H */
index 80cb65efbd62178b5200e784b9e4ecc49195b12f..cbfb0f27f5f9da2a8ac2f2c6783b40b792978f15 100644 (file)
@@ -37,7 +37,8 @@ mb_port_simple::mb_port_simple(mb_mblock *mblock,
                               const std::string &protocol_class_name,
                               bool conjugated,
                               mb_port::port_type_t port_type)
-  : mb_port(mblock, port_name, protocol_class_name, conjugated, port_type)
+  : mb_port(mblock, port_name, protocol_class_name, conjugated, port_type),
+    d_cache_valid(false)
 {
 }
 
@@ -67,6 +68,9 @@ mb_port_simple::find_accepter(mb_port_simple *start)
   mb_endpoint          peer_ep;
   mb_msg_accepter_sptr r;
 
+  if (start->d_cache_valid)
+    return start->d_cached_accepter;
+
   mbi_runtime_lock     l(p->mblock());
 
   // Set up initial context.
@@ -78,6 +82,8 @@ mb_port_simple::find_accepter(mb_port_simple *start)
 
   case mb_port::EXTERNAL:      // binding is in parent's name space
     context = p->mblock()->parent();
+    if (!context)                      // can't be bound if there's no parent
+      return mb_msg_accepter_sptr();   // not bound
     break;
 
   default:
@@ -97,7 +103,11 @@ mb_port_simple::find_accepter(mb_port_simple *start)
   case mb_port::INTERNAL:      // Terminate here.
   case mb_port::EXTERNAL:
     r = pp->make_accepter();
-    // FIXME cache the result
+
+    // cache the result
+
+    start->d_cached_accepter = r;
+    start->d_cache_valid = true;
     return r;
 
   case mb_port::RELAY:         // Traverse to other side of relay port.
@@ -130,5 +140,12 @@ mb_port_simple::find_accepter(mb_port_simple *start)
 mb_msg_accepter_sptr
 mb_port_simple::make_accepter()
 {
-  return d_mblock->impl()->make_accepter(port_name());
+  return d_mblock->impl()->make_accepter(port_symbol());
+}
+
+void
+mb_port_simple::invalidate_cache()
+{
+  d_cache_valid = false;
+  d_cached_accepter.reset();
 }
index 5cfbd3dc0870354115c9b980bb0c12aa77423980..9bfe0eaf76f4ba6ace3a0aa7470d950ac48c4230 100644 (file)
@@ -28,6 +28,9 @@
  */
 class mb_port_simple : public mb_port
 {
+  bool                 d_cache_valid;
+  mb_msg_accepter_sptr d_cached_accepter;
+
 protected:
   static mb_msg_accepter_sptr
   find_accepter(mb_port_simple *start);
@@ -57,6 +60,13 @@ public:
        pmt_t data = PMT_NIL,
        pmt_t metadata = PMT_NIL,
        mb_pri_t priority = MB_PRI_DEFAULT);
+
+  /*
+   * \brief Invalidate any cached peer resolutions
+   * \implementation
+   */
+  void invalidate_cache();
+
 };
 
 #endif /* INCLUDED_MB_PORT_SIMPLE_H */
index f3eeb6035bf992bd004919001c464e3b46799518..a11017fa98d221e6b949c2920db4f48d030f43f1 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 
 #include <mb_protocol_class.h>
+#include <iostream>
 
 static pmt_t s_ALL_PROTOCOL_CLASSES = PMT_NIL;
 
@@ -80,3 +81,25 @@ mb_protocol_class_lookup(pmt_t name)
 
   return PMT_NIL;
 }
+
+mb_protocol_class_init::mb_protocol_class_init(const char *data, size_t len)
+{
+  std::stringbuf sb;
+  sb.str(std::string(data, len));
+
+  while (1){
+    pmt_t obj = pmt_deserialize(sb);
+
+    if (0){
+      pmt_write(obj, std::cout);
+      std::cout << std::endl;
+    }
+
+    if (pmt_is_eof_object(obj))
+      return;
+
+    mb_make_protocol_class(pmt_nth(0, obj),   // protocol-class name
+                          pmt_nth(1, obj),   // list of incoming msg names
+                          pmt_nth(2, obj));  // list of outgoing msg names
+  }
+}
index f4382ada12b33f79d4ee84161320b022aff34545..60b87709d1d00835bf8fa161af1e073cbd680da2 100644 (file)
@@ -39,4 +39,14 @@ pmt_t mb_protocol_class_outgoing(pmt_t pc);  //< return outgoing message set
 
 pmt_t mb_protocol_class_lookup(pmt_t name);    //< lookup an existing protocol class by name
 
+
+/*!
+ * \brief Initialize one or more protocol class from a serialized description.
+ * Used by machine generated code.
+ */
+class mb_protocol_class_init {
+public:
+  mb_protocol_class_init(const char *data, size_t len);
+};
+
 #endif /* INCLUDED_MB_PROTOCOL_CLASS_H */
index 34a0af358086263dffe3e0f4485ff3faa21deb5c..7f3b786789896f1ac7a11687a1a7164d95ae3d7b 100644 (file)
 #endif
 
 #include <mb_runtime.h>
-#include <mb_runtime_thread_per_mblock.h>
+#include <mb_runtime_thread_per_block.h>
 
 mb_runtime_sptr
 mb_make_runtime()
 {
-  return mb_runtime_sptr(new mb_runtime_thread_per_mblock());
+  return mb_runtime_sptr(new mb_runtime_thread_per_block());
 }
 
 mb_runtime::~mb_runtime()
 {
   // nop
 }
+
index 0929e30dc56b25c4fb37e4295afc693627244579..a804af06f4cc42cbc97ef1e43b6bf6eeebf4b9aa 100644 (file)
@@ -37,40 +37,32 @@ mb_runtime_sptr mb_make_runtime();
 class mb_runtime : boost::noncopyable,
                   public boost::enable_shared_from_this<mb_runtime>
 {
-  omni_mutex   d_brl;          // big runtime lock (avoid using this if possible...)
+protected:  
+  mb_mblock_sptr       d_top;
 
 public:
   mb_runtime(){}
   virtual ~mb_runtime();
 
   /*!
-   * \brief Run the mblock hierarchy rooted at \p top
+   * \brief Construct and run the specified mblock hierarchy.
    *
    * This routine turns into the m-block scheduler, and
    * blocks until the system is shutdown.
    *
-   * \param top top-level mblock
+   * \param name name of the top-level mblock (conventionally "top")
+   * \param class_name The class of the top-level mblock to create.
+   * \param user_arg The argument to pass to the top-level mblock constructor
+   *
    * \returns true if the system ran successfully.
    */
-  virtual bool run(mb_mblock_sptr top) = 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 bool run(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg,
+                  pmt_t *result = 0) = 0;
 
+  // QA only...
+  mb_mblock_sptr top() { return d_top; }
 };
 
 #endif /* INCLUDED_MB_RUNTIME_H */
diff --git a/mblock/src/lib/mb_runtime_base.cc b/mblock/src/lib/mb_runtime_base.cc
new file mode 100644 (file)
index 0000000..104b6af
--- /dev/null
@@ -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)
+{
+}
+
diff --git a/mblock/src/lib/mb_runtime_base.h b/mblock/src/lib/mb_runtime_base.h
new file mode 100644 (file)
index 0000000..cb76e45
--- /dev/null
@@ -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 */
index a19f0793aff787af7df0133f9046e60841aef62b..bcae1ebd53ef471d8156739e0f03ab1a680cc231 100644 (file)
@@ -24,6 +24,8 @@
 #endif
 #include <mb_runtime_nop.h>
 #include <mb_mblock.h>
+#include <mb_class_registry.h>
+#include <mb_exception.h>
 
 mb_runtime_sptr 
 mb_make_runtime_nop()
@@ -42,23 +44,41 @@ mb_runtime_nop::~mb_runtime_nop()
   // nop for now
 }
 
+
 bool
-mb_runtime_nop::run(mb_mblock_sptr top)
+mb_runtime_nop::run(const std::string &instance_name,
+                   const std::string &class_name,
+                   pmt_t user_arg, pmt_t *result)
 {
   class initial_visitor : public mb_visitor
   {
   public:
-    bool operator()(mb_mblock *mblock, const std::string &path)
+    bool operator()(mb_mblock *mblock)
     {
-      mblock->set_instance_name(path);
-      mblock->init_fsm();
+      mblock->initial_transition();
       return true;
     }
   };
 
-  initial_visitor      visitor;
+  initial_visitor visitor;
+
+  if (result)
+    *result = PMT_T;
 
-  top->walk_tree(&visitor);
+  d_top = create_component(instance_name, class_name, user_arg);
+  d_top->walk_tree(&visitor);
 
   return true;
 }
+
+mb_mblock_sptr
+mb_runtime_nop::create_component(const std::string &instance_name,
+                                const std::string &class_name,
+                                pmt_t user_arg)
+{
+  mb_mblock_maker_t maker;
+  if (!mb_class_registry::lookup_maker(class_name, &maker))
+    throw mbe_no_such_class(0, class_name + " (in " + instance_name + ")");
+
+  return maker(this, instance_name, user_arg);
+}
index dc788799192af774f092e08bb4c0c92ccc5c6e0c..d7fe105bddbf6edba99dc8c985eda02dea530d9a 100644 (file)
@@ -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,14 +31,22 @@ mb_runtime_sptr mb_make_runtime_nop();
 /*!
  * \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();
   ~mb_runtime_nop();
 
-  bool run(mb_mblock_sptr top);
+  bool run(const std::string &instance_name,
+          const std::string &class_name,
+          pmt_t user_arg,
+          pmt_t *result);
+
+protected:
+  mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg);
 };
 
 #endif /* INCLUDED_MB_RUNTIME_NOP_H */
diff --git a/mblock/src/lib/mb_runtime_placeholder.cc b/mblock/src/lib/mb_runtime_placeholder.cc
deleted file mode 100644 (file)
index 5ce7cc2..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- 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_placeholder.h>
-#include <mb_mblock.h>
-#include <mb_exception.h>
-
-
-static mb_runtime *s_singleton = 0;
-
-
-mb_runtime_placeholder::mb_runtime_placeholder()
-{
-  // nop
-}
-
-mb_runtime_placeholder::~mb_runtime_placeholder()
-{
-  // nop
-}
-
-bool
-mb_runtime_placeholder::run(mb_mblock_sptr top)
-{
-  throw mbe_not_implemented(top.get(), "mb_runtime_placeholder::run");
-}
-
-mb_runtime *
-mb_runtime_placeholder::singleton()
-{
-  if (s_singleton)
-    return s_singleton;
-
-  s_singleton = new mb_runtime_placeholder();
-  return s_singleton;
-}
diff --git a/mblock/src/lib/mb_runtime_placeholder.h b/mblock/src/lib/mb_runtime_placeholder.h
deleted file mode 100644 (file)
index b55d39f..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- 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_PLACEHOLDER_H
-#define INCLUDED_MB_RUNTIME_PLACEHOLDER_H
-
-#include <mb_runtime.h>
-
-/*!
- * \brief Concrete runtime that serves as a placeholder until the real
- * runtime is known.
- *
- * The singleton instance of this class is installed in the d_runtime
- * instance variable of each mb_mblock_impl at construction time.
- * Having a valid instance of runtime removes the "pre runtime::run"
- * corner case, and allows us to lock and unlock the big runtime lock
- * even though there's no "real runtime" yet.
- */
-class mb_runtime_placeholder : public mb_runtime
-{
-
-public:
-  mb_runtime_placeholder();
-  ~mb_runtime_placeholder();
-
-  //! throws mbe_not_implemented
-  bool run(mb_mblock_sptr top);
-
-  //! Return the placeholder singleton
-  static mb_runtime *singleton();
-};
-
-#endif /* INCLUDED_MB_RUNTIME_PLACEHOLDER_H */
diff --git a/mblock/src/lib/mb_runtime_thread_per_block.cc b/mblock/src/lib/mb_runtime_thread_per_block.cc
new file mode 100644 (file)
index 0000000..7ad87aa
--- /dev/null
@@ -0,0 +1,349 @@
+/* -*- 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_thread_per_block.h>
+#include <mb_mblock.h>
+#include <mb_mblock_impl.h>
+#include <mb_class_registry.h>
+#include <mb_exception.h>
+#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_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,
+            mb_pri_t priority = MB_PRI_BEST)
+{
+  mb_message_sptr msg = mb_make_message(signal, data, metadata, priority);
+  msg->set_port_id(s_sys_port);
+  msgq.insert(msg);
+}
+
+
+mb_runtime_thread_per_block::mb_runtime_thread_per_block()
+  : 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()
+{
+  // FIXME iterate over workers and ensure that they are dead.
+
+  if (!d_workers.empty())
+    std::cerr << "\nmb_runtime_thread_per_block: dtor (# workers = "
+             << d_workers.size() << ")\n";
+}
+
+void
+mb_runtime_thread_per_block::request_shutdown(pmt_t result)
+{
+  (*accepter())(s_request_shutdown, result, PMT_F, MB_PRI_BEST);
+}
+
+bool
+mb_runtime_thread_per_block::run(const std::string &instance_name,
+                                const std::string &class_name,
+                                pmt_t user_arg, pmt_t *result)
+{
+  if (result)          // set it to something now, in case we throw
+    *result = PMT_F;
+  
+  // reset the shutdown state
+  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.
+   */
+  d_top = create_component(instance_name, class_name, user_arg);
+
+  try {
+    run_loop();
+  }
+  catch (...){
+    d_top.reset();
+    throw;
+  }
+
+  if (result)
+    *result = d_shutdown_result;
+  
+  d_top.reset();
+  return true;
+}
+
+void
+mb_runtime_thread_per_block::run_loop()
+{
+  while (1){
+    mb_message_sptr msg;
+
+    if (d_timer_queue.empty())                   // Any timeouts pending?
+      msg = d_msgq.get_highest_pri_msg();        // Nope.  Block forever.
+
+    else {
+      mb_timeout_sptr to = d_timer_queue.top();          // Yep.  Get earliest timeout.
+
+      // wait for a msg or the timeout...
+      msg = d_msgq.get_highest_pri_msg_timedwait(to->d_when);
+
+      if (!msg){               // We timed out.
+       d_timer_queue.pop();    // Remove timeout from timer queue.
+
+       // send the %timeout msg
+       (*to->d_accepter)(s_timeout, to->d_user_data, to->handle(), MB_PRI_BEST);
+
+       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
+
+      // 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;
+    }
+    else {
+      std::cerr << "mb_runtime_thread_per_block: unhandled msg: " << msg << std::endl;
+    }
+  }
+}
+
+void
+mb_runtime_thread_per_block::reap_dead_workers()
+{
+  // 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;
+
+    // We can't join while holding the worker mutex, since that would
+    // attempt to destroy the mutex we're holding (omnithread's join
+    // deletes the omni_thread object after the pthread_join
+    // completes) Instead, we lock just long enough to figure out if
+    // the worker is dead.
+    {
+      omni_mutex_lock l2((*wi)->d_mutex);
+      is_dead = (*wi)->d_state == mb_worker::TS_DEAD;
+    }
+
+    if (is_dead){
+      if (0)
+       std::cerr << "\nruntime: "
+                 << "(" << (*wi)->id() << ") "
+                 << (*wi)->d_mblock->instance_name() << " is TS_DEAD\n";
+      void *ignore;
+      (*wi)->join(&ignore);
+      wi = d_workers.erase(wi);
+      continue;
+    }
+    ++wi;
+  }
+}
+
+//
+// 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,
+                                             pmt_t user_arg)
+{
+  mb_mblock_maker_t maker;
+  if (!mb_class_registry::lookup_maker(class_name, &maker))
+    throw mbe_no_such_class(0, class_name + " (in " + instance_name + ")");
+
+  // FIXME here's where we'd lookup NUMA placement requests & mblock
+  // priorities and communicate them to the worker we're creating...
+
+  // Create the worker thread
+  mb_worker *w =
+    new mb_worker(this, maker, instance_name, user_arg);
+
+  w->start_undetached();  // start it
+
+  // Wait for it to reach TS_RUNNING or TS_DEAD
+
+  bool                                 is_dead;
+  mb_worker::cause_of_death_t  why_dead;
+  {
+    omni_mutex_lock l(w->d_mutex);
+    while (!(w->d_state == mb_worker::TS_RUNNING
+            || w->d_state == mb_worker::TS_DEAD))
+      w->d_state_cond.wait();
+
+    is_dead = w->d_state == mb_worker::TS_DEAD;
+    why_dead = w->d_why_dead;
+  }
+
+  // If the worker failed to init (constructor or initial_transition
+  // raised an exception), reap the worker now and raise an exception.
+
+  if (is_dead && why_dead != mb_worker::RIP_EXIT){
+
+    void *ignore;
+    w->join(&ignore);
+
+    // FIXME with some work we ought to be able to propagate the
+    // exception from the worker.
+    throw mbe_mblock_failed(0, instance_name);
+  }
+
+  assert(w->d_mblock);
+
+  // Add w to the vector of workers, and return the mblock.
+  {
+    omni_mutex_lock l(d_workers_mutex);
+    d_workers.push_back(w);
+  }
+
+  if (0)
+    std::cerr << "\nruntime: created "
+             << "(" << w->id() << ") "
+             << w->d_mblock->instance_name() << "\n";
+
+  return w->d_mblock;
+}
+
+void
+mb_runtime_thread_per_block::send_all_sys_msg(pmt_t signal,
+                                             pmt_t data,
+                                             pmt_t metadata,
+                                             mb_pri_t priority)
+{
+  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);
+}
diff --git a/mblock/src/lib/mb_runtime_thread_per_block.h b/mblock/src/lib/mb_runtime_thread_per_block.h
new file mode 100644 (file)
index 0000000..773b8b4
--- /dev/null
@@ -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.
+ */
+#ifndef INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H
+#define INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_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
+ * \implementation
+ *
+ * These are all implementation details.
+ */
+class mb_runtime_thread_per_block : public mb_runtime_base
+{
+public:
+  omni_mutex                 d_workers_mutex;  // hold while manipulating d_workers
+  std::vector<mb_worker*>     d_workers;
+  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*>::iterator  worker_iter_t;
+
+  mb_runtime_thread_per_block();
+  ~mb_runtime_thread_per_block();
+
+  bool run(const std::string &instance_name,
+          const std::string &class_name,
+          pmt_t user_arg,
+          pmt_t *result);
+
+  void request_shutdown(pmt_t result);
+
+protected:
+  mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  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 */
diff --git a/mblock/src/lib/mb_runtime_thread_per_mblock.cc b/mblock/src/lib/mb_runtime_thread_per_mblock.cc
deleted file mode 100644 (file)
index 925dcdc..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- 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_thread_per_mblock.h>
-#include <mb_mblock.h>
-#include <mb_mblock_impl.h>
-
-
-mb_runtime_thread_per_mblock::mb_runtime_thread_per_mblock()
-{
-  // nop for now
-}
-
-mb_runtime_thread_per_mblock::~mb_runtime_thread_per_mblock()
-{
-  // nop for now
-}
-
-bool
-mb_runtime_thread_per_mblock::run(mb_mblock_sptr top)
-{
-  class initial_visitor : public mb_visitor
-  {
-    mb_runtime  *d_rt;
-
-  public:
-    initial_visitor(mb_runtime *rt) : d_rt(rt) {}
-    bool operator()(mb_mblock *mblock, const std::string &path)
-    {
-      mblock->impl()->set_runtime(d_rt);
-      mblock->set_instance_name(path);
-      mblock->init_fsm();
-      return true;
-    }
-  };
-
-  initial_visitor      visitor(this);
-
-  d_top = top;         // remember top of tree
-
-  d_top->walk_tree(&visitor);
-
-  return true;
-}
diff --git a/mblock/src/lib/mb_runtime_thread_per_mblock.h b/mblock/src/lib/mb_runtime_thread_per_mblock.h
deleted file mode 100644 (file)
index cef756e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- 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_THREAD_PER_MBLOCK_H
-#define INCLUDED_MB_RUNTIME_THREAD_PER_MBLOCK_H
-
-#include <mb_runtime.h>
-
-/*!
- * \brief Concrete runtime that uses a single thread for all work.
- */
-class mb_runtime_thread_per_mblock : public mb_runtime
-{
-  mb_mblock_sptr       d_top;          // top mblock
-
-public:
-  mb_runtime_thread_per_mblock();
-  ~mb_runtime_thread_per_mblock();
-
-  bool run(mb_mblock_sptr top);
-};
-
-#endif /* INCLUDED_MB_RUNTIME_THREAD_PER_MBLOCK_H */
diff --git a/mblock/src/lib/mb_time.cc b/mblock/src/lib/mb_time.cc
new file mode 100644 (file)
index 0000000..73c86e4
--- /dev/null
@@ -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);
+}
diff --git a/mblock/src/lib/mb_time.h b/mblock/src/lib/mb_time.h
new file mode 100644 (file)
index 0000000..872304c
--- /dev/null
@@ -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 */
diff --git a/mblock/src/lib/mb_timer_queue.cc b/mblock/src/lib/mb_timer_queue.cc
new file mode 100644 (file)
index 0000000..026035e
--- /dev/null
@@ -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);
+}
diff --git a/mblock/src/lib/mb_timer_queue.h b/mblock/src/lib/mb_timer_queue.h
new file mode 100644 (file)
index 0000000..a176883
--- /dev/null
@@ -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 */
diff --git a/mblock/src/lib/mb_worker.cc b/mblock/src/lib/mb_worker.cc
new file mode 100644 (file)
index 0000000..8a92484
--- /dev/null
@@ -0,0 +1,178 @@
+/* -*- 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_worker.h>
+#include <mb_runtime_thread_per_block.h>
+#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>
+#endif
+
+#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,
+                    pmt_t user_arg)
+  : omni_thread((void *) 0, PRIORITY_NORMAL),
+    d_runtime(runtime), d_maker(maker),
+    d_instance_name(instance_name), d_user_arg(user_arg),
+    d_state_cond(&d_mutex), d_state(TS_UNINITIALIZED),
+    d_why_dead(RIP_NOT_DEAD_YET)
+{
+}
+
+#if 0
+mb_worker::~mb_worker()
+{
+}
+#endif
+
+#ifdef HAVE_SCHED_SETAFFINITY
+static void
+set_affinity(const std::string &instance_name, const std::string &class_name)
+{
+  //static int counter = 0;
+  cpu_set_t    mask;
+  CPU_ZERO(&mask);
+
+  if (0){
+
+    //CPU_SET(counter & 0x1, &mask);
+    //counter++;
+    CPU_SET(0, &mask);
+
+    int r = sched_setaffinity(mb_gettid(), sizeof(mask), &mask);
+    if (r == -1)
+      perror("sched_setaffinity");
+  }
+}
+#else
+static void
+set_affinity(const std::string &instance_name, const std::string &class_name)
+{
+}
+#endif
+
+void
+mb_worker::set_state(worker_state_t state)
+{
+  {
+    omni_mutex_lock  l2(d_mutex);
+
+    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 *
+mb_worker::run_undetached(void *ignored)
+{
+  // FIXME add pthread_sigmask stuff
+
+  //set_affinity(d_instance_name, d_class_name);
+  set_affinity(d_instance_name, "");
+
+  try {
+    worker_thread_top_level();
+    d_why_dead = RIP_EXIT;
+  }
+  catch (mbe_terminate){
+    d_why_dead = RIP_TERMINATE;
+  }
+  catch (mbe_exit){
+    d_why_dead = RIP_EXIT;
+  }
+  catch (std::logic_error e){
+    if (d_why_dead == RIP_NOT_DEAD_YET)
+      d_why_dead = RIP_UNHANDLED_EXCEPTION;
+
+    std::cerr << "\nmb_worker::run_undetached: unhandled exception:\n";
+    std::cerr << "  " << e.what() << std::endl;
+  }
+  catch (...){
+    if (d_why_dead == RIP_NOT_DEAD_YET)
+      d_why_dead = RIP_UNHANDLED_EXCEPTION;
+  }
+
+  if (VERBOSE)
+    std::cerr << "\nrun_undetached: about to return, d_why_dead = "
+             << d_why_dead << std::endl;
+
+  set_state(TS_DEAD);
+  return 0;
+}
+
+void
+mb_worker::worker_thread_top_level()
+{
+  if (VERBOSE)
+    std::cerr << "worker_thread_top_level (enter):" << std::endl
+             << "  instance_name: " << d_instance_name << std::endl
+             << "  omnithread id: " << id() << std::endl
+             << "  gettid:        " << mb_gettid() << std::endl
+             << "  getpid:        " << getpid() << std::endl;
+
+  cause_of_death_t pending_cause_of_death = RIP_NOT_DEAD_YET;
+  
+  try {
+    pending_cause_of_death = RIP_CTOR_EXCEPTION;
+    d_mblock = d_maker(d_runtime, d_instance_name, d_user_arg);
+
+    if (VERBOSE)
+      std::cerr << "worker_thread_top_level (post-construction):" << std::endl
+               << "  instance_name: " << d_instance_name << std::endl;
+
+    pending_cause_of_death = RIP_INIT_EXCEPTION;
+    d_mblock->initial_transition();
+
+    if (VERBOSE)
+      std::cerr << "worker_thread_top_level (post-initial-transition):" << std::endl
+               << "  instance_name: " << d_instance_name << std::endl;
+
+    set_state(TS_RUNNING);
+
+    pending_cause_of_death = RIP_UNHANDLED_EXCEPTION;
+    d_mblock->main_loop();
+  }
+  catch (...){
+    d_why_dead = pending_cause_of_death;
+    throw;
+  }
+
+  if (VERBOSE)
+    std::cerr << "worker_thread_top_level (exit):" << std::endl
+             << "  instance_name: " << d_instance_name << std::endl;
+}
diff --git a/mblock/src/lib/mb_worker.h b/mblock/src/lib/mb_worker.h
new file mode 100644 (file)
index 0000000..b207f4d
--- /dev/null
@@ -0,0 +1,106 @@
+/* -*- 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_WORKER_H
+#define INCLUDED_MB_WORKER_H
+
+#include <omnithread.h>
+#include <mb_common.h>
+#include <mb_class_registry.h>
+
+
+class mb_worker;
+//typedef boost::shared_ptr<mb_worker> mb_worker_sptr;
+
+class mb_runtime_thread_per_block;
+
+/*!
+ * \brief Worker thread for thread_per_block runtime
+ * \implementation
+ */
+class mb_worker : public omni_thread
+{
+public:
+  //! worker thread states
+  enum worker_state_t {
+    TS_UNINITIALIZED,  // new, uninitialized
+    TS_RUNNING,                // normal steady-state condition.
+    TS_DEAD            // thread is dead
+  };
+
+  //! why we're dead
+  enum cause_of_death_t {
+    RIP_NOT_DEAD_YET,          // not dead
+    RIP_EXIT,                  // normal exit
+    RIP_TERMINATE,             // caught terminate exception
+    RIP_CTOR_EXCEPTION,                // constructor raised an exception
+    RIP_INIT_EXCEPTION,                // initial_transition rasised an exception
+    RIP_UNHANDLED_EXCEPTION    // somebody (most likely handle_message) raised an exception
+  };
+
+  /*
+   * Args used by new thread to create mb_mblock
+   */
+  mb_runtime_thread_per_block  *d_runtime;
+  mb_mblock_maker_t            d_maker;
+  std::string                  d_instance_name;
+  pmt_t                                d_user_arg;
+
+  mb_mblock_sptr               d_mblock;       //< holds pointer to created mblock
+
+  /*!
+   * \brief General mutex for all these fields.
+   *
+   * They are accessed by both the main runtime thread and the newly
+   * created thread that runs the mblock's main loop.
+   */
+  omni_mutex                   d_mutex; 
+  omni_condition               d_state_cond;   //< state change notifications
+  worker_state_t               d_state;
+  cause_of_death_t             d_why_dead;
+
+  mb_worker(mb_runtime_thread_per_block *runtime,
+           mb_mblock_maker_t maker,
+           const std::string &instance_name,
+           pmt_t user_arg);
+
+  // ~mb_worker();
+
+
+  /*!
+   * \brief This code runs as the top-level of the new thread
+   */
+  void worker_thread_top_level();
+  
+  /*!
+   * \brief Invokes the top-level of the new thread (name kind of sucks)
+   */
+  void *run_undetached(void *arg);
+
+private:
+  // Neither d_mutex nor runtime->d_mutex may be held while calling this.
+  // It locks and unlocks them itself.
+  void set_state(worker_state_t state);
+};
+
+
+
+#endif /* INCLUDED_MB_WORKER_H */
index 3138a7e1eb70fee720a35620fc17d32b9127be0f..4174f6d54ce13a56ab96806443d0ac80b2011e7f 100644 (file)
@@ -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(); }
diff --git a/mblock/src/lib/qa_bitset.cc b/mblock/src/lib/qa_bitset.cc
new file mode 100644 (file)
index 0000000..0acda82
--- /dev/null
@@ -0,0 +1,493 @@
+/* -*- 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_start = pmt_intern("start");
+static pmt_t s_send_batch = pmt_intern("send-batch");
+static pmt_t s_long0 = pmt_from_long(0);
+
+static std::string
+str(long x)
+{
+  std::ostringstream s;
+  s << x;
+  return s.str();
+}
+
+/*!
+ * \brief mblock used for QA.
+ *
+ * Messages arriving on "in" consist of a pair containing a (long)
+ * message number in the car, and a (long) bitmap in the cdr.  For
+ * each message received on "in", a new message is sent on "out".  The
+ * new message is the same format as the input, but the bitmap in
+ * the cdr has a "1" or'd into it that corresponds to the bit number
+ * specified in the constructor.
+ *
+ * The bitmap can be used by the ultimate receiver to confirm
+ * traversal of a set of blocks, if the blocks are assigned unique bit
+ * numbers.
+ */
+class qa_bitset : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+  int          d_bitno;
+
+public:
+  qa_bitset(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  void handle_message(mb_message_sptr msg);
+};
+
+qa_bitset::qa_bitset(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_bitno = pmt_to_long(user_arg);     // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::EXTERNAL);
+  d_out = define_port("out", "qa-bitset", true, mb_port::EXTERNAL);
+}
+
+void
+qa_bitset::handle_message(mb_message_sptr msg)
+{
+  if (pmt_eq(msg->port_id(), s_in) && pmt_eq(msg->signal(), s_data)){
+    d_out->send(s_data,
+               pmt_cons(pmt_car(msg->data()),
+                        pmt_from_long((1L << d_bitno) | pmt_to_long(pmt_cdr(msg->data())))));
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset);
+
+// ------------------------------------------------------------------------
+
+/*!
+ * \brief mblock used for QA.  Compose two qa_bitset mblocks.
+ */
+class qa_bitset2 : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+
+public:
+  qa_bitset2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+};
+
+qa_bitset2::qa_bitset2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  long bitno = pmt_to_long(user_arg);  // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+
+  define_component("bs0", "qa_bitset", pmt_from_long(bitno));
+  define_component("bs1", "qa_bitset", pmt_from_long(bitno + 1));
+  connect("self", "in", "bs0", "in");
+  connect("bs0", "out", "bs1", "in");
+  connect("bs1", "out", "self", "out");
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset2);
+
+// ------------------------------------------------------------------------
+
+/*!
+ * \brief mblock used for QA.  Compose two qa_bitset2 mblocks.
+ */
+class qa_bitset4 : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+
+public:
+  qa_bitset4(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+};
+
+qa_bitset4::qa_bitset4(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  long bitno = pmt_to_long(user_arg);  // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+
+  define_component("bs0", "qa_bitset2", pmt_from_long(bitno));
+  define_component("bs1", "qa_bitset2", pmt_from_long(bitno + 2));
+  connect("self", "in", "bs0", "in");
+  connect("bs0", "out", "bs1", "in");
+  connect("bs1", "out", "self", "out");
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset4);
+
+// ------------------------------------------------------------------------
+
+/*!
+ * \brief mblock used for QA.  Compose two qa_bitset4 mblocks.
+ */
+class qa_bitset8 : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+
+public:
+  qa_bitset8(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+};
+
+qa_bitset8::qa_bitset8(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  long bitno = pmt_to_long(user_arg);  // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+
+  define_component("bs0", "qa_bitset4", pmt_from_long(bitno));
+  define_component("bs1", "qa_bitset4", pmt_from_long(bitno + 4));
+  connect("self", "in", "bs0", "in");
+  connect("bs0", "out", "bs1", "in");
+  connect("bs1", "out", "self", "out");
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset8);
+
+// ------------------------------------------------------------------------
+
+/*!
+ * \brief mblock used for QA.  Compose two qa_bitset8 mblocks.
+ */
+class qa_bitset16 : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+
+public:
+  qa_bitset16(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+};
+
+qa_bitset16::qa_bitset16(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  long bitno = pmt_to_long(user_arg);  // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+
+  define_component("bs0", "qa_bitset8", pmt_from_long(bitno));
+  define_component("bs1", "qa_bitset8", pmt_from_long(bitno + 8));
+  connect("self", "in", "bs0", "in");
+  connect("bs0", "out", "bs1", "in");
+  connect("bs1", "out", "self", "out");
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset16);
+
+// ------------------------------------------------------------------------
+
+/*!
+ * \brief mblock used for QA.  Compose two qa_bitset16 mblocks.
+ */
+class qa_bitset32 : public mb_mblock
+{
+  mb_port_sptr d_in;
+  mb_port_sptr d_out;
+
+public:
+  qa_bitset32(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+};
+
+qa_bitset32::qa_bitset32(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  long bitno = pmt_to_long(user_arg);  // The bit we are to set
+
+  d_in  = define_port("in", "qa-bitset", false, mb_port::RELAY);
+  d_out = define_port("out", "qa-bitset", true, mb_port::RELAY);
+
+  define_component("bs0", "qa_bitset16", pmt_from_long(bitno));
+  define_component("bs1", "qa_bitset16", pmt_from_long(bitno + 16));
+  connect("self", "in", "bs0", "in");
+  connect("bs0", "out", "bs1", "in");
+  connect("bs1", "out", "self", "out");
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset32);
+
+// ------------------------------------------------------------------------
+
+class qa_bitset_src : public mb_mblock
+{
+  mb_port_sptr d_cs_top;
+  mb_port_sptr d_cs;
+  
+  mb_port_sptr d_out;
+
+  long         d_msg_number;           // starting message number
+  long         d_nmsgs_to_send;        // # of messages to send
+  long         d_batch_size;           // # of messages to send per batch
+  
+public:
+  qa_bitset_src(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  void handle_message(mb_message_sptr msg);
+
+protected:
+  void send_one();
+  void send_batch();
+};
+
+qa_bitset_src::qa_bitset_src(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_msg_number    = pmt_to_long(pmt_nth(0, user_arg));
+  d_nmsgs_to_send = pmt_to_long(pmt_nth(1, user_arg));
+  d_batch_size    = pmt_to_long(pmt_nth(2, user_arg));
+
+  d_cs_top = define_port("cs_top", "qa-bitset-cs", true, mb_port::EXTERNAL);
+  d_cs = define_port("cs", "qa-bitset-cs", true, mb_port::EXTERNAL);
+
+  d_out = define_port("out", "qa-bitset", true, mb_port::EXTERNAL);
+}
+
+void
+qa_bitset_src::handle_message(mb_message_sptr msg)
+{
+  if ((pmt_eq(msg->port_id(), d_cs_top->port_symbol())
+       || pmt_eq(msg->port_id(), d_cs->port_symbol()))
+      && pmt_eq(msg->signal(), s_send_batch)){
+    send_batch();
+  }
+}
+
+void
+qa_bitset_src::send_batch()
+{
+  for (int i = 0; i < d_batch_size; i++)
+    send_one();
+}
+
+void
+qa_bitset_src::send_one()
+{
+  if (d_nmsgs_to_send > 0){
+    pmt_t msg_number = pmt_from_long(d_msg_number++);
+    d_out->send(s_data, pmt_cons(msg_number, s_long0));
+  }
+  if (--d_nmsgs_to_send <= 0)
+    exit();
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset_src);
+
+// ------------------------------------------------------------------------
+
+class qa_bitset_sink : public mb_mblock
+{
+  // Maximum number of messages we can track
+  static const size_t MAX_MSGS = 1 * 1024 * 1024; 
+  
+  mb_port_sptr d_cs0;
+  mb_port_sptr d_cs1;
+  mb_port_sptr d_cs2;
+  mb_port_sptr d_cs3;
+  
+  mb_port_sptr d_in0;
+  mb_port_sptr d_in1;
+  mb_port_sptr d_in2;
+  mb_port_sptr d_in3;
+
+  long                 d_nmsgs_to_recv; // # of messages to receive
+  long                 d_batch_size;    // # of messages to receive per batch
+  uint32_t             d_expected_mask;
+
+  std::bitset<MAX_MSGS>        d_bitset;
+  long                 d_nrecvd;
+  
+public:
+  qa_bitset_sink(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  void handle_message(mb_message_sptr msg);
+
+protected:
+  void receive_one(mb_message_sptr msg);
+};
+
+qa_bitset_sink::qa_bitset_sink(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_nrecvd(0)
+{
+  d_nmsgs_to_recv = pmt_to_long(pmt_nth(0, user_arg));
+  d_batch_size    = pmt_to_long(pmt_nth(1, user_arg));
+  d_expected_mask = pmt_to_long(pmt_nth(2, user_arg));
+
+  if (d_nmsgs_to_recv > (long) MAX_MSGS)
+    throw std::out_of_range("qa_bitset_sink: nmsgs_to_recv is too big");
+
+  if (d_batch_size < 1)
+    throw std::out_of_range("qa_bitset_sink: batch_size must be >= 1");
+
+  d_cs0 = define_port("cs0", "qa-bitset-cs", true, mb_port::EXTERNAL);
+  d_cs1 = define_port("cs1", "qa-bitset-cs", true, mb_port::EXTERNAL);
+  d_cs2 = define_port("cs2", "qa-bitset-cs", true, mb_port::EXTERNAL);
+  d_cs3 = define_port("cs3", "qa-bitset-cs", true, mb_port::EXTERNAL);
+
+  d_in0 = define_port("in0", "qa-bitset", false, mb_port::EXTERNAL);
+  d_in1 = define_port("in1", "qa-bitset", false, mb_port::EXTERNAL);
+  d_in2 = define_port("in2", "qa-bitset", false, mb_port::EXTERNAL);
+  d_in3 = define_port("in3", "qa-bitset", false, mb_port::EXTERNAL);
+}
+
+void
+qa_bitset_sink::handle_message(mb_message_sptr msg)
+{
+  if ((pmt_eq(msg->port_id(), d_in0->port_symbol())
+       || pmt_eq(msg->port_id(), d_in1->port_symbol())
+       || pmt_eq(msg->port_id(), d_in2->port_symbol())
+       || pmt_eq(msg->port_id(), d_in3->port_symbol()))
+      && pmt_eq(msg->signal(), s_data)){
+
+    receive_one(msg);
+  }
+}
+
+void
+qa_bitset_sink::receive_one(mb_message_sptr msg)
+{
+  long msg_number = pmt_to_long(pmt_car(msg->data()));
+  uint32_t mask = pmt_to_long(pmt_cdr(msg->data()));
+
+  // std::cout << msg->data() << std::endl;
+
+  d_nrecvd++;
+  if (d_nrecvd % d_batch_size == d_batch_size - 1){
+    d_cs0->send(s_send_batch);
+    d_cs1->send(s_send_batch);
+    d_cs2->send(s_send_batch);
+    d_cs3->send(s_send_batch);
+  }
+
+  if (msg_number >= d_nmsgs_to_recv){
+    std::cerr << "qa_bitset_sink::receive_one: msg_number too big ("
+             << msg_number << ")\n";
+    shutdown_all(PMT_F);
+    return;
+  }
+  if (mask != d_expected_mask){
+    fprintf(stderr,
+           "qa_bitset_sink::receive_one: Wrong mask.  Expected 0x%08x, got 0x%08x\n",
+           d_expected_mask, mask);
+    shutdown_all(PMT_F);
+    return;
+  }
+
+  if (d_bitset.test((size_t) msg_number)){
+    std::cerr << "qa_bitset_sink::receive_one: duplicate msg_number ("
+             << msg_number << ")\n";
+    shutdown_all(PMT_F);
+    return;
+  }
+
+  d_bitset.set((size_t) msg_number);
+  if (d_nrecvd == d_nmsgs_to_recv)
+    shutdown_all(PMT_T);               // we're done!
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset_sink);
+
+// ------------------------------------------------------------------------
+
+class qa_bitset_top : public mb_mblock
+{
+  static const int NPIPES = 4;
+
+  std::vector<mb_port_sptr>    d_cs;
+  
+  long                 d_nmsgs;         // # of messages to send
+  long                 d_batch_size;    // # of messages to receive per batch
+
+public:
+  qa_bitset_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  void initial_transition();
+};
+
+qa_bitset_top::qa_bitset_top(mb_runtime *runtime,
+                            const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_nmsgs      = pmt_to_long(pmt_nth(0, user_arg));
+  d_nmsgs = (d_nmsgs / NPIPES) * NPIPES;
+  d_batch_size = pmt_to_long(pmt_nth(1, user_arg));
+
+  /*
+   * We build NPIPES sources which feed NPIPES pipelines, each of which
+   * consists of 8-mblocks.  All pipelines feed into a single sink
+   * which keeps track the results.
+   */
+  for (int i = 0; i < NPIPES; i++){
+    d_cs.push_back(define_port("cs"+str(i), "qa-bitset-cs", false, mb_port::INTERNAL));
+  
+    // sources of test messages
+    define_component("src"+str(i), "qa_bitset_src",
+                    pmt_list3(pmt_from_long(i * d_nmsgs/NPIPES),
+                              pmt_from_long(d_nmsgs/NPIPES),
+                              pmt_from_long(d_batch_size)));
+
+    // 8-mblock processing pipelines
+    define_component("pipeline"+str(i), "qa_bitset8", pmt_from_long(0));
+  }
+
+  // sink for output of pipelines
+  define_component("sink", "qa_bitset_sink",
+                  pmt_list3(pmt_from_long(d_nmsgs),
+                            pmt_from_long(d_batch_size * NPIPES),
+                            pmt_from_long(0x000000ff)));
+
+  for (int i = 0; i < NPIPES; i++){
+    connect("self", "cs"+str(i), "src"+str(i), "cs_top");
+    connect("src"+str(i), "out", "pipeline"+str(i), "in");
+    connect("src"+str(i), "cs", "sink", "cs"+str(i));
+    connect("pipeline"+str(i), "out", "sink", "in"+str(i));
+  }
+}
+
+void
+qa_bitset_top::initial_transition()
+{
+  for (int i = 0; i < NPIPES; i++){
+    d_cs[i]->send(s_send_batch);       // prime the pump
+    d_cs[i]->send(s_send_batch);
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_bitset_top);
diff --git a/mblock/src/lib/qa_bitset.mbh b/mblock/src/lib/qa_bitset.mbh
new file mode 100644 (file)
index 0000000..0b2df00
--- /dev/null
@@ -0,0 +1,61 @@
+;; -*- scheme -*- ; not really, but tells emacs how to format this
+;;
+;; Copyright 2007 Free Software Foundation, Inc.
+;; 
+;; This file is part of GNU Radio
+;; 
+;; GNU Radio is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;; 
+;; GNU Radio is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;; 
+;; You should have received a copy of the GNU General Public License along
+;; with this program; if not, write to the Free Software Foundation, Inc.,
+;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;
+
+;; ----------------------------------------------------------------
+;; qa-bitset -- interface to mblock QA code
+;;
+
+(define-protocol-class qa-bitset
+
+  (:incoming
+
+   (data n bitmask)
+
+   )
+  )
+
+(define-protocol-class qa-bitset-cs
+
+  (:outgoing
+
+   (send-batch)
+
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; qa-disconnect -- interface to mblock QA code
+;;
+
+(define-protocol-class qa-disconnect-cs
+
+  (:outgoing
+
+   (select-pipe n)
+
+   )
+
+  (:incoming
+
+   (ack n)
+
+   )
+  )
diff --git a/mblock/src/lib/qa_disconnect.cc b/mblock/src/lib/qa_disconnect.cc
new file mode 100644 (file)
index 0000000..cde8d6e
--- /dev/null
@@ -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);
index 4be4a23c3c02f1bf8d4085af9627338e44c0b2df..cf422454481da2ffa928a6cbf64d7782f89ec548 100644 (file)
@@ -27,6 +27,8 @@
 #include <qa_mblock.h>
 #include <qa_mblock_prims.h>
 #include <qa_mblock_send.h>
+#include <qa_mblock_sys.h>
+#include <qa_timeouts.h>
 
 CppUnit::TestSuite *
 qa_mblock::suite()
@@ -35,6 +37,8 @@ qa_mblock::suite()
 
   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;
 }
index 79ed5a21e278339c829911c131d41635d249a614..2995215fbb83a2b360355a0bfe330456def9ed89 100644 (file)
@@ -34,6 +34,7 @@
 #include <mb_message.h>
 #include <mb_mblock_impl.h>
 #include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
 #include <stdio.h>
 
 static pmt_t s_cs = pmt_intern("cs");
@@ -47,42 +48,49 @@ static pmt_t s_out = pmt_intern("out");
 class dp_1 : public mb_mblock
 {
 public:
-  dp_1();
+  dp_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_1();
 };
 
-dp_1::dp_1()
+dp_1::dp_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
 }
 
 dp_1::~dp_1(){}
 
+REGISTER_MBLOCK_CLASS(dp_1);
+
 // ----------------------------------------------------------------
 
 class dp_2 : public mb_mblock
 {
 public:
-  dp_2();
+  dp_2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_2();
 };
 
-dp_2::dp_2()
+dp_2::dp_2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
 }
 
 dp_2::~dp_2(){}
 
+REGISTER_MBLOCK_CLASS(dp_2);
+
 // ----------------------------------------------------------------
 
 class dp_3 : public mb_mblock
 {
 public:
-  dp_3();
+  dp_3(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_3();
 };
 
-dp_3::dp_3()
+dp_3::dp_3(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);  // duplicate def
@@ -90,19 +98,23 @@ dp_3::dp_3()
 
 dp_3::~dp_3(){}
 
+REGISTER_MBLOCK_CLASS(dp_3);
+
 // ----------------------------------------------------------------
 
 void
 qa_mblock_prims::test_define_ports()
 {
-  // std::vector<mb_port_sptr> intf;
-
-  mb_mblock_sptr       mb1 = mb_mblock_sptr(new dp_1());
-  // intf = mb1->peer_interface();
-  // CPPUNIT_ASSERT_EQUAL(size_t(0), intf.size());
+  
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+  
+  // Should work
+  mb_mblock_sptr  mb1 = mb_mblock_sptr(new dp_1(rt, "top", PMT_F));
 
   // raises runtime_error because of unknown protocol "cs-protocol"
-  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2()), std::runtime_error);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2(rt, "top", PMT_F)),
+                      std::runtime_error);
 
   // define the protocol class
   pmt_t pc = mb_make_protocol_class(pmt_intern("cs-protocol"),
@@ -112,10 +124,11 @@ qa_mblock_prims::test_define_ports()
 
   // std::cout << "pc = " << pc << '\n';
 
-  mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
+  mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2(rt, "top", PMT_F));
 
   // raises pmt_exception because of duplicate port definition of "cs"
-  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3()), mbe_duplicate_port);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3(rt, "top", PMT_F)),
+                      mbe_duplicate_port);
 }
 
 // ================================================================
@@ -123,61 +136,74 @@ qa_mblock_prims::test_define_ports()
 class dc_0 : public mb_mblock
 {
 public:
-  dc_0();
+  dc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dc_0();
 };
 
-dc_0::dc_0()
+dc_0::dc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
 }
 
 dc_0::~dc_0() {}
 
+REGISTER_MBLOCK_CLASS(dc_0);
+
 // ----------------------------------------------------------------
 
 class dc_ok : public mb_mblock
 {
 public:
-  dc_ok();
+  dc_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dc_ok();
 };
 
-dc_ok::dc_ok()
+dc_ok::dc_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new dc_0()));
-  define_component("c1", mb_mblock_sptr(new dc_0()));
-  define_component("c2", mb_mblock_sptr(new dc_0()));
+  define_component("c0", "dc_0");
+  define_component("c1", "dc_0");
+  define_component("c2", "dc_0");
 }
 
 dc_ok::~dc_ok(){}
 
+REGISTER_MBLOCK_CLASS(dc_ok);
+
 // ----------------------------------------------------------------
 
 class dc_not_ok : public mb_mblock
 {
 public:
-  dc_not_ok();
+  dc_not_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dc_not_ok();
 };
 
-dc_not_ok::dc_not_ok()
-  : mb_mblock()
+dc_not_ok::dc_not_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new dc_0()));
-  define_component("c0", mb_mblock_sptr(new dc_0()));  // duplicate name
+  define_component("c0", "dc_0");
+  define_component("c0", "dc_0");      // duplicate name
 }
 
 dc_not_ok::~dc_not_ok(){}
 
+REGISTER_MBLOCK_CLASS(dc_not_ok);
+
 // ----------------------------------------------------------------
 
 void
 qa_mblock_prims::test_define_components()
 {
-  mb_mblock_sptr       mb1 = mb_mblock_sptr(new dc_ok());      // OK
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+  
+  // Should work
+  mb_mblock_sptr  mb1 = mb_mblock_sptr(new dc_ok(rt, "top", PMT_F));
 
   // raises pmt_exception because of duplicate component definition of "c0"
-  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok()), mbe_duplicate_component);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok(rt, "top", PMT_F)),
+                      mbe_duplicate_component);
 }
 
 // ================================================================
@@ -185,7 +211,9 @@ qa_mblock_prims::test_define_components()
 class tc_norm : public mb_mblock
 {
 public:
-  tc_norm(){
+  tc_norm(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
     define_port("data", "i/o", false, mb_port::EXTERNAL);
     define_port("norm", "i/o", false, mb_port::EXTERNAL);
     define_port("conj", "i/o", true,  mb_port::EXTERNAL);
@@ -197,22 +225,26 @@ public:
 
 tc_norm::~tc_norm(){}
 
+REGISTER_MBLOCK_CLASS(tc_norm);
+
 ////////////////////////////////////////////////////////////////
 
 class tc_0 : public mb_mblock
 {
 public:
-  tc_0(){
+  tc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
     define_port("norm", "i/o", false, mb_port::EXTERNAL);
     define_port("conj", "i/o", true,  mb_port::EXTERNAL);
     define_port("int",  "i/o", false, mb_port::INTERNAL);
 
-    define_component("c0", mb_mblock_sptr(new tc_norm()));
-    define_component("c1", mb_mblock_sptr(new tc_norm()));
-    define_component("c2", mb_mblock_sptr(new tc_norm()));
-    define_component("c3", mb_mblock_sptr(new tc_norm()));
-    define_component("c4", mb_mblock_sptr(new tc_norm()));
-    define_component("c5", mb_mblock_sptr(new tc_norm()));
+    define_component("c0", "tc_norm");
+    define_component("c1", "tc_norm");
+    define_component("c2", "tc_norm");
+    define_component("c3", "tc_norm");
+    define_component("c4", "tc_norm");
+    define_component("c5", "tc_norm");
 
     // OK
     connect("c0", "norm", "c1", "conj");
@@ -284,14 +316,18 @@ public:
 
 tc_0::~tc_0(){}
 
+REGISTER_MBLOCK_CLASS(tc_0);
+
 ////////////////////////////////////////////////////////////////
 
 class tc_1 : public mb_mblock
 {
 public:
-  tc_1(){
-    define_component("c0", mb_mblock_sptr(new tc_norm()));
-    define_component("c1", mb_mblock_sptr(new tc_norm()));
+  tc_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
+    define_component("c0", "tc_norm");
+    define_component("c1", "tc_norm");
 
     connect("c0", "norm", "c1", "conj");
   }
@@ -301,6 +337,8 @@ public:
 
 tc_1::~tc_1(){}
 
+REGISTER_MBLOCK_CLASS(tc_1);
+
 ////////////////////////////////////////////////////////////////
 
 void
@@ -315,7 +353,10 @@ qa_mblock_prims::test_connect()
                         pmt_list1(pmt_intern("in")),           // in
                         pmt_list1(pmt_intern("out")));         // out
 
-  mb_mblock_sptr       mb0 = mb_mblock_sptr(new tc_0());
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+
+  mb_mblock_sptr       mb0 = mb_mblock_sptr(new tc_0(rt, "top", PMT_F));
 }
 
 ////////////////////////////////////////////////////////////////
@@ -377,11 +418,14 @@ qa_mblock_prims::test_msg_queue()
 void
 qa_mblock_prims::test_make_accepter()
 {
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+
   // create a block
-  mb_mblock_sptr mb = mb_mblock_sptr(new dp_2());
+  mb_mblock_sptr mb = mb_mblock_sptr(new dp_2(rt, "top", PMT_F));
 
   // use "internal use only" method...
-  mb_msg_accepter_sptr accepter = mb->impl()->make_accepter("cs");
+  mb_msg_accepter_sptr accepter = mb->impl()->make_accepter(pmt_intern("cs"));
 
   // Now push a few messages into it...
   //          signal       data          metadata     pri
index 46d6b6440b2a9b79ce2ff53ca662053beef16e6b..cd81709e2e3094148f1c8b3bf9ba93e21a3a0453 100644 (file)
@@ -35,6 +35,7 @@
 #include <mb_message.h>
 #include <mb_mblock_impl.h>
 #include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
 #include <stdio.h>
 
 static pmt_t s_data    = pmt_intern("data");
@@ -57,6 +58,12 @@ define_protocol_classes()
 
 }
 
+mb_mblock_sptr
+get_top(mb_runtime_sptr rts)
+{
+  return dynamic_cast<mb_runtime_nop *>(rts.get())->top();
+}
+
 // ================================================================
 //                    test_simple_routing
 // ================================================================
@@ -70,12 +77,13 @@ class sr1 : public mb_mblock
   mb_port_sptr d_p3;
 
 public:
-  sr1();
+  sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~sr1();
-  void init_fsm();
+  void initial_transition();
 };
 
-sr1::sr1()
+sr1::sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
   d_p2 = define_port("p2", "qa-send-cs", true, mb_port::EXTERNAL);
@@ -85,9 +93,9 @@ sr1::sr1()
 sr1::~sr1(){}
   
 void
-sr1::init_fsm()
+sr1::initial_transition()
 {
-  // std::cout << instance_name() << "[sr1]: init_fsm\n";
+  // std::cout << instance_name() << "[sr1]: initial_transition\n";
 
   // send two messages to each port
   pmt_t our_name = pmt_intern(instance_name());
@@ -98,6 +106,8 @@ sr1::init_fsm()
   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(1)));
 }
 
+REGISTER_MBLOCK_CLASS(sr1);
+
 // ----------------------------------------------------------------
 
 // top-level container block for test_simple_routing
@@ -106,17 +116,18 @@ class sr0 : public mb_mblock
   mb_port_sptr d_p0;
   
 public:
-  sr0();
+  sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~sr0();
-  void init_fsm();
+  void initial_transition();
 };
 
-sr0::sr0()
+sr0::sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
 
-  define_component("mb1", mb_mblock_sptr(new sr1()));
-  define_component("mb2", mb_mblock_sptr(new sr1()));
+  define_component("mb1", "sr1");
+  define_component("mb2", "sr1");
 
   connect("self", "p0", "mb1", "p1");
   connect("mb1", "p2", "mb2", "p3");
@@ -126,9 +137,9 @@ sr0::sr0()
 sr0::~sr0(){}
 
 void
-sr0::init_fsm()
+sr0::initial_transition()
 {
-  // std::cout << instance_name() << "[sr0]: init_fsm\n";
+  // std::cout << instance_name() << "[sr0]: initial_transition\n";
 
   // send two messages to p0
   pmt_t our_name = pmt_intern(instance_name());
@@ -136,6 +147,8 @@ sr0::init_fsm()
   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(1)));
 }
   
+REGISTER_MBLOCK_CLASS(sr0);
+
 // ----------------------------------------------------------------
 
 /*
@@ -151,9 +164,10 @@ qa_mblock_send::test_simple_routing()
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr mb0 = mb_mblock_sptr(new sr0());
-  rt->run(mb0);
+  rt->run("top", "sr0", PMT_F);
 
+  mb_mblock_sptr mb0 = get_top(rt);
+  
   // Reach into the guts and see if the messages ended up where they should have
 
   // mb0 should have received two messages sent from mb1 via its p1
@@ -238,12 +252,13 @@ class rr2 : public mb_mblock
   mb_port_sptr d_p2;
 
 public:
-  rr2();
+  rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr2();
-  void init_fsm();
+  void initial_transition();
 };
 
-rr2::rr2()
+rr2::rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::EXTERNAL);
   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::EXTERNAL);
@@ -252,9 +267,9 @@ rr2::rr2()
 rr2::~rr2(){}
   
 void
-rr2::init_fsm()
+rr2::initial_transition()
 {
-  // std::cout << instance_name() << "[rr2]: init_fsm\n";
+  // std::cout << instance_name() << "[rr2]: initial_transition\n";
 
   // send two messages via p1
   pmt_t our_name = pmt_intern(instance_name());
@@ -262,6 +277,8 @@ rr2::init_fsm()
   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
 }
 
+REGISTER_MBLOCK_CLASS(rr2);
+
 // ----------------------------------------------------------------
 
 // intermediate block for test_relay_routing
@@ -272,16 +289,17 @@ class rr1 : public mb_mblock
   mb_port_sptr d_p2;
 
 public:
-  rr1();
+  rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr1();
 };
 
-rr1::rr1()
+rr1::rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::RELAY);
   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::RELAY);
 
-  define_component("c0", mb_mblock_sptr(new rr2()));
+  define_component("c0", "rr2");
 
   connect("self", "p1", "c0", "p1");
   connect("self", "p2", "c0", "p2");
@@ -289,6 +307,8 @@ rr1::rr1()
 
 rr1::~rr1(){}
 
+REGISTER_MBLOCK_CLASS(rr1);
+
 // ----------------------------------------------------------------
 
 // top-level container for test_relay_routing
@@ -296,14 +316,15 @@ rr1::~rr1(){}
 class rr0_a : public mb_mblock
 {
 public:
-  rr0_a();
+  rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr0_a();
 };
 
-rr0_a::rr0_a()
+rr0_a::rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new rr1()));
-  define_component("c1", mb_mblock_sptr(new rr2()));
+  define_component("c0", "rr1");
+  define_component("c1", "rr2");
 
   connect("c0", "p1", "c1", "p2");
   connect("c0", "p2", "c1", "p1");
@@ -311,6 +332,7 @@ rr0_a::rr0_a()
 
 rr0_a::~rr0_a(){}
 
+REGISTER_MBLOCK_CLASS(rr0_a);
 
 /*
  * This tests basic message routing using RELAY and EXTERNAL ports.
@@ -323,8 +345,8 @@ qa_mblock_send::test_relay_routing_1()
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr  top = mb_mblock_sptr(new rr0_a());
-  rt->run(top);
+  rt->run("top", "rr0_a", PMT_F);
+  mb_mblock_sptr top = get_top(rt);
 
   // Reach into the guts and see if the messages ended up where they should have
 
@@ -377,14 +399,15 @@ qa_mblock_send::test_relay_routing_1()
 class rr0_b : public mb_mblock
 {
 public:
-  rr0_b();
+  rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr0_b();
 };
 
-rr0_b::rr0_b()
+rr0_b::rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new rr1()));
-  define_component("c1", mb_mblock_sptr(new rr1()));
+  define_component("c0", "rr1");
+  define_component("c1", "rr1");
 
   connect("c0", "p1", "c1", "p2");
   connect("c0", "p2", "c1", "p1");
@@ -392,6 +415,7 @@ rr0_b::rr0_b()
 
 rr0_b::~rr0_b(){}
 
+REGISTER_MBLOCK_CLASS(rr0_b);
 
 /*
  * This tests basic message routing using RELAY and EXTERNAL ports.
@@ -404,8 +428,8 @@ qa_mblock_send::test_relay_routing_2()
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr  top = mb_mblock_sptr(new rr0_b());
-  rt->run(top);
+  rt->run("top", "rr0_b", PMT_F);
+  mb_mblock_sptr top = get_top(rt);
 
   // Reach into the guts and see if the messages ended up where they should have
 
diff --git a/mblock/src/lib/qa_mblock_sys.cc b/mblock/src/lib/qa_mblock_sys.cc
new file mode 100644 (file)
index 0000000..a64f546
--- /dev/null
@@ -0,0 +1,271 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qa_mblock_sys.h>
+#include <cppunit/TestAssert.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+
+
+static pmt_t s_data    = pmt_intern("data");
+static pmt_t s_status  = pmt_intern("status");
+static pmt_t s_control = pmt_intern("control");
+static pmt_t s_p0   = pmt_intern("p0");
+static pmt_t s_p1   = pmt_intern("p1");
+static pmt_t s_p2   = pmt_intern("p2");
+static pmt_t s_p3   = pmt_intern("p3");
+static pmt_t s_e1   = pmt_intern("e1");
+static pmt_t s_r1   = pmt_intern("r1");
+
+static void
+define_protocol_classes()
+{
+  mb_make_protocol_class(s_data,               // name
+                        pmt_list1(s_data),     // incoming
+                        pmt_list1(s_data));    // outgoing
+}
+
+
+// ================================================================
+//                       test_sys_1
+// ================================================================
+
+class sys_1 : public mb_mblock
+{
+  pmt_t                d_user_arg;
+  mb_port_sptr d_data;
+
+public:
+  sys_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~sys_1();
+  void initial_transition();
+};
+
+sys_1::sys_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_user_arg(user_arg)
+{
+  d_data = define_port("data", "data", true, mb_port::EXTERNAL);
+}
+
+sys_1::~sys_1(){}
+  
+void
+sys_1::initial_transition()
+{
+  shutdown_all(d_user_arg);
+}
+
+REGISTER_MBLOCK_CLASS(sys_1);
+
+void
+qa_mblock_sys::test_sys_1()
+{
+  define_protocol_classes();
+
+  pmt_t        result;
+  pmt_t        n1 = pmt_from_long(1);
+  pmt_t        n2 = pmt_from_long(2);
+
+  mb_runtime_sptr rt1 = mb_make_runtime();
+
+#if 0
+  try {
+    rt1->run("top-1", "sys_1", n1, &result);
+  }
+  catch (omni_thread_fatal e){
+    std::cerr << "caught omni_thread_fatal: error = " << e.error
+             << ": " << strerror(e.error) << std::endl;
+  }
+  catch (omni_thread_invalid){
+    std::cerr << "caught omni_thread_invalid\n";
+  }
+#else
+    rt1->run("top-1", "sys_1", n1, &result);
+#endif
+  CPPUNIT_ASSERT(pmt_equal(n1, result));
+  
+  // Execute run a second time, with the same rt, to ensure sanity.
+  rt1->run("top-2", "sys_1", n2, &result);
+  CPPUNIT_ASSERT(pmt_equal(n2, result));
+}
+
+// ================================================================
+//                       test_sys_2
+// ================================================================
+
+class squarer : public mb_mblock
+{
+  mb_port_sptr d_data;
+
+public:
+  squarer(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+
+  void handle_message(mb_message_sptr msg);
+};
+
+squarer::squarer(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_data = define_port("data", "data", true, mb_port::EXTERNAL);
+}
+
+void
+squarer::handle_message(mb_message_sptr msg)
+{
+  if (!pmt_eq(msg->signal(), s_data))  // we only handle the "data" message
+    return;
+
+  // long x -> (long x . long (x * x))
+
+  pmt_t x_pmt = msg->data();
+  long x = pmt_to_long(x_pmt);
+  d_data->send(s_data, pmt_cons(x_pmt, pmt_from_long(x * x)));
+}
+
+REGISTER_MBLOCK_CLASS(squarer);
+
+// ----------------------------------------------------------------
+
+class sys_2 : public mb_mblock
+{
+  mb_port_sptr d_data;
+
+public:
+  sys_2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+};
+
+sys_2::sys_2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{
+  d_data = define_port("data", "data", true, mb_port::INTERNAL);
+  define_component("squarer", "squarer");
+  connect("self", "data", "squarer", "data");
+}
+
+void
+sys_2::initial_transition()
+{
+  // FIXME start timer to detect general failure
+
+  d_data->send(s_data, pmt_from_long(0)); // send initial message
+}
+
+void
+sys_2::handle_message(mb_message_sptr msg)
+{
+  if (!pmt_eq(msg->signal(), s_data))  // we only handle the "data" message
+    return;
+
+  // first check correctness of message
+
+  long x = pmt_to_long(pmt_car(msg->data()));
+  long y = pmt_to_long(pmt_cdr(msg->data()));
+
+  // std::cout << msg->data() << std::endl;
+
+  if (y != x * x){
+    std::cerr << "sys_2::handle_message: Expected y == x * x.  Got y = "
+             << y << " for x = " << x << std::endl;
+
+    shutdown_all(PMT_F);       // failed
+  }
+
+  if (x == 100)
+    shutdown_all(PMT_T);                       // done, OK
+  else 
+    d_data->send(s_data, pmt_from_long(x + 1));        // send next request
+}
+
+REGISTER_MBLOCK_CLASS(sys_2);
+
+// ----------------------------------------------------------------
+
+void
+qa_mblock_sys::test_sys_2()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  // std::cerr << "qa_mblock_sys::test_sys_2 (enter)\n";
+  
+  rt->run("top-sys-2", "sys_2", PMT_F, &result);
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+// ================================================================
+//                       test_bitset_1
+// ================================================================
+
+void
+qa_mblock_sys::test_bitset_1()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_NIL;
+
+  long nmsgs =        1000;
+  long batch_size =      8;
+  
+  pmt_t arg = pmt_list2(pmt_from_long(nmsgs),  // # of messages to send through pipe
+                       pmt_from_long(batch_size));
+
+  rt->run("top", "qa_bitset_top", arg, &result);
+
+  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));
+}
diff --git a/mblock/src/lib/qa_mblock_sys.h b/mblock/src/lib/qa_mblock_sys.h
new file mode 100644 (file)
index 0000000..8733381
--- /dev/null
@@ -0,0 +1,45 @@
+/* -*- 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_MBLOCK_SYS_H
+#define INCLUDED_QA_MBLOCK_SYS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_mblock_sys : public CppUnit::TestCase {
+
+  CPPUNIT_TEST_SUITE(qa_mblock_sys);
+  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 */
+
diff --git a/mblock/src/lib/qa_timeouts.cc b/mblock/src/lib/qa_timeouts.cc
new file mode 100644 (file)
index 0000000..4439b6e
--- /dev/null
@@ -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");
+
+
+// ------------------------------------------------------------------------
+//    Exercise the priority queue used 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));
+}
diff --git a/mblock/src/lib/qa_timeouts.h b/mblock/src/lib/qa_timeouts.h
new file mode 100644 (file)
index 0000000..736c4c2
--- /dev/null
@@ -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 */
+
diff --git a/mblock/src/scheme/Makefile.am b/mblock/src/scheme/Makefile.am
new file mode 100644 (file)
index 0000000..7700a1f
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+SUBDIRS = gnuradio
diff --git a/mblock/src/scheme/gnuradio/Makefile.am b/mblock/src/scheme/gnuradio/Makefile.am
new file mode 100644 (file)
index 0000000..f217f68
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# 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.
+#
diff --git a/mblock/src/scheme/gnuradio/compile-mbh.scm b/mblock/src/scheme/gnuradio/compile-mbh.scm
new file mode 100755 (executable)
index 0000000..fbad90d
--- /dev/null
@@ -0,0 +1,231 @@
+#!/usr/bin/guile \
+-e main -s
+!#
+;; -*-scheme-*-
+;;
+;; 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.
+;;
+
+;; usage: compile-mbh <input-file> <output-file>
+
+(use-modules (ice-9 getopt-long))
+(use-modules (ice-9 format))
+(use-modules (ice-9 pretty-print))
+;(use-modules (ice-9 slib))
+(use-modules (gnuradio pmt-serialize))
+(use-modules (gnuradio macros-etc))
+
+(debug-enable 'backtrace)
+
+;; ----------------------------------------------------------------
+
+(define (main args)
+
+  (define (usage)
+    (format 0 "usage: ~a input-file output-file~%" (car args)))
+
+  (when (not (= (length args) 3))
+       (usage)
+       (exit 1))
+      
+  (let ((input-filename (cadr args))
+       (output-filename (caddr args)))
+      (if (compile-mbh-file input-filename output-filename)
+         (exit 0)
+         (exit 1))))
+
+
+;; ----------------------------------------------------------------
+;; constructor and accessors for protocol-class
+
+(define %protocol-class-tag (string->symbol "[PROTOCOL-CLASS-TAG]"))
+
+(define (make-protocol-class name incoming outgoing)
+  (vector %protocol-class-tag name incoming outgoing))
+
+(define (protocol-class? obj)
+  (and (vector? obj) (eq? %protocol-class-tag (vector-ref obj 0))))
+
+(define (protocol-class-name pc)
+  (vector-ref pc 1))
+
+(define (protocol-class-incoming pc)
+  (vector-ref pc 2))
+
+(define (protocol-class-outgoing pc)
+  (vector-ref pc 3))
+
+
+;; ----------------------------------------------------------------
+
+(define (syntax-error msg e)
+  (throw 'syntax-error msg e))
+
+(define (unrecognized-form form)
+  (syntax-error "Unrecognized form" form))
+
+
+(define (mbh-chk-length= e y n)
+  (cond ((and (null? y)(zero? n))
+        #f)
+        ((null? y)
+         (syntax-error "Expression has too few subexpressions" e))
+        ((atom? y)
+         (syntax-error (if (atom? e)
+                           "List expected"
+                           "Expression ends with `dotted' atom")
+                       e))
+        ((zero? n)
+         (syntax-error "Expression has too many subexpressions" e))
+        (else
+          (mbh-chk-length= e (cdr y) (- n 1)))))
+
+(define (mbh-chk-length>= e y n)
+  (cond ((and (null? y)(< n 1))
+        #f)
+        ((atom? y)
+         (mbh-chk-length= e y -1))
+        (else
+          (mbh-chk-length>= e (cdr y) (- n 1)))))
+
+
+(define (compile-mbh-file input-filename output-filename)
+  (let ((i-port (open-input-file input-filename))
+       (o-port (open-output-file output-filename)))
+
+    (letrec
+      ((protocol-classes '())          ; alist
+
+       (lookup-protocol-class          ; returns protocol-class or #f
+       (lambda (name)
+         (cond ((assq name protocol-classes) => cdr)
+               (else #f))))
+
+       (register-protocol-class
+       (lambda (pc)
+         (set! protocol-classes (acons (protocol-class-name pc)
+                                         pc protocol-classes))
+         pc))
+                                         
+       (parse-top-level-form
+       (lambda (form)
+         (mbh-chk-length>= form form 1)
+         (case (car form)
+           ((define-protocol-class) (parse-define-protocol-class form))
+           (else (syntax-error form)))))
+
+       (parse-define-protocol-class
+       (lambda (form)               
+         (mbh-chk-length>= form form 2)
+           ;; form => (define-protocol-class name
+           ;;           (:include protocol-class-name)
+           ;;           (:incoming list-of-msgs)
+           ;;           (:outgoing list-of-msgs))
+           (let ((name (cadr form))
+                 (incoming '())
+                 (outgoing '()))
+             (if (lookup-protocol-class name)
+                 (syntax-error "Duplicate protocol-class name" name))
+             (for-each
+              (lambda (sub-form)
+                (mbh-chk-length>= sub-form sub-form 1)
+                (case (car sub-form)
+                  ((:include)
+                   (mbh-chk-length>= sub-form sub-form 2)
+                   (cond ((lookup-protocol-class (cadr sub-form)) =>
+                          (lambda (pc)
+                            (set! incoming (append incoming (protocol-class-incoming pc)))
+                            (set! outgoing (append outgoing (protocol-class-outgoing pc)))))
+                         (else
+                          (syntax-error "Unknown protocol-class-name" (cadr sub-form)))))
+                  ((:incoming)
+                   (set! incoming (append incoming (cdr sub-form))))
+                  ((:outgoing)
+                   (set! outgoing (append outgoing (cdr sub-form))))
+                  (else
+                   (unrecognized-form (car sub-form)))))
+              (cddr form))
+             
+             (register-protocol-class (make-protocol-class name incoming outgoing)))))
+
+       ) ; end of bindings
+
+      (for-each-in-file i-port parse-top-level-form)
+
+      ;; generate the output here...
+
+      (letrec ((classes (map cdr protocol-classes))
+              (so-stream (make-serial-output-stream))
+              (format-output-for-c++
+               (lambda (output)
+                 (format o-port "//~%")
+                 (format o-port "// Machine generated by compile-mbh from ~a~%" input-filename)
+                 (format o-port "//~%")
+                 (format o-port "// protocol-classes: ~{~a ~}~%" (map car protocol-classes))
+                 (format o-port "//~%")
+
+                 (format o-port "#include <mb_protocol_class.h>~%")
+                 (format o-port "#include <unistd.h>~%")
+                 (format o-port
+                         "static const char~%protocol_class_init_data[~d] = {~%  "
+                         (length output))
+
+                 (do ((lst output (cdr lst))
+                      (i 0 (+ i 1)))
+                     ((null? lst) #t)
+                   (format o-port "~a, " (car lst))
+                   (when (= 15 (modulo i 16))
+                         (format o-port "~%  ")))
+
+                 (format o-port "~&};~%")
+                 (format o-port "static mb_protocol_class_init _init_(protocol_class_init_data, sizeof(protocol_class_init_data));~%")
+                 )))
+                 
+                 
+       (map (lambda (pc)
+              (let ((obj-to-dump
+                     (list (protocol-class-name pc)                    ; class name
+                           (map car (protocol-class-incoming pc))      ; incoming msg names
+                           (map car (protocol-class-outgoing pc))      ; outgoing msg names
+                           ;;(protocol-class-incoming pc)              ; full incoming msg descriptions
+                           ;;(protocol-class-outgoing pc)              ; full outgoing msg descriptions
+                           ))) 
+                ;;(pretty-print obj-to-dump)  
+                (pmt-serialize obj-to-dump (so-stream 'put-byte))))
+            classes)
+
+       (format-output-for-c++ ((so-stream 'get-output)))
+
+       #t))))
+
+
+(define (make-serial-output-stream)
+  (letrec ((output '())
+          (put-byte
+           (lambda (byte)
+             (set! output (cons byte output))))
+          (get-output
+           (lambda ()
+             (reverse output))))
+    (lambda (key)
+      (case key
+       ((put-byte) put-byte)
+       ((get-output) get-output)
+       (else (error "Unknown key" key))))))
+
index bd916561e1f366057dd7c2ed53cbbe346fbc854c..26e42b0e1ab3cd115c52a398f54961d1321dee45 100644 (file)
@@ -391,11 +391,15 @@ protected:
        // execute the run() or run_undetached() member functions depending on
        // whether start() or start_undetached() is called respectively.
 
+public:
+
     void start_undetached(void);
        // can be used with the above constructor in a derived class to cause
        // the thread to be undetached.  In this case the thread executes the
        // run_undetached member function.
 
+protected:
+
     virtual ~omni_thread(void);
        // destructor cannot be called by user (except via a derived class).
        // Use exit() or cancel() instead. This also means a thread object must
index b82e86df3f26b32efb8d33045b4bb19b3bf0d735..7325166c6ce8da207331db6941bc4b77bbcbe2d5 100644 (file)
 #include <time.h>
 #include <omnithread.h>
 
+#if (PthreadDraftVersion == 0)
+#error "PthreadDraftVersion not defined.  If not sure, define it to 10"
+#endif
+
 #ifdef HAVE_NANOSLEEP
 #undef NoNanoSleep
 #else
 #endif
 #endif
 
+#if 1
 #define DB(x) // x
-//#include <iostream.h> or #include <iostream> if DB is on.
+#else
+#define DB(x) x
+#include <iostream>
+using std::cerr;
+using std::endl;
+#endif
 
 #if (PthreadDraftVersion <= 6)
 #define ERRNO(x) (((x) != 0) ? (errno) : 0)
index bcbab24558b43d41056ed04b6d65850bb7c21f80..df73ba51500b23dc8e56e710d63dbf06f3bc7803 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2004,2006 Free Software Foundation, Inc.
+# Copyright 2006,2007 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -19,4 +19,4 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-SUBDIRS = lib
+SUBDIRS = lib scheme
index a738a16928a5f51763cc29aa8dcad44fc55d82d9..b77f6201bc3b83f7996691ca26459f79d8a5f704 100644 (file)
@@ -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
 
@@ -48,18 +48,22 @@ GENERATED_CC =                              \
 $(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR)
        PYTHONPATH=$(top_srcdir)/pmt/src/lib srcdir=$(srcdir) $(PYTHON) $(srcdir)/generate_unv.py
 
-BUILT_SOURCES = $(GENERATED_H) $(GENERATED_CC)
+pmt_serial_tags.h: $(srcdir)/../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../scheme/gnuradio/pmt-serial-tags.scm
+       $(RUN_GUILE) $(srcdir)/../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../scheme/gnuradio/pmt-serial-tags.scm pmt_serial_tags.h
+
+BUILT_SOURCES = $(GENERATED_H) $(GENERATED_CC) pmt_serial_tags.h
 
 # ----------------------------------------------------------------
 
 EXTRA_DIST =                           \
-       $(CODE_GENERATOR)
-
+       $(CODE_GENERATOR)               
 
 # These are the source files that go into the pmt shared library
 libpmt_la_SOURCES =                    \
        pmt.cc                          \
        pmt_io.cc                       \
+       pmt_pool.cc                     \
+       pmt_serialize.cc                \
        pmt_unv.cc                      
 
 # magic flags
@@ -67,10 +71,13 @@ libpmt_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
 
 # link the library against the c++ standard library
 libpmt_la_LIBADD =                     \
+       $(OMNITHREAD_LA)                \
        -lstdc++                        
 
 include_HEADERS =                      \
-       pmt.h
+       pmt.h                           \
+       pmt_pool.h                      \
+       pmt_serial_tags.h               
 
 noinst_HEADERS =                       \
        $(GENERATED_H)                  \
index cf6547b572f6834a149ae963fc4634e94f354e1b..9378953c149fac087ca6e4b17f0fc8af80b79b9d 100644 (file)
 #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()
 {
@@ -108,25 +135,37 @@ _dict(pmt_t x)
   return dynamic_cast<pmt_dict*>(x.get());
 }
 
+static pmt_any *
+_any(pmt_t x)
+{
+  return dynamic_cast<pmt_any*>(x.get());
+}
+
 ////////////////////////////////////////////////////////////////////////////
-//                           Booleans
+//                           Globals
 ////////////////////////////////////////////////////////////////////////////
 
-const pmt_t PMT_BOOL_T = pmt_t(new pmt_bool());                // singleton
-const pmt_t PMT_BOOL_F = pmt_t(new pmt_bool());                // singleton
+const pmt_t PMT_T = pmt_t(new pmt_bool());             // singleton
+const pmt_t PMT_F = pmt_t(new pmt_bool());             // singleton
+const pmt_t PMT_NIL = pmt_t(new pmt_null());           // singleton
+const pmt_t PMT_EOF = pmt_cons(PMT_NIL, PMT_NIL);      // singleton
+
+////////////////////////////////////////////////////////////////////////////
+//                           Booleans
+////////////////////////////////////////////////////////////////////////////
 
 pmt_bool::pmt_bool(){}
 
 bool
 pmt_is_true(pmt_t obj)
 {
-  return obj != PMT_BOOL_F;
+  return obj != PMT_F;
 }
 
 bool
 pmt_is_false(pmt_t obj)
 {
-  return obj == PMT_BOOL_F;
+  return obj == PMT_F;
 }
 
 bool
@@ -138,15 +177,15 @@ pmt_is_bool(pmt_t obj)
 pmt_t
 pmt_from_bool(bool val)
 {
-  return val ? PMT_BOOL_T : PMT_BOOL_F;
+  return val ? PMT_T : PMT_F;
 }
 
 bool
 pmt_to_bool(pmt_t val)
 {
-  if (val == PMT_BOOL_T)
+  if (val == PMT_T)
     return true;
-  if (val == PMT_BOOL_F)
+  if (val == PMT_F)
     return false;
   throw pmt_wrong_type("pmt_to_bool", val);
 }
@@ -167,7 +206,7 @@ hash_string(const std::string &s)
   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){
@@ -322,8 +361,6 @@ pmt_to_complex(pmt_t x)
 //                              Pairs
 ////////////////////////////////////////////////////////////////////////////
 
-const pmt_t PMT_NIL = pmt_t(new pmt_null());           // singleton
-
 pmt_null::pmt_null() {}
 pmt_pair::pmt_pair(pmt_t car, pmt_t cdr) : d_car(car), d_cdr(cdr) {}
 
@@ -598,6 +635,40 @@ pmt_dict_values(pmt_t dict)
   return _dict(dict)->values();
 }
 
+////////////////////////////////////////////////////////////////////////////
+//                                 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
 ////////////////////////////////////////////////////////////////////////////
@@ -689,14 +760,14 @@ pmt_assq(pmt_t obj, pmt_t alist)
   while (pmt_is_pair(alist)){
     pmt_t p = pmt_car(alist);
     if (!pmt_is_pair(p))       // malformed alist
-      return PMT_BOOL_F;
+      return PMT_F;
 
     if (pmt_eq(obj, pmt_car(p)))
       return p;
 
     alist = pmt_cdr(alist);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 pmt_t
@@ -705,14 +776,14 @@ pmt_assv(pmt_t obj, pmt_t alist)
   while (pmt_is_pair(alist)){
     pmt_t p = pmt_car(alist);
     if (!pmt_is_pair(p))       // malformed alist
-      return PMT_BOOL_F;
+      return PMT_F;
 
     if (pmt_eqv(obj, pmt_car(p)))
       return p;
 
     alist = pmt_cdr(alist);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 pmt_t
@@ -721,14 +792,14 @@ pmt_assoc(pmt_t obj, pmt_t alist)
   while (pmt_is_pair(alist)){
     pmt_t p = pmt_car(alist);
     if (!pmt_is_pair(p))       // malformed alist
-      return PMT_BOOL_F;
+      return PMT_F;
 
     if (pmt_equal(obj, pmt_car(p)))
       return p;
 
     alist = pmt_cdr(alist);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 pmt_t
@@ -805,7 +876,7 @@ pmt_memq(pmt_t obj, pmt_t list)
       return list;
     list = pmt_cdr(list);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 pmt_t
@@ -816,7 +887,7 @@ pmt_memv(pmt_t obj, pmt_t list)
       return list;
     list = pmt_cdr(list);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 pmt_t
@@ -827,7 +898,7 @@ pmt_member(pmt_t obj, pmt_t list)
       return list;
     list = pmt_cdr(list);
   }
-  return PMT_BOOL_F;
+  return PMT_F;
 }
 
 bool
@@ -865,3 +936,62 @@ pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4)
 {
   return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, PMT_NIL))));
 }
+
+pmt_t
+pmt_caar(pmt_t pair)
+{
+  return (pmt_car(pmt_car(pair)));
+}
+
+pmt_t
+pmt_cadr(pmt_t pair)
+{
+  return pmt_car(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_cdar(pmt_t pair)
+{
+  return pmt_cdr(pmt_car(pair));
+}
+
+pmt_t
+pmt_cddr(pmt_t pair)
+{
+  return pmt_cdr(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_caddr(pmt_t pair)
+{
+  return pmt_car(pmt_cdr(pmt_cdr(pair)));
+}
+
+pmt_t
+pmt_cadddr(pmt_t pair)
+{
+  return pmt_car(pmt_cdr(pmt_cdr(pmt_cdr(pair))));
+}
+  
+bool
+pmt_is_eof_object(pmt_t obj)
+{
+  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));
+}
index 030637c4d2318a64d925fa8bcdac0c591e7529bc..dcf1ce668a1a3f8d12fad05c223d386e1cb8dba3 100644 (file)
 #define INCLUDED_PMT_H
 
 #include <boost/shared_ptr.hpp>
+#include <boost/any.hpp>
 #include <complex>
 #include <string>
 #include <stdint.h>
-#include <iostream>
+#include <iosfwd>
 #include <stdexcept>
 
 /*!
@@ -82,8 +83,8 @@ public:
  * I.e., there is a single false value, #f.
  * ------------------------------------------------------------------------
  */
-extern const pmt_t PMT_BOOL_T; //< #t : boolean true constant
-extern const pmt_t PMT_BOOL_F; //< #f : boolean false constant
+extern const pmt_t PMT_T;      //< #t : boolean true constant
+extern const pmt_t PMT_F;      //< #f : boolean false constant
 
 //! Return true if obj is #t or #f, else return false.
 bool pmt_is_bool(pmt_t obj);
@@ -97,7 +98,7 @@ bool pmt_is_false(pmt_t obj);
 //! Return #f is val is false, else return #t.
 pmt_t pmt_from_bool(bool val);
 
-//! Return true if val is PMT_BOOL_T, return false when val is PMT_BOOL_F, 
+//! Return true if val is PMT_T, return false when val is PMT_F, 
 // else raise wrong_type exception.
 bool pmt_to_bool(pmt_t val);
 
@@ -225,6 +226,13 @@ void pmt_set_car(pmt_t pair, pmt_t value);
 //! Stores \p value in the cdr field of \p pair.
 void pmt_set_cdr(pmt_t pair, pmt_t value);
 
+pmt_t pmt_caar(pmt_t pair);
+pmt_t pmt_cadr(pmt_t pair);
+pmt_t pmt_cdar(pmt_t pair);
+pmt_t pmt_cddr(pmt_t pair);
+pmt_t pmt_caddr(pmt_t pair);
+pmt_t pmt_cadddr(pmt_t pair);
+
 /*
  * ------------------------------------------------------------------------
  *                            Vectors
@@ -412,6 +420,28 @@ pmt_t pmt_dict_keys(pmt_t dict);
 //! Return list of values
 pmt_t pmt_dict_values(pmt_t dict);
 
+/*
+ * ------------------------------------------------------------------------
+ *   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
@@ -618,11 +648,14 @@ std::ostream& operator<<(std::ostream &os, pmt_t obj);
 /*!
  * \brief Write portable byte-serial representation of \p obj to \p sink
  */
-void pmt_serialize(pmt_t obj, std::ostream &sink);
+bool pmt_serialize(pmt_t obj, std::streambuf &sink);
 
 /*!
  * \brief Create obj from portable byte-serial representation
  */
-pmt_t pmt_deserialize(std::istream &source);
+pmt_t pmt_deserialize(std::streambuf &source);
+
+
+void pmt_dump_sizeof();        // debugging
 
 #endif /* INCLUDED_PMT_H */
index 458443eafa78b4304910e291dac62feb9b7a66d1..e82ce50e244132f5beb553a7908a78867478080b 100644 (file)
@@ -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 @@ public:
   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 @@ public:
   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 @@ public:
   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:
diff --git a/pmt/src/lib/pmt_pool.cc b/pmt/src/lib/pmt_pool.cc
new file mode 100644 (file)
index 0000000..16ab9c6
--- /dev/null
@@ -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;
+}
diff --git a/pmt/src/lib/pmt_pool.h b/pmt/src/lib/pmt_pool.h
new file mode 100644 (file)
index 0000000..fd9cc06
--- /dev/null
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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 */
diff --git a/pmt/src/lib/pmt_serialize.cc b/pmt/src/lib/pmt_serialize.cc
new file mode 100644 (file)
index 0000000..45f688b
--- /dev/null
@@ -0,0 +1,353 @@
+/* -*- 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 <vector>
+#include <pmt.h>
+#include "pmt_int.h"
+#include "pmt_serial_tags.h"
+
+static pmt_t parse_pair(std::streambuf &sb);
+
+// ----------------------------------------------------------------
+// output primitives
+// ----------------------------------------------------------------
+
+static bool
+serialize_untagged_u8(unsigned int i, std::streambuf &sb)
+{
+  return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+
+// always writes big-endian
+static bool
+serialize_untagged_u16(unsigned int i, std::streambuf &sb)
+{
+  sb.sputc((i >> 8) & 0xff);
+  return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+
+// always writes big-endian
+static bool
+serialize_untagged_u32(unsigned int i, std::streambuf &sb)
+{
+  sb.sputc((i >> 24) & 0xff);
+  sb.sputc((i >> 16) & 0xff);
+  sb.sputc((i >>  8) & 0xff);
+  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)
+{
+  sb.sputc((i >> 56) & 0xff);
+  sb.sputc((i >> 48) & 0xff);
+  sb.sputc((i >> 40) & 0xff);
+  sb.sputc((i >> 32) & 0xff);
+  sb.sputc((i >> 24) & 0xff);
+  sb.sputc((i >> 16) & 0xff);
+  sb.sputc((i >>  8) & 0xff);
+  return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+#endif
+
+// ----------------------------------------------------------------
+// input primitives
+// ----------------------------------------------------------------
+
+
+// always reads big-endian
+static bool
+deserialize_untagged_u8(uint8_t *ip, std::streambuf &sb)
+{
+  std::streambuf::traits_type::int_type  t;
+  int i;
+
+  t = sb.sbumpc();
+  i = t & 0xff;
+
+  *ip = i;
+  return t != std::streambuf::traits_type::eof();
+}
+
+// always reads big-endian
+static bool
+deserialize_untagged_u16(uint16_t *ip, std::streambuf &sb)
+{
+  std::streambuf::traits_type::int_type  t;
+  int i;
+
+  t = sb.sbumpc();
+  i = t & 0xff;
+
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+
+  *ip = i;
+  return t != std::streambuf::traits_type::eof();
+}
+
+// always reads big-endian
+static bool
+deserialize_untagged_u32(uint32_t *ip, std::streambuf &sb)
+{
+  std::streambuf::traits_type::int_type  t;
+  int i;
+
+  t = sb.sbumpc();
+  i = t & 0xff;
+
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+
+  *ip = i;
+  return t != std::streambuf::traits_type::eof();
+}
+
+#if 0
+// always reads big-endian
+static bool
+deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb)
+{
+  std::streambuf::traits_type::int_type  t;
+  uint64_t i;
+
+  t = sb.sbumpc();
+  i = t & 0xff;
+
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+  t = sb.sbumpc();
+  i = (i << 8) | (t & 0xff);
+
+  *ip = i;
+  return t != std::streambuf::traits_type::eof();
+}
+#endif
+
+/*
+ * Write portable byte-serial representation of \p obj to \p sb
+ *
+ * N.B., Circular structures cause infinite recursion.
+ */
+bool
+pmt_serialize(pmt_t obj, std::streambuf &sb)
+{
+  bool ok = true;
+
+ tail_recursion:
+
+  if (pmt_is_bool(obj)){
+    if (pmt_eq(obj, PMT_T))
+      return serialize_untagged_u8(PST_TRUE, sb);
+    else
+      return serialize_untagged_u8(PST_FALSE, sb);
+  }
+  
+  if (pmt_is_null(obj))
+    return serialize_untagged_u8(PST_NULL, sb);
+
+  if (pmt_is_symbol(obj)){
+    const std::string s = pmt_symbol_to_string(obj);
+    size_t len = s.size();
+    ok = serialize_untagged_u8(PST_SYMBOL, sb);
+    ok &= serialize_untagged_u16(len, sb);
+    for (size_t i = 0; i < len; i++)
+      ok &= serialize_untagged_u8(s[i], sb);
+    return ok;
+  }
+
+  if (pmt_is_pair(obj)){
+    ok = serialize_untagged_u8(PST_PAIR, sb);
+    ok &= pmt_serialize(pmt_car(obj), sb);
+    if (!ok)
+      return false;
+    obj = pmt_cdr(obj);
+    goto tail_recursion;
+  }
+
+  if (pmt_is_number(obj)){
+
+    if (pmt_is_integer(obj)){
+      long i = pmt_to_long(obj);
+      if (sizeof(long) > 4){
+       if (i < -2147483647 || i > 2147483647)
+         throw pmt_notimplemented("pmt_serialize (64-bit integers)", obj);
+      }
+      ok = serialize_untagged_u8(PST_INT32, sb);
+      ok &= serialize_untagged_u32(i, sb);
+      return ok;
+    }
+
+    if (pmt_is_real(obj))
+      throw pmt_notimplemented("pmt_serialize (real)", obj);
+
+    if (pmt_is_complex(obj))
+      throw pmt_notimplemented("pmt_serialize (complex)", obj);
+  }
+
+  if (pmt_is_vector(obj))
+    throw pmt_notimplemented("pmt_serialize (vector)", obj);
+
+  if (pmt_is_uniform_vector(obj))
+    throw pmt_notimplemented("pmt_serialize (uniform-vector)", obj);
+    
+  if (pmt_is_dict(obj))
+    throw pmt_notimplemented("pmt_serialize (dict)", obj);
+    
+
+  throw pmt_notimplemented("pmt_serialize (?)", obj);
+}
+
+/*
+ * Create obj from portable byte-serial representation
+ *
+ * Returns next obj from streambuf, or PMT_EOF at end of file.
+ * Throws exception on malformed input.
+ */
+pmt_t
+pmt_deserialize(std::streambuf &sb)
+{
+  uint8_t      tag;
+  //uint8_t    u8;
+  uint16_t     u16;
+  uint32_t     u32;
+  //uint32_t   u64;
+  static char   tmpbuf[1024];
+
+  if (!deserialize_untagged_u8(&tag, sb))
+    return PMT_EOF;
+
+  switch (tag){
+  case PST_TRUE:
+    return PMT_T;
+    
+  case PST_FALSE:
+    return PMT_F;
+
+  case PST_NULL:
+    return PMT_NIL;
+
+  case PST_SYMBOL:
+    if (!deserialize_untagged_u16(&u16, sb))
+      goto error;
+    if (u16 > sizeof(tmpbuf))
+      throw pmt_notimplemented("pmt_deserialize: very long symbol",
+                              PMT_F);
+    if (sb.sgetn(tmpbuf, u16) != u16)
+      goto error;
+    return pmt_intern(std::string(tmpbuf, u16));
+
+  case PST_INT32:
+    if (!deserialize_untagged_u32(&u32, sb))
+      goto error;
+    return pmt_from_long((int32_t) u32);
+
+  case PST_PAIR:
+    return parse_pair(sb);
+
+  case PST_DOUBLE:
+  case PST_COMPLEX:
+  case PST_VECTOR:
+  case PST_DICT:
+  case PST_UNIFORM_VECTOR:
+  case PST_COMMENT:
+    throw pmt_notimplemented("pmt_deserialize: tag value = ",
+                            pmt_from_long(tag));
+    
+  default:
+    throw pmt_exception("pmt_deserialize: malformed input stream, tag value = ",
+                       pmt_from_long(tag));
+  }
+
+ error:
+  throw pmt_exception("pmt_deserialize: malformed input stream", PMT_F);
+}
+
+/*
+ * This is a mostly non-recursive implementation that allows us to
+ * deserialize very long lists w/o exhausting the evaluation stack.
+ *
+ * On entry we've already eaten the PST_PAIR tag.
+ */
+pmt_t
+parse_pair(std::streambuf &sb)
+{
+  uint8_t tag;
+  pmt_t        val, expr, lastnptr, nptr;
+
+  //
+  // Keep appending nodes until we get a non-PAIR cdr.
+  //
+  lastnptr = PMT_NIL;
+  while (1){
+    expr = pmt_deserialize(sb);                // read the car
+
+    nptr = pmt_cons(expr, PMT_NIL);    // build new cell
+    if (pmt_is_null(lastnptr))
+      val = nptr;
+    else
+      pmt_set_cdr(lastnptr, nptr);
+    lastnptr = nptr;
+
+    if (!deserialize_untagged_u8(&tag, sb))  // get tag of cdr
+      throw pmt_exception("pmt_deserialize: malformed input stream", PMT_F);
+
+    if (tag == PST_PAIR)
+      continue;                        // keep on looping...
+
+    if (tag == PST_NULL){
+      expr = PMT_NIL;
+      break;
+    }
+
+    //
+    // default: push tag back and use pmt_deserialize to get the cdr
+    //
+    sb.sungetc();
+    expr = pmt_deserialize(sb);
+    break;
+  }
+
+  //
+  // At this point, expr contains the value of the final cdr in the list.
+  //
+  pmt_set_cdr(lastnptr, expr);
+  return val;
+}
index cb687b0e1b31da713b38778967cdbc79420375ef..4a665fe53e636fef15ab6d915a79c2430ddb454c 100644 (file)
 #include <cppunit/TestAssert.h>
 #include <pmt.h>
 #include <stdio.h>
+#include <sstream>
 
 void
 qa_pmt_prims::test_symbols()
 {
-  CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_T));
-  CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_F));
-  CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_BOOL_F), pmt_wrong_type);
+  CPPUNIT_ASSERT(!pmt_is_symbol(PMT_T));
+  CPPUNIT_ASSERT(!pmt_is_symbol(PMT_F));
+  CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_F), pmt_wrong_type);
 
   pmt_t sym1 = pmt_string_to_symbol("test");
   CPPUNIT_ASSERT(pmt_is_symbol(sym1));
@@ -76,13 +77,13 @@ void
 qa_pmt_prims::test_booleans()
 {
   pmt_t sym = pmt_string_to_symbol("test");
-  CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_T));
-  CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_F));
+  CPPUNIT_ASSERT(pmt_is_bool(PMT_T));
+  CPPUNIT_ASSERT(pmt_is_bool(PMT_F));
   CPPUNIT_ASSERT(!pmt_is_bool(sym));
-  CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_BOOL_F);
-  CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_BOOL_T);
-  CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_BOOL_F));
-  CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_BOOL_T));
+  CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_F);
+  CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_T);
+  CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_F));
+  CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_T));
   CPPUNIT_ASSERT_THROW(pmt_to_bool(sym), pmt_wrong_type);
 }
 
@@ -91,10 +92,10 @@ qa_pmt_prims::test_integers()
 {
   pmt_t p1 = pmt_from_long(1);
   pmt_t m1 = pmt_from_long(-1);
-  CPPUNIT_ASSERT(!pmt_is_integer(PMT_BOOL_T));
+  CPPUNIT_ASSERT(!pmt_is_integer(PMT_T));
   CPPUNIT_ASSERT(pmt_is_integer(p1));
   CPPUNIT_ASSERT(pmt_is_integer(m1));
-  CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_BOOL_T), pmt_wrong_type);
+  CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_T), pmt_wrong_type);
   CPPUNIT_ASSERT_EQUAL(-1L, pmt_to_long(m1));
   CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(p1));
 }
@@ -104,10 +105,10 @@ qa_pmt_prims::test_reals()
 {
   pmt_t p1 = pmt_from_double(1);
   pmt_t m1 = pmt_from_double(-1);
-  CPPUNIT_ASSERT(!pmt_is_real(PMT_BOOL_T));
+  CPPUNIT_ASSERT(!pmt_is_real(PMT_T));
   CPPUNIT_ASSERT(pmt_is_real(p1));
   CPPUNIT_ASSERT(pmt_is_real(m1));
-  CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_BOOL_T), pmt_wrong_type);
+  CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_T), pmt_wrong_type);
   CPPUNIT_ASSERT_EQUAL(-1.0, pmt_to_double(m1));
   CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(p1));
   CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(pmt_from_long(1)));
@@ -118,10 +119,10 @@ qa_pmt_prims::test_complexes()
 {
   pmt_t p1 = pmt_make_rectangular(2, -3);
   pmt_t m1 = pmt_make_rectangular(-3, 2);
-  CPPUNIT_ASSERT(!pmt_is_complex(PMT_BOOL_T));
+  CPPUNIT_ASSERT(!pmt_is_complex(PMT_T));
   CPPUNIT_ASSERT(pmt_is_complex(p1));
   CPPUNIT_ASSERT(pmt_is_complex(m1));
-  CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_BOOL_T), pmt_wrong_type);
+  CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_T), pmt_wrong_type);
   CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt_to_complex(p1));
   CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt_to_complex(m1));
   CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt_to_complex(pmt_from_long(1)));
@@ -242,7 +243,7 @@ qa_pmt_prims::test_misc()
   
   pmt_t alist = pmt_cons(p0, pmt_cons(p1, pmt_cons(p2, PMT_NIL)));
   CPPUNIT_ASSERT(pmt_eq(p1, pmt_assv(k1, alist)));
-  CPPUNIT_ASSERT(pmt_eq(PMT_BOOL_F, pmt_assv(k3, alist)));
+  CPPUNIT_ASSERT(pmt_eq(PMT_F, pmt_assv(k3, alist)));
   
   pmt_t keys = pmt_cons(k0, pmt_cons(k1, pmt_cons(k2, PMT_NIL)));
   pmt_t vals = pmt_cons(v0, pmt_cons(v1, pmt_cons(v2, PMT_NIL)));
@@ -293,3 +294,102 @@ qa_pmt_prims::test_io()
 
   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
+  pmt_t a = pmt_intern("a");
+  pmt_t b = pmt_intern("b");
+  pmt_t c = pmt_intern("c");
+
+  sb.str("");                  // reset channel to empty
+
+  // write stuff to channel
+
+  pmt_serialize(PMT_NIL, sb);
+  pmt_serialize(pmt_intern("foobarvia"), sb);
+  pmt_serialize(pmt_from_long(123456789), sb);
+  pmt_serialize(pmt_from_long(-123456789), sb);
+  pmt_serialize(pmt_cons(PMT_NIL, PMT_NIL), sb);
+  pmt_serialize(pmt_cons(a, b), sb);
+  pmt_serialize(pmt_list1(a), sb);
+  pmt_serialize(pmt_list2(a, b), sb);
+  pmt_serialize(pmt_list3(a, b, c), sb);
+  pmt_serialize(pmt_list3(a, pmt_list3(c, b, a), c), sb);
+  pmt_serialize(PMT_T, sb);
+  pmt_serialize(PMT_F, sb);
+
+  // read it back
+
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_intern("foobarvia")));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(123456789)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(-123456789)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(PMT_NIL, PMT_NIL)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(a, b)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list1(a)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list2(a, b)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, b, c)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, pmt_list3(c, b, a), c)));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_T));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_F));
+
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_EOF));     // last item
+
+
+  // FIXME add tests for real, complex, vector, uniform-vector, dict
+  // FIXME add tests for malformed input too.
+
+}
index 8d379c5afa1415e4c3b5134a6a86fd30eefde40f..a390343bd4da419641b2f32151db33e80b1e6b3b 100644 (file)
@@ -38,7 +38,9 @@ class qa_pmt_prims : public CppUnit::TestCase {
   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();
 
  private:
@@ -52,7 +54,9 @@ class qa_pmt_prims : public CppUnit::TestCase {
   void test_equivalence();
   void test_misc();
   void test_dict();
+  void test_any();
   void test_io();
+  void test_serialize();
 };
 
 #endif /* INCLUDED_QA_PMT_PRIMS_H */
diff --git a/pmt/src/scheme/Makefile.am b/pmt/src/scheme/Makefile.am
new file mode 100644 (file)
index 0000000..7700a1f
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+SUBDIRS = gnuradio
diff --git a/pmt/src/scheme/gnuradio/Makefile.am b/pmt/src/scheme/gnuradio/Makefile.am
new file mode 100644 (file)
index 0000000..12bc9b1
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+#pkgdatadir = $(datadir)/gnuradio
+
+EXTRA_DIST =                           \
+       gen-serial-tags.scm             \
+       pmt-serial-tags.scm             \
+       pmt-serialize.scm               
+
+
+# really scheme source files
+pkgdata_DATA =                         \
+       pmt-serial-tags.scm             \
+       pmt-serialize.scm               
diff --git a/pmt/src/scheme/gnuradio/gen-serial-tags.scm b/pmt/src/scheme/gnuradio/gen-serial-tags.scm
new file mode 100755 (executable)
index 0000000..5bcf801
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/guile \
+-e main -s
+!#
+;;; -*-scheme-*-
+;;;
+;;; 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.
+;;;
+
+(use-modules (ice-9 format))
+
+(defmacro when (pred . body)
+  `(if ,pred (begin ,@body) #f))
+
+;; ----------------------------------------------------------------
+
+(define (main args)
+
+  (define (usage)
+    (format 0
+           "usage: ~a <pmt-serial-tags.scm> <pmt_serial_tags.h>~%"
+           (car args)))
+
+  (when (not (= (length args) 3))
+       (usage)
+       (format 0 "args: ~s~%" args)
+       (exit 1))
+      
+  (let ((i-file (open-input-file (cadr args)))
+       (h-file (open-output-file (caddr args))))
+
+      (write-header-comment h-file "// ")
+      (display "#ifndef INCLUDED_PMT_SERIAL_TAGS_H\n" h-file)
+      (display "#define INCLUDED_PMT_SERIAL_TAGS_H\n" h-file)
+      (newline h-file)
+      (display "enum pst_tags {\n" h-file)
+
+      (for-each-in-file i-file
+       (lambda (form)
+        (let* ((name (cadr form))
+               (c-name (string-upcase (c-ify name)))
+               (value (caddr form)))
+          ;;(format h-file   "static const int ~a\t= 0x~x;~%" c-name value)
+          (format h-file   "  ~a\t= 0x~x,~%" c-name value))))
+
+      (display "};\n" h-file)
+      (display "#endif\n" h-file)))
+
+(define (c-ify name)
+  (list->string (map (lambda (c)
+                      (if (eqv? c #\-) #\_ c))
+                    (string->list (symbol->string name)))))
+
+
+(define (write-header-comment o-port prefix)
+  (for-each (lambda (comment)
+             (format o-port "~a~a~%" prefix comment))
+           header-comment))
+
+(define header-comment
+  '(
+    ""
+    "Copyright 2007 Free Software Foundation, Inc."
+    ""
+    "This file is part of GNU Radio"
+    ""
+    "GNU Radio is free software; you can redistribute it and/or modify"
+    "it under the terms of the GNU General Public License as published by"
+    "the Free Software Foundation; either version 2, or (at your option)"
+    "any later version."
+    ""
+    "GNU Radio is distributed in the hope that it will be useful,"
+    "but WITHOUT ANY WARRANTY; without even the implied warranty of"
+    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
+    "GNU General Public License for more details."
+    ""
+    "You should have received a copy of the GNU General Public License along"
+    "with this program; if not, write to the Free Software Foundation, Inc.,"
+    "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
+    ""
+    ""
+    "THIS FILE IS MACHINE GENERATED FROM pmt-serial-tags.scm. DO NOT EDIT BY HAND."
+    "See pmt-serial-tags.scm for additional commentary."
+    ""))
+
+
+
+(define (for-each-in-file file f)
+  (let ((port (if (port? file)
+                 file
+                 (open-input-file file))))
+    (letrec
+     ((loop
+       (lambda (port form)
+        (cond ((eof-object? form)
+               (when (not (eq? port file))
+                     (close-input-port port))
+               #t)
+              (else
+               (f form)
+               (set! form #f)          ; for GC
+               (loop port (read port)))))))
+     (loop port (read port)))))
diff --git a/pmt/src/scheme/gnuradio/macros-etc.scm b/pmt/src/scheme/gnuradio/macros-etc.scm
new file mode 100644 (file)
index 0000000..518c1ff
--- /dev/null
@@ -0,0 +1,50 @@
+;;; -*- scheme -*-
+;;;
+;;; 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.
+;;;
+
+(define-module (gnuradio macros-etc)
+  :export (atom? when unless for-each-in-file))
+
+(define (atom? obj)
+  (not (pair? obj)))
+
+(defmacro when (pred . body)
+  `(if ,pred (begin ,@body) #f))
+
+(defmacro unless (pred . body)
+  `(if (not ,pred) (begin ,@body) #f))
+
+
+(define (for-each-in-file file f)
+  (let ((port (if (port? file)
+                 file
+                 (open-input-file file))))
+    (letrec
+     ((loop
+       (lambda (port form)
+        (cond ((eof-object? form)
+               (when (not (eq? port file))
+                     (close-input-port port))
+               #t)
+              (else
+               (f form)
+               (set! form #f)          ; for GC
+               (loop port (read port)))))))
+     (loop port (read port)))))
diff --git a/pmt/src/scheme/gnuradio/pmt-serial-tags.scm b/pmt/src/scheme/gnuradio/pmt-serial-tags.scm
new file mode 100644 (file)
index 0000000..4dd1830
--- /dev/null
@@ -0,0 +1,75 @@
+;;; -*-scheme-*-
+;;;
+;;; 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 (define 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.
+;;;
+
+;;; definitions of tag values used for marshalling pmt data
+
+(define pst-true               #x00)
+(define pst-false              #x01)
+(define pst-symbol             #x02)   ; untagged-int16 n; followed by n bytes of symbol name
+(define pst-int32              #x03)
+(define pst-double             #x04)
+(define pst-complex            #x05)   ; complex<double>: real, imag
+(define pst-null               #x06)
+(define pst-pair               #x07)   ; followed by two objects
+(define pst-vector             #x08)   ; untagged-int32 n; followed by n objects
+(define pst-dict               #x09)   ; untagged-int32 n; followed by n key/value tuples
+
+(define pst-uniform-vector     #x0a)
+
+;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64
+;;
+;;   untagged-uint8  tag
+;;   untagged-uint8  uvi (define uniform vector info, see below)
+;;   untagged-int32  n-items
+;;   untagged-uint8  npad
+;;   npad bytes of zeros to align binary data
+;;   n-items binary numeric items
+;;
+;; uvi:
+;; +-+-+-+-+-+-+-+-+
+;; |B|   subtype   |
+;; +-+-+-+-+-+-+-+-+
+;;
+;; B == 0, numeric data is little-endian.
+;; B == 1, numeric data is big-endian.
+
+    (define uvi-endian-mask     #x80)
+    (define uvi-subtype-mask    #x7f)
+
+    (define uvi-little-endian   #x00)
+    (define uvi-big-endian      #x80)
+
+    (define uvi-u8             #x00)
+    (define uvi-s8             #x01)
+    (define uvi-u16            #x02)
+    (define uvi-s16            #x03)
+    (define uvi-u32            #x04)
+    (define uvi-s32            #x05)
+    (define uvi-u64            #x06)
+    (define uvi-s64            #x07)
+    (define uvi-f32            #x08)
+    (define uvi-f64            #x09)
+    (define uvi-c32            #x0a)
+    (define uvi-c64            #x0b)
+
+
+(define pst-comment            #x3b)   ; ascii ';'
+(define pst-comment-end                #x0a)   ; ascii '\n'
diff --git a/pmt/src/scheme/gnuradio/pmt-serialize.scm b/pmt/src/scheme/gnuradio/pmt-serialize.scm
new file mode 100644 (file)
index 0000000..a39f9cf
--- /dev/null
@@ -0,0 +1,48 @@
+;;;
+;;; 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.
+;;;
+
+;;; An implementation of pmt_serialize in scheme.
+;;; Currently handles only symbols and pairs.  They're all we need for now.
+
+(define-module (gnuradio pmt-serialize)
+  :export (pmt-serialize))
+
+(load-from-path "gnuradio/pmt-serial-tags")
+
+(define (pmt-serialize obj put-byte)
+  (define (put-u16 x)
+    (put-byte (logand (ash x -8) #xff))
+    (put-byte (logand x #xff)))
+    
+  (cond ((null? obj)
+        (put-byte pst-null))
+       ((symbol? obj)
+        (let* ((sym-as-bytes (map char->integer (string->list (symbol->string obj))))
+               (len (length sym-as-bytes)))
+          (put-byte pst-symbol)
+          (put-u16 len)
+          (for-each put-byte sym-as-bytes)))
+       
+       ((pair? obj)
+        (put-byte pst-pair)
+        (pmt-serialize (car obj) put-byte)
+        (pmt-serialize (cdr obj) put-byte))
+       (else
+        (throw 'not-implemented "pmt-serialize" obj))))
index ca306fe6051f1f725aa29318457d0e41b61c4a7f..1a5d87073a4ad9a46fc0a902252dbbedde46eccf 100644 (file)
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
 
-This is preliminary design document on the organization of the host
-component of the USRP inband signaling implementation over USB.
 
-Assumptions: we'll have a single usrp_usb_daemon, implemented as an
-mblock, that will provide the high-level message based interface to
-the USRP.  The daemon will handle all resource allocation, muxing and
-demuxing for the control and status messages from multiple clients.
-
-The underlying cross-process IPC mechanism is not yet specified.
-All communication will be via messages.
-
-The external interface to the usrp_usb_daemon will consist of two sets
-of replicated ports, one set for the transmit, and one set for
-receive.
-
-
-// ------------------------------------------------------------------------
-
-// Protocol class usrp_usb_common
-// Defined from client's point-of-view
-//
-// This protocol class is shared by the usrp_usb_tx and usrp_usb_rx
-// protocol classes
-
-// outgoing:
-
-cmd_allocate_channel(invocation_handle, channel, capacity_reservation)
-
-invocation_handle
-Type   Handle
-Use    The identifier provided by the client to tag the method invocation.
-       The identifier will be returned with the response, to provide
-       the client with a mechanism to match asynchronous responses with
-       commands that generated them.
-
-channel
-Type   integer
-Use    Specifies the Tx channel to allocate
-
-capacity_reservation
-Type   float, units are bytes/s
-Use    Specifies the number of bytes/s of USB capacity to reserve for
-       this channel.
-
-
-// incoming:
-
-response_allocate_channel(invocation_handle, status)
-
-Type   Handle
-Use    The identifier provided by the client in the prompting invocation.
-       The identifier is returned with the response, so that the
-       client has a mechanism to match asynchronous responses with
-       commands that generated them.  The value of the invocation_handle
-       is opaque to the server, and is not required by the server to be unique.
-
-Type   Status
-Use    Contains the status code for the operation, per FIXME, and
-       an optional message.
-
-Preconditions:
-  a) None
-  
-Postconditions:
-  a) If successful, the requested channel and USB capacity are
-     allocated for the client's exclusive use.
-
-
-// outgoing:
-
-cmd_deallocate_channel(invocation_handle, channel)
-
-invocation_handle
-Type   Handle
-Use    The identifier provided by the client to tag the method invocation.
-       The identifier will be returned with the response, to provide
-       the client with a mechanism to match asynchronous responses with
-       commands that generated them.
-
-channel
-Type   integer
-Use    Specifies the Tx channel to deallocate
-
-
-// incoming:
-
-response_deallocate_channel(invocation_handle, status)
-
-Type   Handle
-Use    The identifier provided by the client in the prompting invocation.
-       The identifier is returned with the response, so that the
-       client has a mechanism to match asynchronous responses with
-       commands that generated them.  The value of the invocation_handle
-       is opaque to the server, and is not required by the server to be unique.
-
-Type   Status
-Use    Contains the status code for the operation, per FIXME, and
-       an optional message.
-
-Preconditions:
-  a) None
-  
-Postconditions: 
-  a) If successful, the requested channel and associated USB capacity
-     are deallocated, and return to the pool of available resources.
-
-
-// ------------------------------------------------------------------------
-
-// Protocol class usrp_usb_tx inherits from usrp_usb_common 
-// Defined from client's point-of-view
-
-// outgoing:
-
-cmd_xmit_raw_frame(invocation_handle, channel, samples, timestamp)
-
-invocation_handle
-Type   Handle
-Use    The identifier provided by the client to tag the method invocation.
-       The identifier will be returned with the response, to provide
-       the client with a mechanism to match asynchronous responses with
-       commands that generated them.
-
-channel
-Type   integer
-Use    Specifies the channel that the frame of samples shall be transmitted on.
-
-samples
-Type   homogenous vector of unsigned char
-Use    These samples must already be in the appropriate format for parsing
-       by the USRP FPGA.  The required format depends on the
-       configuration associated with this channel.  No conversion of
-       the samples takes place in this method.  Samples will be split
-       into multiple USB data packets as required for transport
-       across the USB.
-
-timestamp
-Type   32-bit integer
-Use    Specifies the time at which the first sample in samples
-       shall be sent to the D/A converter.  The format and
-       interpretation of time is as specified in
-       inband-signaling-usb.
-
-
-// incoming:
-
-response_xmit_raw_frame(invocation_handle, status)
-
-Type   Handle
-Use    The identifier provided by the client in the prompting invocation.
-       The identifier is returned with the response, so that the
-       client has a mechanism to match asynchronous responses with
-       commands that generated them.  The value of the invocation_handle
-       is opaque to the server, and is not required by the server to be unique.
-
-Type   Status
-Use    Contains the status code for the operation, per FIXME, and
-       an optional message.
-
-Preconditions:
-  a) The specified channel is allocated to this client
-  
-Postconditions: 
-  a) If successful, the samples of the frame have been queued for
-     transmission to the USRP.
-
-
-// ------------------------------------------------------------------------
-
-// Protocol class usrp_usb_rx inherits from usrp_usb_common 
-// Defined from client's point-of-view
-
-
-// outgoing:
-
-cmd_recv_raw_samples(invocation_handle, channel)
-
-invocation_handle
-Type   Handle
-Use    The identifier provided by the client to tag the method invocation.
-       The identifier will be returned with the response, to provide
-       the client with a mechanism to match asynchronous responses with
-       commands that generated them.
-
-channel
-Type   integer
-Use    Specifies the channel that the samples shall be received from.
-
-The client may issue multiple cmd_recv_raw_samples commands to ensure
-an uninterrupted flow of samples.  The appropriate number of
-outstanding cmds to issue is TBD, but is at least 2.
-
-[Discussion: I'm not sure if this is really the interface we want.  
-We may want to provide an enable/disable method, and then just begin
-streaming samples.  Or, we may wan to implement packet boundary
-detection in the FPGA, and then return a frame's worth of samples
-(potentially in multiple pieces).
-
-It may be that we need to different modes, one for packet based
-reception and one for continuous streaming.]
-
-
-// incoming:
-
-response_recv_raw_samples(invocation_handle, samples, timestamp, properties)
-
-Type   Handle
-Use    The identifier provided by the client in the prompting invocation.
-       The identifier is returned with the response, so that the
-       client has a mechanism to match asynchronous responses with
-       commands that generated them.  The value of the invocation_handle
-       is opaque to the server, and is not required by the server to be unique.
-
-samples
-Type   homogenous vector of unsigned char
-Use    Samples as returned by the USRP FPGA.  The format of the
-       returned samples depends on the configuration associated with
-       this channel.  No conversion or unpacking of samples takes place in
-       this method.
-
-timestamp
-Type   32-bit integer
-Use    Specifies the time at which the first sample in samples
-       was received from the A/D converter.  The format and
-       interpretation of time is as specified in
-       inband-signaling-usb.
-
-properties
-Type   Map
-Use    Returns additional (key, value) pairs associated with the
-       reception of these samples.  In particular, the map may contain
-       the Received Strength Signal Indication (RSSI) reported by the
-       front end at the time the first sample was received from the A/D.
-
-// ------------------------------------------------------------------------
-
-To do: control and configuration messages...
+See usrp/host/lib/inband/usrp_server.mbh for interface
 
diff --git a/usrp/fpga/inband_lib/chan_fifo_reader.v b/usrp/fpga/inband_lib/chan_fifo_reader.v
new file mode 100755 (executable)
index 0000000..2b3178d
--- /dev/null
@@ -0,0 +1,197 @@
+module chan_fifo_reader 
+  ( input       reset,
+    input       tx_clock,
+    input       tx_strobe,
+    input       [31:0]adc_clock,
+    input       [3:0] samples_format,
+    input       [15:0] fifodata,
+    input       pkt_waiting,
+    output  reg rdreq,
+    output  reg skip,
+    output  reg [15:0]tx_q,
+    output  reg [15:0]tx_i,
+    output  reg overrun,
+    output  reg underrun) ;
+    
+    // Should not be needed if adc clock rate < tx clock rate
+    `define JITTER        5
+    
+    //Samples format
+    // 16 bits interleaved complex samples
+    `define QI16         4'b0
+    
+    // States
+   `define IDLE          4'd0
+   `define READ          4'd1
+   `define HEADER1       4'd2
+   `define HEADER2       4'd3
+   `define TIMESTAMP1    4'd4
+   `define TIMESTAMP2    4'd5
+   `define WAIT          4'd6
+   `define WAITSTROBE    4'd7
+   `define SENDWAIT      4'd8
+   `define SEND          4'd9
+   `define FEED          4'd10
+   `define DISCARD       4'd11
+
+   // State registers
+   reg[3:0] reader_state;
+   reg[3:0] reader_next_state;
+   
+   //Variables
+   reg[8:0] payload_len;
+   reg[8:0] read_len;
+   reg[31:0] timestamp;
+   reg burst;
+   reg qsample;
+   always @(posedge tx_clock)
+   begin
+       if (reset) 
+          begin
+             reader_state <= `IDLE;
+             reader_next_state <= `IDLE;
+             rdreq <= 0;
+             skip <= 0;
+             overrun <= 0;
+             underrun <= 0;
+             burst <= 0;
+             qsample <= 1;
+          end
+       else 
+                begin
+           reader_state = reader_next_state;
+           case (reader_state)
+               `IDLE:
+                  begin
+                     if (pkt_waiting == 1)
+                       begin
+                          reader_next_state <= `READ;
+                          rdreq <= 1;
+                          underrun <= 0;
+                       end
+                     else if (burst == 1)
+                        underrun <= 1;
+                  end
+
+                               // Just wait for the fifo data to arrive
+               `READ: 
+                  begin
+                     reader_next_state <= `HEADER1;
+                  end
+                               
+                               // First part of the header
+               `HEADER1:
+                  begin
+                     reader_next_state <= `HEADER2;
+                     
+                     //Check Start burst flag
+                     if (fifodata[3] == 1)
+                        burst <= 1;
+                        
+                     if (fifodata[4] == 1)
+                        burst <= 0;
+                  end
+
+                               // Read payload length
+               `HEADER2:
+                  begin
+                     payload_len <= (fifodata & 16'h1FF);
+                     read_len <= 9'd0;
+                     reader_next_state <= `TIMESTAMP1;
+                  end
+
+               `TIMESTAMP1: 
+                  begin
+                     timestamp <= {fifodata, 16'b0};
+                     rdreq <= 0;
+                     reader_next_state <= `TIMESTAMP2;
+                  end
+                               
+               `TIMESTAMP2:
+                  begin
+                     timestamp <= timestamp + fifodata;
+                     reader_next_state <= `WAIT;
+                  end
+                               
+                               // Decide if we wait, send or discard samples
+               `WAIT: 
+                  begin
+                   // Wait a little bit more
+                     if (timestamp > adc_clock + `JITTER)
+                        reader_next_state <= `WAIT;
+                   // Let's send it
+                   else if ((timestamp < adc_clock + `JITTER 
+                           && timestamp > adc_clock)
+                           || timestamp == 32'hFFFFFFFF)
+                      begin
+                         reader_next_state <= `WAITSTROBE;
+                      end
+                   // Outdated
+                   else if (timestamp < adc_clock)
+                      begin
+                         reader_next_state <= `DISCARD;
+                         skip <= 1;
+                     end
+                 end
+                 
+            // Wait for the transmit chain to be ready
+               `WAITSTROBE:
+                  begin
+                      // If end of payload...
+                     if (read_len == payload_len)
+                        begin
+                           reader_next_state <= `DISCARD;
+                           skip <= (payload_len < 508);
+                        end
+                          
+                      if (tx_strobe == 1)
+                         reader_next_state <= `SENDWAIT;
+                  end
+               
+               `SENDWAIT:
+                  begin
+                     rdreq <= 1;
+                     reader_next_state <= `SEND; 
+                  end
+               
+                               // Send the samples to the tx_chain
+               `SEND:
+                  begin
+                     reader_next_state <= `WAITSTROBE; 
+                     rdreq <= 0;
+                     read_len <= read_len + 2;
+                     case(samples_format)
+                        `QI16:
+                           begin
+                              tx_q <= qsample ? fifodata : 16'bZ;
+                              tx_i <= ~qsample ? fifodata : 16'bZ;
+                              qsample <= ~ qsample;
+                           end  
+                        default:
+                           begin
+                               // Assume 16 bits complex samples by default
+                              $display ("Error unknown samples format");
+                              tx_q <= qsample ? fifodata : 16'bZ;
+                              tx_i <= ~qsample ? fifodata : 16'bZ;
+                              qsample <= ~ qsample;
+                           end 
+                     endcase
+                  end
+
+               `DISCARD:
+                  begin
+                     skip <= 0;
+                     reader_next_state <= `IDLE;
+                  end
+               
+               default:
+                  begin
+                     $display ("Error unknown state");
+                     reader_state <= `IDLE;
+                     reader_next_state <= `IDLE;
+                  end
+           endcase
+       end
+   end
+endmodule
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/data_packet_fifo.v b/usrp/fpga/inband_lib/data_packet_fifo.v
new file mode 100755 (executable)
index 0000000..5b37b14
--- /dev/null
@@ -0,0 +1,128 @@
+module data_packet_fifo 
+  ( input       reset,
+    input       clock,
+    input       [15:0]ram_data_in,
+    input       write_enable,
+    output  reg have_space,
+    output  reg [15:0]ram_data_out,
+    output  reg pkt_waiting,
+    input       read_enable,
+    input       pkt_complete,
+    input       skip_packet) ;
+
+    /* Some parameters for usage later on */
+    parameter DATA_WIDTH = 16 ;
+    parameter NUM_PACKETS = 4 ;
+
+    /* Create the RAM here */
+    reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
+
+    /* Create the address signals */
+    reg [7:0] usb_ram_offset_out ;
+    reg [1:0] usb_ram_packet_out ;
+    reg [7:0] usb_ram_offset_in ;
+    reg [1:0] usb_ram_packet_in ;
+
+    wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
+    wire [7-2+NUM_PACKETS:0] usb_ram_ain ;
+    reg isfull;
+
+    assign usb_ram_aout = {usb_ram_packet_out, usb_ram_offset_out} ;
+    assign usb_ram_ain = {usb_ram_packet_in, usb_ram_offset_in} ;
+    
+    // Check if there is one full packet to process
+    always @(usb_ram_ain, usb_ram_aout)
+    begin
+        if (reset)
+            pkt_waiting <= 0;
+        else if (usb_ram_ain >= usb_ram_aout)
+            pkt_waiting <= usb_ram_ain - usb_ram_aout >= 256;
+        else
+            pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
+    end
+
+    // Check if there is room
+    always @(usb_ram_ain, usb_ram_aout)
+    begin
+        if (reset)
+            have_space <= 1;
+        else if (usb_ram_ain == usb_ram_aout)
+            have_space <= ~isfull;   
+        else if (usb_ram_ain > usb_ram_aout)
+            have_space <= (usb_ram_ain - usb_ram_aout) <= 256 * (NUM_PACKETS - 1);
+        else
+            have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
+    end
+
+    /* RAM Write Address process */
+    always @(posedge clock)
+    begin
+        if( reset )
+          begin
+            usb_ram_offset_in <= 0 ;
+            usb_ram_packet_in <= 0 ;
+          end
+        else
+            if( pkt_complete )
+              begin
+                usb_ram_packet_in <= usb_ram_packet_in + 1;  
+                usb_ram_offset_in <= 0;
+              end
+            else if( write_enable ) 
+              begin
+                if (usb_ram_offset_in == 8'b11111111)
+                  begin
+                    usb_ram_offset_in <= 0;
+                    usb_ram_packet_in <= usb_ram_packet_in + 1;    
+                  end
+                else
+                    usb_ram_offset_in <= usb_ram_offset_in + 1 ;
+                    if (usb_ram_ain + 1 == usb_ram_aout)
+                       isfull <= 1;
+              end
+    end
+
+    /* RAM Writing process */
+    always @(posedge clock)
+    begin
+        if( write_enable ) 
+          begin
+            usb_ram[usb_ram_ain] <= ram_data_in ;
+          end
+    end
+
+    /* RAM Read Address process */
+    always @(posedge clock)
+    begin
+        if( reset ) 
+          begin
+            usb_ram_packet_out <= 0 ;
+            usb_ram_offset_out <= 0 ;
+            isfull <= 0;
+          end
+        else
+            if( skip_packet )
+              begin
+                usb_ram_packet_out <= usb_ram_packet_out + 1 ;
+                usb_ram_offset_out <= 0 ;
+              end
+            else if(read_enable) begin
+                if( usb_ram_offset_out == 8'b11111111 )
+                  begin
+                    usb_ram_offset_out <= 0 ;
+                    usb_ram_packet_out <= usb_ram_packet_out + 1 ;
+                  end
+                else
+                    usb_ram_offset_out <= usb_ram_offset_out + 1 ;  
+            end 
+            if (usb_ram_ain == usb_ram_aout)
+               isfull <= 0;                    
+    end
+
+    /* RAM Reading Process */
+    always @(posedge clock)
+    begin
+        ram_data_out <= usb_ram[usb_ram_aout] ;
+    end
+
+endmodule
diff --git a/usrp/fpga/inband_lib/tx_buffer_inband.v b/usrp/fpga/inband_lib/tx_buffer_inband.v
new file mode 100755 (executable)
index 0000000..56c0780
--- /dev/null
@@ -0,0 +1,183 @@
+module tx_buffer_inband
+  ( input usbclk,
+    input bus_reset,  // Used here for the 257-Hack to fix the FX2 bug
+    input reset,  // standard DSP-side reset
+    input [15:0] usbdata,
+    input wire WR,
+    output wire have_space,
+    output reg tx_underrun,
+    input wire [3:0] channels,
+    output [15:0] tx_i_0,
+    output [15:0] tx_q_0,
+    output [15:0] tx_i_1,
+    output [15:0] tx_q_1,
+    //NOT USED
+    output reg [15:0] tx_i_2,
+    output reg [15:0] tx_q_2,
+    output reg [15:0] tx_i_3,
+    output reg [15:0] tx_q_3,
+    input txclk,
+    input txstrobe,
+    input clear_status,
+    output wire tx_empty,
+    output [11:0] debugbus
+    );
+
+   wire [15:0] tx_data_bus;
+
+   wire WR_chan_0;
+   wire chan_0_done;
+   wire OR0;
+   wire UR0;
+   
+   wire WR_chan_1;
+   wire chan_1_done;
+   wire OR1;
+   wire UR1;
+   
+   // NOT USED yet
+   wire WR_cmd;
+   wire cmd_done;
+   
+   //EXTERNAL REGISTER
+   //TODO: increment it
+   reg [31:0] time_counter;
+   reg [7:0] txstrobe_rate_0;
+   reg [7:0] txstrobe_rate_1;
+   
+   
+   //Usb block
+   wire [15:0] tupf_fifodata;
+   wire tupf_pkt_waiting;
+   wire tupf_rdreq;
+   wire tupf_skip;
+   wire tupf_have_space;
+   
+   usb_packet_fifo2 tx_usb_packet_fifo 
+     (  .reset         (reset),
+        .usb_clock     (usbclk), 
+        .fpga_clock    (txclk),
+        .write_data    (usbdata),
+        .write_enable  (WR),
+        .read_data     (tupf_fifodata),
+        .pkt_waiting   (tupf_pkt_waiting),
+        .read_enable   (tupf_rdreq), 
+        .skip_packet   (tupf_skip),
+        .have_space    (tupf_have_space),
+        .tx_empty      (tx_empty)
+       );
+   
+       usb_fifo_reader tx_usb_packet_reader (
+               .reset(reset),
+               .tx_clock(txclk),
+               .tx_data_bus(tx_data_bus),
+      .WR_chan_0(WR_chan_0),
+      .WR_chan_1(WR_chan_1),
+      .WR_cmd(WR_cmd),
+      .chan_0_done(chan_0_done),
+      .chan_1_done(chan_1_done),
+      .cmd_done(cmd_done),
+      .rdreq(tupf_rdreq),
+      .skip(tupf_skip),
+      .pkt_waiting(tupf_pkt_waiting),
+      .fifodata(tupf_fifodata)
+       );
+
+
+   //Channel 0 block
+   wire [15:0] tdpf_fifodata_0;
+   wire tdpf_pkt_waiting_0;
+   wire tdpf_rdreq_0;
+   wire tdpf_skip_0;
+   wire tdpf_have_space_0;
+   wire txstrobe_chan_0;
+
+   data_packet_fifo tx_data_packet_fifo_0 
+     (  .reset(reset),
+        .clock(txclk), 
+        .ram_data_in(tx_data_bus),
+        .write_enable(WR_chan_0),
+        .ram_data_out(tdpf_fifodata_0),
+        .pkt_waiting(tdpf_pkt_waiting_0),
+        .read_enable(tdpf_rdreq_0),
+        .pkt_complete(chan_0_done), 
+        .skip_packet(tdpf_skip_0),
+        .have_space(tdpf_have_space_0)
+       );
+   
+   strobe_gen strobe_gen_0
+    (   .clock(txclk),
+        .reset(reset),
+        .enable(1'b1),
+        .rate(txstrobe_rate_0),
+        .strobe_in(txstrobe),
+        .strobe(txstrobe_chan_0) 
+       );
+   
+   chan_fifo_reader tx_chan_0_reader (
+      .reset(reset),
+      .tx_clock(txclk),
+      .tx_strobe(txstrobe),
+      //.tx_strobe(txstrobe_chan_0),
+      .adc_clock(time_counter),
+      .samples_format(4'b0),
+      .tx_q(tx_q_0),
+      .tx_i(tx_i_0),
+      .overrun(OR0),
+      .underrun(UR0),
+      .skip(tdpf_skip_0),
+      .rdreq(tdpf_rdreq_0),
+      .fifodata(tdpf_fifodata_0),
+      .pkt_waiting(tdpf_pkt_waiting_0)
+   );  
+   
+   
+   //Channel 1 block
+   wire [15:0] tdpf_fifodata_1;
+   wire tdpf_pkt_waiting_1;
+   wire tdpf_rdreq_1;
+   wire tdpf_skip_1;
+   wire tdpf_have_space_1;
+   wire txstrobe_chan_1;
+   
+   data_packet_fifo tx_data_packet_fifo_1 
+     (  .reset(reset),
+        .clock(txclk), 
+        .ram_data_in(tx_data_bus),
+        .write_enable(WR_chan_1),
+        .ram_data_out(tdpf_fifodata_1),
+        .pkt_waiting(tdpf_pkt_waiting_1),
+        .read_enable(tdpf_rdreq_1),
+        .pkt_complete(chan_1_done), 
+        .skip_packet(tdpf_skip_1),
+        .have_space(tdpf_have_space_1)
+       );
+   
+   strobe_gen strobe_gen_1
+    (   .clock(txclk),
+        .reset(reset),
+        .enable(1'b1),
+        .rate(txstrobe_rate_1),
+        .strobe_in(txstrobe),
+        .strobe(txstrobe_chan_1) 
+       );
+   
+   chan_fifo_reader tx_chan_1_reader (
+      .reset(reset),
+      .tx_clock(txclk),
+      .tx_strobe(txstrobe),
+      //.tx_strobe(txstrobe_chan_1),
+      .adc_clock(time_counter),
+      .samples_format(4'b0),
+      .tx_q(tx_q_1),
+      .tx_i(tx_i_1),
+      .overrun(OR1),
+      .underrun(UR1),
+      .skip(tdpf_skip_1),
+      .rdreq(tdpf_rdreq_1),
+      .fifodata(tdpf_fifodata_1),
+      .pkt_waiting(tdpf_pkt_waiting_1)
+   );
+   
+endmodule // tx_buffer
+
diff --git a/usrp/fpga/inband_lib/usb_fifo_reader.v b/usrp/fpga/inband_lib/usb_fifo_reader.v
new file mode 100755 (executable)
index 0000000..170c70f
--- /dev/null
@@ -0,0 +1,135 @@
+module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset,
+      rdreq, skip, done_chan, WR_chan, tx_data_bus);
+      
+    /* Module parameters */
+    parameter                       NUM_CHAN      =   2 ;
+    parameter                       WIDTH         =   32 ;
+    
+    input   wire                    tx_clock ;
+    input   wire                    reset ;
+    input   wire       [WIDTH-1:0]  fifodata ;
+    input   wire                    pkt_waiting ;
+    output  reg                     rdreq ;
+    output  reg                     skip ;
+    output  reg        [NUM_CHAN:0] done_chan ;
+    output  reg        [NUM_CHAN:0] WR_chan ;
+    output  reg        [WIDTH-1:0]  tx_data_bus ;
+     
+   
+   
+    /* States definition */
+    `define IDLE                      3'd0
+    `define WAIT                      3'd1
+    `define READ_HEADER               3'd2
+    `define FORWARD_DATA              3'd3
+    `define SKIP_REST                 3'd4
+   
+    /* Channel Ids */
+    `define TXCHAN0                   5'h0
+    `define TXCHAN1                   5'h1
+    `define TXCMD                     5'h1F
+   
+    /* Local registers */
+    reg                      [2:0]    reader_state ;
+    reg                      [2:0]    reader_next_state ;
+    reg                      [4:0]    channel ;
+    reg                      [8:0]    pkt_length ;
+    reg                      [8:0]    read_length ;
+    
+    /* State Machine */
+    always @(posedge tx_clock)
+    begin
+        if (reset) 
+                 begin
+                     reader_state <= `IDLE ;
+            reader_next_state <= `IDLE ;
+            rdreq <= 0 ;
+            skip <= 0 ;
+            WR_chan <= {NUM_CHAN+1{1'b0}} ;
+            done_chan <= {NUM_CHAN+1{1'b0}} ;
+          end
+        else 
+                 begin
+            reader_state = reader_next_state ;
+            
+            case(reader_state)
+            `IDLE: 
+                               begin
+                                   reader_next_state <= pkt_waiting ? `WAIT : `IDLE ;
+                rdreq <= pkt_waiting ;
+            end
+     
+            /* Wait for the fifo's data to show up */
+            `WAIT:
+            begin
+                              reader_next_state <= `READ_HEADER ;
+            end
+               
+            `READ_HEADER: 
+                          begin
+                reader_next_state <= `FORWARD_DATA ;
+                  
+                /* Read header fields */
+                channel <= (fifodata & 32'h1F0000) ;
+                pkt_length <= (fifodata & 16'h1FF) + 4 ;
+                read_length <= 9'd0 ;
+                  
+                /* Forward data */
+                case (channel)
+                    `TXCHAN0: WR_chan[0] <= 1 ;
+                    `TXCHAN1: WR_chan[1] <= 1 ;
+                    `TXCMD:   WR_chan[2] <= 1 ;
+                    default:  WR_chan <= 1 ;
+                endcase
+                tx_data_bus <= fifodata ;
+            end
+               
+            `FORWARD_DATA:
+                          begin
+                read_length <= read_length + 4 ;
+                  
+                // If end of payload...
+                if (read_length == pkt_length)
+                                   begin
+                    reader_next_state <= `SKIP_REST ;
+                    /* If the packet is 512 bytes, don't skip */
+                    skip <= pkt_length < 506 ;
+                     
+                    /* Data pushing done */
+                    WR_chan <= {NUM_CHAN+1{1'b0}} ;
+                    
+                    /* Notify next block */
+                    case (channel)
+                       `TXCHAN0: done_chan[0] <= 1 ;
+                       `TXCHAN1: done_chan[1] <= 1 ;
+                       `TXCMD:   done_chan[2] <= 1 ;
+                       default:  done_chan[0] <= 1 ;
+                    endcase
+                end
+                else if (read_length == pkt_length - 4)
+                    rdreq <= 0 ;
+                    
+                /* Forward data */
+                tx_data_bus <= fifodata ;
+            end
+               
+            `SKIP_REST: 
+                          begin
+                              reader_next_state <= pkt_waiting ? `READ_HEADER : `IDLE ;
+                done_chan <= {NUM_CHAN+1{1'b0}} ;
+                rdreq <= pkt_waiting ;
+                skip <= 0 ;
+            end
+                
+            default: 
+                          begin
+                reader_state <= `IDLE;
+                reader_next_state <= `IDLE;
+            end
+            endcase
+        end
+    end  
+endmodule
+       
+   
+   
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/usb_packet_fifo.v b/usrp/fpga/inband_lib/usb_packet_fifo.v
new file mode 100755 (executable)
index 0000000..c416e2b
--- /dev/null
@@ -0,0 +1,112 @@
+module usb_packet_fifo 
+  ( input       reset,
+    input       clock_in,
+    input       clock_out,
+    input       [15:0]ram_data_in,
+    input       write_enable,
+    output  reg [15:0]ram_data_out,
+    output  reg pkt_waiting,
+    output  reg have_space,
+    input       read_enable,
+    input       skip_packet          ) ;
+
+    /* Some parameters for usage later on */
+    parameter DATA_WIDTH = 16 ;
+    parameter NUM_PACKETS = 4 ;
+
+    /* Create the RAM here */
+    reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
+
+    /* Create the address signals */
+    reg [7-2+NUM_PACKETS:0] usb_ram_ain ;
+    reg [7:0] usb_ram_offset ;
+    reg [1:0] usb_ram_packet ;
+
+    wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
+    reg isfull;
+
+    assign usb_ram_aout = {usb_ram_packet,usb_ram_offset} ;
+    
+    // Check if there is one full packet to process
+    always @(usb_ram_ain, usb_ram_aout)
+    begin
+        if (reset)
+            pkt_waiting <= 0;
+        else if (usb_ram_ain == usb_ram_aout)
+            pkt_waiting <= isfull;
+        else if (usb_ram_ain > usb_ram_aout)
+            pkt_waiting <= (usb_ram_ain - usb_ram_aout) >= 256;
+        else
+            pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
+    end
+    
+    // Check if there is room
+    always @(usb_ram_ain, usb_ram_aout)
+    begin
+        if (reset)
+            have_space <= 1;
+        else if (usb_ram_ain == usb_ram_aout)
+            have_space <= ~isfull;   
+        else if (usb_ram_ain > usb_ram_aout)
+            have_space <= (usb_ram_ain - usb_ram_aout) <= 256 * (NUM_PACKETS - 1);
+        else
+            have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
+    end
+
+    /* RAM Write Address process */
+    always @(posedge clock_in)
+    begin
+        if( reset )
+            usb_ram_ain <= 0 ;
+        else
+            if( write_enable ) 
+              begin
+                usb_ram_ain <= usb_ram_ain + 1 ;
+                if (usb_ram_ain + 1 == usb_ram_aout)
+                   isfull <= 1;
+              end
+    end
+
+    /* RAM Writing process */
+    always @(posedge clock_in)
+    begin
+        if( write_enable ) 
+          begin
+            usb_ram[usb_ram_ain] <= ram_data_in ;
+          end
+    end
+
+    /* RAM Read Address process */
+    always @(posedge clock_out)
+    begin
+        if( reset ) 
+          begin
+            usb_ram_packet <= 0 ;
+            usb_ram_offset <= 0 ;
+            isfull <= 0;
+          end
+        else
+            if( skip_packet )
+              begin
+                usb_ram_packet <= usb_ram_packet + 1 ;
+                usb_ram_offset <= 0 ;
+              end
+            else if(read_enable)
+                if( usb_ram_offset == 8'b11111111 )
+                  begin
+                    usb_ram_offset <= 0 ;
+                    usb_ram_packet <= usb_ram_packet + 1 ;
+                  end
+                else
+                    usb_ram_offset <= usb_ram_offset + 1 ;
+            if (usb_ram_ain == usb_ram_aout)
+               isfull <= 0;                       
+    end
+
+    /* RAM Reading Process */
+    always @(posedge clock_out)
+    begin
+        ram_data_out <= usb_ram[usb_ram_aout] ;
+    end
+
+endmodule
\ No newline at end of file
diff --git a/usrp/fpga/inband_lib/usb_packet_fifo2.v b/usrp/fpga/inband_lib/usb_packet_fifo2.v
new file mode 100755 (executable)
index 0000000..d815e4e
--- /dev/null
@@ -0,0 +1,119 @@
+`default_nettype none
+
+module usb_packet_fifo2(reset, usb_clock, fpga_clock, write_enable, write_data, 
+        read_enable, skip_packet, read_data, have_space, pkt_waiting, tx_empty) ;
+    
+    /* Module parameters */
+    parameter                       LOG2_N          =   2 ;
+    parameter                       BUS_WIDTH       =   16 ;
+    parameter                       FIFO_WIDTH      =   32 ;
+
+    input   wire                    reset;
+    input   wire                    usb_clock ;
+    input   wire                    fpga_clock ;
+    input   wire                    write_enable ;
+    input   wire    [BUS_WIDTH-1:0] write_data ;
+    input   wire                    read_enable ;
+    input   wire                    skip_packet ;
+    output  wire   [FIFO_WIDTH-1:0] read_data ;
+    output  wire                    have_space ;
+    output  wire                    pkt_waiting ;
+    output  wire                    tx_empty;
+
+    
+    /* Variable for generate statement */
+    genvar i ;
+    
+    /* Local wires for FIFO connections */
+    wire                      [2**LOG2_N-1:0]     fifo_resets ;
+    reg                       [2**LOG2_N-1:0]     fifo_we ;
+    wire                      [2**LOG2_N-1:0]     fifo_re ;
+    reg                       [FIFO_WIDTH-1:0]    fifo_wdata[2**LOG2_N-1:0] ;
+    wire                      [FIFO_WIDTH-1:0]    fifo_rdata[2**LOG2_N-1:0] ;
+    wire                      [2**LOG2_N-1:0]     fifo_rempty ;
+    wire                      [2**LOG2_N-1:0]     fifo_rfull ;
+    wire                      [2**LOG2_N-1:0]     fifo_wempty ;
+    wire                      [2**LOG2_N-1:0]     fifo_wfull ;
+    
+    /* FIFO Select for read and write ports */
+    reg     [LOG2_N-1:0]            fifo_rselect ;
+    reg     [LOG2_N-1:0]            fifo_wselect ;
+    
+    /* Used to convert 16 bits usbdata to the 32 bits wide fifo */
+    reg                             word_complete ;
+    reg     [BUS_WIDTH-1:0]         write_data_delayed ;
+    
+    /* Assign have_space to empty flag of currently selected write FIFO */
+    assign have_space = fifo_wempty[fifo_wselect] ;
+    
+    /* Assign pkt_waiting to full flag of currently selected read FIFO */
+    assign pkt_waiting = fifo_rfull[fifo_rselect] ;
+    
+    /* Assign the read_data to the output of the currently selected FIFO */
+    assign read_data = fifo_rdata[fifo_rselect] ;
+    
+    /* Figure out if we're all empty */
+    assign tx_empty = !(~fifo_rempty) ;
+    
+    /* Increment fifo_rselect here */
+    always @(posedge fpga_clock)
+    begin
+        if (reset)
+            fifo_rselect <= {2**LOG2_N{1'b0}} ;
+        
+        if (fifo_rempty[fifo_rselect])
+            fifo_rselect <= fifo_rselect + 1 ;
+            
+        if (skip_packet)
+            fifo_rselect <= fifo_rselect + 1 ;
+    end
+    
+    /* Increment fifo_wselect and pack data into 32 bits block  */
+    always @(posedge usb_clock, reset)
+    begin
+        if (reset)
+          begin
+            fifo_wselect <= {2**LOG2_N{1'b0}} ;
+            word_complete <= 0;
+          end
+            
+        if (fifo_wfull[fifo_wselect])
+            fifo_wselect <= fifo_wselect + 1 ;
+            
+        if (write_enable)
+          begin
+            word_complete <= ~word_complete ;
+            
+            if (word_complete)
+                fifo_wdata[fifo_wselect] <= {write_data_delayed, write_data} ;
+            else
+                write_data_delayed <= write_data ;
+              
+            /* Avoid to continue to write in the previous fifo when we have 
+               just swichted to the next one */ 
+            fifo_we[fifo_wselect-1] <= 0 ;
+            
+            fifo_we[fifo_wselect] <= write_enable & word_complete ;
+          end
+    end
+    
+    /* Generate all the single packet FIFOs */
+    generate
+        for( i = 0 ; i < 2**LOG2_N ; i = i + 1 )
+        begin : generate_single_packet_fifos
+            assign fifo_re[i] = (fifo_rselect == i) ? read_enable : 1'b0 ;
+            assign fifo_resets[i] = (fifo_rselect == i) ? skip_packet : 1'b0 ;
+            fifo_512 single_packet_fifo(.wrclk  ( usb_clock      ),
+                                        .rdclk  ( fpga_clock     ),
+                                        .aclr   ( fifo_resets[i] ), 
+                                        .wrreq  ( fifo_we[i]     ),
+                                        .data   ( fifo_wdata[i]  ),
+                                        .rdreq  ( fifo_re[i]     ),
+                                        .q      ( fifo_rdata[i]  ),
+                                        .rdfull ( fifo_rfull[i]  ),
+                                        .rdempty( fifo_rempty[i] ),
+                                        .wrfull ( fifo_wfull[i]  ),
+                                        .wrempty( fifo_wempty[i] ) ) ;
+        end
+    endgenerate
+endmodule 
\ No newline at end of file
diff --git a/usrp/fpga/megacells/fifo_512.bsf b/usrp/fpga/megacells/fifo_512.bsf
new file mode 100755 (executable)
index 0000000..a955b56
--- /dev/null
@@ -0,0 +1,116 @@
+/*\r
+WARNING: Do NOT edit the input and output ports in this file in a text\r
+editor if you plan to continue editing the block that represents it in\r
+the Block Editor! File corruption is VERY likely to occur.\r
+*/\r
+/*\r
+Copyright (C) 1991-2006 Altera Corporation\r
+Your use of Altera Corporation's design tools, logic functions \r
+and other software and tools, and its AMPP partner logic \r
+functions, and any output files any of the foregoing \r
+(including device programming or simulation files), and any \r
+associated documentation or information are expressly subject \r
+to the terms and conditions of the Altera Program License \r
+Subscription Agreement, Altera MegaCore Function License \r
+Agreement, or other applicable license agreement, including, \r
+without limitation, that your use is for the sole purpose of \r
+programming logic devices manufactured by Altera and sold by \r
+Altera or its authorized distributors.  Please refer to the \r
+applicable agreement for further details.\r
+*/\r
+(header "symbol" (version "1.1"))\r
+(symbol\r
+       (rect 0 0 160 184)\r
+       (text "fifo_512" (rect 58 1 109 17)(font "Arial" (font_size 10)))\r
+       (text "inst" (rect 8 168 25 180)(font "Arial" ))\r
+       (port\r
+               (pt 0 32)\r
+               (input)\r
+               (text "data[31..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))\r
+               (text "data[31..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))\r
+               (line (pt 0 32)(pt 16 32)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 0 56)\r
+               (input)\r
+               (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))\r
+               (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))\r
+               (line (pt 0 56)(pt 16 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 72)\r
+               (input)\r
+               (text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))\r
+               (text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))\r
+               (line (pt 0 72)(pt 16 72)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 104)\r
+               (input)\r
+               (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))\r
+               (text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))\r
+               (line (pt 0 104)(pt 16 104)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 120)\r
+               (input)\r
+               (text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))\r
+               (text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))\r
+               (line (pt 0 120)(pt 16 120)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 0 160)\r
+               (input)\r
+               (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))\r
+               (text "aclr" (rect 20 154 37 167)(font "Arial" (font_size 8)))\r
+               (line (pt 0 160)(pt 16 160)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 40)\r
+               (output)\r
+               (text "wrfull" (rect 0 0 33 14)(font "Arial" (font_size 8)))\r
+               (text "wrfull" (rect 113 34 138 47)(font "Arial" (font_size 8)))\r
+               (line (pt 160 40)(pt 144 40)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 56)\r
+               (output)\r
+               (text "wrempty" (rect 0 0 50 14)(font "Arial" (font_size 8)))\r
+               (text "wrempty" (rect 98 50 137 63)(font "Arial" (font_size 8)))\r
+               (line (pt 160 56)(pt 144 56)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 96)\r
+               (output)\r
+               (text "q[31..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))\r
+               (text "q[31..0]" (rect 105 90 141 103)(font "Arial" (font_size 8)))\r
+               (line (pt 160 96)(pt 144 96)(line_width 3))\r
+       )\r
+       (port\r
+               (pt 160 120)\r
+               (output)\r
+               (text "rdfull" (rect 0 0 28 14)(font "Arial" (font_size 8)))\r
+               (text "rdfull" (rect 117 114 141 127)(font "Arial" (font_size 8)))\r
+               (line (pt 160 120)(pt 144 120)(line_width 1))\r
+       )\r
+       (port\r
+               (pt 160 136)\r
+               (output)\r
+               (text "rdempty" (rect 0 0 46 14)(font "Arial" (font_size 8)))\r
+               (text "rdempty" (rect 102 130 140 143)(font "Arial" (font_size 8)))\r
+               (line (pt 160 136)(pt 144 136)(line_width 1))\r
+       )\r
+       (drawing\r
+               (text "32 bits x 128 words" (rect 63 156 144 168)(font "Arial" ))\r
+               (line (pt 16 16)(pt 144 16)(line_width 1))\r
+               (line (pt 144 16)(pt 144 168)(line_width 1))\r
+               (line (pt 144 168)(pt 16 168)(line_width 1))\r
+               (line (pt 16 168)(pt 16 16)(line_width 1))\r
+               (line (pt 16 84)(pt 144 84)(line_width 1))\r
+               (line (pt 16 148)(pt 144 148)(line_width 1))\r
+               (line (pt 16 66)(pt 22 72)(line_width 1))\r
+               (line (pt 22 72)(pt 16 78)(line_width 1))\r
+               (line (pt 16 114)(pt 22 120)(line_width 1))\r
+               (line (pt 22 120)(pt 16 126)(line_width 1))\r
+       )\r
+)\r
diff --git a/usrp/fpga/megacells/fifo_512.cmp b/usrp/fpga/megacells/fifo_512.cmp
new file mode 100755 (executable)
index 0000000..86fc078
--- /dev/null
@@ -0,0 +1,31 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+component fifo_512\r
+       PORT\r
+       (\r
+               aclr            : IN STD_LOGIC  := '0';\r
+               data            : IN STD_LOGIC_VECTOR (31 DOWNTO 0);\r
+               rdclk           : IN STD_LOGIC ;\r
+               rdreq           : IN STD_LOGIC ;\r
+               wrclk           : IN STD_LOGIC ;\r
+               wrreq           : IN STD_LOGIC ;\r
+               q               : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);\r
+               rdempty         : OUT STD_LOGIC ;\r
+               rdfull          : OUT STD_LOGIC ;\r
+               wrempty         : OUT STD_LOGIC ;\r
+               wrfull          : OUT STD_LOGIC \r
+       );\r
+end component;\r
diff --git a/usrp/fpga/megacells/fifo_512.inc b/usrp/fpga/megacells/fifo_512.inc
new file mode 100755 (executable)
index 0000000..9ae1e3a
--- /dev/null
@@ -0,0 +1,32 @@
+--Copyright (C) 1991-2006 Altera Corporation\r
+--Your use of Altera Corporation's design tools, logic functions \r
+--and other software and tools, and its AMPP partner logic \r
+--functions, and any output files any of the foregoing \r
+--(including device programming or simulation files), and any \r
+--associated documentation or information are expressly subject \r
+--to the terms and conditions of the Altera Program License \r
+--Subscription Agreement, Altera MegaCore Function License \r
+--Agreement, or other applicable license agreement, including, \r
+--without limitation, that your use is for the sole purpose of \r
+--programming logic devices manufactured by Altera and sold by \r
+--Altera or its authorized distributors.  Please refer to the \r
+--applicable agreement for further details.\r
+\r
+\r
+FUNCTION fifo_512 \r
+(\r
+       aclr,\r
+       data[31..0],\r
+       rdclk,\r
+       rdreq,\r
+       wrclk,\r
+       wrreq\r
+)\r
+\r
+RETURNS (\r
+       q[31..0],\r
+       rdempty,\r
+       rdfull,\r
+       wrempty,\r
+       wrfull\r
+);\r
diff --git a/usrp/fpga/megacells/fifo_512.v b/usrp/fpga/megacells/fifo_512.v
new file mode 100755 (executable)
index 0000000..b034b4d
--- /dev/null
@@ -0,0 +1,180 @@
+// megafunction wizard: %LPM_FIFO+%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: dcfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_512.v\r
+// Megafunction Name(s):\r
+//                     dcfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+\r
+// synopsys translate_off\r
+`timescale 1 ps / 1 ps\r
+// synopsys translate_on\r
+module fifo_512 (\r
+       aclr,\r
+       data,\r
+       rdclk,\r
+       rdreq,\r
+       wrclk,\r
+       wrreq,\r
+       q,\r
+       rdempty,\r
+       rdfull,\r
+       wrempty,\r
+       wrfull);\r
+\r
+       input     aclr;\r
+       input   [31:0]  data;\r
+       input     rdclk;\r
+       input     rdreq;\r
+       input     wrclk;\r
+       input     wrreq;\r
+       output  [31:0]  q;\r
+       output    rdempty;\r
+       output    rdfull;\r
+       output    wrempty;\r
+       output    wrfull;\r
+\r
+       wire  sub_wire0;\r
+       wire  sub_wire1;\r
+       wire  sub_wire2;\r
+       wire  sub_wire3;\r
+       wire [31:0] sub_wire4;\r
+       wire  rdfull = sub_wire0;\r
+       wire  rdempty = sub_wire1;\r
+       wire  wrfull = sub_wire2;\r
+       wire  wrempty = sub_wire3;\r
+       wire [31:0] q = sub_wire4[31:0];\r
+\r
+       dcfifo  dcfifo_component (\r
+                               .wrclk (wrclk),\r
+                               .rdreq (rdreq),\r
+                               .aclr (aclr),\r
+                               .rdclk (rdclk),\r
+                               .wrreq (wrreq),\r
+                               .data (data),\r
+                               .rdfull (sub_wire0),\r
+                               .rdempty (sub_wire1),\r
+                               .wrfull (sub_wire2),\r
+                               .wrempty (sub_wire3),\r
+                               .q (sub_wire4)\r
+                               // synopsys translate_off\r
+                               ,\r
+                               .rdusedw (),\r
+                               .wrusedw ()\r
+                               // synopsys translate_on\r
+                               );\r
+       defparam\r
+               dcfifo_component.add_ram_output_register = "OFF",\r
+               dcfifo_component.clocks_are_synchronized = "FALSE",\r
+               dcfifo_component.intended_device_family = "Cyclone",\r
+               dcfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",\r
+               dcfifo_component.lpm_numwords = 128,\r
+               dcfifo_component.lpm_showahead = "OFF",\r
+               dcfifo_component.lpm_type = "dcfifo",\r
+               dcfifo_component.lpm_width = 32,\r
+               dcfifo_component.lpm_widthu = 7,\r
+               dcfifo_component.overflow_checking = "ON",\r
+               dcfifo_component.underflow_checking = "ON",\r
+               dcfifo_component.use_eab = "ON";\r
+\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "4"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "128"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "32"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr\r
+// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]\r
+// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]\r
+// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk\r
+// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty\r
+// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk\r
+// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty\r
+// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0\r
+// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0\r
+// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0\r
+// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0\r
+// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0\r
+// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0\r
+// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE\r
diff --git a/usrp/fpga/megacells/fifo_512_bb.v b/usrp/fpga/megacells/fifo_512_bb.v
new file mode 100755 (executable)
index 0000000..b118031
--- /dev/null
@@ -0,0 +1,131 @@
+// megafunction wizard: %LPM_FIFO+%VBB%\r
+// GENERATION: STANDARD\r
+// VERSION: WM1.0\r
+// MODULE: dcfifo \r
+\r
+// ============================================================\r
+// File Name: fifo_512.v\r
+// Megafunction Name(s):\r
+//                     dcfifo\r
+// ============================================================\r
+// ************************************************************\r
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!\r
+//\r
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition\r
+// ************************************************************\r
+\r
+//Copyright (C) 1991-2006 Altera Corporation\r
+//Your use of Altera Corporation's design tools, logic functions \r
+//and other software and tools, and its AMPP partner logic \r
+//functions, and any output files any of the foregoing \r
+//(including device programming or simulation files), and any \r
+//associated documentation or information are expressly subject \r
+//to the terms and conditions of the Altera Program License \r
+//Subscription Agreement, Altera MegaCore Function License \r
+//Agreement, or other applicable license agreement, including, \r
+//without limitation, that your use is for the sole purpose of \r
+//programming logic devices manufactured by Altera and sold by \r
+//Altera or its authorized distributors.  Please refer to the \r
+//applicable agreement for further details.\r
+\r
+module fifo_512 (\r
+       aclr,\r
+       data,\r
+       rdclk,\r
+       rdreq,\r
+       wrclk,\r
+       wrreq,\r
+       q,\r
+       rdempty,\r
+       rdfull,\r
+       wrempty,\r
+       wrfull);\r
+\r
+       input     aclr;\r
+       input   [31:0]  data;\r
+       input     rdclk;\r
+       input     rdreq;\r
+       input     wrclk;\r
+       input     wrreq;\r
+       output  [31:0]  q;\r
+       output    rdempty;\r
+       output    rdfull;\r
+       output    wrempty;\r
+       output    wrfull;\r
+\r
+endmodule\r
+\r
+// ============================================================\r
+// CNX file retrieval info\r
+// ============================================================\r
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"\r
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"\r
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"\r
+// Retrieval info: PRIVATE: Clock NUMERIC "4"\r
+// Retrieval info: PRIVATE: Depth NUMERIC "128"\r
+// Retrieval info: PRIVATE: Empty NUMERIC "1"\r
+// Retrieval info: PRIVATE: Full NUMERIC "1"\r
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"\r
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"\r
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"\r
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"\r
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"\r
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"\r
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"\r
+// Retrieval info: PRIVATE: Width NUMERIC "32"\r
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"\r
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"\r
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"\r
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"\r
+// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"\r
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"\r
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"\r
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"\r
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"\r
+// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"\r
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"\r
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"\r
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"\r
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"\r
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr\r
+// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]\r
+// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]\r
+// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk\r
+// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty\r
+// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull\r
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq\r
+// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk\r
+// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty\r
+// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull\r
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq\r
+// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0\r
+// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0\r
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0\r
+// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0\r
+// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0\r
+// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0\r
+// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0\r
+// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0\r
+// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0\r
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0\r
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE\r
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE\r
index 2646d831f62cc355618a93acde69382c00b358ea..8296a453e05a5f446091d2cb21f1dde85adbdbd2 100644 (file)
@@ -27,7 +27,7 @@
 # ========================
 set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0
 set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04  JULY 13, 2003"
-set_global_assignment -name LAST_QUARTUS_VERSION 6.1
+set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP1"
 
 # Pin & Location Assignments
 # ==========================
@@ -371,6 +371,13 @@ set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk
 
 set_instance_assignment -name PARTITION_HIERARCHY no_file_for_top_partition -to | -section_id Top
 set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN "100 ps"
+set_global_assignment -name VERILOG_FILE ../../inband_lib/tx_buffer_inband.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_packet_fifo.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/chan_fifo_reader.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/data_packet_fifo.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_fifo_reader.v
+set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_dec_shifter.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/rssi.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v
 set_global_assignment -name VERILOG_FILE ../../megacells/fifo_4k.v
@@ -405,5 +412,4 @@ set_global_assignment -name VERILOG_FILE usrp_inband_usb.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v
 set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v
-set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
-set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN "100 ps"
\ No newline at end of file
+set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
\ No newline at end of file
index 55701b897d661f4db24d8e1ecdf30579eb70cbbb..cc7490c5a12b1dd2130be692e463e30244f5b9c0 100644 (file)
@@ -19,6 +19,7 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
 //
+`define IN_BAND
 
 `include "config.vh"
 `include "../../../firmware/include/fpga_regs_common.v"
@@ -122,6 +123,20 @@ module usrp_inband_usb
    assign      bb_tx_i1 = ch2tx;
    assign      bb_tx_q1 = ch3tx;
    
+`ifdef IN_BAND
+       tx_buffer_inband tx_buffer
+     ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
+       .usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun),
+       .channels({tx_numchan,1'b0}),
+       .tx_i_0(ch0tx),.tx_q_0(ch1tx),
+       .tx_i_1(ch2tx),.tx_q_1(ch3tx),
+       .tx_i_2(),.tx_q_2(),
+       .tx_i_3(),.tx_q_3(),
+       .txclk(clk64),.txstrobe(strobe_interp),
+       .clear_status(clear_status),
+       .tx_empty(tx_empty),
+       .debugbus(tx_debugbus) );
+`else
    tx_buffer tx_buffer
      ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
        .usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun),
@@ -134,6 +149,7 @@ module usrp_inband_usb
        .clear_status(clear_status),
        .tx_empty(tx_empty),
        .debugbus(tx_debugbus) );
+`endif
 
  `ifdef TX_EN_0
    tx_chain tx_chain_0
index 8e0768e844665092e9afc827dc4280064e75d46f..035a23ab7ac2910d5f9e8c20430e47f80c085a27 100644 (file)
@@ -23,8 +23,6 @@ include $(top_srcdir)/Makefile.common
 
 INCLUDES = $(USRP_INCLUDES) $(BOOST_CFLAGS)
 
-USRP_LIB = $(top_builddir)/usrp/host/lib/libusrp.la
-
 bin_PROGRAMS =                         \
        usrper                          \
        usrp_cal_dc_offset              
@@ -45,13 +43,13 @@ noinst_PYTHON =                             \
 check_order_quickly_SOURCES    = check_order_quickly.cc
 
 test_usrp_standard_rx_SOURCES  = test_usrp_standard_rx.cc time_stuff.c
-test_usrp_standard_rx_LDADD    = $(USRP_LIB)
+test_usrp_standard_rx_LDADD    = $(USRP_LA)
 
 test_usrp_standard_tx_SOURCES  = test_usrp_standard_tx.cc time_stuff.c
-test_usrp_standard_tx_LDADD    = $(USRP_LIB)
+test_usrp_standard_tx_LDADD    = $(USRP_LA)
 
 usrper_SOURCES                 = usrper.cc
-usrper_LDADD                   = $(USRP_LIB)
+usrper_LDADD                   = $(USRP_LA)
 
 usrp_cal_dc_offset_SOURCES     = usrp_cal_dc_offset.cc
-usrp_cal_dc_offset_LDADD       = $(USRP_LIB)
+usrp_cal_dc_offset_LDADD       = $(USRP_LA)
index 7d17a380af45493ba8201c60c103d8084470afd6..cd37a9b2b186b26af2a370184894b139ef4ca23d 100644 (file)
 
 include $(top_srcdir)/Makefile.common
 
-INCLUDES = $(USRP_INCLUDES)
+SUBDIRS = legacy inband
 
-lib_LTLIBRARIES = libusrp.la
-
-
-EXTRA_DIST =                           \
-       std_paths.h.in                  \
-       usrp_dbid.dat                   
-
-
-BUILT_SOURCES =                        \
-       usrp_dbid.h                     \
-       usrp_dbid.cc                    \
-       usrp_dbid.py                    
-
-
-# ----------------------------------------------------------------
-# FUSB_TECH is set at configure time by way of
-#   usrp/config/usrp_fusb_tech.m4.
-#   It indicates which fast usb strategy we should be building.
-#   We currently implement "generic", "darwin", "win32" and "linux"
-
-
-generic_CODE =                                 \
-       fusb_generic.cc                 \
-       fusb_sysconfig_generic.cc
-
-darwin_CODE =                          \
-       fusb_darwin.cc                  \
-       fusb_sysconfig_darwin.cc        \
-       README_OSX                      \
-       circular_buffer.h               \
-       circular_linked_list.h          \
-       darwin_libusb.h                 \
-       mld_threads.h                   
-
-win32_CODE =                           \
-       fusb_win32.cc                   \
-       fusb_sysconfig_win32.cc         
-
-linux_CODE =                           \
-       fusb_linux.cc                   \
-       fusb_sysconfig_linux.cc         
-
-ra_wb_CODE =                           \
-       fusb_ra_wb.cc                   \
-       fusb_sysconfig_ra_wb.cc
-
-
-#
-# include each <foo>_CODE entry here...
-#
-EXTRA_libusrp_la_SOURCES =             \
-       $(generic_CODE)                 \
-       $(darwin_CODE)                  \
-       $(win32_CODE)                   \
-       $(linux_CODE)                   \
-       $(ra_wb_CODE)
-
-
-# work around automake deficiency
-libusrp_la_common_SOURCES =            \
-       fusb.cc                         \
-       md5.c                           \
-       usrp_basic.cc                   \
-       usrp_config.cc                  \
-       usrp_dbid.cc                    \
-       usrp_local_sighandler.cc        \
-       usrp_prims.cc                   \
-       usrp_standard.cc
-
-
-if FUSB_TECH_generic
-libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE)
-endif
-
-if FUSB_TECH_darwin
-libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(darwin_CODE)
-endif
-
-if FUSB_TECH_win32
-libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(win32_CODE)
-endif
-
-if FUSB_TECH_linux
-libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(linux_CODE)
-endif
-
-if FUSB_TECH_ra_wb
-libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(ra_wb_CODE)
-endif
-
-
-libusrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
-libusrp_la_LIBADD = $(USB_LIBS) ../misc/libmisc.la
-
-include_HEADERS =                      \
-       usrp_basic.h                    \
-       usrp_bytesex.h                  \
-       usrp_config.h                   \
-       usrp_dbid.h                     \
-       usrp_prims.h                    \
-       usrp_slots.h                    \
-       usrp_standard.h                 
-
-noinst_HEADERS =                       \
-       ad9862.h                        \
-       fusb.h                          \
-       fusb_darwin.h                   \
-       fusb_win32.h                    \
-       fusb_generic.h                  \
-       fusb_linux.h                    \
-       fusb_ra_wb.h                    \
-       md5.h                           \
-       rate_to_regval.h                \
-       usrp_local_sighandler.h         
-
-usrppython_PYTHON =                    \
-       usrp_dbid.py                    
-
-noinst_PYTHON =                                \
-       gen_usrp_dbid.py                \
-       check_data.py                   \
-       dump_data.py
-
-usrp_dbid.py usrp_dbid.h usrp_dbid.cc: gen_usrp_dbid.py usrp_dbid.dat
-       PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat
-
-MOSTLYCLEANFILES = \
-       $(BUILT_SOURCES) *~ *.pyc
diff --git a/usrp/host/lib/README_OSX b/usrp/host/lib/README_OSX
deleted file mode 100644 (file)
index 20230f1..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-USRP Darwin Fast USB Changes
-Version 0.2 of 2006-04-27
-Michael Dickens <mdickens @at@ nd .dot. edu>
-
-The files included in this archive are:
-
-circular_buffer.h
-circular_linked_list.h
-darwin_libusb.h
-fusb_darwin.cc
-fusb_darwin.h
-mld_threads.h
-
-These files allow GNURadio code for Darwin / MaxOS X to talk to the
-USRP via USB 2.0 at rates up to around 30 Mega-Bytes/sec (MBps), up
-from 4-8 MBps without the changes.
-
-I implemented the buffering myself; there are probably GR buffers
-available which would do the work but as this is "beta" software it's
-a good place to start.  Speed improvements are made by porting
-LIBUSB's non-true async bulk read and write functions into USRP's
-"fusb", and upgrading them to handle -true- async transfers.
-Unfortunately, the easiest way to do this is to spawn a thread or 2 to
-handle the "async" part of the transfers.  This implementation uses
-Darwin's pthreads to do the work for mutexes, conditions, and threads.
-Previous implementations (0.1 and before) used "omni_threads" as
-provided by gnuradio-core, which caused issues with compiling and
-execution ... I'm glad that this is no longer the case.
-
-As far as I have tested, there is no way to improve the throughput to
-32+ MBps without moving into Darwin's "port"s ... a kernel-level data
-transport method with a user/application layer for USB-specific
-functions.  Unfortunately, Apple's documentation for these "port"s is
-minimal; I have learned more from reading the Darwin source code
-< http://darwinsource.opendarwin.org/ > than by reading Apple's
-documents!  This would also require -not- using LIBUSB, of which the
-removal from the rest of the USRP code would be potentially tedious.
-
-If you run into issues either compiling or testing the USRP on
-OSX, please send me a note.
-
-(1) Go through the bootstrap, configure, compile, and install as
-usual (e.g. see < http://www.nd.edu/~mdickens/GNURadio/ > for my
-usual).
-
-(2) from .../usrp/host/apps :  run the scripts
-++++++++++++++++
-./test_usrp_standard_tx
-./test_usrp_standard_rx
-++++++++++++++++
-
-For -all- systems I've tested on thus far, both of these return
-exactly 41 overruns / underruns, and -most- systems start out with a
-stalled pipe.  This stall comes in a usb_control funciton call to
-LIBUSB; one would have to change the LIBUSB code to handle this issue.
-
-(3) from gr-build/gnuradio-examples/python/usrp :
-++++++++++++++++
-./benchmark_usb.py
-++++++++++++++++
-
-(4) If you get to here, the try doing the FM receiver (gui or not).
-If that sounds correct, then the USB is working.  Yay!
\ No newline at end of file
diff --git a/usrp/host/lib/ad9862.h b/usrp/host/lib/ad9862.h
deleted file mode 100644 (file)
index d1895bb..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_AD9862_H
-#define INCLUDED_AD9862_H
-
-/*
- * Analog Devices AD9862 registers and some fields
- */
-
-#define BEGIN_AD9862   namespace ad9862 {
-#define        END_AD962       }
-#define        DEF static const int
-
-BEGIN_AD9862;
-
-DEF REG_GENERAL                =  0;
-DEF REG_RX_PWR_DN      =  1;
-DEF    RX_PWR_DN_VREF_DIFF             = (1 << 7);
-DEF    RX_PWR_DN_VREF                  = (1 << 6);
-DEF    RX_PWR_DN_RX_DIGIGAL            = (1 << 5);
-DEF    RX_PWR_DN_RX_B                  = (1 << 4);
-DEF    RX_PWR_DN_RX_A                  = (1 << 3);
-DEF    RX_PWR_DN_BUF_B                 = (1 << 2);
-DEF    RX_PWR_DN_BUF_A                 = (1 << 1);
-DEF    RX_PWR_DN_ALL                   = (1 << 0);
-
-DEF REG_RX_A           =  2;   // bypass input buffer / RxPGA
-DEF REG_RX_B           =  3;   // pypass input buffer / RxPGA
-DEF    RX_X_BYPASS_INPUT_BUFFER        = (1 << 7);
-
-DEF REG_RX_MISC                =  4;
-DEF    RX_MISC_HS_DUTY_CYCLE           = (1 << 2);
-DEF    RX_MISC_SHARED_REF              = (1 << 1);
-DEF    RX_MISC_CLK_DUTY                = (1 << 0);
-
-DEF REG_RX_IF          =  5;
-DEF    RX_IF_THREE_STATE               = (1 << 4);
-DEF    RX_IF_USE_CLKOUT1               = (0 << 3);     
-DEF    RX_IF_USE_CLKOUT2               = (1 << 3);     // aka Rx Retime
-DEF    RX_IF_2S_COMP                   = (1 << 2);
-DEF    RX_IF_INV_RX_SYNC               = (1 << 1);
-DEF    RX_IF_MUX_OUT                   = (1 << 0);
-
-DEF REG_RX_DIGITAL     =  6;
-DEF    RX_DIGITAL_2_CHAN               = (1 << 3);
-DEF    RX_DIGITAL_KEEP_MINUS_VE        = (1 << 2);
-DEF    RX_DIGITAL_HILBERT              = (1 << 1);
-DEF    RX_DIGITAL_DECIMATE             = (1 << 0);
-
-DEF REG_RESERVED_7     =  7;
-
-DEF REG_TX_PWR_DN      =  8;
-DEF    TX_PWR_DN_ALT_TIMING_MODE       = (1 << 5);
-DEF    TX_PWR_DN_TX_OFF_ENABLE         = (1 << 4);
-DEF    TX_PWR_DN_TX_DIGITAL            = (1 << 3);
-DEF    TX_PWR_DN_TX_ANALOG_B           = 0x4;
-DEF    TX_PWR_DN_TX_ANALOG_A           = 0x2;
-DEF    TX_PWR_DN_TX_ANALOG_BOTH        = 0x7;
-
-DEF REG_RESERVED_9     =  9;
-
-DEF REG_TX_A_OFFSET_LO = 10;
-DEF REG_TX_A_OFFSET_HI = 11;
-DEF REG_TX_B_OFFSET_LO = 12;
-DEF REG_TX_B_OFFSET_HI = 13;
-
-DEF REG_TX_A_GAIN      = 14;   // fine trim for matching
-DEF REG_TX_B_GAIN      = 15;   // fine trim for matching
-DEF    TX_X_GAIN_COARSE_FULL           = (3 << 6);
-DEF    TX_X_GAIN_COARSE_1_HALF         = (1 << 6);
-DEF    TX_X_GAIN_COARSE_1_ELEVENTH     = (0 << 6);
-
-DEF REG_TX_PGA         = 16;   // 20 dB continuous gain in 0.1 dB steps
-                               // 0x00 = min gain (-20 dB)
-                               // 0xff = max gain (  0 dB)
-
-DEF REG_TX_MISC                = 17;
-DEF    TX_MISC_SLAVE_ENABLE            = (1 << 1);
-DEF    TX_MISC_TX_PGA_FAST             = (1 << 0);
-
-DEF REG_TX_IF          = 18;
-DEF    TX_IF_USE_CLKOUT2               = (0 << 6);
-DEF    TX_IF_USE_CLKOUT1               = (1 << 6);     // aka Tx Retime
-DEF    TX_IF_I_FIRST                   = (0 << 5);
-DEF    TX_IF_Q_FIRST                   = (1 << 5);
-DEF    TX_IF_INV_TX_SYNC               = (1 << 4);
-DEF    TX_IF_2S_COMP                   = (1 << 3);
-DEF    TX_IF_INVERSE_SAMPLE            = (1 << 2);
-DEF    TX_IF_TWO_EDGES                 = (1 << 1);
-DEF    TX_IF_INTERLEAVED               = (1 << 0);
-
-DEF REG_TX_DIGITAL     = 19;
-DEF    TX_DIGITAL_2_DATA_PATHS         = (1 << 4);
-DEF    TX_DIGITAL_KEEP_NEGATIVE        = (1 << 3);
-DEF    TX_DIGITAL_HILBERT              = (1 << 2);
-DEF    TX_DIGITAL_INTERPOLATE_NONE     = 0x0;
-DEF    TX_DIGITAL_INTERPOLATE_2X       = 0x1;
-DEF    TX_DIGITAL_INTERPOLATE_4X       = 0x2;
-
-DEF REG_TX_MODULATOR   = 20;
-DEF    TX_MODULATOR_NEG_FINE_TUNE      = (1 << 5);
-DEF    TX_MODULATOR_DISABLE_NCO        = (0 << 4);
-DEF    TX_MODULATOR_ENABLE_NCO         = (1 << 4);     // aka Fine Mode
-DEF    TX_MODULATOR_REAL_MIX_MODE      = (1 << 3);
-DEF    TX_MODULATOR_NEG_COARSE_TUNE    = (1 << 2);
-DEF    TX_MODULATOR_COARSE_MODULATION_NONE     = 0x0;
-DEF    TX_MODULATOR_COARSE_MODULATION_F_OVER_4 = 0x1;
-DEF    TX_MODULATOR_COARSE_MODULATION_F_OVER_8 = 0x2;
-DEF    TX_MODULATOR_CM_MASK                    = 0x7;
-
-
-DEF REG_TX_NCO_FTW_7_0 = 21;
-DEF REG_TX_NCO_FTW_15_8        = 22;
-DEF REG_TX_NCO_FTW_23_16= 23;
-
-DEF REG_DLL            = 24;
-DEF    DLL_DISABLE_INTERNAL_XTAL_OSC   = (1 << 6);     // aka Input Clock Ctrl
-DEF    DLL_ADC_DIV2                    = (1 << 5);
-DEF    DLL_MULT_1X                     = (0 << 3);
-DEF    DLL_MULT_2X                     = (1 << 3);
-DEF    DLL_MULT_4X                     = (2 << 3);
-DEF    DLL_PWR_DN                      = (1 << 2);
-// undefined bit                       = (1 << 1);
-DEF    DLL_FAST                        = (1 << 0);
-
-DEF REG_CLKOUT         = 25;
-DEF    CLKOUT2_EQ_DLL                  = (0 << 6);
-DEF    CLKOUT2_EQ_DLL_OVER_2           = (1 << 6);
-DEF    CLKOUT2_EQ_DLL_OVER_4           = (2 << 6);
-DEF    CLKOUT2_EQ_DLL_OVER_8           = (3 << 6);
-DEF    CLKOUT_INVERT_CLKOUT2           = (1 << 5);
-DEF    CLKOUT_DISABLE_CLKOUT2          = (1 << 4);
-// undefined bit                       = (1 << 3);
-// undefined bit                       = (1 << 2);
-DEF    CLKOUT_INVERT_CLKOUT1           = (1 << 1);
-DEF    CLKOUT_DISABLE_CLKOUT1          = (1 << 0);
-
-DEF REG_AUX_ADC_A2_LO  = 26;
-DEF REG_AUX_ADC_A2_HI  = 27;
-DEF REG_AUX_ADC_A1_LO  = 28;
-DEF REG_AUX_ADC_A1_HI  = 29;
-DEF REG_AUX_ADC_B2_LO  = 30;
-DEF REG_AUX_ADC_B2_HI  = 31;
-DEF REG_AUX_ADC_B1_LO  = 32;
-DEF REG_AUX_ADC_B1_HI  = 33;
-
-DEF REG_AUX_ADC_CTRL   = 34;
-DEF    AUX_ADC_CTRL_AUX_SPI            = (1 << 7);
-DEF    AUX_ADC_CTRL_SELBNOTA           = (1 << 6);
-DEF    AUX_ADC_CTRL_REFSEL_B           = (1 << 5);
-DEF    AUX_ADC_CTRL_SELECT_B2          = (0 << 4);
-DEF    AUX_ADC_CTRL_SELECT_B1          = (1 << 4);
-DEF    AUX_ADC_CTRL_START_B            = (1 << 3);
-DEF    AUX_ADC_CTRL_REFSEL_A           = (1 << 2);
-DEF    AUX_ADC_CTRL_SELECT_A2          = (0 << 1);
-DEF    AUX_ADC_CTRL_SELECT_A1          = (1 << 1);
-DEF    AUX_ADC_CTRL_START_A            = (1 << 0);
-
-DEF REG_AUX_ADC_CLK    = 35;
-DEF    AUX_ADC_CLK_CLK_OVER_4          = (1 << 0);
-
-DEF REG_AUX_DAC_A      = 36;
-DEF REG_AUX_DAC_B      = 37;
-DEF REG_AUX_DAC_C      = 38;
-
-DEF REG_AUX_DAC_UPDATE = 39;
-DEF    AUX_DAC_UPDATE_SLAVE_ENABLE     = (1 << 7);
-DEF    AUX_DAC_UPDATE_C                = (1 << 2);
-DEF    AUX_DAC_UPDATE_B                = (1 << 1);
-DEF    AUX_DAC_UPDATE_A                = (1 << 0);
-
-DEF REG_AUX_DAC_PWR_DN = 40;
-DEF    AUX_DAC_PWR_DN_C                = (1 << 2);
-DEF    AUX_DAC_PWR_DN_B                = (1 << 1);
-DEF    AUX_DAC_PWR_DN_A                = (1 << 0);
-
-DEF REG_AUX_DAC_CTRL   = 41;
-DEF    AUX_DAC_CTRL_INV_C              = (1 << 4);
-DEF    AUX_DAC_CTRL_INV_B              = (1 << 2);
-DEF    AUX_DAC_CTRL_INV_A              = (1 << 0);
-
-DEF REG_SIGDELT_LO     = 42;
-DEF REG_SIGDELT_HI     = 43;
-
-// 44 to 48 reserved
-
-DEF REG_ADC_LOW_PWR_LO = 49;
-DEF REG_ADC_LOW_PWR_HI = 50;
-
-// 51 to 62 reserved
-
-DEF REG_CHIP_ID                = 63;
-
-
-END_AD962;
-
-#undef DEF
-#undef BEGIN_AD9862
-#undef END_AD962
-
-#endif /* INCLUDED_AD9862_H */
diff --git a/usrp/host/lib/check_data.py b/usrp/host/lib/check_data.py
deleted file mode 100755 (executable)
index 655ca15..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2003 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., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-
-import sys
-import struct
-
-fin = sys.stdin
-
-count = 0
-expected = 0
-last_correction = 0
-
-while 1:
-    s = fin.read(2)
-    if not s or len(s) != 2:
-        break
-
-    v, = struct.unpack ('H', s)
-    iv = int(v) & 0xffff
-    # print "%8d  %6d  0x%04x" % (count, iv, iv)
-    if count & 0x1:                     # only counting on the Q channel
-        if (expected & 0xffff) != iv:
-            print "%8d  (%6d) %6d  0x%04x" % (count, count - last_correction, iv, iv)
-            expected = iv               # reset expected sequence
-            last_correction = count
-        expected = (expected + 1) & 0xffff 
-        
-    count += 1
-
-    
-
-
diff --git a/usrp/host/lib/circular_buffer.h b/usrp/host/lib/circular_buffer.h
deleted file mode 100644 (file)
index 913360d..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _CIRCULAR_BUFFER_H_
-#define _CIRCULAR_BUFFER_H_
-
-#include "mld_threads.h"
-#include <stdexcept>
-
-#define DO_DEBUG 0
-
-template <class T> class circular_buffer
-{
-private:
-// the buffer to use
-  T* d_buffer;
-
-// the following are in Items (type T)
-  UInt32 d_bufLen_I, d_readNdx_I, d_writeNdx_I;
-  UInt32 d_n_avail_write_I, d_n_avail_read_I;
-
-// stuff to control access to class internals
-  mld_mutex_ptr d_internal;
-  mld_condition_ptr d_readBlock, d_writeBlock;
-
-// booleans to decide how to control reading, writing, and aborting
-  bool d_doWriteBlock, d_doFullRead, d_doAbort;
-
-  void delete_mutex_cond () {
-    if (d_internal) {
-      delete d_internal;
-      d_internal = NULL;
-    }
-    if (d_readBlock) {
-      delete d_readBlock;
-      d_readBlock = NULL;
-    }
-    if (d_writeBlock) {
-      delete d_writeBlock;
-      d_writeBlock = NULL;
-    }
-  };
-
-public:
-  circular_buffer (UInt32 bufLen_I,
-                  bool doWriteBlock = true, bool doFullRead = false) {
-    if (bufLen_I == 0)
-      throw std::runtime_error ("circular_buffer(): "
-                               "Number of items to buffer must be > 0.\n");
-    d_bufLen_I = bufLen_I;
-    d_buffer = (T*) new T[d_bufLen_I];
-    d_doWriteBlock = doWriteBlock;
-    d_doFullRead = doFullRead;
-    d_internal = NULL;
-    d_readBlock = d_writeBlock = NULL;
-    reset ();
-#if DO_DEBUG
-    fprintf (stderr, "c_b(): buf len (items) = %ld, "
-            "doWriteBlock = %s, doFullRead = %s\n", d_bufLen_I,
-            (d_doWriteBlock ? "true" : "false"),
-            (d_doFullRead ? "true" : "false"));
-#endif
-  };
-
-  ~circular_buffer () {
-    delete_mutex_cond ();
-    delete [] d_buffer;
-  };
-
-  inline UInt32 n_avail_write_items () {
-    d_internal->lock ();
-    UInt32 retVal = d_n_avail_write_I;
-    d_internal->unlock ();
-    return (retVal);
-  };
-
-  inline UInt32 n_avail_read_items () {
-    d_internal->lock ();
-    UInt32 retVal = d_n_avail_read_I;
-    d_internal->unlock ();
-    return (retVal);
-  };
-
-  inline UInt32 buffer_length_items () {return (d_bufLen_I);};
-  inline bool do_write_block () {return (d_doWriteBlock);};
-  inline bool do_full_read () {return (d_doFullRead);};
-
-  void reset () {
-    d_doAbort = false;
-    bzero (d_buffer, d_bufLen_I * sizeof (T));
-    d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0;
-    d_n_avail_write_I = d_bufLen_I;
-    delete_mutex_cond ();
-    d_internal = new mld_mutex ();
-    d_readBlock = new mld_condition ();
-    d_writeBlock = new mld_condition ();
-  };
-
-/*
- * enqueue: add the given buffer of item-length to the queue,
- *     first-in-first-out (FIFO).
- *
- * inputs:
- *     buf: a pointer to the buffer holding the data
- *
- *     bufLen_I: the buffer length in items (of the instantiated type)
- *
- * returns:
- *    -1: on overflow (write is not blocking, and data is being
- *                     written faster than it is being read)
- *     0: if nothing to do (0 length buffer)
- *     1: if success
- *     2: in the process of aborting, do doing nothing
- *
- * will throw runtime errors if inputs are improper:
- *     buffer pointer is NULL
- *     buffer length is larger than the instantiated buffer length
- */
-
-  int enqueue (T* buf, UInt32 bufLen_I) {
-#if DO_DEBUG
-    fprintf (stderr, "enqueue: buf = %X, bufLen = %ld.\n",
-            (unsigned int)buf, bufLen_I);
-#endif
-    if (bufLen_I > d_bufLen_I) {
-      fprintf (stderr, "cannot add buffer longer (%ld"
-              ") than instantiated length (%ld"
-              ").\n", bufLen_I, d_bufLen_I);
-      throw std::runtime_error ("circular_buffer::enqueue()");
-    }
-
-    if (bufLen_I == 0)
-      return (0);
-    if (!buf)
-      throw std::runtime_error ("circular_buffer::enqueue(): "
-                               "input buffer is NULL.\n");
-    d_internal->lock ();
-    if (d_doAbort) {
-      d_internal->unlock ();
-      return (2);
-    }
-    if (bufLen_I > d_n_avail_write_I) {
-      if (d_doWriteBlock) {
-       while (bufLen_I > d_n_avail_write_I) {
-#if DO_DEBUG
-         fprintf (stderr, "enqueue: #len > #a, waiting.\n");
-#endif
-         d_internal->unlock ();
-         d_writeBlock->wait ();
-         d_internal->lock ();
-         if (d_doAbort) {
-           d_internal->unlock ();
-#if DO_DEBUG
-           fprintf (stderr, "enqueue: #len > #a, aborting.\n");
-#endif
-           return (2);
-         }
-#if DO_DEBUG
-         fprintf (stderr, "enqueue: #len > #a, done waiting.\n");
-#endif
-       }
-      } else {
-       d_n_avail_read_I = d_bufLen_I - bufLen_I;
-       d_n_avail_write_I = bufLen_I;
-#if DO_DEBUG
-       fprintf (stderr, "circular_buffer::enqueue: overflow\n");
-#endif
-       return (-1);
-      }
-    }
-    UInt32 n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0;
-    if (n_now_I > bufLen_I)
-      n_now_I = bufLen_I;
-    else if (n_now_I < bufLen_I)
-      n_start_I = bufLen_I - n_now_I;
-    bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I * sizeof (T));
-    if (n_start_I) {
-      bcopy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T));
-      d_writeNdx_I = n_start_I;
-    } else
-      d_writeNdx_I += n_now_I;
-    d_n_avail_read_I += bufLen_I;
-    d_n_avail_write_I -= bufLen_I;
-    d_readBlock->signal ();
-    d_internal->unlock ();
-    return (1);
-  };
-
-/*
- * dequeue: removes from the queue the number of items requested, or
- *     available, into the given buffer on a FIFO basis.
- *
- * inputs:
- *     buf: a pointer to the buffer into which to copy the data
- *
- *     bufLen_I: pointer to the number of items to remove in items
- *         (of the instantiated type)
- *
- * returns:
- *     0: if nothing to do (0 length buffer)
- *     1: if success
- *     2: in the process of aborting, do doing nothing
- *
- * will throw runtime errors if inputs are improper:
- *     buffer pointer is NULL
- *     buffer length pointer is NULL
- *     buffer length is larger than the instantiated buffer length
- */
-
-
-  int dequeue (T* buf, UInt32* bufLen_I) {
-#if DO_DEBUG
-    fprintf (stderr, "dequeue: buf = %X, *bufLen = %ld.\n",
-            (unsigned int)buf, *bufLen_I);
-#endif
-    if (!bufLen_I)
-      throw std::runtime_error ("circular_buffer::dequeue(): "
-                               "input bufLen pointer is NULL.\n");
-    if (!buf)
-      throw std::runtime_error ("circular_buffer::dequeue(): "
-                               "input buffer pointer is NULL.\n");
-    UInt32 l_bufLen_I = *bufLen_I;
-    if (l_bufLen_I == 0)
-      return (0);
-    if (l_bufLen_I > d_bufLen_I) {
-      fprintf (stderr, "cannot remove buffer longer (%ld"
-              ") than instantiated length (%ld"
-              ").\n", l_bufLen_I, d_bufLen_I);
-      throw std::runtime_error ("circular_buffer::dequeue()");
-    }
-
-    d_internal->lock ();
-    if (d_doAbort) {
-      d_internal->unlock ();
-      return (2);
-    }
-    if (d_doFullRead) {
-      while (d_n_avail_read_I < l_bufLen_I) {
-#if DO_DEBUG
-       fprintf (stderr, "dequeue: #a < #len, waiting.\n");
-#endif
-       d_internal->unlock ();
-       d_readBlock->wait ();
-       d_internal->lock ();
-       if (d_doAbort) {
-         d_internal->unlock ();
-#if DO_DEBUG
-         fprintf (stderr, "dequeue: #a < #len, aborting.\n");
-#endif
-         return (2);
-       }
-#if DO_DEBUG
-       fprintf (stderr, "dequeue: #a < #len, done waiting.\n");
-#endif
-     }
-    } else {
-      while (d_n_avail_read_I == 0) {
-#if DO_DEBUG
-       fprintf (stderr, "dequeue: #a == 0, waiting.\n");
-#endif
-       d_internal->unlock ();
-       d_readBlock->wait ();
-       d_internal->lock ();
-       if (d_doAbort) {
-         d_internal->unlock ();
-#if DO_DEBUG
-         fprintf (stderr, "dequeue: #a == 0, aborting.\n");
-#endif
-         return (2);
-       }
-#if DO_DEBUG
-       fprintf (stderr, "dequeue: #a == 0, done waiting.\n");
-#endif
-      }
-    }
-    if (l_bufLen_I > d_n_avail_read_I)
-      l_bufLen_I = d_n_avail_read_I;
-    UInt32 n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0;
-    if (n_now_I > l_bufLen_I)
-      n_now_I = l_bufLen_I;
-    else if (n_now_I < l_bufLen_I)
-      n_start_I = l_bufLen_I - n_now_I;
-    bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I * sizeof (T));
-    if (n_start_I) {
-      bcopy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T));
-      d_readNdx_I = n_start_I;
-    } else
-      d_readNdx_I += n_now_I;
-    *bufLen_I = l_bufLen_I;
-    d_n_avail_read_I -= l_bufLen_I;
-    d_n_avail_write_I += l_bufLen_I;
-    d_writeBlock->signal ();
-    d_internal->unlock ();
-    return (1);
-  };
-
-  void abort () {
-    d_internal->lock ();
-    d_doAbort = true;
-    d_writeBlock->signal ();
-    d_readBlock->signal ();
-    d_internal->unlock ();
-  };
-};
-
-#endif /* _CIRCULAR_BUFFER_H_ */
diff --git a/usrp/host/lib/circular_linked_list.h b/usrp/host/lib/circular_linked_list.h
deleted file mode 100644 (file)
index 0e460a2..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _CIRCULAR_LINKED_LIST_H_
-#define _CIRCULAR_LINKED_LIST_H_
-
-#include <mld_threads.h>
-#include <stdexcept>
-
-#define __INLINE__ inline
-
-template <class T> class s_both;
-
-template <class T> class s_node
-{
-  typedef s_node<T>* s_node_ptr;
-
-private:
-  T d_object;
-  bool d_available;
-  s_node_ptr d_prev, d_next;
-  s_both<T>* d_both;
-
-public:
-  s_node (T l_object,
-         s_node_ptr l_prev = NULL,
-         s_node_ptr l_next = NULL)
-    : d_object (l_object), d_available (TRUE), d_prev (l_prev),
-    d_next (l_next), d_both (0) {};
-
-  __INLINE__ s_node (s_node_ptr l_prev, s_node_ptr l_next = NULL) {
-    s_node ((T) NULL, l_prev, l_next); };
-  __INLINE__ s_node () { s_node (NULL, NULL, NULL); };
-  __INLINE__ ~s_node () {};
-
-  void remove () {
-    d_prev->next (d_next);
-    d_next->prev (d_prev);
-    d_prev = d_next = this;
-  };
-
-  void insert_before (s_node_ptr l_next) {
-    if (l_next) {
-      s_node_ptr l_prev = l_next->prev ();
-      d_next = l_next;
-      d_prev = l_prev;
-      l_prev->next (this);
-      l_next->prev (this);
-    } else
-      d_next = d_prev = this;
-  };
-
-  void insert_after (s_node_ptr l_prev) {
-    if (l_prev) {
-      s_node_ptr l_next = l_prev->next ();
-      d_prev = l_prev;
-      d_next = l_next;
-      l_next->prev (this);
-      l_prev->next (this);
-    } else
-      d_prev = d_next = this;
-  };
-
-  __INLINE__ T object () { return (d_object); };
-  __INLINE__ void object (T l_object) { d_object = l_object; };
-  __INLINE__ bool available () { return (d_available); };
-  __INLINE__ void set_available () { d_available = TRUE; };
-  __INLINE__ void set_available (bool l_avail) { d_available = l_avail; };
-  __INLINE__ void set_not_available () { d_available = FALSE; };
-  __INLINE__ s_node_ptr next () { return (d_next); };
-  __INLINE__ s_node_ptr prev () { return (d_prev); };
-  __INLINE__ s_both<T>* both () { return (d_both); };
-  __INLINE__ void next (s_node_ptr l_next) { d_next = l_next; };
-  __INLINE__ void prev (s_node_ptr l_prev) { d_prev = l_prev; };
-  __INLINE__ void both (s_both<T>* l_both) { d_both = l_both; };
-};
-
-template <class T> class circular_linked_list {
-  typedef s_node<T>* s_node_ptr;
-
-private:
-  s_node_ptr d_current, d_iterate, d_available, d_inUse;
-  UInt32 d_n_nodes, d_n_used;
-  mld_mutex_ptr d_internal;
-  mld_condition_ptr d_ioBlock;
-
-public:
-  circular_linked_list (UInt32 n_nodes) {
-    if (n_nodes == 0)
-      throw std::runtime_error ("circular_linked_list(): n_nodes == 0");
-
-    d_iterate = NULL;
-    d_n_nodes = n_nodes;
-    d_n_used = 0;
-    s_node_ptr l_prev, l_next;
-    d_inUse = d_current = l_next = l_prev = NULL;
-
-    l_prev = new s_node<T> ();
-    l_prev->set_available ();
-    l_prev->next (l_prev);
-    l_prev->prev (l_prev);
-    if (n_nodes > 1) {
-      l_next = new s_node<T> (l_prev, l_prev);
-      l_next->set_available ();
-      l_next->next (l_prev);
-      l_next->prev (l_prev);
-      l_prev->next (l_next);
-      l_prev->prev (l_next);
-      if (n_nodes > 2) {
-       UInt32 n = n_nodes - 2;
-       while (n-- > 0) {
-         d_current = new s_node<T> (l_prev, l_next);
-         d_current->set_available ();
-         d_current->prev (l_prev);
-         d_current->next (l_next);
-         l_prev->next (d_current);
-         l_next->prev (d_current);
-         l_next = d_current;
-         d_current = NULL;
-       }
-      }
-    }
-    d_available = d_current = l_prev;
-    d_internal = new mld_mutex ();
-    d_ioBlock = new mld_condition ();
-  };
-
-  ~circular_linked_list () {
-    iterate_start ();
-    s_node_ptr l_node = iterate_next ();
-    while (l_node) {
-      delete l_node;
-      l_node = iterate_next ();
-    }
-    delete d_internal;
-    d_internal = NULL;
-    delete d_ioBlock;
-    d_ioBlock = NULL;
-    d_available = d_inUse = d_iterate = d_current = NULL;
-    d_n_used = d_n_nodes = 0;
-  };
-
-  s_node_ptr find_next_available_node () {
-    d_internal->lock ();
-// find an available node
-    s_node_ptr l_node = d_available; 
-    while (! l_node) {
-      d_internal->unlock ();
-      d_ioBlock->wait ();
-      d_internal->lock ();
-      l_node = d_available;
-    }
-//  fprintf (stderr, "::f_n_a_n: #u = %ld, node = %p\n", num_used(), l_node);
-// remove this one from the current available list
-    if (num_available () == 1) {
-// last one, just set available to NULL
-      d_available = NULL;
-    } else
-      d_available = l_node->next ();
-    l_node->remove ();
-// add is to the inUse list
-    if (! d_inUse)
-      d_inUse = l_node;
-    else
-      l_node->insert_before (d_inUse);
-    d_n_used++;
-    l_node->set_not_available ();
-    d_internal->unlock ();
-    return (l_node);
-  };
-
-  void make_node_available (s_node_ptr l_node) {
-    if (!l_node) return;
-    d_internal->lock ();
-//  fprintf (stderr, "::m_n_a: #u = %ld, node = %p\n", num_used(), l_node);
-// remove this node from the inUse list
-    if (num_used () == 1) {
-// last one, just set inUse to NULL
-      d_inUse = NULL;
-    } else
-      d_inUse = l_node->next ();
-    l_node->remove ();
-// add this node to the available list
-    if (! d_available)
-      d_available = l_node;
-    else
-      l_node->insert_before (d_available);
-    d_n_used--;
-// signal the condition when new data arrives
-    d_ioBlock->signal ();
-// unlock the mutex for thread safety
-    d_internal->unlock ();
-  };
-
-  __INLINE__ void iterate_start () { d_iterate = d_current; };
-
-  s_node_ptr iterate_next () {
-#if 0
-// lock the mutex for thread safety
-    d_internal->lock ();
-#endif
-    s_node_ptr l_this = NULL;
-    if (d_iterate) {
-      l_this = d_iterate;
-      d_iterate = d_iterate->next ();
-      if (d_iterate == d_current)
-       d_iterate = NULL;
-    }
-#if 0
-// unlock the mutex for thread safety
-    d_internal->unlock ();
-#endif
-    return (l_this);
-  };
-
-  __INLINE__ T object () { return (d_current->d_object); };
-  __INLINE__ void object (T l_object) { d_current->d_object = l_object; };
-  __INLINE__ UInt32 num_nodes () { return (d_n_nodes); };
-  __INLINE__ UInt32 num_used () { return (d_n_used); };
-  __INLINE__ void num_used (UInt32 l_n_used) { d_n_used = l_n_used; };
-  __INLINE__ UInt32 num_available () { return (d_n_nodes - d_n_used); };
-  __INLINE__ void num_used_inc (void) {
-    if (d_n_used < d_n_nodes) ++d_n_used;
-  };
-  __INLINE__ void num_used_dec (void) {
-    if (d_n_used != 0) --d_n_used;
-// signal the condition that new data has arrived
-    d_ioBlock->signal ();
-  };
-  __INLINE__ bool in_use () { return (d_n_used != 0); };
-};
-
-template <class T> class s_both
-{
-private:
-  s_node<T>* d_node;
-  void* d_this;
-public:
-  __INLINE__ s_both (s_node<T>* l_node, void* l_this)
-    : d_node (l_node), d_this (l_this) {};
-  __INLINE__ ~s_both () {};
-  __INLINE__ s_node<T>* node () { return (d_node); };
-  __INLINE__ void* This () { return (d_this); };
-  __INLINE__ void set (s_node<T>* l_node, void* l_this) {
-    d_node = l_node; d_this = l_this;};
-};
-
-#endif /* _CIRCULAR_LINKED_LIST_H_ */
diff --git a/usrp/host/lib/darwin_libusb.h b/usrp/host/lib/darwin_libusb.h
deleted file mode 100644 (file)
index bdbdd34..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * The following code was taken from LIBUSB verion 0.1.10a,
- * and makes the fusb_darwin codes do-able in the current GR
- * programming framework.  Parts and pieces were taken from
- * usbi.h, darwin.c, and error.h .
- *
- * LIBUSB version 0.1.10a is covered by the LGPL, version 2;
- * These codes are used with permission from:
- *   (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
- *   (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
- * All rights reserved.
- */
-
-#ifndef __DARWIN_LIBUSB_H__
-#define __DARWIN_LIBUSB_H__
-
-#include <IOKit/IOCFBundle.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/IOKitLib.h>
-
-extern "C" {
-static char *
-darwin_error_str (int result)
-{
-  switch (result) {
-  case kIOReturnSuccess:
-    return "no error";
-  case kIOReturnNotOpen:
-    return "device not opened for exclusive access";
-  case kIOReturnNoDevice:
-    return "no connection to an IOService";
-  case kIOUSBNoAsyncPortErr:
-    return "no asyc port has been opened for interface";
-  case kIOReturnExclusiveAccess:
-    return "another process has device opened for exclusive access";
-  case kIOUSBPipeStalled:
-    return "pipe is stalled";
-  case kIOReturnError:
-    return "could not establish a connection to Darin kernel";
-  case kIOReturnBadArgument:
-    return "invalid argument";
-  default:
-    return "unknown error";
-  }
-}
-
-/* not a valid errorno outside darwin.c */
-#define LUSBDARWINSTALL (ELAST+1)
-
-static int
-darwin_to_errno (int result)
-{
-  switch (result) {
-  case kIOReturnSuccess:
-    return 0;
-  case kIOReturnNotOpen:
-    return EBADF;
-  case kIOReturnNoDevice:
-  case kIOUSBNoAsyncPortErr:
-    return ENXIO;
-  case kIOReturnExclusiveAccess:
-    return EBUSY;
-  case kIOUSBPipeStalled:
-    return LUSBDARWINSTALL;
-  case kIOReturnBadArgument:
-    return EINVAL;
-  case kIOReturnError:
-  default:
-    return 1;
-  }
-}
-
-typedef enum {
-  USB_ERROR_TYPE_NONE = 0,
-  USB_ERROR_TYPE_STRING,
-  USB_ERROR_TYPE_ERRNO,
-} usb_error_type_t;
-
-extern char usb_error_str[1024];
-extern int usb_error_errno;
-extern usb_error_type_t usb_error_type;
-
-#define USB_ERROR(r, x)                                \
-       do { \
-          usb_error_type = USB_ERROR_TYPE_ERRNO; \
-          usb_error_errno = x; \
-         return r; \
-       } while (0)
-
-#define USB_ERROR_STR(r, x, format, args...)   \
-       do { \
-         usb_error_type = USB_ERROR_TYPE_STRING; \
-         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
-          if (usb_debug) \
-            fprintf(stderr, "USB error: %s\n", usb_error_str); \
-         return r; \
-       } while (0)
-
-#define USB_ERROR_STR_ORIG(x, format, args...) \
-       do { \
-         usb_error_type = USB_ERROR_TYPE_STRING; \
-         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
-          if (usb_debug) \
-            fprintf(stderr, "USB error: %s\n", usb_error_str); \
-         return x; \
-       } while (0)
-
-#define USB_ERROR_STR_NO_RET(x, format, args...)       \
-       do { \
-         usb_error_type = USB_ERROR_TYPE_STRING; \
-         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
-          if (usb_debug) \
-            fprintf(stderr, "USB error: %s\n", usb_error_str); \
-       } while (0)
-
-/* simple function that figures out what pipeRef is associated with an endpoint */
-static int ep_to_pipeRef (darwin_dev_handle *device, int ep)
-{
-  io_return_t ret;
-  UInt8 numep, direction, number;
-  UInt8 dont_care1, dont_care3;
-  UInt16 dont_care2;
-  int i;
-
-  if (usb_debug > 3)
-    fprintf(stderr, "Converting ep address to pipeRef.\n");
-
-  /* retrieve the total number of endpoints on this interface */
-  ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
-  if ( ret ) {
-    if ( usb_debug > 3 )
-      fprintf ( stderr, "ep_to_pipeRef: interface is %p\n", device->interface );
-    USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of endpoints for interface" );
-  }
-
-  /* iterate through the pipeRefs until we find the correct one */
-  for (i = 1 ; i <= numep ; i++) {
-    ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
-                                                   &dont_care1, &dont_care2, &dont_care3);
-
-    if (ret != kIOReturnSuccess) {
-      fprintf (stderr, "ep_to_pipeRef: an error occurred getting pipe information on pipe %d\n",
-              i );
-      USB_ERROR_STR_ORIG (-darwin_to_errno(ret), "ep_to_pipeRef(GetPipeProperties): %s", darwin_error_str(ret));
-    }
-
-    if (usb_debug > 3)
-      fprintf (stderr, "ep_to_pipeRef: Pipe %i: DIR: %i number: %i\n", i, direction, number);
-
-    /* calculate the endpoint of the pipe and check it versus the requested endpoint */
-    if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) | (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) {
-      if (usb_debug > 3)
-       fprintf(stderr, "ep_to_pipeRef: pipeRef for ep address 0x%02x found: 0x%02x\n", ep, i);
-
-      return i;
-    }
-  }
-
-  if (usb_debug > 3)
-    fprintf(stderr, "ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
-  
-  /* none of the found pipes match the requested endpoint */
-  return -1;
-}
-
-}
-#endif /* __DARWIN_LIBUSB_H__ */
diff --git a/usrp/host/lib/dump_data.py b/usrp/host/lib/dump_data.py
deleted file mode 100755 (executable)
index 34dde3d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2003 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., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-
-import sys
-import struct
-
-fin = sys.stdin
-
-count = 0
-
-while 1:
-    s = fin.read(2)
-    if not s or len(s) != 2:
-        break
-
-    v, = struct.unpack ('H', s)
-    iv = int(v) & 0xffff
-    print "%8d  %6d  0x%04x" % (count, iv, iv)
-    count += 1
-    
-
-
diff --git a/usrp/host/lib/dxc-io-assignments.gnumeric b/usrp/host/lib/dxc-io-assignments.gnumeric
deleted file mode 100644 (file)
index 85e1a88..0000000
Binary files a/usrp/host/lib/dxc-io-assignments.gnumeric and /dev/null differ
diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc
deleted file mode 100644 (file)
index 01ced9e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fusb.h>
-
-
-// ------------------------------------------------------------------------
-//                          device handle
-// ------------------------------------------------------------------------
-
-fusb_devhandle::fusb_devhandle (usb_dev_handle *udh)
-  : d_udh (udh)
-{
-  // that's it
-};
-
-fusb_devhandle::~fusb_devhandle ()
-{
-  // nop
-}
-
-// ------------------------------------------------------------------------
-//                          end point handle
-// ------------------------------------------------------------------------
-
-fusb_ephandle::fusb_ephandle (int endpoint, bool input_p,
-                             int block_size, int nblocks)
-  : d_endpoint (endpoint), d_input_p (input_p),
-    d_block_size (block_size), d_nblocks (nblocks), d_started (false)
-{
-  // that't it
-}
-
-fusb_ephandle::~fusb_ephandle ()
-{
-  // nop
-}
diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h
deleted file mode 100644 (file)
index da1b7c0..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-// Fast USB interface
-
-#ifndef _FUSB_H_
-#define _FUSB_H_
-
-
-struct  usb_dev_handle;
-class   fusb_ephandle;
-
-/*!
- * \brief abstract usb device handle
- */
-class fusb_devhandle {
-private:
-  // NOT IMPLEMENTED
-  fusb_devhandle (const fusb_devhandle &rhs);            // no copy constructor
-  fusb_devhandle &operator= (const fusb_devhandle &rhs);  // no assignment operator
-
-protected:
-  usb_dev_handle               *d_udh;
-
-public:
-  // CREATORS
-  fusb_devhandle (usb_dev_handle *udh);
-  virtual ~fusb_devhandle ();
-
-  // MANIPULATORS
-  
-  /*!
-   * \brief return an ephandle of the correct subtype
-   */
-  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0) = 0;
-  
-  // ACCESSORS
-  usb_dev_handle *get_usb_dev_handle () const { return d_udh; }
-};
-
-
-/*!
- * \brief abstract usb end point handle
- */
-class fusb_ephandle {
-private:
-  // NOT IMPLEMENTED
-  fusb_ephandle (const fusb_ephandle &rhs);            // no copy constructor
-  fusb_ephandle &operator= (const fusb_ephandle &rhs);  // no assignment operator
-
-protected:
-  int                          d_endpoint;
-  bool                         d_input_p;
-  int                          d_block_size;
-  int                          d_nblocks;
-  bool                         d_started;
-
-public:
-  fusb_ephandle (int endpoint, bool input_p,
-                int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle ();
-
-  virtual bool start () = 0;   //!< begin streaming i/o
-  virtual bool stop () = 0;    //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void *buffer, int nbytes) = 0;
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void *buffer, int nbytes) = 0;
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion () = 0;
-
-  /*!
-   * \brief returns current block size.
-   */
-  int block_size () { return d_block_size; };
-};
-
-
-/*!
- * \brief factory for creating concrete instances of the appropriate subtype.
- */
-class fusb_sysconfig {
-public:
-  /*!
-   * \brief returns fusb_devhandle or throws if trouble
-   */
-  static fusb_devhandle *make_devhandle (usb_dev_handle *udh);
-
-  /*!
-   * \brief returns max block size hard limit
-   */
-  static int max_block_size ();
-
-  /*!
-   * \brief returns the default buffer size
-   */
-  static int default_buffer_size ();
-
-};
-
-#endif /* _FUSB_H_ */
diff --git a/usrp/host/lib/fusb_darwin.cc b/usrp/host/lib/fusb_darwin.cc
deleted file mode 100644 (file)
index 8be5453..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-// tell mld_threads to NOT use omni_threads,
-// but rather Darwin's pthreads
-#undef _USE_OMNI_THREADS_
-
-#include <usb.h>
-#include "fusb.h"
-#include "fusb_darwin.h"
-#include "darwin_libusb.h"
-
-static const int USB_TIMEOUT = 100;    // in milliseconds
-static const UInt8 NUM_QUEUE_ITEMS = 20;
-
-fusb_devhandle_darwin::fusb_devhandle_darwin (usb_dev_handle* udh)
-  : fusb_devhandle (udh)
-{
-  // that's it
-}
-
-fusb_devhandle_darwin::~fusb_devhandle_darwin ()
-{
-  // nop
-}
-
-fusb_ephandle*
-fusb_devhandle_darwin::make_ephandle (int endpoint, bool input_p,
-                                     int block_size, int nblocks)
-{
-  return new fusb_ephandle_darwin (this, endpoint, input_p,
-                                  block_size, nblocks);
-}
-
-// ----------------------------------------------------------------
-
-fusb_ephandle_darwin::fusb_ephandle_darwin (fusb_devhandle_darwin* dh,
-                                           int endpoint, bool input_p,
-                                           int block_size, int nblocks)
-  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
-    d_devhandle (dh), d_pipeRef (0), d_transferType (0),
-    d_interfaceRef (0),  d_interface (0), d_queue (0),
-    d_buffer (0), d_bufLenBytes (0)
-{
-  d_bufLenBytes = fusb_sysconfig::max_block_size();
-
-// create circular buffer
-  d_buffer = new circular_buffer<char> (NUM_QUEUE_ITEMS * d_bufLenBytes,
-                                       !d_input_p, d_input_p);
-
-// create the queue
-  d_queue = new circular_linked_list <s_buffer_ptr> (NUM_QUEUE_ITEMS);
-  d_queue->iterate_start ();
-  s_node_ptr l_node = d_queue->iterate_next ();
-  while (l_node) {
-    l_node->both (new s_both<s_buffer_ptr> (l_node, this));
-    s_buffer_ptr l_buf = new s_buffer (d_bufLenBytes);
-    l_node->object (l_buf);
-    l_node = d_queue->iterate_next ();
-    l_buf = NULL;
-  }
-
-  d_readRunning = new mld_mutex ();
-  d_runThreadRunning = new mld_mutex ();
-  d_runBlock = new mld_condition ();
-  d_readBlock = new mld_condition ();
-}
-
-fusb_ephandle_darwin::~fusb_ephandle_darwin ()
-{
-  stop ();
-
-  d_queue->iterate_start ();
-  s_node_ptr l_node = d_queue->iterate_next ();
-  while (l_node) {
-    s_both_ptr l_both = l_node->both ();
-    delete l_both;
-    l_both = NULL;
-    l_node->both (NULL);
-    s_buffer_ptr l_buf = l_node->object ();
-    delete l_buf;
-    l_buf = NULL;
-    l_node->object (NULL);
-    l_node = d_queue->iterate_next ();
-  }
-  delete d_queue;
-  d_queue = NULL;
-  delete d_buffer;
-  d_buffer = NULL;
-  delete d_readRunning;
-  d_readRunning = NULL;
-  delete d_runThreadRunning;
-  d_runThreadRunning = NULL;
-  delete d_runBlock;
-  d_runBlock = NULL;
-  delete d_readBlock;
-  d_readBlock = NULL;
-}
-
-bool
-fusb_ephandle_darwin::start ()
-{
-  UInt8  direction, number, interval;
-  UInt16 maxPacketSize;
-
-// reset circular buffer
-  d_buffer->reset ();
-
-// reset the queue
-  d_queue->num_used (0);
-  d_queue->iterate_start ();
-  s_node_ptr l_node = d_queue->iterate_next ();
-  while (l_node) {
-    l_node->both()->set (l_node, this);
-    l_node->object()->reset ();
-    l_node->set_available ();
-    l_node = d_queue->iterate_next ();
-  }
-
-  d_pipeRef = d_transferType = 0;
-
-  usb_dev_handle* dev = d_devhandle->get_usb_dev_handle ();
-  if (! dev)
-    USB_ERROR_STR (false, -ENXIO, "fusb_ephandle_darwin::start: "
-                  "null device");
-
-  darwin_dev_handle* device = (darwin_dev_handle*) dev->impl_info;
-  if (! device)
-    USB_ERROR_STR (false, -ENOENT, "fusb_ephandle_darwin::start: "
-                  "device not initialized");
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::start: "
-            "dev = %p, device = %p\n", dev, device);
-
-  d_interfaceRef = device->interface;
-  if (! d_interfaceRef)
-    USB_ERROR_STR (false, -EACCES, "fusb_ephandle_darwin::start: "
-                  "interface used without being claimed");
-  d_interface = *d_interfaceRef;
-
-// get read or write pipe info (depends on "d_input_p")
-
-  if (usb_debug > 3)
-    fprintf (stderr, "fusb_ephandle_darwin::start "
-            "d_endpoint = %d, d_input_p = %s\n",
-            d_endpoint, d_input_p ? "TRUE" : "FALSE");
-
-  int l_endpoint = (d_input_p ? USB_ENDPOINT_IN : USB_ENDPOINT_OUT);
-  int pipeRef = ep_to_pipeRef (device, d_endpoint | l_endpoint);
-  if (pipeRef < 0)
-    USB_ERROR_STR (false, -EINVAL, "fusb_ephandle_darwin::start "
-                  " invalid pipeRef.\n");
-
-  d_pipeRef = pipeRef;
-  d_interface->GetPipeProperties (d_interfaceRef,
-                                 d_pipeRef,
-                                 &direction,
-                                 &number,
-                                 &d_transferType,
-                                 &maxPacketSize,
-                                 &interval);
-  if (usb_debug == 3)
-    fprintf (stderr, "fusb_ephandle_darwin::start: %s: ep = 0x%02x, "
-            "pipeRef = %d, d_i = %p, d_iR = %p, if_dir = %d, if_# = %d, "
-            "if_int = %d, if_maxPS = %d\n", d_input_p ? "read" : "write",
-            d_endpoint, d_pipeRef, d_interface, d_interfaceRef, direction,
-            number, interval, maxPacketSize);
-
-// set global start boolean
-  d_started = true;
-
-// create the run thread, which allows OSX to process I/O separately
-  d_runThread = new mld_thread (run_thread, this);
-
-// wait until the threads are -really- going
-  d_runBlock->wait ();
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::start: %s started.\n",
-            d_input_p ? "read" : "write");
-
-  return (true);
-}
-
-void
-fusb_ephandle_darwin::run_thread (void* arg)
-{
-  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(arg);
-  mld_mutex_ptr l_runThreadRunning = This->d_runThreadRunning;
-  l_runThreadRunning->lock ();
-
-  mld_mutex_ptr l_readRunning = This->d_readRunning;
-  mld_condition_ptr l_readBlock = This->d_readBlock;
-
-  bool l_input_p = This->d_input_p;
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::run_thread: "
-            "starting for %s.\n",
-            l_input_p ? "read" : "write");
-
-  usb_interface_t** l_interfaceRef = This->d_interfaceRef;
-  usb_interface_t* l_interface = This->d_interface;
-  CFRunLoopSourceRef l_cfSource;
-
-// create async run loop
-  l_interface->CreateInterfaceAsyncEventSource (l_interfaceRef, &l_cfSource);
-  CFRunLoopAddSource (CFRunLoopGetCurrent (), l_cfSource,
-                     kCFRunLoopDefaultMode);
-// get run loop reference, to allow other threads to stop
-  This->d_CFRunLoopRef = CFRunLoopGetCurrent ();
-
-  mld_thread_ptr l_rwThread = NULL;
-
-  if (l_input_p) {
-    l_rwThread = new mld_thread (read_thread, arg);
-// wait until the the rwThread is -really- going
-    l_readBlock->wait ();
-  }
-
-// now signal the run condition to release and finish ::start()
-  This->d_runBlock->signal ();
-
-// run the loop
-  CFRunLoopRun ();
-
-  if (l_input_p) {
-// wait for read_thread () to finish
-    l_readRunning->lock ();
-    l_readRunning->unlock ();
-  }
-
-// remove run loop stuff
-  CFRunLoopRemoveSource (CFRunLoopGetCurrent (),
-                        l_cfSource, kCFRunLoopDefaultMode);
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::run_thread: finished for %s.\n",
-            l_input_p ? "read" : "write");
-
-  l_runThreadRunning->unlock ();
-}
-
-void
-fusb_ephandle_darwin::read_thread (void* arg)
-{
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::read_thread: starting.\n");
-
-  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(arg);
-
-  mld_mutex_ptr l_readRunning = This->d_readRunning;
-  l_readRunning->lock ();
-
-// signal the read condition from run_thread() to continue
-  mld_condition_ptr l_readBlock = This->d_readBlock;
-  l_readBlock->signal ();
-
-  s_queue_ptr l_queue = This->d_queue;
-  l_queue->iterate_start ();
-  s_node_ptr l_node = l_queue->iterate_next ();
-  while (l_node) {
-    This->read_issue (l_node->both ());
-    l_node = l_queue->iterate_next ();
-  }
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::read_thread: finished.\n");
-
-  l_readRunning->unlock ();
-}
-
-void
-fusb_ephandle_darwin::read_issue (s_both_ptr l_both)
-{
-  if ((! l_both) || (! d_started))
-    return;
-
-// set the node and buffer from the input "both"
-  s_node_ptr l_node = l_both->node ();
-  s_buffer_ptr l_buf = l_node->object ();
-  void* v_buffer = (void*) l_buf->buffer ();
-
-// read up to d_bufLenBytes
-  UInt32 bufLen = d_bufLenBytes;
-  l_buf->n_used (bufLen);
-
-// setup system call result
-  io_return_t result = kIOReturnSuccess;
-
-  if (d_transferType == kUSBInterrupt)
-/* This is an interrupt pipe. We can't specify a timeout. */
-    result = d_interface->ReadPipeAsync
-      (d_interfaceRef, d_pipeRef, v_buffer, bufLen,
-       (IOAsyncCallback1) read_completed, (void*) l_both);
-  else
-    result = d_interface->ReadPipeAsyncTO
-      (d_interfaceRef, d_pipeRef, v_buffer, bufLen, 0, USB_TIMEOUT,
-       (IOAsyncCallback1) read_completed, (void*) l_both);
-
-  if (result != kIOReturnSuccess)
-    USB_ERROR_STR_NO_RET (- darwin_to_errno (result),
-                         "fusb_ephandle_darwin::read_issue "
-                         "(ReadPipeAsync%s): %s",
-                         d_transferType == kUSBInterrupt ? "" : "TO",
-                         darwin_error_str (result));
-}
-
-void
-fusb_ephandle_darwin::read_completed (void* refCon,
-                                     io_return_t result,
-                                     void* io_size)
-{
-  UInt32 l_size = (UInt32) io_size;
-  s_both_ptr l_both = static_cast<s_both_ptr>(refCon);
-  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(l_both->This ());
-  s_node_ptr l_node = l_both->node ();
-  circular_buffer<char>* l_buffer = This->d_buffer;
-  s_buffer_ptr l_buf = l_node->object ();
-  UInt32 l_i_size = l_buf->n_used ();
-
-  if (This->d_started && (l_i_size != l_size))
-    fprintf (stderr, "fusb_ephandle_darwin::read_completed: "
-            "Expected %ld bytes; read %ld.\n",
-            l_i_size, l_size);
-
-// add this read to the transfer buffer
-  if (l_buffer->enqueue (l_buf->buffer (), l_size) == -1) {
-    fputs ("iU", stderr);
-    fflush (stderr);
-  }
-
-// set buffer's # data to 0
-  l_buf->n_used (0);
-
-// issue another read for this "both"
-  This->read_issue (l_both);
-}
-
-int
-fusb_ephandle_darwin::read (void* buffer, int nbytes)
-{
-  UInt32 l_nbytes = (UInt32) nbytes;
-  d_buffer->dequeue ((char*) buffer, &l_nbytes);
-  return ((int) l_nbytes);
-}
-
-int
-fusb_ephandle_darwin::write (const void* buffer, int nbytes)
-{
-  UInt32 l_nbytes = (UInt32) nbytes;
-
-  if (! d_started) return (0);
-
-  while (l_nbytes != 0) {
-// find out how much data to copy; limited to "d_bufLenBytes" per node
-    UInt32 t_nbytes = (l_nbytes > d_bufLenBytes) ? d_bufLenBytes : l_nbytes;
-
-// get next available node to write into;
-// blocks internally if none available
-    s_node_ptr l_node = d_queue->find_next_available_node ();
-
-// copy the input into the node's buffer
-    s_buffer_ptr l_buf = l_node->object ();
-    l_buf->buffer ((char*) buffer, t_nbytes);
-    void* v_buffer = (void*) l_buf->buffer ();
-
-// setup callback parameter & system call return
-    s_both_ptr l_both = l_node->both ();
-    io_return_t result = kIOReturnSuccess;
-
-    if (d_transferType == kUSBInterrupt)
-/* This is an interrupt pipe ... can't specify a timeout. */
-      result = d_interface->WritePipeAsync
-       (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes,
-        (IOAsyncCallback1) write_completed, (void*) l_both);
-    else
-      result = d_interface->WritePipeAsyncTO
-       (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes, 0, USB_TIMEOUT,
-        (IOAsyncCallback1) write_completed, (void*) l_both);
-
-    if (result != kIOReturnSuccess)
-      USB_ERROR_STR (-1, - darwin_to_errno (result),
-                    "fusb_ephandle_darwin::write_thread "
-                    "(WritePipeAsync%s): %s",
-                    d_transferType == kUSBInterrupt ? "" : "TO",
-                    darwin_error_str (result));
-    l_nbytes -= t_nbytes;
-  }
-
-  return (nbytes);
-}
-
-void
-fusb_ephandle_darwin::write_completed (void* refCon,
-                                      io_return_t result,
-                                      void* io_size)
-{
-  s_both_ptr l_both = static_cast<s_both_ptr>(refCon);
-  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(l_both->This ());
-  UInt32 l_size = (UInt32) io_size;
-  s_node_ptr l_node = l_both->node ();
-  s_queue_ptr l_queue = This->d_queue;
-  s_buffer_ptr l_buf = l_node->object ();
-  UInt32 l_i_size = l_buf->n_used ();
-
-  if (This->d_started && (l_i_size != l_size))
-    fprintf (stderr, "fusb_ephandle_darwin::write_completed: "
-            "Expected %ld bytes written; wrote %ld.\n",
-            l_i_size, l_size);
-
-// set buffer's # data to 0
-  l_buf->n_used (0);
-// make the node available for reuse
-  l_queue->make_node_available (l_node);
-}
-
-void
-fusb_ephandle_darwin::abort ()
-{
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::abort: starting.\n");
-
-  io_return_t result = d_interface->AbortPipe (d_interfaceRef, d_pipeRef);
-
-  if (result != kIOReturnSuccess)
-    USB_ERROR_STR_NO_RET (- darwin_to_errno (result),
-                         "fusb_ephandle_darwin::abort "
-                         "(AbortPipe): %s", darwin_error_str (result));
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::abort: finished.\n");
-}
-
-bool
-fusb_ephandle_darwin::stop ()
-{
-  if (! d_started)
-    return (true);
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::stop: stopping %s.\n",
-            d_input_p ? "read" : "write");
-
-  d_started = false;
-
-// abort any pending IO transfers
-  abort ();
-
-// wait for write transfer to finish
-  wait_for_completion ();
-
-// tell IO buffer to abort any waiting conditions
-  d_buffer->abort ();
-
-// stop the run loop
-  CFRunLoopStop (d_CFRunLoopRef);
-
-// wait for the runThread to stop
-  d_runThreadRunning->lock ();
-  d_runThreadRunning->unlock ();
-
-  if (usb_debug)
-    fprintf (stderr, "fusb_ephandle_darwin::stop: %s stopped.\n",
-            d_input_p ? "read" : "write");
-
-  return (true);
-}
-
-void
-fusb_ephandle_darwin::wait_for_completion ()
-{
-  if (d_queue)
-    while (d_queue->in_use ())
-      usleep (1000);
-}
diff --git a/usrp/host/lib/fusb_darwin.h b/usrp/host/lib/fusb_darwin.h
deleted file mode 100644 (file)
index 9254c7f..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _FUSB_DARWIN_H_
-#define _FUSB_DARWIN_H_
-
-#include <usb.h>
-#include "fusb.h"
-#include <IOKit/IOCFBundle.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/IOKitLib.h>
-#include "circular_linked_list.h"
-#include "circular_buffer.h"
-
-// for MacOS X 10.4.[0-3]
-#define usb_interface_t IOUSBInterfaceInterface220
-#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
-#define InterfaceVersion 220
-
-// for MacOS X 10.3.[0-9] and 10.4.[0-3]
-#define usb_device_t    IOUSBDeviceInterface197
-#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
-#define DeviceVersion 197
-
-extern "C" {
-typedef struct usb_dev_handle {
-  int fd;
-
-  struct usb_bus *bus;
-  struct usb_device *device;
-
-  int config;
-  int interface;
-  int altsetting;
-
-  /* Added by RMT so implementations can store other per-open-device data */
-  void *impl_info;
-} usb_dev_handle;
-
-/* Darwin/OS X impl does not use fd field, instead it uses this */
-typedef struct darwin_dev_handle {
-  usb_device_t** device;
-  usb_interface_t** interface;
-  int open;
-} darwin_dev_handle;
-
-typedef IOReturn io_return_t;
-typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
-
-static int ep_to_pipeRef (darwin_dev_handle* device, int ep);
-extern int usb_debug;
-}
-
-class s_buffer
-{
-private:
-  char* d_buffer;
-  UInt32 d_n_used, d_n_alloc;
-
-public:
-  inline s_buffer (UInt32 n_alloc = 0) {
-    d_n_used = 0;
-    d_n_alloc = n_alloc;
-    if (n_alloc) {
-      d_buffer = (char*) new char [n_alloc];
-    } else {
-      d_buffer = 0;
-    }
-  };
-  inline ~s_buffer () {
-    if (d_n_alloc) {
-      delete [] d_buffer;
-    }
-  };
-  inline UInt32 n_used () { return (d_n_used); };
-  inline void n_used (UInt32 bufLen) {
-    d_n_used = (bufLen > d_n_alloc) ? d_n_alloc : bufLen; };
-  inline UInt32 n_alloc () { return (d_n_alloc); };
-  void buffer (char* l_buffer, UInt32 bufLen) {
-    if (bufLen > d_n_alloc) {
-      fprintf (stderr, "s_buffer::set: Copying only allocated bytes.\n");
-      bufLen = d_n_alloc;
-    }
-    if (!l_buffer) {
-      fprintf (stderr, "s_buffer::set: NULL buffer.\n");
-      return;
-    }
-    bcopy (l_buffer, d_buffer, bufLen);
-    d_n_used = bufLen;
-  };
-  inline char* buffer () { return (d_buffer); };
-  inline void reset () {
-    bzero (d_buffer, d_n_alloc);
-    d_n_used = 0;
-  };
-};
-
-typedef s_buffer* s_buffer_ptr;
-typedef s_node<s_buffer_ptr>* s_node_ptr;
-typedef circular_linked_list<s_buffer_ptr>* s_queue_ptr;
-typedef s_both<s_buffer_ptr>* s_both_ptr;
-
-/*!
- * \brief darwin implementation of fusb_devhandle
- *
- * This is currently identical to the generic implementation
- * and is intended as a starting point for whatever magic is
- * required to make usb fly.
- */
-class fusb_devhandle_darwin : public fusb_devhandle
-{
-public:
-  // CREATORS
-  fusb_devhandle_darwin (usb_dev_handle* udh);
-  virtual ~fusb_devhandle_darwin ();
-
-  // MANIPULATORS
-  virtual fusb_ephandle* make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0);
-};
-
-/*!
- * \brief darwin implementation of fusb_ephandle
- *
- * This is currently identical to the generic implementation
- * and is intended as a starting point for whatever magic is
- * required to make usb fly.
- */
-class fusb_ephandle_darwin : public fusb_ephandle
-{
-private:
-  fusb_devhandle_darwin* d_devhandle;
-  mld_thread_ptr d_runThread;
-  mld_mutex_ptr d_runThreadRunning;
-
-  CFRunLoopRef d_CFRunLoopRef;
-
-  static void write_completed (void* ret_io_size,
-                              io_return_t result,
-                              void* io_size);
-  static void read_completed (void* ret_io_size,
-                             io_return_t result,
-                             void* io_size);
-  static void run_thread (void* arg);
-  static void read_thread (void* arg);
-
-  void read_issue (s_both_ptr l_both);
-
-public:
-  // variables, for now
-  UInt8 d_pipeRef, d_transferType;
-  usb_interface_t** d_interfaceRef;
-  usb_interface_t* d_interface;
-  s_queue_ptr d_queue;
-  circular_buffer<char>* d_buffer;
-  UInt32 d_bufLenBytes;
-  mld_mutex_ptr d_readRunning;
-  mld_condition_ptr d_runBlock, d_readBlock;
-
-// CREATORS
-
-  fusb_ephandle_darwin (fusb_devhandle_darwin *dh, int endpoint, bool input_p,
-                        int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle_darwin ();
-
-// MANIPULATORS
-
-  virtual bool start ();       //!< begin streaming i/o
-  virtual bool stop ();                //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void* buffer, int nbytes);
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void* buffer, int nbytes);
-
-  /*
-   * abort any pending IO transfers
-   */
-  void abort ();
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion ();
-};
-
-#endif /* _FUSB_DARWIN_H_ */
diff --git a/usrp/host/lib/fusb_generic.cc b/usrp/host/lib/fusb_generic.cc
deleted file mode 100644 (file)
index f9f3c29..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fusb_generic.h>
-#include <usb.h>
-
-
-static const int USB_TIMEOUT = 1000;   // in milliseconds
-
-
-fusb_devhandle_generic::fusb_devhandle_generic (usb_dev_handle *udh)
-  : fusb_devhandle (udh)
-{
-  // that's it
-}
-
-fusb_devhandle_generic::~fusb_devhandle_generic ()
-{
-  // nop
-}
-
-fusb_ephandle *
-fusb_devhandle_generic::make_ephandle (int endpoint, bool input_p,
-                                      int block_size, int nblocks)
-{
-  return new fusb_ephandle_generic (this, endpoint, input_p,
-                                   block_size, nblocks);
-}
-
-// ----------------------------------------------------------------
-
-fusb_ephandle_generic::fusb_ephandle_generic (fusb_devhandle_generic *dh,
-                                             int endpoint, bool input_p,
-                                             int block_size, int nblocks)
-  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
-    d_devhandle (dh)
-{
-  // that's it
-}
-
-fusb_ephandle_generic::~fusb_ephandle_generic ()
-{
-  // nop
-}
-
-bool
-fusb_ephandle_generic::start ()
-{
-  d_started = true;
-  return true;
-}
-
-bool
-fusb_ephandle_generic::stop ()
-{
-  d_started = false;
-  return true;
-}
-
-int
-fusb_ephandle_generic::write (const void *buffer, int nbytes)
-{
-  if (!d_started)      // doesn't matter here, but keeps semantics constant
-    return -1;
-  
-  if (d_input_p)
-    return -1;
-  
-  return usb_bulk_write (d_devhandle->get_usb_dev_handle (),
-                        d_endpoint, (char *) buffer, nbytes, USB_TIMEOUT);
-}
-
-int
-fusb_ephandle_generic::read (void *buffer, int nbytes)
-{
-  if (!d_started)      // doesn't matter here, but keeps semantics constant
-    return -1;
-
-  if (!d_input_p)
-    return -1;
-
-  return usb_bulk_read (d_devhandle->get_usb_dev_handle (),
-                       d_endpoint|USB_ENDPOINT_IN, (char *) buffer, nbytes,
-                       USB_TIMEOUT);
-}
diff --git a/usrp/host/lib/fusb_generic.h b/usrp/host/lib/fusb_generic.h
deleted file mode 100644 (file)
index 8c3a456..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _FUSB_GENERIC_H_
-#define _FUSB_GENERIC_H_
-
-#include <fusb.h>
-
-/*!
- * \brief generic implementation of fusb_devhandle using only libusb
- */
-class fusb_devhandle_generic : public fusb_devhandle
-{
-public:
-  // CREATORS
-  fusb_devhandle_generic (usb_dev_handle *udh);
-  virtual ~fusb_devhandle_generic ();
-
-  // MANIPULATORS
-  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0);
-};
-
-
-/*!
- * \brief generic implementation of fusb_ephandle using only libusb
- */
-class fusb_ephandle_generic : public fusb_ephandle
-{
-private:
-  fusb_devhandle_generic       *d_devhandle;
-  
-public:
-  // CREATORS
-  fusb_ephandle_generic (fusb_devhandle_generic *dh, int endpoint, bool input_p,
-                        int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle_generic ();
-
-  // MANIPULATORS
-
-  virtual bool start ();       //!< begin streaming i/o
-  virtual bool stop ();                //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void *buffer, int nbytes);
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void *buffer, int nbytes);
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion () { };
-};
-
-#endif /* _FUSB_GENERIC_H_ */
-
diff --git a/usrp/host/lib/fusb_linux.cc b/usrp/host/lib/fusb_linux.cc
deleted file mode 100644 (file)
index 1eaba4e..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fusb_linux.h>
-#include <usb.h>               // libusb header
-#include <stdexcept>
-#ifdef HAVE_LINUX_COMPILER_H
-#include <linux/compiler.h>
-#endif
-#include <linux/usbdevice_fs.h>        // interface to kernel portion of user mode usb driver
-#include <sys/ioctl.h>
-#include <assert.h>
-#include <string.h>
-#include <algorithm>
-#include <errno.h>
-#include <string.h>
-
-#define MINIMIZE_TX_BUFFERING 1                // must be defined to 0 or 1
-
-
-static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();            // hard limit
-static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE;
-static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20);                         // 4 MB / endpoint
-
-
-// Totally evil and fragile extraction of file descriptor from
-// guts of libusb.  They don't install usbi.h, which is what we'd need
-// to do this nicely.
-//
-// FIXME if everything breaks someday in the future, look here...
-
-static int
-fd_from_usb_dev_handle (usb_dev_handle *udh)
-{
-  return *((int *) udh);
-}
-
-inline static void
-urb_set_ephandle (usbdevfs_urb *urb, fusb_ephandle_linux *handle)
-{
-  urb->usercontext = handle;
-}
-
-inline static fusb_ephandle_linux *
-urb_get_ephandle (usbdevfs_urb *urb)
-{
-  return (fusb_ephandle_linux *) urb->usercontext;
-}
-
-// ------------------------------------------------------------------------
-//                USB request block (urb) allocation
-// ------------------------------------------------------------------------
-
-static usbdevfs_urb *
-alloc_urb (fusb_ephandle_linux *self, int buffer_length, int endpoint,
-          bool input_p, unsigned char *write_buffer)
-{
-  usbdevfs_urb *urb = new usbdevfs_urb;
-  memset (urb, 0, sizeof (*urb));
-
-  urb->buffer_length = buffer_length;
-
-  // We allocate dedicated memory only for input buffers.
-  // For output buffers we reuse the same buffer (the kernel 
-  // copies the data at submital time)
-
-  if (input_p)
-    urb->buffer = new unsigned char [buffer_length];
-  else
-    urb->buffer = write_buffer;
-
-  // init common values
-
-  urb->type = USBDEVFS_URB_TYPE_BULK;
-  urb->endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0);
-
-  // USBDEVFS_URB_QUEUE_BULK goes away in linux 2.5, but is needed if
-  // we are using a 2.4 usb-uhci host controller driver.  This is
-  // unlikely since we're almost always going to be plugged into a
-  // high speed host controller (ehci)
-#if 0 && defined (USBDEVFS_URB_QUEUE_BULK)
-  urb->flags = USBDEVFS_URB_QUEUE_BULK;
-#endif
-
-  urb->signr = 0;
-  urb_set_ephandle (urb, self);
-
-  return urb;
-}
-
-static void
-free_urb (usbdevfs_urb *urb)
-{
-  // if this was an input urb, free the buffer
-  if (urb->endpoint & 0x80)
-    delete [] ((unsigned char *) urb->buffer);
-
-  delete urb;
-}
-
-// ------------------------------------------------------------------------
-//                             device handle
-// ------------------------------------------------------------------------
-
-fusb_devhandle_linux::fusb_devhandle_linux (usb_dev_handle *udh)
-  : fusb_devhandle (udh)
-{
-  // that's all
-}
-
-fusb_devhandle_linux::~fusb_devhandle_linux ()
-{
-  // if there are any pending requests, cancel them and free the urbs.
-  
-  std::list<usbdevfs_urb*>::reverse_iterator it;
-
-  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
-    _cancel_urb (*it);
-    free_urb (*it);
-  }
-}
-
-fusb_ephandle *
-fusb_devhandle_linux::make_ephandle (int endpoint, bool input_p,
-                                    int block_size, int nblocks)
-{
-  return new fusb_ephandle_linux (this, endpoint, input_p,
-                                 block_size, nblocks);
-}
-
-
-// Attempt to cancel all transactions associated with eph.
-
-void
-fusb_devhandle_linux::_cancel_pending_rqsts (fusb_ephandle_linux *eph)
-{
-  std::list<usbdevfs_urb*>::reverse_iterator it;
-
-  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
-    if (urb_get_ephandle (*it) == eph)
-      _cancel_urb (*it);
-  }
-}
-
-void 
-fusb_devhandle_linux::pending_add (usbdevfs_urb *urb)
-{
-  d_pending_rqsts.push_back (urb);
-}
-
-usbdevfs_urb *
-fusb_devhandle_linux::pending_get ()
-{
-  if (d_pending_rqsts.empty ())
-    return 0;
-
-  usbdevfs_urb *urb = d_pending_rqsts.front ();
-  d_pending_rqsts.pop_front ();
-  return urb;
-}
-
-bool
-fusb_devhandle_linux::pending_remove (usbdevfs_urb *urb)
-{
-  std::list<usbdevfs_urb*>::iterator   result = find (d_pending_rqsts.begin (),
-                                                      d_pending_rqsts.end (),
-                                                      urb);
-  if (result == d_pending_rqsts.end ()){
-    fprintf (stderr, "fusb::pending_remove: failed to find urb in pending_rqsts: %p\n", urb);
-    return false;
-  }
-  d_pending_rqsts.erase (result);
-  return true;
-}
-
-/*
- * Submit the urb to the kernel.
- * iff successful, the urb will be placed on the devhandle's pending list.
- */
-bool
-fusb_devhandle_linux::_submit_urb (usbdevfs_urb *urb)
-{
-  int  ret;
-
-  ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_SUBMITURB, urb);
-  if (ret < 0){
-    perror ("fusb::_submit_urb");
-    return false;
-  }
-  
-  pending_add (urb);
-  return true;
-}
-
-/*
- * Attempt to cancel the in pending or in-progress urb transaction.
- * Return true iff transaction was sucessfully cancelled.
- *
- * Failure to cancel should not be considered a problem.  This frequently
- * occurs if the transaction has already completed in the kernel but hasn't
- * yet been reaped by the user mode code.
- *
- * urbs which were cancelled have their status field set to -ENOENT when
- * they are reaped.
- */
-bool
-fusb_devhandle_linux::_cancel_urb (usbdevfs_urb *urb)
-{
-  int ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_DISCARDURB, urb);
-  if (ret < 0){
-    // perror ("fusb::_cancel_urb");
-    return false;
-  }
-  return true;
-}
-
-/*
- * Check with the kernel and see if any of our outstanding requests
- * have completed.  For each completed transaction, remove it from the
- * devhandle's pending list and append it to the completed list for
- * the corresponding endpoint.
- *
- * If any transactions are reaped return true.
- *
- * If ok_to_block_p is true, then this will block until at least one
- * transaction completes.
- */
-bool
-fusb_devhandle_linux::_reap (bool ok_to_block_p)
-{
-  int          ret;
-  int          nreaped = 0;
-  usbdevfs_urb *urb = 0;
-
-  int  fd = fd_from_usb_dev_handle (d_udh);
-  
-  // try to reap as many as possible without blocking...
-
-  while ((ret = ioctl (fd, USBDEVFS_REAPURBNDELAY, &urb)) == 0){
-    if (urb->status != 0 && urb->status != -ENOENT){
-      fprintf (stderr, "_reap: usb->status = %d, actual_length = %5d\n",
-              urb->status, urb->actual_length);
-    }
-    pending_remove (urb);
-    urb_get_ephandle (urb)->completed_list_add (urb);
-    nreaped++;
-  }
-
-  if (nreaped > 0)             // if we got any, return w/o blocking
-    return true;
-
-  if (!ok_to_block_p)
-    return false;
-  
-  ret = ioctl (fd, USBDEVFS_REAPURB, &urb);
-  if (ret < 0){
-    perror ("fusb::_reap");
-    return false;
-  }
-
-  pending_remove (urb);
-  urb_get_ephandle (urb)->completed_list_add (urb);
-  return true;
-}
-
-void
-fusb_devhandle_linux::_wait_for_completion ()
-{
-  while (!d_pending_rqsts.empty ())
-    _reap (true);
-}
-\f// ------------------------------------------------------------------------
-//                          end point handle
-// ------------------------------------------------------------------------
-
-fusb_ephandle_linux::fusb_ephandle_linux (fusb_devhandle_linux *devhandle,
-                                         int endpoint,
-                                         bool input_p,
-                                         int block_size, int nblocks)
-  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
-    d_devhandle (devhandle), 
-    d_write_work_in_progress (0), d_write_buffer (0),
-    d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0)
-{
-
-  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE)
-    throw std::out_of_range ("fusb_ephandle_linux: block_size");
-
-  if (d_nblocks < 0)
-    throw std::out_of_range ("fusb_ephandle_linux: nblocks");
-
-  if (d_block_size == 0)
-    d_block_size = DEFAULT_BLOCK_SIZE;
-
-  if (d_nblocks == 0)
-    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size);
-
-  if (!d_input_p)
-    if (!MINIMIZE_TX_BUFFERING)
-      d_write_buffer = new unsigned char [d_block_size];
-
-  if (0)
-    fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d  d_nblocks = %d\n",
-           d_block_size, d_nblocks);
-
-  // allocate urbs
-
-  for (int i = 0; i < d_nblocks; i++)
-    d_free_list.push_back (alloc_urb (this, d_block_size, d_endpoint,
-                                     d_input_p, d_write_buffer));
-}
-
-fusb_ephandle_linux::~fusb_ephandle_linux ()
-{
-  stop ();
-
-  usbdevfs_urb *urb;
-
-  while ((urb = free_list_get ()) != 0)
-    free_urb (urb);
-
-  while ((urb = completed_list_get ()) != 0)
-    free_urb (urb);
-
-  if (d_write_work_in_progress)
-    free_urb (d_write_work_in_progress);
-
-  delete [] d_write_buffer;
-
-  if (d_read_work_in_progress)
-    free_urb (d_read_work_in_progress);
-}
-
-// ----------------------------------------------------------------
-
-bool
-fusb_ephandle_linux::start ()
-{
-  if (d_started)
-    return true;               // already running
-
-  d_started = true;
-
-  if (d_input_p){              // fire off all the reads
-    usbdevfs_urb *urb;
-
-    int nerrors = 0;
-    while ((urb = free_list_get ()) != 0 && nerrors < d_nblocks){
-      if (!submit_urb (urb))
-       nerrors++;
-    }
-  }
-
-  return true;
-}
-
-//
-// kill all i/o in progress.
-// kill any completed but unprocessed transactions.
-//
-bool
-fusb_ephandle_linux::stop ()
-{
-  if (!d_started)
-    return true;
-  
-  d_devhandle->_cancel_pending_rqsts (this);
-  d_devhandle->_reap (false);
-
-
-  usbdevfs_urb *urb;
-  while ((urb = completed_list_get ()) != 0)
-    free_list_add (urb);
-
-  if (d_write_work_in_progress){
-    free_list_add (d_write_work_in_progress);
-    d_write_work_in_progress = 0;
-  }
-
-  if (d_read_work_in_progress){
-    free_list_add (d_read_work_in_progress);
-    d_read_work_in_progress = 0;
-    d_read_buffer = 0;
-    d_read_buffer_end = 0;
-  }
-
-  if (d_free_list.size () != (unsigned) d_nblocks)
-    fprintf (stderr, "d_free_list.size () = %d, d_nblocks = %d\n",
-            d_free_list.size (), d_nblocks);
-    
-  assert (d_free_list.size () == (unsigned) d_nblocks);
-
-  d_started = false;
-  return true;
-}
-
-// ----------------------------------------------------------------
-//                     routines for writing 
-// ----------------------------------------------------------------
-
-#if (MINIMIZE_TX_BUFFERING)
-
-int 
-fusb_ephandle_linux::write(const void *buffer, int nbytes)
-{
-  if (!d_started)
-    return -1;
-  
-  if (d_input_p)
-    return -1;
-
-  assert(nbytes % 512 == 0);
-
-  unsigned char *src = (unsigned char *) buffer;
-
-  int n = 0;
-  while (n < nbytes){
-
-    usbdevfs_urb *urb = get_write_work_in_progress();
-    assert(urb->actual_length == 0);
-    int m = std::min(nbytes - n, MAX_BLOCK_SIZE);
-    urb->buffer = src;
-    urb->buffer_length = m;
-
-    n += m;
-    src += m;
-
-    if (!submit_urb(urb))
-      return -1;
-
-    d_write_work_in_progress = 0;
-  }
-
-  return n;
-}
-
-#else
-
-int 
-fusb_ephandle_linux::write (const void *buffer, int nbytes)
-{
-  if (!d_started)
-    return -1;
-  
-  if (d_input_p)
-    return -1;
-
-  unsigned char *src = (unsigned char *) buffer;
-
-  int n = 0;
-  while (n < nbytes){
-
-    usbdevfs_urb *urb = get_write_work_in_progress ();
-    unsigned char *dst = (unsigned char *) urb->buffer;
-    int m = std::min (nbytes - n, urb->buffer_length - urb->actual_length);
-
-    memcpy (&dst[urb->actual_length], &src[n], m);
-    urb->actual_length += m;
-    n += m;
-
-    if (urb->actual_length == urb->buffer_length){
-      if (!submit_urb (urb))
-       return -1;
-      d_write_work_in_progress = 0;
-    }
-  }
-
-  return n;
-}
-
-#endif
-
-usbdevfs_urb *
-fusb_ephandle_linux::get_write_work_in_progress ()
-{
-  // if we've already got some work in progress, return it
-
-  if (d_write_work_in_progress)
-    return d_write_work_in_progress;
-
-  while (1){
-
-    reap_complete_writes ();
-
-    usbdevfs_urb *urb = free_list_get ();
-
-    if (urb != 0){
-      assert (urb->actual_length == 0);
-      d_write_work_in_progress = urb;
-      return urb;
-    }
-
-    // The free list is empty.  Tell the device handle to reap.
-    // Anything it reaps for us will end up on our completed list.
-
-    d_devhandle->_reap (true);
-  }
-}
-
-void
-fusb_ephandle_linux::reap_complete_writes ()
-{
-  // take a look at the completed_list and xfer to free list after
-  // checking for errors.
-
-  usbdevfs_urb *urb;
-  
-  while ((urb = completed_list_get ()) != 0){
-
-    // Check for any errors or short writes that were reported in the urb.
-    // The kernel sets status, actual_length and error_count.
-    // error_count is only used for ISO xfers.
-    // status is 0 if successful, else is an errno kind of thing
-
-    if (urb->status != 0){
-      fprintf (stderr, "fusb: (status %d) %s\n", urb->status, strerror (-urb->status));
-    }
-    else if (urb->actual_length != urb->buffer_length){
-      fprintf (stderr, "fusb: short write xfer: %d != %d\n",
-              urb->actual_length, urb->buffer_length);
-    }
-
-    free_list_add (urb);
-  }
-}
-
-void
-fusb_ephandle_linux::wait_for_completion ()
-{
-  d_devhandle->_wait_for_completion ();
-}
-
-// ----------------------------------------------------------------
-//                    routines for reading
-// ----------------------------------------------------------------
-
-int
-fusb_ephandle_linux::read (void *buffer, int nbytes)
-{
-  if (!d_started)
-    return -1;
-  
-  if (!d_input_p)
-    return -1;
-
-  unsigned char *dst = (unsigned char *) buffer;
-
-  int n = 0;
-  while (n < nbytes){
-
-    if (d_read_buffer >= d_read_buffer_end)
-      if (!reload_read_buffer ())
-       return -1;
-
-    int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer));
-
-    memcpy (&dst[n], d_read_buffer, m);
-    d_read_buffer += m;
-    n += m;
-  }
-
-  return n;
-}
-
-bool
-fusb_ephandle_linux::reload_read_buffer ()
-{
-  assert (d_read_buffer >= d_read_buffer_end);
-
-  usbdevfs_urb *urb;
-
-  if (d_read_work_in_progress){
-    // We're done with this urb.  Fire off a read to refill it.
-    urb = d_read_work_in_progress;
-    d_read_work_in_progress = 0;
-    d_read_buffer = 0;
-    d_read_buffer_end = 0;
-    urb->actual_length = 0;
-    if (!submit_urb (urb))
-      return false;
-  }
-
-  while (1){
-
-    while ((urb = completed_list_get ()) == 0)
-      d_devhandle->_reap (true);
-
-    // check result of completed read
-
-    if (urb->status != 0){
-      // We've got a problem.
-      // Report the problem and resubmit.
-      fprintf (stderr, "fusb: (rd status %d) %s\n", urb->status, strerror (-urb->status));
-      urb->actual_length = 0;
-      if (!submit_urb (urb))
-       return false;
-
-      continue;
-    }
-
-    // we've got a happy urb, full of data...
-
-    d_read_work_in_progress = urb;
-    d_read_buffer = (unsigned char *) urb->buffer;
-    d_read_buffer_end = d_read_buffer + urb->actual_length;
-
-    return true;
-  }
-}
-
-// ----------------------------------------------------------------
-
-void
-fusb_ephandle_linux::free_list_add (usbdevfs_urb *urb)
-{
-  assert (urb_get_ephandle (urb) == this);
-  urb->actual_length = 0;
-  d_free_list.push_back (urb);
-}
-
-usbdevfs_urb *
-fusb_ephandle_linux::free_list_get ()
-{
-  if (d_free_list.empty ())
-    return 0;
-
-  usbdevfs_urb *urb = d_free_list.front ();
-  d_free_list.pop_front ();
-  return urb;
-}
-
-void
-fusb_ephandle_linux::completed_list_add (usbdevfs_urb *urb)
-{
-  assert (urb_get_ephandle (urb) == this);
-  d_completed_list.push_back (urb);
-}
-
-usbdevfs_urb *
-fusb_ephandle_linux::completed_list_get ()
-{
-  if (d_completed_list.empty ())
-    return 0;
-
-  usbdevfs_urb *urb = d_completed_list.front ();
-  d_completed_list.pop_front ();
-  return urb;
-}
-
-/*
- * Submit the urb.  If successful the urb ends up on the devhandle's
- * pending list, otherwise, it's back on our free list.
- */
-bool
-fusb_ephandle_linux::submit_urb (usbdevfs_urb *urb)
-{
-  if (!d_devhandle->_submit_urb (urb)){    // FIXME record the problem somewhere
-    fprintf (stderr, "_submit_urb failed\n");
-    free_list_add (urb);
-    return false;
-  }
-  return true;
-}
diff --git a/usrp/host/lib/fusb_linux.h b/usrp/host/lib/fusb_linux.h
deleted file mode 100644 (file)
index b2d46a5..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-// Fast USB interface
-
-#ifndef _FUSB_LINUX_H_
-#define _FUSB_LINUX_H_
-
-#include <fusb.h>
-#include <list>
-
-struct  usbdevfs_urb;
-class   fusb_ephandle_linux;
-
-/*!
- * \brief linux specific implementation of fusb_devhandle using usbdevice_fs
- */
-class fusb_devhandle_linux : public fusb_devhandle {
-private:
-  std::list<usbdevfs_urb*>      d_pending_rqsts;
-
-  void pending_add (usbdevfs_urb *urb);
-  bool pending_remove (usbdevfs_urb *urb);
-  usbdevfs_urb * pending_get ();
-
-
-public:
-  // CREATORS
-  fusb_devhandle_linux (usb_dev_handle *udh);
-  virtual ~fusb_devhandle_linux ();
-
-  // MANIPULATORS
-  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0);
-
-  // internal use only
-  bool _submit_urb (usbdevfs_urb *urb);
-  bool _cancel_urb (usbdevfs_urb *urb);
-  void _cancel_pending_rqsts (fusb_ephandle_linux *eph);
-  bool _reap (bool ok_to_block_p);
-  void _wait_for_completion ();
-};
-
-\f/*!
- * \brief linux specific implementation of fusb_ephandle using usbdevice_fs
- */
-
-class fusb_ephandle_linux : public fusb_ephandle {
-private:
-  fusb_devhandle_linux        *d_devhandle;
-  std::list<usbdevfs_urb*>     d_free_list;
-  std::list<usbdevfs_urb*>     d_completed_list;
-  usbdevfs_urb                *d_write_work_in_progress;
-  unsigned char                       *d_write_buffer;
-  usbdevfs_urb                *d_read_work_in_progress;
-  unsigned char                       *d_read_buffer;
-  unsigned char                       *d_read_buffer_end;
-
-  usbdevfs_urb *get_write_work_in_progress ();
-  void reap_complete_writes ();
-  bool reload_read_buffer ();
-  bool submit_urb (usbdevfs_urb *urb);
-  
-public:
-  fusb_ephandle_linux (fusb_devhandle_linux *dh, int endpoint, bool input_p,
-                      int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle_linux ();
-
-  virtual bool start ();       //!< begin streaming i/o
-  virtual bool stop ();                //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void *buffer, int nbytes);
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void *buffer, int nbytes);
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion ();
-
-  // internal use only
-  void free_list_add (usbdevfs_urb *urb);
-  void completed_list_add (usbdevfs_urb *urb);
-  usbdevfs_urb *free_list_get ();              // pop and return head of list or 0
-  usbdevfs_urb *completed_list_get ();         // pop and return head of list or 0
-};
-
-#endif /* _FUSB_LINUX_H_ */
diff --git a/usrp/host/lib/fusb_ra_wb.cc b/usrp/host/lib/fusb_ra_wb.cc
deleted file mode 100644 (file)
index c95f4af..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fusb_ra_wb.h>
-#include <usb.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sys/event.h>
-#include <dev/usb/usb.h>
-
-static const int USB_TIMEOUT = 1000;   // in milliseconds
-
-// the following comment and function is from fusb_linux.cc
-#if 0
-// Totally evil and fragile extraction of file descriptor from
-// guts of libusb.  They don't install usbi.h, which is what we'd need
-// to do this nicely.
-//
-// FIXME if everything breaks someday in the future, look here...
-
-static int
-fd_from_usb_dev_handle (usb_dev_handle *udh)
-{
-  return *((int *) udh);
-}
-#endif
-
-// the control endpoint doesn't actually do us any good so here is a
-// new "fragile extraction"
-static int
-ep_fd_from_usb_dev_handle (usb_dev_handle *udh, int endpoint)
-{
-  struct usb_dev_handle_kludge2 { // see also usrp_prims.cc
-    int                         fd;
-    struct usb_bus     *bus;
-    struct usb_device  *device;
-    int                         config;
-    int                         interface;
-    int                         altsetting;
-    void               *impl_info;
-  };
-  struct bsd_usb_dev_handle_info_kludge {
-    int                         ep_fd[USB_MAX_ENDPOINTS];
-  };
-  struct bsd_usb_dev_handle_info_kludge *info
-      = (struct bsd_usb_dev_handle_info_kludge *)
-           ((struct usb_dev_handle_kludge2 *)udh)->impl_info;
-  return info->ep_fd[UE_GET_ADDR(endpoint)];
-}
-
-
-fusb_devhandle_ra_wb::fusb_devhandle_ra_wb (usb_dev_handle *udh)
-  : fusb_devhandle (udh)
-{
-  // that's it
-}
-
-fusb_devhandle_ra_wb::~fusb_devhandle_ra_wb ()
-{
-  // nop
-}
-
-fusb_ephandle *
-fusb_devhandle_ra_wb::make_ephandle (int endpoint, bool input_p,
-                                    int block_size, int nblocks)
-{
-  return new fusb_ephandle_ra_wb (this, endpoint, input_p,
-                                 block_size, nblocks);
-}
-
-// ----------------------------------------------------------------
-
-fusb_ephandle_ra_wb::fusb_ephandle_ra_wb (fusb_devhandle_ra_wb *dh,
-                                         int endpoint, bool input_p,
-                                         int block_size, int nblocks)
-  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
-    d_devhandle (dh), d_ra_wb_on (false)
-{
-  // that's it 
-}
-
-fusb_ephandle_ra_wb::~fusb_ephandle_ra_wb ()
-{
-  // nop
-}
-
-bool
-fusb_ephandle_ra_wb::start ()
-{
-  d_started = true;
-
-  char buf = '\0';
-  int fd;
-
-  // this is to cause libusb to open the endpoint
-  if (!d_input_p) {
-    write(&buf, 0);
-    fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
-                                   d_endpoint);
-  }
-  else {
-    read(&buf, 0);
-    fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
-                                   d_endpoint|USB_ENDPOINT_IN);
-  }
-
-  // enable read ahead/write behind
-  int ret;
-  struct usb_bulk_ra_wb_opt opts;
-  int enable = 1;
-
-  opts.ra_wb_buffer_size = d_block_size*d_nblocks;
-  opts.ra_wb_request_size = d_block_size;
-//  fprintf (stderr, "setting buffer size to %d, request size to %d\n",
-//        opts.ra_wb_buffer_size, opts.ra_wb_request_size);
-  if (!d_input_p) {
-    ret = ioctl (fd, USB_SET_BULK_WB_OPT, &opts);
-    if (ret < 0)
-      fprintf (stderr, "USB_SET_BULK_WB_OPT: %s\n", strerror(errno));
-    else {
-      ret = ioctl (fd, USB_SET_BULK_WB, &enable);
-      if (ret < 0)
-       fprintf (stderr, "USB_SET_BULK_WB: %s\n", strerror(errno));
-      else
-       d_ra_wb_on = true;
-    }
-  }
-  else {
-    ret = ioctl (fd, USB_SET_BULK_RA_OPT, &opts);
-    if (ret < 0)
-      fprintf (stderr, "USB_SET_BULK_RA_OPT: %s\n", strerror(errno));
-    else {
-      ret = ioctl (fd, USB_SET_BULK_RA, &enable);
-      if (ret < 0)
-       fprintf (stderr, "USB_SET_BULK_RA: %s\n", strerror(errno));
-      else
-       d_ra_wb_on = true;
-    }
-  }
-
-  return true;
-}
-
-bool
-fusb_ephandle_ra_wb::stop ()
-{
-  int fd;
-  int ret;
-  int enable = 0;
-  if (d_ra_wb_on) {
-    if (!d_input_p) {
-      fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
-                                     d_endpoint);
-      ret = ioctl (fd, USB_SET_BULK_WB, &enable);
-      if (ret < 0)
-       fprintf (stderr, "USB_SET_BULK_WB: %s\n", strerror(errno));
-      else
-       d_ra_wb_on = false;
-    }
-    else {
-      fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
-                                     d_endpoint|USB_ENDPOINT_IN);
-      ret = ioctl (fd, USB_SET_BULK_RA, &enable);
-      if (ret < 0)
-       fprintf (stderr, "USB_SET_BULK_RA: %s\n", strerror(errno));
-      else
-       d_ra_wb_on = false;
-    }
-  }
-
-  d_started = false;
-  return true;
-}
-
-int
-fusb_ephandle_ra_wb::write (const void *buffer, int nbytes)
-{
-  if (!d_started)
-    return -1;
-  
-  if (d_input_p)
-    return -1;
-  
-  return usb_bulk_write (d_devhandle->get_usb_dev_handle (),
-                        d_endpoint, (char *) buffer, nbytes, USB_TIMEOUT);
-}
-
-int
-fusb_ephandle_ra_wb::read (void *buffer, int nbytes)
-{
-  if (!d_started)
-    return -1;
-
-  if (!d_input_p)
-    return -1;
-
-  return usb_bulk_read (d_devhandle->get_usb_dev_handle (),
-                       d_endpoint|USB_ENDPOINT_IN, (char *) buffer, nbytes,
-                       USB_TIMEOUT);
-}
-
-void
-fusb_ephandle_ra_wb::wait_for_completion ()
-{
-  // as the driver is implemented this only makes sense for write 
-  if (d_ra_wb_on && !d_input_p) {
-    int fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
-                                       d_endpoint);
-    int kq = kqueue();
-    if (kq < 0)
-      return;
-    struct kevent evt;
-    int nevents;
-    EV_SET (&evt, fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, 0/*NULL*/);
-    nevents = kevent (kq, &evt, 1, &evt, 1, NULL);
-    if (nevents < 1) {
-      close(kq);
-      return;
-    }
-    while (!(evt.flags & EV_ERROR) && evt.data < (d_block_size*d_nblocks)) {
-      // it's a busy loop, but that's all I can do at the moment
-      nevents = kevent (kq, NULL, 0, &evt, 1, NULL);
-      // let's see if this improves the test_usrp_standard_tx throughput &
-      // "CPU usage" by looping less frequently
-      struct timeval timeout;
-      timeout.tv_sec = 0;
-      timeout.tv_usec = 1000; // 1 ms
-      select (0, NULL, NULL, NULL, &timeout);
-    }
-    close (kq);
-  }
-}
diff --git a/usrp/host/lib/fusb_ra_wb.h b/usrp/host/lib/fusb_ra_wb.h
deleted file mode 100644 (file)
index 09bf8ee..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _FUSB_RA_WB_H_
-#define _FUSB_RA_WB_H_
-
-#include <fusb.h>
-
-/*!
- * \brief generic implementation of fusb_devhandle using only libusb
- */
-class fusb_devhandle_ra_wb : public fusb_devhandle
-{
-public:
-  // CREATORS
-  fusb_devhandle_ra_wb (usb_dev_handle *udh);
-  virtual ~fusb_devhandle_ra_wb ();
-
-  // MANIPULATORS
-  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0);
-};
-
-
-/*!
- * \brief generic implementation of fusb_ephandle using only libusb
- */
-class fusb_ephandle_ra_wb : public fusb_ephandle
-{
-private:
-  fusb_devhandle_ra_wb *d_devhandle;
-  bool d_ra_wb_on;
-  
-public:
-  // CREATORS
-  fusb_ephandle_ra_wb (fusb_devhandle_ra_wb *dh, int endpoint, bool input_p,
-                      int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle_ra_wb ();
-
-  // MANIPULATORS
-
-  virtual bool start ();       //!< begin streaming i/o
-  virtual bool stop ();                //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void *buffer, int nbytes);
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void *buffer, int nbytes);
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion ();
-};
-
-#endif /* _FUSB_RA_WB_H_ */
-
diff --git a/usrp/host/lib/fusb_sysconfig_darwin.cc b/usrp/host/lib/fusb_sysconfig_darwin.cc
deleted file mode 100644 (file)
index f66c298..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <fusb.h>
-#include <fusb_darwin.h>
-
-static const int MAX_BLOCK_SIZE = 32 * 1024;           // hard limit
-static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
-
-fusb_devhandle *
-fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
-{
-  return new fusb_devhandle_darwin (udh);
-}
-
-int fusb_sysconfig::max_block_size ()
-{
-  return MAX_BLOCK_SIZE;
-}
-
-int fusb_sysconfig::default_buffer_size ()
-{
-  return FUSB_BUFFER_SIZE;
-}
-
diff --git a/usrp/host/lib/fusb_sysconfig_generic.cc b/usrp/host/lib/fusb_sysconfig_generic.cc
deleted file mode 100644 (file)
index d336cb9..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <fusb.h>
-#include <fusb_generic.h>
-
-static const int MAX_BLOCK_SIZE = 16 * 1024;           // hard limit
-static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
-
-fusb_devhandle *
-fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
-{
-  return new fusb_devhandle_generic (udh);
-}
-       
-int fusb_sysconfig::max_block_size ()
-{
-  return MAX_BLOCK_SIZE;
-}
-
-int fusb_sysconfig::default_buffer_size ()
-{
-  return FUSB_BUFFER_SIZE;
-}
diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc
deleted file mode 100644 (file)
index 468fa9f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <fusb.h>
-#include <fusb_linux.h>
-
-static const int MAX_BLOCK_SIZE = 16 * 1024;           // hard limit
-static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
-
-fusb_devhandle *
-fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
-{
-  return new fusb_devhandle_linux (udh);
-}
-
-int fusb_sysconfig::max_block_size ()
-{
-  return MAX_BLOCK_SIZE;
-}
-
-int fusb_sysconfig::default_buffer_size ()
-{
-  return FUSB_BUFFER_SIZE;
-}
diff --git a/usrp/host/lib/fusb_sysconfig_ra_wb.cc b/usrp/host/lib/fusb_sysconfig_ra_wb.cc
deleted file mode 100644 (file)
index 68eeced..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <fusb.h>
-#include <fusb_ra_wb.h>
-
-//static const int MAX_BLOCK_SIZE = 16 * 1024;         // hard limit
-// there's no hard limit, even before making any changes to the driver
-// 64k is empirically a pretty good number
-static const int MAX_BLOCK_SIZE = 64 * 1024;
-// there is a limit of 1 MB in the driver for the buffer size
-static const int FUSB_BUFFER_SIZE = 256 * (1L << 10);  // 256 kB
-
-fusb_devhandle *
-fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
-{
-  return new fusb_devhandle_ra_wb (udh);
-}
-       
-int fusb_sysconfig::max_block_size ()
-{
-  return MAX_BLOCK_SIZE;
-}
-
-int fusb_sysconfig::default_buffer_size ()
-{
-  return FUSB_BUFFER_SIZE;
-}
diff --git a/usrp/host/lib/fusb_sysconfig_win32.cc b/usrp/host/lib/fusb_sysconfig_win32.cc
deleted file mode 100644 (file)
index 282e77a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2005 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <fusb.h>
-#include <fusb_win32.h>
-
-static const int MAX_BLOCK_SIZE = 64 * 1024;           // Windows kernel hard limit
-static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
-       
-fusb_devhandle *
-fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
-{
-  return new fusb_devhandle_win32 (udh);
-}
-
-int fusb_sysconfig::max_block_size ()
-{
-  return MAX_BLOCK_SIZE;
-}
-
-int fusb_sysconfig::default_buffer_size ()
-{
-  return FUSB_BUFFER_SIZE;
-}
diff --git a/usrp/host/lib/fusb_win32.cc b/usrp/host/lib/fusb_win32.cc
deleted file mode 100644 (file)
index c6e3c97..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2005 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fusb_win32.h>
-#include <usb.h>
-#include <assert.h>
-#include <stdexcept>
-
-static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();
-static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE;
-static const int DEFAULT_BUFFER_SIZE = 16 * (1L << 20);                // 16 MB / endpoint
-
-
-static const int USB_TIMEOUT = 1000;   // in milliseconds
-
-
-fusb_devhandle_win32::fusb_devhandle_win32 (usb_dev_handle *udh)
-  : fusb_devhandle (udh)
-{
-  // that's it
-}
-
-fusb_devhandle_win32::~fusb_devhandle_win32 ()
-{
-  // nop
-}
-
-fusb_ephandle *
-fusb_devhandle_win32::make_ephandle (int endpoint, bool input_p,
-                                      int block_size, int nblocks)
-{
-  return new fusb_ephandle_win32 (this, endpoint, input_p,
-                                   block_size, nblocks);
-}
-
-// ----------------------------------------------------------------
-
-fusb_ephandle_win32::fusb_ephandle_win32 (fusb_devhandle_win32 *dh,
-                                             int endpoint, bool input_p,
-                                             int block_size, int nblocks)
-  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
-    d_devhandle (dh), d_input_leftover(0),d_output_short(0)
-{
-  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE)
-    throw std::out_of_range ("fusb_ephandle_win32: block_size");
-
-  if (d_nblocks < 0)
-    throw std::out_of_range ("fusb_ephandle_win32: nblocks");
-
-  if (d_block_size == 0)
-    d_block_size = DEFAULT_BLOCK_SIZE;
-
-  if (d_nblocks == 0)
-    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size);
-
-  d_buffer = new char [d_block_size*d_nblocks];
-  d_context = new void * [d_nblocks];
-
-  // allocate contexts
-
-  usb_dev_handle *dev = dh->get_usb_dev_handle ();
-  int i;
-
-  if (d_input_p)
-    endpoint |= USB_ENDPOINT_IN;
-
-  for (i=0; i<d_nblocks; i++)
-    usb_bulk_setup_async(dev, &d_context[i], endpoint);
-}
-
-fusb_ephandle_win32::~fusb_ephandle_win32 ()
-{
-  int i;
-
-  stop ();
-
-  for (i=0; i<d_nblocks; i++)
-    usb_free_async(&d_context[i]);
-
-  delete [] d_buffer;
-  delete [] d_context;
-}
-
-bool
-fusb_ephandle_win32::start ()
-{
-  if (d_started)
-    return true;       // already running
-
-  d_started = true;
-
-  d_curr = d_nblocks-1;
-  d_outstanding_write = 0;
-  d_input_leftover =0;
-  d_output_short = 0;
-
-  if (d_input_p){      // fire off all the reads
-    int i;
-
-    for (i=0; i<d_nblocks; i++) {
-      usb_submit_async(d_context[i], (char * ) d_buffer+i*d_block_size,
-                     d_block_size);
-    }
-  }
-
-  return true;
-}
-
-bool
-fusb_ephandle_win32::stop ()
-{
-  if (!d_started)
-    return true;
-
-  if (!d_input_p)
-    wait_for_completion ();
-
-  d_started = false;
-  return true;
-}
-
-int
-fusb_ephandle_win32::write (const void *buffer, int nbytes)
-{
-  int retval=0;
-  char *buf;
-
-  if (!d_started)      // doesn't matter here, but keeps semantics constant
-    return -1;
-
-  if (d_input_p)
-    return -1;
-
-  int bytes_to_write = nbytes;
-  int a=0;
-
-  if (d_output_short != 0) {
-
-       buf = &d_buffer[d_curr*d_block_size + d_block_size - d_output_short];
-       a = std::min(nbytes, d_output_short);
-       memcpy(buf, buffer, a);
-       bytes_to_write -= a;
-       d_output_short -= a;
-
-    if (d_output_short == 0)
-        usb_submit_async(d_context[d_curr],
-                        &d_buffer[d_curr*d_block_size], d_block_size);
-  }
-
-  while (bytes_to_write > 0) {
-    d_curr = (d_curr+1)%d_nblocks;
-    buf = &d_buffer[d_curr*d_block_size];
-
-    if (d_outstanding_write != d_nblocks) {
-      d_outstanding_write++;
-    } else {
-      retval = usb_reap_async(d_context[d_curr], USB_TIMEOUT);
-      if (retval < 0) {
-                 fprintf(stderr, "%s: usb_reap_async: %s\n",
-                         __FUNCTION__, usb_strerror());
-         return retval;
-       }
-    }
-
-    int ncopy = std::min(bytes_to_write, d_block_size);
-    memcpy(buf, (void *) &(((char*)buffer)[a]), ncopy);
-    bytes_to_write -= ncopy;
-    a += ncopy;
-
-    d_output_short = d_block_size - ncopy;
-    if (d_output_short == 0)
-           usb_submit_async(d_context[d_curr], buf, d_block_size);
-  }
-
-  return retval < 0 ? retval : nbytes;
-}
-
-int
-fusb_ephandle_win32::read (void *buffer, int nbytes)
-{
-  int retval=0;
-  char *buf;
-
-  if (!d_started)      // doesn't matter here, but keeps semantics constant
-    return -1;
-
-  if (!d_input_p)
-    return -1;
-
-  int bytes_to_read = nbytes;
-
-  int a=0;
-  if (d_input_leftover != 0) {
-
-       buf = &d_buffer[d_curr*d_block_size + d_block_size - d_input_leftover];
-       a = std::min(nbytes, d_input_leftover);
-       memcpy(buffer, buf, a);
-       bytes_to_read -= a;
-       d_input_leftover -= a;
-
-    if (d_input_leftover == 0)
-        usb_submit_async(d_context[d_curr],
-                        &d_buffer[d_curr*d_block_size], d_block_size);
-  }
-
-  while (bytes_to_read > 0) {
-
-    d_curr = (d_curr+1)%d_nblocks;
-    buf = &d_buffer[d_curr*d_block_size];
-
-    retval = usb_reap_async(d_context[d_curr], USB_TIMEOUT);
-    if (retval < 0)
-         fprintf(stderr, "%s: usb_reap_async: %s\n",
-                         __FUNCTION__, usb_strerror());
-
-    int ncopy = std::min(bytes_to_read, d_block_size);
-    memcpy((void *) &(((char*)buffer)[a]), buf, ncopy);
-    bytes_to_read -= ncopy;
-    a += ncopy;
-
-    d_input_leftover = d_block_size - ncopy;
-    if (d_input_leftover == 0)
-           usb_submit_async(d_context[d_curr], buf, d_block_size);
-  }
-
-  return retval < 0 ? retval : nbytes;
-}
-
-void
-fusb_ephandle_win32::wait_for_completion ()
-{
-  int i;
-
-  for (i=0; i<d_outstanding_write; i++) {
-    int context_num;
-
-    context_num = (d_curr+d_outstanding_write+i+1)%d_nblocks;
-    usb_reap_async(d_context[context_num], USB_TIMEOUT);
-  }
-
-  d_outstanding_write = 0;
-}
diff --git a/usrp/host/lib/fusb_win32.h b/usrp/host/lib/fusb_win32.h
deleted file mode 100644 (file)
index c796af4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _FUSB_WIN32_H_
-#define _FUSB_WIN32_H_
-
-#include <fusb.h>
-
-/*!
- * \brief win32 implementation of fusb_devhandle using libusb-win32
- */
-class fusb_devhandle_win32 : public fusb_devhandle
-{
-public:
-  // CREATORS
-  fusb_devhandle_win32 (usb_dev_handle *udh);
-  virtual ~fusb_devhandle_win32 ();
-
-  // MANIPULATORS
-  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
-                                       int block_size = 0, int nblocks = 0);
-};
-
-
-/*!
- * \brief win32 implementation of fusb_ephandle using libusb-win32
- */
-class fusb_ephandle_win32 : public fusb_ephandle
-{
-private:
-  fusb_devhandle_win32 *d_devhandle;
-
-  unsigned d_curr;
-  unsigned d_outstanding_write;
-  int d_output_short;
-  int d_input_leftover;
-  void ** d_context;
-  char * d_buffer;
-
-public:
-  // CREATORS
-  fusb_ephandle_win32 (fusb_devhandle_win32 *dh, int endpoint, bool input_p,
-                        int block_size = 0, int nblocks = 0);
-  virtual ~fusb_ephandle_win32 ();
-
-  // MANIPULATORS
-
-  virtual bool start ();       //!< begin streaming i/o
-  virtual bool stop ();                //!< stop streaming i/o
-
-  /*!
-   * \returns \p nbytes if write was successfully enqueued, else -1.
-   * Will block if no free buffers available.
-   */
-  virtual int write (const void *buffer, int nbytes);
-
-  /*!
-   * \returns number of bytes read or -1 if error.
-   * number of bytes read will be <= nbytes.
-   * Will block if no input available.
-   */
-  virtual int read (void *buffer, int nbytes);
-
-  /*
-   * block until all outstanding writes have completed
-   */
-  virtual void wait_for_completion ();
-};
-
-#endif /* _FUSB_WIN32_H_ */
-
diff --git a/usrp/host/lib/gen_usrp_dbid.py b/usrp/host/lib/gen_usrp_dbid.py
deleted file mode 100755 (executable)
index 14d3ee5..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os
-import os.path
-import re
-from optparse import OptionParser
-
-def write_header(f, comment_char):
-    f.write(comment_char); f.write('\n')
-    f.write(comment_char); f.write(' Machine generated by gen_usrp_dbid.py from usrp_dbid.dat\n')
-    f.write(comment_char); f.write(' Do not edit by hand.  All edits will be overwritten.\n')
-    f.write(comment_char); f.write('\n')
-    f.write('\n')
-
-def gen_dbid_py(r):
-    f = open('usrp_dbid.py', 'w')
-    comment_char = '#'
-    write_header(f, comment_char)
-    f.write(comment_char); f.write('\n')
-    f.write(comment_char); f.write(" USRP Daughterboard ID's\n")
-    f.write(comment_char); f.write('\n')
-    f.write('\n')
-    for x in r:
-        f.write('%-16s = %s\n' % (x[1], x[2]))
-
-def gen_dbid_h(r):
-    f = open('usrp_dbid.h', 'w')
-    comment_char = '//'
-    write_header(f, comment_char)
-    f.write(comment_char); f.write('\n')
-    f.write(comment_char); f.write(" USRP Daughterboard ID's\n")
-    f.write(comment_char); f.write('\n')
-    f.write('\n')
-    f.write('#ifndef INCLUDED_USRP_DBID_H\n')
-    f.write('#define INCLUDED_USRP_DBID_H\n')
-    f.write('\n')
-    for x in r:
-        f.write('#define %-25s %s\n' % ('USRP_DBID_' + x[1], x[2]))
-    f.write('\n')
-    f.write('#endif /* INCLUDED_USRP_DBID_H */\n')
-
-def gen_dbid_cc(r):
-    f = open('usrp_dbid.cc', 'w')
-    write_header(f, '//')
-    head = '''/*
- * Copyright 2005 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <usrp_prims.h>
-#include <usrp_dbid.h>
-#include <stdio.h>
-
-#define NELEM(x) sizeof(x)/sizeof(x[0])
-
-static struct {
-  unsigned short       dbid;
-  const char          *name;
-} dbid_map[] = {
-'''
-    
-    tail = '''};
-
-const std::string
-usrp_dbid_to_string (int dbid)
-{
-  if (dbid == -1)
-    return "<none>";
-
-  if (dbid == -2)
-    return "<invalid EEPROM contents>";
-
-  for (unsigned i = 0; i < NELEM (dbid_map); i++)
-    if (dbid == dbid_map[i].dbid)
-      return dbid_map[i].name;
-
-  char tmp[64];
-  snprintf (tmp, sizeof (tmp), "Unknown (0x%04x)", dbid);
-  return tmp;
-}
-'''
-    f.write(head)
-    for x in r:
-        f.write('  { %-27s "%s" },\n' % (
-            'USRP_DBID_' + x[1] + ',', x[0]))
-    f.write(tail)
-
-def gen_all(src_filename):
-    src_file = open(src_filename, 'r')
-    r = []
-    for line in src_file:
-        line = line.strip()
-        line = re.sub(r'\s*#.*$','', line)
-        if len(line) == 0:
-            continue
-        mo = re.match('"([^"]+)"\s*(0x[0-9a-fA-F]+)', line)
-        if mo:
-            str_name = mo.group(1)
-            id_name = str_name.upper().replace(' ', '_')
-            id_val = mo.group(2)
-            r.append((str_name, id_name, id_val))
-            #sys.stdout.write('%-16s\t%-16s\t%s\n' % ('"'+str_name+'"', id_name, id_val))
-
-    gen_dbid_h(r)
-    gen_dbid_py(r)
-    gen_dbid_cc(r)
-    
-
-def main():
-    usage = "usage: %prog [options] usrp_dbid.dat"
-    parser = OptionParser(usage=usage)
-    (options, args) = parser.parse_args()
-    if len(args) != 1:
-        parser.print_help()
-        sys.exit(1)
-
-    gen_all(args[0])
-
-if __name__ == '__main__':
-    main()
diff --git a/usrp/host/lib/inband/Makefile.am b/usrp/host/lib/inband/Makefile.am
new file mode 100644 (file)
index 0000000..9f6a7ab
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# 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.
+#
+
+include $(top_srcdir)/Makefile.common
+
+INCLUDES =     \
+       $(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
+       $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+
+TESTS = test_inband
+
+EXTRA_DIST =                           
+
+lib_LTLIBRARIES =                      \
+       libusrp_inband.la               \
+       libusrp_inband-qa.la                    
+
+
+# ------------------------------------------------------------------------
+# Build the inband library
+
+BUILT_SOURCES =                                \
+       usrp_server_mbh.cc
+
+usrp_server_mbh.cc : usrp_server.mbh
+       $(COMPILE_MBH) usrp_server.mbh usrp_server_mbh.cc
+
+libusrp_inband_la_SOURCES =            \
+       $(BUILT_SOURCES)                \
+       usrp_server.cc
+
+libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
+
+libusrp_inband_la_LIBADD =             \
+       $(MBLOCK_LA)                    \
+       -lstdc++
+
+
+include_HEADERS =                      \
+       usrp_server.h                   
+
+noinst_HEADERS =                       \
+       qa_inband.h                     \
+       qa_inband_packet_prims.h        \
+       qa_inband_usrp_server.h
+
+# ------------------------------------------------------------------------
+# Build the qa code in its own library
+
+libusrp_inband_qa_la_SOURCES =         \
+       qa_inband.cc                    \
+       qa_inband_packet_prims.cc       \
+       qa_inband_usrp_server.cc        
+
+# magic flags
+libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
+
+# link against c++ standard library
+libusrp_inband_qa_la_LIBADD =          \
+       libusrp_inband.la               \
+       $(CPPUNIT_LIBS)                 \
+       -lstdc++
+
+# ------------------------------------------------------------------------
+
+noinst_PROGRAMS =                      \
+       test_inband
+
+test_inband_SOURCES = test_inband.cc
+test_inband_LDADD   = libusrp_inband-qa.la
+
+
+MOSTLYCLEANFILES = \
+       $(BUILT_SOURCES) *~ *.pyc
+
diff --git a/usrp/host/lib/inband/dump_packets.py b/usrp/host/lib/inband/dump_packets.py
new file mode 100755 (executable)
index 0000000..ea27ca5
--- /dev/null
@@ -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()
diff --git a/usrp/host/lib/inband/gen_test_packets.py b/usrp/host/lib/inband/gen_test_packets.py
new file mode 100755 (executable)
index 0000000..1e22722
--- /dev/null
@@ -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"))
diff --git a/usrp/host/lib/inband/qa_inband.cc b/usrp/host/lib/inband/qa_inband.cc
new file mode 100644 (file)
index 0000000..00a821f
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- 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.
+ */
+
+#include <qa_inband.h>
+#include <qa_inband_packet_prims.h>
+#include <qa_inband_usrp_server.h>
+
+CppUnit::TestSuite *
+qa_inband::suite()
+{
+  CppUnit::TestSuite   *s = new CppUnit::TestSuite("inband");
+
+  s->addTest (qa_inband_packet_prims::suite());
+  s->addTest (qa_inband_usrp_server::suite());
+
+  return s;
+}
diff --git a/usrp/host/lib/inband/qa_inband.h b/usrp/host/lib/inband/qa_inband.h
new file mode 100644 (file)
index 0000000..92386f9
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- 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_QA_INBAND_H
+#define INCLUDED_QA_INBAND_H
+
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for the user server
+
+class qa_inband {
+ public:
+  //! return suite of tests for all of usrp server
+  static CppUnit::TestSuite *suite();
+};
+
+#endif /* INCLUDED_QA_INBAND_H */
diff --git a/usrp/host/lib/inband/qa_inband_packet_prims.cc b/usrp/host/lib/inband/qa_inband_packet_prims.cc
new file mode 100644 (file)
index 0000000..9d9a0c7
--- /dev/null
@@ -0,0 +1,161 @@
+/* -*- 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_inband_packet_prims.h>
+#include <cppunit/TestAssert.h>
+#include <stdio.h>
+#include <usrp_inband_usb_packet.h>             // will change on gigabit crossover
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+void
+qa_inband_packet_prims::test_flags()
+{
+  transport_pkt pkt;
+
+  // Test each one of the flags while ensuring no other fields become set in the process
+  pkt.set_header(pkt.FL_START_OF_BURST,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  pkt.set_header(pkt.FL_END_OF_BURST,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  pkt.set_header(pkt.FL_OVERRUN,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  pkt.set_header(pkt.FL_UNDERRUN,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  pkt.set_header(pkt.FL_DROPPED,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  // test of all fields set
+  pkt.set_header(
+    pkt.FL_START_OF_BURST |
+    pkt.FL_END_OF_BURST |
+    pkt.FL_UNDERRUN |
+    pkt.FL_OVERRUN |
+    pkt.FL_DROPPED 
+    ,0,0,0);
+  CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+
+}
+//////////////////////////////////////////////////////////////////////
+
+void
+qa_inband_packet_prims::test_fields()
+{
+  transport_pkt pkt;
+  void * payload;
+  
+  // test word0 field exclusiveness
+  //
+  // I want to test max values of each field to ensure field boundaries
+  // but these max values could change based on technology?  The
+  // max payload is returned by a private method so the code is not
+  // technology dependent
+  pkt.set_header(0,16,0,0);
+  CPPUNIT_ASSERT_EQUAL(16, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+
+  pkt.set_header(0,0,8,0);
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(8, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0,pkt.payload_len());
+
+  pkt.set_header(0,0,0,pkt.max_payload());  
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(pkt.max_payload(), pkt.payload_len());
+
+  // test timestamp, shouldn't have to test other fields since
+  // setting the timestamp only has the ability to affect one word
+  pkt.set_timestamp(54);
+  CPPUNIT_ASSERT_EQUAL(uint32_t(54), pkt.timestamp());
+
+  // test the payload, ensure no other fields overwritten
+  //
+  // is there a better test for this?
+  pkt.set_header(0,0,0,0);
+  payload = malloc(pkt.payload_len());
+  memset(payload, 'f', pkt.payload_len());
+  memcpy(pkt.payload(), payload, pkt.payload_len());
+  CPPUNIT_ASSERT_EQUAL(0, memcmp(pkt.payload(), payload, pkt.payload_len()));
+  CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
+  CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
+  free(payload);
+
+}
+//////////////////////////////////////////////////////////////////////
diff --git a/usrp/host/lib/inband/qa_inband_packet_prims.h b/usrp/host/lib/inband/qa_inband_packet_prims.h
new file mode 100644 (file)
index 0000000..5e60c60
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- 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 QA_INBAND_PACKET_PRIMS_H
+#define QA_INBAND_PACKET_PRIMS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_inband_packet_prims : public CppUnit::TestCase {
+
+  CPPUNIT_TEST_SUITE(qa_inband_packet_prims);
+  CPPUNIT_TEST(test_flags);
+  CPPUNIT_TEST(test_fields);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_flags();
+  void test_fields();
+
+};
+
+#endif /* INCLUDED_QA_INBAND_PACKET_PRIMS_H */
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.cc b/usrp/host/lib/inband/qa_inband_usrp_server.cc
new file mode 100644 (file)
index 0000000..2885a4d
--- /dev/null
@@ -0,0 +1,455 @@
+/* -*- 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_inband_usrp_server.h>
+#include <cppunit/TestAssert.h>
+#include <stdio.h>
+#include <usrp_server.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_protocol_class.h>
+#include <mb_class_registry.h>
+#include <vector>
+#include <iostream>
+
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
+static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
+static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
+static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
+static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
+static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
+static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_alloc_top : public mb_mblock
+{
+  mb_port_sptr d_tx;
+  mb_port_sptr d_rx;
+  mb_port_sptr d_cs;
+
+  long d_nmsgs_to_recv;
+  long d_nrecvd;
+
+  long d_max_capacity;
+  long d_ntx_chan, d_nrx_chan;
+
+  long d_nstatus;
+  long d_nstatus_to_recv;
+
+ public:
+  qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_alloc_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_message(mb_message_sptr msg);
+  void run_tests();
+};
+
+qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+  d_nrecvd=0;
+  d_nmsgs_to_recv = 7;
+  d_nstatus=0;
+  d_nstatus_to_recv = 3;
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Test the TX side
+  define_component("server", "usrp_server", PMT_F);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+
+}
+
+qa_alloc_top::~qa_alloc_top(){}
+
+void
+qa_alloc_top::initial_transition()
+{
+  // Retrieve information about the USRP, then run tests
+  d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+}
+
+void
+qa_alloc_top::run_tests()
+{
+  std::cout << "[qa_alloc_top] Starting tests...\n";
+  // should be able to allocate 1 byte
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+  
+  // should not be able to allocate max capacity after 100 bytes were allocated
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));  
+  
+  // keep allocating a little more until all of the channels are used and test the error response
+  // we start at 1 since we've already allocated 1 channel
+  for(int i=1; i < d_ntx_chan; i++) {
+    d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_nmsgs_to_recv++;
+  }
+  d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
+
+  // test out the same on the RX side
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));  
+
+  for(int i=1; i < d_nrx_chan; i++) {
+    d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_nmsgs_to_recv++;
+  }
+  d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
+
+  // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes allocated
+  d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
+}
+
+void
+qa_alloc_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+
+  if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
+       || pmt_eq(msg->port_id(), d_rx->port_symbol()))
+       && pmt_eq(msg->signal(), s_response_allocate_channel))
+    check_message(msg);
+  
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+      
+    if(pmt_eq(msg->signal(), s_response_max_capacity)) {
+      d_max_capacity = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
+      d_ntx_chan = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
+      d_nrx_chan = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
+      check_message(msg);
+    }
+    
+    d_nstatus++;
+
+    if(d_nstatus==d_nstatus_to_recv)
+      run_tests();
+  }
+}
+
+void
+qa_alloc_top::check_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+
+  pmt_t expected_result = pmt_nth(0, data);
+  pmt_t result = pmt_nth(1, data);
+  
+  d_nrecvd++;
+
+
+  if(!pmt_eqv(expected_result, result)) {
+    std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+    shutdown_all(PMT_F);
+  } else {
+    std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
+  }
+
+  if(d_nrecvd == d_nmsgs_to_recv)
+    shutdown_all(PMT_T);
+}
+
+REGISTER_MBLOCK_CLASS(qa_alloc_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_dealloc_top : public mb_mblock
+{
+  mb_port_sptr d_tx;
+  mb_port_sptr d_rx;
+  mb_port_sptr d_cs;
+  
+  long d_max_capacity;
+  long d_ntx_chan, d_nrx_chan;
+
+  long d_nstatus;
+  long d_nstatus_to_recv;
+
+  long d_nalloc_to_recv;
+  long d_nalloc_recvd;
+
+  long d_ndealloc_to_recv;
+  long d_ndealloc_recvd;
+
+  std::vector<long> d_tx_chans;
+  std::vector<long> d_rx_chans;
+
+ public:
+  qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~qa_dealloc_top();
+  void initial_transition();
+  void handle_message(mb_message_sptr msg);
+
+ protected:
+  void check_allocation(mb_message_sptr msg);
+  void check_deallocation(mb_message_sptr msg);
+  void allocate_max();
+  void deallocate_all();
+};
+
+qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
+{ 
+  d_ndealloc_recvd=0;
+  d_ndealloc_to_recv = 0;
+  d_nalloc_recvd=0;
+  d_nalloc_to_recv = 0;
+  d_nstatus=0;
+  d_nstatus_to_recv = 3;
+  
+  d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+  // Test the TX side
+  define_component("server", "usrp_server", PMT_F);
+  connect("self", "tx0", "server", "tx0");
+  connect("self", "rx0", "server", "rx0");
+  connect("self", "cs", "server", "cs");
+}
+
+qa_dealloc_top::~qa_dealloc_top(){}
+
+void
+qa_dealloc_top::initial_transition()
+{
+  // Retrieve information about the USRP, then run tests
+  d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
+  d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+}
+
+void
+qa_dealloc_top::allocate_max()
+{
+  std::cout << "[qa_dealloc_top] Max allocating...\n";
+
+  // Keep allocating until we hit the maximum number of channels
+  for(int i=0; i < d_ntx_chan; i++) {
+    d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_nalloc_to_recv++;
+  }
+  for(int i=0; i < d_nrx_chan; i++) {
+    d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+    d_nalloc_to_recv++;
+  }
+}
+
+void
+qa_dealloc_top::deallocate_all() {
+  
+  // Deallocate all of the channels that were allocated from allocate_max()
+  for(int i=0; i < (int)d_tx_chans.size(); i++) {
+    d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_tx_chans[i])));
+    d_ndealloc_to_recv++;
+  }
+  for(int i=0; i < (int)d_rx_chans.size(); i++) {
+    d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_rx_chans[i])));
+    d_ndealloc_to_recv++;
+  }
+
+  // Should get permission denied errors trying to re-dealloc the channels, as we no
+  // longer have permission to them after deallocating
+  for(int i=0; i < (int)d_tx_chans.size(); i++) {
+    d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_tx_chans[i])));
+    d_ndealloc_to_recv++;
+  }
+  for(int i=0; i < (int)d_rx_chans.size(); i++) {
+    d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_rx_chans[i])));
+    d_ndealloc_to_recv++;
+  }
+
+  // Try to deallocate a channel that doesn't exist on both sides, the last element in the vectors
+  // is the highest channel number, so we take that plus 1
+  d_ndealloc_to_recv+=2;
+  d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
+  d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
+
+
+  // The used capacity should be back to 0 now that we've deallocated everything
+  d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(0)));
+}
+
+void
+qa_dealloc_top::handle_message(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+  if (pmt_eq(msg->port_id(), d_tx->port_symbol())
+       || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
+    
+    if(pmt_eq(msg->signal(), s_response_allocate_channel)) {
+      check_allocation(msg);
+    }
+    
+    if(pmt_eq(msg->signal(), s_response_deallocate_channel)){
+      check_deallocation(msg);
+    }
+  }
+  
+  if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+      
+    if(pmt_eq(msg->signal(), s_response_max_capacity)) {
+      d_max_capacity = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_dealloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
+      d_ntx_chan = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_dealloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
+      d_nrx_chan = pmt_to_long(pmt_nth(1, data));
+      std::cout << "[qa_dealloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+    }
+    else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
+      // the final command is a capacity check which should be 0, then we shutdown
+      pmt_t expected_result = pmt_nth(0, data);
+      pmt_t result = pmt_nth(1, data);
+
+      if(pmt_eqv(expected_result, result))
+        shutdown_all(PMT_T);
+      else
+        shutdown_all(PMT_F);
+    }
+    
+    d_nstatus++;
+
+    if(d_nstatus==d_nstatus_to_recv)
+      allocate_max();
+  }
+}
+
+void
+qa_dealloc_top::check_deallocation(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+
+  pmt_t expected_result = pmt_nth(0, data);
+  pmt_t result = pmt_nth(1, data);
+
+  d_ndealloc_recvd++;
+
+  if(!pmt_eqv(expected_result, result)) {
+    std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+    shutdown_all(PMT_F);
+  } else {
+    std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
+  }
+}
+
+void
+qa_dealloc_top::check_allocation(mb_message_sptr msg)
+{
+  pmt_t data = msg->data();
+
+  pmt_t invocation_handle = pmt_nth(0, data);
+  pmt_t status = pmt_nth(1, data);
+  pmt_t channel = pmt_nth(2, data);
+  
+  d_nalloc_recvd++;
+
+  if(pmt_eqv(status, PMT_F)) {
+    std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
+    shutdown_all(PMT_F);
+  } else {
+    // store all of the allocate channel numbers
+    if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
+      d_tx_chans.push_back(pmt_to_long(channel));
+    if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
+      d_rx_chans.push_back(pmt_to_long(channel));
+  }
+
+  if(d_nalloc_recvd == d_nalloc_to_recv) {
+    
+    std::cout << "[qa_dealloc_top] Allocated TX channels: ";
+    for(int i=0; i < (int)d_tx_chans.size(); i++)
+      std::cout << d_tx_chans[i] << " ";
+
+    std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
+    for(int i=0; i < (int)d_rx_chans.size(); i++)
+      std::cout << d_rx_chans[i] << " ";
+    std::cout << "\n";
+
+    deallocate_all();   // once we've allocated all of our channels, try to dealloc them
+  }
+}
+
+REGISTER_MBLOCK_CLASS(qa_dealloc_top);
+
+// ----------------------------------------------------------------------------------------------
+
+void 
+qa_inband_usrp_server::test_chan_allocation()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  rt->run("top", "qa_alloc_top", PMT_F, &result);
+  
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_chan_deallocation()
+{
+  mb_runtime_sptr rt = mb_make_runtime();
+  pmt_t result = PMT_T;
+
+  rt->run("top", "qa_dealloc_top", PMT_F, &result);
+  
+  CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_fragmentation()
+{
+  
+}
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.h b/usrp/host/lib/inband/qa_inband_usrp_server.h
new file mode 100644 (file)
index 0000000..eb0f7a3
--- /dev/null
@@ -0,0 +1,42 @@
+/* -*- 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 QA_INBAND_USRP_SERVER_H
+#define QA_INBAND_USRP_SERVER_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_inband_usrp_server : public CppUnit::TestCase {
+
+  CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
+  CPPUNIT_TEST(test_chan_allocation);
+  CPPUNIT_TEST(test_chan_deallocation);
+  CPPUNIT_TEST(test_fragmentation);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_chan_allocation();
+  void test_chan_deallocation();
+  void test_fragmentation();
+};
+
+#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/test_inband.cc b/usrp/host/lib/inband/test_inband.cc
new file mode 100644 (file)
index 0000000..49619be
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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.
+ */
+
+#include <cppunit/TextTestRunner.h>
+#include <qa_inband.h>
+
+int 
+main(int argc, char **argv)
+{
+  
+  CppUnit::TextTestRunner      runner;
+
+  runner.addTest(qa_inband::suite ());
+  
+  bool was_successful = runner.run("", false);
+
+  return was_successful ? 0 : 1;
+}
diff --git a/usrp/host/lib/inband/usb_packet.py b/usrp/host/lib/inband/usb_packet.py
new file mode 100644 (file)
index 0000000..5ca19b7
--- /dev/null
@@ -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
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.h b/usrp/host/lib/inband/usrp_inband_usb_packet.h
new file mode 100644 (file)
index 0000000..471bfc6
--- /dev/null
@@ -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
diff --git a/usrp/host/lib/inband/usrp_server.cc b/usrp/host/lib/inband/usrp_server.cc
new file mode 100644 (file)
index 0000000..5041a92
--- /dev/null
@@ -0,0 +1,394 @@
+/* -*- 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 <usrp_server.h>
+#include <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <mb_class_registry.h>
+#include <vector>
+
+typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
+
+// FIXME We should machine generate these by a simple preprocessor run over this file
+//
+// These are all the messages that we expect to receive.
+//
+// We "intern" these here (make them into symbols) so that our
+// comparisions below are effectively pointer comparisons.
+
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
+static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
+static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
+static pmt_t s_cmd_xmit_raw_frame  = pmt_intern("cmd-xmit-raw-frame");
+static pmt_t s_cmd_max_capacity  = pmt_intern("cmd-max-capacity");
+static pmt_t s_cmd_ntx_chan  = pmt_intern("cmd-ntx-chan");
+static pmt_t s_cmd_nrx_chan  = pmt_intern("cmd-nrx-chan");
+static pmt_t s_cmd_current_capacity_allocation  = pmt_intern("cmd-current-capacity-allocation");
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
+static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
+static pmt_t s_response_current_capacity_allocation  = pmt_intern("response-current-capacity-allocation");
+
+static std::string
+str(long x)
+{
+  std::ostringstream s;
+  s << x;
+  return s.str();
+}
+
+usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg)
+{
+  // define our ports
+
+  // control & status port
+  d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL); 
+
+  // ports
+  //
+  // (if/when we do replicated ports, these will be replaced by a
+  //  single replicated port)
+  for(int port=0; port < N_PORTS; port++) {
+    d_tx.push_back(define_port("tx"+str(port), "usrp-tx", true, mb_port::EXTERNAL));
+    d_rx.push_back(define_port("rx"+str(port), "usrp-rx", true, mb_port::EXTERNAL));
+  }
+
+  // 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()
+{
+}
+
+
+void
+usrp_server::initial_transition()
+{
+  // the initial transition
+}
+
+void
+usrp_server::handle_message(mb_message_sptr msg)
+{
+  pmt_t event = msg->signal();         // the "name" of the message
+  pmt_t port_id = msg->port_id();      // which port it came in on
+  pmt_t data = msg->data();
+  pmt_t metadata = msg->metadata();
+  pmt_t invocation_handle;
+  pmt_t reply_data;
+  pmt_t status;
+
+  if (1){
+    std::cout << "[USRP_SERVER] event: " << event << std::endl;
+    std::cout << "[USRP_SERVER] port_id: " << port_id << std::endl;
+  }
+
+  // It would be nice if this were all table driven, and we could
+  // compute our state transition as f(current_state, port_id, signal)
+
+  if (pmt_eq(port_id, d_cs->port_symbol())){   // message came in on our control/status port
+
+    if (pmt_eq(event, s_cmd_open)){
+      // extract args from data
+      invocation_handle = pmt_nth(0, data);
+      long which_usrp = pmt_to_long(pmt_nth(1, data)); // integer usrp id, usually 0
+      
+      // Do the right thing....
+      // build a reply
+
+      // if everything OK
+      status = PMT_T;
+      reply_data = pmt_list2(invocation_handle, status);
+
+      //  ...and send it
+      d_cs->send(s_response_open, reply_data);
+      return;
+    }
+    else if (pmt_eq(event, s_cmd_close)){
+      // ...
+    }
+    else if (pmt_eq(event, s_cmd_max_capacity)) {
+      invocation_handle = pmt_nth(0, data);
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(max_capacity()));
+      d_cs->send(s_response_max_capacity, reply_data);
+      return;
+    }
+    else if (pmt_eq(event, s_cmd_ntx_chan)) {
+      invocation_handle = pmt_nth(0, data);
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(d_ntx_chan));
+      d_cs->send(s_response_ntx_chan, reply_data);
+    }
+    else if (pmt_eq(event, s_cmd_nrx_chan)) {
+      invocation_handle = pmt_nth(0, data);
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(d_nrx_chan));
+      d_cs->send(s_response_nrx_chan, reply_data);
+    }
+    else if (pmt_eq(event, s_cmd_current_capacity_allocation)) {
+      invocation_handle = pmt_nth(0, data);
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(current_capacity_allocation()));
+      d_cs->send(s_response_current_capacity_allocation, reply_data);
+    }
+    goto unhandled;
+  }
+
+  if (pmt_eq(event, s_cmd_allocate_channel)){
+    handle_cmd_allocate_channel(port_id, data);
+    return;
+  }
+
+  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 << "[USRP_SERVER] unhandled msg: " << msg << std::endl;
+}
+
+// Return -1 if it is not an RX port, or an index
+int usrp_server::tx_port_index(pmt_t port_id) {
+
+  for(int i=0; i < (int) d_tx.size(); i++) 
+    if(pmt_eq(d_tx[i]->port_symbol(), port_id))
+      return i;
+
+  return -1;
+}
+
+// Return -1 if it is not an RX port, or an index
+int usrp_server::rx_port_index(pmt_t port_id) {
+  
+  for(int i=0; i < (int) d_rx.size(); i++) 
+    if(pmt_eq(d_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_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL);  // no capacity available
+      d_tx[port]->send(s_response_allocate_channel, 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(s_response_allocate_channel, reply_data);
+        return;
+      }
+    }
+
+    std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
+
+    reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL);  // no free TX chan found
+    d_tx[port]->send(s_response_allocate_channel, reply_data);
+    return;
+  }
+  
+  // Repeat the same process on the RX side if the port was not determined to be TX
+  if((port = rx_port_index(port_id)) != -1) {
+    
+    if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
+      reply_data = pmt_list3(invocation_handle, pmt_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL);  // no capacity available
+      d_rx[port]->send(s_response_allocate_channel, reply_data);
+      return;
+    }
+
+    for(chan=0; chan < d_nrx_chan; chan++) {
+      if(d_chaninfo_rx[chan].owner == PMT_NIL) {
+        d_chaninfo_rx[chan].owner = port_id;
+        d_chaninfo_rx[chan].assigned_capacity = rqstd_capacity;
+        reply_data = pmt_list3(invocation_handle, PMT_T, pmt_from_long(chan));
+        d_rx[port]->send(s_response_allocate_channel, reply_data);
+        return;
+      }
+    }
+
+    std::cout << "[USRP_SERVER] Couldnt find a RX chan\n";
+    reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL);  // no free RX chan found
+    d_rx[port]->send(s_response_allocate_channel, reply_data);
+    return;
+  }
+}
+
+// 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_from_long(CHANNEL_INVALID));   // not a legit channel number
+      d_tx[port]->send(s_response_deallocate_channel, reply_data);
+      return;
+    }
+
+    if(d_chaninfo_tx[channel].owner != port_id) {
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED));   // not the owner of the port
+      d_tx[port]->send(s_response_deallocate_channel, reply_data);
+      return;
+    }
+
+    d_chaninfo_tx[channel].assigned_capacity = 0;
+    d_chaninfo_tx[channel].owner = PMT_NIL;
+
+    reply_data = pmt_list2(invocation_handle, PMT_T);
+    d_tx[port]->send(s_response_deallocate_channel, reply_data);
+    return;
+  }
+
+  // Repeated process on the RX side
+  if((port = rx_port_index(port_id)) != -1) {
+  
+    if(channel >= d_nrx_chan) {
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(CHANNEL_INVALID));   // not a legit channel number
+      d_rx[port]->send(s_response_deallocate_channel, reply_data);
+      return;
+    }
+
+    if(d_chaninfo_rx[channel].owner != port_id) {
+      reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED));   // not the owner of the port
+      d_rx[port]->send(s_response_deallocate_channel, reply_data);
+      return;
+    }
+
+    d_chaninfo_rx[channel].assigned_capacity = 0;
+    d_chaninfo_rx[channel].owner = PMT_NIL;
+
+    reply_data = pmt_list2(invocation_handle, PMT_T);
+    d_rx[port]->send(s_response_deallocate_channel, reply_data);
+    return;
+  }
+
+}
+
+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 = static_cast<long>(std::ceil(n_bytes / (double)max_payload_len));
+  pmt_t v_packets = pmt_make_u8vector(sizeof(transport_pkt) * n_packets, 0);
+
+  transport_pkt *pkts =
+    (transport_pkt *) pmt_u8vector_writeable_elements(v_packets, psize);
+
+  for(int n=0; n < n_packets; n++) {
+
+    long payload_len = std::min((long)(n_bytes-(n*max_payload_len)), (long)max_payload_len);
+  
+    if(n == 0) { // first packet gets start of burst flag and timestamp
+      pkts[n].set_header(pkts[n].FL_START_OF_BURST, channel, 0, payload_len);
+      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)
+}
+
+REGISTER_MBLOCK_CLASS(usrp_server);
diff --git a/usrp/host/lib/inband/usrp_server.h b/usrp/host/lib/inband/usrp_server.h
new file mode 100644 (file)
index 0000000..87c2768
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- 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_SERVER_H
+#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:
+
+  enum error_codes {
+    RQSTD_CAPACITY_UNAVAIL = 0,
+    CHANNEL_UNAVAIL = 1,
+    CHANNEL_INVALID = 2,
+    PERMISSION_DENIED = 3
+  };
+
+  // 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;
+
+  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);
+
+protected:
+  static int max_capacity() { return D_USB_CAPACITY; }
+
+private:
+  void handle_cmd_allocate_channel(pmt_t port_id, pmt_t data);
+  void handle_cmd_deallocate_channel(pmt_t port_id, pmt_t data);
+  void handle_cmd_xmit_raw_frame(pmt_t data);
+  int rx_port_index(pmt_t port_id);
+  int tx_port_index(pmt_t port_id);
+  long current_capacity_allocation();
+};
+
+#endif /* INCLUDED_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/usrp_server.mbh b/usrp/host/lib/inband/usrp_server.mbh
new file mode 100644 (file)
index 0000000..97bb0e6
--- /dev/null
@@ -0,0 +1,256 @@
+;; -*- scheme -*- ; not really, but tells emacs how to format this
+;;
+;; Copyright 2007 Free Software Foundation, Inc.
+;; 
+;; This file is part of GNU Radio
+;; 
+;; GNU Radio is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;; 
+;; GNU Radio is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;; 
+;; You should have received a copy of the GNU General Public License along
+;; with this program; if not, write to the Free Software Foundation, Inc.,
+;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;
+
+;; ----------------------------------------------------------------
+;;              This is an mblock header file
+;;
+;; The format is very much a work-in-progress.
+;; It'll be compiled to C++.
+;; ----------------------------------------------------------------
+
+;; In the outgoing messages described below, invocation-handle is an
+;; identifier provided by the client to tag the method invocation.
+;; The identifier will be returned with the response, to provide the
+;; client with a mechanism to match asynchronous responses with the
+;; commands that generate them.  The value of the invocation-handle is
+;; opaque the the server, and is not required by the server to be
+;; unique.
+;;
+;; In the incoming messages described below, invocation-handle is the
+;; identifier provided by the client in the prompting invocation.  The
+;; identifier is returned with the response, so that the client has a
+;; mechanism to match asynchronous responses with the commands that
+;; generated them.
+;;
+;; status is either #t, indicating success, or a pair containing
+;; (status-code . message), where status-code is a symbol and message
+;; is a string.
+
+
+;; ----------------------------------------------------------------
+;; usrp-channel
+;;
+;; The protocol class is defined from the client's point-of-view.
+;; (The client port is unconjugated, the server port is conjugated.)
+
+(define-protocol-class usrp-channel
+
+  (:outgoing
+
+   (cmd-allocate-channel invocation-handle capacity-reservation)
+
+   ;; The cmd-allocate-channel message requests that the server
+   ;; allocates a logical channel in the FPGA for use.
+   ;; capacity-reservation specifies the number of bytes/s of
+   ;; interconnect capacity (USB or ethernet) to reserve for this
+   ;; channel.  (The reservation is just a sanity check, no OS
+   ;; specific mechanism is used.)
+
+   (cmd-deallocate-channel invocation-handle channel)
+
+   ;; The integer channel specifies the channel to deallocate.
+
+   )
+
+  (:incoming
+
+
+   (response-allocate-channel invocation-handle status channel)
+
+   ;; If successful, a channel the specified capacity was allocated.
+   ;; channel, an integer, indicates which channel was allocated.
+
+   (response-deallocate-channel invocation-handle status)
+
+   ;; If successful, the specified channel and associated interconnect
+   ;; capacity were deallocated.
+
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; usrp-low-level-cs
+;;
+;; The protocol class is defined from the client's point-of-view.
+;; (The client port is unconjugated, the server port is conjugated.)
+;;
+;; This defines a low level control and status interface to the usrp.
+;; This will probably be replaced (or at least augmented) with a
+;; higher level interface.  For now, this will allow us to get on
+;; the air.
+;;
+;; The subpackets are lists containing the relevant parameters.  The
+;; server will marshall them appropriately.  Below is a list of
+;; subpackets.  See inband-signaling-usb for details.  The opcodes are
+;; symbols; unless otherwise indicated the remaining parameters are
+;; integers.  rid values are limited to 3-bits.
+;;
+;;   (op-ping-fixed rid ping-value)
+;;   (op-ping-fixed-reply rid ping-value)
+;;   (op-write-reg reg-number reg-value)
+;;   (op-write-reg-masked reg-number reg-value mask-value)
+;;   (op-read-reg rid reg-number reg-value)
+;;   (op-read-reg-reply rid reg-number reg-value)
+;;   (op-i2c-write i2c-addr u8-vec)
+;;   (op-i2c-read rid i2c-addr nbytes)
+;;   (op-i2c-read-reply rid i2c-addr u8-vec)
+;;   (op-spi-write enables format opt-header-bytes u8-vec)
+;;   (op-spi-read rid enables format opt-header-bytes nbytes)
+;;   (op-spi-read-reply rid u8-vec)
+;;   (op-delay ticks)
+
+
+(define-protocol-class usrp-low-level-cs
+
+  (:outgoing
+
+   (cmd-to-control-channel invocation-handle list-of-subpackets)
+
+   )
+
+  (:incoming
+
+   (response-from-control-channel invocation-handle status list-of-subpackets)
+
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; usrp-tx
+;;
+;; The protocol class is defined from the client's point-of-view.
+;; (The client port is unconjugated, the server port is conjugated.)
+
+(define-protocol-class usrp-tx
+  (:include usrp-channel)
+  (:include usrp-low-level-cs)
+
+  (:outgoing
+
+   (cmd-xmit-raw-frame invocation-handle channel samples timestamp)
+
+   ;; The argument channel must be an integer.  It specifies the
+   ;; channel on which the frame of samples will be be sent.
+   ;;
+   ;; samples must be a uniform numeric vector.  The contents of the
+   ;; sample vector is treated as opaque and is passed on to the FPGA
+   ;; unmodified.  It is the responsibility of the sender to ensure
+   ;; that the binary format is sensible for the current FPGA
+   ;; configuration.
+   ;;
+   ;; timestamp is a 32-bit integer that specifies the time at which
+   ;; the first sample in samples shall be sent to the D/A converter.
+   ;; The format and interpration of time is specified in the file
+   ;; inband-signaling-usb
+   )
+
+  (:incoming
+
+   (response-xmit-raw-frame invocation-handle status)
+
+   ;; If successful, the samples of the associated frame have been
+   ;; transmitted to the USRP.  This message may be used to implement
+   ;; Tx flow control.  The client could for example implement a
+   ;; policy of never having more than 4 unacknowledged
+   ;; cmd-xmit-raw-frame's outstanding.
+
+   )
+  )
+
+;; ----------------------------------------------------------------
+;; usrp-rx
+;;
+;; The protocol class is defined from the client's point-of-view.
+;; (The client port is unconjugated, the server port is conjugated.)
+
+(define-protocol-class usrp-rx
+  (:include usrp-channel)
+  (:include usrp-low-level-cs)
+
+  (:outgoing
+
+   (cmd-start-recv-raw-samples invocation-handle channel)
+
+   ;; The argument channel must be an integer.  It specifies the
+   ;; channel from which frames of samples will be be received.  The
+   ;; server will return response-recv-raw-samples messages until a
+   ;; cmd-stop-recv-raw-samples message is received.
+
+   (cmd-stop-recv-raw-samples invocation-handle channel)
+
+   ;; The argument channel must be an integer.  There is no reply to
+   ;; this message.
+   
+   )
+
+  (:incoming
+
+   (response-recv-raw-samples invocation-handle status samples timestamp properties)
+
+   ;; samples is a uniform numeric vector.  The contents of the sample
+   ;; vector is treated as opaque and is passed from the FPGA
+   ;; unmodified.  It is the responsibility of the receiver to decode
+   ;; the binary format as appropriate for the current FPGA
+   ;; configuration.
+   ;;
+   ;; timestamp is a 32-bit integer that specifies the time at which
+   ;; the first sample in samples was received from the A/D converter.
+   ;; The format and interpretation of time is as specified in the
+   ;; file inband-signaling-usb.
+   ;;
+   ;; properties is a dictionary containing additional (key, value)
+   ;; pairs associated with the reception of these samples.  In
+   ;; particular, the map may contain the Received Signal Strength
+   ;; Indication (RSSI) reported by the front end at the time the
+   ;; first sample was received from the A/D.
+
+   )
+  )
+
+
+;; ----------------------------------------------------------------
+;; usrp-server-cs
+;;
+;; Control and status port for usrp-server
+;;
+;; The protocol class is defined from the client's point-of-view.
+;; (The client port is unconjugated, the server port is conjugated.)
+
+(define-protocol-class usrp-server-cs
+
+  (:outgoing
+   (cmd-open invocation-handle which-usrp)
+   (cmd-close invocation-handle)
+   (cmd-max-capacity invocation-handle)
+   (cmd-ntx-chan invocation-handle)
+   (cmd-nrx-chan invocation-handle)
+   (cmd-current-capacity-allocation invocation-handle)
+   )
+
+  (:incoming
+   (response-open invocation-handle status)
+   (response-close invocation-handle status)
+   (response-max-capacity invocation-handle capacity)
+   (response-ntx-chan invocation-handle ntx-chan)
+   (response-nrx-chan invocation-handle nrx-chan)
+   (response-current-capacity-allocation invocation-handle capacity)
+   )
+  )
diff --git a/usrp/host/lib/legacy/Makefile.am b/usrp/host/lib/legacy/Makefile.am
new file mode 100644 (file)
index 0000000..7303fb4
--- /dev/null
@@ -0,0 +1,153 @@
+#
+#  USRP - Universal Software Radio Peripheral
+# 
+#  Copyright (C) 2003,2004,2006,2007 Free Software Foundation, Inc.
+# 
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+# 
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+# 
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
+# 
+
+include $(top_srcdir)/Makefile.common
+
+INCLUDES = $(USRP_INCLUDES)
+
+lib_LTLIBRARIES = libusrp.la
+
+libusrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
+
+libusrp_la_LIBADD =                    \
+       $(USB_LIBS)                     \
+       ../../misc/libmisc.la           
+
+EXTRA_DIST =                           \
+       std_paths.h.in                  \
+       usrp_dbid.dat                   
+
+
+BUILT_SOURCES =                        \
+       usrp_dbid.h                     \
+       usrp_dbid.cc                    \
+       usrp_dbid.py                    
+
+
+# ----------------------------------------------------------------
+# FUSB_TECH is set at configure time by way of
+#   usrp/config/usrp_fusb_tech.m4.
+#   It indicates which fast usb strategy we should be building.
+#   We currently implement "generic", "darwin", "win32" and "linux"
+
+
+generic_CODE =                                 \
+       fusb_generic.cc                 \
+       fusb_sysconfig_generic.cc
+
+darwin_CODE =                          \
+       fusb_darwin.cc                  \
+       fusb_sysconfig_darwin.cc        \
+       README_OSX                      \
+       circular_buffer.h               \
+       circular_linked_list.h          \
+       darwin_libusb.h                 \
+       mld_threads.h                   
+
+win32_CODE =                           \
+       fusb_win32.cc                   \
+       fusb_sysconfig_win32.cc         
+
+linux_CODE =                           \
+       fusb_linux.cc                   \
+       fusb_sysconfig_linux.cc         
+
+ra_wb_CODE =                           \
+       fusb_ra_wb.cc                   \
+       fusb_sysconfig_ra_wb.cc
+
+
+#
+# include each <foo>_CODE entry here...
+#
+EXTRA_libusrp_la_SOURCES =             \
+       $(generic_CODE)                 \
+       $(darwin_CODE)                  \
+       $(win32_CODE)                   \
+       $(linux_CODE)                   \
+       $(ra_wb_CODE)
+
+
+# work around automake deficiency
+libusrp_la_common_SOURCES =            \
+       fusb.cc                         \
+       md5.c                           \
+       usrp_basic.cc                   \
+       usrp_config.cc                  \
+       usrp_dbid.cc                    \
+       usrp_local_sighandler.cc        \
+       usrp_prims.cc                   \
+       usrp_standard.cc
+
+
+if FUSB_TECH_generic
+libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE)
+endif
+
+if FUSB_TECH_darwin
+libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(darwin_CODE)
+endif
+
+if FUSB_TECH_win32
+libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(win32_CODE)
+endif
+
+if FUSB_TECH_linux
+libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(linux_CODE)
+endif
+
+if FUSB_TECH_ra_wb
+libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(ra_wb_CODE)
+endif
+
+include_HEADERS =                      \
+       usrp_basic.h                    \
+       usrp_bytesex.h                  \
+       usrp_config.h                   \
+       usrp_dbid.h                     \
+       usrp_prims.h                    \
+       usrp_slots.h                    \
+       usrp_standard.h                 
+
+noinst_HEADERS =                       \
+       ad9862.h                        \
+       fusb.h                          \
+       fusb_darwin.h                   \
+       fusb_win32.h                    \
+       fusb_generic.h                  \
+       fusb_linux.h                    \
+       fusb_ra_wb.h                    \
+       md5.h                           \
+       rate_to_regval.h                \
+       usrp_local_sighandler.h         
+
+usrppython_PYTHON =                    \
+       usrp_dbid.py                    
+
+noinst_PYTHON =                                \
+       gen_usrp_dbid.py                \
+       check_data.py                   \
+       dump_data.py
+
+usrp_dbid.py usrp_dbid.h usrp_dbid.cc: gen_usrp_dbid.py usrp_dbid.dat
+       PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat
+
+MOSTLYCLEANFILES = \
+       $(BUILT_SOURCES) *~ *.pyc
diff --git a/usrp/host/lib/legacy/README_OSX b/usrp/host/lib/legacy/README_OSX
new file mode 100644 (file)
index 0000000..20230f1
--- /dev/null
@@ -0,0 +1,63 @@
+USRP Darwin Fast USB Changes
+Version 0.2 of 2006-04-27
+Michael Dickens <mdickens @at@ nd .dot. edu>
+
+The files included in this archive are:
+
+circular_buffer.h
+circular_linked_list.h
+darwin_libusb.h
+fusb_darwin.cc
+fusb_darwin.h
+mld_threads.h
+
+These files allow GNURadio code for Darwin / MaxOS X to talk to the
+USRP via USB 2.0 at rates up to around 30 Mega-Bytes/sec (MBps), up
+from 4-8 MBps without the changes.
+
+I implemented the buffering myself; there are probably GR buffers
+available which would do the work but as this is "beta" software it's
+a good place to start.  Speed improvements are made by porting
+LIBUSB's non-true async bulk read and write functions into USRP's
+"fusb", and upgrading them to handle -true- async transfers.
+Unfortunately, the easiest way to do this is to spawn a thread or 2 to
+handle the "async" part of the transfers.  This implementation uses
+Darwin's pthreads to do the work for mutexes, conditions, and threads.
+Previous implementations (0.1 and before) used "omni_threads" as
+provided by gnuradio-core, which caused issues with compiling and
+execution ... I'm glad that this is no longer the case.
+
+As far as I have tested, there is no way to improve the throughput to
+32+ MBps without moving into Darwin's "port"s ... a kernel-level data
+transport method with a user/application layer for USB-specific
+functions.  Unfortunately, Apple's documentation for these "port"s is
+minimal; I have learned more from reading the Darwin source code
+< http://darwinsource.opendarwin.org/ > than by reading Apple's
+documents!  This would also require -not- using LIBUSB, of which the
+removal from the rest of the USRP code would be potentially tedious.
+
+If you run into issues either compiling or testing the USRP on
+OSX, please send me a note.
+
+(1) Go through the bootstrap, configure, compile, and install as
+usual (e.g. see < http://www.nd.edu/~mdickens/GNURadio/ > for my
+usual).
+
+(2) from .../usrp/host/apps :  run the scripts
+++++++++++++++++
+./test_usrp_standard_tx
+./test_usrp_standard_rx
+++++++++++++++++
+
+For -all- systems I've tested on thus far, both of these return
+exactly 41 overruns / underruns, and -most- systems start out with a
+stalled pipe.  This stall comes in a usb_control funciton call to
+LIBUSB; one would have to change the LIBUSB code to handle this issue.
+
+(3) from gr-build/gnuradio-examples/python/usrp :
+++++++++++++++++
+./benchmark_usb.py
+++++++++++++++++
+
+(4) If you get to here, the try doing the FM receiver (gui or not).
+If that sounds correct, then the USB is working.  Yay!
\ No newline at end of file
diff --git a/usrp/host/lib/legacy/ad9862.h b/usrp/host/lib/legacy/ad9862.h
new file mode 100644 (file)
index 0000000..d1895bb
--- /dev/null
@@ -0,0 +1,221 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_AD9862_H
+#define INCLUDED_AD9862_H
+
+/*
+ * Analog Devices AD9862 registers and some fields
+ */
+
+#define BEGIN_AD9862   namespace ad9862 {
+#define        END_AD962       }
+#define        DEF static const int
+
+BEGIN_AD9862;
+
+DEF REG_GENERAL                =  0;
+DEF REG_RX_PWR_DN      =  1;
+DEF    RX_PWR_DN_VREF_DIFF             = (1 << 7);
+DEF    RX_PWR_DN_VREF                  = (1 << 6);
+DEF    RX_PWR_DN_RX_DIGIGAL            = (1 << 5);
+DEF    RX_PWR_DN_RX_B                  = (1 << 4);
+DEF    RX_PWR_DN_RX_A                  = (1 << 3);
+DEF    RX_PWR_DN_BUF_B                 = (1 << 2);
+DEF    RX_PWR_DN_BUF_A                 = (1 << 1);
+DEF    RX_PWR_DN_ALL                   = (1 << 0);
+
+DEF REG_RX_A           =  2;   // bypass input buffer / RxPGA
+DEF REG_RX_B           =  3;   // pypass input buffer / RxPGA
+DEF    RX_X_BYPASS_INPUT_BUFFER        = (1 << 7);
+
+DEF REG_RX_MISC                =  4;
+DEF    RX_MISC_HS_DUTY_CYCLE           = (1 << 2);
+DEF    RX_MISC_SHARED_REF              = (1 << 1);
+DEF    RX_MISC_CLK_DUTY                = (1 << 0);
+
+DEF REG_RX_IF          =  5;
+DEF    RX_IF_THREE_STATE               = (1 << 4);
+DEF    RX_IF_USE_CLKOUT1               = (0 << 3);     
+DEF    RX_IF_USE_CLKOUT2               = (1 << 3);     // aka Rx Retime
+DEF    RX_IF_2S_COMP                   = (1 << 2);
+DEF    RX_IF_INV_RX_SYNC               = (1 << 1);
+DEF    RX_IF_MUX_OUT                   = (1 << 0);
+
+DEF REG_RX_DIGITAL     =  6;
+DEF    RX_DIGITAL_2_CHAN               = (1 << 3);
+DEF    RX_DIGITAL_KEEP_MINUS_VE        = (1 << 2);
+DEF    RX_DIGITAL_HILBERT              = (1 << 1);
+DEF    RX_DIGITAL_DECIMATE             = (1 << 0);
+
+DEF REG_RESERVED_7     =  7;
+
+DEF REG_TX_PWR_DN      =  8;
+DEF    TX_PWR_DN_ALT_TIMING_MODE       = (1 << 5);
+DEF    TX_PWR_DN_TX_OFF_ENABLE         = (1 << 4);
+DEF    TX_PWR_DN_TX_DIGITAL            = (1 << 3);
+DEF    TX_PWR_DN_TX_ANALOG_B           = 0x4;
+DEF    TX_PWR_DN_TX_ANALOG_A           = 0x2;
+DEF    TX_PWR_DN_TX_ANALOG_BOTH        = 0x7;
+
+DEF REG_RESERVED_9     =  9;
+
+DEF REG_TX_A_OFFSET_LO = 10;
+DEF REG_TX_A_OFFSET_HI = 11;
+DEF REG_TX_B_OFFSET_LO = 12;
+DEF REG_TX_B_OFFSET_HI = 13;
+
+DEF REG_TX_A_GAIN      = 14;   // fine trim for matching
+DEF REG_TX_B_GAIN      = 15;   // fine trim for matching
+DEF    TX_X_GAIN_COARSE_FULL           = (3 << 6);
+DEF    TX_X_GAIN_COARSE_1_HALF         = (1 << 6);
+DEF    TX_X_GAIN_COARSE_1_ELEVENTH     = (0 << 6);
+
+DEF REG_TX_PGA         = 16;   // 20 dB continuous gain in 0.1 dB steps
+                               // 0x00 = min gain (-20 dB)
+                               // 0xff = max gain (  0 dB)
+
+DEF REG_TX_MISC                = 17;
+DEF    TX_MISC_SLAVE_ENABLE            = (1 << 1);
+DEF    TX_MISC_TX_PGA_FAST             = (1 << 0);
+
+DEF REG_TX_IF          = 18;
+DEF    TX_IF_USE_CLKOUT2               = (0 << 6);
+DEF    TX_IF_USE_CLKOUT1               = (1 << 6);     // aka Tx Retime
+DEF    TX_IF_I_FIRST                   = (0 << 5);
+DEF    TX_IF_Q_FIRST                   = (1 << 5);
+DEF    TX_IF_INV_TX_SYNC               = (1 << 4);
+DEF    TX_IF_2S_COMP                   = (1 << 3);
+DEF    TX_IF_INVERSE_SAMPLE            = (1 << 2);
+DEF    TX_IF_TWO_EDGES                 = (1 << 1);
+DEF    TX_IF_INTERLEAVED               = (1 << 0);
+
+DEF REG_TX_DIGITAL     = 19;
+DEF    TX_DIGITAL_2_DATA_PATHS         = (1 << 4);
+DEF    TX_DIGITAL_KEEP_NEGATIVE        = (1 << 3);
+DEF    TX_DIGITAL_HILBERT              = (1 << 2);
+DEF    TX_DIGITAL_INTERPOLATE_NONE     = 0x0;
+DEF    TX_DIGITAL_INTERPOLATE_2X       = 0x1;
+DEF    TX_DIGITAL_INTERPOLATE_4X       = 0x2;
+
+DEF REG_TX_MODULATOR   = 20;
+DEF    TX_MODULATOR_NEG_FINE_TUNE      = (1 << 5);
+DEF    TX_MODULATOR_DISABLE_NCO        = (0 << 4);
+DEF    TX_MODULATOR_ENABLE_NCO         = (1 << 4);     // aka Fine Mode
+DEF    TX_MODULATOR_REAL_MIX_MODE      = (1 << 3);
+DEF    TX_MODULATOR_NEG_COARSE_TUNE    = (1 << 2);
+DEF    TX_MODULATOR_COARSE_MODULATION_NONE     = 0x0;
+DEF    TX_MODULATOR_COARSE_MODULATION_F_OVER_4 = 0x1;
+DEF    TX_MODULATOR_COARSE_MODULATION_F_OVER_8 = 0x2;
+DEF    TX_MODULATOR_CM_MASK                    = 0x7;
+
+
+DEF REG_TX_NCO_FTW_7_0 = 21;
+DEF REG_TX_NCO_FTW_15_8        = 22;
+DEF REG_TX_NCO_FTW_23_16= 23;
+
+DEF REG_DLL            = 24;
+DEF    DLL_DISABLE_INTERNAL_XTAL_OSC   = (1 << 6);     // aka Input Clock Ctrl
+DEF    DLL_ADC_DIV2                    = (1 << 5);
+DEF    DLL_MULT_1X                     = (0 << 3);
+DEF    DLL_MULT_2X                     = (1 << 3);
+DEF    DLL_MULT_4X                     = (2 << 3);
+DEF    DLL_PWR_DN                      = (1 << 2);
+// undefined bit                       = (1 << 1);
+DEF    DLL_FAST                        = (1 << 0);
+
+DEF REG_CLKOUT         = 25;
+DEF    CLKOUT2_EQ_DLL                  = (0 << 6);
+DEF    CLKOUT2_EQ_DLL_OVER_2           = (1 << 6);
+DEF    CLKOUT2_EQ_DLL_OVER_4           = (2 << 6);
+DEF    CLKOUT2_EQ_DLL_OVER_8           = (3 << 6);
+DEF    CLKOUT_INVERT_CLKOUT2           = (1 << 5);
+DEF    CLKOUT_DISABLE_CLKOUT2          = (1 << 4);
+// undefined bit                       = (1 << 3);
+// undefined bit                       = (1 << 2);
+DEF    CLKOUT_INVERT_CLKOUT1           = (1 << 1);
+DEF    CLKOUT_DISABLE_CLKOUT1          = (1 << 0);
+
+DEF REG_AUX_ADC_A2_LO  = 26;
+DEF REG_AUX_ADC_A2_HI  = 27;
+DEF REG_AUX_ADC_A1_LO  = 28;
+DEF REG_AUX_ADC_A1_HI  = 29;
+DEF REG_AUX_ADC_B2_LO  = 30;
+DEF REG_AUX_ADC_B2_HI  = 31;
+DEF REG_AUX_ADC_B1_LO  = 32;
+DEF REG_AUX_ADC_B1_HI  = 33;
+
+DEF REG_AUX_ADC_CTRL   = 34;
+DEF    AUX_ADC_CTRL_AUX_SPI            = (1 << 7);
+DEF    AUX_ADC_CTRL_SELBNOTA           = (1 << 6);
+DEF    AUX_ADC_CTRL_REFSEL_B           = (1 << 5);
+DEF    AUX_ADC_CTRL_SELECT_B2          = (0 << 4);
+DEF    AUX_ADC_CTRL_SELECT_B1          = (1 << 4);
+DEF    AUX_ADC_CTRL_START_B            = (1 << 3);
+DEF    AUX_ADC_CTRL_REFSEL_A           = (1 << 2);
+DEF    AUX_ADC_CTRL_SELECT_A2          = (0 << 1);
+DEF    AUX_ADC_CTRL_SELECT_A1          = (1 << 1);
+DEF    AUX_ADC_CTRL_START_A            = (1 << 0);
+
+DEF REG_AUX_ADC_CLK    = 35;
+DEF    AUX_ADC_CLK_CLK_OVER_4          = (1 << 0);
+
+DEF REG_AUX_DAC_A      = 36;
+DEF REG_AUX_DAC_B      = 37;
+DEF REG_AUX_DAC_C      = 38;
+
+DEF REG_AUX_DAC_UPDATE = 39;
+DEF    AUX_DAC_UPDATE_SLAVE_ENABLE     = (1 << 7);
+DEF    AUX_DAC_UPDATE_C                = (1 << 2);
+DEF    AUX_DAC_UPDATE_B                = (1 << 1);
+DEF    AUX_DAC_UPDATE_A                = (1 << 0);
+
+DEF REG_AUX_DAC_PWR_DN = 40;
+DEF    AUX_DAC_PWR_DN_C                = (1 << 2);
+DEF    AUX_DAC_PWR_DN_B                = (1 << 1);
+DEF    AUX_DAC_PWR_DN_A                = (1 << 0);
+
+DEF REG_AUX_DAC_CTRL   = 41;
+DEF    AUX_DAC_CTRL_INV_C              = (1 << 4);
+DEF    AUX_DAC_CTRL_INV_B              = (1 << 2);
+DEF    AUX_DAC_CTRL_INV_A              = (1 << 0);
+
+DEF REG_SIGDELT_LO     = 42;
+DEF REG_SIGDELT_HI     = 43;
+
+// 44 to 48 reserved
+
+DEF REG_ADC_LOW_PWR_LO = 49;
+DEF REG_ADC_LOW_PWR_HI = 50;
+
+// 51 to 62 reserved
+
+DEF REG_CHIP_ID                = 63;
+
+
+END_AD962;
+
+#undef DEF
+#undef BEGIN_AD9862
+#undef END_AD962
+
+#endif /* INCLUDED_AD9862_H */
diff --git a/usrp/host/lib/legacy/check_data.py b/usrp/host/lib/legacy/check_data.py
new file mode 100755 (executable)
index 0000000..655ca15
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+#
+# Copyright 2003 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., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+import sys
+import struct
+
+fin = sys.stdin
+
+count = 0
+expected = 0
+last_correction = 0
+
+while 1:
+    s = fin.read(2)
+    if not s or len(s) != 2:
+        break
+
+    v, = struct.unpack ('H', s)
+    iv = int(v) & 0xffff
+    # print "%8d  %6d  0x%04x" % (count, iv, iv)
+    if count & 0x1:                     # only counting on the Q channel
+        if (expected & 0xffff) != iv:
+            print "%8d  (%6d) %6d  0x%04x" % (count, count - last_correction, iv, iv)
+            expected = iv               # reset expected sequence
+            last_correction = count
+        expected = (expected + 1) & 0xffff 
+        
+    count += 1
+
+    
+
+
diff --git a/usrp/host/lib/legacy/circular_buffer.h b/usrp/host/lib/legacy/circular_buffer.h
new file mode 100644 (file)
index 0000000..913360d
--- /dev/null
@@ -0,0 +1,325 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _CIRCULAR_BUFFER_H_
+#define _CIRCULAR_BUFFER_H_
+
+#include "mld_threads.h"
+#include <stdexcept>
+
+#define DO_DEBUG 0
+
+template <class T> class circular_buffer
+{
+private:
+// the buffer to use
+  T* d_buffer;
+
+// the following are in Items (type T)
+  UInt32 d_bufLen_I, d_readNdx_I, d_writeNdx_I;
+  UInt32 d_n_avail_write_I, d_n_avail_read_I;
+
+// stuff to control access to class internals
+  mld_mutex_ptr d_internal;
+  mld_condition_ptr d_readBlock, d_writeBlock;
+
+// booleans to decide how to control reading, writing, and aborting
+  bool d_doWriteBlock, d_doFullRead, d_doAbort;
+
+  void delete_mutex_cond () {
+    if (d_internal) {
+      delete d_internal;
+      d_internal = NULL;
+    }
+    if (d_readBlock) {
+      delete d_readBlock;
+      d_readBlock = NULL;
+    }
+    if (d_writeBlock) {
+      delete d_writeBlock;
+      d_writeBlock = NULL;
+    }
+  };
+
+public:
+  circular_buffer (UInt32 bufLen_I,
+                  bool doWriteBlock = true, bool doFullRead = false) {
+    if (bufLen_I == 0)
+      throw std::runtime_error ("circular_buffer(): "
+                               "Number of items to buffer must be > 0.\n");
+    d_bufLen_I = bufLen_I;
+    d_buffer = (T*) new T[d_bufLen_I];
+    d_doWriteBlock = doWriteBlock;
+    d_doFullRead = doFullRead;
+    d_internal = NULL;
+    d_readBlock = d_writeBlock = NULL;
+    reset ();
+#if DO_DEBUG
+    fprintf (stderr, "c_b(): buf len (items) = %ld, "
+            "doWriteBlock = %s, doFullRead = %s\n", d_bufLen_I,
+            (d_doWriteBlock ? "true" : "false"),
+            (d_doFullRead ? "true" : "false"));
+#endif
+  };
+
+  ~circular_buffer () {
+    delete_mutex_cond ();
+    delete [] d_buffer;
+  };
+
+  inline UInt32 n_avail_write_items () {
+    d_internal->lock ();
+    UInt32 retVal = d_n_avail_write_I;
+    d_internal->unlock ();
+    return (retVal);
+  };
+
+  inline UInt32 n_avail_read_items () {
+    d_internal->lock ();
+    UInt32 retVal = d_n_avail_read_I;
+    d_internal->unlock ();
+    return (retVal);
+  };
+
+  inline UInt32 buffer_length_items () {return (d_bufLen_I);};
+  inline bool do_write_block () {return (d_doWriteBlock);};
+  inline bool do_full_read () {return (d_doFullRead);};
+
+  void reset () {
+    d_doAbort = false;
+    bzero (d_buffer, d_bufLen_I * sizeof (T));
+    d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0;
+    d_n_avail_write_I = d_bufLen_I;
+    delete_mutex_cond ();
+    d_internal = new mld_mutex ();
+    d_readBlock = new mld_condition ();
+    d_writeBlock = new mld_condition ();
+  };
+
+/*
+ * enqueue: add the given buffer of item-length to the queue,
+ *     first-in-first-out (FIFO).
+ *
+ * inputs:
+ *     buf: a pointer to the buffer holding the data
+ *
+ *     bufLen_I: the buffer length in items (of the instantiated type)
+ *
+ * returns:
+ *    -1: on overflow (write is not blocking, and data is being
+ *                     written faster than it is being read)
+ *     0: if nothing to do (0 length buffer)
+ *     1: if success
+ *     2: in the process of aborting, do doing nothing
+ *
+ * will throw runtime errors if inputs are improper:
+ *     buffer pointer is NULL
+ *     buffer length is larger than the instantiated buffer length
+ */
+
+  int enqueue (T* buf, UInt32 bufLen_I) {
+#if DO_DEBUG
+    fprintf (stderr, "enqueue: buf = %X, bufLen = %ld.\n",
+            (unsigned int)buf, bufLen_I);
+#endif
+    if (bufLen_I > d_bufLen_I) {
+      fprintf (stderr, "cannot add buffer longer (%ld"
+              ") than instantiated length (%ld"
+              ").\n", bufLen_I, d_bufLen_I);
+      throw std::runtime_error ("circular_buffer::enqueue()");
+    }
+
+    if (bufLen_I == 0)
+      return (0);
+    if (!buf)
+      throw std::runtime_error ("circular_buffer::enqueue(): "
+                               "input buffer is NULL.\n");
+    d_internal->lock ();
+    if (d_doAbort) {
+      d_internal->unlock ();
+      return (2);
+    }
+    if (bufLen_I > d_n_avail_write_I) {
+      if (d_doWriteBlock) {
+       while (bufLen_I > d_n_avail_write_I) {
+#if DO_DEBUG
+         fprintf (stderr, "enqueue: #len > #a, waiting.\n");
+#endif
+         d_internal->unlock ();
+         d_writeBlock->wait ();
+         d_internal->lock ();
+         if (d_doAbort) {
+           d_internal->unlock ();
+#if DO_DEBUG
+           fprintf (stderr, "enqueue: #len > #a, aborting.\n");
+#endif
+           return (2);
+         }
+#if DO_DEBUG
+         fprintf (stderr, "enqueue: #len > #a, done waiting.\n");
+#endif
+       }
+      } else {
+       d_n_avail_read_I = d_bufLen_I - bufLen_I;
+       d_n_avail_write_I = bufLen_I;
+#if DO_DEBUG
+       fprintf (stderr, "circular_buffer::enqueue: overflow\n");
+#endif
+       return (-1);
+      }
+    }
+    UInt32 n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0;
+    if (n_now_I > bufLen_I)
+      n_now_I = bufLen_I;
+    else if (n_now_I < bufLen_I)
+      n_start_I = bufLen_I - n_now_I;
+    bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I * sizeof (T));
+    if (n_start_I) {
+      bcopy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T));
+      d_writeNdx_I = n_start_I;
+    } else
+      d_writeNdx_I += n_now_I;
+    d_n_avail_read_I += bufLen_I;
+    d_n_avail_write_I -= bufLen_I;
+    d_readBlock->signal ();
+    d_internal->unlock ();
+    return (1);
+  };
+
+/*
+ * dequeue: removes from the queue the number of items requested, or
+ *     available, into the given buffer on a FIFO basis.
+ *
+ * inputs:
+ *     buf: a pointer to the buffer into which to copy the data
+ *
+ *     bufLen_I: pointer to the number of items to remove in items
+ *         (of the instantiated type)
+ *
+ * returns:
+ *     0: if nothing to do (0 length buffer)
+ *     1: if success
+ *     2: in the process of aborting, do doing nothing
+ *
+ * will throw runtime errors if inputs are improper:
+ *     buffer pointer is NULL
+ *     buffer length pointer is NULL
+ *     buffer length is larger than the instantiated buffer length
+ */
+
+
+  int dequeue (T* buf, UInt32* bufLen_I) {
+#if DO_DEBUG
+    fprintf (stderr, "dequeue: buf = %X, *bufLen = %ld.\n",
+            (unsigned int)buf, *bufLen_I);
+#endif
+    if (!bufLen_I)
+      throw std::runtime_error ("circular_buffer::dequeue(): "
+                               "input bufLen pointer is NULL.\n");
+    if (!buf)
+      throw std::runtime_error ("circular_buffer::dequeue(): "
+                               "input buffer pointer is NULL.\n");
+    UInt32 l_bufLen_I = *bufLen_I;
+    if (l_bufLen_I == 0)
+      return (0);
+    if (l_bufLen_I > d_bufLen_I) {
+      fprintf (stderr, "cannot remove buffer longer (%ld"
+              ") than instantiated length (%ld"
+              ").\n", l_bufLen_I, d_bufLen_I);
+      throw std::runtime_error ("circular_buffer::dequeue()");
+    }
+
+    d_internal->lock ();
+    if (d_doAbort) {
+      d_internal->unlock ();
+      return (2);
+    }
+    if (d_doFullRead) {
+      while (d_n_avail_read_I < l_bufLen_I) {
+#if DO_DEBUG
+       fprintf (stderr, "dequeue: #a < #len, waiting.\n");
+#endif
+       d_internal->unlock ();
+       d_readBlock->wait ();
+       d_internal->lock ();
+       if (d_doAbort) {
+         d_internal->unlock ();
+#if DO_DEBUG
+         fprintf (stderr, "dequeue: #a < #len, aborting.\n");
+#endif
+         return (2);
+       }
+#if DO_DEBUG
+       fprintf (stderr, "dequeue: #a < #len, done waiting.\n");
+#endif
+     }
+    } else {
+      while (d_n_avail_read_I == 0) {
+#if DO_DEBUG
+       fprintf (stderr, "dequeue: #a == 0, waiting.\n");
+#endif
+       d_internal->unlock ();
+       d_readBlock->wait ();
+       d_internal->lock ();
+       if (d_doAbort) {
+         d_internal->unlock ();
+#if DO_DEBUG
+         fprintf (stderr, "dequeue: #a == 0, aborting.\n");
+#endif
+         return (2);
+       }
+#if DO_DEBUG
+       fprintf (stderr, "dequeue: #a == 0, done waiting.\n");
+#endif
+      }
+    }
+    if (l_bufLen_I > d_n_avail_read_I)
+      l_bufLen_I = d_n_avail_read_I;
+    UInt32 n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0;
+    if (n_now_I > l_bufLen_I)
+      n_now_I = l_bufLen_I;
+    else if (n_now_I < l_bufLen_I)
+      n_start_I = l_bufLen_I - n_now_I;
+    bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I * sizeof (T));
+    if (n_start_I) {
+      bcopy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T));
+      d_readNdx_I = n_start_I;
+    } else
+      d_readNdx_I += n_now_I;
+    *bufLen_I = l_bufLen_I;
+    d_n_avail_read_I -= l_bufLen_I;
+    d_n_avail_write_I += l_bufLen_I;
+    d_writeBlock->signal ();
+    d_internal->unlock ();
+    return (1);
+  };
+
+  void abort () {
+    d_internal->lock ();
+    d_doAbort = true;
+    d_writeBlock->signal ();
+    d_readBlock->signal ();
+    d_internal->unlock ();
+  };
+};
+
+#endif /* _CIRCULAR_BUFFER_H_ */
diff --git a/usrp/host/lib/legacy/circular_linked_list.h b/usrp/host/lib/legacy/circular_linked_list.h
new file mode 100644 (file)
index 0000000..0e460a2
--- /dev/null
@@ -0,0 +1,267 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _CIRCULAR_LINKED_LIST_H_
+#define _CIRCULAR_LINKED_LIST_H_
+
+#include <mld_threads.h>
+#include <stdexcept>
+
+#define __INLINE__ inline
+
+template <class T> class s_both;
+
+template <class T> class s_node
+{
+  typedef s_node<T>* s_node_ptr;
+
+private:
+  T d_object;
+  bool d_available;
+  s_node_ptr d_prev, d_next;
+  s_both<T>* d_both;
+
+public:
+  s_node (T l_object,
+         s_node_ptr l_prev = NULL,
+         s_node_ptr l_next = NULL)
+    : d_object (l_object), d_available (TRUE), d_prev (l_prev),
+    d_next (l_next), d_both (0) {};
+
+  __INLINE__ s_node (s_node_ptr l_prev, s_node_ptr l_next = NULL) {
+    s_node ((T) NULL, l_prev, l_next); };
+  __INLINE__ s_node () { s_node (NULL, NULL, NULL); };
+  __INLINE__ ~s_node () {};
+
+  void remove () {
+    d_prev->next (d_next);
+    d_next->prev (d_prev);
+    d_prev = d_next = this;
+  };
+
+  void insert_before (s_node_ptr l_next) {
+    if (l_next) {
+      s_node_ptr l_prev = l_next->prev ();
+      d_next = l_next;
+      d_prev = l_prev;
+      l_prev->next (this);
+      l_next->prev (this);
+    } else
+      d_next = d_prev = this;
+  };
+
+  void insert_after (s_node_ptr l_prev) {
+    if (l_prev) {
+      s_node_ptr l_next = l_prev->next ();
+      d_prev = l_prev;
+      d_next = l_next;
+      l_next->prev (this);
+      l_prev->next (this);
+    } else
+      d_prev = d_next = this;
+  };
+
+  __INLINE__ T object () { return (d_object); };
+  __INLINE__ void object (T l_object) { d_object = l_object; };
+  __INLINE__ bool available () { return (d_available); };
+  __INLINE__ void set_available () { d_available = TRUE; };
+  __INLINE__ void set_available (bool l_avail) { d_available = l_avail; };
+  __INLINE__ void set_not_available () { d_available = FALSE; };
+  __INLINE__ s_node_ptr next () { return (d_next); };
+  __INLINE__ s_node_ptr prev () { return (d_prev); };
+  __INLINE__ s_both<T>* both () { return (d_both); };
+  __INLINE__ void next (s_node_ptr l_next) { d_next = l_next; };
+  __INLINE__ void prev (s_node_ptr l_prev) { d_prev = l_prev; };
+  __INLINE__ void both (s_both<T>* l_both) { d_both = l_both; };
+};
+
+template <class T> class circular_linked_list {
+  typedef s_node<T>* s_node_ptr;
+
+private:
+  s_node_ptr d_current, d_iterate, d_available, d_inUse;
+  UInt32 d_n_nodes, d_n_used;
+  mld_mutex_ptr d_internal;
+  mld_condition_ptr d_ioBlock;
+
+public:
+  circular_linked_list (UInt32 n_nodes) {
+    if (n_nodes == 0)
+      throw std::runtime_error ("circular_linked_list(): n_nodes == 0");
+
+    d_iterate = NULL;
+    d_n_nodes = n_nodes;
+    d_n_used = 0;
+    s_node_ptr l_prev, l_next;
+    d_inUse = d_current = l_next = l_prev = NULL;
+
+    l_prev = new s_node<T> ();
+    l_prev->set_available ();
+    l_prev->next (l_prev);
+    l_prev->prev (l_prev);
+    if (n_nodes > 1) {
+      l_next = new s_node<T> (l_prev, l_prev);
+      l_next->set_available ();
+      l_next->next (l_prev);
+      l_next->prev (l_prev);
+      l_prev->next (l_next);
+      l_prev->prev (l_next);
+      if (n_nodes > 2) {
+       UInt32 n = n_nodes - 2;
+       while (n-- > 0) {
+         d_current = new s_node<T> (l_prev, l_next);
+         d_current->set_available ();
+         d_current->prev (l_prev);
+         d_current->next (l_next);
+         l_prev->next (d_current);
+         l_next->prev (d_current);
+         l_next = d_current;
+         d_current = NULL;
+       }
+      }
+    }
+    d_available = d_current = l_prev;
+    d_internal = new mld_mutex ();
+    d_ioBlock = new mld_condition ();
+  };
+
+  ~circular_linked_list () {
+    iterate_start ();
+    s_node_ptr l_node = iterate_next ();
+    while (l_node) {
+      delete l_node;
+      l_node = iterate_next ();
+    }
+    delete d_internal;
+    d_internal = NULL;
+    delete d_ioBlock;
+    d_ioBlock = NULL;
+    d_available = d_inUse = d_iterate = d_current = NULL;
+    d_n_used = d_n_nodes = 0;
+  };
+
+  s_node_ptr find_next_available_node () {
+    d_internal->lock ();
+// find an available node
+    s_node_ptr l_node = d_available; 
+    while (! l_node) {
+      d_internal->unlock ();
+      d_ioBlock->wait ();
+      d_internal->lock ();
+      l_node = d_available;
+    }
+//  fprintf (stderr, "::f_n_a_n: #u = %ld, node = %p\n", num_used(), l_node);
+// remove this one from the current available list
+    if (num_available () == 1) {
+// last one, just set available to NULL
+      d_available = NULL;
+    } else
+      d_available = l_node->next ();
+    l_node->remove ();
+// add is to the inUse list
+    if (! d_inUse)
+      d_inUse = l_node;
+    else
+      l_node->insert_before (d_inUse);
+    d_n_used++;
+    l_node->set_not_available ();
+    d_internal->unlock ();
+    return (l_node);
+  };
+
+  void make_node_available (s_node_ptr l_node) {
+    if (!l_node) return;
+    d_internal->lock ();
+//  fprintf (stderr, "::m_n_a: #u = %ld, node = %p\n", num_used(), l_node);
+// remove this node from the inUse list
+    if (num_used () == 1) {
+// last one, just set inUse to NULL
+      d_inUse = NULL;
+    } else
+      d_inUse = l_node->next ();
+    l_node->remove ();
+// add this node to the available list
+    if (! d_available)
+      d_available = l_node;
+    else
+      l_node->insert_before (d_available);
+    d_n_used--;
+// signal the condition when new data arrives
+    d_ioBlock->signal ();
+// unlock the mutex for thread safety
+    d_internal->unlock ();
+  };
+
+  __INLINE__ void iterate_start () { d_iterate = d_current; };
+
+  s_node_ptr iterate_next () {
+#if 0
+// lock the mutex for thread safety
+    d_internal->lock ();
+#endif
+    s_node_ptr l_this = NULL;
+    if (d_iterate) {
+      l_this = d_iterate;
+      d_iterate = d_iterate->next ();
+      if (d_iterate == d_current)
+       d_iterate = NULL;
+    }
+#if 0
+// unlock the mutex for thread safety
+    d_internal->unlock ();
+#endif
+    return (l_this);
+  };
+
+  __INLINE__ T object () { return (d_current->d_object); };
+  __INLINE__ void object (T l_object) { d_current->d_object = l_object; };
+  __INLINE__ UInt32 num_nodes () { return (d_n_nodes); };
+  __INLINE__ UInt32 num_used () { return (d_n_used); };
+  __INLINE__ void num_used (UInt32 l_n_used) { d_n_used = l_n_used; };
+  __INLINE__ UInt32 num_available () { return (d_n_nodes - d_n_used); };
+  __INLINE__ void num_used_inc (void) {
+    if (d_n_used < d_n_nodes) ++d_n_used;
+  };
+  __INLINE__ void num_used_dec (void) {
+    if (d_n_used != 0) --d_n_used;
+// signal the condition that new data has arrived
+    d_ioBlock->signal ();
+  };
+  __INLINE__ bool in_use () { return (d_n_used != 0); };
+};
+
+template <class T> class s_both
+{
+private:
+  s_node<T>* d_node;
+  void* d_this;
+public:
+  __INLINE__ s_both (s_node<T>* l_node, void* l_this)
+    : d_node (l_node), d_this (l_this) {};
+  __INLINE__ ~s_both () {};
+  __INLINE__ s_node<T>* node () { return (d_node); };
+  __INLINE__ void* This () { return (d_this); };
+  __INLINE__ void set (s_node<T>* l_node, void* l_this) {
+    d_node = l_node; d_this = l_this;};
+};
+
+#endif /* _CIRCULAR_LINKED_LIST_H_ */
diff --git a/usrp/host/lib/legacy/darwin_libusb.h b/usrp/host/lib/legacy/darwin_libusb.h
new file mode 100644 (file)
index 0000000..bdbdd34
--- /dev/null
@@ -0,0 +1,190 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * The following code was taken from LIBUSB verion 0.1.10a,
+ * and makes the fusb_darwin codes do-able in the current GR
+ * programming framework.  Parts and pieces were taken from
+ * usbi.h, darwin.c, and error.h .
+ *
+ * LIBUSB version 0.1.10a is covered by the LGPL, version 2;
+ * These codes are used with permission from:
+ *   (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
+ *   (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
+ * All rights reserved.
+ */
+
+#ifndef __DARWIN_LIBUSB_H__
+#define __DARWIN_LIBUSB_H__
+
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOKitLib.h>
+
+extern "C" {
+static char *
+darwin_error_str (int result)
+{
+  switch (result) {
+  case kIOReturnSuccess:
+    return "no error";
+  case kIOReturnNotOpen:
+    return "device not opened for exclusive access";
+  case kIOReturnNoDevice:
+    return "no connection to an IOService";
+  case kIOUSBNoAsyncPortErr:
+    return "no asyc port has been opened for interface";
+  case kIOReturnExclusiveAccess:
+    return "another process has device opened for exclusive access";
+  case kIOUSBPipeStalled:
+    return "pipe is stalled";
+  case kIOReturnError:
+    return "could not establish a connection to Darin kernel";
+  case kIOReturnBadArgument:
+    return "invalid argument";
+  default:
+    return "unknown error";
+  }
+}
+
+/* not a valid errorno outside darwin.c */
+#define LUSBDARWINSTALL (ELAST+1)
+
+static int
+darwin_to_errno (int result)
+{
+  switch (result) {
+  case kIOReturnSuccess:
+    return 0;
+  case kIOReturnNotOpen:
+    return EBADF;
+  case kIOReturnNoDevice:
+  case kIOUSBNoAsyncPortErr:
+    return ENXIO;
+  case kIOReturnExclusiveAccess:
+    return EBUSY;
+  case kIOUSBPipeStalled:
+    return LUSBDARWINSTALL;
+  case kIOReturnBadArgument:
+    return EINVAL;
+  case kIOReturnError:
+  default:
+    return 1;
+  }
+}
+
+typedef enum {
+  USB_ERROR_TYPE_NONE = 0,
+  USB_ERROR_TYPE_STRING,
+  USB_ERROR_TYPE_ERRNO,
+} usb_error_type_t;
+
+extern char usb_error_str[1024];
+extern int usb_error_errno;
+extern usb_error_type_t usb_error_type;
+
+#define USB_ERROR(r, x)                                \
+       do { \
+          usb_error_type = USB_ERROR_TYPE_ERRNO; \
+          usb_error_errno = x; \
+         return r; \
+       } while (0)
+
+#define USB_ERROR_STR(r, x, format, args...)   \
+       do { \
+         usb_error_type = USB_ERROR_TYPE_STRING; \
+         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
+          if (usb_debug) \
+            fprintf(stderr, "USB error: %s\n", usb_error_str); \
+         return r; \
+       } while (0)
+
+#define USB_ERROR_STR_ORIG(x, format, args...) \
+       do { \
+         usb_error_type = USB_ERROR_TYPE_STRING; \
+         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
+          if (usb_debug) \
+            fprintf(stderr, "USB error: %s\n", usb_error_str); \
+         return x; \
+       } while (0)
+
+#define USB_ERROR_STR_NO_RET(x, format, args...)       \
+       do { \
+         usb_error_type = USB_ERROR_TYPE_STRING; \
+         snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
+          if (usb_debug) \
+            fprintf(stderr, "USB error: %s\n", usb_error_str); \
+       } while (0)
+
+/* simple function that figures out what pipeRef is associated with an endpoint */
+static int ep_to_pipeRef (darwin_dev_handle *device, int ep)
+{
+  io_return_t ret;
+  UInt8 numep, direction, number;
+  UInt8 dont_care1, dont_care3;
+  UInt16 dont_care2;
+  int i;
+
+  if (usb_debug > 3)
+    fprintf(stderr, "Converting ep address to pipeRef.\n");
+
+  /* retrieve the total number of endpoints on this interface */
+  ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
+  if ( ret ) {
+    if ( usb_debug > 3 )
+      fprintf ( stderr, "ep_to_pipeRef: interface is %p\n", device->interface );
+    USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of endpoints for interface" );
+  }
+
+  /* iterate through the pipeRefs until we find the correct one */
+  for (i = 1 ; i <= numep ; i++) {
+    ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
+                                                   &dont_care1, &dont_care2, &dont_care3);
+
+    if (ret != kIOReturnSuccess) {
+      fprintf (stderr, "ep_to_pipeRef: an error occurred getting pipe information on pipe %d\n",
+              i );
+      USB_ERROR_STR_ORIG (-darwin_to_errno(ret), "ep_to_pipeRef(GetPipeProperties): %s", darwin_error_str(ret));
+    }
+
+    if (usb_debug > 3)
+      fprintf (stderr, "ep_to_pipeRef: Pipe %i: DIR: %i number: %i\n", i, direction, number);
+
+    /* calculate the endpoint of the pipe and check it versus the requested endpoint */
+    if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) | (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) {
+      if (usb_debug > 3)
+       fprintf(stderr, "ep_to_pipeRef: pipeRef for ep address 0x%02x found: 0x%02x\n", ep, i);
+
+      return i;
+    }
+  }
+
+  if (usb_debug > 3)
+    fprintf(stderr, "ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
+  
+  /* none of the found pipes match the requested endpoint */
+  return -1;
+}
+
+}
+#endif /* __DARWIN_LIBUSB_H__ */
diff --git a/usrp/host/lib/legacy/dump_data.py b/usrp/host/lib/legacy/dump_data.py
new file mode 100755 (executable)
index 0000000..34dde3d
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+#
+# Copyright 2003 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., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+import sys
+import struct
+
+fin = sys.stdin
+
+count = 0
+
+while 1:
+    s = fin.read(2)
+    if not s or len(s) != 2:
+        break
+
+    v, = struct.unpack ('H', s)
+    iv = int(v) & 0xffff
+    print "%8d  %6d  0x%04x" % (count, iv, iv)
+    count += 1
+    
+
+
diff --git a/usrp/host/lib/legacy/fusb.cc b/usrp/host/lib/legacy/fusb.cc
new file mode 100644 (file)
index 0000000..01ced9e
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fusb.h>
+
+
+// ------------------------------------------------------------------------
+//                          device handle
+// ------------------------------------------------------------------------
+
+fusb_devhandle::fusb_devhandle (usb_dev_handle *udh)
+  : d_udh (udh)
+{
+  // that's it
+};
+
+fusb_devhandle::~fusb_devhandle ()
+{
+  // nop
+}
+
+// ------------------------------------------------------------------------
+//                          end point handle
+// ------------------------------------------------------------------------
+
+fusb_ephandle::fusb_ephandle (int endpoint, bool input_p,
+                             int block_size, int nblocks)
+  : d_endpoint (endpoint), d_input_p (input_p),
+    d_block_size (block_size), d_nblocks (nblocks), d_started (false)
+{
+  // that't it
+}
+
+fusb_ephandle::~fusb_ephandle ()
+{
+  // nop
+}
diff --git a/usrp/host/lib/legacy/fusb.h b/usrp/host/lib/legacy/fusb.h
new file mode 100644 (file)
index 0000000..da1b7c0
--- /dev/null
@@ -0,0 +1,133 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Fast USB interface
+
+#ifndef _FUSB_H_
+#define _FUSB_H_
+
+
+struct  usb_dev_handle;
+class   fusb_ephandle;
+
+/*!
+ * \brief abstract usb device handle
+ */
+class fusb_devhandle {
+private:
+  // NOT IMPLEMENTED
+  fusb_devhandle (const fusb_devhandle &rhs);            // no copy constructor
+  fusb_devhandle &operator= (const fusb_devhandle &rhs);  // no assignment operator
+
+protected:
+  usb_dev_handle               *d_udh;
+
+public:
+  // CREATORS
+  fusb_devhandle (usb_dev_handle *udh);
+  virtual ~fusb_devhandle ();
+
+  // MANIPULATORS
+  
+  /*!
+   * \brief return an ephandle of the correct subtype
+   */
+  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0) = 0;
+  
+  // ACCESSORS
+  usb_dev_handle *get_usb_dev_handle () const { return d_udh; }
+};
+
+
+/*!
+ * \brief abstract usb end point handle
+ */
+class fusb_ephandle {
+private:
+  // NOT IMPLEMENTED
+  fusb_ephandle (const fusb_ephandle &rhs);            // no copy constructor
+  fusb_ephandle &operator= (const fusb_ephandle &rhs);  // no assignment operator
+
+protected:
+  int                          d_endpoint;
+  bool                         d_input_p;
+  int                          d_block_size;
+  int                          d_nblocks;
+  bool                         d_started;
+
+public:
+  fusb_ephandle (int endpoint, bool input_p,
+                int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle ();
+
+  virtual bool start () = 0;   //!< begin streaming i/o
+  virtual bool stop () = 0;    //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void *buffer, int nbytes) = 0;
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void *buffer, int nbytes) = 0;
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion () = 0;
+
+  /*!
+   * \brief returns current block size.
+   */
+  int block_size () { return d_block_size; };
+};
+
+
+/*!
+ * \brief factory for creating concrete instances of the appropriate subtype.
+ */
+class fusb_sysconfig {
+public:
+  /*!
+   * \brief returns fusb_devhandle or throws if trouble
+   */
+  static fusb_devhandle *make_devhandle (usb_dev_handle *udh);
+
+  /*!
+   * \brief returns max block size hard limit
+   */
+  static int max_block_size ();
+
+  /*!
+   * \brief returns the default buffer size
+   */
+  static int default_buffer_size ();
+
+};
+
+#endif /* _FUSB_H_ */
diff --git a/usrp/host/lib/legacy/fusb_darwin.cc b/usrp/host/lib/legacy/fusb_darwin.cc
new file mode 100644 (file)
index 0000000..8be5453
--- /dev/null
@@ -0,0 +1,499 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+// tell mld_threads to NOT use omni_threads,
+// but rather Darwin's pthreads
+#undef _USE_OMNI_THREADS_
+
+#include <usb.h>
+#include "fusb.h"
+#include "fusb_darwin.h"
+#include "darwin_libusb.h"
+
+static const int USB_TIMEOUT = 100;    // in milliseconds
+static const UInt8 NUM_QUEUE_ITEMS = 20;
+
+fusb_devhandle_darwin::fusb_devhandle_darwin (usb_dev_handle* udh)
+  : fusb_devhandle (udh)
+{
+  // that's it
+}
+
+fusb_devhandle_darwin::~fusb_devhandle_darwin ()
+{
+  // nop
+}
+
+fusb_ephandle*
+fusb_devhandle_darwin::make_ephandle (int endpoint, bool input_p,
+                                     int block_size, int nblocks)
+{
+  return new fusb_ephandle_darwin (this, endpoint, input_p,
+                                  block_size, nblocks);
+}
+
+// ----------------------------------------------------------------
+
+fusb_ephandle_darwin::fusb_ephandle_darwin (fusb_devhandle_darwin* dh,
+                                           int endpoint, bool input_p,
+                                           int block_size, int nblocks)
+  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
+    d_devhandle (dh), d_pipeRef (0), d_transferType (0),
+    d_interfaceRef (0),  d_interface (0), d_queue (0),
+    d_buffer (0), d_bufLenBytes (0)
+{
+  d_bufLenBytes = fusb_sysconfig::max_block_size();
+
+// create circular buffer
+  d_buffer = new circular_buffer<char> (NUM_QUEUE_ITEMS * d_bufLenBytes,
+                                       !d_input_p, d_input_p);
+
+// create the queue
+  d_queue = new circular_linked_list <s_buffer_ptr> (NUM_QUEUE_ITEMS);
+  d_queue->iterate_start ();
+  s_node_ptr l_node = d_queue->iterate_next ();
+  while (l_node) {
+    l_node->both (new s_both<s_buffer_ptr> (l_node, this));
+    s_buffer_ptr l_buf = new s_buffer (d_bufLenBytes);
+    l_node->object (l_buf);
+    l_node = d_queue->iterate_next ();
+    l_buf = NULL;
+  }
+
+  d_readRunning = new mld_mutex ();
+  d_runThreadRunning = new mld_mutex ();
+  d_runBlock = new mld_condition ();
+  d_readBlock = new mld_condition ();
+}
+
+fusb_ephandle_darwin::~fusb_ephandle_darwin ()
+{
+  stop ();
+
+  d_queue->iterate_start ();
+  s_node_ptr l_node = d_queue->iterate_next ();
+  while (l_node) {
+    s_both_ptr l_both = l_node->both ();
+    delete l_both;
+    l_both = NULL;
+    l_node->both (NULL);
+    s_buffer_ptr l_buf = l_node->object ();
+    delete l_buf;
+    l_buf = NULL;
+    l_node->object (NULL);
+    l_node = d_queue->iterate_next ();
+  }
+  delete d_queue;
+  d_queue = NULL;
+  delete d_buffer;
+  d_buffer = NULL;
+  delete d_readRunning;
+  d_readRunning = NULL;
+  delete d_runThreadRunning;
+  d_runThreadRunning = NULL;
+  delete d_runBlock;
+  d_runBlock = NULL;
+  delete d_readBlock;
+  d_readBlock = NULL;
+}
+
+bool
+fusb_ephandle_darwin::start ()
+{
+  UInt8  direction, number, interval;
+  UInt16 maxPacketSize;
+
+// reset circular buffer
+  d_buffer->reset ();
+
+// reset the queue
+  d_queue->num_used (0);
+  d_queue->iterate_start ();
+  s_node_ptr l_node = d_queue->iterate_next ();
+  while (l_node) {
+    l_node->both()->set (l_node, this);
+    l_node->object()->reset ();
+    l_node->set_available ();
+    l_node = d_queue->iterate_next ();
+  }
+
+  d_pipeRef = d_transferType = 0;
+
+  usb_dev_handle* dev = d_devhandle->get_usb_dev_handle ();
+  if (! dev)
+    USB_ERROR_STR (false, -ENXIO, "fusb_ephandle_darwin::start: "
+                  "null device");
+
+  darwin_dev_handle* device = (darwin_dev_handle*) dev->impl_info;
+  if (! device)
+    USB_ERROR_STR (false, -ENOENT, "fusb_ephandle_darwin::start: "
+                  "device not initialized");
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::start: "
+            "dev = %p, device = %p\n", dev, device);
+
+  d_interfaceRef = device->interface;
+  if (! d_interfaceRef)
+    USB_ERROR_STR (false, -EACCES, "fusb_ephandle_darwin::start: "
+                  "interface used without being claimed");
+  d_interface = *d_interfaceRef;
+
+// get read or write pipe info (depends on "d_input_p")
+
+  if (usb_debug > 3)
+    fprintf (stderr, "fusb_ephandle_darwin::start "
+            "d_endpoint = %d, d_input_p = %s\n",
+            d_endpoint, d_input_p ? "TRUE" : "FALSE");
+
+  int l_endpoint = (d_input_p ? USB_ENDPOINT_IN : USB_ENDPOINT_OUT);
+  int pipeRef = ep_to_pipeRef (device, d_endpoint | l_endpoint);
+  if (pipeRef < 0)
+    USB_ERROR_STR (false, -EINVAL, "fusb_ephandle_darwin::start "
+                  " invalid pipeRef.\n");
+
+  d_pipeRef = pipeRef;
+  d_interface->GetPipeProperties (d_interfaceRef,
+                                 d_pipeRef,
+                                 &direction,
+                                 &number,
+                                 &d_transferType,
+                                 &maxPacketSize,
+                                 &interval);
+  if (usb_debug == 3)
+    fprintf (stderr, "fusb_ephandle_darwin::start: %s: ep = 0x%02x, "
+            "pipeRef = %d, d_i = %p, d_iR = %p, if_dir = %d, if_# = %d, "
+            "if_int = %d, if_maxPS = %d\n", d_input_p ? "read" : "write",
+            d_endpoint, d_pipeRef, d_interface, d_interfaceRef, direction,
+            number, interval, maxPacketSize);
+
+// set global start boolean
+  d_started = true;
+
+// create the run thread, which allows OSX to process I/O separately
+  d_runThread = new mld_thread (run_thread, this);
+
+// wait until the threads are -really- going
+  d_runBlock->wait ();
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::start: %s started.\n",
+            d_input_p ? "read" : "write");
+
+  return (true);
+}
+
+void
+fusb_ephandle_darwin::run_thread (void* arg)
+{
+  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(arg);
+  mld_mutex_ptr l_runThreadRunning = This->d_runThreadRunning;
+  l_runThreadRunning->lock ();
+
+  mld_mutex_ptr l_readRunning = This->d_readRunning;
+  mld_condition_ptr l_readBlock = This->d_readBlock;
+
+  bool l_input_p = This->d_input_p;
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::run_thread: "
+            "starting for %s.\n",
+            l_input_p ? "read" : "write");
+
+  usb_interface_t** l_interfaceRef = This->d_interfaceRef;
+  usb_interface_t* l_interface = This->d_interface;
+  CFRunLoopSourceRef l_cfSource;
+
+// create async run loop
+  l_interface->CreateInterfaceAsyncEventSource (l_interfaceRef, &l_cfSource);
+  CFRunLoopAddSource (CFRunLoopGetCurrent (), l_cfSource,
+                     kCFRunLoopDefaultMode);
+// get run loop reference, to allow other threads to stop
+  This->d_CFRunLoopRef = CFRunLoopGetCurrent ();
+
+  mld_thread_ptr l_rwThread = NULL;
+
+  if (l_input_p) {
+    l_rwThread = new mld_thread (read_thread, arg);
+// wait until the the rwThread is -really- going
+    l_readBlock->wait ();
+  }
+
+// now signal the run condition to release and finish ::start()
+  This->d_runBlock->signal ();
+
+// run the loop
+  CFRunLoopRun ();
+
+  if (l_input_p) {
+// wait for read_thread () to finish
+    l_readRunning->lock ();
+    l_readRunning->unlock ();
+  }
+
+// remove run loop stuff
+  CFRunLoopRemoveSource (CFRunLoopGetCurrent (),
+                        l_cfSource, kCFRunLoopDefaultMode);
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::run_thread: finished for %s.\n",
+            l_input_p ? "read" : "write");
+
+  l_runThreadRunning->unlock ();
+}
+
+void
+fusb_ephandle_darwin::read_thread (void* arg)
+{
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::read_thread: starting.\n");
+
+  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(arg);
+
+  mld_mutex_ptr l_readRunning = This->d_readRunning;
+  l_readRunning->lock ();
+
+// signal the read condition from run_thread() to continue
+  mld_condition_ptr l_readBlock = This->d_readBlock;
+  l_readBlock->signal ();
+
+  s_queue_ptr l_queue = This->d_queue;
+  l_queue->iterate_start ();
+  s_node_ptr l_node = l_queue->iterate_next ();
+  while (l_node) {
+    This->read_issue (l_node->both ());
+    l_node = l_queue->iterate_next ();
+  }
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::read_thread: finished.\n");
+
+  l_readRunning->unlock ();
+}
+
+void
+fusb_ephandle_darwin::read_issue (s_both_ptr l_both)
+{
+  if ((! l_both) || (! d_started))
+    return;
+
+// set the node and buffer from the input "both"
+  s_node_ptr l_node = l_both->node ();
+  s_buffer_ptr l_buf = l_node->object ();
+  void* v_buffer = (void*) l_buf->buffer ();
+
+// read up to d_bufLenBytes
+  UInt32 bufLen = d_bufLenBytes;
+  l_buf->n_used (bufLen);
+
+// setup system call result
+  io_return_t result = kIOReturnSuccess;
+
+  if (d_transferType == kUSBInterrupt)
+/* This is an interrupt pipe. We can't specify a timeout. */
+    result = d_interface->ReadPipeAsync
+      (d_interfaceRef, d_pipeRef, v_buffer, bufLen,
+       (IOAsyncCallback1) read_completed, (void*) l_both);
+  else
+    result = d_interface->ReadPipeAsyncTO
+      (d_interfaceRef, d_pipeRef, v_buffer, bufLen, 0, USB_TIMEOUT,
+       (IOAsyncCallback1) read_completed, (void*) l_both);
+
+  if (result != kIOReturnSuccess)
+    USB_ERROR_STR_NO_RET (- darwin_to_errno (result),
+                         "fusb_ephandle_darwin::read_issue "
+                         "(ReadPipeAsync%s): %s",
+                         d_transferType == kUSBInterrupt ? "" : "TO",
+                         darwin_error_str (result));
+}
+
+void
+fusb_ephandle_darwin::read_completed (void* refCon,
+                                     io_return_t result,
+                                     void* io_size)
+{
+  UInt32 l_size = (UInt32) io_size;
+  s_both_ptr l_both = static_cast<s_both_ptr>(refCon);
+  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(l_both->This ());
+  s_node_ptr l_node = l_both->node ();
+  circular_buffer<char>* l_buffer = This->d_buffer;
+  s_buffer_ptr l_buf = l_node->object ();
+  UInt32 l_i_size = l_buf->n_used ();
+
+  if (This->d_started && (l_i_size != l_size))
+    fprintf (stderr, "fusb_ephandle_darwin::read_completed: "
+            "Expected %ld bytes; read %ld.\n",
+            l_i_size, l_size);
+
+// add this read to the transfer buffer
+  if (l_buffer->enqueue (l_buf->buffer (), l_size) == -1) {
+    fputs ("iU", stderr);
+    fflush (stderr);
+  }
+
+// set buffer's # data to 0
+  l_buf->n_used (0);
+
+// issue another read for this "both"
+  This->read_issue (l_both);
+}
+
+int
+fusb_ephandle_darwin::read (void* buffer, int nbytes)
+{
+  UInt32 l_nbytes = (UInt32) nbytes;
+  d_buffer->dequeue ((char*) buffer, &l_nbytes);
+  return ((int) l_nbytes);
+}
+
+int
+fusb_ephandle_darwin::write (const void* buffer, int nbytes)
+{
+  UInt32 l_nbytes = (UInt32) nbytes;
+
+  if (! d_started) return (0);
+
+  while (l_nbytes != 0) {
+// find out how much data to copy; limited to "d_bufLenBytes" per node
+    UInt32 t_nbytes = (l_nbytes > d_bufLenBytes) ? d_bufLenBytes : l_nbytes;
+
+// get next available node to write into;
+// blocks internally if none available
+    s_node_ptr l_node = d_queue->find_next_available_node ();
+
+// copy the input into the node's buffer
+    s_buffer_ptr l_buf = l_node->object ();
+    l_buf->buffer ((char*) buffer, t_nbytes);
+    void* v_buffer = (void*) l_buf->buffer ();
+
+// setup callback parameter & system call return
+    s_both_ptr l_both = l_node->both ();
+    io_return_t result = kIOReturnSuccess;
+
+    if (d_transferType == kUSBInterrupt)
+/* This is an interrupt pipe ... can't specify a timeout. */
+      result = d_interface->WritePipeAsync
+       (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes,
+        (IOAsyncCallback1) write_completed, (void*) l_both);
+    else
+      result = d_interface->WritePipeAsyncTO
+       (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes, 0, USB_TIMEOUT,
+        (IOAsyncCallback1) write_completed, (void*) l_both);
+
+    if (result != kIOReturnSuccess)
+      USB_ERROR_STR (-1, - darwin_to_errno (result),
+                    "fusb_ephandle_darwin::write_thread "
+                    "(WritePipeAsync%s): %s",
+                    d_transferType == kUSBInterrupt ? "" : "TO",
+                    darwin_error_str (result));
+    l_nbytes -= t_nbytes;
+  }
+
+  return (nbytes);
+}
+
+void
+fusb_ephandle_darwin::write_completed (void* refCon,
+                                      io_return_t result,
+                                      void* io_size)
+{
+  s_both_ptr l_both = static_cast<s_both_ptr>(refCon);
+  fusb_ephandle_darwin* This = static_cast<fusb_ephandle_darwin*>(l_both->This ());
+  UInt32 l_size = (UInt32) io_size;
+  s_node_ptr l_node = l_both->node ();
+  s_queue_ptr l_queue = This->d_queue;
+  s_buffer_ptr l_buf = l_node->object ();
+  UInt32 l_i_size = l_buf->n_used ();
+
+  if (This->d_started && (l_i_size != l_size))
+    fprintf (stderr, "fusb_ephandle_darwin::write_completed: "
+            "Expected %ld bytes written; wrote %ld.\n",
+            l_i_size, l_size);
+
+// set buffer's # data to 0
+  l_buf->n_used (0);
+// make the node available for reuse
+  l_queue->make_node_available (l_node);
+}
+
+void
+fusb_ephandle_darwin::abort ()
+{
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::abort: starting.\n");
+
+  io_return_t result = d_interface->AbortPipe (d_interfaceRef, d_pipeRef);
+
+  if (result != kIOReturnSuccess)
+    USB_ERROR_STR_NO_RET (- darwin_to_errno (result),
+                         "fusb_ephandle_darwin::abort "
+                         "(AbortPipe): %s", darwin_error_str (result));
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::abort: finished.\n");
+}
+
+bool
+fusb_ephandle_darwin::stop ()
+{
+  if (! d_started)
+    return (true);
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::stop: stopping %s.\n",
+            d_input_p ? "read" : "write");
+
+  d_started = false;
+
+// abort any pending IO transfers
+  abort ();
+
+// wait for write transfer to finish
+  wait_for_completion ();
+
+// tell IO buffer to abort any waiting conditions
+  d_buffer->abort ();
+
+// stop the run loop
+  CFRunLoopStop (d_CFRunLoopRef);
+
+// wait for the runThread to stop
+  d_runThreadRunning->lock ();
+  d_runThreadRunning->unlock ();
+
+  if (usb_debug)
+    fprintf (stderr, "fusb_ephandle_darwin::stop: %s stopped.\n",
+            d_input_p ? "read" : "write");
+
+  return (true);
+}
+
+void
+fusb_ephandle_darwin::wait_for_completion ()
+{
+  if (d_queue)
+    while (d_queue->in_use ())
+      usleep (1000);
+}
diff --git a/usrp/host/lib/legacy/fusb_darwin.h b/usrp/host/lib/legacy/fusb_darwin.h
new file mode 100644 (file)
index 0000000..9254c7f
--- /dev/null
@@ -0,0 +1,215 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FUSB_DARWIN_H_
+#define _FUSB_DARWIN_H_
+
+#include <usb.h>
+#include "fusb.h"
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOKitLib.h>
+#include "circular_linked_list.h"
+#include "circular_buffer.h"
+
+// for MacOS X 10.4.[0-3]
+#define usb_interface_t IOUSBInterfaceInterface220
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
+#define InterfaceVersion 220
+
+// for MacOS X 10.3.[0-9] and 10.4.[0-3]
+#define usb_device_t    IOUSBDeviceInterface197
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
+#define DeviceVersion 197
+
+extern "C" {
+typedef struct usb_dev_handle {
+  int fd;
+
+  struct usb_bus *bus;
+  struct usb_device *device;
+
+  int config;
+  int interface;
+  int altsetting;
+
+  /* Added by RMT so implementations can store other per-open-device data */
+  void *impl_info;
+} usb_dev_handle;
+
+/* Darwin/OS X impl does not use fd field, instead it uses this */
+typedef struct darwin_dev_handle {
+  usb_device_t** device;
+  usb_interface_t** interface;
+  int open;
+} darwin_dev_handle;
+
+typedef IOReturn io_return_t;
+typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
+
+static int ep_to_pipeRef (darwin_dev_handle* device, int ep);
+extern int usb_debug;
+}
+
+class s_buffer
+{
+private:
+  char* d_buffer;
+  UInt32 d_n_used, d_n_alloc;
+
+public:
+  inline s_buffer (UInt32 n_alloc = 0) {
+    d_n_used = 0;
+    d_n_alloc = n_alloc;
+    if (n_alloc) {
+      d_buffer = (char*) new char [n_alloc];
+    } else {
+      d_buffer = 0;
+    }
+  };
+  inline ~s_buffer () {
+    if (d_n_alloc) {
+      delete [] d_buffer;
+    }
+  };
+  inline UInt32 n_used () { return (d_n_used); };
+  inline void n_used (UInt32 bufLen) {
+    d_n_used = (bufLen > d_n_alloc) ? d_n_alloc : bufLen; };
+  inline UInt32 n_alloc () { return (d_n_alloc); };
+  void buffer (char* l_buffer, UInt32 bufLen) {
+    if (bufLen > d_n_alloc) {
+      fprintf (stderr, "s_buffer::set: Copying only allocated bytes.\n");
+      bufLen = d_n_alloc;
+    }
+    if (!l_buffer) {
+      fprintf (stderr, "s_buffer::set: NULL buffer.\n");
+      return;
+    }
+    bcopy (l_buffer, d_buffer, bufLen);
+    d_n_used = bufLen;
+  };
+  inline char* buffer () { return (d_buffer); };
+  inline void reset () {
+    bzero (d_buffer, d_n_alloc);
+    d_n_used = 0;
+  };
+};
+
+typedef s_buffer* s_buffer_ptr;
+typedef s_node<s_buffer_ptr>* s_node_ptr;
+typedef circular_linked_list<s_buffer_ptr>* s_queue_ptr;
+typedef s_both<s_buffer_ptr>* s_both_ptr;
+
+/*!
+ * \brief darwin implementation of fusb_devhandle
+ *
+ * This is currently identical to the generic implementation
+ * and is intended as a starting point for whatever magic is
+ * required to make usb fly.
+ */
+class fusb_devhandle_darwin : public fusb_devhandle
+{
+public:
+  // CREATORS
+  fusb_devhandle_darwin (usb_dev_handle* udh);
+  virtual ~fusb_devhandle_darwin ();
+
+  // MANIPULATORS
+  virtual fusb_ephandle* make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0);
+};
+
+/*!
+ * \brief darwin implementation of fusb_ephandle
+ *
+ * This is currently identical to the generic implementation
+ * and is intended as a starting point for whatever magic is
+ * required to make usb fly.
+ */
+class fusb_ephandle_darwin : public fusb_ephandle
+{
+private:
+  fusb_devhandle_darwin* d_devhandle;
+  mld_thread_ptr d_runThread;
+  mld_mutex_ptr d_runThreadRunning;
+
+  CFRunLoopRef d_CFRunLoopRef;
+
+  static void write_completed (void* ret_io_size,
+                              io_return_t result,
+                              void* io_size);
+  static void read_completed (void* ret_io_size,
+                             io_return_t result,
+                             void* io_size);
+  static void run_thread (void* arg);
+  static void read_thread (void* arg);
+
+  void read_issue (s_both_ptr l_both);
+
+public:
+  // variables, for now
+  UInt8 d_pipeRef, d_transferType;
+  usb_interface_t** d_interfaceRef;
+  usb_interface_t* d_interface;
+  s_queue_ptr d_queue;
+  circular_buffer<char>* d_buffer;
+  UInt32 d_bufLenBytes;
+  mld_mutex_ptr d_readRunning;
+  mld_condition_ptr d_runBlock, d_readBlock;
+
+// CREATORS
+
+  fusb_ephandle_darwin (fusb_devhandle_darwin *dh, int endpoint, bool input_p,
+                        int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle_darwin ();
+
+// MANIPULATORS
+
+  virtual bool start ();       //!< begin streaming i/o
+  virtual bool stop ();                //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void* buffer, int nbytes);
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void* buffer, int nbytes);
+
+  /*
+   * abort any pending IO transfers
+   */
+  void abort ();
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion ();
+};
+
+#endif /* _FUSB_DARWIN_H_ */
diff --git a/usrp/host/lib/legacy/fusb_generic.cc b/usrp/host/lib/legacy/fusb_generic.cc
new file mode 100644 (file)
index 0000000..f9f3c29
--- /dev/null
@@ -0,0 +1,108 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fusb_generic.h>
+#include <usb.h>
+
+
+static const int USB_TIMEOUT = 1000;   // in milliseconds
+
+
+fusb_devhandle_generic::fusb_devhandle_generic (usb_dev_handle *udh)
+  : fusb_devhandle (udh)
+{
+  // that's it
+}
+
+fusb_devhandle_generic::~fusb_devhandle_generic ()
+{
+  // nop
+}
+
+fusb_ephandle *
+fusb_devhandle_generic::make_ephandle (int endpoint, bool input_p,
+                                      int block_size, int nblocks)
+{
+  return new fusb_ephandle_generic (this, endpoint, input_p,
+                                   block_size, nblocks);
+}
+
+// ----------------------------------------------------------------
+
+fusb_ephandle_generic::fusb_ephandle_generic (fusb_devhandle_generic *dh,
+                                             int endpoint, bool input_p,
+                                             int block_size, int nblocks)
+  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
+    d_devhandle (dh)
+{
+  // that's it
+}
+
+fusb_ephandle_generic::~fusb_ephandle_generic ()
+{
+  // nop
+}
+
+bool
+fusb_ephandle_generic::start ()
+{
+  d_started = true;
+  return true;
+}
+
+bool
+fusb_ephandle_generic::stop ()
+{
+  d_started = false;
+  return true;
+}
+
+int
+fusb_ephandle_generic::write (const void *buffer, int nbytes)
+{
+  if (!d_started)      // doesn't matter here, but keeps semantics constant
+    return -1;
+  
+  if (d_input_p)
+    return -1;
+  
+  return usb_bulk_write (d_devhandle->get_usb_dev_handle (),
+                        d_endpoint, (char *) buffer, nbytes, USB_TIMEOUT);
+}
+
+int
+fusb_ephandle_generic::read (void *buffer, int nbytes)
+{
+  if (!d_started)      // doesn't matter here, but keeps semantics constant
+    return -1;
+
+  if (!d_input_p)
+    return -1;
+
+  return usb_bulk_read (d_devhandle->get_usb_dev_handle (),
+                       d_endpoint|USB_ENDPOINT_IN, (char *) buffer, nbytes,
+                       USB_TIMEOUT);
+}
diff --git a/usrp/host/lib/legacy/fusb_generic.h b/usrp/host/lib/legacy/fusb_generic.h
new file mode 100644 (file)
index 0000000..8c3a456
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FUSB_GENERIC_H_
+#define _FUSB_GENERIC_H_
+
+#include <fusb.h>
+
+/*!
+ * \brief generic implementation of fusb_devhandle using only libusb
+ */
+class fusb_devhandle_generic : public fusb_devhandle
+{
+public:
+  // CREATORS
+  fusb_devhandle_generic (usb_dev_handle *udh);
+  virtual ~fusb_devhandle_generic ();
+
+  // MANIPULATORS
+  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0);
+};
+
+
+/*!
+ * \brief generic implementation of fusb_ephandle using only libusb
+ */
+class fusb_ephandle_generic : public fusb_ephandle
+{
+private:
+  fusb_devhandle_generic       *d_devhandle;
+  
+public:
+  // CREATORS
+  fusb_ephandle_generic (fusb_devhandle_generic *dh, int endpoint, bool input_p,
+                        int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle_generic ();
+
+  // MANIPULATORS
+
+  virtual bool start ();       //!< begin streaming i/o
+  virtual bool stop ();                //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void *buffer, int nbytes);
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void *buffer, int nbytes);
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion () { };
+};
+
+#endif /* _FUSB_GENERIC_H_ */
+
diff --git a/usrp/host/lib/legacy/fusb_linux.cc b/usrp/host/lib/legacy/fusb_linux.cc
new file mode 100644 (file)
index 0000000..1eaba4e
--- /dev/null
@@ -0,0 +1,686 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fusb_linux.h>
+#include <usb.h>               // libusb header
+#include <stdexcept>
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/usbdevice_fs.h>        // interface to kernel portion of user mode usb driver
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <string.h>
+#include <algorithm>
+#include <errno.h>
+#include <string.h>
+
+#define MINIMIZE_TX_BUFFERING 1                // must be defined to 0 or 1
+
+
+static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();            // hard limit
+static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE;
+static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20);                         // 4 MB / endpoint
+
+
+// Totally evil and fragile extraction of file descriptor from
+// guts of libusb.  They don't install usbi.h, which is what we'd need
+// to do this nicely.
+//
+// FIXME if everything breaks someday in the future, look here...
+
+static int
+fd_from_usb_dev_handle (usb_dev_handle *udh)
+{
+  return *((int *) udh);
+}
+
+inline static void
+urb_set_ephandle (usbdevfs_urb *urb, fusb_ephandle_linux *handle)
+{
+  urb->usercontext = handle;
+}
+
+inline static fusb_ephandle_linux *
+urb_get_ephandle (usbdevfs_urb *urb)
+{
+  return (fusb_ephandle_linux *) urb->usercontext;
+}
+
+// ------------------------------------------------------------------------
+//                USB request block (urb) allocation
+// ------------------------------------------------------------------------
+
+static usbdevfs_urb *
+alloc_urb (fusb_ephandle_linux *self, int buffer_length, int endpoint,
+          bool input_p, unsigned char *write_buffer)
+{
+  usbdevfs_urb *urb = new usbdevfs_urb;
+  memset (urb, 0, sizeof (*urb));
+
+  urb->buffer_length = buffer_length;
+
+  // We allocate dedicated memory only for input buffers.
+  // For output buffers we reuse the same buffer (the kernel 
+  // copies the data at submital time)
+
+  if (input_p)
+    urb->buffer = new unsigned char [buffer_length];
+  else
+    urb->buffer = write_buffer;
+
+  // init common values
+
+  urb->type = USBDEVFS_URB_TYPE_BULK;
+  urb->endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0);
+
+  // USBDEVFS_URB_QUEUE_BULK goes away in linux 2.5, but is needed if
+  // we are using a 2.4 usb-uhci host controller driver.  This is
+  // unlikely since we're almost always going to be plugged into a
+  // high speed host controller (ehci)
+#if 0 && defined (USBDEVFS_URB_QUEUE_BULK)
+  urb->flags = USBDEVFS_URB_QUEUE_BULK;
+#endif
+
+  urb->signr = 0;
+  urb_set_ephandle (urb, self);
+
+  return urb;
+}
+
+static void
+free_urb (usbdevfs_urb *urb)
+{
+  // if this was an input urb, free the buffer
+  if (urb->endpoint & 0x80)
+    delete [] ((unsigned char *) urb->buffer);
+
+  delete urb;
+}
+
+// ------------------------------------------------------------------------
+//                             device handle
+// ------------------------------------------------------------------------
+
+fusb_devhandle_linux::fusb_devhandle_linux (usb_dev_handle *udh)
+  : fusb_devhandle (udh)
+{
+  // that's all
+}
+
+fusb_devhandle_linux::~fusb_devhandle_linux ()
+{
+  // if there are any pending requests, cancel them and free the urbs.
+  
+  std::list<usbdevfs_urb*>::reverse_iterator it;
+
+  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
+    _cancel_urb (*it);
+    free_urb (*it);
+  }
+}
+
+fusb_ephandle *
+fusb_devhandle_linux::make_ephandle (int endpoint, bool input_p,
+                                    int block_size, int nblocks)
+{
+  return new fusb_ephandle_linux (this, endpoint, input_p,
+                                 block_size, nblocks);
+}
+
+
+// Attempt to cancel all transactions associated with eph.
+
+void
+fusb_devhandle_linux::_cancel_pending_rqsts (fusb_ephandle_linux *eph)
+{
+  std::list<usbdevfs_urb*>::reverse_iterator it;
+
+  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
+    if (urb_get_ephandle (*it) == eph)
+      _cancel_urb (*it);
+  }
+}
+
+void 
+fusb_devhandle_linux::pending_add (usbdevfs_urb *urb)
+{
+  d_pending_rqsts.push_back (urb);
+}
+
+usbdevfs_urb *
+fusb_devhandle_linux::pending_get ()
+{
+  if (d_pending_rqsts.empty ())
+    return 0;
+
+  usbdevfs_urb *urb = d_pending_rqsts.front ();
+  d_pending_rqsts.pop_front ();
+  return urb;
+}
+
+bool
+fusb_devhandle_linux::pending_remove (usbdevfs_urb *urb)
+{
+  std::list<usbdevfs_urb*>::iterator   result = find (d_pending_rqsts.begin (),
+                                                      d_pending_rqsts.end (),
+                                                      urb);
+  if (result == d_pending_rqsts.end ()){
+    fprintf (stderr, "fusb::pending_remove: failed to find urb in pending_rqsts: %p\n", urb);
+    return false;
+  }
+  d_pending_rqsts.erase (result);
+  return true;
+}
+
+/*
+ * Submit the urb to the kernel.
+ * iff successful, the urb will be placed on the devhandle's pending list.
+ */
+bool
+fusb_devhandle_linux::_submit_urb (usbdevfs_urb *urb)
+{
+  int  ret;
+
+  ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_SUBMITURB, urb);
+  if (ret < 0){
+    perror ("fusb::_submit_urb");
+    return false;
+  }
+  
+  pending_add (urb);
+  return true;
+}
+
+/*
+ * Attempt to cancel the in pending or in-progress urb transaction.
+ * Return true iff transaction was sucessfully cancelled.
+ *
+ * Failure to cancel should not be considered a problem.  This frequently
+ * occurs if the transaction has already completed in the kernel but hasn't
+ * yet been reaped by the user mode code.
+ *
+ * urbs which were cancelled have their status field set to -ENOENT when
+ * they are reaped.
+ */
+bool
+fusb_devhandle_linux::_cancel_urb (usbdevfs_urb *urb)
+{
+  int ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_DISCARDURB, urb);
+  if (ret < 0){
+    // perror ("fusb::_cancel_urb");
+    return false;
+  }
+  return true;
+}
+
+/*
+ * Check with the kernel and see if any of our outstanding requests
+ * have completed.  For each completed transaction, remove it from the
+ * devhandle's pending list and append it to the completed list for
+ * the corresponding endpoint.
+ *
+ * If any transactions are reaped return true.
+ *
+ * If ok_to_block_p is true, then this will block until at least one
+ * transaction completes.
+ */
+bool
+fusb_devhandle_linux::_reap (bool ok_to_block_p)
+{
+  int          ret;
+  int          nreaped = 0;
+  usbdevfs_urb *urb = 0;
+
+  int  fd = fd_from_usb_dev_handle (d_udh);
+  
+  // try to reap as many as possible without blocking...
+
+  while ((ret = ioctl (fd, USBDEVFS_REAPURBNDELAY, &urb)) == 0){
+    if (urb->status != 0 && urb->status != -ENOENT){
+      fprintf (stderr, "_reap: usb->status = %d, actual_length = %5d\n",
+              urb->status, urb->actual_length);
+    }
+    pending_remove (urb);
+    urb_get_ephandle (urb)->completed_list_add (urb);
+    nreaped++;
+  }
+
+  if (nreaped > 0)             // if we got any, return w/o blocking
+    return true;
+
+  if (!ok_to_block_p)
+    return false;
+  
+  ret = ioctl (fd, USBDEVFS_REAPURB, &urb);
+  if (ret < 0){
+    perror ("fusb::_reap");
+    return false;
+  }
+
+  pending_remove (urb);
+  urb_get_ephandle (urb)->completed_list_add (urb);
+  return true;
+}
+
+void
+fusb_devhandle_linux::_wait_for_completion ()
+{
+  while (!d_pending_rqsts.empty ())
+    _reap (true);
+}
+\f// ------------------------------------------------------------------------
+//                          end point handle
+// ------------------------------------------------------------------------
+
+fusb_ephandle_linux::fusb_ephandle_linux (fusb_devhandle_linux *devhandle,
+                                         int endpoint,
+                                         bool input_p,
+                                         int block_size, int nblocks)
+  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
+    d_devhandle (devhandle), 
+    d_write_work_in_progress (0), d_write_buffer (0),
+    d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0)
+{
+
+  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE)
+    throw std::out_of_range ("fusb_ephandle_linux: block_size");
+
+  if (d_nblocks < 0)
+    throw std::out_of_range ("fusb_ephandle_linux: nblocks");
+
+  if (d_block_size == 0)
+    d_block_size = DEFAULT_BLOCK_SIZE;
+
+  if (d_nblocks == 0)
+    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size);
+
+  if (!d_input_p)
+    if (!MINIMIZE_TX_BUFFERING)
+      d_write_buffer = new unsigned char [d_block_size];
+
+  if (0)
+    fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d  d_nblocks = %d\n",
+           d_block_size, d_nblocks);
+
+  // allocate urbs
+
+  for (int i = 0; i < d_nblocks; i++)
+    d_free_list.push_back (alloc_urb (this, d_block_size, d_endpoint,
+                                     d_input_p, d_write_buffer));
+}
+
+fusb_ephandle_linux::~fusb_ephandle_linux ()
+{
+  stop ();
+
+  usbdevfs_urb *urb;
+
+  while ((urb = free_list_get ()) != 0)
+    free_urb (urb);
+
+  while ((urb = completed_list_get ()) != 0)
+    free_urb (urb);
+
+  if (d_write_work_in_progress)
+    free_urb (d_write_work_in_progress);
+
+  delete [] d_write_buffer;
+
+  if (d_read_work_in_progress)
+    free_urb (d_read_work_in_progress);
+}
+
+// ----------------------------------------------------------------
+
+bool
+fusb_ephandle_linux::start ()
+{
+  if (d_started)
+    return true;               // already running
+
+  d_started = true;
+
+  if (d_input_p){              // fire off all the reads
+    usbdevfs_urb *urb;
+
+    int nerrors = 0;
+    while ((urb = free_list_get ()) != 0 && nerrors < d_nblocks){
+      if (!submit_urb (urb))
+       nerrors++;
+    }
+  }
+
+  return true;
+}
+
+//
+// kill all i/o in progress.
+// kill any completed but unprocessed transactions.
+//
+bool
+fusb_ephandle_linux::stop ()
+{
+  if (!d_started)
+    return true;
+  
+  d_devhandle->_cancel_pending_rqsts (this);
+  d_devhandle->_reap (false);
+
+
+  usbdevfs_urb *urb;
+  while ((urb = completed_list_get ()) != 0)
+    free_list_add (urb);
+
+  if (d_write_work_in_progress){
+    free_list_add (d_write_work_in_progress);
+    d_write_work_in_progress = 0;
+  }
+
+  if (d_read_work_in_progress){
+    free_list_add (d_read_work_in_progress);
+    d_read_work_in_progress = 0;
+    d_read_buffer = 0;
+    d_read_buffer_end = 0;
+  }
+
+  if (d_free_list.size () != (unsigned) d_nblocks)
+    fprintf (stderr, "d_free_list.size () = %d, d_nblocks = %d\n",
+            d_free_list.size (), d_nblocks);
+    
+  assert (d_free_list.size () == (unsigned) d_nblocks);
+
+  d_started = false;
+  return true;
+}
+
+// ----------------------------------------------------------------
+//                     routines for writing 
+// ----------------------------------------------------------------
+
+#if (MINIMIZE_TX_BUFFERING)
+
+int 
+fusb_ephandle_linux::write(const void *buffer, int nbytes)
+{
+  if (!d_started)
+    return -1;
+  
+  if (d_input_p)
+    return -1;
+
+  assert(nbytes % 512 == 0);
+
+  unsigned char *src = (unsigned char *) buffer;
+
+  int n = 0;
+  while (n < nbytes){
+
+    usbdevfs_urb *urb = get_write_work_in_progress();
+    assert(urb->actual_length == 0);
+    int m = std::min(nbytes - n, MAX_BLOCK_SIZE);
+    urb->buffer = src;
+    urb->buffer_length = m;
+
+    n += m;
+    src += m;
+
+    if (!submit_urb(urb))
+      return -1;
+
+    d_write_work_in_progress = 0;
+  }
+
+  return n;
+}
+
+#else
+
+int 
+fusb_ephandle_linux::write (const void *buffer, int nbytes)
+{
+  if (!d_started)
+    return -1;
+  
+  if (d_input_p)
+    return -1;
+
+  unsigned char *src = (unsigned char *) buffer;
+
+  int n = 0;
+  while (n < nbytes){
+
+    usbdevfs_urb *urb = get_write_work_in_progress ();
+    unsigned char *dst = (unsigned char *) urb->buffer;
+    int m = std::min (nbytes - n, urb->buffer_length - urb->actual_length);
+
+    memcpy (&dst[urb->actual_length], &src[n], m);
+    urb->actual_length += m;
+    n += m;
+
+    if (urb->actual_length == urb->buffer_length){
+      if (!submit_urb (urb))
+       return -1;
+      d_write_work_in_progress = 0;
+    }
+  }
+
+  return n;
+}
+
+#endif
+
+usbdevfs_urb *
+fusb_ephandle_linux::get_write_work_in_progress ()
+{
+  // if we've already got some work in progress, return it
+
+  if (d_write_work_in_progress)
+    return d_write_work_in_progress;
+
+  while (1){
+
+    reap_complete_writes ();
+
+    usbdevfs_urb *urb = free_list_get ();
+
+    if (urb != 0){
+      assert (urb->actual_length == 0);
+      d_write_work_in_progress = urb;
+      return urb;
+    }
+
+    // The free list is empty.  Tell the device handle to reap.
+    // Anything it reaps for us will end up on our completed list.
+
+    d_devhandle->_reap (true);
+  }
+}
+
+void
+fusb_ephandle_linux::reap_complete_writes ()
+{
+  // take a look at the completed_list and xfer to free list after
+  // checking for errors.
+
+  usbdevfs_urb *urb;
+  
+  while ((urb = completed_list_get ()) != 0){
+
+    // Check for any errors or short writes that were reported in the urb.
+    // The kernel sets status, actual_length and error_count.
+    // error_count is only used for ISO xfers.
+    // status is 0 if successful, else is an errno kind of thing
+
+    if (urb->status != 0){
+      fprintf (stderr, "fusb: (status %d) %s\n", urb->status, strerror (-urb->status));
+    }
+    else if (urb->actual_length != urb->buffer_length){
+      fprintf (stderr, "fusb: short write xfer: %d != %d\n",
+              urb->actual_length, urb->buffer_length);
+    }
+
+    free_list_add (urb);
+  }
+}
+
+void
+fusb_ephandle_linux::wait_for_completion ()
+{
+  d_devhandle->_wait_for_completion ();
+}
+
+// ----------------------------------------------------------------
+//                    routines for reading
+// ----------------------------------------------------------------
+
+int
+fusb_ephandle_linux::read (void *buffer, int nbytes)
+{
+  if (!d_started)
+    return -1;
+  
+  if (!d_input_p)
+    return -1;
+
+  unsigned char *dst = (unsigned char *) buffer;
+
+  int n = 0;
+  while (n < nbytes){
+
+    if (d_read_buffer >= d_read_buffer_end)
+      if (!reload_read_buffer ())
+       return -1;
+
+    int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer));
+
+    memcpy (&dst[n], d_read_buffer, m);
+    d_read_buffer += m;
+    n += m;
+  }
+
+  return n;
+}
+
+bool
+fusb_ephandle_linux::reload_read_buffer ()
+{
+  assert (d_read_buffer >= d_read_buffer_end);
+
+  usbdevfs_urb *urb;
+
+  if (d_read_work_in_progress){
+    // We're done with this urb.  Fire off a read to refill it.
+    urb = d_read_work_in_progress;
+    d_read_work_in_progress = 0;
+    d_read_buffer = 0;
+    d_read_buffer_end = 0;
+    urb->actual_length = 0;
+    if (!submit_urb (urb))
+      return false;
+  }
+
+  while (1){
+
+    while ((urb = completed_list_get ()) == 0)
+      d_devhandle->_reap (true);
+
+    // check result of completed read
+
+    if (urb->status != 0){
+      // We've got a problem.
+      // Report the problem and resubmit.
+      fprintf (stderr, "fusb: (rd status %d) %s\n", urb->status, strerror (-urb->status));
+      urb->actual_length = 0;
+      if (!submit_urb (urb))
+       return false;
+
+      continue;
+    }
+
+    // we've got a happy urb, full of data...
+
+    d_read_work_in_progress = urb;
+    d_read_buffer = (unsigned char *) urb->buffer;
+    d_read_buffer_end = d_read_buffer + urb->actual_length;
+
+    return true;
+  }
+}
+
+// ----------------------------------------------------------------
+
+void
+fusb_ephandle_linux::free_list_add (usbdevfs_urb *urb)
+{
+  assert (urb_get_ephandle (urb) == this);
+  urb->actual_length = 0;
+  d_free_list.push_back (urb);
+}
+
+usbdevfs_urb *
+fusb_ephandle_linux::free_list_get ()
+{
+  if (d_free_list.empty ())
+    return 0;
+
+  usbdevfs_urb *urb = d_free_list.front ();
+  d_free_list.pop_front ();
+  return urb;
+}
+
+void
+fusb_ephandle_linux::completed_list_add (usbdevfs_urb *urb)
+{
+  assert (urb_get_ephandle (urb) == this);
+  d_completed_list.push_back (urb);
+}
+
+usbdevfs_urb *
+fusb_ephandle_linux::completed_list_get ()
+{
+  if (d_completed_list.empty ())
+    return 0;
+
+  usbdevfs_urb *urb = d_completed_list.front ();
+  d_completed_list.pop_front ();
+  return urb;
+}
+
+/*
+ * Submit the urb.  If successful the urb ends up on the devhandle's
+ * pending list, otherwise, it's back on our free list.
+ */
+bool
+fusb_ephandle_linux::submit_urb (usbdevfs_urb *urb)
+{
+  if (!d_devhandle->_submit_urb (urb)){    // FIXME record the problem somewhere
+    fprintf (stderr, "_submit_urb failed\n");
+    free_list_add (urb);
+    return false;
+  }
+  return true;
+}
diff --git a/usrp/host/lib/legacy/fusb_linux.h b/usrp/host/lib/legacy/fusb_linux.h
new file mode 100644 (file)
index 0000000..b2d46a5
--- /dev/null
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Fast USB interface
+
+#ifndef _FUSB_LINUX_H_
+#define _FUSB_LINUX_H_
+
+#include <fusb.h>
+#include <list>
+
+struct  usbdevfs_urb;
+class   fusb_ephandle_linux;
+
+/*!
+ * \brief linux specific implementation of fusb_devhandle using usbdevice_fs
+ */
+class fusb_devhandle_linux : public fusb_devhandle {
+private:
+  std::list<usbdevfs_urb*>      d_pending_rqsts;
+
+  void pending_add (usbdevfs_urb *urb);
+  bool pending_remove (usbdevfs_urb *urb);
+  usbdevfs_urb * pending_get ();
+
+
+public:
+  // CREATORS
+  fusb_devhandle_linux (usb_dev_handle *udh);
+  virtual ~fusb_devhandle_linux ();
+
+  // MANIPULATORS
+  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0);
+
+  // internal use only
+  bool _submit_urb (usbdevfs_urb *urb);
+  bool _cancel_urb (usbdevfs_urb *urb);
+  void _cancel_pending_rqsts (fusb_ephandle_linux *eph);
+  bool _reap (bool ok_to_block_p);
+  void _wait_for_completion ();
+};
+
+\f/*!
+ * \brief linux specific implementation of fusb_ephandle using usbdevice_fs
+ */
+
+class fusb_ephandle_linux : public fusb_ephandle {
+private:
+  fusb_devhandle_linux        *d_devhandle;
+  std::list<usbdevfs_urb*>     d_free_list;
+  std::list<usbdevfs_urb*>     d_completed_list;
+  usbdevfs_urb                *d_write_work_in_progress;
+  unsigned char                       *d_write_buffer;
+  usbdevfs_urb                *d_read_work_in_progress;
+  unsigned char                       *d_read_buffer;
+  unsigned char                       *d_read_buffer_end;
+
+  usbdevfs_urb *get_write_work_in_progress ();
+  void reap_complete_writes ();
+  bool reload_read_buffer ();
+  bool submit_urb (usbdevfs_urb *urb);
+  
+public:
+  fusb_ephandle_linux (fusb_devhandle_linux *dh, int endpoint, bool input_p,
+                      int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle_linux ();
+
+  virtual bool start ();       //!< begin streaming i/o
+  virtual bool stop ();                //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void *buffer, int nbytes);
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void *buffer, int nbytes);
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion ();
+
+  // internal use only
+  void free_list_add (usbdevfs_urb *urb);
+  void completed_list_add (usbdevfs_urb *urb);
+  usbdevfs_urb *free_list_get ();              // pop and return head of list or 0
+  usbdevfs_urb *completed_list_get ();         // pop and return head of list or 0
+};
+
+#endif /* _FUSB_LINUX_H_ */
diff --git a/usrp/host/lib/legacy/fusb_ra_wb.cc b/usrp/host/lib/legacy/fusb_ra_wb.cc
new file mode 100644 (file)
index 0000000..c95f4af
--- /dev/null
@@ -0,0 +1,258 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fusb_ra_wb.h>
+#include <usb.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/event.h>
+#include <dev/usb/usb.h>
+
+static const int USB_TIMEOUT = 1000;   // in milliseconds
+
+// the following comment and function is from fusb_linux.cc
+#if 0
+// Totally evil and fragile extraction of file descriptor from
+// guts of libusb.  They don't install usbi.h, which is what we'd need
+// to do this nicely.
+//
+// FIXME if everything breaks someday in the future, look here...
+
+static int
+fd_from_usb_dev_handle (usb_dev_handle *udh)
+{
+  return *((int *) udh);
+}
+#endif
+
+// the control endpoint doesn't actually do us any good so here is a
+// new "fragile extraction"
+static int
+ep_fd_from_usb_dev_handle (usb_dev_handle *udh, int endpoint)
+{
+  struct usb_dev_handle_kludge2 { // see also usrp_prims.cc
+    int                         fd;
+    struct usb_bus     *bus;
+    struct usb_device  *device;
+    int                         config;
+    int                         interface;
+    int                         altsetting;
+    void               *impl_info;
+  };
+  struct bsd_usb_dev_handle_info_kludge {
+    int                         ep_fd[USB_MAX_ENDPOINTS];
+  };
+  struct bsd_usb_dev_handle_info_kludge *info
+      = (struct bsd_usb_dev_handle_info_kludge *)
+           ((struct usb_dev_handle_kludge2 *)udh)->impl_info;
+  return info->ep_fd[UE_GET_ADDR(endpoint)];
+}
+
+
+fusb_devhandle_ra_wb::fusb_devhandle_ra_wb (usb_dev_handle *udh)
+  : fusb_devhandle (udh)
+{
+  // that's it
+}
+
+fusb_devhandle_ra_wb::~fusb_devhandle_ra_wb ()
+{
+  // nop
+}
+
+fusb_ephandle *
+fusb_devhandle_ra_wb::make_ephandle (int endpoint, bool input_p,
+                                    int block_size, int nblocks)
+{
+  return new fusb_ephandle_ra_wb (this, endpoint, input_p,
+                                 block_size, nblocks);
+}
+
+// ----------------------------------------------------------------
+
+fusb_ephandle_ra_wb::fusb_ephandle_ra_wb (fusb_devhandle_ra_wb *dh,
+                                         int endpoint, bool input_p,
+                                         int block_size, int nblocks)
+  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
+    d_devhandle (dh), d_ra_wb_on (false)
+{
+  // that's it 
+}
+
+fusb_ephandle_ra_wb::~fusb_ephandle_ra_wb ()
+{
+  // nop
+}
+
+bool
+fusb_ephandle_ra_wb::start ()
+{
+  d_started = true;
+
+  char buf = '\0';
+  int fd;
+
+  // this is to cause libusb to open the endpoint
+  if (!d_input_p) {
+    write(&buf, 0);
+    fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
+                                   d_endpoint);
+  }
+  else {
+    read(&buf, 0);
+    fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
+                                   d_endpoint|USB_ENDPOINT_IN);
+  }
+
+  // enable read ahead/write behind
+  int ret;
+  struct usb_bulk_ra_wb_opt opts;
+  int enable = 1;
+
+  opts.ra_wb_buffer_size = d_block_size*d_nblocks;
+  opts.ra_wb_request_size = d_block_size;
+//  fprintf (stderr, "setting buffer size to %d, request size to %d\n",
+//        opts.ra_wb_buffer_size, opts.ra_wb_request_size);
+  if (!d_input_p) {
+    ret = ioctl (fd, USB_SET_BULK_WB_OPT, &opts);
+    if (ret < 0)
+      fprintf (stderr, "USB_SET_BULK_WB_OPT: %s\n", strerror(errno));
+    else {
+      ret = ioctl (fd, USB_SET_BULK_WB, &enable);
+      if (ret < 0)
+       fprintf (stderr, "USB_SET_BULK_WB: %s\n", strerror(errno));
+      else
+       d_ra_wb_on = true;
+    }
+  }
+  else {
+    ret = ioctl (fd, USB_SET_BULK_RA_OPT, &opts);
+    if (ret < 0)
+      fprintf (stderr, "USB_SET_BULK_RA_OPT: %s\n", strerror(errno));
+    else {
+      ret = ioctl (fd, USB_SET_BULK_RA, &enable);
+      if (ret < 0)
+       fprintf (stderr, "USB_SET_BULK_RA: %s\n", strerror(errno));
+      else
+       d_ra_wb_on = true;
+    }
+  }
+
+  return true;
+}
+
+bool
+fusb_ephandle_ra_wb::stop ()
+{
+  int fd;
+  int ret;
+  int enable = 0;
+  if (d_ra_wb_on) {
+    if (!d_input_p) {
+      fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
+                                     d_endpoint);
+      ret = ioctl (fd, USB_SET_BULK_WB, &enable);
+      if (ret < 0)
+       fprintf (stderr, "USB_SET_BULK_WB: %s\n", strerror(errno));
+      else
+       d_ra_wb_on = false;
+    }
+    else {
+      fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
+                                     d_endpoint|USB_ENDPOINT_IN);
+      ret = ioctl (fd, USB_SET_BULK_RA, &enable);
+      if (ret < 0)
+       fprintf (stderr, "USB_SET_BULK_RA: %s\n", strerror(errno));
+      else
+       d_ra_wb_on = false;
+    }
+  }
+
+  d_started = false;
+  return true;
+}
+
+int
+fusb_ephandle_ra_wb::write (const void *buffer, int nbytes)
+{
+  if (!d_started)
+    return -1;
+  
+  if (d_input_p)
+    return -1;
+  
+  return usb_bulk_write (d_devhandle->get_usb_dev_handle (),
+                        d_endpoint, (char *) buffer, nbytes, USB_TIMEOUT);
+}
+
+int
+fusb_ephandle_ra_wb::read (void *buffer, int nbytes)
+{
+  if (!d_started)
+    return -1;
+
+  if (!d_input_p)
+    return -1;
+
+  return usb_bulk_read (d_devhandle->get_usb_dev_handle (),
+                       d_endpoint|USB_ENDPOINT_IN, (char *) buffer, nbytes,
+                       USB_TIMEOUT);
+}
+
+void
+fusb_ephandle_ra_wb::wait_for_completion ()
+{
+  // as the driver is implemented this only makes sense for write 
+  if (d_ra_wb_on && !d_input_p) {
+    int fd = ep_fd_from_usb_dev_handle (d_devhandle->get_usb_dev_handle(),
+                                       d_endpoint);
+    int kq = kqueue();
+    if (kq < 0)
+      return;
+    struct kevent evt;
+    int nevents;
+    EV_SET (&evt, fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, 0/*NULL*/);
+    nevents = kevent (kq, &evt, 1, &evt, 1, NULL);
+    if (nevents < 1) {
+      close(kq);
+      return;
+    }
+    while (!(evt.flags & EV_ERROR) && evt.data < (d_block_size*d_nblocks)) {
+      // it's a busy loop, but that's all I can do at the moment
+      nevents = kevent (kq, NULL, 0, &evt, 1, NULL);
+      // let's see if this improves the test_usrp_standard_tx throughput &
+      // "CPU usage" by looping less frequently
+      struct timeval timeout;
+      timeout.tv_sec = 0;
+      timeout.tv_usec = 1000; // 1 ms
+      select (0, NULL, NULL, NULL, &timeout);
+    }
+    close (kq);
+  }
+}
diff --git a/usrp/host/lib/legacy/fusb_ra_wb.h b/usrp/host/lib/legacy/fusb_ra_wb.h
new file mode 100644 (file)
index 0000000..09bf8ee
--- /dev/null
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FUSB_RA_WB_H_
+#define _FUSB_RA_WB_H_
+
+#include <fusb.h>
+
+/*!
+ * \brief generic implementation of fusb_devhandle using only libusb
+ */
+class fusb_devhandle_ra_wb : public fusb_devhandle
+{
+public:
+  // CREATORS
+  fusb_devhandle_ra_wb (usb_dev_handle *udh);
+  virtual ~fusb_devhandle_ra_wb ();
+
+  // MANIPULATORS
+  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0);
+};
+
+
+/*!
+ * \brief generic implementation of fusb_ephandle using only libusb
+ */
+class fusb_ephandle_ra_wb : public fusb_ephandle
+{
+private:
+  fusb_devhandle_ra_wb *d_devhandle;
+  bool d_ra_wb_on;
+  
+public:
+  // CREATORS
+  fusb_ephandle_ra_wb (fusb_devhandle_ra_wb *dh, int endpoint, bool input_p,
+                      int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle_ra_wb ();
+
+  // MANIPULATORS
+
+  virtual bool start ();       //!< begin streaming i/o
+  virtual bool stop ();                //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void *buffer, int nbytes);
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void *buffer, int nbytes);
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion ();
+};
+
+#endif /* _FUSB_RA_WB_H_ */
+
diff --git a/usrp/host/lib/legacy/fusb_sysconfig_darwin.cc b/usrp/host/lib/legacy/fusb_sysconfig_darwin.cc
new file mode 100644 (file)
index 0000000..f66c298
--- /dev/null
@@ -0,0 +1,44 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fusb.h>
+#include <fusb_darwin.h>
+
+static const int MAX_BLOCK_SIZE = 32 * 1024;           // hard limit
+static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
+
+fusb_devhandle *
+fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
+{
+  return new fusb_devhandle_darwin (udh);
+}
+
+int fusb_sysconfig::max_block_size ()
+{
+  return MAX_BLOCK_SIZE;
+}
+
+int fusb_sysconfig::default_buffer_size ()
+{
+  return FUSB_BUFFER_SIZE;
+}
+
diff --git a/usrp/host/lib/legacy/fusb_sysconfig_generic.cc b/usrp/host/lib/legacy/fusb_sysconfig_generic.cc
new file mode 100644 (file)
index 0000000..d336cb9
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fusb.h>
+#include <fusb_generic.h>
+
+static const int MAX_BLOCK_SIZE = 16 * 1024;           // hard limit
+static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
+
+fusb_devhandle *
+fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
+{
+  return new fusb_devhandle_generic (udh);
+}
+       
+int fusb_sysconfig::max_block_size ()
+{
+  return MAX_BLOCK_SIZE;
+}
+
+int fusb_sysconfig::default_buffer_size ()
+{
+  return FUSB_BUFFER_SIZE;
+}
diff --git a/usrp/host/lib/legacy/fusb_sysconfig_linux.cc b/usrp/host/lib/legacy/fusb_sysconfig_linux.cc
new file mode 100644 (file)
index 0000000..468fa9f
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fusb.h>
+#include <fusb_linux.h>
+
+static const int MAX_BLOCK_SIZE = 16 * 1024;           // hard limit
+static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
+
+fusb_devhandle *
+fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
+{
+  return new fusb_devhandle_linux (udh);
+}
+
+int fusb_sysconfig::max_block_size ()
+{
+  return MAX_BLOCK_SIZE;
+}
+
+int fusb_sysconfig::default_buffer_size ()
+{
+  return FUSB_BUFFER_SIZE;
+}
diff --git a/usrp/host/lib/legacy/fusb_sysconfig_ra_wb.cc b/usrp/host/lib/legacy/fusb_sysconfig_ra_wb.cc
new file mode 100644 (file)
index 0000000..68eeced
--- /dev/null
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fusb.h>
+#include <fusb_ra_wb.h>
+
+//static const int MAX_BLOCK_SIZE = 16 * 1024;         // hard limit
+// there's no hard limit, even before making any changes to the driver
+// 64k is empirically a pretty good number
+static const int MAX_BLOCK_SIZE = 64 * 1024;
+// there is a limit of 1 MB in the driver for the buffer size
+static const int FUSB_BUFFER_SIZE = 256 * (1L << 10);  // 256 kB
+
+fusb_devhandle *
+fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
+{
+  return new fusb_devhandle_ra_wb (udh);
+}
+       
+int fusb_sysconfig::max_block_size ()
+{
+  return MAX_BLOCK_SIZE;
+}
+
+int fusb_sysconfig::default_buffer_size ()
+{
+  return FUSB_BUFFER_SIZE;
+}
diff --git a/usrp/host/lib/legacy/fusb_sysconfig_win32.cc b/usrp/host/lib/legacy/fusb_sysconfig_win32.cc
new file mode 100644 (file)
index 0000000..282e77a
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2005 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fusb.h>
+#include <fusb_win32.h>
+
+static const int MAX_BLOCK_SIZE = 64 * 1024;           // Windows kernel hard limit
+static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);    // 2 MB (was 8 MB)
+       
+fusb_devhandle *
+fusb_sysconfig::make_devhandle (usb_dev_handle *udh)
+{
+  return new fusb_devhandle_win32 (udh);
+}
+
+int fusb_sysconfig::max_block_size ()
+{
+  return MAX_BLOCK_SIZE;
+}
+
+int fusb_sysconfig::default_buffer_size ()
+{
+  return FUSB_BUFFER_SIZE;
+}
diff --git a/usrp/host/lib/legacy/fusb_win32.cc b/usrp/host/lib/legacy/fusb_win32.cc
new file mode 100644 (file)
index 0000000..c6e3c97
--- /dev/null
@@ -0,0 +1,265 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2005 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fusb_win32.h>
+#include <usb.h>
+#include <assert.h>
+#include <stdexcept>
+
+static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();
+static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE;
+static const int DEFAULT_BUFFER_SIZE = 16 * (1L << 20);                // 16 MB / endpoint
+
+
+static const int USB_TIMEOUT = 1000;   // in milliseconds
+
+
+fusb_devhandle_win32::fusb_devhandle_win32 (usb_dev_handle *udh)
+  : fusb_devhandle (udh)
+{
+  // that's it
+}
+
+fusb_devhandle_win32::~fusb_devhandle_win32 ()
+{
+  // nop
+}
+
+fusb_ephandle *
+fusb_devhandle_win32::make_ephandle (int endpoint, bool input_p,
+                                      int block_size, int nblocks)
+{
+  return new fusb_ephandle_win32 (this, endpoint, input_p,
+                                   block_size, nblocks);
+}
+
+// ----------------------------------------------------------------
+
+fusb_ephandle_win32::fusb_ephandle_win32 (fusb_devhandle_win32 *dh,
+                                             int endpoint, bool input_p,
+                                             int block_size, int nblocks)
+  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
+    d_devhandle (dh), d_input_leftover(0),d_output_short(0)
+{
+  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE)
+    throw std::out_of_range ("fusb_ephandle_win32: block_size");
+
+  if (d_nblocks < 0)
+    throw std::out_of_range ("fusb_ephandle_win32: nblocks");
+
+  if (d_block_size == 0)
+    d_block_size = DEFAULT_BLOCK_SIZE;
+
+  if (d_nblocks == 0)
+    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size);
+
+  d_buffer = new char [d_block_size*d_nblocks];
+  d_context = new void * [d_nblocks];
+
+  // allocate contexts
+
+  usb_dev_handle *dev = dh->get_usb_dev_handle ();
+  int i;
+
+  if (d_input_p)
+    endpoint |= USB_ENDPOINT_IN;
+
+  for (i=0; i<d_nblocks; i++)
+    usb_bulk_setup_async(dev, &d_context[i], endpoint);
+}
+
+fusb_ephandle_win32::~fusb_ephandle_win32 ()
+{
+  int i;
+
+  stop ();
+
+  for (i=0; i<d_nblocks; i++)
+    usb_free_async(&d_context[i]);
+
+  delete [] d_buffer;
+  delete [] d_context;
+}
+
+bool
+fusb_ephandle_win32::start ()
+{
+  if (d_started)
+    return true;       // already running
+
+  d_started = true;
+
+  d_curr = d_nblocks-1;
+  d_outstanding_write = 0;
+  d_input_leftover =0;
+  d_output_short = 0;
+
+  if (d_input_p){      // fire off all the reads
+    int i;
+
+    for (i=0; i<d_nblocks; i++) {
+      usb_submit_async(d_context[i], (char * ) d_buffer+i*d_block_size,
+                     d_block_size);
+    }
+  }
+
+  return true;
+}
+
+bool
+fusb_ephandle_win32::stop ()
+{
+  if (!d_started)
+    return true;
+
+  if (!d_input_p)
+    wait_for_completion ();
+
+  d_started = false;
+  return true;
+}
+
+int
+fusb_ephandle_win32::write (const void *buffer, int nbytes)
+{
+  int retval=0;
+  char *buf;
+
+  if (!d_started)      // doesn't matter here, but keeps semantics constant
+    return -1;
+
+  if (d_input_p)
+    return -1;
+
+  int bytes_to_write = nbytes;
+  int a=0;
+
+  if (d_output_short != 0) {
+
+       buf = &d_buffer[d_curr*d_block_size + d_block_size - d_output_short];
+       a = std::min(nbytes, d_output_short);
+       memcpy(buf, buffer, a);
+       bytes_to_write -= a;
+       d_output_short -= a;
+
+    if (d_output_short == 0)
+        usb_submit_async(d_context[d_curr],
+                        &d_buffer[d_curr*d_block_size], d_block_size);
+  }
+
+  while (bytes_to_write > 0) {
+    d_curr = (d_curr+1)%d_nblocks;
+    buf = &d_buffer[d_curr*d_block_size];
+
+    if (d_outstanding_write != d_nblocks) {
+      d_outstanding_write++;
+    } else {
+      retval = usb_reap_async(d_context[d_curr], USB_TIMEOUT);
+      if (retval < 0) {
+                 fprintf(stderr, "%s: usb_reap_async: %s\n",
+                         __FUNCTION__, usb_strerror());
+         return retval;
+       }
+    }
+
+    int ncopy = std::min(bytes_to_write, d_block_size);
+    memcpy(buf, (void *) &(((char*)buffer)[a]), ncopy);
+    bytes_to_write -= ncopy;
+    a += ncopy;
+
+    d_output_short = d_block_size - ncopy;
+    if (d_output_short == 0)
+           usb_submit_async(d_context[d_curr], buf, d_block_size);
+  }
+
+  return retval < 0 ? retval : nbytes;
+}
+
+int
+fusb_ephandle_win32::read (void *buffer, int nbytes)
+{
+  int retval=0;
+  char *buf;
+
+  if (!d_started)      // doesn't matter here, but keeps semantics constant
+    return -1;
+
+  if (!d_input_p)
+    return -1;
+
+  int bytes_to_read = nbytes;
+
+  int a=0;
+  if (d_input_leftover != 0) {
+
+       buf = &d_buffer[d_curr*d_block_size + d_block_size - d_input_leftover];
+       a = std::min(nbytes, d_input_leftover);
+       memcpy(buffer, buf, a);
+       bytes_to_read -= a;
+       d_input_leftover -= a;
+
+    if (d_input_leftover == 0)
+        usb_submit_async(d_context[d_curr],
+                        &d_buffer[d_curr*d_block_size], d_block_size);
+  }
+
+  while (bytes_to_read > 0) {
+
+    d_curr = (d_curr+1)%d_nblocks;
+    buf = &d_buffer[d_curr*d_block_size];
+
+    retval = usb_reap_async(d_context[d_curr], USB_TIMEOUT);
+    if (retval < 0)
+         fprintf(stderr, "%s: usb_reap_async: %s\n",
+                         __FUNCTION__, usb_strerror());
+
+    int ncopy = std::min(bytes_to_read, d_block_size);
+    memcpy((void *) &(((char*)buffer)[a]), buf, ncopy);
+    bytes_to_read -= ncopy;
+    a += ncopy;
+
+    d_input_leftover = d_block_size - ncopy;
+    if (d_input_leftover == 0)
+           usb_submit_async(d_context[d_curr], buf, d_block_size);
+  }
+
+  return retval < 0 ? retval : nbytes;
+}
+
+void
+fusb_ephandle_win32::wait_for_completion ()
+{
+  int i;
+
+  for (i=0; i<d_outstanding_write; i++) {
+    int context_num;
+
+    context_num = (d_curr+d_outstanding_write+i+1)%d_nblocks;
+    usb_reap_async(d_context[context_num], USB_TIMEOUT);
+  }
+
+  d_outstanding_write = 0;
+}
diff --git a/usrp/host/lib/legacy/fusb_win32.h b/usrp/host/lib/legacy/fusb_win32.h
new file mode 100644 (file)
index 0000000..c796af4
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FUSB_WIN32_H_
+#define _FUSB_WIN32_H_
+
+#include <fusb.h>
+
+/*!
+ * \brief win32 implementation of fusb_devhandle using libusb-win32
+ */
+class fusb_devhandle_win32 : public fusb_devhandle
+{
+public:
+  // CREATORS
+  fusb_devhandle_win32 (usb_dev_handle *udh);
+  virtual ~fusb_devhandle_win32 ();
+
+  // MANIPULATORS
+  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p,
+                                       int block_size = 0, int nblocks = 0);
+};
+
+
+/*!
+ * \brief win32 implementation of fusb_ephandle using libusb-win32
+ */
+class fusb_ephandle_win32 : public fusb_ephandle
+{
+private:
+  fusb_devhandle_win32 *d_devhandle;
+
+  unsigned d_curr;
+  unsigned d_outstanding_write;
+  int d_output_short;
+  int d_input_leftover;
+  void ** d_context;
+  char * d_buffer;
+
+public:
+  // CREATORS
+  fusb_ephandle_win32 (fusb_devhandle_win32 *dh, int endpoint, bool input_p,
+                        int block_size = 0, int nblocks = 0);
+  virtual ~fusb_ephandle_win32 ();
+
+  // MANIPULATORS
+
+  virtual bool start ();       //!< begin streaming i/o
+  virtual bool stop ();                //!< stop streaming i/o
+
+  /*!
+   * \returns \p nbytes if write was successfully enqueued, else -1.
+   * Will block if no free buffers available.
+   */
+  virtual int write (const void *buffer, int nbytes);
+
+  /*!
+   * \returns number of bytes read or -1 if error.
+   * number of bytes read will be <= nbytes.
+   * Will block if no input available.
+   */
+  virtual int read (void *buffer, int nbytes);
+
+  /*
+   * block until all outstanding writes have completed
+   */
+  virtual void wait_for_completion ();
+};
+
+#endif /* _FUSB_WIN32_H_ */
+
diff --git a/usrp/host/lib/legacy/gen_usrp_dbid.py b/usrp/host/lib/legacy/gen_usrp_dbid.py
new file mode 100755 (executable)
index 0000000..14d3ee5
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import os.path
+import re
+from optparse import OptionParser
+
+def write_header(f, comment_char):
+    f.write(comment_char); f.write('\n')
+    f.write(comment_char); f.write(' Machine generated by gen_usrp_dbid.py from usrp_dbid.dat\n')
+    f.write(comment_char); f.write(' Do not edit by hand.  All edits will be overwritten.\n')
+    f.write(comment_char); f.write('\n')
+    f.write('\n')
+
+def gen_dbid_py(r):
+    f = open('usrp_dbid.py', 'w')
+    comment_char = '#'
+    write_header(f, comment_char)
+    f.write(comment_char); f.write('\n')
+    f.write(comment_char); f.write(" USRP Daughterboard ID's\n")
+    f.write(comment_char); f.write('\n')
+    f.write('\n')
+    for x in r:
+        f.write('%-16s = %s\n' % (x[1], x[2]))
+
+def gen_dbid_h(r):
+    f = open('usrp_dbid.h', 'w')
+    comment_char = '//'
+    write_header(f, comment_char)
+    f.write(comment_char); f.write('\n')
+    f.write(comment_char); f.write(" USRP Daughterboard ID's\n")
+    f.write(comment_char); f.write('\n')
+    f.write('\n')
+    f.write('#ifndef INCLUDED_USRP_DBID_H\n')
+    f.write('#define INCLUDED_USRP_DBID_H\n')
+    f.write('\n')
+    for x in r:
+        f.write('#define %-25s %s\n' % ('USRP_DBID_' + x[1], x[2]))
+    f.write('\n')
+    f.write('#endif /* INCLUDED_USRP_DBID_H */\n')
+
+def gen_dbid_cc(r):
+    f = open('usrp_dbid.cc', 'w')
+    write_header(f, '//')
+    head = '''/*
+ * Copyright 2005 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <usrp_prims.h>
+#include <usrp_dbid.h>
+#include <stdio.h>
+
+#define NELEM(x) sizeof(x)/sizeof(x[0])
+
+static struct {
+  unsigned short       dbid;
+  const char          *name;
+} dbid_map[] = {
+'''
+    
+    tail = '''};
+
+const std::string
+usrp_dbid_to_string (int dbid)
+{
+  if (dbid == -1)
+    return "<none>";
+
+  if (dbid == -2)
+    return "<invalid EEPROM contents>";
+
+  for (unsigned i = 0; i < NELEM (dbid_map); i++)
+    if (dbid == dbid_map[i].dbid)
+      return dbid_map[i].name;
+
+  char tmp[64];
+  snprintf (tmp, sizeof (tmp), "Unknown (0x%04x)", dbid);
+  return tmp;
+}
+'''
+    f.write(head)
+    for x in r:
+        f.write('  { %-27s "%s" },\n' % (
+            'USRP_DBID_' + x[1] + ',', x[0]))
+    f.write(tail)
+
+def gen_all(src_filename):
+    src_file = open(src_filename, 'r')
+    r = []
+    for line in src_file:
+        line = line.strip()
+        line = re.sub(r'\s*#.*$','', line)
+        if len(line) == 0:
+            continue
+        mo = re.match('"([^"]+)"\s*(0x[0-9a-fA-F]+)', line)
+        if mo:
+            str_name = mo.group(1)
+            id_name = str_name.upper().replace(' ', '_')
+            id_val = mo.group(2)
+            r.append((str_name, id_name, id_val))
+            #sys.stdout.write('%-16s\t%-16s\t%s\n' % ('"'+str_name+'"', id_name, id_val))
+
+    gen_dbid_h(r)
+    gen_dbid_py(r)
+    gen_dbid_cc(r)
+    
+
+def main():
+    usage = "usage: %prog [options] usrp_dbid.dat"
+    parser = OptionParser(usage=usage)
+    (options, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.print_help()
+        sys.exit(1)
+
+    gen_all(args[0])
+
+if __name__ == '__main__':
+    main()
diff --git a/usrp/host/lib/legacy/md5.c b/usrp/host/lib/legacy/md5.c
new file mode 100644 (file)
index 0000000..abee067
--- /dev/null
@@ -0,0 +1,452 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995, 1996, 2001, 2003 Free Software Foundation, Inc.
+   NOTE: The canonical source of this file is maintained with the GNU C
+   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "md5.h"
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+// #include "unlocked-io.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+/* We need to keep the namespace clean so define the MD5 function
+   protected using leading __ .  */
+# define md5_init_ctx __md5_init_ctx
+# define md5_process_block __md5_process_block
+# define md5_process_bytes __md5_process_bytes
+# define md5_finish_ctx __md5_finish_ctx
+# define md5_read_ctx __md5_read_ctx
+# define md5_stream __md5_stream
+# define md5_buffer __md5_buffer
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)                                                       \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+#define BLOCKSIZE 4096
+/* Ensure that BLOCKSIZE is a multiple of 64.  */
+#if BLOCKSIZE % 64 != 0
+/* FIXME-someday (soon?): use #error instead of this kludge.  */
+"invalid BLOCKSIZE"
+#endif
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (struct md5_ctx *ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+                                                       (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (FILE *stream, void *resblock)
+{
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+        computation function processes the whole buffer so that with the
+        next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      while (1)
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+
+         if (sum == BLOCKSIZE)
+           break;
+
+         if (n == 0)
+           {
+             /* Check for the error flag IFF N == 0, so that we don't
+                exit the loop after a partial read due to e.g., EAGAIN
+                or EWOULDBLOCK.  */
+             if (ferror (stream))
+               return 1;
+             goto process_partial_block;
+           }
+
+         /* We've read at least one byte, so ignore errors.  But always
+            check for EOF, since feof may be true even though N > 0.
+            Otherwise, we could end up calling fread after EOF.  */
+         if (feof (stream))
+           goto process_partial_block;
+       }
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+                       BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+ process_partial_block:;
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md5_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
+# else
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         md5_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         md5_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+        the next context is computed.  Because the algorithms processing
+        unit is a 32-bit word and it is determined to work on words in
+        little endian byte order we perhaps have to change the byte order
+        before the computation.  To reduce the work for the next steps
+        we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
+         ++words;                                                      \
+         a = rol (a, s);                                               \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+      /* Before we start, one word to the strange constants.
+        They are defined in RFC 1321 as
+
+        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or
+        perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}'
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, 0xd76aa478);
+      OP (D, A, B, C, 12, 0xe8c7b756);
+      OP (C, D, A, B, 17, 0x242070db);
+      OP (B, C, D, A, 22, 0xc1bdceee);
+      OP (A, B, C, D,  7, 0xf57c0faf);
+      OP (D, A, B, C, 12, 0x4787c62a);
+      OP (C, D, A, B, 17, 0xa8304613);
+      OP (B, C, D, A, 22, 0xfd469501);
+      OP (A, B, C, D,  7, 0x698098d8);
+      OP (D, A, B, C, 12, 0x8b44f7af);
+      OP (C, D, A, B, 17, 0xffff5bb1);
+      OP (B, C, D, A, 22, 0x895cd7be);
+      OP (A, B, C, D,  7, 0x6b901122);
+      OP (D, A, B, C, 12, 0xfd987193);
+      OP (C, D, A, B, 17, 0xa679438e);
+      OP (B, C, D, A, 22, 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+        in CORRECT_WORDS.  Redefine the macro to take an additional first
+        argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)                                     \
+      do                                                               \
+       {                                                               \
+         a += f (b, c, d) + correct_words[k] + T;                      \
+         a = rol (a, s);                                               \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+      /* Round 2.  */
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+      OP (FG, D, A, B, C, 10,  9, 0x02441453);
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+      /* Round 3.  */
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+      /* Round 4.  */
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
diff --git a/usrp/host/lib/legacy/md5.h b/usrp/host/lib/legacy/md5.h
new file mode 100644 (file)
index 0000000..709cefb
--- /dev/null
@@ -0,0 +1,129 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+   computing library functions.
+   Copyright (C) 1995, 1996, 1999, 2000, 2003 Free Software Foundation, Inc.
+   NOTE: The canonical source of this file is maintained with the GNU C
+   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.  */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+#include <limits.h>
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   doing that would require that the configure script compile and *run*
+   the resulting executable.  Locally running cross-compiled executables
+   is usually not possible.  */
+
+#ifdef _LIBC
+# include <stdint.h>
+typedef uint32_t md5_uint32;
+typedef uintptr_t md5_uintptr;
+#else
+# define UINT_MAX_32_BITS 4294967295U
+
+# if UINT_MAX == UINT_MAX_32_BITS
+   typedef unsigned int md5_uint32;
+# else
+#  if USHRT_MAX == UINT_MAX_32_BITS
+    typedef unsigned short md5_uint32;
+#  else
+#   if ULONG_MAX == UINT_MAX_32_BITS
+     typedef unsigned long md5_uint32;
+#   else
+     /* The following line is intended to evoke an error.
+        Using #error is not portable enough.  */
+     "Cannot determine unsigned 32-bit data type."
+#   endif
+#  endif
+# endif
+/* We have to make a guess about the integer type equivalent in size
+   to pointers which should always be correct.  */
+typedef unsigned long int md5_uintptr;
+#endif
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void md5_init_ctx (struct md5_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block (const void *buffer, size_t len,
+                              struct md5_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md5_process_bytes (const void *buffer, size_t len,
+                              struct md5_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF be correctly
+   aligned for a 32 bits value.  */
+extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf);
+
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md5_stream (FILE *stream, void *resblock);
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *md5_buffer (const char *buffer, size_t len, void *resblock);
+
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+
+#endif
diff --git a/usrp/host/lib/legacy/mld_threads.h b/usrp/host/lib/legacy/mld_threads.h
new file mode 100644 (file)
index 0000000..08b3555
--- /dev/null
@@ -0,0 +1,257 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
+ * 
+ * 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _INCLUDED_MLD_THREADS_H_
+#define _INCLUDED_MLD_THREADS_H_
+
+/* classes which allow for either pthreads or omni_threads */
+
+#ifdef _USE_OMNI_THREADS_
+#include <gnuradio/omnithread.h>
+#else
+#include <pthread.h>
+#endif
+
+#include <stdexcept>
+
+#define __INLINE__ inline
+
+class mld_condition_t;
+
+class mld_mutex_t {
+#ifdef _USE_OMNI_THREADS_
+  typedef omni_mutex l_mutex, *l_mutex_ptr;
+#else
+  typedef pthread_mutex_t l_mutex, *l_mutex_ptr;
+#endif
+
+  friend class mld_condition_t;
+
+private:
+  l_mutex_ptr d_mutex;
+
+protected:
+  inline l_mutex_ptr mutex () { return (d_mutex); };
+
+public:
+  __INLINE__ mld_mutex_t () {
+#ifdef _USE_OMNI_THREADS_
+    d_mutex = new omni_mutex ();
+#else
+    d_mutex = (l_mutex_ptr) new l_mutex;
+    int l_ret = pthread_mutex_init (d_mutex, NULL);
+    if (l_ret != 0) {
+      fprintf (stderr, "Error %d creating mutex.\n", l_ret);
+      throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n");
+    }
+#endif
+  };
+
+  __INLINE__ ~mld_mutex_t () {
+    unlock ();
+#ifndef _USE_OMNI_THREADS_
+    int l_ret = pthread_mutex_destroy (d_mutex);
+    if (l_ret != 0) {
+      fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): "
+              "Error %d destroying mutex.\n", l_ret);
+    }
+#endif
+    delete d_mutex;
+    d_mutex = NULL;
+  };
+
+  __INLINE__ void lock () {
+#ifdef _USE_OMNI_THREADS_
+    d_mutex->lock ();
+#else
+    int l_ret = pthread_mutex_lock (d_mutex);
+    if (l_ret != 0) {
+      fprintf (stderr, "mld_mutex_t::lock(): "
+              "Error %d locking mutex.\n", l_ret);
+    }
+#endif
+  };
+
+  __INLINE__ void unlock () {
+#ifdef _USE_OMNI_THREADS_
+    d_mutex->unlock ();
+#else
+    int l_ret = pthread_mutex_unlock (d_mutex);
+    if (l_ret != 0) {
+      fprintf (stderr, "mld_mutex_t::unlock(): "
+              "Error %d locking mutex.\n", l_ret);
+    }
+#endif
+  };
+
+  __INLINE__ bool trylock () {
+#ifdef _USE_OMNI_THREADS_
+    int l_ret = d_mutex->trylock ();
+#else
+    int l_ret = pthread_mutex_unlock (d_mutex);
+#endif
+    return (l_ret == 0 ? true : false);
+  };
+
+  inline void acquire () { lock(); };
+  inline void release () { unlock(); };
+  inline void wait () { lock(); };
+  inline void post () { unlock(); };
+};
+
+typedef mld_mutex_t mld_mutex, *mld_mutex_ptr;
+
+class mld_condition_t {
+#ifdef _USE_OMNI_THREADS_
+  typedef omni_condition l_condition, *l_condition_ptr;
+#else
+  typedef pthread_cond_t l_condition, *l_condition_ptr;
+#endif
+
+private:
+  l_condition_ptr d_condition;
+  mld_mutex_ptr d_mutex;
+  bool d_waiting;
+
+public:
+  __INLINE__ mld_condition_t () {
+    d_waiting = false;
+    d_mutex = new mld_mutex ();
+#ifdef _USE_OMNI_THREADS_
+    d_condition = new omni_condition (d_mutex->mutex ());
+#else
+    d_condition = (l_condition_ptr) new l_condition;
+    int l_ret = pthread_cond_init (d_condition, NULL);
+    if (l_ret != 0) {
+      fprintf (stderr, "Error %d creating condition.\n", l_ret);
+      throw std::runtime_error ("mld_condition_t::mld_condition_t()\n");
+    }
+#endif
+  };
+
+  __INLINE__ ~mld_condition_t () {
+    signal ();
+#ifndef _USE_OMNI_THREADS_
+    int l_ret = pthread_cond_destroy (d_condition);
+    if (l_ret != 0) {
+      fprintf (stderr, "mld_condition_t::mld_condition_t(): "
+              "Error %d destroying condition.\n", l_ret);
+    }
+#endif
+    delete d_condition;
+    d_condition = NULL;
+    delete d_mutex;
+    d_mutex = NULL;
+  };
+
+  __INLINE__ void signal () {
+    if (d_waiting == true) {
+#ifdef _USE_OMNI_THREADS_
+      d_condition->signal ();
+#else
+      int l_ret = pthread_cond_signal (d_condition);
+      if (l_ret != 0) {
+       fprintf (stderr, "mld_condition_t::signal(): "
+                "Error %d.\n", l_ret);
+      }
+#endif
+      d_waiting = false;
+    }
+  };
+
+  __INLINE__ void wait () {
+    if (d_waiting == false) {
+      d_waiting = true;
+#ifdef _USE_OMNI_THREADS_
+      d_condition->wait ();
+#else
+      int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ());
+      if (l_ret != 0) {
+       fprintf (stderr, "mld_condition_t::wait(): "
+                "Error %d.\n", l_ret);
+      }
+#endif
+    }
+  };
+};
+
+typedef mld_condition_t mld_condition, *mld_condition_ptr;
+
+class mld_thread_t {
+#ifdef _USE_OMNI_THREADS_
+  typedef omni_thread l_thread, *l_thread_ptr;
+#else
+  typedef pthread_t l_thread, *l_thread_ptr;
+#endif
+
+private:
+#ifndef _USE_OMNI_THREADS_
+  l_thread d_thread;
+  void (*d_start_routine)(void*);
+  void *d_arg;
+#else
+  l_thread_ptr d_thread;
+#endif
+
+#ifndef _USE_OMNI_THREADS_
+  static void* local_start_routine (void *arg) {
+    mld_thread_t* This = (mld_thread_t*) arg;
+    (*(This->d_start_routine))(This->d_arg);
+    return (NULL);
+  };
+#endif
+
+public:
+  __INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) {
+#ifdef _USE_OMNI_THREADS_
+    d_thread = new omni_thread (start_routine, arg);
+    d_thread->start ();
+#else
+    d_start_routine = start_routine;
+    d_arg = arg;
+    int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this);
+    if (l_ret != 0) {
+      fprintf (stderr, "Error %d creating thread.\n", l_ret);
+      throw std::runtime_error ("mld_thread_t::mld_thread_t()\n");
+    }
+#endif
+  };
+
+  __INLINE__ ~mld_thread_t () {
+#ifdef _USE_OMNI_THREADS_
+//  delete d_thread;
+    d_thread = NULL;
+#else
+    int l_ret = pthread_detach (d_thread);
+    if (l_ret != 0) {
+      fprintf (stderr, "Error %d detaching thread.\n", l_ret);
+      throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n");
+    }
+#endif
+  };
+};
+
+typedef mld_thread_t mld_thread, *mld_thread_ptr;
+
+#endif /* _INCLUDED_MLD_THREADS_H_ */
diff --git a/usrp/host/lib/legacy/rate_to_regval.h b/usrp/host/lib/legacy/rate_to_regval.h
new file mode 100644 (file)
index 0000000..1ffdc0f
--- /dev/null
@@ -0,0 +1,97 @@
+  {   1, 0x00 },
+  {   2, 0x01 },
+  {   3, 0x02 },
+  {   4, 0x11 },
+  {   5, 0x04 },
+  {   6, 0x05 },
+  {   7, 0x06 },
+  {   8, 0x13 },
+  {   9, 0x08 },
+  {  10, 0x09 },
+  {  11, 0x0a },
+  {  12, 0x15 },
+  {  13, 0x0c },
+  {  14, 0x0d },
+  {  15, 0x0e },
+  {  16, 0x33 },
+  {  18, 0x18 },
+  {  20, 0x19 },
+  {  21, 0x26 },
+  {  22, 0x1a },
+  {  24, 0x35 },
+  {  25, 0x44 },
+  {  26, 0x1c },
+  {  27, 0x28 },
+  {  28, 0x1d },
+  {  30, 0x1e },
+  {  32, 0x37 },
+  {  33, 0x2a },
+  {  35, 0x46 },
+  {  36, 0x55 },
+  {  39, 0x2c },
+  {  40, 0x39 },
+  {  42, 0x56 },
+  {  44, 0x3a },
+  {  45, 0x2e },
+  {  48, 0x57 },
+  {  49, 0x66 },
+  {  50, 0x49 },
+  {  52, 0x3c },
+  {  54, 0x58 },
+  {  55, 0x4a },
+  {  56, 0x3d },
+  {  60, 0x59 },
+  {  63, 0x68 },
+  {  64, 0x77 },
+  {  65, 0x4c },
+  {  66, 0x5a },
+  {  70, 0x69 },
+  {  72, 0x5b },
+  {  75, 0x4e },
+  {  77, 0x6a },
+  {  78, 0x5c },
+  {  80, 0x79 },
+  {  81, 0x88 },
+  {  84, 0x5d },
+  {  88, 0x7a },
+  {  90, 0x5e },
+  {  91, 0x6c },
+  {  96, 0x7b },
+  {  98, 0x6d },
+  {  99, 0x8a },
+  { 100, 0x99 },
+  { 104, 0x7c },
+  { 105, 0x6e },
+  { 108, 0x8b },
+  { 110, 0x9a },
+  { 112, 0x7d },
+  { 117, 0x8c },
+  { 120, 0x9b },
+  { 121, 0xaa },
+  { 126, 0x8d },
+  { 128, 0x7f },
+  { 130, 0x9c },
+  { 132, 0xab },
+  { 135, 0x8e },
+  { 140, 0x9d },
+  { 143, 0xac },
+  { 144, 0xbb },
+  { 150, 0x9e },
+  { 154, 0xad },
+  { 156, 0xbc },
+  { 160, 0x9f },
+  { 165, 0xae },
+  { 168, 0xbd },
+  { 169, 0xcc },
+  { 176, 0xaf },
+  { 180, 0xbe },
+  { 182, 0xcd },
+  { 192, 0xbf },
+  { 195, 0xce },
+  { 196, 0xdd },
+  { 208, 0xcf },
+  { 210, 0xde },
+  { 224, 0xdf },
+  { 225, 0xee },
+  { 240, 0xef },
+  { 256, 0xff }
diff --git a/usrp/host/lib/legacy/std_paths.h.in b/usrp/host/lib/legacy/std_paths.h.in
new file mode 100644 (file)
index 0000000..22a8ecb
--- /dev/null
@@ -0,0 +1,27 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+static char *std_paths[] = {
+  "@prefix@/share/usrp",
+  "/usr/local/share/usrp",
+  0
+};
diff --git a/usrp/host/lib/legacy/usrp_basic.cc b/usrp/host/lib/legacy/usrp_basic.cc
new file mode 100644 (file)
index 0000000..2eef147
--- /dev/null
@@ -0,0 +1,1238 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "usrp_basic.h"
+#include "usrp_prims.h"
+#include "usrp_interfaces.h"
+#include "fpga_regs_common.h"
+#include "fusb.h"
+#include <usb.h>
+#include <stdexcept>
+#include <assert.h>
+#include <math.h>
+#include <ad9862.h>
+
+using namespace ad9862;
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+// These set the buffer size used for each end point using the fast
+// usb interface.  The kernel ends up locking down this much memory.
+
+static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size();
+static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size();
+static const int FUSB_NBLOCKS    = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE;
+
+
+static const double POLLING_INTERVAL = 0.1;    // seconds
+
+////////////////////////////////////////////////////////////////
+
+static struct usb_dev_handle *
+open_rx_interface (struct usb_device *dev)
+{
+  struct usb_dev_handle *udh = usrp_open_rx_interface (dev);
+  if (udh == 0){
+    fprintf (stderr, "usrp_basic_rx: can't open rx interface\n");
+    usb_strerror ();
+  }
+  return udh;
+}
+
+static struct usb_dev_handle *
+open_tx_interface (struct usb_device *dev)
+{
+  struct usb_dev_handle *udh = usrp_open_tx_interface (dev);
+  if (udh == 0){
+    fprintf (stderr, "usrp_basic_tx: can't open tx interface\n");
+    usb_strerror ();
+  }
+  return udh;
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+//                     usrp_basic
+//
+////////////////////////////////////////////////////////////////
+
+
+// Given:
+//   CLKIN = 64 MHz
+//   CLKSEL pin = high 
+//
+// These settings give us:
+//   CLKOUT1 = CLKIN = 64 MHz
+//   CLKOUT2 = CLKIN = 64 MHz
+//   ADC is clocked at  64 MHz
+//   DAC is clocked at 128 MHz
+
+static unsigned char common_regs[] = {
+  REG_GENERAL,         0,
+  REG_DLL,             (DLL_DISABLE_INTERNAL_XTAL_OSC
+                        | DLL_MULT_2X
+                        | DLL_FAST),
+  REG_CLKOUT,          CLKOUT2_EQ_DLL_OVER_2,
+  REG_AUX_ADC_CLK,     AUX_ADC_CLK_CLK_OVER_4
+};
+
+
+usrp_basic::usrp_basic (int which_board, 
+                       struct usb_dev_handle *
+                       open_interface (struct usb_device *dev),
+                       const std::string fpga_filename,
+                       const std::string firmware_filename)
+  : d_udh (0),
+    d_usb_data_rate (16000000),        // SWAG, see below
+    d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)),
+    d_verbose (false)
+{
+  /*
+   * SWAG: Scientific Wild Ass Guess.
+   *
+   * d_usb_data_rate is used only to determine how often to poll for over- and under-runs.
+   * We defualt it to 1/2  of our best case.  Classes derived from usrp_basic (e.g., 
+   * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the
+   * actual rate.  This doesn't change our throughput, that's determined by the signal
+   * processing code in the FPGA (which we know nothing about), and the system limits
+   * determined by libusb, fusb_*, and the underlying drivers.
+   */
+  memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows));
+
+  usrp_one_time_init ();
+
+  if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename))
+    throw std::runtime_error ("usrp_basic/usrp_load_standard_bits");
+
+  struct usb_device *dev = usrp_find_device (which_board);
+  if (dev == 0){
+    fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board);
+    throw std::runtime_error ("usrp_basic/usrp_find_device");
+  }
+
+  if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){
+    fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n");
+    throw std::runtime_error ("usrp_basic/bad_rev");
+  }
+
+  if ((d_udh = open_interface (dev)) == 0)
+    throw std::runtime_error ("usrp_basic/open_interface");
+
+  // initialize registers that are common to rx and tx
+
+  if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){
+    fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n");
+    throw std::runtime_error ("usrp_basic/init_9862");
+  }
+
+  _write_fpga_reg (FR_MODE, 0);                // ensure we're in normal mode
+  _write_fpga_reg (FR_DEBUG_EN, 0);    // disable debug outputs
+}
+
+usrp_basic::~usrp_basic ()
+{
+  if (d_udh)
+    usb_close (d_udh);
+}
+
+bool
+usrp_basic::start ()
+{
+  return true;         // nop
+}
+
+bool
+usrp_basic::stop ()
+{
+  return true;         // nop
+}
+
+void
+usrp_basic::set_usb_data_rate (int usb_data_rate)
+{
+  d_usb_data_rate = usb_data_rate;
+  d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL);
+}
+
+bool
+usrp_basic::write_aux_dac (int slot, int which_dac, int value)
+{
+  return usrp_write_aux_dac (d_udh, slot, which_dac, value);
+}
+
+bool
+usrp_basic::read_aux_adc (int slot, int which_adc, int *value)
+{
+  return usrp_read_aux_adc (d_udh, slot, which_adc, value);
+}
+
+int
+usrp_basic::read_aux_adc (int slot, int which_adc)
+{
+  int  value;
+  if (!read_aux_adc (slot, which_adc, &value))
+    return READ_FAILED;
+
+  return value;
+}
+
+bool
+usrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf)
+{
+  return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ());
+}
+
+std::string
+usrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len)
+{
+  if (len <= 0)
+    return "";
+
+  char buf[len];
+
+  if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len))
+    return "";
+
+  return std::string (buf, len);
+}
+
+bool
+usrp_basic::write_i2c (int i2c_addr, const std::string buf)
+{
+  return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ());
+}
+
+std::string
+usrp_basic::read_i2c (int i2c_addr, int len)
+{
+  if (len <= 0)
+    return "";
+
+  char buf[len];
+
+  if (!usrp_i2c_read (d_udh, i2c_addr, buf, len))
+    return "";
+
+  return std::string (buf, len);
+}
+
+std::string
+usrp_basic::serial_number()
+{
+  return usrp_serial_number(d_udh);
+}
+
+// ----------------------------------------------------------------
+
+bool
+usrp_basic::set_adc_offset (int which, int offset)
+{
+  if (which < 0 || which > 3)
+    return false;
+
+  return _write_fpga_reg (FR_ADC_OFFSET_0 + which, offset);
+}
+
+bool
+usrp_basic::set_dac_offset (int which, int offset, int offset_pin)
+{
+  if (which < 0 || which > 3)
+    return false;
+
+  int which_codec = which >> 1;
+  int tx_a = (which & 0x1) == 0;
+  int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1);
+  int hi = (offset >> 2);
+  bool ok;
+
+  if (tx_a){
+    ok =  _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo);
+    ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi);
+  }
+  else {
+    ok =  _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo);
+    ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi);
+  }
+  return ok;
+}
+
+bool
+usrp_basic::set_adc_buffer_bypass (int which, bool bypass)
+{
+  if (which < 0 || which > 3)
+    return false;
+
+  int codec = which >> 1;
+  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
+
+  unsigned char cur_rx;
+  unsigned char cur_pwr_dn;
+
+  // If the input buffer is bypassed, we need to power it down too.
+
+  bool ok = _read_9862 (codec, reg, &cur_rx);
+  ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn);
+  if (!ok)
+    return false;
+
+  if (bypass){
+    cur_rx |= RX_X_BYPASS_INPUT_BUFFER;
+    cur_pwr_dn |= ((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B;
+  }
+  else {
+    cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER;
+    cur_pwr_dn &= ~(((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B);
+  }
+
+  ok &= _write_9862 (codec, reg, cur_rx);
+  ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn);
+  return ok;
+}
+
+// ----------------------------------------------------------------
+
+bool
+usrp_basic::_write_fpga_reg (int regno, int value)
+{
+  if (d_verbose){
+    fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value);
+    fflush (stdout);
+  }
+
+  if (regno >= 0 && regno < MAX_REGS)
+    d_fpga_shadows[regno] = value;
+
+  return usrp_write_fpga_reg (d_udh, regno, value);
+}
+
+bool
+usrp_basic::_write_fpga_reg_masked (int regno, int value, int mask)
+{
+  //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE
+  //value is a 16 bits value and mask is a 16 bits mask
+  if (d_verbose){
+    fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask);
+    fflush (stdout);
+  }
+
+  if (regno >= 0 && regno < MAX_REGS)
+    d_fpga_shadows[regno] = value;
+
+  return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16));
+}
+
+
+bool
+usrp_basic::_read_fpga_reg (int regno, int *value)
+{
+  return usrp_read_fpga_reg (d_udh, regno, value);
+}
+
+int
+usrp_basic::_read_fpga_reg (int regno)
+{
+  int value;
+  if (!_read_fpga_reg (regno, &value))
+    return READ_FAILED;
+  return value;
+}
+
+bool
+usrp_basic::_write_9862 (int which_codec, int regno, unsigned char value)
+{
+  if (0 && d_verbose){
+    // FIXME really want to enable logging in usrp_prims:usrp_9862_write
+    fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value);
+    fflush(stdout);
+  }
+
+  return usrp_9862_write (d_udh, which_codec, regno, value);
+}
+
+
+bool
+usrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const
+{
+  return usrp_9862_read (d_udh, which_codec, regno, value);
+}
+
+int
+usrp_basic::_read_9862 (int which_codec, int regno) const
+{
+  unsigned char value;
+  if (!_read_9862 (which_codec, regno, &value))
+    return READ_FAILED;
+  return value;
+}
+
+bool
+usrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf)
+{
+  return usrp_spi_write (d_udh, optional_header, enables, format,
+                        buf.data(), buf.size());
+}
+
+std::string
+usrp_basic::_read_spi (int optional_header, int enables, int format, int len)
+{
+  if (len <= 0)
+    return "";
+  
+  char buf[len];
+
+  if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len))
+    return "";
+
+  return std::string (buf, len);
+}
+
+
+bool
+usrp_basic::_set_led (int which, bool on)
+{
+  return usrp_set_led (d_udh, which, on);
+}
+
+////////////////////////////////////////////////////////////////
+//
+//                        usrp_basic_rx
+//
+////////////////////////////////////////////////////////////////
+
+static unsigned char rx_init_regs[] = {
+  REG_RX_PWR_DN,       0,
+  REG_RX_A,            0,      // minimum gain = 0x00 (max gain = 0x14)
+  REG_RX_B,            0,      // minimum gain = 0x00 (max gain = 0x14)
+  REG_RX_MISC,         (RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY),
+  REG_RX_IF,           (RX_IF_USE_CLKOUT1
+                        | RX_IF_2S_COMP),
+  REG_RX_DIGITAL,      (RX_DIGITAL_2_CHAN)
+};
+
+
+usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nblocks,
+                             const std::string fpga_filename,
+                             const std::string firmware_filename
+                             )
+  : usrp_basic (which_board, open_rx_interface, fpga_filename, firmware_filename),
+    d_devhandle (0), d_ephandle (0),
+    d_bytes_seen (0), d_first_read (true),
+    d_rx_enable (false)
+{
+  // initialize rx specific registers
+
+  if (!usrp_9862_write_many_all (d_udh, rx_init_regs, sizeof (rx_init_regs))){
+    fprintf (stderr, "usrp_basic_rx: failed to init AD9862 RX regs\n");
+    throw std::runtime_error ("usrp_basic_rx/init_9862");
+  }
+
+  if (0){
+    // FIXME power down 2nd codec rx path
+    usrp_9862_write (d_udh, 1, REG_RX_PWR_DN, 0x1);    // power down everything
+  }
+
+  // Reset the rx path and leave it disabled.
+  set_rx_enable (false);
+  usrp_set_fpga_rx_reset (d_udh, true);
+  usrp_set_fpga_rx_reset (d_udh, false);
+
+  set_fpga_rx_sample_rate_divisor (2); // usually correct
+
+  set_dc_offset_cl_enable(0xf, 0xf);   // enable DC offset removal control loops
+
+  probe_rx_slots (false);
+
+  // check fusb buffering parameters
+
+  if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE)
+    throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size");
+
+  if (fusb_nblocks < 0)
+    throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks");
+  
+  if (fusb_block_size == 0)
+    fusb_block_size = FUSB_BLOCK_SIZE;
+
+  if (fusb_nblocks == 0)
+    fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
+
+  d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
+  d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true,
+                                          fusb_block_size, fusb_nblocks);
+
+  _write_fpga_reg(FR_ATR_MASK_1, 0);   // zero Rx side Auto Transmit/Receive regs
+  _write_fpga_reg(FR_ATR_TXVAL_1, 0);
+  _write_fpga_reg(FR_ATR_RXVAL_1, 0);
+  _write_fpga_reg(FR_ATR_MASK_3, 0);
+  _write_fpga_reg(FR_ATR_TXVAL_3, 0);
+  _write_fpga_reg(FR_ATR_RXVAL_3, 0);
+}
+
+static unsigned char rx_fini_regs[] = {
+  REG_RX_PWR_DN,       0x1                             // power down everything
+};
+
+usrp_basic_rx::~usrp_basic_rx ()
+{
+  if (!set_rx_enable (false)){
+    fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n");
+    usb_strerror ();
+  }
+
+  d_ephandle->stop ();
+  delete d_ephandle;
+  delete d_devhandle;
+
+  if (!usrp_9862_write_many_all (d_udh, rx_fini_regs, sizeof (rx_fini_regs))){
+    fprintf (stderr, "usrp_basic_rx: failed to fini AD9862 RX regs\n");
+  }
+}
+
+
+bool
+usrp_basic_rx::start ()
+{
+  if (!usrp_basic::start ())   // invoke parent's method
+    return false;
+
+  // fire off reads before asserting rx_enable
+
+  if (!d_ephandle->start ()){
+    fprintf (stderr, "usrp_basic_rx: failed to start end point streaming");
+    usb_strerror ();
+    return false;
+  }
+
+  if (!set_rx_enable (true)){
+    fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n");
+    usb_strerror ();
+    return false;
+  }
+  
+  return true;
+}
+
+bool
+usrp_basic_rx::stop ()
+{
+  bool ok = usrp_basic::stop();
+
+  if (!d_ephandle->stop()){
+    fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming");
+    usb_strerror ();
+    ok = false;
+  }
+  if (!set_rx_enable(false)){
+    fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n");
+    usb_strerror ();
+    ok = false;
+  }
+  return false;
+}
+
+usrp_basic_rx *
+usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks,
+                    const std::string fpga_filename,
+                    const std::string firmware_filename)
+{
+  usrp_basic_rx *u = 0;
+  
+  try {
+    u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
+                          fpga_filename, firmware_filename);
+    return u;
+  }
+  catch (...){
+    delete u;
+    return 0;
+  }
+
+  return u;
+}
+
+bool
+usrp_basic_rx::set_fpga_rx_sample_rate_divisor (unsigned int div)
+{
+  return _write_fpga_reg (FR_RX_SAMPLE_RATE_DIV, div - 1);
+}
+
+
+/*
+ * \brief read data from the D/A's via the FPGA.
+ * \p len must be a multiple of 512 bytes.
+ *
+ * \returns the number of bytes read, or -1 on error.
+ *
+ * If overrun is non-NULL it will be set true iff an RX overrun is detected.
+ */
+int
+usrp_basic_rx::read (void *buf, int len, bool *overrun)
+{
+  int  r;
+  
+  if (overrun)
+    *overrun = false;
+  
+  if (len < 0 || (len % 512) != 0){
+    fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len);
+    return -1;
+  }
+
+  r = d_ephandle->read (buf, len);
+  if (r > 0)
+    d_bytes_seen += r;
+
+  /*
+   * In many cases, the FPGA reports an rx overrun right after we
+   * enable the Rx path.  If this is our first read, check for the
+   * overrun to clear the condition, then ignore the result.
+   */
+  if (0 && d_first_read){      // FIXME
+    d_first_read = false;
+    bool bogus_overrun;
+    usrp_check_rx_overrun (d_udh, &bogus_overrun);
+  }
+
+  if (overrun != 0 && d_bytes_seen >= d_bytes_per_poll){
+    d_bytes_seen = 0;
+    if (!usrp_check_rx_overrun (d_udh, overrun)){
+      fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n");
+      usb_strerror ();
+    }
+  }
+    
+  return r;
+}
+
+bool
+usrp_basic_rx::set_rx_enable (bool on)
+{
+  d_rx_enable = on;
+  return usrp_set_fpga_rx_enable (d_udh, on);
+}
+
+// conditional disable, return prev state
+bool
+usrp_basic_rx::disable_rx ()
+{
+  bool enabled = rx_enable ();
+  if (enabled)
+    set_rx_enable (false);
+  return enabled;
+}
+
+// conditional set
+void
+usrp_basic_rx::restore_rx (bool on)
+{
+  if (on != rx_enable ())
+    set_rx_enable (on);
+}
+
+bool
+usrp_basic_rx::set_pga (int which, double gain)
+{
+  if (which < 0 || which > 3)
+    return false;
+
+  gain = std::max (pga_min (), gain);
+  gain = std::min (pga_max (), gain);
+
+  int codec = which >> 1;
+  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
+
+  // read current value to get input buffer bypass flag.
+  unsigned char cur_rx;
+  if (!_read_9862 (codec, reg, &cur_rx))
+    return false;
+
+  int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step());
+
+  cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f);
+  return _write_9862 (codec, reg, cur_rx);
+}
+
+double
+usrp_basic_rx::pga (int which) const
+{
+  if (which < 0 || which > 3)
+    return READ_FAILED;
+
+  int codec = which >> 1;
+  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
+  unsigned char v;
+  bool ok = _read_9862 (codec, reg, &v);
+  if (!ok)
+    return READ_FAILED;
+
+  return (pga_db_per_step() * (v & 0x1f)) + pga_min();
+}
+
+static int
+slot_id_to_oe_reg (int slot_id)
+{
+  static int reg[4]  = { FR_OE_0, FR_OE_1, FR_OE_2, FR_OE_3 };
+  assert (0 <= slot_id && slot_id < 4);
+  return reg[slot_id];
+}
+
+static int
+slot_id_to_io_reg (int slot_id)
+{
+  static int reg[4]  = { FR_IO_0, FR_IO_1, FR_IO_2, FR_IO_3 };
+  assert (0 <= slot_id && slot_id < 4);
+  return reg[slot_id];
+}
+
+void
+usrp_basic_rx::probe_rx_slots (bool verbose)
+{
+  struct usrp_dboard_eeprom    eeprom;
+  static int slot_id_map[2] = { SLOT_RX_A, SLOT_RX_B };
+  static const char *slot_name[2] = { "RX d'board A", "RX d'board B" };
+
+  for (int i = 0; i < 2; i++){
+    int slot_id = slot_id_map [i];
+    const char *msg = 0;
+    usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom);
+
+    switch (s){
+    case UDBE_OK:
+      d_dbid[i] = eeprom.id;
+      msg = usrp_dbid_to_string (eeprom.id).c_str ();
+      set_adc_offset (2*i+0, eeprom.offset[0]);
+      set_adc_offset (2*i+1, eeprom.offset[1]);
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_NO_EEPROM:
+      d_dbid[i] = -1;
+      msg = "<none>";
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_INVALID_EEPROM:
+      d_dbid[i] = -2;
+      msg = "Invalid EEPROM contents";
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_BAD_SLOT:
+    default:
+      assert (0);
+    }
+
+    if (verbose){
+      fflush (stdout);
+      fprintf (stderr, "%s: %s\n", slot_name[i], msg);
+    }
+  }
+}
+
+bool
+usrp_basic_rx::_write_oe (int which_dboard, int value, int mask)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)),
+                         (mask << 16) | (value & 0xffff));
+}
+
+bool
+usrp_basic_rx::write_io (int which_dboard, int value, int mask)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)),
+                         (mask << 16) | (value & 0xffff));
+}
+
+bool
+usrp_basic_rx::read_io (int which_dboard, int *value)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  int t;
+  int reg = which_dboard + 1;  // FIXME, *very* magic number (fix in serial_io.v)
+  bool ok = _read_fpga_reg (reg, &t);
+  if (!ok)
+    return false;
+
+  *value = (t >> 16) & 0xffff; // FIXME, more magic
+  return true;
+}
+
+int
+usrp_basic_rx::read_io (int which_dboard)
+{
+  int  value;
+  if (!read_io (which_dboard, &value))
+    return READ_FAILED;
+  return value;
+}
+
+bool
+usrp_basic_rx::write_aux_dac (int which_dboard, int which_dac, int value)
+{
+  return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard),
+                                   which_dac, value);
+}
+
+bool
+usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc, int *value)
+{
+  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard),
+                                  which_adc, value);
+}
+
+int
+usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc)
+{
+  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc);
+}
+
+int
+usrp_basic_rx::block_size () const { return d_ephandle->block_size(); }
+
+bool
+usrp_basic_rx::set_dc_offset_cl_enable(int bits, int mask)
+{
+  return _write_fpga_reg(FR_DC_OFFSET_CL_EN, 
+                        (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask));
+}
+
+////////////////////////////////////////////////////////////////
+//
+//                        usrp_basic_tx
+//
+////////////////////////////////////////////////////////////////
+
+
+//
+// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz
+// DAC input is latched on rising edge of CLKOUT2
+// NCO is disabled
+// interpolate 2x
+// coarse modulator disabled
+//
+
+static unsigned char tx_init_regs[] = {
+  REG_TX_PWR_DN,       0,
+  REG_TX_A_OFFSET_LO,  0,
+  REG_TX_A_OFFSET_HI,  0,
+  REG_TX_B_OFFSET_LO,  0,
+  REG_TX_B_OFFSET_HI,  0,
+  REG_TX_A_GAIN,       (TX_X_GAIN_COARSE_FULL | 0),
+  REG_TX_B_GAIN,       (TX_X_GAIN_COARSE_FULL | 0),
+  REG_TX_PGA,          0xff,                   // maximum gain (0 dB)
+  REG_TX_MISC,         0,
+  REG_TX_IF,           (TX_IF_USE_CLKOUT1
+                        | TX_IF_I_FIRST
+                        | TX_IF_INV_TX_SYNC
+                        | TX_IF_2S_COMP
+                        | TX_IF_INTERLEAVED),
+  REG_TX_DIGITAL,      (TX_DIGITAL_2_DATA_PATHS
+                        | TX_DIGITAL_INTERPOLATE_4X),
+  REG_TX_MODULATOR,    (TX_MODULATOR_DISABLE_NCO
+                        | TX_MODULATOR_COARSE_MODULATION_NONE),
+  REG_TX_NCO_FTW_7_0,  0,
+  REG_TX_NCO_FTW_15_8, 0,
+  REG_TX_NCO_FTW_23_16,        0
+};
+
+usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks,
+                             const std::string fpga_filename,
+                             const std::string firmware_filename)
+  : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename),
+    d_devhandle (0), d_ephandle (0),
+    d_bytes_seen (0), d_first_write (true),
+    d_tx_enable (false)
+{
+  if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){
+    fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n");
+    throw std::runtime_error ("usrp_basic_tx/init_9862");
+  }
+
+  if (0){
+    // FIXME power down 2nd codec tx path
+    usrp_9862_write (d_udh, 1, REG_TX_PWR_DN,
+                    (TX_PWR_DN_TX_DIGITAL
+                     | TX_PWR_DN_TX_ANALOG_BOTH));
+  }
+
+  // Reset the tx path and leave it disabled.
+  set_tx_enable (false);
+  usrp_set_fpga_tx_reset (d_udh, true);
+  usrp_set_fpga_tx_reset (d_udh, false);
+
+  set_fpga_tx_sample_rate_divisor (4); // we're using interp x4
+
+  probe_tx_slots (false);
+
+  // check fusb buffering parameters
+
+  if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE)
+    throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size");
+
+  if (fusb_nblocks < 0)
+    throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks");
+  
+  if (fusb_block_size == 0)
+    fusb_block_size = FUSB_BLOCK_SIZE;
+
+  if (fusb_nblocks == 0)
+    fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
+
+  d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
+  d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false,
+                                          fusb_block_size, fusb_nblocks);
+
+  _write_fpga_reg(FR_ATR_MASK_0, 0); // zero Tx side Auto Transmit/Receive regs
+  _write_fpga_reg(FR_ATR_TXVAL_0, 0);
+  _write_fpga_reg(FR_ATR_RXVAL_0, 0);
+  _write_fpga_reg(FR_ATR_MASK_2, 0);
+  _write_fpga_reg(FR_ATR_TXVAL_2, 0);
+  _write_fpga_reg(FR_ATR_RXVAL_2, 0);
+}
+
+
+static unsigned char tx_fini_regs[] = {
+  REG_TX_PWR_DN,       (TX_PWR_DN_TX_DIGITAL
+                        | TX_PWR_DN_TX_ANALOG_BOTH),
+  REG_TX_MODULATOR,    (TX_MODULATOR_DISABLE_NCO
+                        | TX_MODULATOR_COARSE_MODULATION_NONE)
+};
+
+usrp_basic_tx::~usrp_basic_tx ()
+{
+  d_ephandle->stop ();
+  delete d_ephandle;
+  delete d_devhandle;
+
+  if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){
+    fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n");
+  }
+}
+
+bool
+usrp_basic_tx::start ()
+{
+  if (!usrp_basic::start ())
+    return false;
+
+  if (!set_tx_enable (true)){
+    fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n");
+    usb_strerror ();
+    return false;
+  }
+  
+  if (!d_ephandle->start ()){
+    fprintf (stderr, "usrp_basic_tx: failed to start end point streaming");
+    usb_strerror ();
+    return false;
+  }
+
+  return true;
+}
+
+bool
+usrp_basic_tx::stop ()
+{
+  bool ok = usrp_basic::stop ();
+
+  if (!set_tx_enable (false)){
+    fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n");
+    usb_strerror ();
+    ok = false;
+  }
+  if (!d_ephandle->stop ()){
+    fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming");
+    usb_strerror ();
+    ok = false;
+  }
+  return ok;
+}
+
+usrp_basic_tx *
+usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks,
+                    const std::string fpga_filename,
+                    const std::string firmware_filename)
+{
+  usrp_basic_tx *u = 0;
+  
+  try {
+    u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks,
+                          fpga_filename, firmware_filename);
+    return u;
+  }
+  catch (...){
+    delete u;
+    return 0;
+  }
+
+  return u;
+}
+
+bool
+usrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div)
+{
+  return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1);
+}
+
+/*!
+ * \brief Write data to the A/D's via the FPGA.
+ *
+ * \p len must be a multiple of 512 bytes.
+ * \returns number of bytes written or -1 on error.
+ *
+ * if \p underrun is non-NULL, it will be set to true iff
+ * a transmit underrun condition is detected.
+ */
+int
+usrp_basic_tx::write (const void *buf, int len, bool *underrun)
+{
+  int  r;
+  
+  if (underrun)
+    *underrun = false;
+  
+  if (len < 0 || (len % 512) != 0){
+    fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len);
+    return -1;
+  }
+
+  r = d_ephandle->write (buf, len);
+  if (r > 0)
+    d_bytes_seen += r;
+    
+  /*
+   * In many cases, the FPGA reports an tx underrun right after we
+   * enable the Tx path.  If this is our first write, check for the
+   * underrun to clear the condition, then ignore the result.
+   */
+  if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){
+    d_first_write = false;
+    bool bogus_underrun;
+    usrp_check_tx_underrun (d_udh, &bogus_underrun);
+  }
+
+  if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){
+    d_bytes_seen = 0;
+    if (!usrp_check_tx_underrun (d_udh, underrun)){
+      fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n");
+      usb_strerror ();
+    }
+  }
+
+  return r;
+}
+
+void
+usrp_basic_tx::wait_for_completion ()
+{
+  d_ephandle->wait_for_completion ();
+}
+
+bool
+usrp_basic_tx::set_tx_enable (bool on)
+{
+  d_tx_enable = on;
+  // fprintf (stderr, "set_tx_enable %d\n", on);
+  return usrp_set_fpga_tx_enable (d_udh, on);
+}
+
+// conditional disable, return prev state
+bool
+usrp_basic_tx::disable_tx ()
+{
+  bool enabled = tx_enable ();
+  if (enabled)
+    set_tx_enable (false);
+  return enabled;
+}
+
+// conditional set
+void
+usrp_basic_tx::restore_tx (bool on)
+{
+  if (on != tx_enable ())
+    set_tx_enable (on);
+}
+
+bool
+usrp_basic_tx::set_pga (int which, double gain)
+{
+  if (which < 0 || which > 3)
+    return false;
+
+  gain = std::max (pga_min (), gain);
+  gain = std::min (pga_max (), gain);
+
+  int codec = which >> 1;      // 0 and 1 are same, as are 2 and 3
+
+  int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step());
+
+  return _write_9862 (codec, REG_TX_PGA, int_gain);
+}
+
+double
+usrp_basic_tx::pga (int which) const
+{
+  if (which < 0 || which > 3)
+    return READ_FAILED;
+
+  int codec = which >> 1;
+  unsigned char v;
+  bool ok = _read_9862 (codec, REG_TX_PGA, &v);
+  if (!ok)
+    return READ_FAILED;
+
+  return (pga_db_per_step() * v) + pga_min();
+}
+
+void
+usrp_basic_tx::probe_tx_slots (bool verbose)
+{
+  struct usrp_dboard_eeprom    eeprom;
+  static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B };
+  static const char *slot_name[2] = { "TX d'board A", "TX d'board B" };
+
+  for (int i = 0; i < 2; i++){
+    int slot_id = slot_id_map [i];
+    const char *msg = 0;
+    usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom);
+
+    switch (s){
+    case UDBE_OK:
+      d_dbid[i] = eeprom.id;
+      msg = usrp_dbid_to_string (eeprom.id).c_str ();
+      // FIXME, figure out interpretation of dc offset for TX d'boards
+      // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff);
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_NO_EEPROM:
+      d_dbid[i] = -1;
+      msg = "<none>";
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_INVALID_EEPROM:
+      d_dbid[i] = -2;
+      msg = "Invalid EEPROM contents";
+      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
+      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
+      break;
+      
+    case UDBE_BAD_SLOT:
+    default:
+      assert (0);
+    }
+
+    if (verbose){
+      fflush (stdout);
+      fprintf (stderr, "%s: %s\n", slot_name[i], msg);
+    }
+  }
+}
+
+bool
+usrp_basic_tx::_write_oe (int which_dboard, int value, int mask)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)),
+                         (mask << 16) | (value & 0xffff));
+}
+
+bool
+usrp_basic_tx::write_io (int which_dboard, int value, int mask)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)),
+                         (mask << 16) | (value & 0xffff));
+}
+
+bool
+usrp_basic_tx::read_io (int which_dboard, int *value)
+{
+  if (! (0 <= which_dboard && which_dboard <= 1))
+    return false;
+
+  int t;
+  int reg = which_dboard + 1;  // FIXME, *very* magic number (fix in serial_io.v)
+  bool ok = _read_fpga_reg (reg, &t);
+  if (!ok)
+    return false;
+
+  *value = t & 0xffff;         // FIXME, more magic
+  return true;
+}
+
+int
+usrp_basic_tx::read_io (int which_dboard)
+{
+  int  value;
+  if (!read_io (which_dboard, &value))
+    return READ_FAILED;
+  return value;
+}
+
+bool
+usrp_basic_tx::write_aux_dac (int which_dboard, int which_dac, int value)
+{
+  return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard),
+                                   which_dac, value);
+}
+
+bool
+usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc, int *value)
+{
+  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard),
+                                  which_adc, value);
+}
+
+int
+usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc)
+{
+  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc);
+}
+
+int
+usrp_basic_tx::block_size () const { return d_ephandle->block_size(); }
+
diff --git a/usrp/host/lib/legacy/usrp_basic.h b/usrp/host/lib/legacy/usrp_basic.h
new file mode 100644 (file)
index 0000000..796a0f4
--- /dev/null
@@ -0,0 +1,776 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * ----------------------------------------------------------------------
+ * Mid level interface to the Universal Software Radio Peripheral (Rev 1)
+ *
+ * These classes implement the basic functionality for talking to the
+ * USRP.  They try to be as independent of the signal processing code
+ * in FPGA as possible.  They implement access to the low level
+ * peripherals on the board, provide a common way for reading and
+ * writing registers in the FPGA, and provide the high speed interface
+ * to streaming data across the USB.
+ *
+ * It is expected that subclasses will be derived that provide
+ * access to the functionality to a particular FPGA configuration.
+ * ----------------------------------------------------------------------
+ */
+
+#ifndef INCLUDED_USRP_BASIC_H
+#define INCLUDED_USRP_BASIC_H
+
+#include <usrp_slots.h>
+#include <string>
+
+struct usb_dev_handle;
+class  fusb_devhandle;
+class  fusb_ephandle;
+
+/*!
+ * \brief base class for usrp operations
+ */
+class usrp_basic
+{
+private:
+  // NOT IMPLEMENTED
+  usrp_basic (const usrp_basic &rhs);                  // no copy constructor
+  usrp_basic &operator= (const usrp_basic &rhs);       // no assignment operator
+
+  
+protected:
+  struct usb_dev_handle        *d_udh;
+  int                   d_usb_data_rate;       // bytes/sec
+  int                   d_bytes_per_poll;      // how often to poll for overruns
+  bool                  d_verbose;
+
+  static const int      MAX_REGS = 128;
+  unsigned int          d_fpga_shadows[MAX_REGS];
+
+  usrp_basic (int which_board,
+             struct usb_dev_handle *open_interface (struct usb_device *dev),
+             const std::string fpga_filename = "",
+             const std::string firmware_filename = "");
+
+  /*!
+   * \brief advise usrp_basic of usb data rate (bytes/sec)
+   *
+   * N.B., this doesn't tweak any hardware.  Derived classes
+   * should call this to inform us of the data rate whenever it's
+   * first set or if it changes.
+   *
+   * \param usb_data_rate      bytes/sec
+   */
+  void set_usb_data_rate (int usb_data_rate);
+  
+  /*!
+   * \brief Write auxiliary digital to analog converter.
+   *
+   * \param slot       Which Tx or Rx slot to write.
+   *                   N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
+   *                   SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
+   * \param which_dac  [0,3] RX slots must use only 0 and 1.  TX slots must use only 2 and 3.
+   * \param value      [0,4095]
+   * \returns true iff successful
+   */
+  bool write_aux_dac (int slot, int which_dac, int value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param slot       2-bit slot number. E.g., SLOT_TX_A
+   * \param which_adc  [0,1]
+   * \param value      return 12-bit value [0,4095]
+   * \returns true iff successful
+   */
+  bool read_aux_adc (int slot, int which_adc, int *value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param slot       2-bit slot number. E.g., SLOT_TX_A
+   * \param which_adc  [0,1]
+   * \returns value in the range [0,4095] if successful, else READ_FAILED.
+   */
+  int read_aux_adc (int slot, int which_adc);
+
+public:
+  virtual ~usrp_basic ();
+
+  /*!
+   * \brief return frequency of master oscillator on USRP
+   */
+  long  fpga_master_clock_freq () const { return 64000000; }
+
+  /*!
+   * \returns usb data rate in bytes/sec
+   */
+  int usb_data_rate () const { return d_usb_data_rate; }
+
+  void set_verbose (bool on) { d_verbose = on; }
+
+  //! magic value used on alternate register read interfaces
+  static const int READ_FAILED = -99999;
+
+  /*!
+   * \brief Write EEPROM on motherboard or any daughterboard.
+   * \param i2c_addr           I2C bus address of EEPROM
+   * \param eeprom_offset      byte offset in EEPROM to begin writing
+   * \param buf                        the data to write
+   * \returns true iff sucessful
+   */
+  bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf);
+
+  /*!
+   * \brief Read EEPROM on motherboard or any daughterboard.
+   * \param i2c_addr           I2C bus address of EEPROM
+   * \param eeprom_offset      byte offset in EEPROM to begin reading
+   * \param len                        number of bytes to read
+   * \returns the data read if successful, else a zero length string.
+   */
+  std::string read_eeprom (int i2c_addr, int eeprom_offset, int len);
+
+  /*!
+   * \brief Write to I2C peripheral
+   * \param i2c_addr           I2C bus address (7-bits)
+   * \param buf                        the data to write
+   * \returns true iff successful
+   * Writes are limited to a maximum of of 64 bytes.
+   */
+  bool write_i2c (int i2c_addr, const std::string buf);
+
+  /*!
+   * \brief Read from I2C peripheral
+   * \param i2c_addr           I2C bus address (7-bits)
+   * \param len                        number of bytes to read
+   * \returns the data read if successful, else a zero length string.
+   * Reads are limited to a maximum of 64 bytes.
+   */
+  std::string read_i2c (int i2c_addr, int len);
+
+  /*!
+   * \brief Set ADC offset correction
+   * \param which      which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q...
+   * \param offset     16-bit value to subtract from raw ADC input.
+   */
+  bool set_adc_offset (int which, int offset);
+
+  /*!
+   * \brief Set DAC offset correction
+   * \param which      which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q...
+   * \param offset     10-bit offset value (ambiguous format:  See AD9862 datasheet).
+   * \param offset_pin 1-bit value.  If 0 offset applied to -ve differential pin;
+   *                                  If 1 offset applied to +ve differential pin.
+   */
+  bool set_dac_offset (int which, int offset, int offset_pin);
+
+  /*!
+   * \brief Control ADC input buffer
+   * \param which      which ADC[0,3]
+   * \param bypass     if non-zero, bypass input buffer and connect input
+   *                   directly to switched cap SHA input of RxPGA.
+   */
+  bool set_adc_buffer_bypass (int which, bool bypass);
+
+
+  /*!
+   * \brief return the usrp's serial number.
+   *
+   * \returns non-zero length string iff successful.
+   */
+  std::string serial_number();
+
+  // ----------------------------------------------------------------
+  // Low level implementation routines.
+  // You probably shouldn't be using these...
+  //
+
+  bool _set_led (int which, bool on);
+
+  /*!
+   * \brief Write FPGA register.
+   * \param regno      7-bit register number
+   * \param value      32-bit value
+   * \returns true iff successful
+   */
+  bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value
+
+  /*!
+   * \brief Read FPGA register.
+   * \param regno      7-bit register number
+   * \param value      32-bit value
+   * \returns true iff successful
+   */
+  bool _read_fpga_reg (int regno, int *value); //< 7-bit regno, 32-bit value
+
+  /*!
+   * \brief Read FPGA register.
+   * \param regno      7-bit register number
+   * \returns register value if successful, else READ_FAILED
+   */
+  int  _read_fpga_reg (int regno);
+
+
+  /*!
+   * \brief Write FPGA register with mask.
+   * \param regno      7-bit register number
+   * \param value      16-bit value
+   * \param mask       16-bit value
+   * \returns true if successful
+   * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE
+   */
+  bool _write_fpga_reg_masked (int regno, int value, int mask);
+
+  /*!
+   * \brief Write AD9862 register.
+   * \param which_codec 0 or 1
+   * \param regno      6-bit register number
+   * \param value      8-bit value
+   * \returns true iff successful
+   */
+  bool _write_9862 (int which_codec, int regno, unsigned char value);
+
+  /*!
+   * \brief Read AD9862 register.
+   * \param which_codec 0 or 1
+   * \param regno      6-bit register number
+   * \param value      8-bit value
+   * \returns true iff successful
+   */
+  bool _read_9862 (int which_codec, int regno, unsigned char *value) const;
+
+  /*!
+   * \brief Read AD9862 register.
+   * \param which_codec 0 or 1
+   * \param regno      6-bit register number
+   * \returns register value if successful, else READ_FAILED
+   */
+  int  _read_9862 (int which_codec, int regno) const;
+
+  /*!
+   * \brief Write data to SPI bus peripheral.
+   *
+   * \param optional_header    0,1 or 2 bytes to write before buf.
+   * \param enables            bitmask of peripherals to write. See usrp_spi_defs.h
+   * \param format             transaction format.  See usrp_spi_defs.h SPI_FMT_*
+   * \param buf                        the data to write
+   * \returns true iff successful
+   * Writes are limited to a maximum of 64 bytes.
+   *
+   * If \p format specifies that optional_header bytes are present, they are
+   * written to the peripheral immediately prior to writing \p buf.
+   */
+  bool _write_spi (int optional_header, int enables, int format, std::string buf);
+
+  /*
+   * \brief Read data from SPI bus peripheral.
+   *
+   * \param optional_header    0,1 or 2 bytes to write before buf.
+   * \param enables            bitmask of peripheral to read. See usrp_spi_defs.h
+   * \param format             transaction format.  See usrp_spi_defs.h SPI_FMT_*
+   * \param len                        number of bytes to read.  Must be in [0,64].
+   * \returns the data read if sucessful, else a zero length string.
+   *
+   * Reads are limited to a maximum of 64 bytes.
+   *
+   * If \p format specifies that optional_header bytes are present, they
+   * are written to the peripheral first.  Then \p len bytes are read from
+   * the peripheral and returned.
+   */
+  std::string _read_spi (int optional_header, int enables, int format, int len);
+
+  /*!
+   * \brief Start data transfers.
+   * Called in base class to derived class order.
+   */
+  bool start ();
+
+  /*!
+   * \brief Stop data transfers.
+   * Called in base class to derived class order.
+   */
+  bool stop ();
+};
+
+\f/*!
+ * \brief class for accessing the receive side of the USRP
+ */
+class usrp_basic_rx : public usrp_basic 
+{
+private:
+  fusb_devhandle       *d_devhandle;
+  fusb_ephandle                *d_ephandle;
+  int                   d_bytes_seen;          // how many bytes we've seen
+  bool                  d_first_read;
+  bool                  d_rx_enable;
+
+protected:
+  int                   d_dbid[2];             // Rx daughterboard ID's
+
+  /*!
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   */
+  usrp_basic_rx (int which_board,
+                int fusb_block_size=0,
+                int fusb_nblocks=0,
+                const std::string fpga_filename = "",
+                const std::string firmware_filename = ""
+                );  // throws if trouble
+
+  bool set_rx_enable (bool on);
+  bool rx_enable () const { return d_rx_enable; }
+
+  bool disable_rx ();          // conditional disable, return prev state
+  void restore_rx (bool on);   // conditional set
+
+  void probe_rx_slots (bool verbose);
+  int  dboard_to_slot (int dboard) { return (dboard << 1) | 1; }
+
+public:
+  ~usrp_basic_rx ();
+
+  /*!
+   * \brief invokes constructor, returns instance or 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   */
+  static usrp_basic_rx *make (int which_board,
+                             int fusb_block_size=0,
+                             int fusb_nblocks=0,
+                             const std::string fpga_filename = "",
+                             const std::string firmware_filename = ""
+                             );
+
+  // MANIPULATORS
+
+  /*!
+   * \brief tell the fpga the rate rx samples are coming from the A/D's
+   *
+   * div = fpga_master_clock_freq () / sample_rate
+   *
+   * sample_rate is determined by a myriad of registers
+   * in the 9862.  That's why you have to tell us, so
+   * we can tell the fpga.
+   */
+  bool set_fpga_rx_sample_rate_divisor (unsigned int div);
+
+  /*!
+   * \brief read data from the D/A's via the FPGA.
+   * \p len must be a multiple of 512 bytes.
+   *
+   * \returns the number of bytes read, or -1 on error.
+   *
+   * If overrun is non-NULL it will be set true iff an RX overrun is detected.
+   */
+  int read (void *buf, int len, bool *overrun);
+
+  // ACCESSORS
+
+  //! sampling rate of A/D converter
+  virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M
+  long adc_rate() const { return converter_rate(); }
+  long adc_freq() const { return converter_rate(); }   //!< deprecated method name
+
+  /*!
+   * \brief Return daughterboard ID for given Rx daughterboard slot [0,1].
+   *
+   * \param which_dboard       [0,1] which Rx daughterboard
+   *
+   * \return daughterboard id >= 0 if successful
+   * \return -1 if no daugherboard
+   * \return -2 if invalid EEPROM on daughterboard
+   */
+  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }
+
+  // ----------------------------------------------------------------
+  // routines for controlling the Programmable Gain Amplifier
+  /*!
+   * \brief Set Programmable Gain Amplifier (PGA)
+   *
+   * \param which      which A/D [0,3]
+   * \param gain_in_db gain value (linear in dB)
+   *
+   * gain is rounded to closest setting supported by hardware.
+   *
+   * \returns true iff sucessful.
+   *
+   * \sa pga_min(), pga_max(), pga_db_per_step()
+   */
+  bool set_pga (int which, double gain_in_db);
+
+  /*!
+   * \brief Return programmable gain amplifier gain setting in dB.
+   *
+   * \param which      which A/D [0,3]
+   */
+  double pga (int which) const;
+
+  /*!
+   * \brief Return minimum legal PGA gain in dB.
+   */
+  double pga_min () const { return 0.0; }
+
+  /*!
+   * \brief Return maximum legal PGA gain in dB.
+   */
+  double pga_max () const { return 20.0; }
+
+  /*!
+   * \brief Return hardware step size of PGA (linear in dB).
+   */
+  double pga_db_per_step () const { return 20.0 / 20; }
+
+  /*!
+   * \brief Write direction register (output enables) for pins that go to daughterboard.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              value to write into register
+   * \param mask               which bits of value to write into reg
+   *
+   * Each d'board has 16-bits of general purpose i/o.
+   * Setting the bit makes it an output from the FPGA to the d'board.
+   *
+   * This register is initialized based on a value stored in the
+   * d'board EEPROM.  In general, you shouldn't be using this routine
+   * without a very good reason.  Using this method incorrectly will
+   * kill your USRP motherboard and/or daughterboard.
+   */
+  bool _write_oe (int which_dboard, int value, int mask);
+
+  /*!
+   * \brief Write daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              value to write into register
+   * \param mask               which bits of value to write into reg
+   */
+  bool write_io (int which_dboard, int value, int mask);
+
+  /*!
+   * \brief Read daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              output
+   */
+  bool read_io (int which_dboard, int *value);
+
+  /*!
+   * \brief Read daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \returns register value if successful, else READ_FAILED
+   */
+  int read_io (int which_dboard);
+
+  /*!
+   * \brief Write auxiliary digital to analog converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   *                           N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
+   *                           SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
+   * \param which_dac          [2,3] TX slots must use only 2 and 3.
+   * \param value              [0,4095]
+   * \returns true iff successful
+   */
+  bool write_aux_dac (int which_board, int which_dac, int value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param which_adc          [0,1]
+   * \param value              return 12-bit value [0,4095]
+   * \returns true iff successful
+   */
+  bool read_aux_adc (int which_dboard, int which_adc, int *value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param which_adc          [0,1]
+   * \returns value in the range [0,4095] if successful, else READ_FAILED.
+   */
+  int read_aux_adc (int which_dboard, int which_adc);
+
+  /*!
+   * \brief returns current fusb block size
+   */
+  int block_size() const;
+
+  /*!
+   * \brief Enable/disable automatic DC offset removal control loop in FPGA
+   *
+   * \param bits  which control loops to enable
+   * \param mask  which \p bits to pay attention to
+   *
+   * If the corresponding bit is set, enable the automatic DC
+   * offset correction control loop.
+   *
+   * <pre>
+   * The 4 low bits are significant:
+   *
+   *   ADC0 = (1 << 0)
+   *   ADC1 = (1 << 1)
+   *   ADC2 = (1 << 2)
+   *   ADC3 = (1 << 3)
+   * </pre>
+   *
+   * By default the control loop is enabled on all ADC's.
+   */
+  bool set_dc_offset_cl_enable(int bits, int mask);
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+\f/*!
+ * \brief class for accessing the transmit side of the USRP
+ */
+class usrp_basic_tx : public usrp_basic 
+{
+private:
+  fusb_devhandle       *d_devhandle;
+  fusb_ephandle                *d_ephandle;
+  int                   d_bytes_seen;          // how many bytes we've seen
+  bool                  d_first_write;
+  bool                  d_tx_enable;
+
+ protected:
+  int                   d_dbid[2];             // Tx daughterboard ID's
+
+  /*!
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512.
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default.
+   */
+  usrp_basic_tx (int which_board,
+                int fusb_block_size=0,
+                int fusb_nblocks=0,
+                const std::string fpga_filename = "",
+                const std::string firmware_filename = ""
+                );             // throws if trouble
+
+  bool set_tx_enable (bool on);
+  bool tx_enable () const { return d_tx_enable; }
+
+  bool disable_tx ();          // conditional disable, return prev state
+  void restore_tx (bool on);   // conditional set
+
+  void probe_tx_slots (bool verbose);
+  int  dboard_to_slot (int dboard) { return (dboard << 1) | 0; }
+
+public:
+
+  ~usrp_basic_tx ();
+
+  /*!
+   * \brief invokes constructor, returns instance or 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   */
+  static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0,
+                             const std::string fpga_filename = "",
+                             const std::string firmware_filename = ""
+                             );
+
+  // MANIPULATORS
+
+  /*!
+   * \brief tell the fpga the rate tx samples are going to the D/A's
+   *
+   * div = fpga_master_clock_freq () * 2
+   *
+   * sample_rate is determined by a myriad of registers
+   * in the 9862.  That's why you have to tell us, so
+   * we can tell the fpga.
+   */
+  bool set_fpga_tx_sample_rate_divisor (unsigned int div);
+
+  /*!
+   * \brief Write data to the A/D's via the FPGA.
+   *
+   * \p len must be a multiple of 512 bytes.
+   * \returns number of bytes written or -1 on error.
+   *
+   * if \p underrun is non-NULL, it will be set to true iff
+   * a transmit underrun condition is detected.
+   */
+  int write (const void *buf, int len, bool *underrun);
+
+  /*
+   * Block until all outstanding writes have completed.
+   * This is typically used to assist with benchmarking
+   */
+  void wait_for_completion ();
+
+  // ACCESSORS
+
+  //! sampling rate of D/A converter
+  virtual long converter_rate() const { return fpga_master_clock_freq () * 2; } // 128M
+  long dac_rate() const { return converter_rate(); }
+  long dac_freq() const { return converter_rate(); }   //!< deprecated method name
+
+  /*!
+   * \brief Return daughterboard ID for given Tx daughterboard slot [0,1].
+   *
+   * \return daughterboard id >= 0 if successful
+   * \return -1 if no daugherboard
+   * \return -2 if invalid EEPROM on daughterboard
+   */
+  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }
+
+  // ----------------------------------------------------------------
+  // routines for controlling the Programmable Gain Amplifier
+  /*!
+   * \brief Set Programmable Gain Amplifier (PGA)
+   *
+   * \param which      which D/A [0,3]
+   * \param gain_in_db gain value (linear in dB)
+   *
+   * gain is rounded to closest setting supported by hardware.
+   * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3.
+   * Setting DAC 0 affects DAC 1 and vice versa.  Same with DAC 2 and DAC 3.
+   *
+   * \returns true iff sucessful.
+   *
+   * \sa pga_min(), pga_max(), pga_db_per_step()
+   */
+  bool set_pga (int which, double gain_in_db);
+
+  /*!
+   * \brief Return programmable gain amplifier gain in dB.
+   *
+   * \param which      which D/A [0,3]
+   */
+  double pga (int which) const;
+
+  /*!
+   * \brief Return minimum legal PGA gain in dB.
+   */
+  double pga_min () const { return -20.0; }
+
+  /*!
+   * \brief Return maximum legal PGA gain in dB.
+   */
+  double pga_max () const { return 0.0; }
+
+  /*!
+   * \brief Return hardware step size of PGA (linear in dB).
+   */
+  double pga_db_per_step () const { return 20.0/255; }
+
+  /*!
+   * \brief Write direction register (output enables) for pins that go to daughterboard.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              value to write into register
+   * \param mask               which bits of value to write into reg
+   *
+   * Each d'board has 16-bits of general purpose i/o.
+   * Setting the bit makes it an output from the FPGA to the d'board.
+   *
+   * This register is initialized based on a value stored in the
+   * d'board EEPROM.  In general, you shouldn't be using this routine
+   * without a very good reason.  Using this method incorrectly will
+   * kill your USRP motherboard and/or daughterboard.
+   */
+  bool _write_oe (int which_dboard, int value, int mask);
+
+  /*!
+   * \brief Write daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              value to write into register
+   * \param mask               which bits of value to write into reg
+   */
+  bool write_io (int which_dboard, int value, int mask);
+
+  /*!
+   * \brief Read daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param value              return value
+   */
+  bool read_io (int which_dboard, int *value);
+
+  /*!
+   * \brief Read daughterboard i/o pin value
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \returns register value if successful, else READ_FAILED
+   */
+  int read_io (int which_dboard);
+
+  /*!
+   * \brief Write auxiliary digital to analog converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   *                           N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
+   *                           SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
+   * \param which_dac          [2,3] TX slots must use only 2 and 3.
+   * \param value              [0,4095]
+   * \returns true iff successful
+   */
+  bool write_aux_dac (int which_board, int which_dac, int value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param which_adc          [0,1]
+   * \param value              return 12-bit value [0,4095]
+   * \returns true iff successful
+   */
+  bool read_aux_adc (int which_dboard, int which_adc, int *value);
+
+  /*!
+   * \brief Read auxiliary analog to digital converter.
+   *
+   * \param which_dboard       [0,1] which d'board
+   * \param which_adc          [0,1]
+   * \returns value in the range [0,4095] if successful, else READ_FAILED.
+   */
+  int read_aux_adc (int which_dboard, int which_adc);
+
+  /*!
+   * \brief returns current fusb block size
+   */
+  int block_size() const;
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+#endif
diff --git a/usrp/host/lib/legacy/usrp_bytesex.h b/usrp/host/lib/legacy/usrp_bytesex.h
new file mode 100644 (file)
index 0000000..6c4e129
--- /dev/null
@@ -0,0 +1,105 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_USRP_BYTESEX_H
+#define INCLUDED_USRP_BYTESEX_H
+
+/*!
+ * \brief routines for convertering between host and usrp byte order
+ *
+ * Prior to including this file, the user must include "config.h"
+ * which will or won't define WORDS_BIGENDIAN based on the
+ * result of the AC_C_BIGENDIAN autoconf test.
+ */
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+static inline unsigned short int
+bswap_16 (unsigned short int x)
+{
+  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)
+{
+  return bswap_16 (x);
+}
+
+static inline short int
+usrp_to_host_short (short int x)
+{
+  return bswap_16 (x);
+}
+
+#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)
+{
+  return x;
+}
+
+static inline short int
+usrp_to_host_short (unsigned short int x)
+{
+  return x;
+}
+
+#endif
+
+#endif /* INCLUDED_USRP_BYTESEX_H */
diff --git a/usrp/host/lib/legacy/usrp_config.cc b/usrp/host/lib/legacy/usrp_config.cc
new file mode 100644 (file)
index 0000000..17bfd48
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_config.h"
+
+int
+usrp_rx_config_stream_count (unsigned int usrp_rx_config)
+{
+  return 1;
+}
+
+int
+usrp_tx_config_stream_count (unsigned int usrp_tx_config)
+{
+  return 1;
+}
diff --git a/usrp/host/lib/legacy/usrp_config.h b/usrp/host/lib/legacy/usrp_config.h
new file mode 100644 (file)
index 0000000..91b398b
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _USRP_CONFIG_H_
+#define _USRP_CONFIG_H_
+
+/*
+ * ----------------------------------------------------------------
+ * USRP Rx configurations.
+ *
+ * For now this is a placeholder, but will eventually specify the
+ * mapping from A/D outputs to DDC inputs (I & Q).
+ *
+ * What's implemented today is a single DDC that has its I input
+ * connected to ADC0 and its Q input connected to ADC1
+ * ----------------------------------------------------------------
+ */
+
+#define        USRP_RX_CONFIG_DEFAULT  0
+
+/*!
+ * given a usrp_rx_config word, return the number of I & Q streams that
+ * are interleaved on the USB.
+ */
+
+int usrp_rx_config_stream_count (unsigned int usrp_rx_config);
+
+/*
+ * USRP Tx configurations.
+ *
+ * For now this is a placeholder, but will eventually specify the
+ * mapping from DUC outputs to D/A inputs.
+ *
+ * What's implemented today is a single DUC that has its I output
+ * connected to DAC0 and its Q output connected to DAC1
+ */
+
+#define        USRP_TX_CONFIG_DEFAULT  0
+
+/*!
+ * given a usrp_tx_config word, return the number of I & Q streams that
+ * are interleaved on the USB.
+ */
+
+int usrp_tx_config_stream_count (unsigned int usrp_tx_config);
+
+
+#endif /* _USRP_CONFIG_H_ */
diff --git a/usrp/host/lib/legacy/usrp_dbid.dat b/usrp/host/lib/legacy/usrp_dbid.dat
new file mode 100644 (file)
index 0000000..a85d053
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright 2005 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+# This file is used to generate usrp_dbid.h, usrp_dbid.cc and usrp_dbid.py
+
+"Basic Tx"             0x0000
+"Basic Rx"             0x0001
+"DBS Rx"               0x0002
+"TV Rx"                        0x0003
+
+"Flex 400 Rx"          0x0004
+"Flex 900 Rx"          0x0005
+"Flex 1200 Rx"         0x0006
+"Flex 2400 Rx"         0x0007
+
+"Flex 400 Tx"          0x0008
+"Flex 900 Tx"          0x0009
+"Flex 1200 Tx"         0x000a
+"Flex 2400 Tx"         0x000b
+
+"TV Rx Rev 2"          0x000c
+"DBS Rx Rev 2_1"       0x000d
+
+"LF Tx"                        0x000e
+"LF Rx"                        0x000f
+
+"Flex 400 Rx MIMO A"   0x0014
+"Flex 900 Rx MIMO A"   0x0015
+"Flex 1200 Rx MIMO A"  0x0016
+"Flex 2400 Rx MIMO A"  0x0017
+
+"Flex 400 Tx MIMO A"   0x0018
+"Flex 900 Tx MIMO A"   0x0019
+"Flex 1200 Tx MIMO A"  0x001a
+"Flex 2400 Tx MIMO A"  0x001b
+
+"Flex 400 Rx MIMO B"   0x0024
+"Flex 900 Rx MIMO B"   0x0025
+"Flex 1200 Rx MIMO B"  0x0026
+"Flex 2400 Rx MIMO B"  0x0027
+
+"Flex 400 Tx MIMO B"   0x0028
+"Flex 900 Tx MIMO B"   0x0029
+"Flex 1200 Tx MIMO B"  0x002a
+"Flex 2400 Tx MIMO B"  0x002b
+
+"Flex 1800 Rx"         0x0030
+"Flex 1800 Tx"         0x0031
+"Flex 1800 Rx MIMO A"  0x0032
+"Flex 1800 Tx MIMO A"  0x0033
+"Flex 1800 Rx MIMO B"  0x0034
+"Flex 1800 Tx MIMO B"  0x0035
+
+"TV Rx Rev 3"          0x0040
+
+"Experimental Tx"      0xfffe
+"Experimental Rx"      0xffff
diff --git a/usrp/host/lib/legacy/usrp_local_sighandler.cc b/usrp/host/lib/legacy/usrp_local_sighandler.cc
new file mode 100644 (file)
index 0000000..ab6c485
--- /dev/null
@@ -0,0 +1,190 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * This is actually the same as gr_local_signhandler, but with a different name.
+ * We don't have a common library to put this in, so...
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <usrp_local_sighandler.h>
+#include <stdexcept>
+#include <stdio.h>
+
+usrp_local_sighandler::usrp_local_sighandler (int signum,
+                                             void (*new_handler)(int))
+  : d_signum (signum)
+{
+#ifdef HAVE_SIGACTION
+  struct sigaction new_action;
+  memset (&new_action, 0, sizeof (new_action));
+
+  new_action.sa_handler = new_handler;
+  sigemptyset (&new_action.sa_mask);
+  new_action.sa_flags = 0;
+
+  if (sigaction (d_signum, &new_action, &d_old_action) < 0){
+    perror ("sigaction (install new)");
+    throw std::runtime_error ("sigaction");
+  }
+#endif
+}
+
+usrp_local_sighandler::~usrp_local_sighandler ()
+{
+#ifdef HAVE_SIGACTION
+  if (sigaction (d_signum, &d_old_action, 0) < 0){
+    perror ("sigaction (restore old)");
+    throw std::runtime_error ("sigaction");
+  }
+#endif
+}
+
+void
+usrp_local_sighandler::throw_signal(int signum) throw(usrp_signal)
+{
+  throw usrp_signal (signum);
+}
+
+/*
+ * Semi-hideous way to may a signal number into a signal name
+ */
+
+#define SIGNAME(x) case x: return #x
+
+std::string
+usrp_signal::name () const
+{
+  char tmp[128];
+
+  switch (signal ()){
+#ifdef SIGHUP
+    SIGNAME (SIGHUP);
+#endif
+#ifdef SIGINT
+    SIGNAME (SIGINT);
+#endif
+#ifdef SIGQUIT
+    SIGNAME (SIGQUIT);
+#endif
+#ifdef SIGILL
+    SIGNAME (SIGILL);
+#endif
+#ifdef SIGTRAP
+    SIGNAME (SIGTRAP);
+#endif
+#ifdef SIGABRT
+    SIGNAME (SIGABRT);
+#endif
+#ifdef SIGBUS
+    SIGNAME (SIGBUS);
+#endif
+#ifdef SIGFPE
+    SIGNAME (SIGFPE);
+#endif
+#ifdef SIGKILL
+    SIGNAME (SIGKILL);
+#endif
+#ifdef SIGUSR1
+    SIGNAME (SIGUSR1);
+#endif
+#ifdef SIGSEGV
+    SIGNAME (SIGSEGV);
+#endif
+#ifdef SIGUSR2
+    SIGNAME (SIGUSR2);
+#endif
+#ifdef SIGPIPE
+    SIGNAME (SIGPIPE);
+#endif
+#ifdef SIGALRM
+    SIGNAME (SIGALRM);
+#endif
+#ifdef SIGTERM
+    SIGNAME (SIGTERM);
+#endif
+#ifdef SIGSTKFLT
+    SIGNAME (SIGSTKFLT);
+#endif
+#ifdef SIGCHLD
+    SIGNAME (SIGCHLD);
+#endif
+#ifdef SIGCONT
+    SIGNAME (SIGCONT);
+#endif
+#ifdef SIGSTOP
+    SIGNAME (SIGSTOP);
+#endif
+#ifdef SIGTSTP
+    SIGNAME (SIGTSTP);
+#endif
+#ifdef SIGTTIN
+    SIGNAME (SIGTTIN);
+#endif
+#ifdef SIGTTOU
+    SIGNAME (SIGTTOU);
+#endif
+#ifdef SIGURG
+    SIGNAME (SIGURG);
+#endif
+#ifdef SIGXCPU
+    SIGNAME (SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+    SIGNAME (SIGXFSZ);
+#endif
+#ifdef SIGVTALRM
+    SIGNAME (SIGVTALRM);
+#endif
+#ifdef SIGPROF
+    SIGNAME (SIGPROF);
+#endif
+#ifdef SIGWINCH
+    SIGNAME (SIGWINCH);
+#endif
+#ifdef SIGIO
+    SIGNAME (SIGIO);
+#endif
+#ifdef SIGPWR
+    SIGNAME (SIGPWR);
+#endif
+#ifdef SIGSYS
+    SIGNAME (SIGSYS);
+#endif
+  default:
+#if defined (HAVE_SNPRINTF)
+#if defined (SIGRTMIN) && defined (SIGRTMAX) 
+    if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){
+      snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ());
+      return tmp;
+    }
+#endif
+    snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ());
+    return tmp;
+#else
+    return "Unknown signal";
+#endif
+  }
+}
diff --git a/usrp/host/lib/legacy/usrp_local_sighandler.h b/usrp/host/lib/legacy/usrp_local_sighandler.h
new file mode 100644 (file)
index 0000000..f1c00cd
--- /dev/null
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP_LOCAL_SIGHANDLER_H
+#define INCLUDED_USRP_LOCAL_SIGHANDLER_H
+
+#include <signal.h>
+#include <string>
+
+/*!
+ * \brief Representation of signal.
+ */
+class usrp_signal
+{
+  int  d_signum;
+public:
+  usrp_signal (int signum) : d_signum (signum) {}
+  int signal () const { return d_signum; }
+  std::string name () const;
+};
+
+
+/*!
+ * \brief Get and set signal handler.
+ *
+ * Constructor installs new handler, destructor reinstalls
+ * original value.
+ */
+class usrp_local_sighandler {
+  int                  d_signum;
+#ifdef HAVE_SIGACTION
+  struct sigaction     d_old_action;
+#endif
+public:
+  usrp_local_sighandler (int signum, void (*new_handler)(int));
+  ~usrp_local_sighandler ();
+
+  /* throw usrp_signal (signum) */
+  static void throw_signal (int signum) throw (usrp_signal);
+};
+
+#endif /* INCLUDED_USRP_LOCAL_SIGHANDLER_H */
diff --git a/usrp/host/lib/legacy/usrp_prims.cc b/usrp/host/lib/legacy/usrp_prims.cc
new file mode 100644 (file)
index 0000000..f666a29
--- /dev/null
@@ -0,0 +1,1356 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004,2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "usrp_prims.h"
+#include "usrp_commands.h"
+#include "usrp_ids.h"
+#include "usrp_i2c_addr.h"
+#include "fpga_regs_common.h"
+#include "fpga_regs_standard.h"
+#include <usb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>              // FIXME should check with autoconf (nanosleep)
+#include <algorithm>
+#include <ad9862.h>
+#include <assert.h>
+
+extern "C" {
+#include "md5.h"
+};
+
+#define VERBOSE 0
+
+using namespace ad9862;
+
+static const int FIRMWARE_HASH_SLOT    = 0;
+static const int FPGA_HASH_SLOT        = 1;
+
+static const int hash_slot_addr[2] = {
+  USRP_HASH_SLOT_0_ADDR,
+  USRP_HASH_SLOT_1_ADDR
+};
+
+static char *default_firmware_filename = "std.ihx";
+static char *default_fpga_filename     = "std_2rxhb_2tx.rbf";
+
+#include "std_paths.h"
+
+static char *
+find_file (const char *filename, int hw_rev)
+{
+  char **sp = std_paths;
+  static char path[1000];
+  char *s;
+
+  s = getenv("USRP_PATH");
+  if (s) {
+    snprintf (path, sizeof (path), "%s/rev%d/%s", s, hw_rev, filename);
+    if (access (path, R_OK) == 0)
+      return path;
+  }
+
+  while (*sp){
+    snprintf (path, sizeof (path), "%s/rev%d/%s", *sp, hw_rev, filename);
+    if (access (path, R_OK) == 0)
+      return path;
+    sp++;
+  }
+  return 0;
+}
+
+static const char *
+get_proto_filename(const std::string user_filename, const char *env_var, const char *def)
+{
+  if (user_filename.length() != 0)
+    return user_filename.c_str();
+
+  char *s = getenv(env_var);
+  if (s && *s)
+    return s;
+
+  return def;
+}
+
+
+static void power_down_9862s (struct usb_dev_handle *udh);
+
+void
+usrp_one_time_init ()
+{
+  static bool first = true;
+
+  if (first){
+    first = false;
+    usb_init ();                       // usb library init
+    usb_find_busses ();
+    usb_find_devices ();
+  }
+}
+
+void
+usrp_rescan ()
+{
+  usb_find_busses ();
+  usb_find_devices ();
+}
+
+
+// ----------------------------------------------------------------
+// Danger, big, fragile KLUDGE.  The problem is that we want to be
+// able to get from a usb_dev_handle back to a usb_device, and the
+// right way to do this is buried in a non-installed include file.
+
+static struct usb_device *
+dev_handle_to_dev (usb_dev_handle *udh)
+{
+  struct usb_dev_handle_kludge {
+    int                         fd;
+    struct usb_bus     *bus;
+    struct usb_device  *device;
+  };
+
+  return ((struct usb_dev_handle_kludge *) udh)->device;
+}
+
+// ----------------------------------------------------------------
+
+/*
+ * q must be a real USRP, not an FX2.  Return its hardware rev number.
+ */
+int
+usrp_hw_rev (struct usb_device *q)
+{
+  return q->descriptor.bcdDevice & 0x00FF;
+}
+
+/*
+ * q must be a real USRP, not an FX2.  Return true if it's configured.
+ */
+static bool
+_usrp_configured_p (struct usb_device *q)
+{
+  return (q->descriptor.bcdDevice & 0xFF00) != 0;
+}
+
+bool
+usrp_usrp_p (struct usb_device *q)
+{
+  return (q->descriptor.idVendor == USB_VID_FSF
+         && q->descriptor.idProduct == USB_PID_FSF_USRP);
+}
+
+bool
+usrp_fx2_p (struct usb_device *q)
+{
+  return (q->descriptor.idVendor == USB_VID_CYPRESS
+         && q->descriptor.idProduct == USB_PID_CYPRESS_FX2);
+}
+
+bool
+usrp_usrp0_p (struct usb_device *q)
+{
+  return usrp_usrp_p (q) && usrp_hw_rev (q) == 0;
+}
+
+bool
+usrp_usrp1_p (struct usb_device *q)
+{
+  return usrp_usrp_p (q) && usrp_hw_rev (q) == 1;
+}
+
+bool
+usrp_usrp2_p (struct usb_device *q)
+{
+  return usrp_usrp_p (q) && usrp_hw_rev (q) == 2;
+}
+
+
+bool
+usrp_unconfigured_usrp_p (struct usb_device *q)
+{
+  return usrp_usrp_p (q) && !_usrp_configured_p (q);
+}
+
+bool
+usrp_configured_usrp_p (struct usb_device *q)
+{
+  return usrp_usrp_p (q) && _usrp_configured_p (q);
+}
+
+// ----------------------------------------------------------------
+
+struct usb_device *
+usrp_find_device (int nth, bool fx2_ok_p)
+{
+  struct usb_bus *p;
+  struct usb_device *q;
+  int   n_found = 0;
+
+  usrp_one_time_init ();
+  
+  p = usb_get_busses();
+  while (p != NULL){
+    q = p->devices;
+    while (q != NULL){
+      if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){
+       if (n_found == nth)     // return this one
+         return q;
+       n_found++;              // keep looking
+      }
+      q = q->next;
+    }
+    p = p->next;
+  }
+  return 0;    // not found
+}
+
+static struct usb_dev_handle *
+usrp_open_interface (struct usb_device *dev, int interface, int altinterface)
+{
+  struct usb_dev_handle *udh = usb_open (dev);
+  if (udh == 0)
+    return 0;
+
+  if (dev != dev_handle_to_dev (udh)){
+    fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__);
+    abort ();
+  }
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+  // There's no get get_configuration function, and with some of the newer kernels
+  // setting the configuration, even if to the same value, hoses any other processes
+  // that have it open.  Hence we opt to not set it at all (We've only
+  // got a single configuration anyway).  This may hose the win32 stuff...
+
+  // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06
+  if (usb_set_configuration (udh, 1) < 0){
+    /*
+     * Ignore this error.  
+     *
+     * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that
+     * it returns -EBUSY if _any_ of the interfaces of a device are open.
+     * We've only got a single configuration, so setting it doesn't even seem
+     * like it should be required.
+     */
+  }
+#endif
+
+  if (usb_claim_interface (udh, interface) < 0){
+    fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface);
+    fprintf (stderr, "%s\n", usb_strerror());
+    usb_close (udh);
+    return 0;
+  }
+
+  if (usb_set_altinterface (udh, altinterface) < 0){
+    fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__);
+    fprintf (stderr, "%s\n", usb_strerror());
+    usb_release_interface (udh, interface);
+    usb_close (udh);
+    return 0;
+  }
+
+  return udh;
+}
+
+struct usb_dev_handle *
+usrp_open_cmd_interface (struct usb_device *dev)
+{
+  return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE);
+}
+
+struct usb_dev_handle *
+usrp_open_rx_interface (struct usb_device *dev)
+{
+  return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE);
+}
+
+struct usb_dev_handle *
+usrp_open_tx_interface (struct usb_device *dev)
+{
+  return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE);
+}
+
+bool
+usrp_close_interface (struct usb_dev_handle *udh)
+{
+  // we're assuming that closing an interface automatically releases it.
+  return usb_close (udh) == 0;
+}
+
+// ----------------------------------------------------------------
+// write internal ram using Cypress vendor extension
+
+static bool
+write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf,
+                   int start_addr, size_t len)
+{
+  int addr;
+  int n;
+  int a;
+  int quanta = MAX_EP0_PKTSIZE;
+
+  for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){
+    n = len + start_addr - addr;
+    if (n > quanta)
+      n = quanta;
+
+    a = usb_control_msg (udh, 0x40, 0xA0,
+                        addr, 0, (char *)(buf + (addr - start_addr)), n, 1000);
+
+    if (a < 0){
+      fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror());
+      return false;
+    }
+  }
+  return true;
+}
+
+// ----------------------------------------------------------------
+// whack the CPUCS register using the upload RAM vendor extension
+
+static bool
+reset_cpu (struct usb_dev_handle *udh, bool reset_p)
+{
+  unsigned char v;
+
+  if (reset_p)
+    v = 1;             // hold processor in reset
+  else
+    v = 0;             // release reset
+
+  return write_internal_ram (udh, &v, 0xE600, 1);
+}
+
+// ----------------------------------------------------------------
+// Load intel format file into cypress FX2 (8051)
+
+static bool
+_usrp_load_firmware (struct usb_dev_handle *udh, const char *filename,
+                    unsigned char hash[USRP_HASH_SIZE])
+{
+  FILE *f = fopen (filename, "ra");
+  if (f == 0){
+    perror (filename);
+    return false;
+  }
+
+  if (!reset_cpu (udh, true))  // hold CPU in reset while loading firmware
+    goto fail;
+
+  
+  char s[1024];
+  int length;
+  int addr;
+  int type;
+  unsigned char data[256];
+  unsigned char checksum, a;
+  unsigned int b;
+  int i;
+
+  while (!feof(f)){
+    fgets(s, sizeof (s), f); /* we should not use more than 263 bytes normally */
+    if(s[0]!=':'){
+      fprintf(stderr,"%s: invalid line: \"%s\"\n", filename, s);
+      goto fail;
+    }
+    sscanf(s+1, "%02x", &length);
+    sscanf(s+3, "%04x", &addr);
+    sscanf(s+7, "%02x", &type);
+
+    if(type==0){
+
+      a=length+(addr &0xff)+(addr>>8)+type;
+      for(i=0;i<length;i++){
+       sscanf (s+9+i*2,"%02x", &b);
+       data[i]=b;
+       a=a+data[i];
+      }
+
+      sscanf (s+9+length*2,"%02x", &b);
+      checksum=b;
+      if (((a+checksum)&0xff)!=0x00){
+       fprintf (stderr, "  ** Checksum failed: got 0x%02x versus 0x%02x\n", (-a)&0xff, checksum);
+       goto fail;
+      }
+      if (!write_internal_ram (udh, data, addr, length))
+       goto fail;
+    }
+    else if (type == 0x01){      // EOF
+      break;
+    }
+    else if (type == 0x02){
+      fprintf(stderr, "Extended address: whatever I do with it?\n");
+      fprintf (stderr, "%s: invalid line: \"%s\"\n", filename, s);
+      goto fail;
+    }
+  }
+
+  // we jam the hash value into the FX2 memory before letting
+  // the cpu out of reset.  When it comes out of reset it
+  // may renumerate which will invalidate udh.
+
+  if (!usrp_set_hash (udh, FIRMWARE_HASH_SLOT, hash))
+    fprintf (stderr, "usrp: failed to write firmware hash slot\n");
+
+  if (!reset_cpu (udh, false))         // take CPU out of reset
+    goto fail;
+
+  fclose (f);
+  return true;
+
+ fail:
+  fclose (f);
+  return false;
+}
+
+// ----------------------------------------------------------------
+// write vendor extension command to USRP
+
+static int
+write_cmd (struct usb_dev_handle *udh,
+          int request, int value, int index,
+          unsigned char *bytes, int len)
+{
+  int  requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT;
+
+  int r = usb_control_msg (udh, requesttype, request, value, index,
+                          (char *) bytes, len, 1000);
+  if (r < 0){
+    // we get EPIPE if the firmware stalls the endpoint.
+    if (errno != EPIPE)
+      fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ());
+  }
+
+  return r;
+}
+
+// ----------------------------------------------------------------
+// load fpga
+
+static bool
+_usrp_load_fpga (struct usb_dev_handle *udh, const char *filename,
+                unsigned char hash[USRP_HASH_SIZE])
+{
+  bool ok = true;
+
+  FILE *fp = fopen (filename, "rb");
+  if (fp == 0){
+    perror (filename);
+    return false;
+  }
+
+  unsigned char buf[MAX_EP0_PKTSIZE];  // 64 is max size of EP0 packet on FX2
+  int n;
+
+  usrp_set_led (udh, 1, 1);            // led 1 on
+
+
+  // reset FPGA (and on rev1 both AD9862's, thus killing clock)
+  usrp_set_fpga_reset (udh, 1);                // hold fpga in reset
+
+  if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_BEGIN, 0, 0) != 0)
+    goto fail;
+  
+  while ((n = fread (buf, 1, sizeof (buf), fp)) > 0){
+    if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n)
+      goto fail;
+  }
+
+  if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0)
+    goto fail;
+  
+  fclose (fp);
+
+  if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash))
+    fprintf (stderr, "usrp: failed to write fpga hash slot\n");
+
+  // On the rev1 USRP, the {tx,rx}_{enable,reset} bits are
+  // controlled over the serial bus, and hence aren't observed until
+  // we've got a good fpga bitstream loaded.
+
+  usrp_set_fpga_reset (udh, 0);                // fpga out of master reset
+
+  // now these commands will work
+  
+  ok &= usrp_set_fpga_tx_enable (udh, 0);
+  ok &= usrp_set_fpga_rx_enable (udh, 0);
+
+  ok &= usrp_set_fpga_tx_reset (udh, 1);       // reset tx and rx paths
+  ok &= usrp_set_fpga_rx_reset (udh, 1);
+  ok &= usrp_set_fpga_tx_reset (udh, 0);       // reset tx and rx paths
+  ok &= usrp_set_fpga_rx_reset (udh, 0);
+
+  if (!ok)
+    fprintf (stderr, "usrp: failed to reset tx and/or rx path\n");
+
+  // Manually reset all regs except master control to zero.
+  // FIXME may want to remove this when we rework FPGA reset strategy.
+  // In the mean while, this gets us reproducible behavior.
+  for (int i = 0; i < FR_USER_0; i++){
+    if (i == FR_MASTER_CTRL)
+      continue;
+    usrp_write_fpga_reg(udh, i, 0);
+  }
+
+  power_down_9862s (udh);              // on the rev1, power these down!
+  usrp_set_led (udh, 1, 0);            // led 1 off
+
+  return true;
+
+ fail:
+  power_down_9862s (udh);              // on the rev1, power these down!
+  fclose (fp);
+  return false;
+}
+
+// ----------------------------------------------------------------
+
+bool 
+usrp_set_led (struct usb_dev_handle *udh, int which, bool on)
+{
+  int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0);
+
+  return r == 0;
+}
+
+bool
+usrp_set_hash (struct usb_dev_handle *udh, int which,
+              const unsigned char hash[USRP_HASH_SIZE])
+{
+  which &= 1;
+  
+  // we use the Cypress firmware down load command to jam it in.
+  int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0,
+                          (char *) hash, USRP_HASH_SIZE, 1000);
+  return r == USRP_HASH_SIZE;
+}
+
+bool
+usrp_get_hash (struct usb_dev_handle *udh, int which, 
+              unsigned char hash[USRP_HASH_SIZE])
+{
+  which &= 1;
+  
+  // we use the Cypress firmware upload command to fetch it.
+  int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0,
+                          (char *) hash, USRP_HASH_SIZE, 1000);
+  return r == USRP_HASH_SIZE;
+}
+
+static bool
+usrp_set_switch (struct usb_dev_handle *udh, int cmd_byte, bool on)
+{
+  return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0;
+}
+
+
+static bool
+usrp1_fpga_write (struct usb_dev_handle *udh,
+                 int regno, int value)
+{
+  // on the rev1 usrp, we use the generic spi_write interface
+
+  unsigned char buf[4];
+
+  buf[0] = (value >> 24) & 0xff;       // MSB first
+  buf[1] = (value >> 16) & 0xff;
+  buf[2] = (value >>  8) & 0xff;
+  buf[3] = (value >>  0) & 0xff;
+  
+  return usrp_spi_write (udh, 0x00 | (regno & 0x7f),
+                        SPI_ENABLE_FPGA,
+                        SPI_FMT_MSB | SPI_FMT_HDR_1,
+                        buf, sizeof (buf));
+}
+
+static bool
+usrp1_fpga_read (struct usb_dev_handle *udh,
+                int regno, int *value)
+{
+  *value = 0;
+  unsigned char buf[4];
+
+  bool ok = usrp_spi_read (udh, 0x80 | (regno & 0x7f),
+                          SPI_ENABLE_FPGA,
+                          SPI_FMT_MSB | SPI_FMT_HDR_1,
+                          buf, sizeof (buf));
+
+  if (ok)
+    *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+
+  return ok;
+}
+
+
+bool
+usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value)
+{
+  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
+  case 0:                      // not supported ;)
+    abort();   
+
+  default:
+    return usrp1_fpga_write (udh, reg, value);
+  }
+}
+
+bool
+usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value)
+{
+  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
+  case 0:              // not supported ;)
+    abort();
+    
+  default:
+    return usrp1_fpga_read (udh, reg, value);
+  }
+}
+
+bool 
+usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on)
+{
+  return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on);
+}
+
+bool 
+usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on)
+{
+  return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on);
+}
+
+bool 
+usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on)
+{
+  return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on);
+}
+
+bool 
+usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on)
+{
+  return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on);
+}
+
+bool 
+usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on)
+{
+  return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on);
+}
+
+
+// ----------------------------------------------------------------
+// conditional load stuff
+
+static bool
+compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE])
+{
+  assert (USRP_HASH_SIZE == 16);
+  memset (hash, 0, USRP_HASH_SIZE);
+
+  FILE *fp = fopen (filename, "rb");
+  if (fp == 0){
+    perror (filename);
+    return false;
+  }
+  int r = md5_stream (fp, hash);
+  fclose (fp);
+  
+  return r == 0;
+}
+
+static usrp_load_status_t
+usrp_conditionally_load_something (struct usb_dev_handle *udh,
+                                  const char *filename,
+                                  bool force,
+                                  int slot,
+                                  bool loader (struct usb_dev_handle *,
+                                               const char *,
+                                               unsigned char [USRP_HASH_SIZE]))
+{
+  unsigned char file_hash[USRP_HASH_SIZE];
+  unsigned char usrp_hash[USRP_HASH_SIZE];
+  
+  if (access (filename, R_OK) != 0){
+    perror (filename);
+    return ULS_ERROR;
+  }
+
+  if (!compute_hash (filename, file_hash))
+    return ULS_ERROR;
+
+  if (!force
+      && usrp_get_hash (udh, slot, usrp_hash)
+      && memcmp (file_hash, usrp_hash, USRP_HASH_SIZE) == 0)
+    return ULS_ALREADY_LOADED;
+
+  bool r = loader (udh, filename, file_hash);
+
+  if (!r)
+    return ULS_ERROR;
+
+  return ULS_OK;
+}
+
+usrp_load_status_t
+usrp_load_firmware (struct usb_dev_handle *udh,
+                   const char *filename,
+                   bool force)
+{
+  return usrp_conditionally_load_something (udh, filename, force,
+                                           FIRMWARE_HASH_SLOT,
+                                           _usrp_load_firmware);
+}
+
+usrp_load_status_t
+usrp_load_fpga (struct usb_dev_handle *udh,
+               const char *filename,
+               bool force)
+{
+  return usrp_conditionally_load_something (udh, filename, force,
+                                           FPGA_HASH_SLOT,
+                                           _usrp_load_fpga);
+}
+
+static usb_dev_handle *
+open_nth_cmd_interface (int nth)
+{
+  struct usb_device *udev = usrp_find_device (nth);
+  if (udev == 0){
+    fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
+    return 0;
+  }
+
+  struct usb_dev_handle *udh;
+
+  udh = usrp_open_cmd_interface (udev);
+  if (udh == 0){
+    // FIXME this could be because somebody else has it open.
+    // We should delay and retry...
+    fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n");
+    usb_strerror ();
+    return 0;
+  }
+
+  return udh;
+ }
+
+static bool
+our_nanosleep (const struct timespec *delay)
+{
+  struct timespec      new_delay = *delay;
+  struct timespec      remainder;
+
+  while (1){
+    int r = nanosleep (&new_delay, &remainder);
+    if (r == 0)
+      return true;
+    if (errno == EINTR)
+      new_delay = remainder;
+    else {
+      perror ("nanosleep");
+      return false;
+    }
+  }
+}
+
+static bool
+mdelay (int millisecs)
+{
+  struct timespec      ts;
+  ts.tv_sec = millisecs / 1000;
+  ts.tv_nsec = (millisecs - (1000 * ts.tv_sec)) * 1000000;
+  return our_nanosleep (&ts);
+}
+
+usrp_load_status_t
+usrp_load_firmware_nth (int nth, const char *filename, bool force){
+  struct usb_dev_handle *udh = open_nth_cmd_interface (nth);
+  if (udh == 0)
+    return ULS_ERROR;
+
+  usrp_load_status_t s = usrp_load_firmware (udh, filename, force);
+  usrp_close_interface (udh);
+
+  switch (s){
+
+  case ULS_ALREADY_LOADED:             // nothing changed...
+    return ULS_ALREADY_LOADED;
+    break;
+
+  case ULS_OK:
+    // we loaded firmware successfully.
+
+    // It's highly likely that the board will renumerate (simulate a
+    // disconnect/reconnect sequence), invalidating our current
+    // handle.
+
+    // FIXME.  Turn this into a loop that rescans until we refind ourselves
+    
+    struct timespec    t;      // delay for 1 second
+    t.tv_sec = 2;
+    t.tv_nsec = 0;
+    our_nanosleep (&t);
+
+    usb_find_busses ();                // rescan busses and devices
+    usb_find_devices ();
+
+    return ULS_OK;
+
+  default:
+  case ULS_ERROR:              // some kind of problem
+    return ULS_ERROR;
+  }
+}
+
+static void
+load_status_msg (usrp_load_status_t s, const char *type, const char *filename)
+{
+  char *e = getenv("USRP_VERBOSE");
+  bool verbose = e != 0;
+  
+  switch (s){
+  case ULS_ERROR:
+    fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename);
+    break;
+    
+  case ULS_ALREADY_LOADED:
+    if (verbose)
+      fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename);
+    break;
+
+  case ULS_OK:
+    if (verbose)
+      fprintf (stderr, "usrp: %s %s loaded successfully.\n", type, filename);
+    break;
+  }
+}
+
+bool
+usrp_load_standard_bits (int nth, bool force,
+                        const std::string fpga_filename,
+                        const std::string firmware_filename)
+{
+  usrp_load_status_t   s;
+  const char           *filename;
+  const char           *proto_filename;
+  int hw_rev;
+
+  // first, figure out what hardware rev we're dealing with
+  {
+    struct usb_device *udev = usrp_find_device (nth);
+    if (udev == 0){
+      fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
+      return false;
+    }
+    hw_rev = usrp_hw_rev (udev);
+  }
+
+  // start by loading the firmware
+
+  proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE",
+                                     default_firmware_filename);
+  filename = find_file(proto_filename, hw_rev);
+  if (filename == 0){
+    fprintf (stderr, "Can't find firmware: %s\n", proto_filename);
+    return false;
+  }
+
+  s = usrp_load_firmware_nth (nth, filename, force);
+  load_status_msg (s, "firmware", filename);
+
+  if (s == ULS_ERROR)
+    return false;
+
+  // if we actually loaded firmware, we must reload fpga ...
+  if (s == ULS_OK)
+    force = true;
+
+  // now move on to the fpga configuration bitstream
+
+  proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA",
+                                     default_fpga_filename);
+  filename = find_file (proto_filename, hw_rev);
+  if (filename == 0){
+    fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename);
+    return false;
+  }
+
+  struct usb_dev_handle *udh = open_nth_cmd_interface (nth);
+  if (udh == 0)
+    return false;
+  
+  s = usrp_load_fpga (udh, filename, force);
+  usrp_close_interface (udh);
+  load_status_msg (s, "fpga bitstream", filename);
+
+  if (s == ULS_ERROR)
+    return false;
+
+  return true;
+}
+
+bool
+_usrp_get_status (struct usb_dev_handle *udh, int which, bool *trouble)
+{
+  unsigned char        status;
+  *trouble = true;
+  
+  if (write_cmd (udh, VRQ_GET_STATUS, 0, which,
+                &status, sizeof (status)) != sizeof (status))
+    return false;
+
+  *trouble = status;
+  return true;
+}
+
+bool
+usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p)
+{
+  return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p);
+}
+
+bool
+usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p)
+{
+  return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p);
+}
+
+
+bool
+usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr,
+               const void *buf, int len)
+{
+  if (len < 1 || len > MAX_EP0_PKTSIZE)
+    return false;
+
+  return write_cmd (udh, VRQ_I2C_WRITE, i2c_addr, 0,
+                   (unsigned char *) buf, len) == len;
+}
+
+
+bool
+usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr,
+              void *buf, int len)
+{
+  if (len < 1 || len > MAX_EP0_PKTSIZE)
+    return false;
+
+  return write_cmd (udh, VRQ_I2C_READ, i2c_addr, 0,
+                   (unsigned char *) buf, len) == len;
+}
+
+bool
+usrp_spi_write (struct usb_dev_handle *udh,
+               int optional_header, int enables, int format,
+               const void *buf, int len)
+{
+  if (len < 0 || len > MAX_EP0_PKTSIZE)
+    return false;
+
+  return write_cmd (udh, VRQ_SPI_WRITE,
+                   optional_header,
+                   ((enables & 0xff) << 8) | (format & 0xff),
+                   (unsigned char *) buf, len) == len;
+}
+
+
+bool
+usrp_spi_read (struct usb_dev_handle *udh,
+              int optional_header, int enables, int format,
+              void *buf, int len)
+{
+  if (len < 0 || len > MAX_EP0_PKTSIZE)
+    return false;
+
+  return write_cmd (udh, VRQ_SPI_READ,
+                   optional_header,
+                   ((enables & 0xff) << 8) | (format & 0xff),
+                   (unsigned char *) buf, len) == len;
+}
+
+bool
+usrp_9862_write (struct usb_dev_handle *udh, int which_codec,
+                int regno, int value)
+{
+  if (0)
+    fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n",
+            which_codec, regno, value, value);
+
+  unsigned char buf[1];
+
+  buf[0] = value;
+  
+  return usrp_spi_write (udh, 0x00 | (regno & 0x3f),
+                        which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B,
+                        SPI_FMT_MSB | SPI_FMT_HDR_1,
+                        buf, 1);
+}
+
+bool
+usrp_9862_read (struct usb_dev_handle *udh, int which_codec,
+               int regno, unsigned char *value)
+{
+  return usrp_spi_read (udh, 0x80 | (regno & 0x3f),
+                       which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B,
+                       SPI_FMT_MSB | SPI_FMT_HDR_1,
+                       value, 1);
+}
+
+bool
+usrp_9862_write_many (struct usb_dev_handle *udh,
+                     int which_codec,
+                     const unsigned char *buf,
+                     int len)
+{
+  if (len & 0x1)
+    return false;              // must be even
+
+  bool result = true;
+
+  while (len > 0){
+    result &= usrp_9862_write (udh, which_codec, buf[0], buf[1]);
+    len -= 2;
+    buf += 2;
+  }
+
+  return result;
+}
+
+
+bool
+usrp_9862_write_many_all (struct usb_dev_handle *udh,
+                          const unsigned char *buf, int len)
+{
+  // FIXME handle 2/2 and 4/4 versions
+
+  bool result;
+  result  = usrp_9862_write_many (udh, 0, buf, len);
+  result &= usrp_9862_write_many (udh, 1, buf, len);
+  return result;
+}
+
+static void
+power_down_9862s (struct usb_dev_handle *udh)
+{
+  static const unsigned char regs[] = {
+    REG_RX_PWR_DN,     0x01,                   // everything
+    REG_TX_PWR_DN,     0x0f,                   // pwr dn digital and analog_both
+    REG_TX_MODULATOR,  0x00                    // coarse & fine modulators disabled
+  };
+
+  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
+  case 0:
+    break;
+
+  default:
+    usrp_9862_write_many_all (udh, regs, sizeof (regs));
+    break;
+  }
+}
+
+
+
+static const int EEPROM_PAGESIZE = 16;
+
+bool
+usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr,
+                  int eeprom_offset, const void *buf, int len)
+{
+  unsigned char cmd[2];
+  const unsigned char *p = (unsigned char *) buf;
+  
+  // The simplest thing that could possibly work:
+  //   all writes are single byte writes.
+  //
+  // We could speed this up using the page write feature,
+  // but we write so infrequently, why bother...
+
+  while (len-- > 0){
+    cmd[0] = eeprom_offset++;
+    cmd[1] = *p++;
+    bool r = usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd));
+    mdelay (10);               // delay 10ms worst case write time
+    if (!r)
+      return false;
+  }
+  
+  return true;
+}
+
+bool
+usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr,
+                 int eeprom_offset, void *buf, int len)
+{
+  unsigned char *p = (unsigned char *) buf;
+
+  // We setup a random read by first doing a "zero byte write".
+  // Writes carry an address.  Reads use an implicit address.
+
+  unsigned char cmd[1];
+  cmd[0] = eeprom_offset;
+  if (!usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd)))
+    return false;
+
+  while (len > 0){
+    int n = std::min (len, MAX_EP0_PKTSIZE);
+    if (!usrp_i2c_read (udh, i2c_addr, p, n))
+      return false;
+    len -= n;
+    p += n;
+  }
+  return true;
+}
+// ----------------------------------------------------------------
+
+static bool
+slot_to_codec (int slot, int *which_codec)
+{
+  *which_codec = 0;
+  
+  switch (slot){
+  case SLOT_TX_A:
+  case SLOT_RX_A:
+    *which_codec = 0;
+    break;
+
+  case SLOT_TX_B:
+  case SLOT_RX_B:
+    *which_codec = 1;
+    break;
+
+  default:
+    fprintf (stderr, "usrp_prims:slot_to_codec: invalid slot = %d\n", slot);
+    return false;
+  }
+  return true;
+}
+
+static bool
+tx_slot_p (int slot)
+{
+  switch (slot){
+  case SLOT_TX_A:
+  case SLOT_TX_B:
+    return true;
+
+  default:
+    return false;
+  }
+}
+
+bool
+usrp_write_aux_dac (struct usb_dev_handle *udh, int slot,
+                   int which_dac, int value)
+{
+  int which_codec;
+  
+  if (!slot_to_codec (slot, &which_codec))
+    return false;
+
+  if (!(0 <= which_dac && which_dac < 4)){
+    fprintf (stderr, "usrp_write_aux_dac: invalid dac = %d\n", which_dac);
+    return false;
+  }
+
+  value &= 0x0fff;     // mask to 12-bits
+  
+  if (which_dac == 3){
+    // dac 3 is really 12-bits.  Use value as is.
+    bool r = true;
+    r &= usrp_9862_write (udh, which_codec, 43, (value >> 4));       // most sig
+    r &= usrp_9862_write (udh, which_codec, 42, (value & 0xf) << 4); // least sig
+    return r;
+  }
+  else {
+    // dac 0, 1, and 2 are really 8 bits.  
+    value = value >> 4;                // shift value appropriately
+    return usrp_9862_write (udh, which_codec, 36 + which_dac, value);
+  }
+}
+
+
+bool
+usrp_read_aux_adc (struct usb_dev_handle *udh, int slot,
+                  int which_adc, int *value)
+{
+  *value = 0;
+  int  which_codec;
+
+  if (!slot_to_codec (slot, &which_codec))
+    return false;
+
+  if (!(0 <= which_codec && which_codec < 2)){
+    fprintf (stderr, "usrp_read_aux_adc: invalid adc = %d\n", which_adc);
+    return false;
+  }
+
+  unsigned char aux_adc_control =
+    AUX_ADC_CTRL_REFSEL_A              // on chip reference
+    | AUX_ADC_CTRL_REFSEL_B;           // on chip reference
+
+  int  rd_reg = 26;    // base address of two regs to read for result
+  
+  // program the ADC mux bits
+  if (tx_slot_p (slot))
+    aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2;
+  else {
+    rd_reg += 2;
+    aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1;
+  }
+  
+  // I'm not sure if we can set the mux and issue a start conversion
+  // in the same cycle, so let's do them one at a time.
+
+  usrp_9862_write (udh, which_codec, 34, aux_adc_control);
+
+  if (which_adc == 0)
+    aux_adc_control |= AUX_ADC_CTRL_START_A;
+  else {
+    rd_reg += 4;
+    aux_adc_control |= AUX_ADC_CTRL_START_B;
+  }
+
+  // start the conversion
+  usrp_9862_write (udh, which_codec, 34, aux_adc_control);
+
+  // read the 10-bit result back
+  unsigned char v_lo = 0;
+  unsigned char v_hi = 0;
+  bool r = usrp_9862_read (udh, which_codec, rd_reg, &v_lo);
+  r &= usrp_9862_read (udh, which_codec, rd_reg + 1, &v_hi);
+
+  if (r)
+    *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit
+  
+  return r;
+}
+
+// ----------------------------------------------------------------
+
+static int slot_to_i2c_addr (int slot)
+{
+  switch (slot){
+  case SLOT_TX_A:      return I2C_ADDR_TX_A;
+  case SLOT_RX_A:      return I2C_ADDR_RX_A;
+  case SLOT_TX_B:      return I2C_ADDR_TX_B;
+  case SLOT_RX_B:      return I2C_ADDR_RX_B;
+  default:             return -1;
+  }
+}
+
+static void
+set_chksum (unsigned char *buf)
+{
+  int sum = 0;
+  unsigned int i;
+  for (i = 0; i < DB_EEPROM_CLEN - 1; i++)
+    sum += buf[i];
+  buf[i] = -sum;
+}
+
+static usrp_dbeeprom_status_t
+read_dboard_eeprom (struct usb_dev_handle *udh,
+                   int slot_id, unsigned char *buf)
+{
+  int i2c_addr = slot_to_i2c_addr (slot_id);
+  if (i2c_addr == -1)
+    return UDBE_BAD_SLOT;
+
+  if (!usrp_eeprom_read (udh, i2c_addr, 0, buf, DB_EEPROM_CLEN))
+    return UDBE_NO_EEPROM;
+
+  if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE)
+    return UDBE_INVALID_EEPROM;
+
+  int sum = 0;
+  for (unsigned int i = 0; i < DB_EEPROM_CLEN; i++)
+    sum += buf[i];
+
+  if ((sum & 0xff) != 0)
+    return UDBE_INVALID_EEPROM;
+
+  return UDBE_OK;
+}
+
+usrp_dbeeprom_status_t
+usrp_read_dboard_eeprom (struct usb_dev_handle *udh,
+                        int slot_id, usrp_dboard_eeprom *eeprom)
+{
+  unsigned char buf[DB_EEPROM_CLEN];
+
+  memset (eeprom, 0, sizeof (*eeprom));
+
+  usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf);
+  if (s != UDBE_OK)
+    return s;
+
+  eeprom->id = (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB];
+  eeprom->oe = (buf[DB_EEPROM_OE_MSB] << 8) | buf[DB_EEPROM_OE_LSB];
+  eeprom->offset[0] = (buf[DB_EEPROM_OFFSET_0_MSB] << 8) | buf[DB_EEPROM_OFFSET_0_LSB];
+  eeprom->offset[1] = (buf[DB_EEPROM_OFFSET_1_MSB] << 8) | buf[DB_EEPROM_OFFSET_1_LSB];
+
+  return UDBE_OK;
+}
+
+bool
+usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id,
+                          short offset0, short offset1)
+{
+  unsigned char buf[DB_EEPROM_CLEN];
+
+  usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf);
+  if (s != UDBE_OK)
+    return false;
+
+  buf[DB_EEPROM_OFFSET_0_LSB] = (offset0 >> 0) & 0xff;
+  buf[DB_EEPROM_OFFSET_0_MSB] = (offset0 >> 8) & 0xff;
+  buf[DB_EEPROM_OFFSET_1_LSB] = (offset1 >> 0) & 0xff;
+  buf[DB_EEPROM_OFFSET_1_MSB] = (offset1 >> 8) & 0xff;
+  set_chksum (buf);
+
+  return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id),
+                           0, buf, sizeof (buf));
+}
+
+std::string
+usrp_serial_number(struct usb_dev_handle *udh)
+{
+  unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber;
+  if (iserial == 0)
+    return "";
+
+  char buf[1024];
+  if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0)
+    return "";
+
+  return buf;
+}
diff --git a/usrp/host/lib/legacy/usrp_prims.h b/usrp/host/lib/legacy/usrp_prims.h
new file mode 100644 (file)
index 0000000..97cfb4a
--- /dev/null
@@ -0,0 +1,294 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004,2006 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Low level primitives for directly messing with USRP hardware.
+ *
+ * If you're trying to use the USRP, you'll probably want to take a look
+ * at the usrp_rx and usrp_tx classes.  They hide a bunch of low level details
+ * and provide high performance streaming i/o.
+ *
+ * This interface is built on top of libusb, which allegedly works under
+ * Linux, *BSD and Mac OS/X.  http://libusb.sourceforge.net
+ */
+
+#ifndef _USRP_PRIMS_H_
+#define _USRP_PRIMS_H_
+
+#include <usrp_slots.h>
+#include <string>
+
+static const int USRP_HASH_SIZE = 16;
+
+enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED };
+
+struct usb_dev_handle;
+struct usb_device;
+
+/*!
+ * \brief initialize libusb; probe busses and devices.
+ * Safe to call more than once.
+ */
+void usrp_one_time_init ();
+
+/*
+ * force a rescan of the buses and devices
+ */
+void usrp_rescan ();
+
+/*!
+ * \brief locate Nth (zero based) USRP device in system.
+ * Return pointer or 0 if not found.
+ *
+ * The following kinds of devices are considered USRPs:
+ *
+ *   unconfigured USRP (no firwmare loaded)
+ *   configured USRP (firmware loaded)
+ *   unconfigured Cypress FX2 (only if fx2_ok_p is true)
+ */
+struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false);
+
+bool usrp_usrp_p (struct usb_device *q);               //< is this a USRP
+bool usrp_usrp0_p (struct usb_device *q);              //< is this a USRP Rev 0
+bool usrp_usrp1_p (struct usb_device *q);              //< is this a USRP Rev 1
+bool usrp_usrp2_p (struct usb_device *q);              //< is this a USRP Rev 2
+int  usrp_hw_rev (struct usb_device *q);               //< return h/w rev code
+
+bool usrp_fx2_p (struct usb_device *q);                        //< is this an unconfigured Cypress FX2
+
+bool usrp_unconfigured_usrp_p (struct usb_device *q);  //< some kind of unconfigured USRP
+bool usrp_configured_usrp_p (struct usb_device *q);    //< some kind of configured USRP
+
+/*!
+ * \brief given a usb_device return an instance of the appropriate usb_dev_handle
+ *
+ * These routines claim the specified interface and select the
+ * correct alternate interface.  (USB nomenclature is totally screwed!)
+ *
+ * If interface can't be opened, or is already claimed by some other
+ * process, 0 is returned.
+ */
+struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev);
+struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev);
+struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev);
+
+/*!
+ * \brief close interface.
+ */
+bool usrp_close_interface (struct usb_dev_handle *udh);
+
+/*!
+ * \brief load intel hex format file into USRP/Cypress FX2 (8051).
+ *
+ * The filename extension is typically *.ihx
+ *
+ * Note that loading firmware may cause the device to renumerate.  I.e.,
+ * change its configuration, invalidating the current device handle.
+ */
+
+usrp_load_status_t 
+usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force);
+
+/*!
+ * \brief load intel hex format file into USRP FX2 (8051).
+ *
+ * The filename extension is typically *.ihx
+ *
+ * Note that loading firmware may cause the device to renumerate.  I.e.,
+ * change its configuration, invalidating the current device handle.
+ * If the result is ULS_OK, usrp_load_firmware_nth delays 1 second
+ * then rescans the busses and devices.
+ */
+usrp_load_status_t
+usrp_load_firmware_nth (int nth, const char *filename, bool force);
+
+/*!
+ * \brief load fpga configuration bitstream
+ */
+usrp_load_status_t
+usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force);
+
+/*!
+ * \brief load the regular firmware and fpga bitstream in the Nth USRP.
+ *
+ * This is the normal starting point...
+ */
+bool usrp_load_standard_bits (int nth, bool force,
+                             const std::string fpga_filename = "",
+                             const std::string firmware_filename = "");
+
+/*!
+ * \brief copy the given \p hash into the USRP hash slot \p which.
+ * The usrp implements two hash slots, 0 and 1.
+ */
+bool usrp_set_hash (struct usb_dev_handle *udh, int which,
+                   const unsigned char hash[USRP_HASH_SIZE]);
+
+/*!
+ * \brief retrieve the \p hash from the USRP hash slot \p which.
+ * The usrp implements two hash slots, 0 and 1.
+ */
+bool usrp_get_hash (struct usb_dev_handle *udh, int which,
+                   unsigned char hash[USRP_HASH_SIZE]);
+
+bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value);
+bool usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value);
+bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on);
+bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on);
+bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on);
+bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on);
+bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on);
+bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on);
+
+bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p);
+bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p);
+
+// i2c_read and i2c_write are limited to a maximum len of 64 bytes.
+
+bool usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr,
+                    const void *buf, int len);
+
+bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr,
+                   void *buf, int len);
+
+// spi_read and spi_write are limited to a maximum of 64 bytes
+// See usrp_spi_defs.h for more info
+
+bool usrp_spi_write (struct usb_dev_handle *udh,
+                    int optional_header, int enables, int format,
+                    const void *buf, int len);
+
+bool usrp_spi_read (struct usb_dev_handle *udh,
+                    int optional_header, int enables, int format,
+                    void *buf, int len);
+
+
+bool usrp_9862_write (struct usb_dev_handle *udh,
+                     int which_codec,                  // [0,  1]
+                     int regno,                        // [0, 63]
+                     int value);                       // [0, 255]     
+
+bool usrp_9862_read (struct usb_dev_handle *udh,
+                    int which_codec,                   // [0,  1]
+                    int regno,                         // [0, 63]
+                    unsigned char *value);             // [0, 255]
+
+/*!
+ * \brief Write multiple 9862 regs at once.
+ *
+ * \p buf contains alternating register_number, register_value pairs.
+ * \p len must be even and is the length of buf in bytes.
+ */
+bool usrp_9862_write_many (struct usb_dev_handle *udh, int which_codec,
+                          const unsigned char *buf, int len);
+                          
+
+/*!
+ * \brief write specified regs to all 9862's in the system
+ */
+bool usrp_9862_write_many_all (struct usb_dev_handle *udh,
+                              const unsigned char *buf, int len);
+                          
+
+// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
+// Which EEPROM is determined by i2c_addr.  See i2c_addr.h
+
+bool usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr,
+                       int eeprom_offset, const void *buf, int len);
+
+
+// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
+// Which EEPROM is determined by i2c_addr.  See i2c_addr.h
+
+bool usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr,
+                      int eeprom_offset, void *buf, int len);
+
+
+// Slot specific i/o routines
+
+/*!
+ * \brief write to the specified aux dac.
+ *
+ * \p slot: which Tx or Rx slot to write.
+ *    N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's
+ *          SLOT_TX_B and SLOT_RX_B share the same AUX DAC's
+ *
+ * \p which_dac: [0,3]  RX slots must use only 0 and 1.
+ *                     TX slots must use only 2 and 3.
+ *
+ * AUX DAC 3 is really the 9862 sigma delta output.
+ *
+ * \p value to write to aux dac.  All dacs take straight
+ * binary values.  Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit,
+ * the interface is in terms of 12-bit values [0,4095]
+ */
+bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot,
+                        int which_dac, int value);
+
+/*!
+ * \brief Read the specified aux adc
+ *
+ * \p slot: which Tx or Rx slot to read aux dac
+ * \p which_adc: [0,1]  which of the two adcs to read
+ * \p *value: return value, 12-bit straight binary.
+ */
+bool usrp_read_aux_adc (struct usb_dev_handle *udh, int slot,
+                       int which_adc, int *value);
+
+
+/*!
+ * \brief usrp daughterboard id to name mapping
+ */
+const std::string usrp_dbid_to_string (int dbid);
+
+
+enum usrp_dbeeprom_status_t { UDBE_OK, UDBE_BAD_SLOT, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM };
+
+struct usrp_dboard_eeprom {
+  unsigned short       id;             // d'board identifier code
+  unsigned short       oe;             // fpga output enables:
+                                       //   If bit set, i/o pin is an output from FPGA.
+  short                        offset[2];      // ADC/DAC offset correction
+};
+
+/*!
+ * \brief Read and return parsed daughterboard eeprom
+ */
+usrp_dbeeprom_status_t
+usrp_read_dboard_eeprom (struct usb_dev_handle *udh,
+                        int slot_id, usrp_dboard_eeprom *eeprom);
+
+/*!
+ * \brief write ADC/DAC offset calibration constants to d'board eeprom
+ */
+bool usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id,
+                               short offset0, short offset1);
+
+/*!
+ * \brief return a usrp's serial number.
+ *
+ * Note that this only works on a configured usrp.
+ * \returns non-zero length string iff successful.
+ */
+std::string usrp_serial_number(struct usb_dev_handle *udh);
+
+#endif /* _USRP_PRIMS_H_ */
diff --git a/usrp/host/lib/legacy/usrp_slots.h b/usrp/host/lib/legacy/usrp_slots.h
new file mode 100644 (file)
index 0000000..c4971d1
--- /dev/null
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP_SLOTS_H
+#define INCLUDED_USRP_SLOTS_H
+
+// daughterboard slot numbers used in some calls
+
+static const int SLOT_TX_A = 0;
+static const int SLOT_RX_A = 1;
+static const int SLOT_TX_B = 2;
+static const int SLOT_RX_B = 3;
+
+#endif /* INCLUDED_USRP_SLOTS_H */
diff --git a/usrp/host/lib/legacy/usrp_standard.cc b/usrp/host/lib/legacy/usrp_standard.cc
new file mode 100644 (file)
index 0000000..6b4ec93
--- /dev/null
@@ -0,0 +1,831 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <usrp_standard.h>
+
+#include "usrp_prims.h"
+#include "fpga_regs_common.h"
+#include "fpga_regs_standard.h"
+#include <stdexcept>
+#include <assert.h>
+#include <math.h>
+#include <ad9862.h>
+
+
+static const int OLD_CAPS_VAL = 0xaa55ff77;
+static const int DEFAULT_CAPS_VAL = ((2 << bmFR_RB_CAPS_NDUC_SHIFT)
+                                    | (2 << bmFR_RB_CAPS_NDDC_SHIFT)
+                                    | bmFR_RB_CAPS_RX_HAS_HALFBAND);
+
+// #define USE_FPGA_TX_CORDIC
+
+
+using namespace ad9862;
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+
+static unsigned int
+compute_freq_control_word_fpga (double master_freq, double target_freq,
+                               double *actual_freq, bool verbose)
+{
+  static const int NBITS = 14;
+  
+  int  v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
+
+  if (0)
+    v = (v >> (32 - NBITS)) << (32 - NBITS);   // keep only top NBITS
+
+  *actual_freq = v * master_freq / pow (2.0, 32.0);
+
+  if (verbose)
+    fprintf (stderr,
+            "compute_freq_control_word_fpga: target = %g  actual = %g  delta = %g\n",
+            target_freq, *actual_freq, *actual_freq - target_freq);
+
+  return (unsigned int) v;
+}
+
+// The 9862 uses an unsigned 24-bit frequency tuning word and 
+// a separate register to control the sign.
+
+static unsigned int
+compute_freq_control_word_9862 (double master_freq, double target_freq,
+                               double *actual_freq, bool verbose)
+{
+  double sign = 1.0;
+
+  if (target_freq < 0)
+    sign = -1.0;
+
+  int  v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0));
+  *actual_freq = v * master_freq / pow (2.0, 24.0) * sign;
+
+  if (verbose)
+    fprintf (stderr,
+     "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n",
+     target_freq, *actual_freq, *actual_freq - target_freq, v);
+
+  return (unsigned int) v;
+}
+
+// ----------------------------------------------------------------
+
+usrp_standard_common::usrp_standard_common(usrp_basic *parent)
+{
+  // read new FPGA capability register
+  if (!parent->_read_fpga_reg(FR_RB_CAPS, &d_fpga_caps)){
+    fprintf (stderr, "usrp_standard_common: failed to read FPGA cap register.\n");
+    throw std::runtime_error ("usrp_standard_common::ctor");
+  }
+  // If we don't have the cap register, set the value to what it would
+  // have had if we did have one ;)
+  if (d_fpga_caps == OLD_CAPS_VAL)
+    d_fpga_caps = DEFAULT_CAPS_VAL;
+
+  if (0){
+    fprintf(stdout, "has_rx_halfband = %d\n", has_rx_halfband());
+    fprintf(stdout, "nddcs           = %d\n", nddcs());
+    fprintf(stdout, "has_tx_halfband = %d\n", has_tx_halfband());
+    fprintf(stdout, "nducs           = %d\n", nducs());
+  }
+}
+
+bool
+usrp_standard_common::has_rx_halfband() const
+{
+  return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? true : false;
+}
+
+int
+usrp_standard_common::nddcs() const
+{
+  return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT;
+}
+
+bool
+usrp_standard_common::has_tx_halfband() const
+{
+  return (d_fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND) ? true : false;
+}
+
+int
+usrp_standard_common::nducs() const
+{
+  return (d_fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT;
+}
+
+// ----------------------------------------------------------------
+
+static int 
+real_rx_mux_value (int mux, int nchan)
+{
+  if (mux != -1)
+    return mux;
+
+  return 0x32103210;
+}
+
+usrp_standard_rx::usrp_standard_rx (int which_board,
+                                   unsigned int decim_rate,
+                                   int nchan, int mux, int mode,
+                                   int fusb_block_size, int fusb_nblocks,
+                                   const std::string fpga_filename,
+                                   const std::string firmware_filename
+                                   )
+  : usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
+                  fpga_filename, firmware_filename),
+    usrp_standard_common(this),
+    d_nchan (1), d_sw_mux (0x0), d_hw_mux (0x0)
+{
+  if (!set_format(make_format())){
+    fprintf (stderr, "usrp_standard_rx: set_format failed\n");
+    throw std::runtime_error ("usrp_standard_rx::ctor");
+  }
+  if (!set_nchannels (nchan)){
+    fprintf (stderr, "usrp_standard_rx: set_nchannels failed\n");
+    throw std::runtime_error ("usrp_standard_rx::ctor");
+  }
+  if (!set_decim_rate (decim_rate)){
+    fprintf (stderr, "usrp_standard_rx: set_decim_rate failed\n");
+    throw std::runtime_error ("usrp_standard_rx::ctor");
+  }
+  if (!set_mux (real_rx_mux_value (mux, nchan))){
+    fprintf (stderr, "usrp_standard_rx: set_mux failed\n");
+    throw std::runtime_error ("usrp_standard_rx::ctor");
+  }
+  if (!set_fpga_mode (mode)){
+    fprintf (stderr, "usrp_standard_rx: set_fpga_mode failed\n");
+    throw std::runtime_error ("usrp_standard_rx::ctor");
+  }
+
+  for (int i = 0; i < MAX_CHAN; i++){
+    set_rx_freq(i, 0);
+    set_ddc_phase(i, 0);
+  }
+}
+
+usrp_standard_rx::~usrp_standard_rx ()
+{
+  // fprintf(stderr, "\nusrp_standard_rx: dtor\n");
+}
+
+bool
+usrp_standard_rx::start ()
+{
+  if (!usrp_basic_rx::start ())
+    return false;
+
+  // add our code here
+
+  return true;
+}
+
+bool
+usrp_standard_rx::stop ()
+{
+  bool ok = usrp_basic_rx::stop ();
+
+  // add our code here
+
+  return ok;
+}
+
+usrp_standard_rx *
+usrp_standard_rx::make (int which_board,
+                       unsigned int decim_rate,
+                       int nchan, int mux, int mode,
+                       int fusb_block_size, int fusb_nblocks,
+                       const std::string fpga_filename,
+                       const std::string firmware_filename
+                       )
+{
+  usrp_standard_rx *u = 0;
+  
+  try {
+    u = new usrp_standard_rx (which_board, decim_rate,
+                             nchan, mux, mode,
+                             fusb_block_size, fusb_nblocks,
+                             fpga_filename, firmware_filename);
+    return u;
+  }
+  catch (...){
+    delete u;
+    return 0;
+  }
+
+  return u;
+}
+
+bool
+usrp_standard_rx::set_decim_rate(unsigned int rate)
+{
+  if ((rate & 0x1) || rate < 4 || rate > 256){
+    fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n");
+    return false;
+  }
+
+  d_decim_rate = rate;
+  set_usb_data_rate ((adc_rate () / rate * nchannels ())
+                    * (2 * sizeof (short)));
+
+  bool s = disable_rx ();
+  int v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1;
+  bool ok = _write_fpga_reg (FR_DECIM_RATE, v);
+  restore_rx (s);
+  return ok;
+}
+
+bool usrp_standard_rx::set_nchannels (int nchan)
+{
+  if (!(nchan == 1 || nchan == 2 || nchan == 4))
+    return false;
+
+  if (nchan > nddcs())
+    return false;
+
+  d_nchan = nchan;
+
+  return write_hw_mux_reg ();
+}
+
+
+// map software mux value to hw mux value
+//
+// Software mux value:
+//
+//    3                   2                   1                       
+//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-------+-------+-------+-------+-------+-------+-------+-------+
+// |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
+// +-------+-------+-------+-------+-------+-------+-------+-------+
+//
+// Each 4-bit I field is either 0,1,2,3
+// Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
+// All Q's must be 0xf or none of them may be 0xf
+//
+//
+// Hardware mux value:
+//
+//    3                   2                   1                       
+//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------+-------+-------+-------+-------+-+-----+
+// |      must be zero     | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
+// +-----------------------+-------+-------+-------+-------+-+-----+
+
+
+static bool
+map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr)
+{
+  // confirm that all I's are either 0,1,2,3 
+
+  for (int i = 0; i < 8; i += 2){
+    int t = (sw_mux >> (4 * i)) & 0xf;
+    if (!(0 <= t && t <= 3))
+      return false;
+  }
+
+  // confirm that all Q's are either 0,1,2,3 or 0xf
+
+  for (int i = 1; i < 8; i += 2){
+    int t = (sw_mux >> (4 * i)) & 0xf;
+    if (!(t == 0xf || (0 <= t && t <= 3)))
+      return false;
+  }
+
+  // confirm that all Q inputs are 0xf (const zero input),
+  // or none of them are 0xf
+
+  int q_and = 1;
+  int q_or =  0;
+
+  for (int i = 0; i < 4; i++){
+    int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf;
+    q_and &= qx_is_0xf;
+    q_or  |= qx_is_0xf;
+  }
+
+  if (q_and || !q_or){         // OK
+    int hw_mux_value = 0;
+
+    for (int i = 0; i < 8; i++){
+      int t = (sw_mux >> (4 * i)) & 0x3;
+      hw_mux_value |= t << (2 * i + 4);
+    }
+
+    if (q_and)
+      hw_mux_value |= 0x8;     // all Q's zero
+
+    *hw_mux_ptr = hw_mux_value;
+    return true;
+  }
+  else
+    return false;
+}
+
+bool
+usrp_standard_rx::set_mux (int mux)
+{
+  if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux))
+    return false;
+
+  // fprintf (stderr, "sw_mux = 0x%08x  hw_mux = 0x%08x\n", mux, d_hw_mux);
+
+  d_sw_mux = mux;
+  return write_hw_mux_reg ();
+}
+
+bool
+usrp_standard_rx::write_hw_mux_reg ()
+{
+  bool s = disable_rx ();
+  bool ok = _write_fpga_reg (FR_RX_MUX, d_hw_mux | d_nchan);
+  restore_rx (s);
+  return ok;
+}
+
+
+bool
+usrp_standard_rx::set_rx_freq (int channel, double freq)
+{
+  if (channel < 0 || channel > MAX_CHAN)
+    return false;
+
+  unsigned int v =
+    compute_freq_control_word_fpga (adc_freq(),
+                                   freq, &d_rx_freq[channel],
+                                   d_verbose);
+
+  return _write_fpga_reg (FR_RX_FREQ_0 + channel, v);
+}
+
+unsigned int
+usrp_standard_rx::decim_rate () const { return d_decim_rate; }
+
+int
+usrp_standard_rx::nchannels () const { return d_nchan; }
+
+int
+usrp_standard_rx::mux () const { return d_sw_mux; }
+
+double 
+usrp_standard_rx::rx_freq (int channel) const
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return 0;
+
+  return d_rx_freq[channel];
+}
+
+bool
+usrp_standard_rx::set_fpga_mode (int mode)
+{
+  return _write_fpga_reg (FR_MODE, mode);
+}
+
+bool
+usrp_standard_rx::set_ddc_phase(int channel, int phase)
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return false;
+
+  return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase);
+}
+
+
+// To avoid quiet failures, check for things that our code cares about.
+
+static bool
+rx_format_is_valid(unsigned int format)
+{
+  int width =  usrp_standard_rx::format_width(format);
+  int want_q = usrp_standard_rx::format_want_q(format);
+
+  if (!(width == 8 || width == 16))    // FIXME add other widths when valid
+    return false;
+
+  if (!want_q)         // FIXME remove check when the rest of the code can handle I only
+    return false;
+
+  return true;
+}
+
+bool
+usrp_standard_rx::set_format(unsigned int format)
+{
+  if (!rx_format_is_valid(format))
+    return false;
+
+  return _write_fpga_reg(FR_RX_FORMAT, format);
+}
+
+unsigned int
+usrp_standard_rx::format() const
+{
+  return d_fpga_shadows[FR_RX_FORMAT];
+}
+
+// ----------------------------------------------------------------
+
+unsigned int 
+usrp_standard_rx::make_format(int width, int shift, bool want_q, bool bypass_halfband)
+{
+  unsigned int format = 
+    (((width << bmFR_RX_FORMAT_WIDTH_SHIFT) & bmFR_RX_FORMAT_WIDTH_MASK)
+     | (shift << bmFR_RX_FORMAT_SHIFT_SHIFT) & bmFR_RX_FORMAT_SHIFT_MASK);
+
+  if (want_q)
+    format |= bmFR_RX_FORMAT_WANT_Q;
+  if (bypass_halfband)
+    format |= bmFR_RX_FORMAT_BYPASS_HB;
+
+  return format;
+}
+
+int
+usrp_standard_rx::format_width(unsigned int format)
+{
+  return (format & bmFR_RX_FORMAT_WIDTH_MASK) >> bmFR_RX_FORMAT_WIDTH_SHIFT;
+}
+
+int
+usrp_standard_rx::format_shift(unsigned int format)
+{
+  return (format & bmFR_RX_FORMAT_SHIFT_MASK) >> bmFR_RX_FORMAT_SHIFT_SHIFT;
+}
+
+bool
+usrp_standard_rx::format_want_q(unsigned int format)
+{
+  return (format & bmFR_RX_FORMAT_WANT_Q) != 0;
+}
+
+bool
+usrp_standard_rx::format_bypass_halfband(unsigned int format)
+{
+  return (format & bmFR_RX_FORMAT_BYPASS_HB) != 0;
+}
+
+//////////////////////////////////////////////////////////////////
+
+
+// tx data is timed to CLKOUT1 (64 MHz)
+// interpolate 4x
+// fine modulator enabled
+
+
+static unsigned char tx_regs_use_nco[] = {
+  REG_TX_IF,           (TX_IF_USE_CLKOUT1
+                        | TX_IF_I_FIRST
+                        | TX_IF_2S_COMP
+                        | TX_IF_INTERLEAVED),
+  REG_TX_DIGITAL,      (TX_DIGITAL_2_DATA_PATHS
+                        | TX_DIGITAL_INTERPOLATE_4X)
+};
+
+
+static int
+real_tx_mux_value (int mux, int nchan)
+{
+  if (mux != -1)
+    return mux;
+
+  switch (nchan){
+  case 1:
+    return 0x0098;
+  case 2:
+    return 0xba98;
+  default:
+    assert (0);
+  }
+}
+
+usrp_standard_tx::usrp_standard_tx (int which_board,
+                                   unsigned int interp_rate,
+                                   int nchan, int mux,
+                                   int fusb_block_size, int fusb_nblocks,
+                                   const std::string fpga_filename,
+                                   const std::string firmware_filename
+                                   )
+  : usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename),
+    usrp_standard_common(this),
+    d_sw_mux (0x8), d_hw_mux (0x81)
+{
+  if (!usrp_9862_write_many_all (d_udh, tx_regs_use_nco, sizeof (tx_regs_use_nco))){
+    fprintf (stderr, "usrp_standard_tx: failed to init AD9862 TX regs\n");
+    throw std::runtime_error ("usrp_standard_tx::ctor");
+  }
+  if (!set_nchannels (nchan)){
+    fprintf (stderr, "usrp_standard_tx: set_nchannels failed\n");
+    throw std::runtime_error ("usrp_standard_tx::ctor");
+  }
+  if (!set_interp_rate (interp_rate)){
+    fprintf (stderr, "usrp_standard_tx: set_interp_rate failed\n");
+    throw std::runtime_error ("usrp_standard_tx::ctor");
+  }
+  if (!set_mux (real_tx_mux_value (mux, nchan))){
+    fprintf (stderr, "usrp_standard_tx: set_mux failed\n");
+    throw std::runtime_error ("usrp_standard_tx::ctor");
+  }
+
+  for (int i = 0; i < MAX_CHAN; i++){
+    d_tx_modulator_shadow[i] = (TX_MODULATOR_DISABLE_NCO
+                               | TX_MODULATOR_COARSE_MODULATION_NONE);
+    d_coarse_mod[i] = CM_OFF;
+    set_tx_freq (i, 0);
+  }
+}
+
+usrp_standard_tx::~usrp_standard_tx ()
+{
+  // fprintf(stderr, "\nusrp_standard_tx: dtor\n");
+}
+
+bool
+usrp_standard_tx::start ()
+{
+  if (!usrp_basic_tx::start ())
+    return false;
+
+  // add our code here
+
+  return true;
+}
+
+bool
+usrp_standard_tx::stop ()
+{
+  bool ok = usrp_basic_tx::stop ();
+
+  // add our code here
+
+  return ok;
+}
+
+usrp_standard_tx *
+usrp_standard_tx::make (int which_board,
+                       unsigned int interp_rate,
+                       int nchan, int mux,
+                       int fusb_block_size, int fusb_nblocks,
+                       const std::string fpga_filename,
+                       const std::string firmware_filename
+                       )
+{
+  usrp_standard_tx *u = 0;
+  
+  try {
+    u = new usrp_standard_tx (which_board, interp_rate, nchan, mux,
+                             fusb_block_size, fusb_nblocks,
+                             fpga_filename, firmware_filename);
+    return u;
+  }
+  catch (...){
+    delete u;
+    return 0;
+  }
+
+  return u;
+}
+
+bool
+usrp_standard_tx::set_interp_rate (unsigned int rate)
+{
+  // fprintf (stderr, "usrp_standard_tx::set_interp_rate\n");
+
+  if ((rate & 0x3) || rate < 4 || rate > 512){
+    fprintf (stderr, "usrp_standard_tx::set_interp_rate: rate must be in [4, 512] and a multiple of 4.\n");
+    return false;
+  }
+
+  d_interp_rate = rate;
+  set_usb_data_rate ((dac_rate () / rate * nchannels ())
+                    * (2 * sizeof (short)));
+
+  // We're using the interp by 4 feature of the 9862 so that we can
+  // use its fine modulator.  Thus, we reduce the FPGA's interpolation rate
+  // by a factor of 4.
+
+  bool s = disable_tx ();
+  bool ok = _write_fpga_reg (FR_INTERP_RATE, d_interp_rate/4 - 1);
+  restore_tx (s);
+  return ok;
+}
+
+bool
+usrp_standard_tx::set_nchannels (int nchan)
+{
+  if (!(nchan == 1 || nchan == 2))
+    return false;
+
+  if (nchan > nducs())
+    return false;
+
+  d_nchan = nchan;
+  return write_hw_mux_reg ();
+}
+
+bool
+usrp_standard_tx::set_mux (int mux)
+{
+  d_sw_mux = mux;
+  d_hw_mux = mux << 4;
+  return write_hw_mux_reg ();
+}
+
+bool
+usrp_standard_tx::write_hw_mux_reg ()
+{
+  bool s = disable_tx ();
+  bool ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan);
+  restore_tx (s);
+  return ok;
+}
+
+#ifdef USE_FPGA_TX_CORDIC
+
+bool
+usrp_standard_tx::set_tx_freq (int channel, double freq)
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return false;
+
+  // This assumes we're running the 4x on-chip interpolator.
+
+  unsigned int v =
+    compute_freq_control_word_fpga (dac_freq () / 4,
+                                   freq, &d_tx_freq[channel],
+                                   d_verbose);
+
+  return _write_fpga_reg (FR_TX_FREQ_0 + channel, v);
+}
+
+
+#else
+
+bool
+usrp_standard_tx::set_tx_freq (int channel, double freq)
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return false;
+
+  // split freq into fine and coarse components
+
+  coarse_mod_t cm;
+  double       coarse;
+
+  assert (dac_freq () == 128000000);
+
+  if (freq < -44e6)            // too low
+    return false;
+  else if (freq < -24e6){      // [-44, -24)
+    cm = CM_NEG_FDAC_OVER_4;
+    coarse = -dac_freq () / 4;
+  }
+  else if (freq < -8e6){       // [-24, -8)
+    cm = CM_NEG_FDAC_OVER_8;
+    coarse = -dac_freq () / 8;
+  }
+  else if (freq < 8e6){                // [-8, 8)
+    cm = CM_OFF;
+    coarse = 0;
+  }
+  else if (freq < 24e6){       // [8, 24)
+    cm = CM_POS_FDAC_OVER_8;
+    coarse = dac_freq () / 8;
+  }
+  else if (freq <= 44e6){      // [24, 44]
+    cm = CM_POS_FDAC_OVER_4;
+    coarse = dac_freq () / 4;
+  }
+  else                         // too high
+    return false;
+
+
+  set_coarse_modulator (channel, cm);  // set bits in d_tx_modulator_shadow
+
+  double fine = freq - coarse;
+
+
+  // Compute fine tuning word...
+  // This assumes we're running the 4x on-chip interpolator.
+  // (This is required to use the fine modulator.)
+
+  unsigned int v =
+    compute_freq_control_word_9862 (dac_freq () / 4,
+                                   fine, &d_tx_freq[channel], d_verbose);
+
+  d_tx_freq[channel] += coarse;                // adjust actual
+  
+  unsigned char high, mid, low;
+
+  high = (v >> 16) & 0xff;
+  mid =  (v >>  8) & 0xff;
+  low =  (v >>  0) & 0xff;
+
+  bool ok = true;
+
+  // write the fine tuning word
+  ok &= _write_9862 (channel, REG_TX_NCO_FTW_23_16, high);
+  ok &= _write_9862 (channel, REG_TX_NCO_FTW_15_8,  mid);
+  ok &= _write_9862 (channel, REG_TX_NCO_FTW_7_0,   low);
+
+
+  d_tx_modulator_shadow[channel] |= TX_MODULATOR_ENABLE_NCO;
+
+  if (fine < 0)
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_FINE_TUNE;
+  else
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_NEG_FINE_TUNE;
+
+  ok &=_write_9862 (channel, REG_TX_MODULATOR, d_tx_modulator_shadow[channel]);
+
+  return ok;
+}
+#endif
+
+bool
+usrp_standard_tx::set_coarse_modulator (int channel, coarse_mod_t cm)
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return false;
+
+  switch (cm){
+  case CM_NEG_FDAC_OVER_4:
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
+    break;
+
+  case CM_NEG_FDAC_OVER_8:
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
+    break;
+
+  case CM_OFF:
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
+    break;
+
+  case CM_POS_FDAC_OVER_8:
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
+    break;
+
+  case CM_POS_FDAC_OVER_4:
+    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
+    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
+    break;
+
+  default:
+    return false;
+  }
+
+  d_coarse_mod[channel] = cm;
+  return true;
+}
+
+unsigned int
+usrp_standard_tx::interp_rate () const { return d_interp_rate; }
+
+int
+usrp_standard_tx::nchannels () const { return d_nchan; }
+
+int
+usrp_standard_tx::mux () const { return d_sw_mux; }
+
+double
+usrp_standard_tx::tx_freq (int channel) const
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return 0;
+
+  return d_tx_freq[channel];
+}
+
+usrp_standard_tx::coarse_mod_t
+usrp_standard_tx::coarse_modulator (int channel) const
+{
+  if (channel < 0 || channel >= MAX_CHAN)
+    return CM_OFF;
+
+  return d_coarse_mod[channel];
+}
diff --git a/usrp/host/lib/legacy/usrp_standard.h b/usrp/host/lib/legacy/usrp_standard.h
new file mode 100644 (file)
index 0000000..6fee4b9
--- /dev/null
@@ -0,0 +1,366 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP_STANDARD_H
+#define INCLUDED_USRP_STANDARD_H
+
+#include <usrp_basic.h>
+
+class usrp_standard_common
+{
+  int                  d_fpga_caps;            // capability register val
+
+protected:
+  usrp_standard_common(usrp_basic *parent);
+
+public:
+  /*!
+   *\brief does the FPGA implement the final Rx half-band filter?
+   * If it doesn't, the maximum decimation factor with proper gain 
+   * is 1/2 of what it would otherwise be.
+   */
+  bool has_rx_halfband() const;
+
+  /*!
+   * \brief number of digital downconverters implemented in the FPGA
+   * This will be 0, 1, 2 or 4.
+   */
+  int nddcs() const;
+
+  /*!
+   *\brief does the FPGA implement the initial Tx half-band filter?
+   */
+  bool has_tx_halfband() const;
+
+  /*!
+   * \brief number of digital upconverters implemented in the FPGA
+   * This will be 0, 1, or 2.
+   */
+  int nducs() const;
+};
+
+/*!
+ * \brief standard usrp RX class.  
+ *
+ * Assumes digital down converter in FPGA
+ */
+class usrp_standard_rx : public usrp_basic_rx, usrp_standard_common
+{
+ private:
+  static const int     MAX_CHAN = 4;
+  unsigned int         d_decim_rate;
+  int                  d_nchan;
+  int                  d_sw_mux;
+  int                  d_hw_mux;
+  double               d_rx_freq[MAX_CHAN];
+
+ protected:
+  usrp_standard_rx (int which_board,
+                   unsigned int decim_rate,
+                   int nchan = 1,
+                   int mux = -1,
+                   int mode = 0,
+                   int fusb_block_size = 0,
+                   int fusb_nblocks = 0,
+                   const std::string fpga_filename = "",
+                   const std::string firmware_filename = ""
+                   );  // throws if trouble
+
+  bool write_hw_mux_reg ();
+
+ public:
+
+  enum {
+    FPGA_MODE_NORMAL     = 0x00,
+    FPGA_MODE_LOOPBACK   = 0x01,
+    FPGA_MODE_COUNTING   = 0x02,
+    FPGA_MODE_COUNTING_32BIT   = 0x04
+  };
+
+  ~usrp_standard_rx ();
+
+  /*!
+   * \brief invokes constructor, returns instance or 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   */
+  static usrp_standard_rx *make (int which_board,
+                                unsigned int decim_rate,
+                                int nchan = 1,
+                                int mux = -1,
+                                int mode = 0,
+                                int fusb_block_size = 0,
+                                int fusb_nblocks = 0,
+                                const std::string fpga_filename = "",
+                                const std::string firmware_filename = ""
+                                );
+  /*!
+   * \brief Set decimator rate.  \p rate MUST BE EVEN and in [8, 256].
+   *
+   * The final complex sample rate across the USB is
+   *   adc_freq () / decim_rate () * nchannels ()
+   */
+  bool set_decim_rate  (unsigned int rate);
+
+  /*!
+   * \brief Set number of active channels.  \p nchannels must be 1, 2 or 4.
+   *
+   * The final complex sample rate across the USB is
+   *   adc_freq () / decim_rate () * nchannels ()
+   */
+  bool set_nchannels (int nchannels);
+
+  /*!
+   * \brief Set input mux configuration.
+   *
+   * This determines which ADC (or constant zero) is connected to 
+   * each DDC input.  There are 4 DDCs.  Each has two inputs.
+   *
+   * <pre>
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 4-bit I field is either 0,1,2,3
+   * Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
+   * All Q's must be 0xf or none of them may be 0xf
+   * </pre>
+   */
+  bool set_mux  (int mux);
+
+  /*!
+   * \brief set the frequency of the digital down converter.
+   *
+   * \p channel must be in the range [0,3].  \p freq is the center
+   * frequency in Hz.  \p freq may be either negative or postive.
+   * The frequency specified is quantized.  Use rx_freq to retrieve
+   * the actual value used.
+   */
+  bool set_rx_freq (int channel, double freq);  
+
+  /*!
+   * \brief set fpga mode
+   */
+  bool set_fpga_mode (int mode);
+
+  /*!
+   * \brief Set the digital down converter phase register.
+   *
+   * \param channel    which ddc channel [0, 3]
+   * \param phase      32-bit integer phase value.
+   */
+  bool set_ddc_phase(int channel, int phase);
+
+  /*!
+   * \brief Specify Rx data format.
+   *
+   * \param format     format specifier
+   *
+   * Rx data format control register
+   *
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-----------------------------------------+-+-+---------+-------+
+   *  |          Reserved (Must be zero)        |B|Q|  WIDTH  | SHIFT |
+   *  +-----------------------------------------+-+-+---------+-------+
+   *
+   *  SHIFT specifies arithmetic right shift [0, 15]
+   *  WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid)
+   *  Q     if set deliver both I & Q, else just I
+   *  B     if set bypass half-band filter.
+   *
+   * Right now the acceptable values are:
+   *
+   *   B  Q  WIDTH  SHIFT
+   *   0  1    16     0
+   *   0  1     8     8
+   *
+   * More valid combos to come.
+   *
+   * Default value is 0x00000300  16-bits, 0 shift, deliver both I & Q.
+   */
+  bool set_format(unsigned int format);
+
+  static unsigned int make_format(int width=16, int shift=0,
+                                 bool want_q=true, bool bypass_halfband=false);
+  static int format_width(unsigned int format);
+  static int format_shift(unsigned int format);
+  static bool format_want_q(unsigned int format);
+  static bool format_bypass_halfband(unsigned int format);
+
+  // ACCESSORS
+  unsigned int decim_rate () const;
+  double rx_freq (int channel) const;
+  int nchannels () const;
+  int mux () const;
+  unsigned int format () const;
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+// ----------------------------------------------------------------
+
+/*!
+ * \brief standard usrp TX class.
+ *
+ * Uses digital upconverter (coarse & fine modulators) in AD9862...
+ */
+class usrp_standard_tx : public usrp_basic_tx, usrp_standard_common
+{
+ public:
+  enum coarse_mod_t {
+    CM_NEG_FDAC_OVER_4,                // -32 MHz
+    CM_NEG_FDAC_OVER_8,                // -16 MHz
+    CM_OFF,
+    CM_POS_FDAC_OVER_8,                // +16 MHz
+    CM_POS_FDAC_OVER_4         // +32 MHz
+  };
+
+ protected:
+  static const int     MAX_CHAN = 2;
+  unsigned int         d_interp_rate;
+  int                  d_nchan;
+  int                  d_sw_mux;
+  int                  d_hw_mux;
+  double               d_tx_freq[MAX_CHAN];
+  coarse_mod_t         d_coarse_mod[MAX_CHAN];
+  unsigned char                d_tx_modulator_shadow[MAX_CHAN];
+
+  virtual bool set_coarse_modulator (int channel, coarse_mod_t cm);
+  usrp_standard_tx::coarse_mod_t coarse_modulator (int channel) const;
+
+ protected:
+  usrp_standard_tx (int which_board,
+                   unsigned int interp_rate,
+                   int nchan = 1,
+                   int mux = -1,
+                   int fusb_block_size = 0,
+                   int fusb_nblocks = 0,
+                   const std::string fpga_filename = "",
+                   const std::string firmware_filename = ""
+                   );  // throws if trouble
+
+  bool write_hw_mux_reg ();
+
+ public:
+  ~usrp_standard_tx ();
+
+  /*!
+   * \brief invokes constructor, returns instance or 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   */
+  static usrp_standard_tx *make (int which_board,
+                                unsigned int interp_rate,
+                                int nchan = 1,
+                                int mux = -1,
+                                int fusb_block_size = 0,
+                                int fusb_nblocks = 0,
+                                const std::string fpga_filename = "",
+                                const std::string firmware_filename = ""
+                                );
+
+  /*!
+   * \brief Set interpolator rate.  \p rate must be in [4, 512] and a multiple of 4.
+   *
+   * The final complex sample rate across the USB is
+   *   dac_freq () / interp_rate () * nchannels ()
+   */
+  virtual bool set_interp_rate (unsigned int rate);
+
+  /*!
+   * \brief Set number of active channels.  \p nchannels must be 1 or 2.
+   *
+   * The final complex sample rate across the USB is
+   *   dac_freq () / decim_rate () * nchannels ()
+   */
+  bool set_nchannels  (int nchannels);
+
+  /*!
+   * \brief Set output mux configuration.
+   *
+   * <pre>
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                               | DAC3  | DAC2  | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are two interpolators with complex inputs and outputs.
+   *  There are four DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC and
+   *  whether or not that DAC is enabled.  Each subfield is coded
+   *  like this: 
+   * 
+   *     3 2 1 0
+   *    +-+-----+
+   *    |E|  N  |
+   *    +-+-----+
+   * 
+   *  Where E is set if the DAC is enabled, and N specifies which
+   *  interpolator output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   chan 0 I
+   *   1   chan 0 Q
+   *   2   chan 1 I
+   *   3   chan 1 Q
+   * </pre>
+   */
+  bool set_mux  (int mux);
+
+  /*!
+   * \brief set the frequency of the digital up converter.
+   *
+   * \p channel must be in the range [0,1].  \p freq is the center
+   * frequency in Hz.  It must be in the range [-44M, 44M].
+   * The frequency specified is quantized.  Use tx_freq to retrieve
+   * the actual value used.
+   */
+  virtual bool set_tx_freq (int channel, double freq);  // chan: [0,1]
+
+  // ACCESSORS
+  unsigned int interp_rate () const;
+  double tx_freq (int channel) const;
+  int nchannels () const;
+  int mux () const;
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+#endif /* INCLUDED_USRP_STANDARD_H */
diff --git a/usrp/host/lib/md5.c b/usrp/host/lib/md5.c
deleted file mode 100644 (file)
index abee067..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/* md5.c - Functions to compute MD5 message digest of files or memory blocks
-   according to the definition of MD5 in RFC 1321 from April 1992.
-   Copyright (C) 1995, 1996, 2001, 2003 Free Software Foundation, Inc.
-   NOTE: The canonical source of this file is maintained with the GNU C
-   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.  */
-
-/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "md5.h"
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-// #include "unlocked-io.h"
-
-#ifdef _LIBC
-# include <endian.h>
-# if __BYTE_ORDER == __BIG_ENDIAN
-#  define WORDS_BIGENDIAN 1
-# endif
-/* We need to keep the namespace clean so define the MD5 function
-   protected using leading __ .  */
-# define md5_init_ctx __md5_init_ctx
-# define md5_process_block __md5_process_block
-# define md5_process_bytes __md5_process_bytes
-# define md5_finish_ctx __md5_finish_ctx
-# define md5_read_ctx __md5_read_ctx
-# define md5_stream __md5_stream
-# define md5_buffer __md5_buffer
-#endif
-
-#ifdef WORDS_BIGENDIAN
-# define SWAP(n)                                                       \
-    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-#else
-# define SWAP(n) (n)
-#endif
-
-#define BLOCKSIZE 4096
-/* Ensure that BLOCKSIZE is a multiple of 64.  */
-#if BLOCKSIZE % 64 != 0
-/* FIXME-someday (soon?): use #error instead of this kludge.  */
-"invalid BLOCKSIZE"
-#endif
-
-/* This array contains the bytes used to pad the buffer to the next
-   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
-static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
-
-
-/* Initialize structure containing state of computation.
-   (RFC 1321, 3.3: Step 3)  */
-void
-md5_init_ctx (struct md5_ctx *ctx)
-{
-  ctx->A = 0x67452301;
-  ctx->B = 0xefcdab89;
-  ctx->C = 0x98badcfe;
-  ctx->D = 0x10325476;
-
-  ctx->total[0] = ctx->total[1] = 0;
-  ctx->buflen = 0;
-}
-
-/* Put result from CTX in first 16 bytes following RESBUF.  The result
-   must be in little endian byte order.
-
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
-void *
-md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
-{
-  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
-  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
-  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
-  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
-
-  return resbuf;
-}
-
-/* Process the remaining bytes in the internal buffer and the usual
-   prolog according to the standard and write the result to RESBUF.
-
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
-void *
-md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
-{
-  /* Take yet unprocessed bytes into account.  */
-  md5_uint32 bytes = ctx->buflen;
-  size_t pad;
-
-  /* Now count remaining bytes.  */
-  ctx->total[0] += bytes;
-  if (ctx->total[0] < bytes)
-    ++ctx->total[1];
-
-  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
-  memcpy (&ctx->buffer[bytes], fillbuf, pad);
-
-  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
-  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
-  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
-                                                       (ctx->total[0] >> 29));
-
-  /* Process last bytes.  */
-  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
-
-  return md5_read_ctx (ctx, resbuf);
-}
-
-/* Compute MD5 message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 16 bytes
-   beginning at RESBLOCK.  */
-int
-md5_stream (FILE *stream, void *resblock)
-{
-  struct md5_ctx ctx;
-  char buffer[BLOCKSIZE + 72];
-  size_t sum;
-
-  /* Initialize the computation context.  */
-  md5_init_ctx (&ctx);
-
-  /* Iterate over full file contents.  */
-  while (1)
-    {
-      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
-        computation function processes the whole buffer so that with the
-        next round of the loop another block can be read.  */
-      size_t n;
-      sum = 0;
-
-      /* Read block.  Take care for partial reads.  */
-      while (1)
-       {
-         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
-         sum += n;
-
-         if (sum == BLOCKSIZE)
-           break;
-
-         if (n == 0)
-           {
-             /* Check for the error flag IFF N == 0, so that we don't
-                exit the loop after a partial read due to e.g., EAGAIN
-                or EWOULDBLOCK.  */
-             if (ferror (stream))
-               return 1;
-             goto process_partial_block;
-           }
-
-         /* We've read at least one byte, so ignore errors.  But always
-            check for EOF, since feof may be true even though N > 0.
-            Otherwise, we could end up calling fread after EOF.  */
-         if (feof (stream))
-           goto process_partial_block;
-       }
-
-      /* Process buffer with BLOCKSIZE bytes.  Note that
-                       BLOCKSIZE % 64 == 0
-       */
-      md5_process_block (buffer, BLOCKSIZE, &ctx);
-    }
-
- process_partial_block:;
-
-  /* Process any remaining bytes.  */
-  if (sum > 0)
-    md5_process_bytes (buffer, sum, &ctx);
-
-  /* Construct result in desired memory.  */
-  md5_finish_ctx (&ctx, resblock);
-  return 0;
-}
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-   result is always in little endian byte order, so that a byte-wise
-   output yields to the wanted ASCII representation of the message
-   digest.  */
-void *
-md5_buffer (const char *buffer, size_t len, void *resblock)
-{
-  struct md5_ctx ctx;
-
-  /* Initialize the computation context.  */
-  md5_init_ctx (&ctx);
-
-  /* Process whole buffer but last len % 64 bytes.  */
-  md5_process_bytes (buffer, len, &ctx);
-
-  /* Put result in desired memory area.  */
-  return md5_finish_ctx (&ctx, resblock);
-}
-
-
-void
-md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
-{
-  /* When we already have some bits in our internal buffer concatenate
-     both inputs first.  */
-  if (ctx->buflen != 0)
-    {
-      size_t left_over = ctx->buflen;
-      size_t add = 128 - left_over > len ? len : 128 - left_over;
-
-      memcpy (&ctx->buffer[left_over], buffer, add);
-      ctx->buflen += add;
-
-      if (ctx->buflen > 64)
-       {
-         md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
-
-         ctx->buflen &= 63;
-         /* The regions in the following copy operation cannot overlap.  */
-         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
-                 ctx->buflen);
-       }
-
-      buffer = (const char *) buffer + add;
-      len -= add;
-    }
-
-  /* Process available complete blocks.  */
-  if (len >= 64)
-    {
-#if !_STRING_ARCH_unaligned
-/* To check alignment gcc has an appropriate operator.  Other
-   compilers don't.  */
-# if __GNUC__ >= 2
-#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
-# else
-#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
-# endif
-      if (UNALIGNED_P (buffer))
-       while (len > 64)
-         {
-           md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
-           buffer = (const char *) buffer + 64;
-           len -= 64;
-         }
-      else
-#endif
-       {
-         md5_process_block (buffer, len & ~63, ctx);
-         buffer = (const char *) buffer + (len & ~63);
-         len &= 63;
-       }
-    }
-
-  /* Move remaining bytes in internal buffer.  */
-  if (len > 0)
-    {
-      size_t left_over = ctx->buflen;
-
-      memcpy (&ctx->buffer[left_over], buffer, len);
-      left_over += len;
-      if (left_over >= 64)
-       {
-         md5_process_block (ctx->buffer, 64, ctx);
-         left_over -= 64;
-         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
-       }
-      ctx->buflen = left_over;
-    }
-}
-
-
-/* These are the four functions used in the four steps of the MD5 algorithm
-   and defined in the RFC 1321.  The first function is a little bit optimized
-   (as found in Colin Plumbs public domain implementation).  */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
-/* Process LEN bytes of BUFFER, accumulating context into CTX.
-   It is assumed that LEN % 64 == 0.  */
-
-void
-md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
-{
-  md5_uint32 correct_words[16];
-  const md5_uint32 *words = buffer;
-  size_t nwords = len / sizeof (md5_uint32);
-  const md5_uint32 *endp = words + nwords;
-  md5_uint32 A = ctx->A;
-  md5_uint32 B = ctx->B;
-  md5_uint32 C = ctx->C;
-  md5_uint32 D = ctx->D;
-
-  /* First increment the byte count.  RFC 1321 specifies the possible
-     length of the file up to 2^64 bits.  Here we only compute the
-     number of bytes.  Do a double word increment.  */
-  ctx->total[0] += len;
-  if (ctx->total[0] < len)
-    ++ctx->total[1];
-
-  /* Process all bytes in the buffer with 64 bytes in each round of
-     the loop.  */
-  while (words < endp)
-    {
-      md5_uint32 *cwp = correct_words;
-      md5_uint32 A_save = A;
-      md5_uint32 B_save = B;
-      md5_uint32 C_save = C;
-      md5_uint32 D_save = D;
-
-      /* First round: using the given function, the context and a constant
-        the next context is computed.  Because the algorithms processing
-        unit is a 32-bit word and it is determined to work on words in
-        little endian byte order we perhaps have to change the byte order
-        before the computation.  To reduce the work for the next steps
-        we store the swapped words in the array CORRECT_WORDS.  */
-
-#define OP(a, b, c, d, s, T)                                           \
-      do                                                               \
-        {                                                              \
-         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
-         ++words;                                                      \
-         a = rol (a, s);                                               \
-         a += b;                                                       \
-        }                                                              \
-      while (0)
-
-      /* Before we start, one word to the strange constants.
-        They are defined in RFC 1321 as
-
-        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or
-        perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}'
-       */
-
-      /* Round 1.  */
-      OP (A, B, C, D,  7, 0xd76aa478);
-      OP (D, A, B, C, 12, 0xe8c7b756);
-      OP (C, D, A, B, 17, 0x242070db);
-      OP (B, C, D, A, 22, 0xc1bdceee);
-      OP (A, B, C, D,  7, 0xf57c0faf);
-      OP (D, A, B, C, 12, 0x4787c62a);
-      OP (C, D, A, B, 17, 0xa8304613);
-      OP (B, C, D, A, 22, 0xfd469501);
-      OP (A, B, C, D,  7, 0x698098d8);
-      OP (D, A, B, C, 12, 0x8b44f7af);
-      OP (C, D, A, B, 17, 0xffff5bb1);
-      OP (B, C, D, A, 22, 0x895cd7be);
-      OP (A, B, C, D,  7, 0x6b901122);
-      OP (D, A, B, C, 12, 0xfd987193);
-      OP (C, D, A, B, 17, 0xa679438e);
-      OP (B, C, D, A, 22, 0x49b40821);
-
-      /* For the second to fourth round we have the possibly swapped words
-        in CORRECT_WORDS.  Redefine the macro to take an additional first
-        argument specifying the function to use.  */
-#undef OP
-#define OP(f, a, b, c, d, k, s, T)                                     \
-      do                                                               \
-       {                                                               \
-         a += f (b, c, d) + correct_words[k] + T;                      \
-         a = rol (a, s);                                               \
-         a += b;                                                       \
-       }                                                               \
-      while (0)
-
-      /* Round 2.  */
-      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
-      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
-      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
-      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
-      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
-      OP (FG, D, A, B, C, 10,  9, 0x02441453);
-      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
-      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
-      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
-      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
-      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
-      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
-      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
-      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
-      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
-      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
-      /* Round 3.  */
-      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
-      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
-      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
-      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
-      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
-      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
-      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
-      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
-      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
-      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
-      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
-      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
-      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
-      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
-      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
-      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
-
-      /* Round 4.  */
-      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
-      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
-      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
-      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
-      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
-      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
-      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
-      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
-      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
-      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
-      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
-      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
-      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
-      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
-      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
-      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
-
-      /* Add the starting values of the context.  */
-      A += A_save;
-      B += B_save;
-      C += C_save;
-      D += D_save;
-    }
-
-  /* Put checksum in context given as argument.  */
-  ctx->A = A;
-  ctx->B = B;
-  ctx->C = C;
-  ctx->D = D;
-}
diff --git a/usrp/host/lib/md5.h b/usrp/host/lib/md5.h
deleted file mode 100644 (file)
index 709cefb..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* md5.h - Declaration of functions and data types used for MD5 sum
-   computing library functions.
-   Copyright (C) 1995, 1996, 1999, 2000, 2003 Free Software Foundation, Inc.
-   NOTE: The canonical source of this file is maintained with the GNU C
-   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.  */
-
-#ifndef _MD5_H
-#define _MD5_H 1
-
-#include <stdio.h>
-#include <limits.h>
-
-/* The following contortions are an attempt to use the C preprocessor
-   to determine an unsigned integral type that is 32 bits wide.  An
-   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
-   doing that would require that the configure script compile and *run*
-   the resulting executable.  Locally running cross-compiled executables
-   is usually not possible.  */
-
-#ifdef _LIBC
-# include <stdint.h>
-typedef uint32_t md5_uint32;
-typedef uintptr_t md5_uintptr;
-#else
-# define UINT_MAX_32_BITS 4294967295U
-
-# if UINT_MAX == UINT_MAX_32_BITS
-   typedef unsigned int md5_uint32;
-# else
-#  if USHRT_MAX == UINT_MAX_32_BITS
-    typedef unsigned short md5_uint32;
-#  else
-#   if ULONG_MAX == UINT_MAX_32_BITS
-     typedef unsigned long md5_uint32;
-#   else
-     /* The following line is intended to evoke an error.
-        Using #error is not portable enough.  */
-     "Cannot determine unsigned 32-bit data type."
-#   endif
-#  endif
-# endif
-/* We have to make a guess about the integer type equivalent in size
-   to pointers which should always be correct.  */
-typedef unsigned long int md5_uintptr;
-#endif
-
-/* Structure to save state of computation between the single steps.  */
-struct md5_ctx
-{
-  md5_uint32 A;
-  md5_uint32 B;
-  md5_uint32 C;
-  md5_uint32 D;
-
-  md5_uint32 total[2];
-  md5_uint32 buflen;
-  char buffer[128];
-};
-
-/*
- * The following three functions are build up the low level used in
- * the functions `md5_stream' and `md5_buffer'.
- */
-
-/* Initialize structure containing state of computation.
-   (RFC 1321, 3.3: Step 3)  */
-extern void md5_init_ctx (struct md5_ctx *ctx);
-
-/* Starting with the result of former calls of this function (or the
-   initialization function update the context for the next LEN bytes
-   starting at BUFFER.
-   It is necessary that LEN is a multiple of 64!!! */
-extern void md5_process_block (const void *buffer, size_t len,
-                              struct md5_ctx *ctx);
-
-/* Starting with the result of former calls of this function (or the
-   initialization function update the context for the next LEN bytes
-   starting at BUFFER.
-   It is NOT required that LEN is a multiple of 64.  */
-extern void md5_process_bytes (const void *buffer, size_t len,
-                              struct md5_ctx *ctx);
-
-/* Process the remaining bytes in the buffer and put result from CTX
-   in first 16 bytes following RESBUF.  The result is always in little
-   endian byte order, so that a byte-wise output yields to the wanted
-   ASCII representation of the message digest.
-
-   IMPORTANT: On some systems it is required that RESBUF be correctly
-   aligned for a 32 bits value.  */
-extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf);
-
-
-/* Put result from CTX in first 16 bytes following RESBUF.  The result is
-   always in little endian byte order, so that a byte-wise output yields
-   to the wanted ASCII representation of the message digest.
-
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
-extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf);
-
-
-/* Compute MD5 message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 16 bytes
-   beginning at RESBLOCK.  */
-extern int md5_stream (FILE *stream, void *resblock);
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-   result is always in little endian byte order, so that a byte-wise
-   output yields to the wanted ASCII representation of the message
-   digest.  */
-extern void *md5_buffer (const char *buffer, size_t len, void *resblock);
-
-#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#endif
diff --git a/usrp/host/lib/mld_threads.h b/usrp/host/lib/mld_threads.h
deleted file mode 100644 (file)
index 08b3555..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio.
- *
- * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
- * 
- * 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _INCLUDED_MLD_THREADS_H_
-#define _INCLUDED_MLD_THREADS_H_
-
-/* classes which allow for either pthreads or omni_threads */
-
-#ifdef _USE_OMNI_THREADS_
-#include <gnuradio/omnithread.h>
-#else
-#include <pthread.h>
-#endif
-
-#include <stdexcept>
-
-#define __INLINE__ inline
-
-class mld_condition_t;
-
-class mld_mutex_t {
-#ifdef _USE_OMNI_THREADS_
-  typedef omni_mutex l_mutex, *l_mutex_ptr;
-#else
-  typedef pthread_mutex_t l_mutex, *l_mutex_ptr;
-#endif
-
-  friend class mld_condition_t;
-
-private:
-  l_mutex_ptr d_mutex;
-
-protected:
-  inline l_mutex_ptr mutex () { return (d_mutex); };
-
-public:
-  __INLINE__ mld_mutex_t () {
-#ifdef _USE_OMNI_THREADS_
-    d_mutex = new omni_mutex ();
-#else
-    d_mutex = (l_mutex_ptr) new l_mutex;
-    int l_ret = pthread_mutex_init (d_mutex, NULL);
-    if (l_ret != 0) {
-      fprintf (stderr, "Error %d creating mutex.\n", l_ret);
-      throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n");
-    }
-#endif
-  };
-
-  __INLINE__ ~mld_mutex_t () {
-    unlock ();
-#ifndef _USE_OMNI_THREADS_
-    int l_ret = pthread_mutex_destroy (d_mutex);
-    if (l_ret != 0) {
-      fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): "
-              "Error %d destroying mutex.\n", l_ret);
-    }
-#endif
-    delete d_mutex;
-    d_mutex = NULL;
-  };
-
-  __INLINE__ void lock () {
-#ifdef _USE_OMNI_THREADS_
-    d_mutex->lock ();
-#else
-    int l_ret = pthread_mutex_lock (d_mutex);
-    if (l_ret != 0) {
-      fprintf (stderr, "mld_mutex_t::lock(): "
-              "Error %d locking mutex.\n", l_ret);
-    }
-#endif
-  };
-
-  __INLINE__ void unlock () {
-#ifdef _USE_OMNI_THREADS_
-    d_mutex->unlock ();
-#else
-    int l_ret = pthread_mutex_unlock (d_mutex);
-    if (l_ret != 0) {
-      fprintf (stderr, "mld_mutex_t::unlock(): "
-              "Error %d locking mutex.\n", l_ret);
-    }
-#endif
-  };
-
-  __INLINE__ bool trylock () {
-#ifdef _USE_OMNI_THREADS_
-    int l_ret = d_mutex->trylock ();
-#else
-    int l_ret = pthread_mutex_unlock (d_mutex);
-#endif
-    return (l_ret == 0 ? true : false);
-  };
-
-  inline void acquire () { lock(); };
-  inline void release () { unlock(); };
-  inline void wait () { lock(); };
-  inline void post () { unlock(); };
-};
-
-typedef mld_mutex_t mld_mutex, *mld_mutex_ptr;
-
-class mld_condition_t {
-#ifdef _USE_OMNI_THREADS_
-  typedef omni_condition l_condition, *l_condition_ptr;
-#else
-  typedef pthread_cond_t l_condition, *l_condition_ptr;
-#endif
-
-private:
-  l_condition_ptr d_condition;
-  mld_mutex_ptr d_mutex;
-  bool d_waiting;
-
-public:
-  __INLINE__ mld_condition_t () {
-    d_waiting = false;
-    d_mutex = new mld_mutex ();
-#ifdef _USE_OMNI_THREADS_
-    d_condition = new omni_condition (d_mutex->mutex ());
-#else
-    d_condition = (l_condition_ptr) new l_condition;
-    int l_ret = pthread_cond_init (d_condition, NULL);
-    if (l_ret != 0) {
-      fprintf (stderr, "Error %d creating condition.\n", l_ret);
-      throw std::runtime_error ("mld_condition_t::mld_condition_t()\n");
-    }
-#endif
-  };
-
-  __INLINE__ ~mld_condition_t () {
-    signal ();
-#ifndef _USE_OMNI_THREADS_
-    int l_ret = pthread_cond_destroy (d_condition);
-    if (l_ret != 0) {
-      fprintf (stderr, "mld_condition_t::mld_condition_t(): "
-              "Error %d destroying condition.\n", l_ret);
-    }
-#endif
-    delete d_condition;
-    d_condition = NULL;
-    delete d_mutex;
-    d_mutex = NULL;
-  };
-
-  __INLINE__ void signal () {
-    if (d_waiting == true) {
-#ifdef _USE_OMNI_THREADS_
-      d_condition->signal ();
-#else
-      int l_ret = pthread_cond_signal (d_condition);
-      if (l_ret != 0) {
-       fprintf (stderr, "mld_condition_t::signal(): "
-                "Error %d.\n", l_ret);
-      }
-#endif
-      d_waiting = false;
-    }
-  };
-
-  __INLINE__ void wait () {
-    if (d_waiting == false) {
-      d_waiting = true;
-#ifdef _USE_OMNI_THREADS_
-      d_condition->wait ();
-#else
-      int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ());
-      if (l_ret != 0) {
-       fprintf (stderr, "mld_condition_t::wait(): "
-                "Error %d.\n", l_ret);
-      }
-#endif
-    }
-  };
-};
-
-typedef mld_condition_t mld_condition, *mld_condition_ptr;
-
-class mld_thread_t {
-#ifdef _USE_OMNI_THREADS_
-  typedef omni_thread l_thread, *l_thread_ptr;
-#else
-  typedef pthread_t l_thread, *l_thread_ptr;
-#endif
-
-private:
-#ifndef _USE_OMNI_THREADS_
-  l_thread d_thread;
-  void (*d_start_routine)(void*);
-  void *d_arg;
-#else
-  l_thread_ptr d_thread;
-#endif
-
-#ifndef _USE_OMNI_THREADS_
-  static void* local_start_routine (void *arg) {
-    mld_thread_t* This = (mld_thread_t*) arg;
-    (*(This->d_start_routine))(This->d_arg);
-    return (NULL);
-  };
-#endif
-
-public:
-  __INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) {
-#ifdef _USE_OMNI_THREADS_
-    d_thread = new omni_thread (start_routine, arg);
-    d_thread->start ();
-#else
-    d_start_routine = start_routine;
-    d_arg = arg;
-    int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this);
-    if (l_ret != 0) {
-      fprintf (stderr, "Error %d creating thread.\n", l_ret);
-      throw std::runtime_error ("mld_thread_t::mld_thread_t()\n");
-    }
-#endif
-  };
-
-  __INLINE__ ~mld_thread_t () {
-#ifdef _USE_OMNI_THREADS_
-//  delete d_thread;
-    d_thread = NULL;
-#else
-    int l_ret = pthread_detach (d_thread);
-    if (l_ret != 0) {
-      fprintf (stderr, "Error %d detaching thread.\n", l_ret);
-      throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n");
-    }
-#endif
-  };
-};
-
-typedef mld_thread_t mld_thread, *mld_thread_ptr;
-
-#endif /* _INCLUDED_MLD_THREADS_H_ */
diff --git a/usrp/host/lib/rate_to_regval.h b/usrp/host/lib/rate_to_regval.h
deleted file mode 100644 (file)
index 1ffdc0f..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-  {   1, 0x00 },
-  {   2, 0x01 },
-  {   3, 0x02 },
-  {   4, 0x11 },
-  {   5, 0x04 },
-  {   6, 0x05 },
-  {   7, 0x06 },
-  {   8, 0x13 },
-  {   9, 0x08 },
-  {  10, 0x09 },
-  {  11, 0x0a },
-  {  12, 0x15 },
-  {  13, 0x0c },
-  {  14, 0x0d },
-  {  15, 0x0e },
-  {  16, 0x33 },
-  {  18, 0x18 },
-  {  20, 0x19 },
-  {  21, 0x26 },
-  {  22, 0x1a },
-  {  24, 0x35 },
-  {  25, 0x44 },
-  {  26, 0x1c },
-  {  27, 0x28 },
-  {  28, 0x1d },
-  {  30, 0x1e },
-  {  32, 0x37 },
-  {  33, 0x2a },
-  {  35, 0x46 },
-  {  36, 0x55 },
-  {  39, 0x2c },
-  {  40, 0x39 },
-  {  42, 0x56 },
-  {  44, 0x3a },
-  {  45, 0x2e },
-  {  48, 0x57 },
-  {  49, 0x66 },
-  {  50, 0x49 },
-  {  52, 0x3c },
-  {  54, 0x58 },
-  {  55, 0x4a },
-  {  56, 0x3d },
-  {  60, 0x59 },
-  {  63, 0x68 },
-  {  64, 0x77 },
-  {  65, 0x4c },
-  {  66, 0x5a },
-  {  70, 0x69 },
-  {  72, 0x5b },
-  {  75, 0x4e },
-  {  77, 0x6a },
-  {  78, 0x5c },
-  {  80, 0x79 },
-  {  81, 0x88 },
-  {  84, 0x5d },
-  {  88, 0x7a },
-  {  90, 0x5e },
-  {  91, 0x6c },
-  {  96, 0x7b },
-  {  98, 0x6d },
-  {  99, 0x8a },
-  { 100, 0x99 },
-  { 104, 0x7c },
-  { 105, 0x6e },
-  { 108, 0x8b },
-  { 110, 0x9a },
-  { 112, 0x7d },
-  { 117, 0x8c },
-  { 120, 0x9b },
-  { 121, 0xaa },
-  { 126, 0x8d },
-  { 128, 0x7f },
-  { 130, 0x9c },
-  { 132, 0xab },
-  { 135, 0x8e },
-  { 140, 0x9d },
-  { 143, 0xac },
-  { 144, 0xbb },
-  { 150, 0x9e },
-  { 154, 0xad },
-  { 156, 0xbc },
-  { 160, 0x9f },
-  { 165, 0xae },
-  { 168, 0xbd },
-  { 169, 0xcc },
-  { 176, 0xaf },
-  { 180, 0xbe },
-  { 182, 0xcd },
-  { 192, 0xbf },
-  { 195, 0xce },
-  { 196, 0xdd },
-  { 208, 0xcf },
-  { 210, 0xde },
-  { 224, 0xdf },
-  { 225, 0xee },
-  { 240, 0xef },
-  { 256, 0xff }
diff --git a/usrp/host/lib/std_paths.h.in b/usrp/host/lib/std_paths.h.in
deleted file mode 100644 (file)
index 22a8ecb..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2005 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-static char *std_paths[] = {
-  "@prefix@/share/usrp",
-  "/usr/local/share/usrp",
-  0
-};
diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc
deleted file mode 100644 (file)
index cc9df04..0000000
+++ /dev/null
@@ -1,1240 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "usrp_basic.h"
-#include "usrp_prims.h"
-#include "usrp_interfaces.h"
-#include "fpga_regs_common.h"
-#include "fusb.h"
-#include <usb.h>
-#include <stdexcept>
-#include <assert.h>
-#include <math.h>
-#include <ad9862.h>
-
-using namespace ad9862;
-
-#define NELEM(x) (sizeof (x) / sizeof (x[0]))
-
-// These set the buffer size used for each end point using the fast
-// usb interface.  The kernel ends up locking down this much memory.
-
-static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size();
-static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size();
-static const int FUSB_NBLOCKS    = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE;
-
-
-static const double POLLING_INTERVAL = 0.1;    // seconds
-
-////////////////////////////////////////////////////////////////
-
-static struct usb_dev_handle *
-open_rx_interface (struct usb_device *dev)
-{
-  struct usb_dev_handle *udh = usrp_open_rx_interface (dev);
-  if (udh == 0){
-    fprintf (stderr, "usrp_basic_rx: can't open rx interface\n");
-    usb_strerror ();
-  }
-  return udh;
-}
-
-static struct usb_dev_handle *
-open_tx_interface (struct usb_device *dev)
-{
-  struct usb_dev_handle *udh = usrp_open_tx_interface (dev);
-  if (udh == 0){
-    fprintf (stderr, "usrp_basic_tx: can't open tx interface\n");
-    usb_strerror ();
-  }
-  return udh;
-}
-
-
-//////////////////////////////////////////////////////////////////
-//
-//                     usrp_basic
-//
-////////////////////////////////////////////////////////////////
-
-
-// Given:
-//   CLKIN = 64 MHz
-//   CLKSEL pin = high 
-//
-// These settings give us:
-//   CLKOUT1 = CLKIN = 64 MHz
-//   CLKOUT2 = CLKIN = 64 MHz
-//   ADC is clocked at  64 MHz
-//   DAC is clocked at 128 MHz
-
-static unsigned char common_regs[] = {
-  REG_GENERAL,         0,
-  REG_DLL,             (DLL_DISABLE_INTERNAL_XTAL_OSC
-                        | DLL_MULT_2X
-                        | DLL_FAST),
-  REG_CLKOUT,          CLKOUT2_EQ_DLL_OVER_2,
-  REG_AUX_ADC_CLK,     AUX_ADC_CLK_CLK_OVER_4
-};
-
-
-usrp_basic::usrp_basic (int which_board, 
-                       struct usb_dev_handle *
-                       open_interface (struct usb_device *dev),
-                       const std::string fpga_filename,
-                       const std::string firmware_filename)
-  : d_udh (0),
-    d_usb_data_rate (16000000),        // SWAG, see below
-    d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)),
-    d_verbose (false)
-{
-  /*
-   * SWAG: Scientific Wild Ass Guess.
-   *
-   * d_usb_data_rate is used only to determine how often to poll for over- and under-runs.
-   * We defualt it to 1/2  of our best case.  Classes derived from usrp_basic (e.g., 
-   * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the
-   * actual rate.  This doesn't change our throughput, that's determined by the signal
-   * processing code in the FPGA (which we know nothing about), and the system limits
-   * determined by libusb, fusb_*, and the underlying drivers.
-   */
-  memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows));
-
-  usrp_one_time_init ();
-
-  if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename))
-    throw std::runtime_error ("usrp_basic/usrp_load_standard_bits");
-
-  struct usb_device *dev = usrp_find_device (which_board);
-  if (dev == 0){
-    fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board);
-    throw std::runtime_error ("usrp_basic/usrp_find_device");
-  }
-
-  if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){
-    fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n");
-    throw std::runtime_error ("usrp_basic/bad_rev");
-  }
-
-  if ((d_udh = open_interface (dev)) == 0)
-    throw std::runtime_error ("usrp_basic/open_interface");
-
-  // initialize registers that are common to rx and tx
-
-  if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){
-    fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n");
-    throw std::runtime_error ("usrp_basic/init_9862");
-  }
-
-  _write_fpga_reg (FR_MODE, 0);                // ensure we're in normal mode
-  _write_fpga_reg (FR_DEBUG_EN, 0);    // disable debug outputs
-}
-
-usrp_basic::~usrp_basic ()
-{
-  if (d_udh)
-    usb_close (d_udh);
-}
-
-bool
-usrp_basic::start ()
-{
-  return true;         // nop
-}
-
-bool
-usrp_basic::stop ()
-{
-  return true;         // nop
-}
-
-void
-usrp_basic::set_usb_data_rate (int usb_data_rate)
-{
-  d_usb_data_rate = usb_data_rate;
-  d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL);
-}
-
-bool
-usrp_basic::write_aux_dac (int slot, int which_dac, int value)
-{
-  return usrp_write_aux_dac (d_udh, slot, which_dac, value);
-}
-
-bool
-usrp_basic::read_aux_adc (int slot, int which_adc, int *value)
-{
-  return usrp_read_aux_adc (d_udh, slot, which_adc, value);
-}
-
-int
-usrp_basic::read_aux_adc (int slot, int which_adc)
-{
-  int  value;
-  if (!read_aux_adc (slot, which_adc, &value))
-    return READ_FAILED;
-
-  return value;
-}
-
-bool
-usrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf)
-{
-  return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ());
-}
-
-std::string
-usrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len)
-{
-  if (len <= 0)
-    return "";
-
-  char buf[len];
-
-  if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len))
-    return "";
-
-  return std::string (buf, len);
-}
-
-bool
-usrp_basic::write_i2c (int i2c_addr, const std::string buf)
-{
-  return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ());
-}
-
-std::string
-usrp_basic::read_i2c (int i2c_addr, int len)
-{
-  if (len <= 0)
-    return "";
-
-  char buf[len];
-
-  if (!usrp_i2c_read (d_udh, i2c_addr, buf, len))
-    return "";
-
-  return std::string (buf, len);
-}
-
-std::string
-usrp_basic::serial_number()
-{
-  return usrp_serial_number(d_udh);
-}
-
-// ----------------------------------------------------------------
-
-bool
-usrp_basic::set_adc_offset (int which, int offset)
-{
-  if (which < 0 || which > 3)
-    return false;
-
-  return _write_fpga_reg (FR_ADC_OFFSET_0 + which, offset);
-}
-
-bool
-usrp_basic::set_dac_offset (int which, int offset, int offset_pin)
-{
-  if (which < 0 || which > 3)
-    return false;
-
-  int which_codec = which >> 1;
-  int tx_a = (which & 0x1) == 0;
-  int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1);
-  int hi = (offset >> 2);
-  bool ok;
-
-  if (tx_a){
-    ok =  _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo);
-    ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi);
-  }
-  else {
-    ok =  _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo);
-    ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi);
-  }
-  return ok;
-}
-
-bool
-usrp_basic::set_adc_buffer_bypass (int which, bool bypass)
-{
-  if (which < 0 || which > 3)
-    return false;
-
-  int codec = which >> 1;
-  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
-
-  unsigned char cur_rx;
-  unsigned char cur_pwr_dn;
-
-  // If the input buffer is bypassed, we need to power it down too.
-
-  bool ok = _read_9862 (codec, reg, &cur_rx);
-  ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn);
-  if (!ok)
-    return false;
-
-  if (bypass){
-    cur_rx |= RX_X_BYPASS_INPUT_BUFFER;
-    cur_pwr_dn |= ((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B;
-  }
-  else {
-    cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER;
-    cur_pwr_dn &= ~(((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B);
-  }
-
-  ok &= _write_9862 (codec, reg, cur_rx);
-  ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn);
-  return ok;
-}
-
-// ----------------------------------------------------------------
-
-bool
-usrp_basic::_write_fpga_reg (int regno, int value)
-{
-  if (d_verbose){
-    fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value);
-    fflush (stdout);
-  }
-
-  if (regno >= 0 && regno < MAX_REGS)
-    d_fpga_shadows[regno] = value;
-
-  return usrp_write_fpga_reg (d_udh, regno, value);
-}
-
-bool
-usrp_basic::_write_fpga_reg_masked (int regno, int value, int mask)
-{
-  //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE
-  //value is a 16 bits value and mask is a 16 bits mask
-  if (d_verbose){
-    fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask);
-    fflush (stdout);
-  }
-
-  if (regno >= 0 && regno < MAX_REGS)
-    d_fpga_shadows[regno] = value;
-
-  return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16));
-}
-
-
-bool
-usrp_basic::_read_fpga_reg (int regno, int *value)
-{
-  return usrp_read_fpga_reg (d_udh, regno, value);
-}
-
-int
-usrp_basic::_read_fpga_reg (int regno)
-{
-  int value;
-  if (!_read_fpga_reg (regno, &value))
-    return READ_FAILED;
-  return value;
-}
-
-bool
-usrp_basic::_write_9862 (int which_codec, int regno, unsigned char value)
-{
-  if (0 && d_verbose){
-    // FIXME really want to enable logging in usrp_prims:usrp_9862_write
-    fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value);
-    fflush(stdout);
-  }
-
-  return usrp_9862_write (d_udh, which_codec, regno, value);
-}
-
-
-bool
-usrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const
-{
-  return usrp_9862_read (d_udh, which_codec, regno, value);
-}
-
-int
-usrp_basic::_read_9862 (int which_codec, int regno) const
-{
-  unsigned char value;
-  if (!_read_9862 (which_codec, regno, &value))
-    return READ_FAILED;
-  return value;
-}
-
-bool
-usrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf)
-{
-  return usrp_spi_write (d_udh, optional_header, enables, format,
-                        buf.data(), buf.size());
-}
-
-std::string
-usrp_basic::_read_spi (int optional_header, int enables, int format, int len)
-{
-  if (len <= 0)
-    return "";
-  
-  char buf[len];
-
-  if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len))
-    return "";
-
-  return std::string (buf, len);
-}
-
-
-bool
-usrp_basic::_set_led (int which, bool on)
-{
-  return usrp_set_led (d_udh, which, on);
-}
-
-////////////////////////////////////////////////////////////////
-//
-//                        usrp_basic_rx
-//
-////////////////////////////////////////////////////////////////
-
-static unsigned char rx_init_regs[] = {
-  REG_RX_PWR_DN,       0,
-  REG_RX_A,            0,      // minimum gain = 0x00 (max gain = 0x14)
-  REG_RX_B,            0,      // minimum gain = 0x00 (max gain = 0x14)
-  REG_RX_MISC,         (RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY),
-  REG_RX_IF,           (RX_IF_USE_CLKOUT1
-                        | RX_IF_2S_COMP),
-  REG_RX_DIGITAL,      (RX_DIGITAL_2_CHAN)
-};
-
-
-usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nblocks,
-                             const std::string fpga_filename,
-                             const std::string firmware_filename
-                             )
-  : usrp_basic (which_board, open_rx_interface, fpga_filename, firmware_filename),
-    d_devhandle (0), d_ephandle (0),
-    d_bytes_seen (0), d_first_read (true),
-    d_rx_enable (false)
-{
-  // initialize rx specific registers
-
-  if (!usrp_9862_write_many_all (d_udh, rx_init_regs, sizeof (rx_init_regs))){
-    fprintf (stderr, "usrp_basic_rx: failed to init AD9862 RX regs\n");
-    throw std::runtime_error ("usrp_basic_rx/init_9862");
-  }
-
-  if (0){
-    // FIXME power down 2nd codec rx path
-    usrp_9862_write (d_udh, 1, REG_RX_PWR_DN, 0x1);    // power down everything
-  }
-
-  // Reset the rx path and leave it disabled.
-  set_rx_enable (false);
-  usrp_set_fpga_rx_reset (d_udh, true);
-  usrp_set_fpga_rx_reset (d_udh, false);
-
-  set_fpga_rx_sample_rate_divisor (2); // usually correct
-
-  set_dc_offset_cl_enable(0xf, 0xf);   // enable DC offset removal control loops
-
-  probe_rx_slots (false);
-
-  // check fusb buffering parameters
-
-  if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE)
-    throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size");
-
-  if (fusb_nblocks < 0)
-    throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks");
-  
-  if (fusb_block_size == 0)
-    fusb_block_size = FUSB_BLOCK_SIZE;
-
-  if (fusb_nblocks == 0)
-    fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
-
-  d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
-  d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true,
-                                          fusb_block_size, fusb_nblocks);
-
-  _write_fpga_reg(FR_ATR_MASK_1, 0);   // zero Rx side Auto Transmit/Receive regs
-  _write_fpga_reg(FR_ATR_TXVAL_1, 0);
-  _write_fpga_reg(FR_ATR_RXVAL_1, 0);
-  _write_fpga_reg(FR_ATR_MASK_3, 0);
-  _write_fpga_reg(FR_ATR_TXVAL_3, 0);
-  _write_fpga_reg(FR_ATR_RXVAL_3, 0);
-}
-
-static unsigned char rx_fini_regs[] = {
-  REG_RX_PWR_DN,       0x1                             // power down everything
-};
-
-usrp_basic_rx::~usrp_basic_rx ()
-{
-  if (!set_rx_enable (false)){
-    fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n");
-    usb_strerror ();
-  }
-
-  d_ephandle->stop ();
-  delete d_ephandle;
-  delete d_devhandle;
-
-  if (!usrp_9862_write_many_all (d_udh, rx_fini_regs, sizeof (rx_fini_regs))){
-    fprintf (stderr, "usrp_basic_rx: failed to fini AD9862 RX regs\n");
-  }
-}
-
-
-bool
-usrp_basic_rx::start ()
-{
-  if (!usrp_basic::start ())   // invoke parent's method
-    return false;
-
-  // fire off reads before asserting rx_enable
-
-  if (!d_ephandle->start ()){
-    fprintf (stderr, "usrp_basic_rx: failed to start end point streaming");
-    usb_strerror ();
-    return false;
-  }
-
-  if (!set_rx_enable (true)){
-    fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n");
-    usb_strerror ();
-    return false;
-  }
-  
-  return true;
-}
-
-bool
-usrp_basic_rx::stop ()
-{
-  bool ok = usrp_basic::stop();
-
-  if (!d_ephandle->stop()){
-    fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming");
-    usb_strerror ();
-    ok = false;
-  }
-  if (!set_rx_enable(false)){
-    fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n");
-    usb_strerror ();
-    ok = false;
-  }
-  return false;
-}
-
-usrp_basic_rx *
-usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks,
-                    const std::string fpga_filename,
-                    const std::string firmware_filename)
-{
-  usrp_basic_rx *u = 0;
-  
-  try {
-    u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
-                          fpga_filename, firmware_filename);
-    return u;
-  }
-  catch (...){
-    delete u;
-    return 0;
-  }
-
-  return u;
-}
-
-bool
-usrp_basic_rx::set_fpga_rx_sample_rate_divisor (unsigned int div)
-{
-  return _write_fpga_reg (FR_RX_SAMPLE_RATE_DIV, div - 1);
-}
-
-
-/*
- * \brief read data from the D/A's via the FPGA.
- * \p len must be a multiple of 512 bytes.
- *
- * \returns the number of bytes read, or -1 on error.
- *
- * If overrun is non-NULL it will be set true iff an RX overrun is detected.
- */
-int
-usrp_basic_rx::read (void *buf, int len, bool *overrun)
-{
-  int  r;
-  
-  if (overrun)
-    *overrun = false;
-  
-  if (len < 0 || (len % 512) != 0){
-    fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len);
-    return -1;
-  }
-
-  r = d_ephandle->read (buf, len);
-  if (r > 0)
-    d_bytes_seen += r;
-
-  /*
-   * In many cases, the FPGA reports an rx overrun right after we
-   * enable the Rx path.  If this is our first read, check for the
-   * overrun to clear the condition, then ignore the result.
-   */
-  if (0 && d_first_read){      // FIXME
-    d_first_read = false;
-    bool bogus_overrun;
-    usrp_check_rx_overrun (d_udh, &bogus_overrun);
-  }
-
-  if (overrun != 0 && d_bytes_seen >= d_bytes_per_poll){
-    d_bytes_seen = 0;
-    if (!usrp_check_rx_overrun (d_udh, overrun)){
-      fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n");
-      usb_strerror ();
-    }
-  }
-    
-  return r;
-}
-
-bool
-usrp_basic_rx::set_rx_enable (bool on)
-{
-  d_rx_enable = on;
-  return usrp_set_fpga_rx_enable (d_udh, on);
-}
-
-// conditional disable, return prev state
-bool
-usrp_basic_rx::disable_rx ()
-{
-  bool enabled = rx_enable ();
-  if (enabled)
-    set_rx_enable (false);
-  return enabled;
-}
-
-// conditional set
-void
-usrp_basic_rx::restore_rx (bool on)
-{
-  if (on != rx_enable ())
-    set_rx_enable (on);
-}
-
-bool
-usrp_basic_rx::set_pga (int which, double gain)
-{
-  if (which < 0 || which > 3)
-    return false;
-
-  gain = std::max (pga_min (), gain);
-  gain = std::min (pga_max (), gain);
-
-  int codec = which >> 1;
-  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
-
-  // read current value to get input buffer bypass flag.
-  unsigned char cur_rx;
-  if (!_read_9862 (codec, reg, &cur_rx))
-    return false;
-
-  int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step());
-
-  cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f);
-  return _write_9862 (codec, reg, cur_rx);
-}
-
-double
-usrp_basic_rx::pga (int which) const
-{
-  if (which < 0 || which > 3)
-    return READ_FAILED;
-
-  int codec = which >> 1;
-  int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
-  unsigned char v;
-  bool ok = _read_9862 (codec, reg, &v);
-  if (!ok)
-    return READ_FAILED;
-
-  return (pga_db_per_step() * (v & 0x1f)) + pga_min();
-}
-
-static int
-slot_id_to_oe_reg (int slot_id)
-{
-  static int reg[4]  = { FR_OE_0, FR_OE_1, FR_OE_2, FR_OE_3 };
-  assert (0 <= slot_id && slot_id < 4);
-  return reg[slot_id];
-}
-
-static int
-slot_id_to_io_reg (int slot_id)
-{
-  static int reg[4]  = { FR_IO_0, FR_IO_1, FR_IO_2, FR_IO_3 };
-  assert (0 <= slot_id && slot_id < 4);
-  return reg[slot_id];
-}
-
-void
-usrp_basic_rx::probe_rx_slots (bool verbose)
-{
-  struct usrp_dboard_eeprom    eeprom;
-  static int slot_id_map[2] = { SLOT_RX_A, SLOT_RX_B };
-  static const char *slot_name[2] = { "RX d'board A", "RX d'board B" };
-
-  for (int i = 0; i < 2; i++){
-    int slot_id = slot_id_map [i];
-    const char *msg = 0;
-    usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom);
-
-    switch (s){
-    case UDBE_OK:
-      d_dbid[i] = eeprom.id;
-      msg = usrp_dbid_to_string (eeprom.id).c_str ();
-      set_adc_offset (2*i+0, eeprom.offset[0]);
-      set_adc_offset (2*i+1, eeprom.offset[1]);
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_NO_EEPROM:
-      d_dbid[i] = -1;
-      msg = "<none>";
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_INVALID_EEPROM:
-      d_dbid[i] = -2;
-      msg = "Invalid EEPROM contents";
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_BAD_SLOT:
-    default:
-      assert (0);
-    }
-
-    if (verbose){
-      fflush (stdout);
-      fprintf (stderr, "%s: %s\n", slot_name[i], msg);
-    }
-  }
-}
-
-bool
-usrp_basic_rx::_write_oe (int which_dboard, int value, int mask)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)),
-                         (mask << 16) | (value & 0xffff));
-}
-
-bool
-usrp_basic_rx::write_io (int which_dboard, int value, int mask)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)),
-                         (mask << 16) | (value & 0xffff));
-}
-
-bool
-usrp_basic_rx::read_io (int which_dboard, int *value)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  int t;
-  int reg = which_dboard + 1;  // FIXME, *very* magic number (fix in serial_io.v)
-  bool ok = _read_fpga_reg (reg, &t);
-  if (!ok)
-    return false;
-
-  *value = (t >> 16) & 0xffff; // FIXME, more magic
-  return true;
-}
-
-int
-usrp_basic_rx::read_io (int which_dboard)
-{
-  int  value;
-  if (!read_io (which_dboard, &value))
-    return READ_FAILED;
-  return value;
-}
-
-bool
-usrp_basic_rx::write_aux_dac (int which_dboard, int which_dac, int value)
-{
-  return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard),
-                                   which_dac, value);
-}
-
-bool
-usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc, int *value)
-{
-  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard),
-                                  which_adc, value);
-}
-
-int
-usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc)
-{
-  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc);
-}
-
-int
-usrp_basic_rx::block_size () const { return d_ephandle->block_size(); }
-
-bool
-usrp_basic_rx::set_dc_offset_cl_enable(int bits, int mask)
-{
-  return _write_fpga_reg(FR_DC_OFFSET_CL_EN, 
-                        (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask));
-}
-
-////////////////////////////////////////////////////////////////
-//
-//                        usrp_basic_tx
-//
-////////////////////////////////////////////////////////////////
-
-
-//
-// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz
-// DAC input is latched on rising edge of CLKOUT2
-// NCO is disabled
-// interpolate 2x
-// coarse modulator disabled
-//
-
-static unsigned char tx_init_regs[] = {
-  REG_TX_PWR_DN,       0,
-  REG_TX_A_OFFSET_LO,  0,
-  REG_TX_A_OFFSET_HI,  0,
-  REG_TX_B_OFFSET_LO,  0,
-  REG_TX_B_OFFSET_HI,  0,
-  REG_TX_A_GAIN,       (TX_X_GAIN_COARSE_FULL | 0),
-  REG_TX_B_GAIN,       (TX_X_GAIN_COARSE_FULL | 0),
-  REG_TX_PGA,          0xff,                   // maximum gain (0 dB)
-  REG_TX_MISC,         0,
-  REG_TX_IF,           (TX_IF_USE_CLKOUT1
-                        | TX_IF_I_FIRST
-                        | TX_IF_INV_TX_SYNC
-                        | TX_IF_2S_COMP
-                        | TX_IF_INTERLEAVED),
-  REG_TX_DIGITAL,      (TX_DIGITAL_2_DATA_PATHS
-                        | TX_DIGITAL_INTERPOLATE_4X),
-  REG_TX_MODULATOR,    (TX_MODULATOR_DISABLE_NCO
-                        | TX_MODULATOR_COARSE_MODULATION_NONE),
-  REG_TX_NCO_FTW_7_0,  0,
-  REG_TX_NCO_FTW_15_8, 0,
-  REG_TX_NCO_FTW_23_16,        0
-};
-
-usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks,
-                             const std::string fpga_filename,
-                             const std::string firmware_filename)
-  : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename),
-    d_devhandle (0), d_ephandle (0),
-    d_bytes_seen (0), d_first_write (true),
-    d_tx_enable (false)
-{
-  if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){
-    fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n");
-    throw std::runtime_error ("usrp_basic_tx/init_9862");
-  }
-
-  if (0){
-    // FIXME power down 2nd codec tx path
-    usrp_9862_write (d_udh, 1, REG_TX_PWR_DN,
-                    (TX_PWR_DN_TX_DIGITAL
-                     | TX_PWR_DN_TX_ANALOG_BOTH));
-  }
-
-  // Reset the tx path and leave it disabled.
-  set_tx_enable (false);
-  usrp_set_fpga_tx_reset (d_udh, true);
-  usrp_set_fpga_tx_reset (d_udh, false);
-
-  set_fpga_tx_sample_rate_divisor (4); // we're using interp x4
-
-  probe_tx_slots (false);
-
-  // check fusb buffering parameters
-
-  if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE)
-    throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size");
-
-  if (fusb_nblocks < 0)
-    throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks");
-  
-  if (fusb_block_size == 0)
-    fusb_block_size = FUSB_BLOCK_SIZE;
-
-  if (fusb_nblocks == 0)
-    fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
-
-  d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
-  d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false,
-                                          fusb_block_size, fusb_nblocks);
-
-  _write_fpga_reg(FR_ATR_MASK_0, 0); // zero Tx side Auto Transmit/Receive regs
-  _write_fpga_reg(FR_ATR_TXVAL_0, 0);
-  _write_fpga_reg(FR_ATR_RXVAL_0, 0);
-  _write_fpga_reg(FR_ATR_MASK_2, 0);
-  _write_fpga_reg(FR_ATR_TXVAL_2, 0);
-  _write_fpga_reg(FR_ATR_RXVAL_2, 0);
-  _write_fpga_reg(FR_ATR_TX_DELAY, 0);
-  _write_fpga_reg(FR_ATR_RX_DELAY, 0);
-}
-
-
-static unsigned char tx_fini_regs[] = {
-  REG_TX_PWR_DN,       (TX_PWR_DN_TX_DIGITAL
-                        | TX_PWR_DN_TX_ANALOG_BOTH),
-  REG_TX_MODULATOR,    (TX_MODULATOR_DISABLE_NCO
-                        | TX_MODULATOR_COARSE_MODULATION_NONE)
-};
-
-usrp_basic_tx::~usrp_basic_tx ()
-{
-  d_ephandle->stop ();
-  delete d_ephandle;
-  delete d_devhandle;
-
-  if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){
-    fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n");
-  }
-}
-
-bool
-usrp_basic_tx::start ()
-{
-  if (!usrp_basic::start ())
-    return false;
-
-  if (!set_tx_enable (true)){
-    fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n");
-    usb_strerror ();
-    return false;
-  }
-  
-  if (!d_ephandle->start ()){
-    fprintf (stderr, "usrp_basic_tx: failed to start end point streaming");
-    usb_strerror ();
-    return false;
-  }
-
-  return true;
-}
-
-bool
-usrp_basic_tx::stop ()
-{
-  bool ok = usrp_basic::stop ();
-
-  if (!set_tx_enable (false)){
-    fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n");
-    usb_strerror ();
-    ok = false;
-  }
-  if (!d_ephandle->stop ()){
-    fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming");
-    usb_strerror ();
-    ok = false;
-  }
-  return ok;
-}
-
-usrp_basic_tx *
-usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks,
-                    const std::string fpga_filename,
-                    const std::string firmware_filename)
-{
-  usrp_basic_tx *u = 0;
-  
-  try {
-    u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks,
-                          fpga_filename, firmware_filename);
-    return u;
-  }
-  catch (...){
-    delete u;
-    return 0;
-  }
-
-  return u;
-}
-
-bool
-usrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div)
-{
-  return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1);
-}
-
-/*!
- * \brief Write data to the A/D's via the FPGA.
- *
- * \p len must be a multiple of 512 bytes.
- * \returns number of bytes written or -1 on error.
- *
- * if \p underrun is non-NULL, it will be set to true iff
- * a transmit underrun condition is detected.
- */
-int
-usrp_basic_tx::write (const void *buf, int len, bool *underrun)
-{
-  int  r;
-  
-  if (underrun)
-    *underrun = false;
-  
-  if (len < 0 || (len % 512) != 0){
-    fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len);
-    return -1;
-  }
-
-  r = d_ephandle->write (buf, len);
-  if (r > 0)
-    d_bytes_seen += r;
-    
-  /*
-   * In many cases, the FPGA reports an tx underrun right after we
-   * enable the Tx path.  If this is our first write, check for the
-   * underrun to clear the condition, then ignore the result.
-   */
-  if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){
-    d_first_write = false;
-    bool bogus_underrun;
-    usrp_check_tx_underrun (d_udh, &bogus_underrun);
-  }
-
-  if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){
-    d_bytes_seen = 0;
-    if (!usrp_check_tx_underrun (d_udh, underrun)){
-      fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n");
-      usb_strerror ();
-    }
-  }
-
-  return r;
-}
-
-void
-usrp_basic_tx::wait_for_completion ()
-{
-  d_ephandle->wait_for_completion ();
-}
-
-bool
-usrp_basic_tx::set_tx_enable (bool on)
-{
-  d_tx_enable = on;
-  // fprintf (stderr, "set_tx_enable %d\n", on);
-  return usrp_set_fpga_tx_enable (d_udh, on);
-}
-
-// conditional disable, return prev state
-bool
-usrp_basic_tx::disable_tx ()
-{
-  bool enabled = tx_enable ();
-  if (enabled)
-    set_tx_enable (false);
-  return enabled;
-}
-
-// conditional set
-void
-usrp_basic_tx::restore_tx (bool on)
-{
-  if (on != tx_enable ())
-    set_tx_enable (on);
-}
-
-bool
-usrp_basic_tx::set_pga (int which, double gain)
-{
-  if (which < 0 || which > 3)
-    return false;
-
-  gain = std::max (pga_min (), gain);
-  gain = std::min (pga_max (), gain);
-
-  int codec = which >> 1;      // 0 and 1 are same, as are 2 and 3
-
-  int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step());
-
-  return _write_9862 (codec, REG_TX_PGA, int_gain);
-}
-
-double
-usrp_basic_tx::pga (int which) const
-{
-  if (which < 0 || which > 3)
-    return READ_FAILED;
-
-  int codec = which >> 1;
-  unsigned char v;
-  bool ok = _read_9862 (codec, REG_TX_PGA, &v);
-  if (!ok)
-    return READ_FAILED;
-
-  return (pga_db_per_step() * v) + pga_min();
-}
-
-void
-usrp_basic_tx::probe_tx_slots (bool verbose)
-{
-  struct usrp_dboard_eeprom    eeprom;
-  static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B };
-  static const char *slot_name[2] = { "TX d'board A", "TX d'board B" };
-
-  for (int i = 0; i < 2; i++){
-    int slot_id = slot_id_map [i];
-    const char *msg = 0;
-    usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom);
-
-    switch (s){
-    case UDBE_OK:
-      d_dbid[i] = eeprom.id;
-      msg = usrp_dbid_to_string (eeprom.id).c_str ();
-      // FIXME, figure out interpretation of dc offset for TX d'boards
-      // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff);
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_NO_EEPROM:
-      d_dbid[i] = -1;
-      msg = "<none>";
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_INVALID_EEPROM:
-      d_dbid[i] = -2;
-      msg = "Invalid EEPROM contents";
-      _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000);
-      _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000);
-      break;
-      
-    case UDBE_BAD_SLOT:
-    default:
-      assert (0);
-    }
-
-    if (verbose){
-      fflush (stdout);
-      fprintf (stderr, "%s: %s\n", slot_name[i], msg);
-    }
-  }
-}
-
-bool
-usrp_basic_tx::_write_oe (int which_dboard, int value, int mask)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)),
-                         (mask << 16) | (value & 0xffff));
-}
-
-bool
-usrp_basic_tx::write_io (int which_dboard, int value, int mask)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)),
-                         (mask << 16) | (value & 0xffff));
-}
-
-bool
-usrp_basic_tx::read_io (int which_dboard, int *value)
-{
-  if (! (0 <= which_dboard && which_dboard <= 1))
-    return false;
-
-  int t;
-  int reg = which_dboard + 1;  // FIXME, *very* magic number (fix in serial_io.v)
-  bool ok = _read_fpga_reg (reg, &t);
-  if (!ok)
-    return false;
-
-  *value = t & 0xffff;         // FIXME, more magic
-  return true;
-}
-
-int
-usrp_basic_tx::read_io (int which_dboard)
-{
-  int  value;
-  if (!read_io (which_dboard, &value))
-    return READ_FAILED;
-  return value;
-}
-
-bool
-usrp_basic_tx::write_aux_dac (int which_dboard, int which_dac, int value)
-{
-  return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard),
-                                   which_dac, value);
-}
-
-bool
-usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc, int *value)
-{
-  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard),
-                                  which_adc, value);
-}
-
-int
-usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc)
-{
-  return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc);
-}
-
-int
-usrp_basic_tx::block_size () const { return d_ephandle->block_size(); }
-
diff --git a/usrp/host/lib/usrp_basic.h b/usrp/host/lib/usrp_basic.h
deleted file mode 100644 (file)
index 796a0f4..0000000
+++ /dev/null
@@ -1,776 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * ----------------------------------------------------------------------
- * Mid level interface to the Universal Software Radio Peripheral (Rev 1)
- *
- * These classes implement the basic functionality for talking to the
- * USRP.  They try to be as independent of the signal processing code
- * in FPGA as possible.  They implement access to the low level
- * peripherals on the board, provide a common way for reading and
- * writing registers in the FPGA, and provide the high speed interface
- * to streaming data across the USB.
- *
- * It is expected that subclasses will be derived that provide
- * access to the functionality to a particular FPGA configuration.
- * ----------------------------------------------------------------------
- */
-
-#ifndef INCLUDED_USRP_BASIC_H
-#define INCLUDED_USRP_BASIC_H
-
-#include <usrp_slots.h>
-#include <string>
-
-struct usb_dev_handle;
-class  fusb_devhandle;
-class  fusb_ephandle;
-
-/*!
- * \brief base class for usrp operations
- */
-class usrp_basic
-{
-private:
-  // NOT IMPLEMENTED
-  usrp_basic (const usrp_basic &rhs);                  // no copy constructor
-  usrp_basic &operator= (const usrp_basic &rhs);       // no assignment operator
-
-  
-protected:
-  struct usb_dev_handle        *d_udh;
-  int                   d_usb_data_rate;       // bytes/sec
-  int                   d_bytes_per_poll;      // how often to poll for overruns
-  bool                  d_verbose;
-
-  static const int      MAX_REGS = 128;
-  unsigned int          d_fpga_shadows[MAX_REGS];
-
-  usrp_basic (int which_board,
-             struct usb_dev_handle *open_interface (struct usb_device *dev),
-             const std::string fpga_filename = "",
-             const std::string firmware_filename = "");
-
-  /*!
-   * \brief advise usrp_basic of usb data rate (bytes/sec)
-   *
-   * N.B., this doesn't tweak any hardware.  Derived classes
-   * should call this to inform us of the data rate whenever it's
-   * first set or if it changes.
-   *
-   * \param usb_data_rate      bytes/sec
-   */
-  void set_usb_data_rate (int usb_data_rate);
-  
-  /*!
-   * \brief Write auxiliary digital to analog converter.
-   *
-   * \param slot       Which Tx or Rx slot to write.
-   *                   N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
-   *                   SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
-   * \param which_dac  [0,3] RX slots must use only 0 and 1.  TX slots must use only 2 and 3.
-   * \param value      [0,4095]
-   * \returns true iff successful
-   */
-  bool write_aux_dac (int slot, int which_dac, int value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param slot       2-bit slot number. E.g., SLOT_TX_A
-   * \param which_adc  [0,1]
-   * \param value      return 12-bit value [0,4095]
-   * \returns true iff successful
-   */
-  bool read_aux_adc (int slot, int which_adc, int *value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param slot       2-bit slot number. E.g., SLOT_TX_A
-   * \param which_adc  [0,1]
-   * \returns value in the range [0,4095] if successful, else READ_FAILED.
-   */
-  int read_aux_adc (int slot, int which_adc);
-
-public:
-  virtual ~usrp_basic ();
-
-  /*!
-   * \brief return frequency of master oscillator on USRP
-   */
-  long  fpga_master_clock_freq () const { return 64000000; }
-
-  /*!
-   * \returns usb data rate in bytes/sec
-   */
-  int usb_data_rate () const { return d_usb_data_rate; }
-
-  void set_verbose (bool on) { d_verbose = on; }
-
-  //! magic value used on alternate register read interfaces
-  static const int READ_FAILED = -99999;
-
-  /*!
-   * \brief Write EEPROM on motherboard or any daughterboard.
-   * \param i2c_addr           I2C bus address of EEPROM
-   * \param eeprom_offset      byte offset in EEPROM to begin writing
-   * \param buf                        the data to write
-   * \returns true iff sucessful
-   */
-  bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf);
-
-  /*!
-   * \brief Read EEPROM on motherboard or any daughterboard.
-   * \param i2c_addr           I2C bus address of EEPROM
-   * \param eeprom_offset      byte offset in EEPROM to begin reading
-   * \param len                        number of bytes to read
-   * \returns the data read if successful, else a zero length string.
-   */
-  std::string read_eeprom (int i2c_addr, int eeprom_offset, int len);
-
-  /*!
-   * \brief Write to I2C peripheral
-   * \param i2c_addr           I2C bus address (7-bits)
-   * \param buf                        the data to write
-   * \returns true iff successful
-   * Writes are limited to a maximum of of 64 bytes.
-   */
-  bool write_i2c (int i2c_addr, const std::string buf);
-
-  /*!
-   * \brief Read from I2C peripheral
-   * \param i2c_addr           I2C bus address (7-bits)
-   * \param len                        number of bytes to read
-   * \returns the data read if successful, else a zero length string.
-   * Reads are limited to a maximum of 64 bytes.
-   */
-  std::string read_i2c (int i2c_addr, int len);
-
-  /*!
-   * \brief Set ADC offset correction
-   * \param which      which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q...
-   * \param offset     16-bit value to subtract from raw ADC input.
-   */
-  bool set_adc_offset (int which, int offset);
-
-  /*!
-   * \brief Set DAC offset correction
-   * \param which      which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q...
-   * \param offset     10-bit offset value (ambiguous format:  See AD9862 datasheet).
-   * \param offset_pin 1-bit value.  If 0 offset applied to -ve differential pin;
-   *                                  If 1 offset applied to +ve differential pin.
-   */
-  bool set_dac_offset (int which, int offset, int offset_pin);
-
-  /*!
-   * \brief Control ADC input buffer
-   * \param which      which ADC[0,3]
-   * \param bypass     if non-zero, bypass input buffer and connect input
-   *                   directly to switched cap SHA input of RxPGA.
-   */
-  bool set_adc_buffer_bypass (int which, bool bypass);
-
-
-  /*!
-   * \brief return the usrp's serial number.
-   *
-   * \returns non-zero length string iff successful.
-   */
-  std::string serial_number();
-
-  // ----------------------------------------------------------------
-  // Low level implementation routines.
-  // You probably shouldn't be using these...
-  //
-
-  bool _set_led (int which, bool on);
-
-  /*!
-   * \brief Write FPGA register.
-   * \param regno      7-bit register number
-   * \param value      32-bit value
-   * \returns true iff successful
-   */
-  bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value
-
-  /*!
-   * \brief Read FPGA register.
-   * \param regno      7-bit register number
-   * \param value      32-bit value
-   * \returns true iff successful
-   */
-  bool _read_fpga_reg (int regno, int *value); //< 7-bit regno, 32-bit value
-
-  /*!
-   * \brief Read FPGA register.
-   * \param regno      7-bit register number
-   * \returns register value if successful, else READ_FAILED
-   */
-  int  _read_fpga_reg (int regno);
-
-
-  /*!
-   * \brief Write FPGA register with mask.
-   * \param regno      7-bit register number
-   * \param value      16-bit value
-   * \param mask       16-bit value
-   * \returns true if successful
-   * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE
-   */
-  bool _write_fpga_reg_masked (int regno, int value, int mask);
-
-  /*!
-   * \brief Write AD9862 register.
-   * \param which_codec 0 or 1
-   * \param regno      6-bit register number
-   * \param value      8-bit value
-   * \returns true iff successful
-   */
-  bool _write_9862 (int which_codec, int regno, unsigned char value);
-
-  /*!
-   * \brief Read AD9862 register.
-   * \param which_codec 0 or 1
-   * \param regno      6-bit register number
-   * \param value      8-bit value
-   * \returns true iff successful
-   */
-  bool _read_9862 (int which_codec, int regno, unsigned char *value) const;
-
-  /*!
-   * \brief Read AD9862 register.
-   * \param which_codec 0 or 1
-   * \param regno      6-bit register number
-   * \returns register value if successful, else READ_FAILED
-   */
-  int  _read_9862 (int which_codec, int regno) const;
-
-  /*!
-   * \brief Write data to SPI bus peripheral.
-   *
-   * \param optional_header    0,1 or 2 bytes to write before buf.
-   * \param enables            bitmask of peripherals to write. See usrp_spi_defs.h
-   * \param format             transaction format.  See usrp_spi_defs.h SPI_FMT_*
-   * \param buf                        the data to write
-   * \returns true iff successful
-   * Writes are limited to a maximum of 64 bytes.
-   *
-   * If \p format specifies that optional_header bytes are present, they are
-   * written to the peripheral immediately prior to writing \p buf.
-   */
-  bool _write_spi (int optional_header, int enables, int format, std::string buf);
-
-  /*
-   * \brief Read data from SPI bus peripheral.
-   *
-   * \param optional_header    0,1 or 2 bytes to write before buf.
-   * \param enables            bitmask of peripheral to read. See usrp_spi_defs.h
-   * \param format             transaction format.  See usrp_spi_defs.h SPI_FMT_*
-   * \param len                        number of bytes to read.  Must be in [0,64].
-   * \returns the data read if sucessful, else a zero length string.
-   *
-   * Reads are limited to a maximum of 64 bytes.
-   *
-   * If \p format specifies that optional_header bytes are present, they
-   * are written to the peripheral first.  Then \p len bytes are read from
-   * the peripheral and returned.
-   */
-  std::string _read_spi (int optional_header, int enables, int format, int len);
-
-  /*!
-   * \brief Start data transfers.
-   * Called in base class to derived class order.
-   */
-  bool start ();
-
-  /*!
-   * \brief Stop data transfers.
-   * Called in base class to derived class order.
-   */
-  bool stop ();
-};
-
-\f/*!
- * \brief class for accessing the receive side of the USRP
- */
-class usrp_basic_rx : public usrp_basic 
-{
-private:
-  fusb_devhandle       *d_devhandle;
-  fusb_ephandle                *d_ephandle;
-  int                   d_bytes_seen;          // how many bytes we've seen
-  bool                  d_first_read;
-  bool                  d_rx_enable;
-
-protected:
-  int                   d_dbid[2];             // Rx daughterboard ID's
-
-  /*!
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
-   */
-  usrp_basic_rx (int which_board,
-                int fusb_block_size=0,
-                int fusb_nblocks=0,
-                const std::string fpga_filename = "",
-                const std::string firmware_filename = ""
-                );  // throws if trouble
-
-  bool set_rx_enable (bool on);
-  bool rx_enable () const { return d_rx_enable; }
-
-  bool disable_rx ();          // conditional disable, return prev state
-  void restore_rx (bool on);   // conditional set
-
-  void probe_rx_slots (bool verbose);
-  int  dboard_to_slot (int dboard) { return (dboard << 1) | 1; }
-
-public:
-  ~usrp_basic_rx ();
-
-  /*!
-   * \brief invokes constructor, returns instance or 0 if trouble
-   *
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
-   */
-  static usrp_basic_rx *make (int which_board,
-                             int fusb_block_size=0,
-                             int fusb_nblocks=0,
-                             const std::string fpga_filename = "",
-                             const std::string firmware_filename = ""
-                             );
-
-  // MANIPULATORS
-
-  /*!
-   * \brief tell the fpga the rate rx samples are coming from the A/D's
-   *
-   * div = fpga_master_clock_freq () / sample_rate
-   *
-   * sample_rate is determined by a myriad of registers
-   * in the 9862.  That's why you have to tell us, so
-   * we can tell the fpga.
-   */
-  bool set_fpga_rx_sample_rate_divisor (unsigned int div);
-
-  /*!
-   * \brief read data from the D/A's via the FPGA.
-   * \p len must be a multiple of 512 bytes.
-   *
-   * \returns the number of bytes read, or -1 on error.
-   *
-   * If overrun is non-NULL it will be set true iff an RX overrun is detected.
-   */
-  int read (void *buf, int len, bool *overrun);
-
-  // ACCESSORS
-
-  //! sampling rate of A/D converter
-  virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M
-  long adc_rate() const { return converter_rate(); }
-  long adc_freq() const { return converter_rate(); }   //!< deprecated method name
-
-  /*!
-   * \brief Return daughterboard ID for given Rx daughterboard slot [0,1].
-   *
-   * \param which_dboard       [0,1] which Rx daughterboard
-   *
-   * \return daughterboard id >= 0 if successful
-   * \return -1 if no daugherboard
-   * \return -2 if invalid EEPROM on daughterboard
-   */
-  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }
-
-  // ----------------------------------------------------------------
-  // routines for controlling the Programmable Gain Amplifier
-  /*!
-   * \brief Set Programmable Gain Amplifier (PGA)
-   *
-   * \param which      which A/D [0,3]
-   * \param gain_in_db gain value (linear in dB)
-   *
-   * gain is rounded to closest setting supported by hardware.
-   *
-   * \returns true iff sucessful.
-   *
-   * \sa pga_min(), pga_max(), pga_db_per_step()
-   */
-  bool set_pga (int which, double gain_in_db);
-
-  /*!
-   * \brief Return programmable gain amplifier gain setting in dB.
-   *
-   * \param which      which A/D [0,3]
-   */
-  double pga (int which) const;
-
-  /*!
-   * \brief Return minimum legal PGA gain in dB.
-   */
-  double pga_min () const { return 0.0; }
-
-  /*!
-   * \brief Return maximum legal PGA gain in dB.
-   */
-  double pga_max () const { return 20.0; }
-
-  /*!
-   * \brief Return hardware step size of PGA (linear in dB).
-   */
-  double pga_db_per_step () const { return 20.0 / 20; }
-
-  /*!
-   * \brief Write direction register (output enables) for pins that go to daughterboard.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              value to write into register
-   * \param mask               which bits of value to write into reg
-   *
-   * Each d'board has 16-bits of general purpose i/o.
-   * Setting the bit makes it an output from the FPGA to the d'board.
-   *
-   * This register is initialized based on a value stored in the
-   * d'board EEPROM.  In general, you shouldn't be using this routine
-   * without a very good reason.  Using this method incorrectly will
-   * kill your USRP motherboard and/or daughterboard.
-   */
-  bool _write_oe (int which_dboard, int value, int mask);
-
-  /*!
-   * \brief Write daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              value to write into register
-   * \param mask               which bits of value to write into reg
-   */
-  bool write_io (int which_dboard, int value, int mask);
-
-  /*!
-   * \brief Read daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              output
-   */
-  bool read_io (int which_dboard, int *value);
-
-  /*!
-   * \brief Read daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \returns register value if successful, else READ_FAILED
-   */
-  int read_io (int which_dboard);
-
-  /*!
-   * \brief Write auxiliary digital to analog converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   *                           N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
-   *                           SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
-   * \param which_dac          [2,3] TX slots must use only 2 and 3.
-   * \param value              [0,4095]
-   * \returns true iff successful
-   */
-  bool write_aux_dac (int which_board, int which_dac, int value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param which_adc          [0,1]
-   * \param value              return 12-bit value [0,4095]
-   * \returns true iff successful
-   */
-  bool read_aux_adc (int which_dboard, int which_adc, int *value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param which_adc          [0,1]
-   * \returns value in the range [0,4095] if successful, else READ_FAILED.
-   */
-  int read_aux_adc (int which_dboard, int which_adc);
-
-  /*!
-   * \brief returns current fusb block size
-   */
-  int block_size() const;
-
-  /*!
-   * \brief Enable/disable automatic DC offset removal control loop in FPGA
-   *
-   * \param bits  which control loops to enable
-   * \param mask  which \p bits to pay attention to
-   *
-   * If the corresponding bit is set, enable the automatic DC
-   * offset correction control loop.
-   *
-   * <pre>
-   * The 4 low bits are significant:
-   *
-   *   ADC0 = (1 << 0)
-   *   ADC1 = (1 << 1)
-   *   ADC2 = (1 << 2)
-   *   ADC3 = (1 << 3)
-   * </pre>
-   *
-   * By default the control loop is enabled on all ADC's.
-   */
-  bool set_dc_offset_cl_enable(int bits, int mask);
-
-  // called in base class to derived class order
-  bool start ();
-  bool stop ();
-};
-
-\f/*!
- * \brief class for accessing the transmit side of the USRP
- */
-class usrp_basic_tx : public usrp_basic 
-{
-private:
-  fusb_devhandle       *d_devhandle;
-  fusb_ephandle                *d_ephandle;
-  int                   d_bytes_seen;          // how many bytes we've seen
-  bool                  d_first_write;
-  bool                  d_tx_enable;
-
- protected:
-  int                   d_dbid[2];             // Tx daughterboard ID's
-
-  /*!
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512.
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default.
-   */
-  usrp_basic_tx (int which_board,
-                int fusb_block_size=0,
-                int fusb_nblocks=0,
-                const std::string fpga_filename = "",
-                const std::string firmware_filename = ""
-                );             // throws if trouble
-
-  bool set_tx_enable (bool on);
-  bool tx_enable () const { return d_tx_enable; }
-
-  bool disable_tx ();          // conditional disable, return prev state
-  void restore_tx (bool on);   // conditional set
-
-  void probe_tx_slots (bool verbose);
-  int  dboard_to_slot (int dboard) { return (dboard << 1) | 0; }
-
-public:
-
-  ~usrp_basic_tx ();
-
-  /*!
-   * \brief invokes constructor, returns instance or 0 if trouble
-   *
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
-   */
-  static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0,
-                             const std::string fpga_filename = "",
-                             const std::string firmware_filename = ""
-                             );
-
-  // MANIPULATORS
-
-  /*!
-   * \brief tell the fpga the rate tx samples are going to the D/A's
-   *
-   * div = fpga_master_clock_freq () * 2
-   *
-   * sample_rate is determined by a myriad of registers
-   * in the 9862.  That's why you have to tell us, so
-   * we can tell the fpga.
-   */
-  bool set_fpga_tx_sample_rate_divisor (unsigned int div);
-
-  /*!
-   * \brief Write data to the A/D's via the FPGA.
-   *
-   * \p len must be a multiple of 512 bytes.
-   * \returns number of bytes written or -1 on error.
-   *
-   * if \p underrun is non-NULL, it will be set to true iff
-   * a transmit underrun condition is detected.
-   */
-  int write (const void *buf, int len, bool *underrun);
-
-  /*
-   * Block until all outstanding writes have completed.
-   * This is typically used to assist with benchmarking
-   */
-  void wait_for_completion ();
-
-  // ACCESSORS
-
-  //! sampling rate of D/A converter
-  virtual long converter_rate() const { return fpga_master_clock_freq () * 2; } // 128M
-  long dac_rate() const { return converter_rate(); }
-  long dac_freq() const { return converter_rate(); }   //!< deprecated method name
-
-  /*!
-   * \brief Return daughterboard ID for given Tx daughterboard slot [0,1].
-   *
-   * \return daughterboard id >= 0 if successful
-   * \return -1 if no daugherboard
-   * \return -2 if invalid EEPROM on daughterboard
-   */
-  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }
-
-  // ----------------------------------------------------------------
-  // routines for controlling the Programmable Gain Amplifier
-  /*!
-   * \brief Set Programmable Gain Amplifier (PGA)
-   *
-   * \param which      which D/A [0,3]
-   * \param gain_in_db gain value (linear in dB)
-   *
-   * gain is rounded to closest setting supported by hardware.
-   * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3.
-   * Setting DAC 0 affects DAC 1 and vice versa.  Same with DAC 2 and DAC 3.
-   *
-   * \returns true iff sucessful.
-   *
-   * \sa pga_min(), pga_max(), pga_db_per_step()
-   */
-  bool set_pga (int which, double gain_in_db);
-
-  /*!
-   * \brief Return programmable gain amplifier gain in dB.
-   *
-   * \param which      which D/A [0,3]
-   */
-  double pga (int which) const;
-
-  /*!
-   * \brief Return minimum legal PGA gain in dB.
-   */
-  double pga_min () const { return -20.0; }
-
-  /*!
-   * \brief Return maximum legal PGA gain in dB.
-   */
-  double pga_max () const { return 0.0; }
-
-  /*!
-   * \brief Return hardware step size of PGA (linear in dB).
-   */
-  double pga_db_per_step () const { return 20.0/255; }
-
-  /*!
-   * \brief Write direction register (output enables) for pins that go to daughterboard.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              value to write into register
-   * \param mask               which bits of value to write into reg
-   *
-   * Each d'board has 16-bits of general purpose i/o.
-   * Setting the bit makes it an output from the FPGA to the d'board.
-   *
-   * This register is initialized based on a value stored in the
-   * d'board EEPROM.  In general, you shouldn't be using this routine
-   * without a very good reason.  Using this method incorrectly will
-   * kill your USRP motherboard and/or daughterboard.
-   */
-  bool _write_oe (int which_dboard, int value, int mask);
-
-  /*!
-   * \brief Write daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              value to write into register
-   * \param mask               which bits of value to write into reg
-   */
-  bool write_io (int which_dboard, int value, int mask);
-
-  /*!
-   * \brief Read daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param value              return value
-   */
-  bool read_io (int which_dboard, int *value);
-
-  /*!
-   * \brief Read daughterboard i/o pin value
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \returns register value if successful, else READ_FAILED
-   */
-  int read_io (int which_dboard);
-
-  /*!
-   * \brief Write auxiliary digital to analog converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   *                           N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
-   *                           SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
-   * \param which_dac          [2,3] TX slots must use only 2 and 3.
-   * \param value              [0,4095]
-   * \returns true iff successful
-   */
-  bool write_aux_dac (int which_board, int which_dac, int value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param which_adc          [0,1]
-   * \param value              return 12-bit value [0,4095]
-   * \returns true iff successful
-   */
-  bool read_aux_adc (int which_dboard, int which_adc, int *value);
-
-  /*!
-   * \brief Read auxiliary analog to digital converter.
-   *
-   * \param which_dboard       [0,1] which d'board
-   * \param which_adc          [0,1]
-   * \returns value in the range [0,4095] if successful, else READ_FAILED.
-   */
-  int read_aux_adc (int which_dboard, int which_adc);
-
-  /*!
-   * \brief returns current fusb block size
-   */
-  int block_size() const;
-
-  // called in base class to derived class order
-  bool start ();
-  bool stop ();
-};
-
-#endif
diff --git a/usrp/host/lib/usrp_bytesex.h b/usrp/host/lib/usrp_bytesex.h
deleted file mode 100644 (file)
index 391d29c..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-#ifndef INCLUDED_USRP_BYTESEX_H
-#define INCLUDED_USRP_BYTESEX_H
-
-/*!
- * \brief routines for convertering between host and usrp byte order
- *
- * Prior to including this file, the user must include "config.h"
- * which will or won't define WORDS_BIGENDIAN based on the
- * result of the AC_C_BIGENDIAN autoconf test.
- */
-
-#ifdef HAVE_BYTESWAP_H
-#include <byteswap.h>
-#else
-static inline unsigned short int
-bswap_16 (unsigned short int x)
-{
-  return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
-}
-#endif
-
-
-#ifdef WORDS_BIGENDIAN
-
-static inline short int
-host_to_usrp_short (short int x)
-{
-  return bswap_16 (x);
-}
-
-static inline short int
-usrp_to_host_short (short int x)
-{
-  return bswap_16 (x);
-}
-
-#else
-
-static inline short int
-host_to_usrp_short (short int x)
-{
-  return x;
-}
-
-static inline short int
-usrp_to_host_short (unsigned short int x)
-{
-  return x;
-}
-
-#endif
-
-#endif /* INCLUDED_USRP_BYTESEX_H */
diff --git a/usrp/host/lib/usrp_config.cc b/usrp/host/lib/usrp_config.cc
deleted file mode 100644 (file)
index 17bfd48..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "usrp_config.h"
-
-int
-usrp_rx_config_stream_count (unsigned int usrp_rx_config)
-{
-  return 1;
-}
-
-int
-usrp_tx_config_stream_count (unsigned int usrp_tx_config)
-{
-  return 1;
-}
diff --git a/usrp/host/lib/usrp_config.h b/usrp/host/lib/usrp_config.h
deleted file mode 100644 (file)
index 91b398b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _USRP_CONFIG_H_
-#define _USRP_CONFIG_H_
-
-/*
- * ----------------------------------------------------------------
- * USRP Rx configurations.
- *
- * For now this is a placeholder, but will eventually specify the
- * mapping from A/D outputs to DDC inputs (I & Q).
- *
- * What's implemented today is a single DDC that has its I input
- * connected to ADC0 and its Q input connected to ADC1
- * ----------------------------------------------------------------
- */
-
-#define        USRP_RX_CONFIG_DEFAULT  0
-
-/*!
- * given a usrp_rx_config word, return the number of I & Q streams that
- * are interleaved on the USB.
- */
-
-int usrp_rx_config_stream_count (unsigned int usrp_rx_config);
-
-/*
- * USRP Tx configurations.
- *
- * For now this is a placeholder, but will eventually specify the
- * mapping from DUC outputs to D/A inputs.
- *
- * What's implemented today is a single DUC that has its I output
- * connected to DAC0 and its Q output connected to DAC1
- */
-
-#define        USRP_TX_CONFIG_DEFAULT  0
-
-/*!
- * given a usrp_tx_config word, return the number of I & Q streams that
- * are interleaved on the USB.
- */
-
-int usrp_tx_config_stream_count (unsigned int usrp_tx_config);
-
-
-#endif /* _USRP_CONFIG_H_ */
diff --git a/usrp/host/lib/usrp_dbid.dat b/usrp/host/lib/usrp_dbid.dat
deleted file mode 100644 (file)
index a85d053..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Copyright 2005 Free Software Foundation, Inc.
-# 
-# This file is part of GNU Radio
-# 
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-# 
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-
-# This file is used to generate usrp_dbid.h, usrp_dbid.cc and usrp_dbid.py
-
-"Basic Tx"             0x0000
-"Basic Rx"             0x0001
-"DBS Rx"               0x0002
-"TV Rx"                        0x0003
-
-"Flex 400 Rx"          0x0004
-"Flex 900 Rx"          0x0005
-"Flex 1200 Rx"         0x0006
-"Flex 2400 Rx"         0x0007
-
-"Flex 400 Tx"          0x0008
-"Flex 900 Tx"          0x0009
-"Flex 1200 Tx"         0x000a
-"Flex 2400 Tx"         0x000b
-
-"TV Rx Rev 2"          0x000c
-"DBS Rx Rev 2_1"       0x000d
-
-"LF Tx"                        0x000e
-"LF Rx"                        0x000f
-
-"Flex 400 Rx MIMO A"   0x0014
-"Flex 900 Rx MIMO A"   0x0015
-"Flex 1200 Rx MIMO A"  0x0016
-"Flex 2400 Rx MIMO A"  0x0017
-
-"Flex 400 Tx MIMO A"   0x0018
-"Flex 900 Tx MIMO A"   0x0019
-"Flex 1200 Tx MIMO A"  0x001a
-"Flex 2400 Tx MIMO A"  0x001b
-
-"Flex 400 Rx MIMO B"   0x0024
-"Flex 900 Rx MIMO B"   0x0025
-"Flex 1200 Rx MIMO B"  0x0026
-"Flex 2400 Rx MIMO B"  0x0027
-
-"Flex 400 Tx MIMO B"   0x0028
-"Flex 900 Tx MIMO B"   0x0029
-"Flex 1200 Tx MIMO B"  0x002a
-"Flex 2400 Tx MIMO B"  0x002b
-
-"Flex 1800 Rx"         0x0030
-"Flex 1800 Tx"         0x0031
-"Flex 1800 Rx MIMO A"  0x0032
-"Flex 1800 Tx MIMO A"  0x0033
-"Flex 1800 Rx MIMO B"  0x0034
-"Flex 1800 Tx MIMO B"  0x0035
-
-"TV Rx Rev 3"          0x0040
-
-"Experimental Tx"      0xfffe
-"Experimental Rx"      0xffff
diff --git a/usrp/host/lib/usrp_local_sighandler.cc b/usrp/host/lib/usrp_local_sighandler.cc
deleted file mode 100644 (file)
index ab6c485..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * This is actually the same as gr_local_signhandler, but with a different name.
- * We don't have a common library to put this in, so...
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <usrp_local_sighandler.h>
-#include <stdexcept>
-#include <stdio.h>
-
-usrp_local_sighandler::usrp_local_sighandler (int signum,
-                                             void (*new_handler)(int))
-  : d_signum (signum)
-{
-#ifdef HAVE_SIGACTION
-  struct sigaction new_action;
-  memset (&new_action, 0, sizeof (new_action));
-
-  new_action.sa_handler = new_handler;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_flags = 0;
-
-  if (sigaction (d_signum, &new_action, &d_old_action) < 0){
-    perror ("sigaction (install new)");
-    throw std::runtime_error ("sigaction");
-  }
-#endif
-}
-
-usrp_local_sighandler::~usrp_local_sighandler ()
-{
-#ifdef HAVE_SIGACTION
-  if (sigaction (d_signum, &d_old_action, 0) < 0){
-    perror ("sigaction (restore old)");
-    throw std::runtime_error ("sigaction");
-  }
-#endif
-}
-
-void
-usrp_local_sighandler::throw_signal(int signum) throw(usrp_signal)
-{
-  throw usrp_signal (signum);
-}
-
-/*
- * Semi-hideous way to may a signal number into a signal name
- */
-
-#define SIGNAME(x) case x: return #x
-
-std::string
-usrp_signal::name () const
-{
-  char tmp[128];
-
-  switch (signal ()){
-#ifdef SIGHUP
-    SIGNAME (SIGHUP);
-#endif
-#ifdef SIGINT
-    SIGNAME (SIGINT);
-#endif
-#ifdef SIGQUIT
-    SIGNAME (SIGQUIT);
-#endif
-#ifdef SIGILL
-    SIGNAME (SIGILL);
-#endif
-#ifdef SIGTRAP
-    SIGNAME (SIGTRAP);
-#endif
-#ifdef SIGABRT
-    SIGNAME (SIGABRT);
-#endif
-#ifdef SIGBUS
-    SIGNAME (SIGBUS);
-#endif
-#ifdef SIGFPE
-    SIGNAME (SIGFPE);
-#endif
-#ifdef SIGKILL
-    SIGNAME (SIGKILL);
-#endif
-#ifdef SIGUSR1
-    SIGNAME (SIGUSR1);
-#endif
-#ifdef SIGSEGV
-    SIGNAME (SIGSEGV);
-#endif
-#ifdef SIGUSR2
-    SIGNAME (SIGUSR2);
-#endif
-#ifdef SIGPIPE
-    SIGNAME (SIGPIPE);
-#endif
-#ifdef SIGALRM
-    SIGNAME (SIGALRM);
-#endif
-#ifdef SIGTERM
-    SIGNAME (SIGTERM);
-#endif
-#ifdef SIGSTKFLT
-    SIGNAME (SIGSTKFLT);
-#endif
-#ifdef SIGCHLD
-    SIGNAME (SIGCHLD);
-#endif
-#ifdef SIGCONT
-    SIGNAME (SIGCONT);
-#endif
-#ifdef SIGSTOP
-    SIGNAME (SIGSTOP);
-#endif
-#ifdef SIGTSTP
-    SIGNAME (SIGTSTP);
-#endif
-#ifdef SIGTTIN
-    SIGNAME (SIGTTIN);
-#endif
-#ifdef SIGTTOU
-    SIGNAME (SIGTTOU);
-#endif
-#ifdef SIGURG
-    SIGNAME (SIGURG);
-#endif
-#ifdef SIGXCPU
-    SIGNAME (SIGXCPU);
-#endif
-#ifdef SIGXFSZ
-    SIGNAME (SIGXFSZ);
-#endif
-#ifdef SIGVTALRM
-    SIGNAME (SIGVTALRM);
-#endif
-#ifdef SIGPROF
-    SIGNAME (SIGPROF);
-#endif
-#ifdef SIGWINCH
-    SIGNAME (SIGWINCH);
-#endif
-#ifdef SIGIO
-    SIGNAME (SIGIO);
-#endif
-#ifdef SIGPWR
-    SIGNAME (SIGPWR);
-#endif
-#ifdef SIGSYS
-    SIGNAME (SIGSYS);
-#endif
-  default:
-#if defined (HAVE_SNPRINTF)
-#if defined (SIGRTMIN) && defined (SIGRTMAX) 
-    if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){
-      snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ());
-      return tmp;
-    }
-#endif
-    snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ());
-    return tmp;
-#else
-    return "Unknown signal";
-#endif
-  }
-}
diff --git a/usrp/host/lib/usrp_local_sighandler.h b/usrp/host/lib/usrp_local_sighandler.h
deleted file mode 100644 (file)
index f1c00cd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_USRP_LOCAL_SIGHANDLER_H
-#define INCLUDED_USRP_LOCAL_SIGHANDLER_H
-
-#include <signal.h>
-#include <string>
-
-/*!
- * \brief Representation of signal.
- */
-class usrp_signal
-{
-  int  d_signum;
-public:
-  usrp_signal (int signum) : d_signum (signum) {}
-  int signal () const { return d_signum; }
-  std::string name () const;
-};
-
-
-/*!
- * \brief Get and set signal handler.
- *
- * Constructor installs new handler, destructor reinstalls
- * original value.
- */
-class usrp_local_sighandler {
-  int                  d_signum;
-#ifdef HAVE_SIGACTION
-  struct sigaction     d_old_action;
-#endif
-public:
-  usrp_local_sighandler (int signum, void (*new_handler)(int));
-  ~usrp_local_sighandler ();
-
-  /* throw usrp_signal (signum) */
-  static void throw_signal (int signum) throw (usrp_signal);
-};
-
-#endif /* INCLUDED_USRP_LOCAL_SIGHANDLER_H */
diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc
deleted file mode 100644 (file)
index f666a29..0000000
+++ /dev/null
@@ -1,1356 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2004,2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "usrp_prims.h"
-#include "usrp_commands.h"
-#include "usrp_ids.h"
-#include "usrp_i2c_addr.h"
-#include "fpga_regs_common.h"
-#include "fpga_regs_standard.h"
-#include <usb.h>
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>              // FIXME should check with autoconf (nanosleep)
-#include <algorithm>
-#include <ad9862.h>
-#include <assert.h>
-
-extern "C" {
-#include "md5.h"
-};
-
-#define VERBOSE 0
-
-using namespace ad9862;
-
-static const int FIRMWARE_HASH_SLOT    = 0;
-static const int FPGA_HASH_SLOT        = 1;
-
-static const int hash_slot_addr[2] = {
-  USRP_HASH_SLOT_0_ADDR,
-  USRP_HASH_SLOT_1_ADDR
-};
-
-static char *default_firmware_filename = "std.ihx";
-static char *default_fpga_filename     = "std_2rxhb_2tx.rbf";
-
-#include "std_paths.h"
-
-static char *
-find_file (const char *filename, int hw_rev)
-{
-  char **sp = std_paths;
-  static char path[1000];
-  char *s;
-
-  s = getenv("USRP_PATH");
-  if (s) {
-    snprintf (path, sizeof (path), "%s/rev%d/%s", s, hw_rev, filename);
-    if (access (path, R_OK) == 0)
-      return path;
-  }
-
-  while (*sp){
-    snprintf (path, sizeof (path), "%s/rev%d/%s", *sp, hw_rev, filename);
-    if (access (path, R_OK) == 0)
-      return path;
-    sp++;
-  }
-  return 0;
-}
-
-static const char *
-get_proto_filename(const std::string user_filename, const char *env_var, const char *def)
-{
-  if (user_filename.length() != 0)
-    return user_filename.c_str();
-
-  char *s = getenv(env_var);
-  if (s && *s)
-    return s;
-
-  return def;
-}
-
-
-static void power_down_9862s (struct usb_dev_handle *udh);
-
-void
-usrp_one_time_init ()
-{
-  static bool first = true;
-
-  if (first){
-    first = false;
-    usb_init ();                       // usb library init
-    usb_find_busses ();
-    usb_find_devices ();
-  }
-}
-
-void
-usrp_rescan ()
-{
-  usb_find_busses ();
-  usb_find_devices ();
-}
-
-
-// ----------------------------------------------------------------
-// Danger, big, fragile KLUDGE.  The problem is that we want to be
-// able to get from a usb_dev_handle back to a usb_device, and the
-// right way to do this is buried in a non-installed include file.
-
-static struct usb_device *
-dev_handle_to_dev (usb_dev_handle *udh)
-{
-  struct usb_dev_handle_kludge {
-    int                         fd;
-    struct usb_bus     *bus;
-    struct usb_device  *device;
-  };
-
-  return ((struct usb_dev_handle_kludge *) udh)->device;
-}
-
-// ----------------------------------------------------------------
-
-/*
- * q must be a real USRP, not an FX2.  Return its hardware rev number.
- */
-int
-usrp_hw_rev (struct usb_device *q)
-{
-  return q->descriptor.bcdDevice & 0x00FF;
-}
-
-/*
- * q must be a real USRP, not an FX2.  Return true if it's configured.
- */
-static bool
-_usrp_configured_p (struct usb_device *q)
-{
-  return (q->descriptor.bcdDevice & 0xFF00) != 0;
-}
-
-bool
-usrp_usrp_p (struct usb_device *q)
-{
-  return (q->descriptor.idVendor == USB_VID_FSF
-         && q->descriptor.idProduct == USB_PID_FSF_USRP);
-}
-
-bool
-usrp_fx2_p (struct usb_device *q)
-{
-  return (q->descriptor.idVendor == USB_VID_CYPRESS
-         && q->descriptor.idProduct == USB_PID_CYPRESS_FX2);
-}
-
-bool
-usrp_usrp0_p (struct usb_device *q)
-{
-  return usrp_usrp_p (q) && usrp_hw_rev (q) == 0;
-}
-
-bool
-usrp_usrp1_p (struct usb_device *q)
-{
-  return usrp_usrp_p (q) && usrp_hw_rev (q) == 1;
-}
-
-bool
-usrp_usrp2_p (struct usb_device *q)
-{
-  return usrp_usrp_p (q) && usrp_hw_rev (q) == 2;
-}
-
-
-bool
-usrp_unconfigured_usrp_p (struct usb_device *q)
-{
-  return usrp_usrp_p (q) && !_usrp_configured_p (q);
-}
-
-bool
-usrp_configured_usrp_p (struct usb_device *q)
-{
-  return usrp_usrp_p (q) && _usrp_configured_p (q);
-}
-
-// ----------------------------------------------------------------
-
-struct usb_device *
-usrp_find_device (int nth, bool fx2_ok_p)
-{
-  struct usb_bus *p;
-  struct usb_device *q;
-  int   n_found = 0;
-
-  usrp_one_time_init ();
-  
-  p = usb_get_busses();
-  while (p != NULL){
-    q = p->devices;
-    while (q != NULL){
-      if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){
-       if (n_found == nth)     // return this one
-         return q;
-       n_found++;              // keep looking
-      }
-      q = q->next;
-    }
-    p = p->next;
-  }
-  return 0;    // not found
-}
-
-static struct usb_dev_handle *
-usrp_open_interface (struct usb_device *dev, int interface, int altinterface)
-{
-  struct usb_dev_handle *udh = usb_open (dev);
-  if (udh == 0)
-    return 0;
-
-  if (dev != dev_handle_to_dev (udh)){
-    fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__);
-    abort ();
-  }
-
-#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-  // There's no get get_configuration function, and with some of the newer kernels
-  // setting the configuration, even if to the same value, hoses any other processes
-  // that have it open.  Hence we opt to not set it at all (We've only
-  // got a single configuration anyway).  This may hose the win32 stuff...
-
-  // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06
-  if (usb_set_configuration (udh, 1) < 0){
-    /*
-     * Ignore this error.  
-     *
-     * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that
-     * it returns -EBUSY if _any_ of the interfaces of a device are open.
-     * We've only got a single configuration, so setting it doesn't even seem
-     * like it should be required.
-     */
-  }
-#endif
-
-  if (usb_claim_interface (udh, interface) < 0){
-    fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface);
-    fprintf (stderr, "%s\n", usb_strerror());
-    usb_close (udh);
-    return 0;
-  }
-
-  if (usb_set_altinterface (udh, altinterface) < 0){
-    fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__);
-    fprintf (stderr, "%s\n", usb_strerror());
-    usb_release_interface (udh, interface);
-    usb_close (udh);
-    return 0;
-  }
-
-  return udh;
-}
-
-struct usb_dev_handle *
-usrp_open_cmd_interface (struct usb_device *dev)
-{
-  return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE);
-}
-
-struct usb_dev_handle *
-usrp_open_rx_interface (struct usb_device *dev)
-{
-  return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE);
-}
-
-struct usb_dev_handle *
-usrp_open_tx_interface (struct usb_device *dev)
-{
-  return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE);
-}
-
-bool
-usrp_close_interface (struct usb_dev_handle *udh)
-{
-  // we're assuming that closing an interface automatically releases it.
-  return usb_close (udh) == 0;
-}
-
-// ----------------------------------------------------------------
-// write internal ram using Cypress vendor extension
-
-static bool
-write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf,
-                   int start_addr, size_t len)
-{
-  int addr;
-  int n;
-  int a;
-  int quanta = MAX_EP0_PKTSIZE;
-
-  for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){
-    n = len + start_addr - addr;
-    if (n > quanta)
-      n = quanta;
-
-    a = usb_control_msg (udh, 0x40, 0xA0,
-                        addr, 0, (char *)(buf + (addr - start_addr)), n, 1000);
-
-    if (a < 0){
-      fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror());
-      return false;
-    }
-  }
-  return true;
-}
-
-// ----------------------------------------------------------------
-// whack the CPUCS register using the upload RAM vendor extension
-
-static bool
-reset_cpu (struct usb_dev_handle *udh, bool reset_p)
-{
-  unsigned char v;
-
-  if (reset_p)
-    v = 1;             // hold processor in reset
-  else
-    v = 0;             // release reset
-
-  return write_internal_ram (udh, &v, 0xE600, 1);
-}
-
-// ----------------------------------------------------------------
-// Load intel format file into cypress FX2 (8051)
-
-static bool
-_usrp_load_firmware (struct usb_dev_handle *udh, const char *filename,
-                    unsigned char hash[USRP_HASH_SIZE])
-{
-  FILE *f = fopen (filename, "ra");
-  if (f == 0){
-    perror (filename);
-    return false;
-  }
-
-  if (!reset_cpu (udh, true))  // hold CPU in reset while loading firmware
-    goto fail;
-
-  
-  char s[1024];
-  int length;
-  int addr;
-  int type;
-  unsigned char data[256];
-  unsigned char checksum, a;
-  unsigned int b;
-  int i;
-
-  while (!feof(f)){
-    fgets(s, sizeof (s), f); /* we should not use more than 263 bytes normally */
-    if(s[0]!=':'){
-      fprintf(stderr,"%s: invalid line: \"%s\"\n", filename, s);
-      goto fail;
-    }
-    sscanf(s+1, "%02x", &length);
-    sscanf(s+3, "%04x", &addr);
-    sscanf(s+7, "%02x", &type);
-
-    if(type==0){
-
-      a=length+(addr &0xff)+(addr>>8)+type;
-      for(i=0;i<length;i++){
-       sscanf (s+9+i*2,"%02x", &b);
-       data[i]=b;
-       a=a+data[i];
-      }
-
-      sscanf (s+9+length*2,"%02x", &b);
-      checksum=b;
-      if (((a+checksum)&0xff)!=0x00){
-       fprintf (stderr, "  ** Checksum failed: got 0x%02x versus 0x%02x\n", (-a)&0xff, checksum);
-       goto fail;
-      }
-      if (!write_internal_ram (udh, data, addr, length))
-       goto fail;
-    }
-    else if (type == 0x01){      // EOF
-      break;
-    }
-    else if (type == 0x02){
-      fprintf(stderr, "Extended address: whatever I do with it?\n");
-      fprintf (stderr, "%s: invalid line: \"%s\"\n", filename, s);
-      goto fail;
-    }
-  }
-
-  // we jam the hash value into the FX2 memory before letting
-  // the cpu out of reset.  When it comes out of reset it
-  // may renumerate which will invalidate udh.
-
-  if (!usrp_set_hash (udh, FIRMWARE_HASH_SLOT, hash))
-    fprintf (stderr, "usrp: failed to write firmware hash slot\n");
-
-  if (!reset_cpu (udh, false))         // take CPU out of reset
-    goto fail;
-
-  fclose (f);
-  return true;
-
- fail:
-  fclose (f);
-  return false;
-}
-
-// ----------------------------------------------------------------
-// write vendor extension command to USRP
-
-static int
-write_cmd (struct usb_dev_handle *udh,
-          int request, int value, int index,
-          unsigned char *bytes, int len)
-{
-  int  requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT;
-
-  int r = usb_control_msg (udh, requesttype, request, value, index,
-                          (char *) bytes, len, 1000);
-  if (r < 0){
-    // we get EPIPE if the firmware stalls the endpoint.
-    if (errno != EPIPE)
-      fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ());
-  }
-
-  return r;
-}
-
-// ----------------------------------------------------------------
-// load fpga
-
-static bool
-_usrp_load_fpga (struct usb_dev_handle *udh, const char *filename,
-                unsigned char hash[USRP_HASH_SIZE])
-{
-  bool ok = true;
-
-  FILE *fp = fopen (filename, "rb");
-  if (fp == 0){
-    perror (filename);
-    return false;
-  }
-
-  unsigned char buf[MAX_EP0_PKTSIZE];  // 64 is max size of EP0 packet on FX2
-  int n;
-
-  usrp_set_led (udh, 1, 1);            // led 1 on
-
-
-  // reset FPGA (and on rev1 both AD9862's, thus killing clock)
-  usrp_set_fpga_reset (udh, 1);                // hold fpga in reset
-
-  if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_BEGIN, 0, 0) != 0)
-    goto fail;
-  
-  while ((n = fread (buf, 1, sizeof (buf), fp)) > 0){
-    if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n)
-      goto fail;
-  }
-
-  if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0)
-    goto fail;
-  
-  fclose (fp);
-
-  if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash))
-    fprintf (stderr, "usrp: failed to write fpga hash slot\n");
-
-  // On the rev1 USRP, the {tx,rx}_{enable,reset} bits are
-  // controlled over the serial bus, and hence aren't observed until
-  // we've got a good fpga bitstream loaded.
-
-  usrp_set_fpga_reset (udh, 0);                // fpga out of master reset
-
-  // now these commands will work
-  
-  ok &= usrp_set_fpga_tx_enable (udh, 0);
-  ok &= usrp_set_fpga_rx_enable (udh, 0);
-
-  ok &= usrp_set_fpga_tx_reset (udh, 1);       // reset tx and rx paths
-  ok &= usrp_set_fpga_rx_reset (udh, 1);
-  ok &= usrp_set_fpga_tx_reset (udh, 0);       // reset tx and rx paths
-  ok &= usrp_set_fpga_rx_reset (udh, 0);
-
-  if (!ok)
-    fprintf (stderr, "usrp: failed to reset tx and/or rx path\n");
-
-  // Manually reset all regs except master control to zero.
-  // FIXME may want to remove this when we rework FPGA reset strategy.
-  // In the mean while, this gets us reproducible behavior.
-  for (int i = 0; i < FR_USER_0; i++){
-    if (i == FR_MASTER_CTRL)
-      continue;
-    usrp_write_fpga_reg(udh, i, 0);
-  }
-
-  power_down_9862s (udh);              // on the rev1, power these down!
-  usrp_set_led (udh, 1, 0);            // led 1 off
-
-  return true;
-
- fail:
-  power_down_9862s (udh);              // on the rev1, power these down!
-  fclose (fp);
-  return false;
-}
-
-// ----------------------------------------------------------------
-
-bool 
-usrp_set_led (struct usb_dev_handle *udh, int which, bool on)
-{
-  int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0);
-
-  return r == 0;
-}
-
-bool
-usrp_set_hash (struct usb_dev_handle *udh, int which,
-              const unsigned char hash[USRP_HASH_SIZE])
-{
-  which &= 1;
-  
-  // we use the Cypress firmware down load command to jam it in.
-  int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0,
-                          (char *) hash, USRP_HASH_SIZE, 1000);
-  return r == USRP_HASH_SIZE;
-}
-
-bool
-usrp_get_hash (struct usb_dev_handle *udh, int which, 
-              unsigned char hash[USRP_HASH_SIZE])
-{
-  which &= 1;
-  
-  // we use the Cypress firmware upload command to fetch it.
-  int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0,
-                          (char *) hash, USRP_HASH_SIZE, 1000);
-  return r == USRP_HASH_SIZE;
-}
-
-static bool
-usrp_set_switch (struct usb_dev_handle *udh, int cmd_byte, bool on)
-{
-  return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0;
-}
-
-
-static bool
-usrp1_fpga_write (struct usb_dev_handle *udh,
-                 int regno, int value)
-{
-  // on the rev1 usrp, we use the generic spi_write interface
-
-  unsigned char buf[4];
-
-  buf[0] = (value >> 24) & 0xff;       // MSB first
-  buf[1] = (value >> 16) & 0xff;
-  buf[2] = (value >>  8) & 0xff;
-  buf[3] = (value >>  0) & 0xff;
-  
-  return usrp_spi_write (udh, 0x00 | (regno & 0x7f),
-                        SPI_ENABLE_FPGA,
-                        SPI_FMT_MSB | SPI_FMT_HDR_1,
-                        buf, sizeof (buf));
-}
-
-static bool
-usrp1_fpga_read (struct usb_dev_handle *udh,
-                int regno, int *value)
-{
-  *value = 0;
-  unsigned char buf[4];
-
-  bool ok = usrp_spi_read (udh, 0x80 | (regno & 0x7f),
-                          SPI_ENABLE_FPGA,
-                          SPI_FMT_MSB | SPI_FMT_HDR_1,
-                          buf, sizeof (buf));
-
-  if (ok)
-    *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-
-  return ok;
-}
-
-
-bool
-usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value)
-{
-  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
-  case 0:                      // not supported ;)
-    abort();   
-
-  default:
-    return usrp1_fpga_write (udh, reg, value);
-  }
-}
-
-bool
-usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value)
-{
-  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
-  case 0:              // not supported ;)
-    abort();
-    
-  default:
-    return usrp1_fpga_read (udh, reg, value);
-  }
-}
-
-bool 
-usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on)
-{
-  return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on);
-}
-
-bool 
-usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on)
-{
-  return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on);
-}
-
-bool 
-usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on)
-{
-  return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on);
-}
-
-bool 
-usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on)
-{
-  return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on);
-}
-
-bool 
-usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on)
-{
-  return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on);
-}
-
-
-// ----------------------------------------------------------------
-// conditional load stuff
-
-static bool
-compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE])
-{
-  assert (USRP_HASH_SIZE == 16);
-  memset (hash, 0, USRP_HASH_SIZE);
-
-  FILE *fp = fopen (filename, "rb");
-  if (fp == 0){
-    perror (filename);
-    return false;
-  }
-  int r = md5_stream (fp, hash);
-  fclose (fp);
-  
-  return r == 0;
-}
-
-static usrp_load_status_t
-usrp_conditionally_load_something (struct usb_dev_handle *udh,
-                                  const char *filename,
-                                  bool force,
-                                  int slot,
-                                  bool loader (struct usb_dev_handle *,
-                                               const char *,
-                                               unsigned char [USRP_HASH_SIZE]))
-{
-  unsigned char file_hash[USRP_HASH_SIZE];
-  unsigned char usrp_hash[USRP_HASH_SIZE];
-  
-  if (access (filename, R_OK) != 0){
-    perror (filename);
-    return ULS_ERROR;
-  }
-
-  if (!compute_hash (filename, file_hash))
-    return ULS_ERROR;
-
-  if (!force
-      && usrp_get_hash (udh, slot, usrp_hash)
-      && memcmp (file_hash, usrp_hash, USRP_HASH_SIZE) == 0)
-    return ULS_ALREADY_LOADED;
-
-  bool r = loader (udh, filename, file_hash);
-
-  if (!r)
-    return ULS_ERROR;
-
-  return ULS_OK;
-}
-
-usrp_load_status_t
-usrp_load_firmware (struct usb_dev_handle *udh,
-                   const char *filename,
-                   bool force)
-{
-  return usrp_conditionally_load_something (udh, filename, force,
-                                           FIRMWARE_HASH_SLOT,
-                                           _usrp_load_firmware);
-}
-
-usrp_load_status_t
-usrp_load_fpga (struct usb_dev_handle *udh,
-               const char *filename,
-               bool force)
-{
-  return usrp_conditionally_load_something (udh, filename, force,
-                                           FPGA_HASH_SLOT,
-                                           _usrp_load_fpga);
-}
-
-static usb_dev_handle *
-open_nth_cmd_interface (int nth)
-{
-  struct usb_device *udev = usrp_find_device (nth);
-  if (udev == 0){
-    fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
-    return 0;
-  }
-
-  struct usb_dev_handle *udh;
-
-  udh = usrp_open_cmd_interface (udev);
-  if (udh == 0){
-    // FIXME this could be because somebody else has it open.
-    // We should delay and retry...
-    fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n");
-    usb_strerror ();
-    return 0;
-  }
-
-  return udh;
- }
-
-static bool
-our_nanosleep (const struct timespec *delay)
-{
-  struct timespec      new_delay = *delay;
-  struct timespec      remainder;
-
-  while (1){
-    int r = nanosleep (&new_delay, &remainder);
-    if (r == 0)
-      return true;
-    if (errno == EINTR)
-      new_delay = remainder;
-    else {
-      perror ("nanosleep");
-      return false;
-    }
-  }
-}
-
-static bool
-mdelay (int millisecs)
-{
-  struct timespec      ts;
-  ts.tv_sec = millisecs / 1000;
-  ts.tv_nsec = (millisecs - (1000 * ts.tv_sec)) * 1000000;
-  return our_nanosleep (&ts);
-}
-
-usrp_load_status_t
-usrp_load_firmware_nth (int nth, const char *filename, bool force){
-  struct usb_dev_handle *udh = open_nth_cmd_interface (nth);
-  if (udh == 0)
-    return ULS_ERROR;
-
-  usrp_load_status_t s = usrp_load_firmware (udh, filename, force);
-  usrp_close_interface (udh);
-
-  switch (s){
-
-  case ULS_ALREADY_LOADED:             // nothing changed...
-    return ULS_ALREADY_LOADED;
-    break;
-
-  case ULS_OK:
-    // we loaded firmware successfully.
-
-    // It's highly likely that the board will renumerate (simulate a
-    // disconnect/reconnect sequence), invalidating our current
-    // handle.
-
-    // FIXME.  Turn this into a loop that rescans until we refind ourselves
-    
-    struct timespec    t;      // delay for 1 second
-    t.tv_sec = 2;
-    t.tv_nsec = 0;
-    our_nanosleep (&t);
-
-    usb_find_busses ();                // rescan busses and devices
-    usb_find_devices ();
-
-    return ULS_OK;
-
-  default:
-  case ULS_ERROR:              // some kind of problem
-    return ULS_ERROR;
-  }
-}
-
-static void
-load_status_msg (usrp_load_status_t s, const char *type, const char *filename)
-{
-  char *e = getenv("USRP_VERBOSE");
-  bool verbose = e != 0;
-  
-  switch (s){
-  case ULS_ERROR:
-    fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename);
-    break;
-    
-  case ULS_ALREADY_LOADED:
-    if (verbose)
-      fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename);
-    break;
-
-  case ULS_OK:
-    if (verbose)
-      fprintf (stderr, "usrp: %s %s loaded successfully.\n", type, filename);
-    break;
-  }
-}
-
-bool
-usrp_load_standard_bits (int nth, bool force,
-                        const std::string fpga_filename,
-                        const std::string firmware_filename)
-{
-  usrp_load_status_t   s;
-  const char           *filename;
-  const char           *proto_filename;
-  int hw_rev;
-
-  // first, figure out what hardware rev we're dealing with
-  {
-    struct usb_device *udev = usrp_find_device (nth);
-    if (udev == 0){
-      fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
-      return false;
-    }
-    hw_rev = usrp_hw_rev (udev);
-  }
-
-  // start by loading the firmware
-
-  proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE",
-                                     default_firmware_filename);
-  filename = find_file(proto_filename, hw_rev);
-  if (filename == 0){
-    fprintf (stderr, "Can't find firmware: %s\n", proto_filename);
-    return false;
-  }
-
-  s = usrp_load_firmware_nth (nth, filename, force);
-  load_status_msg (s, "firmware", filename);
-
-  if (s == ULS_ERROR)
-    return false;
-
-  // if we actually loaded firmware, we must reload fpga ...
-  if (s == ULS_OK)
-    force = true;
-
-  // now move on to the fpga configuration bitstream
-
-  proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA",
-                                     default_fpga_filename);
-  filename = find_file (proto_filename, hw_rev);
-  if (filename == 0){
-    fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename);
-    return false;
-  }
-
-  struct usb_dev_handle *udh = open_nth_cmd_interface (nth);
-  if (udh == 0)
-    return false;
-  
-  s = usrp_load_fpga (udh, filename, force);
-  usrp_close_interface (udh);
-  load_status_msg (s, "fpga bitstream", filename);
-
-  if (s == ULS_ERROR)
-    return false;
-
-  return true;
-}
-
-bool
-_usrp_get_status (struct usb_dev_handle *udh, int which, bool *trouble)
-{
-  unsigned char        status;
-  *trouble = true;
-  
-  if (write_cmd (udh, VRQ_GET_STATUS, 0, which,
-                &status, sizeof (status)) != sizeof (status))
-    return false;
-
-  *trouble = status;
-  return true;
-}
-
-bool
-usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p)
-{
-  return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p);
-}
-
-bool
-usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p)
-{
-  return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p);
-}
-
-
-bool
-usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr,
-               const void *buf, int len)
-{
-  if (len < 1 || len > MAX_EP0_PKTSIZE)
-    return false;
-
-  return write_cmd (udh, VRQ_I2C_WRITE, i2c_addr, 0,
-                   (unsigned char *) buf, len) == len;
-}
-
-
-bool
-usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr,
-              void *buf, int len)
-{
-  if (len < 1 || len > MAX_EP0_PKTSIZE)
-    return false;
-
-  return write_cmd (udh, VRQ_I2C_READ, i2c_addr, 0,
-                   (unsigned char *) buf, len) == len;
-}
-
-bool
-usrp_spi_write (struct usb_dev_handle *udh,
-               int optional_header, int enables, int format,
-               const void *buf, int len)
-{
-  if (len < 0 || len > MAX_EP0_PKTSIZE)
-    return false;
-
-  return write_cmd (udh, VRQ_SPI_WRITE,
-                   optional_header,
-                   ((enables & 0xff) << 8) | (format & 0xff),
-                   (unsigned char *) buf, len) == len;
-}
-
-
-bool
-usrp_spi_read (struct usb_dev_handle *udh,
-              int optional_header, int enables, int format,
-              void *buf, int len)
-{
-  if (len < 0 || len > MAX_EP0_PKTSIZE)
-    return false;
-
-  return write_cmd (udh, VRQ_SPI_READ,
-                   optional_header,
-                   ((enables & 0xff) << 8) | (format & 0xff),
-                   (unsigned char *) buf, len) == len;
-}
-
-bool
-usrp_9862_write (struct usb_dev_handle *udh, int which_codec,
-                int regno, int value)
-{
-  if (0)
-    fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n",
-            which_codec, regno, value, value);
-
-  unsigned char buf[1];
-
-  buf[0] = value;
-  
-  return usrp_spi_write (udh, 0x00 | (regno & 0x3f),
-                        which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B,
-                        SPI_FMT_MSB | SPI_FMT_HDR_1,
-                        buf, 1);
-}
-
-bool
-usrp_9862_read (struct usb_dev_handle *udh, int which_codec,
-               int regno, unsigned char *value)
-{
-  return usrp_spi_read (udh, 0x80 | (regno & 0x3f),
-                       which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B,
-                       SPI_FMT_MSB | SPI_FMT_HDR_1,
-                       value, 1);
-}
-
-bool
-usrp_9862_write_many (struct usb_dev_handle *udh,
-                     int which_codec,
-                     const unsigned char *buf,
-                     int len)
-{
-  if (len & 0x1)
-    return false;              // must be even
-
-  bool result = true;
-
-  while (len > 0){
-    result &= usrp_9862_write (udh, which_codec, buf[0], buf[1]);
-    len -= 2;
-    buf += 2;
-  }
-
-  return result;
-}
-
-
-bool
-usrp_9862_write_many_all (struct usb_dev_handle *udh,
-                          const unsigned char *buf, int len)
-{
-  // FIXME handle 2/2 and 4/4 versions
-
-  bool result;
-  result  = usrp_9862_write_many (udh, 0, buf, len);
-  result &= usrp_9862_write_many (udh, 1, buf, len);
-  return result;
-}
-
-static void
-power_down_9862s (struct usb_dev_handle *udh)
-{
-  static const unsigned char regs[] = {
-    REG_RX_PWR_DN,     0x01,                   // everything
-    REG_TX_PWR_DN,     0x0f,                   // pwr dn digital and analog_both
-    REG_TX_MODULATOR,  0x00                    // coarse & fine modulators disabled
-  };
-
-  switch (usrp_hw_rev (dev_handle_to_dev (udh))){
-  case 0:
-    break;
-
-  default:
-    usrp_9862_write_many_all (udh, regs, sizeof (regs));
-    break;
-  }
-}
-
-
-
-static const int EEPROM_PAGESIZE = 16;
-
-bool
-usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr,
-                  int eeprom_offset, const void *buf, int len)
-{
-  unsigned char cmd[2];
-  const unsigned char *p = (unsigned char *) buf;
-  
-  // The simplest thing that could possibly work:
-  //   all writes are single byte writes.
-  //
-  // We could speed this up using the page write feature,
-  // but we write so infrequently, why bother...
-
-  while (len-- > 0){
-    cmd[0] = eeprom_offset++;
-    cmd[1] = *p++;
-    bool r = usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd));
-    mdelay (10);               // delay 10ms worst case write time
-    if (!r)
-      return false;
-  }
-  
-  return true;
-}
-
-bool
-usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr,
-                 int eeprom_offset, void *buf, int len)
-{
-  unsigned char *p = (unsigned char *) buf;
-
-  // We setup a random read by first doing a "zero byte write".
-  // Writes carry an address.  Reads use an implicit address.
-
-  unsigned char cmd[1];
-  cmd[0] = eeprom_offset;
-  if (!usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd)))
-    return false;
-
-  while (len > 0){
-    int n = std::min (len, MAX_EP0_PKTSIZE);
-    if (!usrp_i2c_read (udh, i2c_addr, p, n))
-      return false;
-    len -= n;
-    p += n;
-  }
-  return true;
-}
-// ----------------------------------------------------------------
-
-static bool
-slot_to_codec (int slot, int *which_codec)
-{
-  *which_codec = 0;
-  
-  switch (slot){
-  case SLOT_TX_A:
-  case SLOT_RX_A:
-    *which_codec = 0;
-    break;
-
-  case SLOT_TX_B:
-  case SLOT_RX_B:
-    *which_codec = 1;
-    break;
-
-  default:
-    fprintf (stderr, "usrp_prims:slot_to_codec: invalid slot = %d\n", slot);
-    return false;
-  }
-  return true;
-}
-
-static bool
-tx_slot_p (int slot)
-{
-  switch (slot){
-  case SLOT_TX_A:
-  case SLOT_TX_B:
-    return true;
-
-  default:
-    return false;
-  }
-}
-
-bool
-usrp_write_aux_dac (struct usb_dev_handle *udh, int slot,
-                   int which_dac, int value)
-{
-  int which_codec;
-  
-  if (!slot_to_codec (slot, &which_codec))
-    return false;
-
-  if (!(0 <= which_dac && which_dac < 4)){
-    fprintf (stderr, "usrp_write_aux_dac: invalid dac = %d\n", which_dac);
-    return false;
-  }
-
-  value &= 0x0fff;     // mask to 12-bits
-  
-  if (which_dac == 3){
-    // dac 3 is really 12-bits.  Use value as is.
-    bool r = true;
-    r &= usrp_9862_write (udh, which_codec, 43, (value >> 4));       // most sig
-    r &= usrp_9862_write (udh, which_codec, 42, (value & 0xf) << 4); // least sig
-    return r;
-  }
-  else {
-    // dac 0, 1, and 2 are really 8 bits.  
-    value = value >> 4;                // shift value appropriately
-    return usrp_9862_write (udh, which_codec, 36 + which_dac, value);
-  }
-}
-
-
-bool
-usrp_read_aux_adc (struct usb_dev_handle *udh, int slot,
-                  int which_adc, int *value)
-{
-  *value = 0;
-  int  which_codec;
-
-  if (!slot_to_codec (slot, &which_codec))
-    return false;
-
-  if (!(0 <= which_codec && which_codec < 2)){
-    fprintf (stderr, "usrp_read_aux_adc: invalid adc = %d\n", which_adc);
-    return false;
-  }
-
-  unsigned char aux_adc_control =
-    AUX_ADC_CTRL_REFSEL_A              // on chip reference
-    | AUX_ADC_CTRL_REFSEL_B;           // on chip reference
-
-  int  rd_reg = 26;    // base address of two regs to read for result
-  
-  // program the ADC mux bits
-  if (tx_slot_p (slot))
-    aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2;
-  else {
-    rd_reg += 2;
-    aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1;
-  }
-  
-  // I'm not sure if we can set the mux and issue a start conversion
-  // in the same cycle, so let's do them one at a time.
-
-  usrp_9862_write (udh, which_codec, 34, aux_adc_control);
-
-  if (which_adc == 0)
-    aux_adc_control |= AUX_ADC_CTRL_START_A;
-  else {
-    rd_reg += 4;
-    aux_adc_control |= AUX_ADC_CTRL_START_B;
-  }
-
-  // start the conversion
-  usrp_9862_write (udh, which_codec, 34, aux_adc_control);
-
-  // read the 10-bit result back
-  unsigned char v_lo = 0;
-  unsigned char v_hi = 0;
-  bool r = usrp_9862_read (udh, which_codec, rd_reg, &v_lo);
-  r &= usrp_9862_read (udh, which_codec, rd_reg + 1, &v_hi);
-
-  if (r)
-    *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit
-  
-  return r;
-}
-
-// ----------------------------------------------------------------
-
-static int slot_to_i2c_addr (int slot)
-{
-  switch (slot){
-  case SLOT_TX_A:      return I2C_ADDR_TX_A;
-  case SLOT_RX_A:      return I2C_ADDR_RX_A;
-  case SLOT_TX_B:      return I2C_ADDR_TX_B;
-  case SLOT_RX_B:      return I2C_ADDR_RX_B;
-  default:             return -1;
-  }
-}
-
-static void
-set_chksum (unsigned char *buf)
-{
-  int sum = 0;
-  unsigned int i;
-  for (i = 0; i < DB_EEPROM_CLEN - 1; i++)
-    sum += buf[i];
-  buf[i] = -sum;
-}
-
-static usrp_dbeeprom_status_t
-read_dboard_eeprom (struct usb_dev_handle *udh,
-                   int slot_id, unsigned char *buf)
-{
-  int i2c_addr = slot_to_i2c_addr (slot_id);
-  if (i2c_addr == -1)
-    return UDBE_BAD_SLOT;
-
-  if (!usrp_eeprom_read (udh, i2c_addr, 0, buf, DB_EEPROM_CLEN))
-    return UDBE_NO_EEPROM;
-
-  if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE)
-    return UDBE_INVALID_EEPROM;
-
-  int sum = 0;
-  for (unsigned int i = 0; i < DB_EEPROM_CLEN; i++)
-    sum += buf[i];
-
-  if ((sum & 0xff) != 0)
-    return UDBE_INVALID_EEPROM;
-
-  return UDBE_OK;
-}
-
-usrp_dbeeprom_status_t
-usrp_read_dboard_eeprom (struct usb_dev_handle *udh,
-                        int slot_id, usrp_dboard_eeprom *eeprom)
-{
-  unsigned char buf[DB_EEPROM_CLEN];
-
-  memset (eeprom, 0, sizeof (*eeprom));
-
-  usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf);
-  if (s != UDBE_OK)
-    return s;
-
-  eeprom->id = (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB];
-  eeprom->oe = (buf[DB_EEPROM_OE_MSB] << 8) | buf[DB_EEPROM_OE_LSB];
-  eeprom->offset[0] = (buf[DB_EEPROM_OFFSET_0_MSB] << 8) | buf[DB_EEPROM_OFFSET_0_LSB];
-  eeprom->offset[1] = (buf[DB_EEPROM_OFFSET_1_MSB] << 8) | buf[DB_EEPROM_OFFSET_1_LSB];
-
-  return UDBE_OK;
-}
-
-bool
-usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id,
-                          short offset0, short offset1)
-{
-  unsigned char buf[DB_EEPROM_CLEN];
-
-  usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf);
-  if (s != UDBE_OK)
-    return false;
-
-  buf[DB_EEPROM_OFFSET_0_LSB] = (offset0 >> 0) & 0xff;
-  buf[DB_EEPROM_OFFSET_0_MSB] = (offset0 >> 8) & 0xff;
-  buf[DB_EEPROM_OFFSET_1_LSB] = (offset1 >> 0) & 0xff;
-  buf[DB_EEPROM_OFFSET_1_MSB] = (offset1 >> 8) & 0xff;
-  set_chksum (buf);
-
-  return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id),
-                           0, buf, sizeof (buf));
-}
-
-std::string
-usrp_serial_number(struct usb_dev_handle *udh)
-{
-  unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber;
-  if (iserial == 0)
-    return "";
-
-  char buf[1024];
-  if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0)
-    return "";
-
-  return buf;
-}
diff --git a/usrp/host/lib/usrp_prims.h b/usrp/host/lib/usrp_prims.h
deleted file mode 100644 (file)
index 97cfb4a..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2003,2004,2006 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * Low level primitives for directly messing with USRP hardware.
- *
- * If you're trying to use the USRP, you'll probably want to take a look
- * at the usrp_rx and usrp_tx classes.  They hide a bunch of low level details
- * and provide high performance streaming i/o.
- *
- * This interface is built on top of libusb, which allegedly works under
- * Linux, *BSD and Mac OS/X.  http://libusb.sourceforge.net
- */
-
-#ifndef _USRP_PRIMS_H_
-#define _USRP_PRIMS_H_
-
-#include <usrp_slots.h>
-#include <string>
-
-static const int USRP_HASH_SIZE = 16;
-
-enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED };
-
-struct usb_dev_handle;
-struct usb_device;
-
-/*!
- * \brief initialize libusb; probe busses and devices.
- * Safe to call more than once.
- */
-void usrp_one_time_init ();
-
-/*
- * force a rescan of the buses and devices
- */
-void usrp_rescan ();
-
-/*!
- * \brief locate Nth (zero based) USRP device in system.
- * Return pointer or 0 if not found.
- *
- * The following kinds of devices are considered USRPs:
- *
- *   unconfigured USRP (no firwmare loaded)
- *   configured USRP (firmware loaded)
- *   unconfigured Cypress FX2 (only if fx2_ok_p is true)
- */
-struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false);
-
-bool usrp_usrp_p (struct usb_device *q);               //< is this a USRP
-bool usrp_usrp0_p (struct usb_device *q);              //< is this a USRP Rev 0
-bool usrp_usrp1_p (struct usb_device *q);              //< is this a USRP Rev 1
-bool usrp_usrp2_p (struct usb_device *q);              //< is this a USRP Rev 2
-int  usrp_hw_rev (struct usb_device *q);               //< return h/w rev code
-
-bool usrp_fx2_p (struct usb_device *q);                        //< is this an unconfigured Cypress FX2
-
-bool usrp_unconfigured_usrp_p (struct usb_device *q);  //< some kind of unconfigured USRP
-bool usrp_configured_usrp_p (struct usb_device *q);    //< some kind of configured USRP
-
-/*!
- * \brief given a usb_device return an instance of the appropriate usb_dev_handle
- *
- * These routines claim the specified interface and select the
- * correct alternate interface.  (USB nomenclature is totally screwed!)
- *
- * If interface can't be opened, or is already claimed by some other
- * process, 0 is returned.
- */
-struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev);
-struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev);
-struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev);
-
-/*!
- * \brief close interface.
- */
-bool usrp_close_interface (struct usb_dev_handle *udh);
-
-/*!
- * \brief load intel hex format file into USRP/Cypress FX2 (8051).
- *
- * The filename extension is typically *.ihx
- *
- * Note that loading firmware may cause the device to renumerate.  I.e.,
- * change its configuration, invalidating the current device handle.
- */
-
-usrp_load_status_t 
-usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force);
-
-/*!
- * \brief load intel hex format file into USRP FX2 (8051).
- *
- * The filename extension is typically *.ihx
- *
- * Note that loading firmware may cause the device to renumerate.  I.e.,
- * change its configuration, invalidating the current device handle.
- * If the result is ULS_OK, usrp_load_firmware_nth delays 1 second
- * then rescans the busses and devices.
- */
-usrp_load_status_t
-usrp_load_firmware_nth (int nth, const char *filename, bool force);
-
-/*!
- * \brief load fpga configuration bitstream
- */
-usrp_load_status_t
-usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force);
-
-/*!
- * \brief load the regular firmware and fpga bitstream in the Nth USRP.
- *
- * This is the normal starting point...
- */
-bool usrp_load_standard_bits (int nth, bool force,
-                             const std::string fpga_filename = "",
-                             const std::string firmware_filename = "");
-
-/*!
- * \brief copy the given \p hash into the USRP hash slot \p which.
- * The usrp implements two hash slots, 0 and 1.
- */
-bool usrp_set_hash (struct usb_dev_handle *udh, int which,
-                   const unsigned char hash[USRP_HASH_SIZE]);
-
-/*!
- * \brief retrieve the \p hash from the USRP hash slot \p which.
- * The usrp implements two hash slots, 0 and 1.
- */
-bool usrp_get_hash (struct usb_dev_handle *udh, int which,
-                   unsigned char hash[USRP_HASH_SIZE]);
-
-bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value);
-bool usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value);
-bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on);
-bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on);
-bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on);
-bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on);
-bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on);
-bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on);
-
-bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p);
-bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p);
-
-// i2c_read and i2c_write are limited to a maximum len of 64 bytes.
-
-bool usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr,
-                    const void *buf, int len);
-
-bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr,
-                   void *buf, int len);
-
-// spi_read and spi_write are limited to a maximum of 64 bytes
-// See usrp_spi_defs.h for more info
-
-bool usrp_spi_write (struct usb_dev_handle *udh,
-                    int optional_header, int enables, int format,
-                    const void *buf, int len);
-
-bool usrp_spi_read (struct usb_dev_handle *udh,
-                    int optional_header, int enables, int format,
-                    void *buf, int len);
-
-
-bool usrp_9862_write (struct usb_dev_handle *udh,
-                     int which_codec,                  // [0,  1]
-                     int regno,                        // [0, 63]
-                     int value);                       // [0, 255]     
-
-bool usrp_9862_read (struct usb_dev_handle *udh,
-                    int which_codec,                   // [0,  1]
-                    int regno,                         // [0, 63]
-                    unsigned char *value);             // [0, 255]
-
-/*!
- * \brief Write multiple 9862 regs at once.
- *
- * \p buf contains alternating register_number, register_value pairs.
- * \p len must be even and is the length of buf in bytes.
- */
-bool usrp_9862_write_many (struct usb_dev_handle *udh, int which_codec,
-                          const unsigned char *buf, int len);
-                          
-
-/*!
- * \brief write specified regs to all 9862's in the system
- */
-bool usrp_9862_write_many_all (struct usb_dev_handle *udh,
-                              const unsigned char *buf, int len);
-                          
-
-// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
-// Which EEPROM is determined by i2c_addr.  See i2c_addr.h
-
-bool usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr,
-                       int eeprom_offset, const void *buf, int len);
-
-
-// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
-// Which EEPROM is determined by i2c_addr.  See i2c_addr.h
-
-bool usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr,
-                      int eeprom_offset, void *buf, int len);
-
-
-// Slot specific i/o routines
-
-/*!
- * \brief write to the specified aux dac.
- *
- * \p slot: which Tx or Rx slot to write.
- *    N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's
- *          SLOT_TX_B and SLOT_RX_B share the same AUX DAC's
- *
- * \p which_dac: [0,3]  RX slots must use only 0 and 1.
- *                     TX slots must use only 2 and 3.
- *
- * AUX DAC 3 is really the 9862 sigma delta output.
- *
- * \p value to write to aux dac.  All dacs take straight
- * binary values.  Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit,
- * the interface is in terms of 12-bit values [0,4095]
- */
-bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot,
-                        int which_dac, int value);
-
-/*!
- * \brief Read the specified aux adc
- *
- * \p slot: which Tx or Rx slot to read aux dac
- * \p which_adc: [0,1]  which of the two adcs to read
- * \p *value: return value, 12-bit straight binary.
- */
-bool usrp_read_aux_adc (struct usb_dev_handle *udh, int slot,
-                       int which_adc, int *value);
-
-
-/*!
- * \brief usrp daughterboard id to name mapping
- */
-const std::string usrp_dbid_to_string (int dbid);
-
-
-enum usrp_dbeeprom_status_t { UDBE_OK, UDBE_BAD_SLOT, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM };
-
-struct usrp_dboard_eeprom {
-  unsigned short       id;             // d'board identifier code
-  unsigned short       oe;             // fpga output enables:
-                                       //   If bit set, i/o pin is an output from FPGA.
-  short                        offset[2];      // ADC/DAC offset correction
-};
-
-/*!
- * \brief Read and return parsed daughterboard eeprom
- */
-usrp_dbeeprom_status_t
-usrp_read_dboard_eeprom (struct usb_dev_handle *udh,
-                        int slot_id, usrp_dboard_eeprom *eeprom);
-
-/*!
- * \brief write ADC/DAC offset calibration constants to d'board eeprom
- */
-bool usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id,
-                               short offset0, short offset1);
-
-/*!
- * \brief return a usrp's serial number.
- *
- * Note that this only works on a configured usrp.
- * \returns non-zero length string iff successful.
- */
-std::string usrp_serial_number(struct usb_dev_handle *udh);
-
-#endif /* _USRP_PRIMS_H_ */
diff --git a/usrp/host/lib/usrp_slots.h b/usrp/host/lib/usrp_slots.h
deleted file mode 100644 (file)
index c4971d1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_USRP_SLOTS_H
-#define INCLUDED_USRP_SLOTS_H
-
-// daughterboard slot numbers used in some calls
-
-static const int SLOT_TX_A = 0;
-static const int SLOT_RX_A = 1;
-static const int SLOT_TX_B = 2;
-static const int SLOT_RX_B = 3;
-
-#endif /* INCLUDED_USRP_SLOTS_H */
diff --git a/usrp/host/lib/usrp_standard.cc b/usrp/host/lib/usrp_standard.cc
deleted file mode 100644 (file)
index 6b4ec93..0000000
+++ /dev/null
@@ -1,831 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <usrp_standard.h>
-
-#include "usrp_prims.h"
-#include "fpga_regs_common.h"
-#include "fpga_regs_standard.h"
-#include <stdexcept>
-#include <assert.h>
-#include <math.h>
-#include <ad9862.h>
-
-
-static const int OLD_CAPS_VAL = 0xaa55ff77;
-static const int DEFAULT_CAPS_VAL = ((2 << bmFR_RB_CAPS_NDUC_SHIFT)
-                                    | (2 << bmFR_RB_CAPS_NDDC_SHIFT)
-                                    | bmFR_RB_CAPS_RX_HAS_HALFBAND);
-
-// #define USE_FPGA_TX_CORDIC
-
-
-using namespace ad9862;
-
-#define NELEM(x) (sizeof (x) / sizeof (x[0]))
-
-
-static unsigned int
-compute_freq_control_word_fpga (double master_freq, double target_freq,
-                               double *actual_freq, bool verbose)
-{
-  static const int NBITS = 14;
-  
-  int  v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
-
-  if (0)
-    v = (v >> (32 - NBITS)) << (32 - NBITS);   // keep only top NBITS
-
-  *actual_freq = v * master_freq / pow (2.0, 32.0);
-
-  if (verbose)
-    fprintf (stderr,
-            "compute_freq_control_word_fpga: target = %g  actual = %g  delta = %g\n",
-            target_freq, *actual_freq, *actual_freq - target_freq);
-
-  return (unsigned int) v;
-}
-
-// The 9862 uses an unsigned 24-bit frequency tuning word and 
-// a separate register to control the sign.
-
-static unsigned int
-compute_freq_control_word_9862 (double master_freq, double target_freq,
-                               double *actual_freq, bool verbose)
-{
-  double sign = 1.0;
-
-  if (target_freq < 0)
-    sign = -1.0;
-
-  int  v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0));
-  *actual_freq = v * master_freq / pow (2.0, 24.0) * sign;
-
-  if (verbose)
-    fprintf (stderr,
-     "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n",
-     target_freq, *actual_freq, *actual_freq - target_freq, v);
-
-  return (unsigned int) v;
-}
-
-// ----------------------------------------------------------------
-
-usrp_standard_common::usrp_standard_common(usrp_basic *parent)
-{
-  // read new FPGA capability register
-  if (!parent->_read_fpga_reg(FR_RB_CAPS, &d_fpga_caps)){
-    fprintf (stderr, "usrp_standard_common: failed to read FPGA cap register.\n");
-    throw std::runtime_error ("usrp_standard_common::ctor");
-  }
-  // If we don't have the cap register, set the value to what it would
-  // have had if we did have one ;)
-  if (d_fpga_caps == OLD_CAPS_VAL)
-    d_fpga_caps = DEFAULT_CAPS_VAL;
-
-  if (0){
-    fprintf(stdout, "has_rx_halfband = %d\n", has_rx_halfband());
-    fprintf(stdout, "nddcs           = %d\n", nddcs());
-    fprintf(stdout, "has_tx_halfband = %d\n", has_tx_halfband());
-    fprintf(stdout, "nducs           = %d\n", nducs());
-  }
-}
-
-bool
-usrp_standard_common::has_rx_halfband() const
-{
-  return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? true : false;
-}
-
-int
-usrp_standard_common::nddcs() const
-{
-  return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT;
-}
-
-bool
-usrp_standard_common::has_tx_halfband() const
-{
-  return (d_fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND) ? true : false;
-}
-
-int
-usrp_standard_common::nducs() const
-{
-  return (d_fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT;
-}
-
-// ----------------------------------------------------------------
-
-static int 
-real_rx_mux_value (int mux, int nchan)
-{
-  if (mux != -1)
-    return mux;
-
-  return 0x32103210;
-}
-
-usrp_standard_rx::usrp_standard_rx (int which_board,
-                                   unsigned int decim_rate,
-                                   int nchan, int mux, int mode,
-                                   int fusb_block_size, int fusb_nblocks,
-                                   const std::string fpga_filename,
-                                   const std::string firmware_filename
-                                   )
-  : usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
-                  fpga_filename, firmware_filename),
-    usrp_standard_common(this),
-    d_nchan (1), d_sw_mux (0x0), d_hw_mux (0x0)
-{
-  if (!set_format(make_format())){
-    fprintf (stderr, "usrp_standard_rx: set_format failed\n");
-    throw std::runtime_error ("usrp_standard_rx::ctor");
-  }
-  if (!set_nchannels (nchan)){
-    fprintf (stderr, "usrp_standard_rx: set_nchannels failed\n");
-    throw std::runtime_error ("usrp_standard_rx::ctor");
-  }
-  if (!set_decim_rate (decim_rate)){
-    fprintf (stderr, "usrp_standard_rx: set_decim_rate failed\n");
-    throw std::runtime_error ("usrp_standard_rx::ctor");
-  }
-  if (!set_mux (real_rx_mux_value (mux, nchan))){
-    fprintf (stderr, "usrp_standard_rx: set_mux failed\n");
-    throw std::runtime_error ("usrp_standard_rx::ctor");
-  }
-  if (!set_fpga_mode (mode)){
-    fprintf (stderr, "usrp_standard_rx: set_fpga_mode failed\n");
-    throw std::runtime_error ("usrp_standard_rx::ctor");
-  }
-
-  for (int i = 0; i < MAX_CHAN; i++){
-    set_rx_freq(i, 0);
-    set_ddc_phase(i, 0);
-  }
-}
-
-usrp_standard_rx::~usrp_standard_rx ()
-{
-  // fprintf(stderr, "\nusrp_standard_rx: dtor\n");
-}
-
-bool
-usrp_standard_rx::start ()
-{
-  if (!usrp_basic_rx::start ())
-    return false;
-
-  // add our code here
-
-  return true;
-}
-
-bool
-usrp_standard_rx::stop ()
-{
-  bool ok = usrp_basic_rx::stop ();
-
-  // add our code here
-
-  return ok;
-}
-
-usrp_standard_rx *
-usrp_standard_rx::make (int which_board,
-                       unsigned int decim_rate,
-                       int nchan, int mux, int mode,
-                       int fusb_block_size, int fusb_nblocks,
-                       const std::string fpga_filename,
-                       const std::string firmware_filename
-                       )
-{
-  usrp_standard_rx *u = 0;
-  
-  try {
-    u = new usrp_standard_rx (which_board, decim_rate,
-                             nchan, mux, mode,
-                             fusb_block_size, fusb_nblocks,
-                             fpga_filename, firmware_filename);
-    return u;
-  }
-  catch (...){
-    delete u;
-    return 0;
-  }
-
-  return u;
-}
-
-bool
-usrp_standard_rx::set_decim_rate(unsigned int rate)
-{
-  if ((rate & 0x1) || rate < 4 || rate > 256){
-    fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n");
-    return false;
-  }
-
-  d_decim_rate = rate;
-  set_usb_data_rate ((adc_rate () / rate * nchannels ())
-                    * (2 * sizeof (short)));
-
-  bool s = disable_rx ();
-  int v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1;
-  bool ok = _write_fpga_reg (FR_DECIM_RATE, v);
-  restore_rx (s);
-  return ok;
-}
-
-bool usrp_standard_rx::set_nchannels (int nchan)
-{
-  if (!(nchan == 1 || nchan == 2 || nchan == 4))
-    return false;
-
-  if (nchan > nddcs())
-    return false;
-
-  d_nchan = nchan;
-
-  return write_hw_mux_reg ();
-}
-
-
-// map software mux value to hw mux value
-//
-// Software mux value:
-//
-//    3                   2                   1                       
-//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-// +-------+-------+-------+-------+-------+-------+-------+-------+
-// |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
-// +-------+-------+-------+-------+-------+-------+-------+-------+
-//
-// Each 4-bit I field is either 0,1,2,3
-// Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
-// All Q's must be 0xf or none of them may be 0xf
-//
-//
-// Hardware mux value:
-//
-//    3                   2                   1                       
-//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-// +-----------------------+-------+-------+-------+-------+-+-----+
-// |      must be zero     | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
-// +-----------------------+-------+-------+-------+-------+-+-----+
-
-
-static bool
-map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr)
-{
-  // confirm that all I's are either 0,1,2,3 
-
-  for (int i = 0; i < 8; i += 2){
-    int t = (sw_mux >> (4 * i)) & 0xf;
-    if (!(0 <= t && t <= 3))
-      return false;
-  }
-
-  // confirm that all Q's are either 0,1,2,3 or 0xf
-
-  for (int i = 1; i < 8; i += 2){
-    int t = (sw_mux >> (4 * i)) & 0xf;
-    if (!(t == 0xf || (0 <= t && t <= 3)))
-      return false;
-  }
-
-  // confirm that all Q inputs are 0xf (const zero input),
-  // or none of them are 0xf
-
-  int q_and = 1;
-  int q_or =  0;
-
-  for (int i = 0; i < 4; i++){
-    int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf;
-    q_and &= qx_is_0xf;
-    q_or  |= qx_is_0xf;
-  }
-
-  if (q_and || !q_or){         // OK
-    int hw_mux_value = 0;
-
-    for (int i = 0; i < 8; i++){
-      int t = (sw_mux >> (4 * i)) & 0x3;
-      hw_mux_value |= t << (2 * i + 4);
-    }
-
-    if (q_and)
-      hw_mux_value |= 0x8;     // all Q's zero
-
-    *hw_mux_ptr = hw_mux_value;
-    return true;
-  }
-  else
-    return false;
-}
-
-bool
-usrp_standard_rx::set_mux (int mux)
-{
-  if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux))
-    return false;
-
-  // fprintf (stderr, "sw_mux = 0x%08x  hw_mux = 0x%08x\n", mux, d_hw_mux);
-
-  d_sw_mux = mux;
-  return write_hw_mux_reg ();
-}
-
-bool
-usrp_standard_rx::write_hw_mux_reg ()
-{
-  bool s = disable_rx ();
-  bool ok = _write_fpga_reg (FR_RX_MUX, d_hw_mux | d_nchan);
-  restore_rx (s);
-  return ok;
-}
-
-
-bool
-usrp_standard_rx::set_rx_freq (int channel, double freq)
-{
-  if (channel < 0 || channel > MAX_CHAN)
-    return false;
-
-  unsigned int v =
-    compute_freq_control_word_fpga (adc_freq(),
-                                   freq, &d_rx_freq[channel],
-                                   d_verbose);
-
-  return _write_fpga_reg (FR_RX_FREQ_0 + channel, v);
-}
-
-unsigned int
-usrp_standard_rx::decim_rate () const { return d_decim_rate; }
-
-int
-usrp_standard_rx::nchannels () const { return d_nchan; }
-
-int
-usrp_standard_rx::mux () const { return d_sw_mux; }
-
-double 
-usrp_standard_rx::rx_freq (int channel) const
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return 0;
-
-  return d_rx_freq[channel];
-}
-
-bool
-usrp_standard_rx::set_fpga_mode (int mode)
-{
-  return _write_fpga_reg (FR_MODE, mode);
-}
-
-bool
-usrp_standard_rx::set_ddc_phase(int channel, int phase)
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return false;
-
-  return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase);
-}
-
-
-// To avoid quiet failures, check for things that our code cares about.
-
-static bool
-rx_format_is_valid(unsigned int format)
-{
-  int width =  usrp_standard_rx::format_width(format);
-  int want_q = usrp_standard_rx::format_want_q(format);
-
-  if (!(width == 8 || width == 16))    // FIXME add other widths when valid
-    return false;
-
-  if (!want_q)         // FIXME remove check when the rest of the code can handle I only
-    return false;
-
-  return true;
-}
-
-bool
-usrp_standard_rx::set_format(unsigned int format)
-{
-  if (!rx_format_is_valid(format))
-    return false;
-
-  return _write_fpga_reg(FR_RX_FORMAT, format);
-}
-
-unsigned int
-usrp_standard_rx::format() const
-{
-  return d_fpga_shadows[FR_RX_FORMAT];
-}
-
-// ----------------------------------------------------------------
-
-unsigned int 
-usrp_standard_rx::make_format(int width, int shift, bool want_q, bool bypass_halfband)
-{
-  unsigned int format = 
-    (((width << bmFR_RX_FORMAT_WIDTH_SHIFT) & bmFR_RX_FORMAT_WIDTH_MASK)
-     | (shift << bmFR_RX_FORMAT_SHIFT_SHIFT) & bmFR_RX_FORMAT_SHIFT_MASK);
-
-  if (want_q)
-    format |= bmFR_RX_FORMAT_WANT_Q;
-  if (bypass_halfband)
-    format |= bmFR_RX_FORMAT_BYPASS_HB;
-
-  return format;
-}
-
-int
-usrp_standard_rx::format_width(unsigned int format)
-{
-  return (format & bmFR_RX_FORMAT_WIDTH_MASK) >> bmFR_RX_FORMAT_WIDTH_SHIFT;
-}
-
-int
-usrp_standard_rx::format_shift(unsigned int format)
-{
-  return (format & bmFR_RX_FORMAT_SHIFT_MASK) >> bmFR_RX_FORMAT_SHIFT_SHIFT;
-}
-
-bool
-usrp_standard_rx::format_want_q(unsigned int format)
-{
-  return (format & bmFR_RX_FORMAT_WANT_Q) != 0;
-}
-
-bool
-usrp_standard_rx::format_bypass_halfband(unsigned int format)
-{
-  return (format & bmFR_RX_FORMAT_BYPASS_HB) != 0;
-}
-
-//////////////////////////////////////////////////////////////////
-
-
-// tx data is timed to CLKOUT1 (64 MHz)
-// interpolate 4x
-// fine modulator enabled
-
-
-static unsigned char tx_regs_use_nco[] = {
-  REG_TX_IF,           (TX_IF_USE_CLKOUT1
-                        | TX_IF_I_FIRST
-                        | TX_IF_2S_COMP
-                        | TX_IF_INTERLEAVED),
-  REG_TX_DIGITAL,      (TX_DIGITAL_2_DATA_PATHS
-                        | TX_DIGITAL_INTERPOLATE_4X)
-};
-
-
-static int
-real_tx_mux_value (int mux, int nchan)
-{
-  if (mux != -1)
-    return mux;
-
-  switch (nchan){
-  case 1:
-    return 0x0098;
-  case 2:
-    return 0xba98;
-  default:
-    assert (0);
-  }
-}
-
-usrp_standard_tx::usrp_standard_tx (int which_board,
-                                   unsigned int interp_rate,
-                                   int nchan, int mux,
-                                   int fusb_block_size, int fusb_nblocks,
-                                   const std::string fpga_filename,
-                                   const std::string firmware_filename
-                                   )
-  : usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename),
-    usrp_standard_common(this),
-    d_sw_mux (0x8), d_hw_mux (0x81)
-{
-  if (!usrp_9862_write_many_all (d_udh, tx_regs_use_nco, sizeof (tx_regs_use_nco))){
-    fprintf (stderr, "usrp_standard_tx: failed to init AD9862 TX regs\n");
-    throw std::runtime_error ("usrp_standard_tx::ctor");
-  }
-  if (!set_nchannels (nchan)){
-    fprintf (stderr, "usrp_standard_tx: set_nchannels failed\n");
-    throw std::runtime_error ("usrp_standard_tx::ctor");
-  }
-  if (!set_interp_rate (interp_rate)){
-    fprintf (stderr, "usrp_standard_tx: set_interp_rate failed\n");
-    throw std::runtime_error ("usrp_standard_tx::ctor");
-  }
-  if (!set_mux (real_tx_mux_value (mux, nchan))){
-    fprintf (stderr, "usrp_standard_tx: set_mux failed\n");
-    throw std::runtime_error ("usrp_standard_tx::ctor");
-  }
-
-  for (int i = 0; i < MAX_CHAN; i++){
-    d_tx_modulator_shadow[i] = (TX_MODULATOR_DISABLE_NCO
-                               | TX_MODULATOR_COARSE_MODULATION_NONE);
-    d_coarse_mod[i] = CM_OFF;
-    set_tx_freq (i, 0);
-  }
-}
-
-usrp_standard_tx::~usrp_standard_tx ()
-{
-  // fprintf(stderr, "\nusrp_standard_tx: dtor\n");
-}
-
-bool
-usrp_standard_tx::start ()
-{
-  if (!usrp_basic_tx::start ())
-    return false;
-
-  // add our code here
-
-  return true;
-}
-
-bool
-usrp_standard_tx::stop ()
-{
-  bool ok = usrp_basic_tx::stop ();
-
-  // add our code here
-
-  return ok;
-}
-
-usrp_standard_tx *
-usrp_standard_tx::make (int which_board,
-                       unsigned int interp_rate,
-                       int nchan, int mux,
-                       int fusb_block_size, int fusb_nblocks,
-                       const std::string fpga_filename,
-                       const std::string firmware_filename
-                       )
-{
-  usrp_standard_tx *u = 0;
-  
-  try {
-    u = new usrp_standard_tx (which_board, interp_rate, nchan, mux,
-                             fusb_block_size, fusb_nblocks,
-                             fpga_filename, firmware_filename);
-    return u;
-  }
-  catch (...){
-    delete u;
-    return 0;
-  }
-
-  return u;
-}
-
-bool
-usrp_standard_tx::set_interp_rate (unsigned int rate)
-{
-  // fprintf (stderr, "usrp_standard_tx::set_interp_rate\n");
-
-  if ((rate & 0x3) || rate < 4 || rate > 512){
-    fprintf (stderr, "usrp_standard_tx::set_interp_rate: rate must be in [4, 512] and a multiple of 4.\n");
-    return false;
-  }
-
-  d_interp_rate = rate;
-  set_usb_data_rate ((dac_rate () / rate * nchannels ())
-                    * (2 * sizeof (short)));
-
-  // We're using the interp by 4 feature of the 9862 so that we can
-  // use its fine modulator.  Thus, we reduce the FPGA's interpolation rate
-  // by a factor of 4.
-
-  bool s = disable_tx ();
-  bool ok = _write_fpga_reg (FR_INTERP_RATE, d_interp_rate/4 - 1);
-  restore_tx (s);
-  return ok;
-}
-
-bool
-usrp_standard_tx::set_nchannels (int nchan)
-{
-  if (!(nchan == 1 || nchan == 2))
-    return false;
-
-  if (nchan > nducs())
-    return false;
-
-  d_nchan = nchan;
-  return write_hw_mux_reg ();
-}
-
-bool
-usrp_standard_tx::set_mux (int mux)
-{
-  d_sw_mux = mux;
-  d_hw_mux = mux << 4;
-  return write_hw_mux_reg ();
-}
-
-bool
-usrp_standard_tx::write_hw_mux_reg ()
-{
-  bool s = disable_tx ();
-  bool ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan);
-  restore_tx (s);
-  return ok;
-}
-
-#ifdef USE_FPGA_TX_CORDIC
-
-bool
-usrp_standard_tx::set_tx_freq (int channel, double freq)
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return false;
-
-  // This assumes we're running the 4x on-chip interpolator.
-
-  unsigned int v =
-    compute_freq_control_word_fpga (dac_freq () / 4,
-                                   freq, &d_tx_freq[channel],
-                                   d_verbose);
-
-  return _write_fpga_reg (FR_TX_FREQ_0 + channel, v);
-}
-
-
-#else
-
-bool
-usrp_standard_tx::set_tx_freq (int channel, double freq)
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return false;
-
-  // split freq into fine and coarse components
-
-  coarse_mod_t cm;
-  double       coarse;
-
-  assert (dac_freq () == 128000000);
-
-  if (freq < -44e6)            // too low
-    return false;
-  else if (freq < -24e6){      // [-44, -24)
-    cm = CM_NEG_FDAC_OVER_4;
-    coarse = -dac_freq () / 4;
-  }
-  else if (freq < -8e6){       // [-24, -8)
-    cm = CM_NEG_FDAC_OVER_8;
-    coarse = -dac_freq () / 8;
-  }
-  else if (freq < 8e6){                // [-8, 8)
-    cm = CM_OFF;
-    coarse = 0;
-  }
-  else if (freq < 24e6){       // [8, 24)
-    cm = CM_POS_FDAC_OVER_8;
-    coarse = dac_freq () / 8;
-  }
-  else if (freq <= 44e6){      // [24, 44]
-    cm = CM_POS_FDAC_OVER_4;
-    coarse = dac_freq () / 4;
-  }
-  else                         // too high
-    return false;
-
-
-  set_coarse_modulator (channel, cm);  // set bits in d_tx_modulator_shadow
-
-  double fine = freq - coarse;
-
-
-  // Compute fine tuning word...
-  // This assumes we're running the 4x on-chip interpolator.
-  // (This is required to use the fine modulator.)
-
-  unsigned int v =
-    compute_freq_control_word_9862 (dac_freq () / 4,
-                                   fine, &d_tx_freq[channel], d_verbose);
-
-  d_tx_freq[channel] += coarse;                // adjust actual
-  
-  unsigned char high, mid, low;
-
-  high = (v >> 16) & 0xff;
-  mid =  (v >>  8) & 0xff;
-  low =  (v >>  0) & 0xff;
-
-  bool ok = true;
-
-  // write the fine tuning word
-  ok &= _write_9862 (channel, REG_TX_NCO_FTW_23_16, high);
-  ok &= _write_9862 (channel, REG_TX_NCO_FTW_15_8,  mid);
-  ok &= _write_9862 (channel, REG_TX_NCO_FTW_7_0,   low);
-
-
-  d_tx_modulator_shadow[channel] |= TX_MODULATOR_ENABLE_NCO;
-
-  if (fine < 0)
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_FINE_TUNE;
-  else
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_NEG_FINE_TUNE;
-
-  ok &=_write_9862 (channel, REG_TX_MODULATOR, d_tx_modulator_shadow[channel]);
-
-  return ok;
-}
-#endif
-
-bool
-usrp_standard_tx::set_coarse_modulator (int channel, coarse_mod_t cm)
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return false;
-
-  switch (cm){
-  case CM_NEG_FDAC_OVER_4:
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
-    break;
-
-  case CM_NEG_FDAC_OVER_8:
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
-    break;
-
-  case CM_OFF:
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
-    break;
-
-  case CM_POS_FDAC_OVER_8:
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
-    break;
-
-  case CM_POS_FDAC_OVER_4:
-    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
-    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
-    break;
-
-  default:
-    return false;
-  }
-
-  d_coarse_mod[channel] = cm;
-  return true;
-}
-
-unsigned int
-usrp_standard_tx::interp_rate () const { return d_interp_rate; }
-
-int
-usrp_standard_tx::nchannels () const { return d_nchan; }
-
-int
-usrp_standard_tx::mux () const { return d_sw_mux; }
-
-double
-usrp_standard_tx::tx_freq (int channel) const
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return 0;
-
-  return d_tx_freq[channel];
-}
-
-usrp_standard_tx::coarse_mod_t
-usrp_standard_tx::coarse_modulator (int channel) const
-{
-  if (channel < 0 || channel >= MAX_CHAN)
-    return CM_OFF;
-
-  return d_coarse_mod[channel];
-}
diff --git a/usrp/host/lib/usrp_standard.h b/usrp/host/lib/usrp_standard.h
deleted file mode 100644 (file)
index 6fee4b9..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 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., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_USRP_STANDARD_H
-#define INCLUDED_USRP_STANDARD_H
-
-#include <usrp_basic.h>
-
-class usrp_standard_common
-{
-  int                  d_fpga_caps;            // capability register val
-
-protected:
-  usrp_standard_common(usrp_basic *parent);
-
-public:
-  /*!
-   *\brief does the FPGA implement the final Rx half-band filter?
-   * If it doesn't, the maximum decimation factor with proper gain 
-   * is 1/2 of what it would otherwise be.
-   */
-  bool has_rx_halfband() const;
-
-  /*!
-   * \brief number of digital downconverters implemented in the FPGA
-   * This will be 0, 1, 2 or 4.
-   */
-  int nddcs() const;
-
-  /*!
-   *\brief does the FPGA implement the initial Tx half-band filter?
-   */
-  bool has_tx_halfband() const;
-
-  /*!
-   * \brief number of digital upconverters implemented in the FPGA
-   * This will be 0, 1, or 2.
-   */
-  int nducs() const;
-};
-
-/*!
- * \brief standard usrp RX class.  
- *
- * Assumes digital down converter in FPGA
- */
-class usrp_standard_rx : public usrp_basic_rx, usrp_standard_common
-{
- private:
-  static const int     MAX_CHAN = 4;
-  unsigned int         d_decim_rate;
-  int                  d_nchan;
-  int                  d_sw_mux;
-  int                  d_hw_mux;
-  double               d_rx_freq[MAX_CHAN];
-
- protected:
-  usrp_standard_rx (int which_board,
-                   unsigned int decim_rate,
-                   int nchan = 1,
-                   int mux = -1,
-                   int mode = 0,
-                   int fusb_block_size = 0,
-                   int fusb_nblocks = 0,
-                   const std::string fpga_filename = "",
-                   const std::string firmware_filename = ""
-                   );  // throws if trouble
-
-  bool write_hw_mux_reg ();
-
- public:
-
-  enum {
-    FPGA_MODE_NORMAL     = 0x00,
-    FPGA_MODE_LOOPBACK   = 0x01,
-    FPGA_MODE_COUNTING   = 0x02,
-    FPGA_MODE_COUNTING_32BIT   = 0x04
-  };
-
-  ~usrp_standard_rx ();
-
-  /*!
-   * \brief invokes constructor, returns instance or 0 if trouble
-   *
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
-   */
-  static usrp_standard_rx *make (int which_board,
-                                unsigned int decim_rate,
-                                int nchan = 1,
-                                int mux = -1,
-                                int mode = 0,
-                                int fusb_block_size = 0,
-                                int fusb_nblocks = 0,
-                                const std::string fpga_filename = "",
-                                const std::string firmware_filename = ""
-                                );
-  /*!
-   * \brief Set decimator rate.  \p rate MUST BE EVEN and in [8, 256].
-   *
-   * The final complex sample rate across the USB is
-   *   adc_freq () / decim_rate () * nchannels ()
-   */
-  bool set_decim_rate  (unsigned int rate);
-
-  /*!
-   * \brief Set number of active channels.  \p nchannels must be 1, 2 or 4.
-   *
-   * The final complex sample rate across the USB is
-   *   adc_freq () / decim_rate () * nchannels ()
-   */
-  bool set_nchannels (int nchannels);
-
-  /*!
-   * \brief Set input mux configuration.
-   *
-   * This determines which ADC (or constant zero) is connected to 
-   * each DDC input.  There are 4 DDCs.  Each has two inputs.
-   *
-   * <pre>
-   * Mux value:
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   * |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   *
-   * Each 4-bit I field is either 0,1,2,3
-   * Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
-   * All Q's must be 0xf or none of them may be 0xf
-   * </pre>
-   */
-  bool set_mux  (int mux);
-
-  /*!
-   * \brief set the frequency of the digital down converter.
-   *
-   * \p channel must be in the range [0,3].  \p freq is the center
-   * frequency in Hz.  \p freq may be either negative or postive.
-   * The frequency specified is quantized.  Use rx_freq to retrieve
-   * the actual value used.
-   */
-  bool set_rx_freq (int channel, double freq);  
-
-  /*!
-   * \brief set fpga mode
-   */
-  bool set_fpga_mode (int mode);
-
-  /*!
-   * \brief Set the digital down converter phase register.
-   *
-   * \param channel    which ddc channel [0, 3]
-   * \param phase      32-bit integer phase value.
-   */
-  bool set_ddc_phase(int channel, int phase);
-
-  /*!
-   * \brief Specify Rx data format.
-   *
-   * \param format     format specifier
-   *
-   * Rx data format control register
-   *
-   *     3                   2                   1                       
-   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   *  +-----------------------------------------+-+-+---------+-------+
-   *  |          Reserved (Must be zero)        |B|Q|  WIDTH  | SHIFT |
-   *  +-----------------------------------------+-+-+---------+-------+
-   *
-   *  SHIFT specifies arithmetic right shift [0, 15]
-   *  WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid)
-   *  Q     if set deliver both I & Q, else just I
-   *  B     if set bypass half-band filter.
-   *
-   * Right now the acceptable values are:
-   *
-   *   B  Q  WIDTH  SHIFT
-   *   0  1    16     0
-   *   0  1     8     8
-   *
-   * More valid combos to come.
-   *
-   * Default value is 0x00000300  16-bits, 0 shift, deliver both I & Q.
-   */
-  bool set_format(unsigned int format);
-
-  static unsigned int make_format(int width=16, int shift=0,
-                                 bool want_q=true, bool bypass_halfband=false);
-  static int format_width(unsigned int format);
-  static int format_shift(unsigned int format);
-  static bool format_want_q(unsigned int format);
-  static bool format_bypass_halfband(unsigned int format);
-
-  // ACCESSORS
-  unsigned int decim_rate () const;
-  double rx_freq (int channel) const;
-  int nchannels () const;
-  int mux () const;
-  unsigned int format () const;
-
-  // called in base class to derived class order
-  bool start ();
-  bool stop ();
-};
-
-// ----------------------------------------------------------------
-
-/*!
- * \brief standard usrp TX class.
- *
- * Uses digital upconverter (coarse & fine modulators) in AD9862...
- */
-class usrp_standard_tx : public usrp_basic_tx, usrp_standard_common
-{
- public:
-  enum coarse_mod_t {
-    CM_NEG_FDAC_OVER_4,                // -32 MHz
-    CM_NEG_FDAC_OVER_8,                // -16 MHz
-    CM_OFF,
-    CM_POS_FDAC_OVER_8,                // +16 MHz
-    CM_POS_FDAC_OVER_4         // +32 MHz
-  };
-
- protected:
-  static const int     MAX_CHAN = 2;
-  unsigned int         d_interp_rate;
-  int                  d_nchan;
-  int                  d_sw_mux;
-  int                  d_hw_mux;
-  double               d_tx_freq[MAX_CHAN];
-  coarse_mod_t         d_coarse_mod[MAX_CHAN];
-  unsigned char                d_tx_modulator_shadow[MAX_CHAN];
-
-  virtual bool set_coarse_modulator (int channel, coarse_mod_t cm);
-  usrp_standard_tx::coarse_mod_t coarse_modulator (int channel) const;
-
- protected:
-  usrp_standard_tx (int which_board,
-                   unsigned int interp_rate,
-                   int nchan = 1,
-                   int mux = -1,
-                   int fusb_block_size = 0,
-                   int fusb_nblocks = 0,
-                   const std::string fpga_filename = "",
-                   const std::string firmware_filename = ""
-                   );  // throws if trouble
-
-  bool write_hw_mux_reg ();
-
- public:
-  ~usrp_standard_tx ();
-
-  /*!
-   * \brief invokes constructor, returns instance or 0 if trouble
-   *
-   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
-   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
-   *                         Use zero for a reasonable default.
-   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
-   */
-  static usrp_standard_tx *make (int which_board,
-                                unsigned int interp_rate,
-                                int nchan = 1,
-                                int mux = -1,
-                                int fusb_block_size = 0,
-                                int fusb_nblocks = 0,
-                                const std::string fpga_filename = "",
-                                const std::string firmware_filename = ""
-                                );
-
-  /*!
-   * \brief Set interpolator rate.  \p rate must be in [4, 512] and a multiple of 4.
-   *
-   * The final complex sample rate across the USB is
-   *   dac_freq () / interp_rate () * nchannels ()
-   */
-  virtual bool set_interp_rate (unsigned int rate);
-
-  /*!
-   * \brief Set number of active channels.  \p nchannels must be 1 or 2.
-   *
-   * The final complex sample rate across the USB is
-   *   dac_freq () / decim_rate () * nchannels ()
-   */
-  bool set_nchannels  (int nchannels);
-
-  /*!
-   * \brief Set output mux configuration.
-   *
-   * <pre>
-   *     3                   2                   1                       
-   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   *  +-------------------------------+-------+-------+-------+-------+
-   *  |                               | DAC3  | DAC2  | DAC1  |  DAC0 |
-   *  +-------------------------------+-------+-------+-------+-------+
-   * 
-   *  There are two interpolators with complex inputs and outputs.
-   *  There are four DACs.
-   * 
-   *  Each 4-bit DACx field specifies the source for the DAC and
-   *  whether or not that DAC is enabled.  Each subfield is coded
-   *  like this: 
-   * 
-   *     3 2 1 0
-   *    +-+-----+
-   *    |E|  N  |
-   *    +-+-----+
-   * 
-   *  Where E is set if the DAC is enabled, and N specifies which
-   *  interpolator output is connected to this DAC.
-   * 
-   *   N   which interp output
-   *  ---  -------------------
-   *   0   chan 0 I
-   *   1   chan 0 Q
-   *   2   chan 1 I
-   *   3   chan 1 Q
-   * </pre>
-   */
-  bool set_mux  (int mux);
-
-  /*!
-   * \brief set the frequency of the digital up converter.
-   *
-   * \p channel must be in the range [0,1].  \p freq is the center
-   * frequency in Hz.  It must be in the range [-44M, 44M].
-   * The frequency specified is quantized.  Use tx_freq to retrieve
-   * the actual value used.
-   */
-  virtual bool set_tx_freq (int channel, double freq);  // chan: [0,1]
-
-  // ACCESSORS
-  unsigned int interp_rate () const;
-  double tx_freq (int channel) const;
-  int nchannels () const;
-  int mux () const;
-
-  // called in base class to derived class order
-  bool start ();
-  bool stop ();
-};
-
-#endif /* INCLUDED_USRP_STANDARD_H */
index 8868d1ecb99153fd3385c99574cbe96fe221f897..35a81ea2972e93dfd0ab7d4ca61dd28661daf12f 100644 (file)
@@ -64,7 +64,7 @@ _usrp_prims_la_SOURCES =              \
 
 noinst_HEADERS =
 
-_usrp_prims_la_LIBADD  = $(top_builddir)/usrp/host/lib/libusrp.la -lstdc++ $(PYTHON_LDFLAGS)
+_usrp_prims_la_LIBADD  = $(USRP_LA) -lstdc++ $(PYTHON_LDFLAGS)
 _usrp_prims_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version