diff options
author | Manoj Gudi | 2013-10-07 20:19:55 +0530 |
---|---|---|
committer | Manoj Gudi | 2013-10-07 20:20:35 +0530 |
commit | 1826d0763c8595997f5f4af1fdb0354e9c0998ad (patch) | |
tree | acbd852cd5a1bf17241b1038b5e37a0e72e64612 /gnuradio-core/src/lib/io | |
parent | 452defdb4a78e9e826740ddf4b9673e926c568a4 (diff) | |
parent | 24b640997ba7fee0c725e65f401f5cbebdab8d08 (diff) | |
download | gnuradio-1826d0763c8595997f5f4af1fdb0354e9c0998ad.tar.gz gnuradio-1826d0763c8595997f5f4af1fdb0354e9c0998ad.tar.bz2 gnuradio-1826d0763c8595997f5f4af1fdb0354e9c0998ad.zip |
README change
Diffstat (limited to 'gnuradio-core/src/lib/io')
107 files changed, 10130 insertions, 0 deletions
diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt new file mode 100644 index 000000000..59ca06b5a --- /dev/null +++ b/gnuradio-core/src/lib/io/CMakeLists.txt @@ -0,0 +1,118 @@ +# Copyright 2010-2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink_f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_guts.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_x.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bitbang.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio_pp.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4702.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4937.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.cc + ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.cc +) + +######################################################################## +# Install runtime headers +######################################################################## +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink_f.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_guts.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_f.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_x.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_trigger_mode.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bitbang.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio_pp.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4702.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4937.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_eval_board_defs.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.h + ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Install swig headers +######################################################################## +if(ENABLE_PYTHON) +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/io.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) +endif(ENABLE_PYTHON) + +######################################################################## +# Handle triple-threat files that have cc, h, and i +######################################################################## +set(gr_core_io_triple_threats + gr_file_sink + gr_file_sink_base + gr_file_source + gr_file_descriptor_sink + gr_file_descriptor_source + gr_message_debug + gr_message_sink + gr_message_source + gr_message_burst_source + gr_pdu_to_tagged_stream + microtune_xxxx_eval_board + microtune_4702_eval_board + microtune_4937_eval_board + ppio + sdr_1000 + gr_udp_sink + gr_udp_source + gr_wavfile_source + gr_wavfile_sink + gr_tagged_file_sink + gr_tagged_stream_to_pdu + gr_tuntap_pdu + gr_socket_pdu +) + +foreach(file_tt ${gr_core_io_triple_threats}) + list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.cc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel") + if(ENABLE_PYTHON) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "core_swig") + endif(ENABLE_PYTHON) +endforeach(file_tt ${gr_core_io_triple_threats}) diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc new file mode 100644 index 000000000..099d46dbd --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_descriptor_sink.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +gr_file_descriptor_sink::gr_file_descriptor_sink (size_t itemsize, int fd) + : gr_sync_block ("file_descriptor_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_fd (fd) +{ +} + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd) +{ + return gnuradio::get_initial_sptr(new gr_file_descriptor_sink (itemsize, fd)); +} + +gr_file_descriptor_sink::~gr_file_descriptor_sink () +{ + close (d_fd); +} + +int +gr_file_descriptor_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + unsigned long byte_size = noutput_items * d_itemsize; + + while (byte_size > 0){ + ssize_t r; + + r = write (d_fd, inbuf, byte_size); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("gr_file_descriptor_sink"); + return -1; // indicate we're done + } + } + else { + byte_size -= r; + inbuf += r; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h new file mode 100644 index 000000000..3b1c1167f --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SINK_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_file_descriptor_sink; +typedef boost::shared_ptr<gr_file_descriptor_sink> gr_file_descriptor_sink_sptr; + +GR_CORE_API gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_file_descriptor_sink : public gr_sync_block +{ + friend GR_CORE_API gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + + private: + size_t d_itemsize; + int d_fd; + + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i new file mode 100644 index 000000000..2c256e44d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_descriptor_sink) + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd); + +class gr_file_descriptor_sink : public gr_sync_block +{ + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc new file mode 100644 index 000000000..a63abf96b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_descriptor_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +gr_file_descriptor_source::gr_file_descriptor_source (size_t itemsize, + int fd, + bool repeat) + : gr_sync_block ("file_descriptor_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize (itemsize), d_fd (fd), d_repeat (repeat), + d_residue (new unsigned char[itemsize]), d_residue_len (0) +{ +} + +// public constructor that returns a shared_ptr + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat) +{ + return gr_file_descriptor_source_sptr ( + new gr_file_descriptor_source (itemsize, fd, repeat)); +} + +gr_file_descriptor_source::~gr_file_descriptor_source () +{ + close (d_fd); + delete [] d_residue; +} + +int +gr_file_descriptor_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items > 0); + + char *o = (char *) output_items[0]; + int nread = 0; + + while (1){ + int r = read_items (o, noutput_items - nread); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("file_descriptor_source[read]"); + return -1; + } + } + else if (r == 0){ // end of file + if (!d_repeat) + break; + else { + flush_residue (); + if (lseek (d_fd, 0, SEEK_SET) == -1){ + perror ("file_descriptor_source[lseek]"); + return -1; + } + } + } + else { + o += r * d_itemsize; + nread += r; + break; + } + } + + if (nread == 0) // EOF + return -1; + + return nread; +} + +int +gr_file_descriptor_source::read_items (char *buf, int nitems) +{ + assert (nitems > 0); + assert (d_residue_len < d_itemsize); + + int nbytes_read = 0; + + if (d_residue_len > 0){ + memcpy (buf, d_residue, d_residue_len); + nbytes_read = d_residue_len; + d_residue_len = 0; + } + + int r = read (d_fd, buf + nbytes_read, nitems * d_itemsize - nbytes_read); + if (r <= 0){ + handle_residue (buf, nbytes_read); + return r; + } + + r = handle_residue (buf, r + nbytes_read); + + if (r == 0) // block until we get something + return read_items (buf, nitems); + + return r; +} + +int +gr_file_descriptor_source::handle_residue (char *buf, int nbytes_read) +{ + assert (nbytes_read >= 0); + int nitems_read = nbytes_read / d_itemsize; + d_residue_len = nbytes_read % d_itemsize; + if (d_residue_len > 0){ + // fprintf (stderr, "handle_residue: %d\n", d_residue_len); + memcpy (d_residue, buf + nbytes_read - d_residue_len, d_residue_len); + } + return nitems_read; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.h b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h new file mode 100644 index 000000000..ebabd81ed --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_file_descriptor_source; +typedef boost::shared_ptr<gr_file_descriptor_source> gr_file_descriptor_source_sptr; + +GR_CORE_API gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat = false); + +/*! + * \brief Read stream from file descriptor. + * \ingroup source_blk + */ + +class GR_CORE_API gr_file_descriptor_source : public gr_sync_block +{ + friend GR_CORE_API gr_file_descriptor_source_sptr + gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat); + private: + size_t d_itemsize; + int d_fd; + bool d_repeat; + + unsigned char *d_residue; + unsigned long d_residue_len; + + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + int read_items (char *buf, int nitems); + int handle_residue (char *buf, int nbytes_read); + void flush_residue () { d_residue_len = 0; } + + + public: + ~gr_file_descriptor_source (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.i b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i new file mode 100644 index 000000000..3ca082522 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_descriptor_source) + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat=false); + +class gr_file_descriptor_source : public gr_sync_block +{ + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + public: + ~gr_file_descriptor_source (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_sink.cc b/gnuradio-core/src/lib/io/gr_file_sink.cc new file mode 100644 index 000000000..10c8360cb --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> + + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename) +{ + return gnuradio::get_initial_sptr(new gr_file_sink (itemsize, filename)); +} + +gr_file_sink::gr_file_sink(size_t itemsize, const char *filename) + : gr_sync_block ("file_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + gr_file_sink_base(filename, true), + d_itemsize(itemsize) +{ +} + +gr_file_sink::~gr_file_sink () +{ +} + +int +gr_file_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char*)input_items[0]; + int nwritten = 0; + + do_update(); // update d_fp is reqd + + if(!d_fp) + return noutput_items; // drop output on the floor + + while(nwritten < noutput_items) { + int count = fwrite(inbuf, d_itemsize, noutput_items - nwritten, d_fp); + if(count == 0) { + if(ferror(d_fp)) { + std::stringstream s; + s << "file_sink write failed with error " << fileno(d_fp) << std::endl; + throw std::runtime_error(s.str()); + } + else { // is EOF + break; + } + } + nwritten += count; + inbuf += count * d_itemsize; + } + + if(d_unbuffered) + fflush (d_fp); + + return nwritten; +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink.h b/gnuradio-core/src/lib/io/gr_file_sink.h new file mode 100644 index 000000000..e40ec9ab8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 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_GR_FILE_SINK_H +#define INCLUDED_GR_FILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_file_sink_base.h> + +class gr_file_sink; +typedef boost::shared_ptr<gr_file_sink> gr_file_sink_sptr; + +GR_CORE_API gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + +/*! + * \brief Write stream to file. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_file_sink : public gr_sync_block, public gr_file_sink_base +{ + friend GR_CORE_API gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + + private: + size_t d_itemsize; + + protected: + gr_file_sink(size_t itemsize, const char *filename); + + public: + ~gr_file_sink(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink.i b/gnuradio-core/src/lib/io/gr_file_sink.i new file mode 100644 index 000000000..47ab9e964 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_sink) + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename); + +class gr_file_sink : public gr_sync_block, public gr_file_sink_base +{ + protected: + gr_file_sink (size_t itemsize, const char *filename); + + public: + ~gr_file_sink (); + + /*! + * \brief open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief close current output file. + */ + void close(); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.cc b/gnuradio-core/src/lib/io/gr_file_sink_base.cc new file mode 100644 index 000000000..d0aca418e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_sink_base.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> +#include <gruel/thread.h> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_sink_base::gr_file_sink_base(const char *filename, bool is_binary) + : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary) +{ + if (!open(filename)) + throw std::runtime_error ("can't open file"); +} + +gr_file_sink_base::~gr_file_sink_base () +{ + close(); + if (d_fp){ + fclose(d_fp); + d_fp = 0; + } +} + +bool +gr_file_sink_base::open(const char *filename) +{ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename); + return false; + } + if (d_new_fp){ // if we've already got a new one open, close it + fclose(d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){ + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + d_updated = true; + return d_new_fp != 0; +} + +void +gr_file_sink_base::close() +{ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + + if (d_new_fp){ + fclose(d_new_fp); + d_new_fp = 0; + } + d_updated = true; +} + +void +gr_file_sink_base::do_update() +{ + if (d_updated){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this block + if (d_fp) + fclose(d_fp); + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } +} + +void +gr_file_sink_base::set_unbuffered(bool unbuffered) +{ + d_unbuffered = unbuffered; +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.h b/gnuradio-core/src/lib/io/gr_file_sink_base.h new file mode 100644 index 000000000..8a70cee76 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FILE_SINK_BASE_H +#define INCLUDED_GR_FILE_SINK_BASE_H + +#include <gr_core_api.h> +#include <boost/thread.hpp> +#include <cstdio> + +/*! + * \brief Common base class for file sinks + */ +class GR_CORE_API gr_file_sink_base +{ + protected: + FILE *d_fp; // current FILE pointer + FILE *d_new_fp; // new FILE pointer + bool d_updated; // is there a new FILE pointer? + bool d_is_binary; + boost::mutex d_mutex; + bool d_unbuffered; + + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); + + + /*! + * \brief turn on unbuffered writes for slower outputs + */ + void set_unbuffered(bool unbuffered); +}; + + +#endif /* INCLUDED_GR_FILE_SINK_BASE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.i b/gnuradio-core/src/lib/io/gr_file_sink_base.i new file mode 100644 index 000000000..993dba277 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.i @@ -0,0 +1,51 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +class gr_file_sink_base +{ + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); + + /*! + *\brief turn on unbuffered mode for slow outputs + */ + void set_unbuffered(bool unbuffered); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc new file mode 100644 index 000000000..6da7abac2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gruel/thread.h> +#include <gr_file_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_source::gr_file_source(size_t itemsize, const char *filename, bool repeat) + : gr_sync_block("file_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), d_fp(0), d_new_fp (0), d_repeat(repeat), + d_updated(false) +{ + open(filename, repeat); +} + +// public constructor that returns a shared_ptr + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat) +{ + return gnuradio::get_initial_sptr(new gr_file_source (itemsize, filename, repeat)); +} + +gr_file_source::~gr_file_source () +{ + close(); + if(d_fp) { + fclose(d_fp); + d_fp = 0; + } +} + +int +gr_file_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *o = (char *) output_items[0]; + int i; + int size = noutput_items; + + do_update(); // update d_fp is reqd + if(d_fp == NULL) + throw std::runtime_error("work with file not open"); + + gruel::scoped_lock lock(fp_mutex); // hold for the rest of this function + while (size) { + i = fread(o, d_itemsize, size, (FILE *) d_fp); + + size -= i; + o += i * d_itemsize; + + if (size == 0) // done + break; + + if (i > 0) // short read, try again + continue; + + // We got a zero from fread. This is either EOF or error. In + // any event, if we're in repeat mode, seek back to the beginning + // of the file and try again, else break + + if (!d_repeat) + break; + + if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) { + std::stringstream s; + s << "[" << __FILE__ << "]" << " fseek failed" << std::endl; + throw std::runtime_error(s.str()); + } + } + + if (size > 0){ // EOF or error + if (size == noutput_items) // we didn't read anything; say we're done + return -1; + return noutput_items - size; // else return partial result + } + + return noutput_items; +} + +bool +gr_file_source::seek (long seek_point, int whence) +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; +} + +void +gr_file_source::open(const char *filename, bool repeat) +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + + int fd; + + // we use "open" to use to the O_LARGEFILE flag + if((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { + perror(filename); + throw std::runtime_error("can't open file"); + } + + if(d_new_fp) { + fclose(d_new_fp); + d_new_fp = 0; + } + + if((d_new_fp = fdopen (fd, "rb")) == NULL) { + perror(filename); + ::close(fd); // don't leak file descriptor if fdopen fails + throw std::runtime_error("can't open file"); + } + + d_updated = true; + d_repeat = repeat; +} + +void +gr_file_source::close() +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + + if(d_new_fp != NULL) { + fclose(d_new_fp); + d_new_fp = NULL; + } + d_updated = true; +} + +void +gr_file_source::do_update() +{ + if(d_updated) { + gruel::scoped_lock lock(fp_mutex); // hold while in scope + + if(d_fp) + fclose(d_fp); + + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } +} diff --git a/gnuradio-core/src/lib/io/gr_file_source.h b/gnuradio-core/src/lib/io/gr_file_source.h new file mode 100644 index 000000000..0478fba04 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FILE_SOURCE_H +#define INCLUDED_GR_FILE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <boost/thread/mutex.hpp> + +class gr_file_source; +typedef boost::shared_ptr<gr_file_source> gr_file_source_sptr; + +GR_CORE_API gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false); + +/*! + * \brief Read stream from file + * \ingroup source_blk + */ + +class GR_CORE_API gr_file_source : public gr_sync_block +{ + private: + size_t d_itemsize; + FILE *d_fp; + FILE *d_new_fp; + bool d_repeat; + bool d_updated; + + protected: + gr_file_source(size_t itemsize, const char *filename, bool repeat); + + void do_update(); + + boost::mutex fp_mutex; + + public: + /*! + * \brief Create a file source. + * + * Opens \p filename as a source of items into a flowgraph. The data + * is expected to be in binary format, item after item. The \p + * itemsize of the block determines the conversion from bits to + * items. + * + * If \p repeat is turned on, the file will repeat the file after + * it's reached the end. + * + * \param itemsize the size of each item in the file, in bytes + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + friend GR_CORE_API gr_file_source_sptr + gr_make_file_source(size_t itemsize, + const char *filename, + bool repeat); + + ~gr_file_source(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Seek file to \p seek_point relative to \p whence + * + * \param seek_point sample offset in file + * \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek) + */ + bool seek(long seek_point, int whence); + + /*! + * \brief Opens a new file. + * + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + void open(const char *filename, bool repeat); + + /*! + * \brief Close the file handle. + */ + void close(); + +}; + +#endif /* INCLUDED_GR_FILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_source.i b/gnuradio-core/src/lib/io/gr_file_source.i new file mode 100644 index 000000000..e71cef0d1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +%constant int SEEK_SET = 0; /* Seek from beginning of file. */ +%constant int SEEK_CUR = 1; /* Seek from current position. */ +%constant int SEEK_END = 2; /* Seek from end of file. */ + + +GR_SWIG_BLOCK_MAGIC(gr,file_source) + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat=false); + +class gr_file_source : public gr_sync_block +{ + protected: + gr_file_source (size_t itemsize, const char *filename, bool repeat); + + public: + ~gr_file_source (); + + bool seek (long seek_point, int whence); + void open (const char *filename, bool repeat); + void close(); +}; diff --git a/gnuradio-core/src/lib/io/gr_histo_sink.i b/gnuradio-core/src/lib/io/gr_histo_sink.i new file mode 100644 index 000000000..14079e190 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,histo_sink_f) + +gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + +class gr_histo_sink_f : public gr_sync_block +{ +public: + ~gr_histo_sink_f (void); + + unsigned int get_frame_size(void); + unsigned int get_num_bins(void); + + void set_frame_size(unsigned int frame_size); + void set_num_bins(unsigned int num_bins); + +}; diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.cc b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc new file mode 100644 index 000000000..fc0c12ce6 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc @@ -0,0 +1,165 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_histo_sink_f.h> +#include <gr_io_signature.h> +#include <boost/math/special_functions/round.hpp> + +static float get_clean_num(float num){ + if (num == 0) return 0; + /* extract sign and exponent from num */ + int sign = (num < 0) ? -1 : 1; num = fabs(num); + float exponent = floor(log10(num)); + /* search for closest number with base 1, 2, 5, 10 */ + float closest_num = 10*pow(10, exponent); + if (fabs(num - 1*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 1*pow(10, exponent); + if (fabs(num - 2*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 2*pow(10, exponent); + if (fabs(num - 5*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 5*pow(10, exponent); + return sign*closest_num; +} + +gr_histo_sink_f_sptr +gr_make_histo_sink_f (gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_histo_sink_f (msgq)); +} + +gr_histo_sink_f::gr_histo_sink_f (gr_msg_queue_sptr msgq) + : gr_sync_block ("histo_sink_f", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (0, 0, 0)), + d_msgq (msgq), d_num_bins(11), d_frame_size(1000), d_sample_count(0), d_bins(NULL), d_samps(NULL) +{ + //allocate arrays and clear + set_num_bins(d_num_bins); + set_frame_size(d_frame_size); +} + +gr_histo_sink_f::~gr_histo_sink_f (void) +{ + delete [] d_samps; + delete [] d_bins; +} + +int +gr_histo_sink_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + for (unsigned int i = 0; i < (unsigned int)noutput_items; i++){ + d_samps[d_sample_count] = in[i]; + d_sample_count++; + /* processed a frame? */ + if (d_sample_count == d_frame_size){ + send_frame(); + clear(); + } + } + return noutput_items; +} + +void +gr_histo_sink_f::send_frame(void){ + /* output queue full, drop the data */ + if (d_msgq->full_p()) return; + /* find the minimum and maximum */ + float minimum = d_samps[0]; + float maximum = d_samps[0]; + for (unsigned int i = 0; i < d_frame_size; i++){ + if (d_samps[i] < minimum) minimum = d_samps[i]; + if (d_samps[i] > maximum) maximum = d_samps[i]; + } + minimum = get_clean_num(minimum); + maximum = get_clean_num(maximum); + if (minimum == maximum || minimum > maximum) return; //useless data or screw up? + /* load the bins */ + int index; + float bin_width = (maximum - minimum)/(d_num_bins-1); + for (unsigned int i = 0; i < d_sample_count; i++){ + index = boost::math::iround((d_samps[i] - minimum)/bin_width); + /* ensure the index range in case a small floating point error is involed */ + if (index < 0) index = 0; + if (index >= (int)d_num_bins) index = d_num_bins-1; + d_bins[index]++; + } + /* Build a message to hold the output records */ + gr_message_sptr msg = gr_make_message(0, minimum, maximum, d_num_bins*sizeof(float)); + float *out = (float *)msg->msg(); // get pointer to raw message buffer + /* normalize the bins and put into message */ + for (unsigned int i = 0; i < d_num_bins; i++){ + out[i] = ((float)d_bins[i])/d_frame_size; + } + /* send the message */ + d_msgq->handle(msg); +} + +void +gr_histo_sink_f::clear(void){ + d_sample_count = 0; + /* zero the bins */ + for (unsigned int i = 0; i < d_num_bins; i++){ + d_bins[i] = 0; + } +} + +/************************************************** + * Getters + **************************************************/ +unsigned int +gr_histo_sink_f::get_frame_size(void){ + return d_frame_size; +} + +unsigned int +gr_histo_sink_f::get_num_bins(void){ + return d_num_bins; +} + +/************************************************** + * Setters + **************************************************/ +void +gr_histo_sink_f::set_frame_size(unsigned int frame_size){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + d_frame_size = frame_size; + /* allocate a new sample array */ + delete [] d_samps; + d_samps = new float[d_frame_size]; + clear(); +} + +void +gr_histo_sink_f::set_num_bins(unsigned int num_bins){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + d_num_bins = num_bins; + /* allocate a new bin array */ + delete [] d_bins; + d_bins = new unsigned int[d_num_bins]; + clear(); +} diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.h b/gnuradio-core/src/lib/io/gr_histo_sink_f.h new file mode 100644 index 000000000..934066ba2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_HISTO_SINK_F_H +#define INCLUDED_GR_HISTO_SINK_F_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_msg_queue.h> +#include <gruel/thread.h> + +class gr_histo_sink_f; +typedef boost::shared_ptr<gr_histo_sink_f> gr_histo_sink_f_sptr; + +GR_CORE_API gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + +/*! + * \brief Histogram module. + * \ingroup sink_blk + */ +class GR_CORE_API gr_histo_sink_f : public gr_sync_block +{ +private: + gr_msg_queue_sptr d_msgq; + unsigned int d_num_bins; + unsigned int d_frame_size; + unsigned int d_sample_count; + unsigned int *d_bins; + float *d_samps; + gruel::mutex d_mutex; + + friend GR_CORE_API gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + gr_histo_sink_f (gr_msg_queue_sptr msgq); + void send_frame(void); + void clear(void); + +public: + ~gr_histo_sink_f (void); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int get_frame_size(void); + unsigned int get_num_bins(void); + + void set_frame_size(unsigned int frame_size); + void set_num_bins(unsigned int num_bins); + +}; + +#endif /* INCLUDED_GR_HISTO_SINK_F_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.cc b/gnuradio-core/src/lib/io/gr_message_burst_source.cc new file mode 100644 index 000000000..e9e2dfd4d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_message_burst_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> +#include <gr_tags.h> + +// public constructor that returns a shared_ptr + +gr_message_burst_source_sptr +gr_make_message_burst_source(size_t itemsize, int msgq_limit) +{ + return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq_limit)); +} + +// public constructor that takes existing message queue +gr_message_burst_source_sptr +gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq)); +} + +gr_message_burst_source::gr_message_burst_source (size_t itemsize, int msgq_limit) + : gr_sync_block("message_burst_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false) +{ + std::stringstream id; + id << name() << unique_id(); + d_me = pmt::pmt_string_to_symbol(id.str()); +} + +gr_message_burst_source::gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq) + : gr_sync_block("message_burst_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false) +{ + std::stringstream id; + id << name() << unique_id(); + d_me = pmt::pmt_string_to_symbol(id.str()); +} + +gr_message_burst_source::~gr_message_burst_source() +{ +} + +int +gr_message_burst_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nn = 0; + + uint64_t abs_sample_count = nitems_written(0); + + while (nn < noutput_items){ + if (d_msg){ + // + // Consume whatever we can from the current message + // + + int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize)); + memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize); + + nn += mm; + out += mm * d_itemsize; + d_msg_offset += mm * d_itemsize; + assert(d_msg_offset <= d_msg->length()); + + if (d_msg_offset == d_msg->length()){ + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); + //tag end of burst + add_item_tag(0, //stream ID + abs_sample_count+nn-1, //sample number + pmt::pmt_string_to_symbol("tx_eob"), + pmt::pmt_from_bool(1), + d_me //block src id + ); + } + } + else { + // + // No current message + // + if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got + break; + } + + if (d_eof) + return -1; + + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + //tag start of burst + add_item_tag(0, //stream ID + abs_sample_count+nn, //sample number + pmt::pmt_string_to_symbol("tx_sob"), + pmt::pmt_from_bool(1), + d_me //block src id + ); + + + if ((d_msg->length() % d_itemsize) != 0) + throw std::runtime_error("msg length is not a multiple of d_itemsize"); + } + } + + return nn; +} diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.h b/gnuradio-core/src/lib/io/gr_message_burst_source.h new file mode 100644 index 000000000..63e220113 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_BURST_SOURCE_H +#define INCLUDED_GR_MESSAGE_BURST_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_burst_source; +typedef boost::shared_ptr<gr_message_burst_source> gr_message_burst_source_sptr; + +GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0); +GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + +/*! + * \brief Turn received messages into a stream and tag them for UHD to send. + * \ingroup source_blk + */ +class GR_CORE_API gr_message_burst_source : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + + pmt::pmt_t d_me; + + friend GR_CORE_API gr_message_burst_source_sptr + gr_make_message_burst_source(size_t itemsize, int msgq_limit); + friend GR_CORE_API gr_message_burst_source_sptr + gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq); + + protected: + gr_message_burst_source (size_t itemsize, int msgq_limit); + gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_burst_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_gr_message_burst_source_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.i b/gnuradio-core/src/lib/io/gr_message_burst_source.i new file mode 100644 index 000000000..f7ad840c2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.i @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_burst_source); + +gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0); +gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + +class gr_message_burst_source : public gr_sync_block +{ + protected: + gr_message_burst_source (size_t itemsize, int msgq_limit); + gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_burst_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc new file mode 100644 index 000000000..9eb1bb639 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_message_debug.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> +#include <iostream> + +// public constructor that returns a shared_ptr + +gr_message_debug_sptr +gr_make_message_debug () +{ + return gnuradio::get_initial_sptr(new gr_message_debug()); +} + +void +gr_message_debug::print(pmt::pmt_t msg) +{ + std::cout << "******* MESSAGE DEBUG PRINT ********\n"; + pmt::pmt_print(msg); + std::cout << "************************************\n"; +} + +void +gr_message_debug::store(pmt::pmt_t msg) +{ + gruel::scoped_lock guard(d_mutex); + d_messages.push_back(msg); +} + +void +gr_message_debug::print_pdu(pmt::pmt_t pdu) +{ + pmt::pmt_t meta = pmt::pmt_car(pdu); + pmt::pmt_t vector = pmt::pmt_cdr(pdu); + std::cout << "* MESSAGE DEBUG PRINT PDU VERBOSE *\n"; + pmt::pmt_print(meta); + size_t len = pmt::pmt_length(vector); + std::cout << "pdu_length = " << len << std::endl; + std::cout << "contents = " << std::endl; + size_t offset(0); + const uint8_t* d = (const uint8_t*) pmt_uniform_vector_elements(vector, offset); + for(size_t i=0; i<len; i+=16){ + printf("%04x: ", ((unsigned int)i)); + for(size_t j=i; j<std::min(i+16,len); j++){ + printf("%02x ",d[j] ); + } + + std::cout << std::endl; + } + + std::cout << "***********************************\n"; +} + +int +gr_message_debug::num_messages() +{ + return (int)d_messages.size(); +} + +pmt::pmt_t +gr_message_debug::get_message(int i) +{ + gruel::scoped_lock guard(d_mutex); + + if((size_t)i >= d_messages.size()) { + throw std::runtime_error("gr_message_debug: index for message out of bounds.\n"); + } + + return d_messages[i]; +} + +gr_message_debug::gr_message_debug() + : gr_block("message_debug", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)) +{ + message_port_register_in(pmt::mp("print")); + set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1)); + + message_port_register_in(pmt::mp("store")); + set_msg_handler(pmt::mp("store"), boost::bind(&gr_message_debug::store, this, _1)); + + message_port_register_in(pmt::mp("print_pdu")); + set_msg_handler(pmt::mp("print_pdu"), boost::bind(&gr_message_debug::print_pdu, this, _1)); +} + +gr_message_debug::~gr_message_debug() +{ +} diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h new file mode 100644 index 000000000..f1374e806 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.h @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_DEBUG_H +#define INCLUDED_GR_MESSAGE_DEBUG_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gruel/thread.h> + +class gr_message_debug; +typedef boost::shared_ptr<gr_message_debug> gr_message_debug_sptr; + +GR_CORE_API gr_message_debug_sptr gr_make_message_debug(); + +/*! + * \brief Print received messages to stdout + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_debug : public gr_block +{ + private: + friend GR_CORE_API gr_message_debug_sptr + gr_make_message_debug(); + + /*! + * \brief Messages received in this port are printed to stdout. + * + * This port receives messages from the scheduler's message handling + * mechanism and prints it to stdout. This message handler function + * is only meant to be used by the scheduler to handle messages + * posted to port 'print'. + * + * \param msg A pmt message passed from the scheduler's message handling. + */ + void print(pmt::pmt_t msg); + + /*! + * \brief PDU formatted messages received in this port are printed to stdout. + * + * This port receives messages from the scheduler's message handling + * mechanism and prints it to stdout. This message handler function + * is only meant to be used by the scheduler to handle messages + * posted to port 'print'. + * + * \param pdu A PDU message passed from the scheduler's message handling. + */ + void print_pdu(pmt::pmt_t pdu); + + /*! + * \brief Messages received in this port are stored in a vector. + * + * This port receives messages from the scheduler's message handling + * mechanism and stores it in a vector. Messages can be retrieved + * later using the 'get_message' function. This message handler + * function is only meant to be used by the scheduler to handle + * messages posted to port 'store'. + * + * \param msg A pmt message passed from the scheduler's message handling. + */ + void store(pmt::pmt_t msg); + + gruel::mutex d_mutex; + std::vector<pmt::pmt_t> d_messages; + + protected: + gr_message_debug (); + + public: + ~gr_message_debug (); + + /*! + * \brief Reports the number of messages received by this block. + */ + int num_messages(); + + /*! + * \brief Get a message (as a PMT) from the message vector at index \p i. + * + * Messages passed to the 'store' port will be stored in a + * vector. This function retrieves those messages by index. They are + * index in order of when they were received (all messages are just + * pushed onto the back of a vector). This is mostly useful in + * debugging message passing graphs and in QA code. + * + * \param i The index in the vector for the message to retrieve. + * + * \return a message at index \p i as a pmt_t. + */ + pmt::pmt_t get_message(int i); +}; + +#endif /* INCLUDED_GR_MESSAGE_DEBUG_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i new file mode 100644 index 000000000..65d3bfc4a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_debug); + +%{ +#include <gr_message_debug.h> +%} + +%include "gr_message_debug.h" + diff --git a/gnuradio-core/src/lib/io/gr_message_sink.cc b/gnuradio-core/src/lib/io/gr_message_sink.cc new file mode 100644 index 000000000..ae0b5c764 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.cc @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_message_sink.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> + + +// public constructor that returns a shared_ptr + +gr_message_sink_sptr +gr_make_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) +{ + return gnuradio::get_initial_sptr(new gr_message_sink(itemsize, msgq, dont_block)); +} + +gr_message_sink::gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) + : gr_sync_block("message_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block) +{ +} + +gr_message_sink::~gr_message_sink() +{ +} + +int +gr_message_sink::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + + // if we'd block, drop the data on the floor and say everything is OK + if (d_dont_block && d_msgq->full_p()) + return noutput_items; + + // build a message to hold whatever we've got + gr_message_sptr msg = gr_make_message(0, // msg type + d_itemsize, // arg1 for other end + noutput_items, // arg2 for other end (redundant) + noutput_items * d_itemsize); // len of msg + memcpy(msg->msg(), in, noutput_items * d_itemsize); + + d_msgq->handle(msg); // send it + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_message_sink.h b/gnuradio-core/src/lib/io/gr_message_sink.h new file mode 100644 index 000000000..84005694a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.h @@ -0,0 +1,63 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SINK_H +#define INCLUDED_GR_MESSAGE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_sink; +typedef boost::shared_ptr<gr_message_sink> gr_message_sink_sptr; + +GR_CORE_API gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_sink : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + bool d_dont_block; + + friend GR_CORE_API gr_message_sink_sptr + gr_make_message_sink(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_sink.i b/gnuradio-core/src/lib/io/gr_message_sink.i new file mode 100644 index 000000000..8415cbd66 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.i @@ -0,0 +1,36 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_sink); + +gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +class gr_message_sink : public gr_sync_block +{ + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_message_source.cc b/gnuradio-core/src/lib/io/gr_message_source.cc new file mode 100644 index 000000000..fb3da89a8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_message_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> + + +// public constructor that returns a shared_ptr + +gr_message_source_sptr +gr_make_message_source(size_t itemsize, int msgq_limit) +{ + return gnuradio::get_initial_sptr(new gr_message_source(itemsize, msgq_limit)); +} + +// public constructor that takes existing message queue +gr_message_source_sptr +gr_make_message_source(size_t itemsize, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_message_source(itemsize, msgq)); +} + +gr_message_source::gr_message_source (size_t itemsize, int msgq_limit) + : gr_sync_block("message_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false) +{ +} + +gr_message_source::gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq) + : gr_sync_block("message_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false) +{ +} + +gr_message_source::~gr_message_source() +{ +} + +int +gr_message_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nn = 0; + + while (nn < noutput_items){ + if (d_msg){ + // + // Consume whatever we can from the current message + // + int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize)); + memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize); + + nn += mm; + out += mm * d_itemsize; + d_msg_offset += mm * d_itemsize; + assert(d_msg_offset <= d_msg->length()); + + if (d_msg_offset == d_msg->length()){ + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); + } + } + else { + // + // No current message + // + if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got + break; + } + + if (d_eof) + return -1; + + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + + if ((d_msg->length() % d_itemsize) != 0) + throw std::runtime_error("msg length is not a multiple of d_itemsize"); + } + } + + return nn; +} diff --git a/gnuradio-core/src/lib/io/gr_message_source.h b/gnuradio-core/src/lib/io/gr_message_source.h new file mode 100644 index 000000000..c510d1775 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.h @@ -0,0 +1,69 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SOURCE_H +#define INCLUDED_GR_MESSAGE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_source; +typedef boost::shared_ptr<gr_message_source> gr_message_source_sptr; + +GR_CORE_API gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); +GR_CORE_API gr_message_source_sptr gr_make_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_message_source : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + + friend GR_CORE_API gr_message_source_sptr + gr_make_message_source(size_t itemsize, int msgq_limit); + friend GR_CORE_API gr_message_source_sptr + gr_make_message_source(size_t itemsize, gr_msg_queue_sptr msgq); + + protected: + gr_message_source (size_t itemsize, int msgq_limit); + gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_source.i b/gnuradio-core/src/lib/io/gr_message_source.i new file mode 100644 index 000000000..9ee9157e8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.i @@ -0,0 +1,38 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_source); + +gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); +gr_message_source_sptr gr_make_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + +class gr_message_source : public gr_sync_block +{ + protected: + gr_message_source (size_t itemsize, int msgq_limit); + gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.cc b/gnuradio-core/src/lib/io/gr_oscope_guts.cc new file mode 100644 index 000000000..a5ea3002a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc @@ -0,0 +1,437 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_oscope_guts.h> +#include <stdexcept> +#include <stdio.h> +#include <algorithm> +#include <unistd.h> +#include <math.h> +#include <assert.h> + +/* + * Bad performance if it's large, and flaky triggering if it's too small + */ +static const int OUTPUT_RECORD_SIZE = 1024; // Must be power of 2 + +/* + * For (slow-updated) STRIPCHART triggering, we make the record size larger, since we + * potentially want to be able to "see" hours of data. This works as long as the + * update rates to a STRIPCHART are low, which they generally are--that's rather what + * a stripchart is all about! + */ +static const int SCHART_MULT = 8; + + +static inline int +wrap_bi (int buffer_index, int mx) // wrap buffer index +{ + return buffer_index & (mx - 1); +} + +static inline int +incr_bi (int buffer_index, int mx) // increment buffer index +{ + return wrap_bi (buffer_index + 1, mx); +} + +static inline int +decr_bi (int buffer_index, int mx) // decrement buffer index +{ + return wrap_bi (buffer_index - 1, mx); +} + +gr_oscope_guts::gr_oscope_guts (double sample_rate, gr_msg_queue_sptr msgq) + : d_nchannels (1), + d_msgq (msgq), + d_trigger_mode (gr_TRIG_MODE_AUTO), + d_trigger_slope (gr_TRIG_SLOPE_POS), + d_trigger_channel (0), + d_sample_rate (sample_rate), + d_update_rate (20), + d_trigger_level (0), + d_obi (0), + d_state (HOLD_OFF), + d_decimator_count (0), + d_decimator_count_init (1), + d_hold_off_count (0), + d_hold_off_count_init (OUTPUT_RECORD_SIZE/2-1), + d_pre_trigger_count (0), + d_post_trigger_count (0), + d_post_trigger_count_init (OUTPUT_RECORD_SIZE/2) +{ + for (int i = 0; i < MAX_CHANNELS; i++) + d_buffer[i] = 0; + + for (int i = 0; i < MAX_CHANNELS; i++){ + d_buffer[i] = new float [OUTPUT_RECORD_SIZE*SCHART_MULT]; + for (int j = 0; j < OUTPUT_RECORD_SIZE*SCHART_MULT; j++) + d_buffer[i][j] = 0.0; + } + + // be sure buffer is full before first write + enter_hold_off (); + update_rate_or_decimation_changed (); +} + +gr_oscope_guts::~gr_oscope_guts () +{ + for (int i = 0; i < MAX_CHANNELS; i++) + delete [] d_buffer[i]; +} + +// MANIPULATORS + +// \p channel_data points to nchannels float values. These are the values +// for each channel at this sample time. + +void +gr_oscope_guts::process_sample (const float *channel_data) +{ + d_decimator_count--; + if (d_decimator_count > 0) + return; + + d_decimator_count = d_decimator_count_init; + + if (d_trigger_mode != gr_TRIG_MODE_STRIPCHART) + { + for (int i = 0; i < d_nchannels; i++) + d_buffer[i][d_obi] = channel_data[i]; // copy data into buffer + + switch (d_state){ + case HOLD_OFF: + d_hold_off_count--; + if (d_hold_off_count <= 0) + enter_look_for_trigger (); + break; + + case LOOK_FOR_TRIGGER: + if (found_trigger ()) + enter_post_trigger (); + break; + + case POST_TRIGGER: + d_post_trigger_count--; + if (d_post_trigger_count <= 0){ + write_output_records (); + enter_hold_off (); + } + break; + + default: + assert (0); + } + + d_obi = incr_bi (d_obi, OUTPUT_RECORD_SIZE); + } + else + { + for (int i = 0; i < d_nchannels; i++) + { + for (int j = (OUTPUT_RECORD_SIZE*SCHART_MULT)-1; j > 0; j--) + { + d_buffer[i][j] = d_buffer[i][j-1]; + } + d_buffer[i][0] = channel_data[i]; + } + d_trigger_off = 0; + write_output_records(); + } +} + +/* + * Functions called on state entry + */ + +void +gr_oscope_guts::enter_hold_off () +{ + d_state = HOLD_OFF; + d_hold_off_count = d_hold_off_count_init; +} + +void +gr_oscope_guts::enter_look_for_trigger () +{ + d_pre_trigger_count = 0; + d_state = LOOK_FOR_TRIGGER; +} + +void +gr_oscope_guts::enter_post_trigger () +{ + d_state = POST_TRIGGER; + d_post_trigger_count = d_post_trigger_count_init; + //ensure that the trigger offset is no more than than half a sample + if (d_trigger_off > .5) d_trigger_off -= 1; + else d_post_trigger_count--; +} + +// ---------------------------------------------------------------- +// returns true if trigger found + +bool +gr_oscope_guts::found_trigger () +{ + int mx = d_trigger_mode == gr_TRIG_MODE_STRIPCHART ? OUTPUT_RECORD_SIZE*SCHART_MULT : + OUTPUT_RECORD_SIZE; + + float prev_sample = d_buffer[d_trigger_channel][decr_bi(d_obi, mx)]; + float new_sample = d_buffer[d_trigger_channel][d_obi]; + + switch (d_trigger_mode){ + + case gr_TRIG_MODE_AUTO: //too many samples without a trigger + d_pre_trigger_count++; + if (d_pre_trigger_count > OUTPUT_RECORD_SIZE/2) return true; + + case gr_TRIG_MODE_NORM: //look for trigger + switch (d_trigger_slope){ + + case gr_TRIG_SLOPE_POS: //trigger point in pos slope? + if (new_sample < d_trigger_level || prev_sample >= d_trigger_level) return false; + break; + + case gr_TRIG_SLOPE_NEG: //trigger point in neg slope? + if (new_sample > d_trigger_level || prev_sample <= d_trigger_level) return false; + break; + } + + //calculate the trigger offset in % sample + d_trigger_off = (d_trigger_level - prev_sample)/(new_sample - prev_sample); + return true; + + case gr_TRIG_MODE_FREE: //free run mode, always trigger + d_trigger_off = 0; + return true; + + default: + assert (0); + return false; + } +} + +// ---------------------------------------------------------------- +// write output records (duh!) + +void +gr_oscope_guts::write_output_records () +{ + int mx; + + mx = d_trigger_mode == gr_TRIG_MODE_STRIPCHART ? + OUTPUT_RECORD_SIZE*SCHART_MULT : OUTPUT_RECORD_SIZE; + + // if the output queue if full, drop the data like its hot. + if (d_msgq->full_p()) + return; + // Build a message to hold the output records + gr_message_sptr msg = + gr_make_message(0, // msg type + d_nchannels, // arg1 for other side + mx, // arg2 for other side + ((d_nchannels * mx) + 1) * sizeof(float)); // sizeof payload + + float *out = (float *)msg->msg(); // get pointer to raw message buffer + + for (int ch = 0; ch < d_nchannels; ch++){ + // note that d_obi + 1 points at the oldest sample in the buffer + for (int i = 0; i < mx; i++){ + out[i] = d_buffer[ch][wrap_bi(d_obi + 1 + i, mx)]; + } + out += mx; + } + //Set the last sample as the trigger offset: + // The non gl scope sink will not look at this last sample. + // The gl scope sink will use this last sample as an offset. + out[0] = d_trigger_off; + d_msgq->handle(msg); // send the msg +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_guts::set_update_rate (double update_rate) +{ + d_update_rate = std::min (std::max (1./10., update_rate), d_sample_rate); + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_decimation_count (int decimator_count) +{ + decimator_count = std::max (1, decimator_count); + d_decimator_count_init = decimator_count; + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_sample_rate(double sample_rate) +{ + d_sample_rate = sample_rate; + return set_update_rate(update_rate()); +} + + +void +gr_oscope_guts::update_rate_or_decimation_changed () +{ + d_hold_off_count_init = + (int) rint (d_sample_rate / d_update_rate / d_decimator_count_init); +} + +bool +gr_oscope_guts::set_trigger_channel (int channel) +{ + if (channel >= 0 && channel < d_nchannels){ + d_trigger_channel = channel; + trigger_changed (); + return true; + } + + return false; +} + +bool +gr_oscope_guts::set_trigger_mode (gr_trigger_mode mode) +{ + d_trigger_mode = mode; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_slope (gr_trigger_slope slope) +{ + d_trigger_slope = slope; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_level (double trigger_level) +{ + d_trigger_level = trigger_level; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_level_auto () +{ + // find the level 1/2 way between the min and the max + + float min_v = d_buffer[d_trigger_channel][0]; + float max_v = d_buffer[d_trigger_channel][0]; + + for (int i = 1; i < OUTPUT_RECORD_SIZE; i++){ + min_v = std::min (min_v, d_buffer[d_trigger_channel][i]); + max_v = std::max (max_v, d_buffer[d_trigger_channel][i]); + } + return set_trigger_level((min_v + max_v) * 0.5); +} + +bool +gr_oscope_guts::set_num_channels(int nchannels) +{ + if (nchannels > 0 && nchannels <= MAX_CHANNELS){ + d_nchannels = nchannels; + return true; + } + return false; +} + + +void +gr_oscope_guts::trigger_changed () +{ + enter_look_for_trigger (); +} + +// ACCESSORS + +int +gr_oscope_guts::num_channels () const +{ + return d_nchannels; +} + +double +gr_oscope_guts::sample_rate () const +{ + return d_sample_rate; +} + +double +gr_oscope_guts::update_rate () const +{ + return d_update_rate; +} + +int +gr_oscope_guts::get_decimation_count () const +{ + return d_decimator_count_init; +} + +int +gr_oscope_guts::get_trigger_channel () const +{ + return d_trigger_channel; +} + +gr_trigger_mode +gr_oscope_guts::get_trigger_mode () const +{ + return d_trigger_mode; +} + +gr_trigger_slope +gr_oscope_guts::get_trigger_slope () const +{ + return d_trigger_slope; +} + +double +gr_oscope_guts::get_trigger_level () const +{ + return d_trigger_level; +} + +int +gr_oscope_guts::get_samples_per_output_record () const +{ + int mx; + + mx = OUTPUT_RECORD_SIZE; + if (d_trigger_mode == gr_TRIG_MODE_STRIPCHART) + { + mx = OUTPUT_RECORD_SIZE*SCHART_MULT; + } + return mx; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.h b/gnuradio-core/src/lib/io/gr_oscope_guts.h new file mode 100644 index 000000000..bc9513c7e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.h @@ -0,0 +1,123 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_OSCOPE_GUTS_H +#define INCLUDED_GR_OSCOPE_GUTS_H + +#include <gr_core_api.h> +#include <gr_trigger_mode.h> +#include <gr_msg_queue.h> + +/*! + * \brief guts of oscilloscope trigger and buffer module + * + * This module processes sets of samples provided the \p process_sample + * method. When appropriate given the updateRate, sampleRate and + * trigger conditions, process_sample will periodically write output + * records of captured data to output_fd. For each trigger event, + * nchannels records will be written. Each record consists of + * get_samples_per_output_record binary floats. The trigger instant + * occurs at the 1/2 way point in the buffer. Thus, output records + * consist of 50% pre-trigger data and 50% post-trigger data. + */ + +class GR_CORE_API gr_oscope_guts { +public: + static const int MAX_CHANNELS = 8; +private: + enum scope_state { HOLD_OFF, LOOK_FOR_TRIGGER, POST_TRIGGER }; + + int d_nchannels; // how many channels + gr_msg_queue_sptr d_msgq; // message queue we stuff output records into + gr_trigger_mode d_trigger_mode; + gr_trigger_slope d_trigger_slope; + int d_trigger_channel; // which channel to watch for trigger condition + double d_sample_rate; // input sample rate in Hz + double d_update_rate; // approx freq to produce an output record (Hz) + double d_trigger_level; + + int d_obi; // output buffer index + float *d_buffer[MAX_CHANNELS]; + + scope_state d_state; + int d_decimator_count; + int d_decimator_count_init; + int d_hold_off_count; + int d_hold_off_count_init; + int d_pre_trigger_count; + int d_post_trigger_count; + int d_post_trigger_count_init; + float d_trigger_off; //%sample trigger is off + + // NOT IMPLEMENTED + gr_oscope_guts (const gr_oscope_guts &rhs); // no copy constructor + gr_oscope_guts &operator= (const gr_oscope_guts &rhs); // no assignment operator + + void trigger_changed (); + void update_rate_or_decimation_changed (); + bool found_trigger (); // returns true if found + void write_output_records (); + + void enter_hold_off (); // called on state entry + void enter_look_for_trigger (); + void enter_post_trigger (); + +public: + // CREATORS + gr_oscope_guts (double sample_rate, gr_msg_queue_sptr msgq); + ~gr_oscope_guts (); + + // MANIPULATORS + + /*! + * \p channel_data points to nchannels float values. These are the values + * for each channel at this sample time. + */ + void process_sample (const float *channel_data); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + bool set_num_channels(int nchannels); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +#endif /* INCLUDED_GR_OSCOPE_GUTS_H */ diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink.i b/gnuradio-core/src/lib/io/gr_oscope_sink.i new file mode 100644 index 000000000..3d7072ed4 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink.i @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%include gr_trigger_mode.h + +// GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_x) + +%ignore gr_oscope_sink_x; +class gr_oscope_sink_x : public gr_sync_block +{ + protected: + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sample_rate); + + public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_f) + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +class gr_oscope_sink_f : public gr_oscope_sink_x +{ +private: + gr_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +public: + ~gr_oscope_sink_f (); +}; + +// ---------------------------------------------------------------- diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc new file mode 100644 index 000000000..493a25e81 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2005,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_oscope_sink_f.h> +#include <gr_io_signature.h> +#include <gr_oscope_guts.h> + + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_oscope_sink_f (sampling_rate, msgq)); +} + + +gr_oscope_sink_f::gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) + : gr_oscope_sink_x ("oscope_sink_f", + gr_make_io_signature (1, gr_oscope_guts::MAX_CHANNELS, sizeof (float)), + sampling_rate), + d_msgq(msgq) +{ + d_guts = new gr_oscope_guts (d_sampling_rate, d_msgq); +} + + +bool +gr_oscope_sink_f::check_topology (int ninputs, int noutputs) +{ + return d_guts->set_num_channels(ninputs); +} + + +gr_oscope_sink_f::~gr_oscope_sink_f () +{ +} + +int +gr_oscope_sink_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ni = input_items.size (); + float tmp[gr_oscope_guts::MAX_CHANNELS]; + + for (int i = 0; i < noutput_items; i++){ + + // FIXME for now, copy the data. Fix later if reqd + for (int ch = 0; ch < ni; ch++) + tmp[ch] = ((const float *) input_items[ch])[i]; + + d_guts->process_sample (tmp); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.h b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h new file mode 100644 index 000000000..8d434d2bc --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_F_H +#define INCLUDED_GR_OSCOPE_SINK_F_H + +#include <gr_core_api.h> +#include <gr_oscope_sink_x.h> +#include <gr_msg_queue.h> + +class gr_oscope_sink_f; +typedef boost::shared_ptr<gr_oscope_sink_x> gr_oscope_sink_f_sptr; + +GR_CORE_API gr_oscope_sink_f_sptr gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + +/*! + * \brief Building block for python oscilloscope module. + * \ingroup sink_blk + * + * Accepts multiple float streams. + */ +class GR_CORE_API gr_oscope_sink_f : public gr_oscope_sink_x +{ +private: + friend GR_CORE_API gr_oscope_sink_f_sptr + gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_msg_queue_sptr d_msgq; + + public: + ~gr_oscope_sink_f (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool check_topology (int ninputs, int noutputs); +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_F_H */ + diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc new file mode 100644 index 000000000..9580dbf6a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc @@ -0,0 +1,156 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_oscope_sink_x.h> +#include <gr_io_signature.h> +#include <gr_oscope_guts.h> + + +gr_oscope_sink_x::gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate) + : gr_sync_block (name, input_sig, gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), d_guts (0) +{ +} + +gr_oscope_sink_x::~gr_oscope_sink_x () +{ + delete d_guts; +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_sink_x::set_update_rate (double update_rate) +{ + return d_guts->set_update_rate (update_rate); +} + +bool +gr_oscope_sink_x::set_decimation_count (int decimation_count) +{ + return d_guts->set_decimation_count (decimation_count); +} + +bool +gr_oscope_sink_x::set_trigger_channel (int channel) +{ + return d_guts->set_trigger_channel (channel); +} + +bool +gr_oscope_sink_x::set_trigger_mode (gr_trigger_mode mode) +{ + return d_guts->set_trigger_mode (mode); +} + +bool +gr_oscope_sink_x::set_trigger_slope (gr_trigger_slope slope) +{ + return d_guts->set_trigger_slope (slope); +} + +bool +gr_oscope_sink_x::set_trigger_level (double trigger_level) +{ + return d_guts->set_trigger_level (trigger_level); +} + + +bool +gr_oscope_sink_x::set_trigger_level_auto () +{ + return d_guts->set_trigger_level_auto (); +} + +bool +gr_oscope_sink_x::set_sample_rate (double sample_rate) +{ + return d_guts->set_sample_rate (sample_rate); +} + +bool +gr_oscope_sink_x::set_num_channels (int nchannels) +{ + return d_guts->set_num_channels (nchannels); +} + +// ACCESSORS + +int +gr_oscope_sink_x::num_channels () const +{ + return d_guts->num_channels (); +} + +double +gr_oscope_sink_x::sample_rate () const +{ + return d_guts->sample_rate (); +} + +double +gr_oscope_sink_x::update_rate () const +{ + return d_guts->update_rate (); +} + +int +gr_oscope_sink_x::get_decimation_count () const +{ + return d_guts->get_decimation_count (); +} + +int +gr_oscope_sink_x::get_trigger_channel () const +{ + return d_guts->get_trigger_channel (); +} + +gr_trigger_mode +gr_oscope_sink_x::get_trigger_mode () const +{ + return d_guts->get_trigger_mode (); +} + +gr_trigger_slope +gr_oscope_sink_x::get_trigger_slope () const +{ + return d_guts->get_trigger_slope (); +} + +double +gr_oscope_sink_x::get_trigger_level () const +{ + return d_guts->get_trigger_level (); +} + +int +gr_oscope_sink_x::get_samples_per_output_record () const +{ + return d_guts->get_samples_per_output_record (); +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.h b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h new file mode 100644 index 000000000..153d0937a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h @@ -0,0 +1,77 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_X_H +#define INCLUDED_GR_OSCOPE_SINK_X_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_trigger_mode.h> + +class gr_oscope_guts; + +/*! + * \brief Abstract class for python oscilloscope module. + * \ingroup sink_blk + * + * Don't instantiate this. Use gr_oscope_sink_f or gr_oscope_sink_c instead. + */ +class GR_CORE_API gr_oscope_sink_x : public gr_sync_block +{ +protected: + double d_sampling_rate; + gr_oscope_guts *d_guts; + + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate); + +public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + bool set_num_channels (int nchannels); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; + +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_X_H */ diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc new file mode 100644 index 000000000..302fd7b9b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.cc @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pdu.h> + +size_t +gr_pdu_itemsize(gr_pdu_vector_type type){ + switch(type){ + case pdu_byte: + return 1; + case pdu_float: + return sizeof(float); + case pdu_complex: + return sizeof(gr_complex); + default: + throw std::runtime_error("bad type!"); + } +} + +bool +gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ + switch(type){ + case pdu_byte: + return pmt::pmt_is_u8vector(v); + case pdu_float: + return pmt::pmt_is_f32vector(v); + case pdu_complex: + return pmt::pmt_is_c32vector(v); + default: + throw std::runtime_error("bad type!"); + } +} + +pmt::pmt_t +gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){ + switch(type){ + case pdu_byte: + return pmt::pmt_init_u8vector(items, buf); + case pdu_float: + return pmt::pmt_init_f32vector(items, (const float*)buf); + case pdu_complex: + return pmt::pmt_init_c32vector(items, (const gr_complex*)buf); + default: + throw std::runtime_error("bad type!"); + } +} + +gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector){ + if(pmt_is_u8vector(vector)) + return pdu_byte; + if(pmt_is_f32vector(vector)) + return pdu_float; + if(pmt_is_c32vector(vector)) + return pdu_complex; + throw std::runtime_error("bad type!"); +} diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h new file mode 100644 index 000000000..a5ae87db7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_PDU_H +#define GR_PDU_H + +#include <gr_complex.h> +#include <gruel/pmt.h> + +#define pdu_port_id pmt::mp("pdus") +#define pdu_length_tag pmt::mp("pdu_length") + +enum gr_pdu_vector_type { pdu_byte, pdu_float, pdu_complex }; + +size_t gr_pdu_itemsize(gr_pdu_vector_type type); +bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v); +pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items); +gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector); + +#endif diff --git a/gnuradio-core/src/lib/io/gr_pdu.i b/gnuradio-core/src/lib/io/gr_pdu.i new file mode 100644 index 000000000..ada3a63a7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.i @@ -0,0 +1,30 @@ +/* -*- 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+%{
+#include <gr_pdu.h>
+%}
+
+enum gr_pdu_vector_type { pdu_byte, pdu_float, pdu_complex };
+
+
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc new file mode 100644 index 000000000..5c319dc39 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc @@ -0,0 +1,132 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pdu_to_tagged_stream.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> + + +// public constructor that returns a shared_ptr + +gr_pdu_to_tagged_stream_sptr +gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_pdu_to_tagged_stream(t)); +} + +gr_pdu_to_tagged_stream::gr_pdu_to_tagged_stream (gr_pdu_vector_type t) + : gr_sync_block("pdu_to_tagged_stream", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, gr_pdu_itemsize(t))), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)) +{ + message_port_register_in(pdu_port_id); +} + +gr_pdu_to_tagged_stream::~gr_pdu_to_tagged_stream() +{ +} + +int +gr_pdu_to_tagged_stream::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nout = 0; + + // if we have remaining output, send it + if(d_remain.size() > 0){ + nout = std::min((size_t)d_remain.size()/d_itemsize, (size_t)noutput_items); + memcpy(out, &d_remain[0], nout*d_itemsize); + d_remain.erase( d_remain.begin(), d_remain.begin()+nout); + noutput_items -= nout; + out += nout*d_itemsize; + } + + // if we have space for at least one item output as much as we can + if(noutput_items > 0){ + + // grab a message if one exists + //pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) ); + pmt::pmt_t msg( delete_head_blocking( pdu_port_id ) ); + if(msg.get() == NULL ){ + return nout; + } + + // make sure type is valid + if(!pmt::pmt_is_pair(msg)){ + throw std::runtime_error("received a malformed pdu message!"); + } + +// printf("got a msg\n"); +// pmt::pmt_print(msg); + + // grab the components of the pdu message + pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ? + pmt::pmt_t vect(pmt::pmt_cdr(msg)); // make sure this is a vector? + + // compute offset for output tag + uint64_t offset = nitems_written(0) + nout; + + // add a tag for pdu length + add_item_tag(0, offset, pdu_length_tag, pmt::pmt_from_long( pmt::pmt_length(vect) ), pmt::mp(alias())); + + // if we recieved metadata add it as tags + if( !pmt_eq(meta, pmt::PMT_NIL) ){ + pmt::pmt_t pair(pmt::pmt_dict_keys( meta )); + while( !pmt_eq(pair, pmt::PMT_NIL) ){ + pmt::pmt_t k(pmt::pmt_cdr(pair)); + pmt::pmt_t v(pmt::pmt_dict_ref(meta, k, pmt::PMT_NIL)); + add_item_tag(0, offset, k, v, pmt::mp(alias())); + } + } + + // copy vector output + size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::pmt_length(vect)); + size_t nsave = pmt::pmt_length(vect) - ncopy; + + // copy output + size_t io(0); + nout += ncopy; + memcpy(out, pmt_uniform_vector_elements(vect,io), ncopy*d_itemsize); + + // save leftover items if needed for next work call + if(nsave > 0){ + d_remain.resize(nsave*d_itemsize, 0); + memcpy(&d_remain[0], pmt_uniform_vector_elements(vect,ncopy), nsave*d_itemsize); + } + + } + + return nout; +} diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h new file mode 100644 index 000000000..3105a3d38 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_PDU_TO_TAGGED_STREAM_H +#define INCLUDED_GR_PDU_TO_TAGGED_STREAM_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_pdu.h> + +class gr_pdu_to_tagged_stream; +typedef boost::shared_ptr<gr_pdu_to_tagged_stream> gr_pdu_to_tagged_stream_sptr; + +GR_CORE_API gr_pdu_to_tagged_stream_sptr gr_make_pdu_to_tagged_stream (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + std::vector<uint8_t> d_remain; + + friend GR_CORE_API gr_pdu_to_tagged_stream_sptr + gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t); + + protected: + gr_pdu_to_tagged_stream (gr_pdu_vector_type t); + + public: + ~gr_pdu_to_tagged_stream (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i new file mode 100644 index 000000000..ec760b309 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pdu_to_tagged_stream); + +%{ +#include <gr_pdu_to_tagged_stream.h> +%} + +%include <gr_pdu_to_tagged_stream.h> + + diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.cc b/gnuradio-core/src/lib/io/gr_socket_pdu.cc new file mode 100644 index 000000000..bb374b300 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.cc @@ -0,0 +1,157 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_socket_pdu.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/format.hpp> + +// public constructor that returns a shared_ptr +gr_socket_pdu_sptr +gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_socket_pdu(type,addr,port,MTU)); +} + +gr_socket_pdu::gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU) + : gr_stream_pdu_base(MTU) +{ + + if( (type == "TCP_SERVER") || (type == "TCP_CLIENT")){ + boost::asio::ip::tcp::resolver resolver(_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); + _tcp_endpoint = *resolver.resolve(query); + } + if( (type == "UDP_SERVER") || (type == "UDP_CLIENT")){ + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + if( (type == "UDP_SERVER") ){ + _udp_endpoint = *resolver.resolve(query); + } else { + _udp_endpoint_other = *resolver.resolve(query); + } + } + + // register ports + message_port_register_out(pmt::mp("pdus")); + message_port_register_in(pmt::mp("pdus")); + + // set up socketry + if (type == "TCP_SERVER"){ + _acceptor_tcp.reset(new boost::asio::ip::tcp::acceptor(_io_service, _tcp_endpoint)); + _acceptor_tcp->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + start_tcp_accept(); + // bind tcp server send handler + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_server_send, this, _1)); + } else if(type =="TCP_CLIENT"){ + boost::system::error_code error = boost::asio::error::host_not_found; + _tcp_socket.reset(new boost::asio::ip::tcp::socket(_io_service)); + _tcp_socket->connect(_tcp_endpoint, error); + if(error){ + throw boost::system::system_error(error); + } + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_client_send, this, _1)); + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else if(type =="UDP_SERVER"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else if(type =="UDP_CLIENT"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else { + throw std::runtime_error("unknown socket type!"); + } + + // start thread for io_service + d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_socket_pdu::run_io_service, this))); + d_started = true; +} + +void tcp_connection::handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred) + { + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&buf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + d_block->message_port_pub( pmt::mp("pdus"), pdu ); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + std::cout << "error occurred\n"; + } + + } + + +void gr_socket_pdu::tcp_server_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + for(size_t i=0; i<d_tcp_connections.size(); i++){ + d_tcp_connections[i]->send(vector); + } +} + +void gr_socket_pdu::tcp_client_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + _tcp_socket->send(boost::asio::buffer(txbuf,len)); +} + +void gr_socket_pdu::udp_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + if(_udp_endpoint_other.address().to_string() != "0.0.0.0") + _udp_socket->send_to(boost::asio::buffer(txbuf,len), _udp_endpoint_other); +} diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.h b/gnuradio-core/src/lib/io/gr_socket_pdu.h new file mode 100644 index 000000000..2fedb317d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.h @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SOCKET_PDU_H +#define INCLUDED_GR_SOCKET_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_stream_pdu_base.h> +#include <boost/array.hpp> +#include <boost/asio.hpp> +#include <iostream> + +class gr_socket_pdu; +typedef boost::shared_ptr<gr_socket_pdu> gr_socket_pdu_sptr; + +GR_CORE_API gr_socket_pdu_sptr gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + +class tcp_connection + : public boost::enable_shared_from_this<tcp_connection> +{ +public: + typedef boost::shared_ptr<tcp_connection> pointer; + gr_socket_pdu *d_block; + boost::array<char, 10000> buf; + + static pointer create(boost::asio::io_service& io_service) + { + return pointer(new tcp_connection(io_service)); + } + + boost::asio::ip::tcp::socket& socket() + { + return socket_; + } + + void start(gr_socket_pdu* parent) + { + d_block = parent; +// message_ = "connected to gr_socket_pdu\n"; +// boost::asio::async_write(socket_, boost::asio::buffer(message_), +// boost::bind(&tcp_connection::handle_write, shared_from_this(), +// boost::asio::placeholders::error, +// boost::asio::placeholders::bytes_transferred)); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + void send(pmt::pmt_t vector){ + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + boost::asio::async_write(socket_, boost::asio::buffer(txbuf, len), + boost::bind(&tcp_connection::handle_write, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + ~tcp_connection(){ +// std::cout << "tcp_connection destroyed\n"; + } + +private: + tcp_connection(boost::asio::io_service& io_service) + : socket_(io_service) + { + } + + void handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred); + + void handle_write(const boost::system::error_code& /*error*/, + size_t /*bytes_transferred*/) + { + } + + boost::asio::ip::tcp::socket socket_; + std::string message_; +}; + + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_socket_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_socket_pdu_sptr + gr_make_socket_pdu(std::string type, std::string addr, std::string port, int MTU); + + boost::asio::io_service _io_service; + + boost::array<char, 10000> rxbuf; + + // tcp specific + boost::asio::ip::tcp::endpoint _tcp_endpoint; + + // specific to tcp server + boost::shared_ptr<boost::asio::ip::tcp::acceptor> _acceptor_tcp; + std::vector<tcp_connection::pointer> d_tcp_connections; + void tcp_server_send(pmt::pmt_t msg); + void tcp_client_send(pmt::pmt_t msg); + void udp_send(pmt::pmt_t msg); + + // specific to tcp client + boost::shared_ptr<boost::asio::ip::tcp::socket> _tcp_socket; + + // specific to udp client/server + boost::asio::ip::udp::endpoint _udp_endpoint; + boost::asio::ip::udp::endpoint _udp_endpoint_other; + boost::shared_ptr<boost::asio::ip::udp::socket> _udp_socket; + + void handle_receive(const boost::system::error_code& error, std::size_t ){ + } + + void start_tcp_accept(){ + tcp_connection::pointer new_connection = + tcp_connection::create(_acceptor_tcp->get_io_service()); + + _acceptor_tcp->async_accept(new_connection->socket(), + boost::bind(&gr_socket_pdu::handle_tcp_accept, this, new_connection, + boost::asio::placeholders::error)); + } + + void handle_tcp_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error){ + if (!error) + { + new_connection->start(this); + d_tcp_connections.push_back(new_connection); + start_tcp_accept(); + } else { + std::cout << error << std::endl; + } + } + + void run_io_service(){ + _io_service.run(); + } + + void handle_udp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error){ + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } else { + throw boost::system::system_error(error); +// std::cout << "error occurred\n"; + } + } + void handle_tcp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + //std::cout << "error occurred\n"; + throw boost::system::system_error(error); + } + } + + protected: + gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + public: + ~gr_socket_pdu () {} +}; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.i b/gnuradio-core/src/lib/io/gr_socket_pdu.i new file mode 100644 index 000000000..3e20b63e2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.i @@ -0,0 +1,33 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,socket_pdu); + +%ignore tcp_connection; + +%{ +#include <gr_socket_pdu.h> +%} + +%include "gr_stream_pdu_base.h" +%include "gr_socket_pdu.h" + diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc new file mode 100644 index 000000000..7250c33e5 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ciso646> +#include <gr_stream_pdu_base.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/asio.hpp> +#include <boost/format.hpp> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +static const long timeout_us = 100*1000; //100ms + +gr_stream_pdu_base::gr_stream_pdu_base (int MTU) + : gr_sync_block("stream_pdu_base", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_finished(false), d_started(false), d_fd(-1) +{ + // reserve space for rx buffer + d_rxbuf.resize(MTU,0); +} + +gr_stream_pdu_base::~gr_stream_pdu_base() +{ + stop_rxthread(); +} + +void gr_stream_pdu_base::stop_rxthread(){ + d_finished = true; + if(d_started){ + d_thread->interrupt(); + d_thread->join(); + } + } + +void gr_stream_pdu_base::start_rxthread(pmt::pmt_t _rxport){ + rxport = _rxport; + d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_stream_pdu_base::run, this))); + d_started = true; + } + +void gr_stream_pdu_base::run(){ + while(!d_finished) { + if(not wait_ready()){ continue; } + const int result = read( d_fd, &d_rxbuf[0], d_rxbuf.size() ); + if(result <= 0){ throw std::runtime_error("gr_stream_pdu_base, bad socket read!"); } + pmt::pmt_t vector = pmt::pmt_init_u8vector(result, &d_rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + message_port_pub(rxport, pdu); + } +} + +void gr_stream_pdu_base::send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t offset(0); + size_t itemsize(gr_pdu_itemsize(type_from_pmt(vector))); + int len( pmt::pmt_length(vector)*itemsize ); + + const int rv = write(d_fd, pmt::pmt_uniform_vector_elements(vector, offset), len); + if(rv != len){ + std::cerr << boost::format("WARNING: gr_stream_pdu_base::send(pdu) write failed! (d_fd=%d, len=%d, rv=%d)") + % d_fd % len % rv << std::endl; + } +} + +int +gr_stream_pdu_base::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + throw std::runtime_error("should not be called.\n"); + return 0; +} + +bool gr_stream_pdu_base::wait_ready(){ + //setup timeval for timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout_us; + + //setup rset for timeout + fd_set rset; + FD_ZERO(&rset); + FD_SET(d_fd, &rset); + + //call select with timeout on receive socket + return ::select(d_fd+1, &rset, NULL, NULL, &tv) > 0; +} diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.h b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h new file mode 100644 index 000000000..35bacf523 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_STREAM_PDU_BASE_H +#define INCLUDED_GR_STREAM_PDU_BASE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_stream_pdu_base : public gr_sync_block +{ + public: + boost::shared_ptr<boost::thread> d_thread; + bool d_finished; + bool d_started; + std::vector<uint8_t> d_rxbuf; + void run(); + int d_fd; + gr_stream_pdu_base (int MTU=10000); + ~gr_stream_pdu_base (); + void send(pmt::pmt_t msg); + bool wait_ready(); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void start_rxthread(pmt::pmt_t _rxport); + void stop_rxthread(); + private: + pmt::pmt_t rxport; +}; + +typedef boost::shared_ptr<gr_stream_pdu_base> gr_stream_pdu_base_sptr; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc new file mode 100644 index 000000000..6d642088e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc @@ -0,0 +1,216 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_tagged_file_sink.h> +#include <gr_io_signature.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <iostream> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_tagged_file_sink::gr_tagged_file_sink (size_t itemsize, double samp_rate) + : gr_sync_block ("tagged_file_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_n(0), d_sample_rate(samp_rate) +{ + d_state = NOT_IN_BURST; + d_last_N = 0; + d_timeval = 0; +} + +gr_tagged_file_sink_sptr +gr_make_tagged_file_sink (size_t itemsize, double samp_rate) +{ + return gnuradio::get_initial_sptr(new gr_tagged_file_sink (itemsize, samp_rate)); +} + +gr_tagged_file_sink::~gr_tagged_file_sink () +{ +} + +int +gr_tagged_file_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + + uint64_t start_N = nitems_read(0); + uint64_t end_N = start_N + (uint64_t)(noutput_items); + pmt::pmt_t bkey = pmt::pmt_string_to_symbol("burst"); + //pmt::pmt_t tkey = pmt::pmt_string_to_symbol("time"); // use gr_tags::key_time + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, 0, start_N, end_N); + + std::sort(all_tags.begin(), all_tags.end(), gr_tag_t::offset_compare); + + std::vector<gr_tag_t>::iterator vitr = all_tags.begin(); + + int idx = 0, idx_stop = 0; + while(idx < noutput_items) { + if(d_state == NOT_IN_BURST) { + while(vitr != all_tags.end()) { + if((pmt::pmt_eqv((*vitr).key, bkey)) && + pmt::pmt_is_true((*vitr).value)) { + + uint64_t N = (*vitr).offset; + idx = (int)(N - start_N); + + //std::cout << std::endl << "Found start of burst: " + // << idx << ", " << N << std::endl; + + // Find time burst occurred by getting latest time tag and extrapolating + // to new time based on sample rate of this block. + std::vector<gr_tag_t> time_tags; + //get_tags_in_range(time_tags, 0, d_last_N, N, gr_tags::key_time); + get_tags_in_range(time_tags, 0, d_last_N, N, + pmt::pmt_string_to_symbol("time")); + if(time_tags.size() > 0) { + const gr_tag_t tag = time_tags[time_tags.size()-1]; + + uint64_t time_nitems = tag.offset; + + // Get time based on last time tag from USRP + pmt::pmt_t time = tag.value; + int tsecs = pmt::pmt_to_long(pmt::pmt_tuple_ref(time, 0)); + double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1)); + + // Get new time from last time tag + difference in time to when + // burst tag occured based on the sample rate + double delta = (double)(N - time_nitems) / d_sample_rate; + d_timeval = (double)tsecs + tfrac + delta; + + //std::cout.setf(std::ios::fixed, std::ios::floatfield); + //std::cout.precision(8); + //std::cout << "Time found: " << (double)tsecs + tfrac << std::endl; + //std::cout << " time: " << d_timeval << std::endl; + //std::cout << " time at N = " << time_nitems << " burst N = " << N << std::endl; + } + else { + // if no time tag, use last seen tag and update time based on + // sample rate of the block + d_timeval += (double)(N - d_last_N) / d_sample_rate; + //std::cout << "Time not found" << std::endl; + //std::cout << " time: " << d_timeval << std::endl; + } + d_last_N = N; + + std::stringstream filename; + filename.setf(std::ios::fixed, std::ios::floatfield); + filename.precision(8); + filename << "file" << unique_id() << "_" << d_n << "_" << d_timeval << ".dat"; + d_n++; + + int fd; + if ((fd = ::open (filename.str().c_str(), + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename.str().c_str()); + return -1; + } + + // FIXME: + //if ((d_handle = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){ + if ((d_handle = fdopen (fd, "wb")) == NULL){ + perror (filename.str().c_str()); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + //std::cout << "Created new file: " << filename.str() << std::endl; + + d_state = IN_BURST; + break; + } + + vitr++; + } + if(d_state == NOT_IN_BURST) + return noutput_items; + } + else { // In burst + while(vitr != all_tags.end()) { + if((pmt::pmt_eqv((*vitr).key, bkey)) && + pmt::pmt_is_false((*vitr).value)) { + uint64_t N = (*vitr).offset; + idx_stop = (int)N - start_N; + + //std::cout << "Found end of burst: " + // << idx_stop << ", " << N << std::endl; + + int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, + idx_stop-idx, d_handle); + if (count == 0) { + if(ferror(d_handle)) { + perror("gr_tagged_file_sink: error writing file"); + } + } + idx = idx_stop; + d_state = NOT_IN_BURST; + vitr++; + fclose(d_handle); + break; + } + else { + vitr++; + } + } + if(d_state == IN_BURST) { + int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, + noutput_items-idx, d_handle); + if (count == 0) { + if(ferror(d_handle)) { + perror("gr_tagged_file_sink: error writing file"); + } + } + idx = noutput_items; + } + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.h b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h new file mode 100644 index 000000000..d6f931a67 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TAGGED_FILE_SINK_H +#define INCLUDED_GR_TAGGED_FILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <cstdio> // for FILE + +class gr_tagged_file_sink; +typedef boost::shared_ptr<gr_tagged_file_sink> gr_tagged_file_sink_sptr; + +GR_CORE_API gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize, + double samp_rate); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_tagged_file_sink : public gr_sync_block +{ + friend GR_CORE_API gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize, + double samp_rate); + + private: + enum { + NOT_IN_BURST = 0, + IN_BURST + }; + + size_t d_itemsize; + int d_state; + FILE *d_handle; + int d_n; + double d_sample_rate; + uint64_t d_last_N; + double d_timeval; + + protected: + gr_tagged_file_sink (size_t itemsize, double samp_rate); + + public: + ~gr_tagged_file_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_TAGGED_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.i b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i new file mode 100644 index 000000000..2f2596e12 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tagged_file_sink) + +gr_tagged_file_sink_sptr +gr_make_tagged_file_sink (size_t itemsize, double samp_rate); + +class gr_tagged_file_sink : public gr_sync_block +{ + protected: + gr_tagged_file_sink (size_t itemsize, double samp_rate); + + public: + ~gr_tagged_file_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc new file mode 100644 index 000000000..8211b7672 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_tagged_stream_to_pdu.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> + +// public constructor that returns a shared_ptr + +gr_tagged_stream_to_pdu_sptr +gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_tagged_stream_to_pdu(t)); +} + +gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t) + : gr_sync_block("tagged_stream_to_pdu", + gr_make_io_signature(1, 1, gr_pdu_itemsize(t)), + gr_make_io_signature(0, 0, 0)), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false), + d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL) +{ + message_port_register_out(pdu_port_id); +} + +gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu() +{ + printf("destructor running\n"); +} + +int +gr_tagged_stream_to_pdu::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const uint8_t *in = (const uint8_t*) input_items[0]; + uint64_t abs_N = nitems_read(0); + + // if we are not in a pdu already, start a new one + if(!d_inpdu){ + get_tags_in_range(d_tags, 0, abs_N, abs_N+1); + bool found_length_tag(false); + for(d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++){ + if( pmt::pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + if( (*d_tags_itr).offset != abs_N ){ + throw std::runtime_error("expected next pdu length tag on a different item..."); + } + found_length_tag = true; + d_pdu_length = pmt::pmt_to_long( (*d_tags_itr).value ); + d_pdu_remain = d_pdu_length; + d_pdu_meta = pmt::pmt_make_dict(); + break; + } // if have length tag + } // iter over tags + if(!found_length_tag){ + throw std::runtime_error("tagged stream does not contain a pdu_length tag!"); + } + } + + size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain); + + // copy any tags in this range into our meta object + get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy); + for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++){ + if( ! pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + d_pdu_meta = pmt_dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value); + } + } + + // copy samples for this vector into either a pmt or our save buffer + if(ncopy == d_pdu_remain){ // we will send this pdu + if(d_save.size() == 0){ + d_pdu_vector = gr_pdu_make_vector(d_vectortype, in, ncopy); + send_message(); + } else { + size_t oldsize = d_save.size(); + d_save.resize((oldsize + ncopy)*d_itemsize, 0); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_vector = gr_pdu_make_vector(d_vectortype, &d_save[0], d_pdu_length); + send_message(); + d_save.clear(); + } + } else { + d_inpdu = true; + size_t oldsize = d_save.size(); + d_save.resize( (oldsize+ncopy)*d_itemsize ); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_remain -= ncopy; + } + + return ncopy; +} + +void gr_tagged_stream_to_pdu::send_message(){ + + if(pmt::pmt_length(d_pdu_vector) != d_pdu_length){ + throw std::runtime_error("msg length not correct"); + } + + pmt::pmt_t msg = pmt::pmt_cons( d_pdu_meta, d_pdu_vector ); + message_port_pub( pdu_port_id, msg ); + + d_pdu_meta = pmt::PMT_NIL; + d_pdu_vector = pmt::PMT_NIL; + d_pdu_length = 0; + d_pdu_remain = 0; + d_inpdu = false; +} diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h new file mode 100644 index 000000000..c3fff3581 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TAGGED_STREAM_TO_PDU_H +#define INCLUDED_GR_TAGGED_STREAM_TO_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_pdu.h> + +class gr_tagged_stream_to_pdu; +typedef boost::shared_ptr<gr_tagged_stream_to_pdu> gr_tagged_stream_to_pdu_sptr; + +GR_CORE_API gr_tagged_stream_to_pdu_sptr gr_make_tagged_stream_to_pdu (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + + std::vector<uint8_t> d_save; + + std::vector<gr_tag_t> d_tags; + std::vector<gr_tag_t>::iterator d_tags_itr; + + bool d_inpdu; + + size_t d_pdu_length; + size_t d_pdu_remain; + pmt::pmt_t d_pdu_meta; + pmt::pmt_t d_pdu_vector; + + friend GR_CORE_API gr_tagged_stream_to_pdu_sptr + gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t); + + protected: + gr_tagged_stream_to_pdu (gr_pdu_vector_type t); + + public: + ~gr_tagged_stream_to_pdu (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void send_message(); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i new file mode 100644 index 000000000..f12987b74 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tagged_stream_to_pdu); + +%{ +#include <gr_tagged_stream_to_pdu.h> +%} + +%include <gr_tagged_stream_to_pdu.h> + + diff --git a/gnuradio-core/src/lib/io/gr_trigger_mode.h b/gnuradio-core/src/lib/io/gr_trigger_mode.h new file mode 100644 index 000000000..be131686b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_trigger_mode.h @@ -0,0 +1,38 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TRIGGER_MODE_H +#define INCLUDED_GR_TRIGGER_MODE_H + +enum gr_trigger_mode { + gr_TRIG_MODE_FREE, + gr_TRIG_MODE_AUTO, + gr_TRIG_MODE_NORM, + gr_TRIG_MODE_STRIPCHART, +}; + +enum gr_trigger_slope { + gr_TRIG_SLOPE_POS, + gr_TRIG_SLOPE_NEG, +}; + +#endif /* INCLUDED_GR_TRIGGER_MODE_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc new file mode 100644 index 000000000..8dd4b18a1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc @@ -0,0 +1,145 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_tuntap_pdu.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/format.hpp> + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <arpa/inet.h> +#include <linux/if.h> + + +// public constructor that returns a shared_ptr + +gr_tuntap_pdu_sptr +gr_make_tuntap_pdu (std::string dev, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_tuntap_pdu(dev, MTU)); +} + +gr_tuntap_pdu::gr_tuntap_pdu (std::string dev, int MTU) + : gr_stream_pdu_base(MTU) +{ + + // make the tuntap + char dev_cstr[1024]; + memset(dev_cstr, 0x00, 1024); + strncpy(dev_cstr, dev.c_str(), std::min(sizeof(dev_cstr), dev.size())); + d_fd = tun_alloc(dev_cstr); + if(d_fd <= 0){ + throw std::runtime_error("TunTap make: tun_alloc failed (are you running as root?)"); + } + + std::cout << boost::format( + "Allocated virtual ethernet interface: %s\n" + "You must now use ifconfig to set its IP address. E.g.,\n" + " $ sudo ifconfig %s 192.168.200.1\n" + "Be sure to use a different address in the same subnet for each machine.\n" + ) % dev % dev << std::endl; + + // set up output message port + message_port_register_out(pmt::mp("pdus")); + start_rxthread(pmt::mp("pdus")); + + // set up input message port + message_port_register_in(pmt::mp("pdus")); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_tuntap_pdu::send, this, _1)); +} + + +int gr_tuntap_pdu::tun_alloc(char *dev, int flags) { + struct ifreq ifr; + int fd, err; + const char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + /* open the clone device */ + if( (fd = open(clonedev, O_RDWR)) < 0 ) { + return fd; + } + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + +#else //if not linux + +gr_block_sptr +gr_make_tuntap_pdu(std::string dev, int MTU) +{ + gr_block_sptr rv; + throw std::runtime_error("tuntap only implemented on linux"); + return rv; +} + +#endif diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.h b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h new file mode 100644 index 000000000..18c83f42b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TUNTAP_PDU_H +#define INCLUDED_GR_TUNTAP_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_stream_pdu_base.h> + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include <linux/if_tun.h> + +class gr_tuntap_pdu; +typedef boost::shared_ptr<gr_tuntap_pdu> gr_tuntap_pdu_sptr; + +GR_CORE_API gr_tuntap_pdu_sptr gr_make_tuntap_pdu (std::string dev, int MTU=10000); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_tuntap_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_tuntap_pdu_sptr + gr_make_tuntap_pdu(std::string dev, int MTU); + int tun_alloc(char* dev, int flags = IFF_TAP | IFF_NO_PI); + std::string d_dev; + protected: + gr_tuntap_pdu (std::string dev, int MTU=10000); + + public: + ~gr_tuntap_pdu () {} + +}; + +#else // if not linux + +class gr_tuntap_pdu +{ +private: + gr_tuntap_pdu() {}; +public: + ~gr_tuntap_pdu() {}; +}; + +GR_CORE_API gr_block_sptr gr_make_tuntap_pdu (std::string dev, int MTU=0); + +#endif + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.i b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i new file mode 100644 index 000000000..589bbc385 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i @@ -0,0 +1,30 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tuntap_pdu); + +%{ +#include <gr_tuntap_pdu.h> +%} + +%include "gr_tuntap_pdu.h" + diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.cc b/gnuradio-core/src/lib/io/gr_udp_sink.cc new file mode 100644 index 000000000..6b1d34ef7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.cc @@ -0,0 +1,304 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <boost/asio.hpp> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_udp_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#if defined(HAVE_NETDB_H) +#include <netdb.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> //usually included by <netdb.h>? +#endif +typedef void* optval_t; +#elif defined(HAVE_WINDOWS_H) +// if not posix, assume winsock +#define USING_WINSOCK +#include <winsock2.h> +#include <ws2tcpip.h> +#define SHUT_RDWR 2 +typedef char* optval_t; +#endif + +#include <gruel/thread.h> + +#define SNK_VERBOSE 0 + +static int is_error( int perr ) +{ + // Compare error to posix error code; return nonzero if match. +#if defined(USING_WINSOCK) +#define ENOPROTOOPT 109 +#define ECONNREFUSED 111 + // All codes to be checked for must be defined below + int werr = WSAGetLastError(); + switch( werr ) { + case WSAETIMEDOUT: + return( perr == EAGAIN ); + case WSAENOPROTOOPT: + return( perr == ENOPROTOOPT ); + case WSAECONNREFUSED: + return( perr == ECONNREFUSED ); + default: + fprintf(stderr,"gr_udp_source/is_error: unknown error %d\n", perr ); + throw std::runtime_error("internal error"); + } + return 0; +#else + return( perr == errno ); +#endif +} + +static void report_error( const char *msg1, const char *msg2 ) +{ + // Deal with errors, both posix and winsock +#if defined(USING_WINSOCK) + int werr = WSAGetLastError(); + fprintf(stderr, "%s: winsock error %d\n", msg1, werr ); +#else + perror(msg1); +#endif + if( msg2 != NULL ) + throw std::runtime_error(msg2); + return; +} + +gr_udp_sink::gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) + : gr_sync_block ("udp_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_payload_size(payload_size), d_eof(eof), + d_socket(-1), d_connected(false) +{ +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // initialize winsock DLL + WSADATA wsaData; + int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); + if( iResult != NO_ERROR ) { + report_error( "gr_udp_source WSAStartup", "can't open socket" ); + } +#endif + + // create socket + d_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(d_socket == -1) { + report_error("socket open","can't open socket"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (optval_t)&lngr, sizeof(linger)) == -1) { + if( !is_error(ENOPROTOOPT) ) { // no SO_LINGER for SOCK_DGRAM on Windows + report_error("SO_LINGER","can't set socket option SO_LINGER"); + } + } + + // Get the destination address + connect(host, port); +} + +// public constructor that returns a shared_ptr + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) +{ + return gnuradio::get_initial_sptr(new gr_udp_sink (itemsize, + host, port, + payload_size, eof)); +} + +gr_udp_sink::~gr_udp_sink () +{ + if (d_connected) + disconnect(); + + if (d_socket != -1){ + shutdown(d_socket, SHUT_RDWR); +#if defined(USING_WINSOCK) + closesocket(d_socket); +#else + ::close(d_socket); +#endif + d_socket = -1; + } + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // free winsock resources + WSACleanup(); +#endif +} + +int +gr_udp_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + ssize_t r=0, bytes_sent=0, bytes_to_send=0; + ssize_t total_size = noutput_items*d_itemsize; + + #if SNK_VERBOSE + printf("Entered udp_sink\n"); + #endif + + gruel::scoped_lock guard(d_mutex); // protect d_socket + + while(bytes_sent < total_size) { + bytes_to_send = std::min((ssize_t)d_payload_size, (total_size-bytes_sent)); + + if(d_connected) { + r = send(d_socket, (in+bytes_sent), bytes_to_send, 0); + if(r == -1) { // error on send command + if( is_error(ECONNREFUSED) ) + r = bytes_to_send; // discard data until receiver is started + else { + report_error("udp_sink",NULL); // there should be no error case where + return -1; // this function should not exit immediately + } + } + } + else + r = bytes_to_send; // discarded for lack of connection + bytes_sent += r; + + #if SNK_VERBOSE + printf("\tbyte sent: %d bytes\n", r); + #endif + } + + #if SNK_VERBOSE + printf("Sent: %d bytes (noutput_items: %d)\n", bytes_sent, noutput_items); + #endif + + return noutput_items; +} + +void gr_udp_sink::connect( const char *host, unsigned short port ) +{ + if(d_connected) + disconnect(); + + if(host != NULL ) { + // Get the destination address + struct addrinfo *ip_dst; + struct addrinfo hints; + memset( (void*)&hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + char port_str[12]; + sprintf( port_str, "%d", port ); + + // FIXME leaks if report_error throws below + int ret = getaddrinfo( host, port_str, &hints, &ip_dst ); + if( ret != 0 ) + report_error("gr_udp_source/getaddrinfo", + "can't initialize destination socket" ); + + // don't need d_mutex lock when !d_connected + if(::connect(d_socket, ip_dst->ai_addr, ip_dst->ai_addrlen) == -1) { + report_error("socket connect","can't connect to socket"); + } + d_connected = true; + + freeaddrinfo(ip_dst); + } + + return; +} + +void gr_udp_sink::disconnect() +{ + if(!d_connected) + return; + + #if SNK_VERBOSE + printf("gr_udp_sink disconnecting\n"); + #endif + + gruel::scoped_lock guard(d_mutex); // protect d_socket from work() + + // Send a few zero-length packets to signal receiver we are done + if(d_eof) { + int i; + for( i = 0; i < 3; i++ ) + (void) send( d_socket, NULL, 0, 0 ); // ignore errors + } + + // Sending EOF can produce ERRCONNREFUSED errors that won't show up + // until the next send or recv, which might confuse us if it happens + // on a new connection. The following does a nonblocking recv to + // clear any such errors. + timeval timeout; + timeout.tv_sec = 0; // zero time for immediate return + timeout.tv_usec = 0; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(d_socket, &readfds); + int r = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); + if(r < 0) { + #if SNK_VERBOSE + report_error("udp_sink/select",NULL); + #endif + } + else if(r > 0) { // call recv() to get error return + r = recv(d_socket, (char*)&readfds, sizeof(readfds), 0); + if(r < 0) { + #if SNK_VERBOSE + report_error("udp_sink/recv",NULL); + #endif + } + } + + // Since I can't find any way to disconnect a datagram socket in Cygwin, + // we just leave it connected but disable sending. +#if 0 + // zeroed address structure should reset connection + struct sockaddr addr; + memset( (void*)&addr, 0, sizeof(addr) ); + // addr.sa_family = AF_UNSPEC; // doesn't work on Cygwin + // addr.sa_family = AF_INET; // doesn't work on Cygwin + + if(::connect(d_socket, &addr, sizeof(addr)) == -1) + report_error("socket connect","can't connect to socket"); +#endif + + d_connected = false; + + return; +} diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.h b/gnuradio-core/src/lib/io/gr_udp_sink.h new file mode 100644 index 000000000..bf042a6d1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.h @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_UDP_SINK_H +#define INCLUDED_GR_UDP_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> + +class gr_udp_sink; +typedef boost::shared_ptr<gr_udp_sink> gr_udp_sink_sptr; + +GR_CORE_API gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size=1472, bool eof=true); + +/*! + * \brief Write stream to an UDP socket. + * \ingroup sink_blk + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; use + * NULL or None for no connection + * \param port Destination port to connect to on receiving host + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Send zero-length packet on disconnect + */ + +class GR_CORE_API gr_udp_sink : public gr_sync_block +{ + friend GR_CORE_API gr_udp_sink_sptr gr_make_udp_sink (size_t itemsize, + const char *host, + unsigned short port, + int payload_size, bool eof); + private: + size_t d_itemsize; + + int d_payload_size; // maximum transmission unit (packet length) + bool d_eof; // send zero-length packet on disconnect + int d_socket; // handle to socket + bool d_connected; // are we connected? + gruel::mutex d_mutex; // protects d_socket and d_connected + + protected: + /*! + * \brief UDP Sink Constructor + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; use + * NULL or None for no connection + * \param port Destination port to connect to on receiving host + * \param payload_size UDP payload size by default set to + * 1472 = (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Send zero-length packet on disconnect + */ + gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof); + + public: + ~gr_udp_sink (); + + /*! \brief return the PAYLOAD_SIZE of the socket */ + int payload_size() { return d_payload_size; } + + /*! \brief Change the connection to a new destination + * + * \param host The name or IP address of the receiving host; use + * NULL or None to break the connection without closing + * \param port Destination port to connect to on receiving host + * + * Calls disconnect() to terminate any current connection first. + */ + void connect( const char *host, unsigned short port ); + + /*! \brief Send zero-length packet (if eof is requested) then stop sending + * + * Zero-byte packets can be interpreted as EOF by gr_udp_source. Note that + * disconnect occurs automatically when the sink is destroyed, but not when + * its top_block stops.*/ + void disconnect(); + + // should we export anything else? + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_UDP_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.i b/gnuradio-core/src/lib/io/gr_udp_sink.i new file mode 100644 index 000000000..ba7043937 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.i @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,udp_sink) + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size=1472, bool eof=true) throw (std::runtime_error); + +class gr_udp_sink : public gr_sync_block +{ + protected: + gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) + throw (std::runtime_error); + + public: + ~gr_udp_sink (); + + int payload_size() { return d_payload_size; } + void connect( const char *host, unsigned short port ); + void disconnect(); + +}; diff --git a/gnuradio-core/src/lib/io/gr_udp_source.cc b/gnuradio-core/src/lib/io/gr_udp_source.cc new file mode 100644 index 000000000..eca8e89d0 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.cc @@ -0,0 +1,374 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_udp_source.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#if defined(HAVE_NETDB_H) +#include <netdb.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +typedef void* optval_t; + +// ntohs() on FreeBSD may require both netinet/in.h and arpa/inet.h, in order +#if defined(HAVE_NETINET_IN_H) +#include <netinet/in.h> +#endif +#if defined(HAVE_ARPA_INET_H) +#include <arpa/inet.h> +#endif + +#elif defined(HAVE_WINDOWS_H) +// if not posix, assume winsock +#define USING_WINSOCK +#include <winsock2.h> +#include <ws2tcpip.h> +#define SHUT_RDWR 2 +typedef char* optval_t; +#endif + +#define USE_SELECT 1 // non-blocking receive on all platforms +#define USE_RCV_TIMEO 0 // non-blocking receive on all but Cygwin +#define SRC_VERBOSE 0 + +static int is_error( int perr ) +{ + // Compare error to posix error code; return nonzero if match. +#if defined(USING_WINSOCK) +#define ENOPROTOOPT 109 + // All codes to be checked for must be defined below + int werr = WSAGetLastError(); + switch( werr ) { + case WSAETIMEDOUT: + return( perr == EAGAIN ); + case WSAENOPROTOOPT: + return( perr == ENOPROTOOPT ); + default: + fprintf(stderr,"gr_udp_source/is_error: unknown error %d\n", perr ); + throw std::runtime_error("internal error"); + } + return 0; +#else + return( perr == errno ); +#endif +} + +static void report_error( const char *msg1, const char *msg2 ) +{ + // Deal with errors, both posix and winsock +#if defined(USING_WINSOCK) + int werr = WSAGetLastError(); + fprintf(stderr, "%s: winsock error %d\n", msg1, werr ); +#else + perror(msg1); +#endif + if( msg2 != NULL ) + throw std::runtime_error(msg2); + return; +} + +gr_udp_source::gr_udp_source(size_t itemsize, const char *host, + unsigned short port, int payload_size, + bool eof, bool wait) + : gr_sync_block ("udp_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_payload_size(payload_size), + d_eof(eof), d_wait(wait), d_socket(-1), d_residual(0), d_temp_offset(0) +{ + int ret = 0; + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // initialize winsock DLL + WSADATA wsaData; + int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); + if( iResult != NO_ERROR ) { + report_error( "gr_udp_source WSAStartup", "can't open socket" ); + } +#endif + + // Set up the address stucture for the source address and port numbers + // Get the source IP address from the host name + struct addrinfo *ip_src; // store the source IP address to use + struct addrinfo hints; + memset( (void*)&hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_PASSIVE; + char port_str[12]; + sprintf( port_str, "%d", port ); + + // FIXME leaks if report_error throws below + ret = getaddrinfo( host, port_str, &hints, &ip_src ); + if( ret != 0 ) + report_error("gr_udp_source/getaddrinfo", + "can't initialize source socket" ); + + // FIXME leaks if report_error throws below + d_temp_buff = new char[d_payload_size]; // allow it to hold up to payload_size bytes + + // create socket + d_socket = socket(ip_src->ai_family, ip_src->ai_socktype, + ip_src->ai_protocol); + if(d_socket == -1) { + report_error("socket open","can't open socket"); + } + + // Turn on reuse address + int opt_val = 1; + if(setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, (optval_t)&opt_val, sizeof(int)) == -1) { + report_error("SO_REUSEADDR","can't set socket option SO_REUSEADDR"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (optval_t)&lngr, sizeof(linger)) == -1) { + if( !is_error(ENOPROTOOPT) ) { // no SO_LINGER for SOCK_DGRAM on Windows + report_error("SO_LINGER","can't set socket option SO_LINGER"); + } + } + +#if USE_RCV_TIMEO + // Set a timeout on the receive function to not block indefinitely + // This value can (and probably should) be changed + // Ignored on Cygwin +#if defined(USING_WINSOCK) + DWORD timeout = 1000; // milliseconds +#else + timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; +#endif + if(setsockopt(d_socket, SOL_SOCKET, SO_RCVTIMEO, (optval_t)&timeout, sizeof(timeout)) == -1) { + report_error("SO_RCVTIMEO","can't set socket option SO_RCVTIMEO"); + } +#endif // USE_RCV_TIMEO + + // bind socket to an address and port number to listen on + if(bind (d_socket, ip_src->ai_addr, ip_src->ai_addrlen) == -1) { + report_error("socket bind","can't bind socket"); + } + freeaddrinfo(ip_src); + +} + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *ipaddr, + unsigned short port, int payload_size, bool eof, bool wait) +{ + return gnuradio::get_initial_sptr(new gr_udp_source (itemsize, ipaddr, + port, payload_size, eof, wait)); +} + +gr_udp_source::~gr_udp_source () +{ + delete [] d_temp_buff; + + if (d_socket != -1){ + shutdown(d_socket, SHUT_RDWR); +#if defined(USING_WINSOCK) + closesocket(d_socket); +#else + ::close(d_socket); +#endif + d_socket = -1; + } + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // free winsock resources + WSACleanup(); +#endif +} + +int +gr_udp_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + ssize_t r=0, nbytes=0, bytes_received=0; + ssize_t total_bytes = (ssize_t)(d_itemsize*noutput_items); + + #if SRC_VERBOSE + printf("\nEntered udp_source\n"); + #endif + + // Remove items from temp buffer if they are in there + if(d_residual) { + nbytes = std::min(d_residual, total_bytes); + memcpy(out, d_temp_buff+d_temp_offset, nbytes); + bytes_received = nbytes; + + #if SRC_VERBOSE + printf("\tTemp buff size: %d offset: %d (bytes_received: %d) (noutput_items: %d)\n", + d_residual, d_temp_offset, bytes_received, noutput_items); + #endif + + // Increment pointer + out += bytes_received; + + // Update indexing of amount of bytes left in the buffer + d_residual -= nbytes; + d_temp_offset += nbytes; + + // Return now with what we've got. + assert(nbytes % d_itemsize == 0); + return nbytes/d_itemsize; + } + + while(1) { + // get the data into our output buffer and record the number of bytes + +#if USE_SELECT + // RCV_TIMEO doesn't work on all systems (e.g., Cygwin) + // use select() instead of, or in addition to RCV_TIMEO + fd_set readfds; + timeval timeout; + timeout.tv_sec = 1; // Init timeout each iteration. Select can modify it. + timeout.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(d_socket, &readfds); + r = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); + if(r < 0) { + report_error("udp_source/select",NULL); + return -1; + } + else if(r == 0 ) { // timed out + if( d_wait ) { + // Allow boost thread interrupt, then try again + //boost::this_thread::interruption_point(); + //continue; + return 0; + } + else + return -1; + } +#endif // USE_SELECT + + // This is a non-blocking call with a timeout set in the constructor + r = recv(d_socket, d_temp_buff, d_payload_size, 0); // get the entire payload or the what's available + + // If r > 0, round it down to a multiple of d_itemsize + // (If sender is broken, don't propagate problem) + if (r > 0) + r = (r/d_itemsize) * d_itemsize; + + // Check if there was a problem; forget it if the operation just timed out + if(r == -1) { + if( is_error(EAGAIN) ) { // handle non-blocking call timeout + #if SRC_VERBOSE + printf("UDP receive timed out\n"); + #endif + + if( d_wait ) { + // Allow boost thread interrupt, then try again + //boost::this_thread::interruption_point(); + //continue; + return 0; + } + else + return -1; + } + else { + report_error("udp_source/recv",NULL); + return -1; + } + } + else if(r==0) { + if(d_eof) { + // zero-length packet interpreted as EOF + + #if SNK_VERBOSE + printf("\tzero-length packet received; returning EOF\n"); + #endif + + return -1; + } + else{ + // do we need to allow boost thread interrupt? + boost::this_thread::interruption_point(); + continue; + } + } + else { + // Calculate the number of bytes we can take from the buffer in this call + nbytes = std::min(r, total_bytes-bytes_received); + + // adjust the total number of bytes we have to round down to nearest integer of an itemsize + nbytes -= ((bytes_received+nbytes) % d_itemsize); + + // copy the number of bytes we want to look at here + memcpy(out, d_temp_buff, nbytes); + + d_residual = r - nbytes; // save the number of bytes stored + d_temp_offset=nbytes; // reset buffer index + + // keep track of the total number of bytes received + bytes_received += nbytes; + + // increment the pointer + out += nbytes; + + // Immediately return when data comes in + break; + } + + #if SNK_VERBOSE + printf("\tbytes received: %d bytes (nbytes: %d)\n", bytes, nbytes); + #endif + } + + #if SRC_VERBOSE + printf("Total Bytes Received: %d (bytes_received / noutput_items = %d / %d)\n", + bytes_received, bytes_received, noutput_items); + #endif + + // bytes_received is already set to some integer multiple of itemsize + return bytes_received/d_itemsize; +} + +// Return port number of d_socket +int gr_udp_source::get_port(void) +{ + sockaddr_in name; + socklen_t len = sizeof(name); + int ret = getsockname( d_socket, (sockaddr*)&name, &len ); + if( ret ) { + report_error("gr_udp_source/getsockname",NULL); + return -1; + } + return ntohs(name.sin_port); +} diff --git a/gnuradio-core/src/lib/io/gr_udp_source.h b/gnuradio-core/src/lib/io/gr_udp_source.h new file mode 100644 index 000000000..56dcb3c0a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_UDP_SOURCE_H +#define INCLUDED_GR_UDP_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> + +class gr_udp_source; +typedef boost::shared_ptr<gr_udp_source> gr_udp_source_sptr; + +GR_CORE_API gr_udp_source_sptr gr_make_udp_source(size_t itemsize, const char *host, + unsigned short port, + int payload_size=1472, + bool eof=true, bool wait=true); + +/*! + * \brief Read stream from an UDP socket. + * \ingroup source_blk + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; can be + * NULL, None, or "0.0.0.0" to allow reading from any + * interface on the host + * \param port The port number on which to receive data; use 0 to + * have the system assign an unused port number + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Interpret zero-length packet as EOF (default: true) + * \param wait Wait for data if not immediately available + * (default: true) + * +*/ + +class GR_CORE_API gr_udp_source : public gr_sync_block +{ + friend GR_CORE_API gr_udp_source_sptr gr_make_udp_source(size_t itemsize, + const char *host, + unsigned short port, + int payload_size, + bool eof, bool wait); + + private: + size_t d_itemsize; + int d_payload_size; // maximum transmission unit (packet length) + bool d_eof; // zero-length packet is EOF + bool d_wait; // wait if data if not immediately available + int d_socket; // handle to socket + char *d_temp_buff; // hold buffer between calls + ssize_t d_residual; // hold information about number of bytes stored in the temp buffer + size_t d_temp_offset; // point to temp buffer location offset + + protected: + /*! + * \brief UDP Source Constructor + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; can be + * NULL, None, or "0.0.0.0" to allow reading from any + * interface on the host + * \param port The port number on which to receive data; use 0 to + * have the system assign an unused port number + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Interpret zero-length packet as EOF (default: true) + * \param wait Wait for data if not immediately available + * (default: true) + */ + gr_udp_source(size_t itemsize, const char *host, unsigned short port, + int payload_size, bool eof, bool wait); + + public: + ~gr_udp_source(); + + /*! \brief return the PAYLOAD_SIZE of the socket */ + int payload_size() { return d_payload_size; } + + /*! \brief return the port number of the socket */ + int get_port(); + + // should we export anything else? + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_UDP_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_source.i b/gnuradio-core/src/lib/io/gr_udp_source.i new file mode 100644 index 000000000..18823a356 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,udp_source) + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *host, + unsigned short port, int payload_size=1472, + bool eof=true, bool wait=true) throw (std::runtime_error); + +class gr_udp_source : public gr_sync_block +{ + protected: + gr_udp_source (size_t itemsize, const char *host, + unsigned short port, int payload_size, bool eof, bool wait) throw (std::runtime_error); + + public: + ~gr_udp_source (); + + int payload_size() { return d_payload_size; } + int get_port(); +}; diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.cc b/gnuradio-core/src/lib/io/gr_wavfile_sink.cc new file mode 100644 index 000000000..8526032f6 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.cc @@ -0,0 +1,280 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_wavfile_sink.h> +#include <gr_io_signature.h> +#include <gri_wavfile.h> +#include <stdexcept> +#include <climits> +#include <cstring> +#include <cmath> +#include <fcntl.h> +#include <gruel/thread.h> +#include <boost/math/special_functions/round.hpp> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_wavfile_sink_sptr +gr_make_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) +{ + return gnuradio::get_initial_sptr(new gr_wavfile_sink (filename, + n_channels, + sample_rate, + bits_per_sample)); +} + +gr_wavfile_sink::gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) + : gr_sync_block ("wavfile_sink", + gr_make_io_signature(1, n_channels, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_sample_rate(sample_rate), d_nchans(n_channels), + d_fp(0), d_new_fp(0), d_updated(false) +{ + if (bits_per_sample != 8 && bits_per_sample != 16) { + throw std::runtime_error("Invalid bits per sample (supports 8 and 16)"); + } + d_bytes_per_sample = bits_per_sample / 8; + d_bytes_per_sample_new = d_bytes_per_sample; + + if (!open(filename)) { + throw std::runtime_error ("can't open file"); + } + + if (bits_per_sample == 8) { + d_max_sample_val = 0xFF; + d_min_sample_val = 0; + d_normalize_fac = d_max_sample_val/2; + d_normalize_shift = 1; + } else { + d_max_sample_val = 0x7FFF; + d_min_sample_val = -0x7FFF; + d_normalize_fac = d_max_sample_val; + d_normalize_shift = 0; + if (bits_per_sample != 16) { + fprintf(stderr, "Invalid bits per sample value requested, using 16"); + } + } +} + + +bool +gr_wavfile_sink::open(const char* filename) +{ + gruel::scoped_lock guard(d_mutex); + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename); + return false; + } + + if (d_new_fp) { // if we've already got a new one open, close it + fclose(d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, "wb")) == NULL) { + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + return false; + } + d_updated = true; + + if (!gri_wavheader_write(d_new_fp, + d_sample_rate, + d_nchans, + d_bytes_per_sample_new)) { + fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__); + exit(-1); + } + + return true; +} + + +void +gr_wavfile_sink::close() +{ + gruel::scoped_lock guard(d_mutex); + + if (!d_fp) + return; + + close_wav(); +} + +void gr_wavfile_sink::close_wav() +{ + unsigned int byte_count = d_sample_count * d_bytes_per_sample; + + gri_wavheader_complete(d_fp, byte_count); + + fclose(d_fp); + d_fp = NULL; +} + + +gr_wavfile_sink::~gr_wavfile_sink () +{ + if (d_new_fp) { + fclose(d_new_fp); + } + + close(); +} + + +int +gr_wavfile_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float **in = (float **) &input_items[0]; + int n_in_chans = input_items.size(); + + short int sample_buf_s; + + int nwritten; + + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this block + do_update(); // update: d_fp is reqd + if (!d_fp) // drop output on the floor + return noutput_items; + + for (nwritten = 0; nwritten < noutput_items; nwritten++) { + for (int chan = 0; chan < d_nchans; chan++) { + // Write zeros to channels which are in the WAV file + // but don't have any inputs here + if (chan < n_in_chans) { + sample_buf_s = + convert_to_short(in[chan][nwritten]); + } else { + sample_buf_s = 0; + } + + gri_wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); + + if (feof(d_fp) || ferror(d_fp)) { + fprintf(stderr, "[%s] file i/o error\n", __FILE__); + close(); + exit(-1); + } + d_sample_count++; + } + } + + return nwritten; +} + + +short int +gr_wavfile_sink::convert_to_short(float sample) +{ + sample += d_normalize_shift; + sample *= d_normalize_fac; + if (sample > d_max_sample_val) { + sample = d_max_sample_val; + } else if (sample < d_min_sample_val) { + sample = d_min_sample_val; + } + + return (short int) boost::math::iround(sample); +} + + +void +gr_wavfile_sink::set_bits_per_sample(int bits_per_sample) +{ + gruel::scoped_lock guard(d_mutex); + if (bits_per_sample == 8 || bits_per_sample == 16) { + d_bytes_per_sample_new = bits_per_sample / 8; + } +} + + +void +gr_wavfile_sink::set_sample_rate(unsigned int sample_rate) +{ + gruel::scoped_lock guard(d_mutex); + d_sample_rate = sample_rate; +} + + +void +gr_wavfile_sink::do_update() +{ + if (!d_updated) { + return; + } + + if (d_fp) { + close_wav(); + } + + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_sample_count = 0; + d_bytes_per_sample = d_bytes_per_sample_new; + + if (d_bytes_per_sample == 1) { + d_max_sample_val = UCHAR_MAX; + d_min_sample_val = 0; + d_normalize_fac = d_max_sample_val/2; + d_normalize_shift = 1; + } else if (d_bytes_per_sample == 2) { + d_max_sample_val = SHRT_MAX; + d_min_sample_val = SHRT_MIN; + d_normalize_fac = d_max_sample_val; + d_normalize_shift = 0; + } + + d_updated = false; +} diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.h b/gnuradio-core/src/lib/io/gr_wavfile_sink.h new file mode 100644 index 000000000..162151b7a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.h @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_WAVFILE_SINK_H +#define INCLUDED_GR_WAVFILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_file_sink_base.h> +#include <boost/thread.hpp> + +class gr_wavfile_sink; +typedef boost::shared_ptr<gr_wavfile_sink> gr_wavfile_sink_sptr; + +/* + * \p filename The .wav file to be opened + * \p n_channels Number of channels (2 = stereo or I/Q output) + * \p sample_rate Sample rate [S/s] + * \p bits_per_sample 16 or 8 bit, default is 16 + */ +GR_CORE_API gr_wavfile_sink_sptr +gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample = 16); + +/*! + * \brief Write stream to a Microsoft PCM (.wav) file. + * + * Values must be floats within [-1;1]. + * Check gr_make_wavfile_sink() for extra info. + * + * \ingroup sink_blk + */ +class GR_CORE_API gr_wavfile_sink : public gr_sync_block +{ +private: + friend GR_CORE_API gr_wavfile_sink_sptr gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample); + + gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample); + + unsigned d_sample_rate; + int d_nchans; + unsigned d_sample_count; + int d_bytes_per_sample; + int d_bytes_per_sample_new; + int d_max_sample_val; + int d_min_sample_val; + int d_normalize_shift; + int d_normalize_fac; + + FILE *d_fp; + FILE *d_new_fp; + bool d_updated; + boost::mutex d_mutex; + + /*! + * \brief Convert a sample value within [-1;+1] to a corresponding + * short integer value + */ + short convert_to_short(float sample); + + /*! + * \brief If any file changes have occurred, update now. This is called + * internally by work() and thus doesn't usually need to be called by + * hand. + */ + void do_update(); + + /*! + * \brief Writes information to the WAV header which is not available + * a-priori (chunk size etc.) and closes the file. Not thread-safe and + * assumes d_fp is a valid file pointer, should thus only be called by + * other methods. + */ + void close_wav(); + +public: + ~gr_wavfile_sink (); + + /*! + * \brief Opens a new file and writes a WAV header. Thread-safe. + */ + bool open(const char* filename); + + /*! + * \brief Closes the currently active file and completes the WAV + * header. Thread-safe. + */ + void close(); + + /*! + * \brief Set the sample rate. This will not affect the WAV file + * currently opened. Any following open() calls will use this new + * sample rate. + */ + void set_sample_rate(unsigned int sample_rate); + + /*! + * \brief Set bits per sample. This will not affect the WAV file + * currently opened (see set_sample_rate()). If the value is neither + * 8 nor 16, the call is ignored and the current value is kept. + */ + void set_bits_per_sample(int bits_per_sample); + + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_WAVFILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.i b/gnuradio-core/src/lib/io/gr_wavfile_sink.i new file mode 100644 index 000000000..48d1130bd --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.i @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,wavfile_sink); + +gr_wavfile_sink_sptr +gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample = 16) throw (std::runtime_error); + +class gr_wavfile_sink : public gr_sync_block +{ +protected: + gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) throw (std::runtime_error); + +public: + ~gr_wavfile_sink (); + bool open(const char* filename); + void close(); + void set_sample_rate(unsigned int sample_rate); + void set_bits_per_sample(int bits_per_sample); +}; + diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.cc b/gnuradio-core/src/lib/io/gr_wavfile_source.cc new file mode 100644 index 000000000..c8372868b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.cc @@ -0,0 +1,171 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_wavfile_source.h> +#include <gr_io_signature.h> +#include <gri_wavfile.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdexcept> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, bool repeat) +{ + return gnuradio::get_initial_sptr(new gr_wavfile_source (filename, repeat)); +} + + +gr_wavfile_source::gr_wavfile_source (const char *filename, bool repeat) + : gr_sync_block ("wavfile_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 2, sizeof(float))), + d_fp(NULL), d_repeat(repeat), + d_sample_rate(1), d_nchans(1), d_bytes_per_sample(2), d_first_sample_pos(0), + d_samples_per_chan(0), d_sample_idx(0) +{ + // we use "open" to use to the O_LARGEFILE flag + + int fd; + if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { + perror (filename); + throw std::runtime_error ("can't open file"); + } + + if ((d_fp = fdopen (fd, "rb")) == NULL) { + perror (filename); + throw std::runtime_error ("can't open file"); + } + + // Scan headers, check file validity + if (!gri_wavheader_parse(d_fp, + d_sample_rate, + d_nchans, + d_bytes_per_sample, + d_first_sample_pos, + d_samples_per_chan)) { + throw std::runtime_error("is not a valid wav file"); + } + + if (d_samples_per_chan == 0) { + throw std::runtime_error("WAV file does not contain any samples"); + } + + if (d_bytes_per_sample == 1) { + d_normalize_fac = 128; + d_normalize_shift = 1; + } else { + d_normalize_fac = 0x7FFF; + d_normalize_shift = 0; + } + + // Re-set the output signature + set_output_signature(gr_make_io_signature(1, d_nchans, sizeof(float))); +} + + +gr_wavfile_source::~gr_wavfile_source () +{ + fclose(d_fp); +} + + +int +gr_wavfile_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float **out = (float **) &output_items[0]; + int n_out_chans = output_items.size(); + + int i; + short sample; + + for (i = 0; i < noutput_items; i++) { + if (d_sample_idx >= d_samples_per_chan) { + if (!d_repeat) { + // if nothing was read at all, say we're done. + return i ? i : -1; + } + + if (fseek (d_fp, d_first_sample_pos, SEEK_SET) == -1) { + fprintf(stderr, "[%s] fseek failed\n", __FILE__); + exit(-1); + } + + d_sample_idx = 0; + } + + for (int chan = 0; chan < d_nchans; chan++) { + sample = gri_wav_read_sample(d_fp, d_bytes_per_sample); + + if (chan < n_out_chans) { + out[chan][i] = convert_to_float(sample); + } + } + + d_sample_idx++; + + // OK, EOF is not necessarily an error. But we're not going to + // deal with handling corrupt wav files, so if they give us any + // trouble they won't be processed. Serves them bloody right. + if (feof(d_fp) || ferror(d_fp)) { + if (i == 0) { + fprintf(stderr, "[%s] WAV file has corrupted header or i/o error\n", __FILE__); + return -1; + } + return i; + } + } + + return noutput_items; +} + + +float +gr_wavfile_source::convert_to_float(short int sample) +{ + float sample_out = (float) sample; + sample_out /= d_normalize_fac; + sample_out -= d_normalize_shift; + return sample_out; +} diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.h b/gnuradio-core/src/lib/io/gr_wavfile_source.h new file mode 100644 index 000000000..02e6e3678 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_WAVFILE_SOURCE_H +#define INCLUDED_GR_WAVFILE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <cstdio> // for FILE + +class gr_wavfile_source; +typedef boost::shared_ptr<gr_wavfile_source> gr_wavfile_source_sptr; + +GR_CORE_API gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, bool repeat = false); + +/*! + * \brief Read stream from a Microsoft PCM (.wav) file, output floats + * + * Unless otherwise called, values are within [-1;1]. + * Check gr_make_wavfile_source() for extra info. + * + * \ingroup source_blk + */ + +class GR_CORE_API gr_wavfile_source : public gr_sync_block +{ +private: + friend GR_CORE_API gr_wavfile_source_sptr gr_make_wavfile_source (const char *filename, + bool repeat); + gr_wavfile_source(const char *filename, bool repeat); + + FILE *d_fp; + bool d_repeat; + + unsigned d_sample_rate; + int d_nchans; + int d_bytes_per_sample; + int d_first_sample_pos; + unsigned d_samples_per_chan; + unsigned d_sample_idx; + int d_normalize_shift; + int d_normalize_fac; + + /*! + * \brief Convert an integer sample value to a float value within [-1;1] + */ + float convert_to_float(short int sample); + +public: + ~gr_wavfile_source (); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Read the sample rate as specified in the wav file header + */ + unsigned int sample_rate() const { return d_sample_rate; }; + + /*! + * \brief Return the number of bits per sample as specified in the wav + * file header. Only 8 or 16 bit are supported here. + */ + int bits_per_sample() const { return d_bytes_per_sample * 8; }; + + /*! + * \brief Return the number of channels in the wav file as specified in + * the wav file header. This is also the max number of outputs you can + * have. + */ + int channels() const { return d_nchans; }; +}; + +#endif /* INCLUDED_GR_WAVFILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.i b/gnuradio-core/src/lib/io/gr_wavfile_source.i new file mode 100644 index 000000000..5af2224f1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,wavfile_source); + +gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, + bool repeat = false) throw (std::runtime_error); + +class gr_wavfile_source : public gr_sync_block +{ +private: + gr_wavfile_source(const char *filename, + bool repeat) throw (std::runtime_error); + +public: + ~gr_wavfile_source(); + + unsigned int sample_rate(); + int bits_per_sample(); + int channels(); +}; + diff --git a/gnuradio-core/src/lib/io/gri_wavfile.cc b/gnuradio-core/src/lib/io/gri_wavfile.cc new file mode 100644 index 000000000..277e6b7b0 --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_wavfile.cc @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gri_wavfile.h> +#include <cstring> +#include <stdint.h> +#include <boost/detail/endian.hpp> //BOOST_BIG_ENDIAN + +# define VALID_COMPRESSION_TYPE 0x0001 + +// Basically, this is the opposite of htonx() and ntohx() +// Define host to/from worknet (little endian) short and long +#ifdef BOOST_BIG_ENDIAN + + static inline uint16_t __gri_wav_bs16(uint16_t x) + { + return (x>>8) | (x<<8); + } + + static inline uint32_t __gri_wav_bs32(uint32_t x) + { + return (uint32_t(__gri_wav_bs16(uint16_t(x&0xfffful)))<<16) | (__gri_wav_bs16(uint16_t(x>>16))); + } + + #define htowl(x) __gri_wav_bs32(x) + #define wtohl(x) __gri_wav_bs32(x) + #define htows(x) __gri_wav_bs16(x) + #define wtohs(x) __gri_wav_bs16(x) + +#else + + #define htowl(x) uint32_t(x) + #define wtohl(x) uint32_t(x) + #define htows(x) uint16_t(x) + #define wtohs(x) uint16_t(x) + +#endif // BOOST_BIG_ENDIAN + +// WAV files are always little-endian, so we need some byte switching macros +static inline uint32_t host_to_wav(uint32_t x) { return htowl(x); } +static inline uint16_t host_to_wav(uint16_t x) { return htows(x); } +static inline int16_t host_to_wav(int16_t x) { return htows(x); } +static inline uint32_t wav_to_host(uint32_t x) { return wtohl(x); } +static inline uint16_t wav_to_host(uint16_t x) { return wtohs(x); } +static inline int16_t wav_to_host(int16_t x) { return wtohs(x); } + +bool +gri_wavheader_parse(FILE *fp, + unsigned int &sample_rate_o, + int &nchans_o, + int &bytes_per_sample_o, + int &first_sample_pos_o, + unsigned int &samples_per_chan_o) +{ + // _o variables take return values + char str_buf[8] = {0}; + + uint32_t file_size; + uint32_t fmt_hdr_skip; + uint16_t compression_type; + uint16_t nchans; + uint32_t sample_rate; + uint32_t avg_bytes_per_sec; + uint16_t block_align; + uint16_t bits_per_sample; + uint32_t chunk_size; + + size_t fresult; + + fresult = fread(str_buf, 1, 4, fp); + if (fresult != 4 || strncmp(str_buf, "RIFF", 4) || feof(fp)) { + return false; + } + + fresult = fread(&file_size, 1, 4, fp); + + fresult = fread(str_buf, 1, 8, fp); + if (fresult != 8 || strncmp(str_buf, "WAVEfmt ", 8) || feof(fp)) { + return false; + } + + fresult = fread(&fmt_hdr_skip, 1, 4, fp); + + fresult = fread(&compression_type, 1, 2, fp); + if (wav_to_host(compression_type) != VALID_COMPRESSION_TYPE) { + return false; + } + + fresult = fread(&nchans, 1, 2, fp); + fresult = fread(&sample_rate, 1, 4, fp); + fresult = fread(&avg_bytes_per_sec, 1, 4, fp); + fresult = fread(&block_align, 1, 2, fp); + fresult = fread(&bits_per_sample, 1, 2, fp); + + if (ferror(fp)) { + return false; + } + + fmt_hdr_skip = wav_to_host(fmt_hdr_skip); + nchans = wav_to_host(nchans); + sample_rate = wav_to_host(sample_rate); + bits_per_sample = wav_to_host(bits_per_sample); + + if (bits_per_sample != 8 && bits_per_sample != 16) { + return false; + } + + fmt_hdr_skip -= 16; + if (fmt_hdr_skip) { + fseek(fp, fmt_hdr_skip, SEEK_CUR); + } + + // data chunk + fresult = fread(str_buf, 1, 4, fp); + if (strncmp(str_buf, "data", 4)) { + return false; + } + + fresult = fread(&chunk_size, 1, 4, fp); + if (ferror(fp)) { + return false; + } + + // More byte swapping + chunk_size = wav_to_host(chunk_size); + + // Output values + sample_rate_o = (unsigned) sample_rate; + nchans_o = (int) nchans; + bytes_per_sample_o = (int) (bits_per_sample / 8); + first_sample_pos_o = (int) ftell(fp); + samples_per_chan_o = (unsigned) (chunk_size / (bytes_per_sample_o * nchans)); + return true; +} + + +short int +gri_wav_read_sample(FILE *fp, int bytes_per_sample) +{ + int16_t buf_16bit; + + if(!fread(&buf_16bit, bytes_per_sample, 1, fp)) { + return 0; + } + if(bytes_per_sample == 1) { + return (short) buf_16bit; + } + return (short)wav_to_host(buf_16bit); +} + + +bool +gri_wavheader_write(FILE *fp, + unsigned int sample_rate, + int nchans, + int bytes_per_sample) +{ + const int header_len = 44; + char wav_hdr[header_len] = "RIFF\0\0\0\0WAVEfmt \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0data\0\0\0"; + uint16_t nchans_f = (uint16_t) nchans; + uint32_t sample_rate_f = (uint32_t) sample_rate; + uint16_t block_align = bytes_per_sample * nchans; + uint32_t avg_bytes = sample_rate * block_align; + uint16_t bits_per_sample = bytes_per_sample * 8; + + nchans_f = host_to_wav(nchans_f); + sample_rate_f = host_to_wav(sample_rate_f); + block_align = host_to_wav(block_align); + avg_bytes = host_to_wav(avg_bytes); + bits_per_sample = host_to_wav(bits_per_sample); + + wav_hdr[16] = 0x10; // no extra bytes + wav_hdr[20] = 0x01; // no compression + memcpy((void *) (wav_hdr + 22), (void *) &nchans_f, 2); + memcpy((void *) (wav_hdr + 24), (void *) &sample_rate_f, 4); + memcpy((void *) (wav_hdr + 28), (void *) &avg_bytes, 4); + memcpy((void *) (wav_hdr + 32), (void *) &block_align, 2); + memcpy((void *) (wav_hdr + 34), (void *) &bits_per_sample, 2); + + fwrite(&wav_hdr, 1, header_len, fp); + if (ferror(fp)) { + return false; + } + + return true; +} + + +void +gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample) +{ + void *data_ptr; + unsigned char buf_8bit; + int16_t buf_16bit; + + if (bytes_per_sample == 1) { + buf_8bit = (unsigned char) sample; + data_ptr = (void *) &buf_8bit; + } else { + buf_16bit = host_to_wav((int16_t) sample); + data_ptr = (void *) &buf_16bit; + } + + fwrite(data_ptr, 1, bytes_per_sample, fp); +} + + +bool +gri_wavheader_complete(FILE *fp, unsigned int byte_count) +{ + uint32_t chunk_size = (uint32_t) byte_count; + chunk_size = host_to_wav(chunk_size); + + fseek(fp, 40, SEEK_SET); + fwrite(&chunk_size, 1, 4, fp); + + chunk_size = (uint32_t) byte_count + 36; // fmt chunk and data header + chunk_size = host_to_wav(chunk_size); + fseek(fp, 4, SEEK_SET); + + fwrite(&chunk_size, 1, 4, fp); + + if (ferror(fp)) { + return false; + } + + return true; +} diff --git a/gnuradio-core/src/lib/io/gri_wavfile.h b/gnuradio-core/src/lib/io/gri_wavfile.h new file mode 100644 index 000000000..16280e34a --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_wavfile.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// This file stores all the RIFF file type knowledge for the gr_wavfile_* +// blocks. + +#include <gr_core_api.h> +#include <cstdio> + +/*! + * \brief Read signal information from a given WAV file. + * + * \param[in] fp File pointer to an opened, empty file. + * \param[out] sample_rate Stores the sample rate [S/s] + * \param[out] nchans Number of channels + * \param[out] bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding o + * 8 or 16 bit samples, respectively) + * \param[out] first_sample_pos Number of the first byte containing a sample. Use this + * with fseek() to jump from the end of the file to the + * first sample when in repeat mode. + * \param[out] samples_per_chan Number of samples per channel + * \return True on a successful read, false if the file could not be read or is + * not a valid WAV file. + */ +bool +gri_wavheader_parse(FILE *fp, + unsigned int &sample_rate, + int &nchans, + int &bytes_per_sample, + int &first_sample_pos, + unsigned int &samples_per_chan); + + +/*! + * \brief Read one sample from an open WAV file at the current position. + * + * Takes care of endianness. + */ +short int +gri_wav_read_sample(FILE *fp, int bytes_per_sample); + + +/*! + * \brief Write a valid RIFF file header + * + * Note: Some header values are kept blank because they're usually not known + * a-priori (file and chunk lengths). Use gri_wavheader_complete() to fill + * these in. + */ +bool +gri_wavheader_write(FILE *fp, + unsigned int sample_rate, + int nchans, + int bytes_per_sample); + +/*! + * \brief Write one sample to an open WAV file at the current position. + * + * Takes care of endianness. + */ +void +gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample); + + +/*! + * \brief Complete a WAV header + * + * Note: The stream position is changed during this function. If anything + * needs to be written to the WAV file after calling this function (which + * shouldn't happen), you need to fseek() to the end of the file (or + * whereever). + * + * \param[in] fp File pointer to an open WAV file with a blank header + * \param[in] byte_count Length of all samples written to the file in bytes. + */ +bool +gri_wavheader_complete(FILE *fp, unsigned int byte_count); diff --git a/gnuradio-core/src/lib/io/i2c.cc b/gnuradio-core/src/lib/io/i2c.cc new file mode 100644 index 000000000..02dd47b53 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.cc @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "i2c.h" + +i2c::~i2c () +{ + // NOP +} diff --git a/gnuradio-core/src/lib/io/i2c.h b/gnuradio-core/src/lib/io/i2c.h new file mode 100644 index 000000000..6b7f25a29 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_I2C_H +#define INCLUDED_I2C_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling i2c bus + */ +class GR_CORE_API i2c { + public: + + i2c () {} + virtual ~i2c (); + + //! \returns true iff successful + virtual bool write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int read (int addr, unsigned char *buf, int max_bytes) = 0; +}; + +#endif /* INCLUDED_I2C_H */ + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.cc b/gnuradio-core/src/lib/io/i2c_bbio.cc new file mode 100644 index 000000000..ddd00290d --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.cc @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "i2c_bbio.h" + +i2c_bbio::~i2c_bbio () +{ + // NOP +} + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.h b/gnuradio-core/src/lib/io/i2c_bbio.h new file mode 100644 index 000000000..6bf47b9cd --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_H +#define INCLUDED_I2C_BBIO_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c_bbio; +typedef boost::shared_ptr<i2c_bbio> i2c_bbio_sptr; + + +/*! + * \brief abstract class that implements bit banging i/o for i2c bus. + * \ingroup base + */ +class GR_CORE_API i2c_bbio { + public: + + i2c_bbio () {} + virtual ~i2c_bbio (); + + virtual void set_scl (bool state) = 0; + virtual void set_sda (bool state) = 0; + virtual bool get_sda () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +#endif /* INCLUDED_I2C_BBIO_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.cc b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc new file mode 100644 index 000000000..382bb6b37 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "i2c_bbio_pp.h" +#include "microtune_eval_board_defs.h" + +i2c_bbio_pp::i2c_bbio_pp (ppio_sptr pp) +{ + d_pp = pp; + d_pp->lock (); + d_pp->write_control (d_pp->read_control () & ~UT_CP_MUST_BE_ZERO); // output, no interrupts + d_pp->unlock (); +} + +i2c_bbio_sptr +make_i2c_bbio_pp (ppio_sptr pp) +{ + return i2c_bbio_sptr (new i2c_bbio_pp (pp)); +} + +void +i2c_bbio_pp::set_scl (bool state) +{ + int r = d_pp->read_control(); + + if (!state){ // active low + d_pp->write_control (r | UT_CP_TUNER_SCL); + } + else { + d_pp->write_control (r & ~UT_CP_TUNER_SCL); + } + d_pp->read_control (); // use for 1us delay + d_pp->read_control (); // use for 1us delay +} + +void +i2c_bbio_pp::set_sda (bool state) +{ + int r = d_pp->read_data (); + + if (!state){ // active low + d_pp->write_data (r | UT_DP_TUNER_SDA_OUT); + } + else { + d_pp->write_data (r & ~UT_DP_TUNER_SDA_OUT); + } + d_pp->read_data (); // use for 1us delay + d_pp->read_data (); // use for 1us delay +} + +bool +i2c_bbio_pp::get_sda () +{ + int r = d_pp->read_status (); + return (r & UT_SP_TUNER_SDA_IN) == 0; // eval board has an inverter on it +} + +void +i2c_bbio_pp::lock () +{ + d_pp->lock (); +} + +void +i2c_bbio_pp::unlock () +{ + d_pp->unlock (); +} diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.h b/gnuradio-core/src/lib/io/i2c_bbio_pp.h new file mode 100644 index 000000000..2391bc1fc --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_PP_H +#define INCLUDED_I2C_BBIO_PP_H + +#include <gr_core_api.h> +#include "i2c_bbio.h" +#include "ppio.h" + +/*! + * \brief concrete class that bit bangs eval board i2c bus using parallel port + * + * \ingroup base + * This class talks to the i2c bus on the microtune eval board using + * the parallel port. This works for both the 4937 and 4702 boards. + */ +class GR_CORE_API i2c_bbio_pp : public i2c_bbio { + friend GR_CORE_API i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + i2c_bbio_pp (ppio_sptr pp); + + public: + + virtual void set_scl (bool state); + virtual void set_sda (bool state); + virtual bool get_sda (); + + virtual void lock (); + virtual void unlock (); + + private: + ppio_sptr d_pp; +}; + +GR_CORE_API i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + + +#endif /* INCLUDED_I2C_BBIO_PP_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.cc b/gnuradio-core/src/lib/io/i2c_bitbang.cc new file mode 100644 index 000000000..eb801c68f --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "i2c_bitbang.h" + +i2c_bitbang::i2c_bitbang (i2c_bbio_sptr io) +{ + d_io = io; + d_io->lock (); + + stop (); // get bus in known state + + d_io->unlock (); +} + +i2c_sptr +make_i2c_bitbang (i2c_bbio_sptr io) +{ + return i2c_sptr (new i2c_bitbang (io)); +} + + +// start: +// entry: SCL = 1, SDA = 1 +// exit: SCL = 0, SDA = 0 + +void +i2c_bitbang::start () +{ + set_sda (1); + set_scl (1); + set_sda (0); // SDA high -> low while SCL high + set_scl (0); +} + + +// stop: +// entry: SCL = X, SDA = X +// exit: SCL = 1, SDA = 1 + +void +i2c_bitbang::stop () +{ + set_scl (0); + set_sda (0); + set_scl (1); + set_sda (1); // SDA low -> high while SCL high +} + + +// write_bit: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = X + +void +i2c_bitbang::write_bit (bool bit) +{ + set_sda (bit); + set_scl (1); + set_scl (0); +} + + +// write_byte: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = 1 + +bool +i2c_bitbang::write_byte (char t) +{ + int i; + bool ack_bit; + + for (i = 0; i < 8; i++){ + write_bit (t & 0x80); + t <<= 1; + } + + // clock #9. This is the ACK bit. + + set_sda (1); // tristate SDA + set_scl (1); + ack_bit = get_sda (); // slave should pull SDA line low + set_scl (0); + + return ack_bit == 0; +} + + +// write: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +bool +i2c_bitbang::write (int addr, const unsigned char *buf, int nbytes) +{ + bool ok = true; + + d_io->lock (); + start (); + ok = write_byte ((addr << 1) | 0); // addr plus "read opcode" + + for (int i = 0; i < nbytes; i++) + ok &= write_byte (buf[i]); + + stop (); + d_io->unlock (); + return ok; +} + + +// read: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +int +i2c_bitbang::read (int addr, unsigned char *buf, int max_bytes) +{ + d_io->lock (); + + // FIXME + + d_io->unlock (); + return -1; +} diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.h b/gnuradio-core/src/lib/io/i2c_bitbang.h new file mode 100644 index 000000000..1d6fe5044 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_I2C_BITBANG_H +#define INCLUDED_I2C_BITBANG_H + +#include <gr_core_api.h> +#include <i2c.h> +#include <i2c_bbio.h> + +/*! + * \brief class for controlling i2c bus + * \ingroup base + */ +class GR_CORE_API i2c_bitbang : public i2c { + friend GR_CORE_API i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + i2c_bitbang (i2c_bbio_sptr io); + + public: + ~i2c_bitbang () {} + + //! \returns true iff successful + bool write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + int read (int addr, unsigned char *buf, int max_bytes); + + +private: + void start (); + void stop (); + void write_bit (bool bit); + bool write_byte (char byte); + + void set_sda (bool bit) { d_io->set_sda (bit); } + void set_scl (bool bit) { d_io->set_scl (bit); } + bool get_sda () { return d_io->get_sda (); } + + i2c_bbio_sptr d_io; +}; + +GR_CORE_API i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + +#endif /* INCLUDED_I2C_BITBANG_H */ + + diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i new file mode 100644 index 000000000..e2de4eb97 --- /dev/null +++ b/gnuradio-core/src/lib/io/io.i @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 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 <gr_file_sink.h> +#include <gr_file_source.h> +#include <gr_file_descriptor_sink.h> +#include <gr_file_descriptor_source.h> +#include <gr_histo_sink_f.h> +#include <microtune_4702_eval_board.h> +#include <microtune_4937_eval_board.h> +#include <sdr_1000.h> +#include <gr_oscope_sink_x.h> +#include <gr_oscope_sink_f.h> +#include <ppio.h> +#include <gr_message_source.h> +#include <gr_message_burst_source.h> +#include <gr_message_sink.h> +#include <gr_udp_sink.h> +#include <gr_udp_source.h> +#include <gr_wavfile_sink.h> +#include <gr_wavfile_source.h> +#include <gr_tagged_file_sink.h> +#include <gr_pdu_to_tagged_stream.h> +#include <gr_tagged_stream_to_pdu.h> +#include <gr_message_debug.h> +#include <gr_pdu.h> +#include <gr_tuntap_pdu.h> +#include <gr_socket_pdu.h> +%} + +%include "gr_file_sink_base.i" +%include "gr_file_sink.i" +%include "gr_file_source.i" +%include "gr_file_descriptor_sink.i" +%include "gr_file_descriptor_source.i" +%include "gr_histo_sink.i" +%include "microtune_xxxx_eval_board.i" +%include "microtune_4702_eval_board.i" +%include "microtune_4937_eval_board.i" +%include "sdr_1000.i" +%include "gr_oscope_sink.i" +%include "ppio.i" +%include "gr_message_source.i" +%include "gr_message_burst_source.i" +%include "gr_message_sink.i" +%include "gr_udp_sink.i" +%include "gr_udp_source.i" +%include "gr_wavfile_sink.i" +%include "gr_wavfile_source.i" +%include "gr_tagged_file_sink.i" +%include "gr_pdu_to_tagged_stream.i" +%include "gr_tagged_stream_to_pdu.i" +%include "gr_message_debug.i" +%include "gr_pdu.i" +%include "gr_tuntap_pdu.i" +%include "gr_socket_pdu.i" + + diff --git a/gnuradio-core/src/lib/io/microtune_4702.cc b/gnuradio-core/src/lib/io/microtune_4702.cc new file mode 100644 index 000000000..3ec072d51 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.cc @@ -0,0 +1,183 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "microtune_4702.h" +#include <stdlib.h> +#include <stdio.h> +#include "i2c.h" + +static const double FIRST_IF = 36.00e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 174e6; +static const double UHF_takeover = 470e6; + +static int PLL_I2C_ADDR = 0x60; + +static unsigned char +control_byte_1 (bool prescaler, int reference_divisor) +{ + int c = 0x80; + //Note: Last two divider bits (bits 2 and 3 of this byte) determined later + if (prescaler) + c |= 0x10; + + switch (reference_divisor){ + case 2: + c |= 0x00; break; + case 4: + c |= 0x01; break; + case 8: + c |= 0x02; break; + case 16: + c |= 0x03; break; + case 32: + c |= 0x04; break; + case 64: + c |= 0x05; break; + case 128: + c |= 0x06; break; + case 256: + c |= 0x07; break; + case 24: + c |= 0x08; break; + case 5: + c |= 0x09; break; + case 10: + c |= 0x0A; break; + case 20: + c |= 0x0B; break; + case 40: + c |= 0x0C; break; + case 80: + c |= 0x0D; break; + case 160: + c |= 0x0E; break; + case 320: + c |= 0x0F; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0x8E; + + else if (target_freq < UHF_takeover){ // VHF high + c = 0x05; + if (target_freq < 390e6) + c |= 0x40; + else + c |= 0x80; + } + else { // UHF + c = 0x03; + if (target_freq < 750e6) + c |= 0x80; + else + c |= 0xC0; + } + + return c; +} + + +microtune_4702::microtune_4702 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 320; + d_prescaler = false; +} + +microtune_4702::~microtune_4702 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4702::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + FIRST_IF; + + double f_ref = 4e6 / d_reference_divider; + + //int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + + long int divisor = (long int) (target_f_osc / f_ref); + double actual_freq = (f_ref * divisor) - FIRST_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x1ffff) != 0) // >17 bit divisor + return false; + + buf[0] = ((divisor & 0x07f00) >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_prescaler, d_reference_divider); + buf[2] = buf[2] | (((divisor & 0x18000) >> 10) & 0xff); + buf[3] = control_byte_2 (target_freq); + + printf ("%x\n", PLL_I2C_ADDR); +//#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +//#endif + + return d_i2c->write (d_i2c_addr, buf, sizeof (buf)); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4702::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4702::get_output_freq () +{ + return FIRST_IF; +} diff --git a/gnuradio-core/src/lib/io/microtune_4702.h b/gnuradio-core/src/lib/io/microtune_4702.h new file mode 100644 index 000000000..ccc66db71 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_H +#define INCLUDED_MICROTUNE_4702_H + +#include <gr_core_api.h> +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4702 tuner module + * \ingroup hardware + */ + +class GR_CORE_API microtune_4702 : public microtune_xxxx { +public: + microtune_4702 (i2c_sptr i2c, int i2c_addr); + + virtual ~microtune_4702 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_prescaler; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4702_H */ + diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc new file mode 100644 index 000000000..f6c68726b --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "microtune_4702_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4702.h" + +static const int TUNER_I2C_ADDR = 0x60; + +microtune_4702_eval_board::microtune_4702_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4702 (d_i2c, TUNER_I2C_ADDR); +} + +microtune_4702_eval_board::~microtune_4702_eval_board () +{ + // default is OK +} + +static const float RF_MIN_V = 1.0; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4702_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.h b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h new file mode 100644 index 000000000..d866a4b94 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h @@ -0,0 +1,49 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4702_EVAL_BOARD_H + +#include <gr_core_api.h> +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4702 eval board + * \ingroup hardware + */ + +class GR_CORE_API microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + +#endif /* INCLUDED_MICROTUNE_4702_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.i b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i new file mode 100644 index 000000000..fc085a975 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_4937.cc b/gnuradio-core/src/lib/io/microtune_4937.cc new file mode 100644 index 000000000..72ddd4bb6 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.cc @@ -0,0 +1,146 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "microtune_4937.h" +#include <stdlib.h> +#include <stdio.h> +#include <i2c.h> + +static const double first_IF = 43.75e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 158e6; +static const double UHF_takeover = 464e6; + + +static unsigned char +control_byte_1 (bool fast_tuning_p, int reference_divisor) +{ + int c = 0x88; + + if (fast_tuning_p) + c |= 0x40; + + switch (reference_divisor){ + case 512: + c |= 0x3 << 1; break; + case 640: + c |= 0x0 << 1; break; + case 1024: + c |= 0x1 << 1; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq, bool shutdown_tx_PGA) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0xa0; + else if (target_freq < UHF_takeover) // VHF high + c = 0x90; + else // UHF + c = 0x30; + + if (shutdown_tx_PGA) + c |= 0x08; + + return c; +} + +microtune_4937::microtune_4937 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 640; + d_fast_tuning_p = false; +} + +microtune_4937::~microtune_4937 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4937::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + first_IF; + + double f_ref = 4e6 / d_reference_divider; + + // f_osc = f_ref * 8 * divisor + // divisor = f_osc / (f_ref * 8) + + int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + double actual_freq = (f_ref * 8 * divisor) - first_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x7fff) != 0) // 15 bit divisor + return false; + + buf[0] = (divisor >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_fast_tuning_p, d_reference_divider); + buf[3] = control_byte_2 (target_freq, true); + +#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +#endif + + return d_i2c->write (d_i2c_addr, buf, 4); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4937::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4937::get_output_freq () +{ + return 5.75e6; // 3x7702 +} diff --git a/gnuradio-core/src/lib/io/microtune_4937.h b/gnuradio-core/src/lib/io/microtune_4937.h new file mode 100644 index 000000000..be8657c95 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_H +#define INCLUDED_MICROTUNE_4937_H + +#include <gr_core_api.h> +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4937 tuner module + * \ingroup hardware + */ +class GR_CORE_API microtune_4937 : public microtune_xxxx { +public: + microtune_4937 (i2c_sptr i2c, int i2c_addr = 0x61); + virtual ~microtune_4937 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4937_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc new file mode 100644 index 000000000..a25b8addf --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "microtune_4937_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4937.h" + +static const int TUNER_I2C_ADDR = 0x61; + +microtune_4937_eval_board::microtune_4937_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4937 (d_i2c, TUNER_I2C_ADDR); + + // disable upstream amplifier + d_ppio->lock (); + int t = d_ppio->read_data (); + t &= ~(UT_DP_TX_ENABLE | UT_DP_TX_SDA | UT_DP_TX_SCL); + t |= UT_DP_TX_AS; + d_ppio->write_data (t); + d_ppio->unlock (); +} + +microtune_4937_eval_board::~microtune_4937_eval_board () +{ + // Default action is OK +} + + +static const float RF_MIN_V = 1.5; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4937_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.h b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h new file mode 100644 index 000000000..3abd9084e --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h @@ -0,0 +1,50 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4937_EVAL_BOARD_H + +#include <gr_core_api.h> +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4937 eval board + * \ingroup hardware + */ + +class GR_CORE_API microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + + +#endif /* INCLUDED_MICROTUNE_4937_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.i b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i new file mode 100644 index 000000000..e261416f7 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board.i b/gnuradio-core/src/lib/io/microtune_eval_board.i new file mode 100644 index 000000000..f77ef47b4 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board.i @@ -0,0 +1,95 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * SWIG interface defs for Microtune 4937 and eval board with Eric's daughterboard + */ + +/*! + * \brief abstract class for controlling microtune 4937 tuner module + */ +class microtune_4937 { +public: + microtune_4937 (); + + virtual ~microtune_4937 (); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + + private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes) = 0; + + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +/*! + * \brief concrete class for controlling microtune 4937 eval board attached to parallel port + */ +class microtune_eval_board : public microtune_4937 { +public: + microtune_eval_board (int which_pp = 0); + ~microtune_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + void set_AGC (float value_0_1000); + +private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board_defs.h b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h new file mode 100644 index 000000000..61c52364f --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h @@ -0,0 +1,71 @@ +/* -*-C-*- +******************************************************************************* +* +* File: microtune_eval_board_defs.h +* Description: defines for parallel port control of eval board +* +******************************************************************************* +*/ + +/* + * Copyright 2001 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _MICROTUNE_EVAL_BOARD_DEFS_H_ +#define _MICROTUNE_EVAL_BOARD_DEFS_H_ + +/* + * The Microtune 4937DI5 cable modem tuner eval board is controlled + * by bit banging the PC parallel port. This file defines the relevant + * bits. + * + * The parallel port has an 8 bit data port (output), + * an 8 bit control port (output) and + * an 8 bit status port (input). + * + * Not all bits of the control and status ports may be arbitrarily used. + */ + + +// parallel port data port constants (output) + +static const int UT_DP_TX_SDA = 0x01; // upstream control bus +static const int UT_DP_TX_SCL = 0x02; // upstream control bus +static const int UT_DP_TX_AS = 0x04; // upstream control bus +static const int UT_DP_TX_ENABLE = 0x08; // upstream h/w enable +// bits 4,5,6 not used +static const int UT_DP_TUNER_SDA_OUT = 0x80; // tuner i2c bus data + +// parallel port control port constants (output) + +static const int UT_CP_TUNER_SCL = 0x08; // tuner i2c bus clock +static const int UT_CP_MUST_BE_ZERO = 0xf0; // must be zero + +// parallel port status port constants (input) + +// bits 0,1,2 not used +static const int UT_SP_TUNER_SCL_LOOP_BACK= 0x08; // inverted SCL loop back +static const int UT_SP_SHOULD_BE_ZERO = 0x10; // reads as zero +static const int UT_SP_SHOULD_BE_ONE = 0x20; // reads as one +// bit 6 not used +static const int UT_SP_TUNER_SDA_IN = 0x80; + + +#endif /* _MICROTUNE_EVAL_BOARD_DEFS_H_ */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.cc b/gnuradio-core/src/lib/io/microtune_xxxx.cc new file mode 100644 index 000000000..3d55f534a --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.cc @@ -0,0 +1,41 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "microtune_xxxx.h" + +microtune_xxxx::~microtune_xxxx () +{ + // nop +} + +double +microtune_xxxx::set_RF_freq (double target_freq) +{ + double actual_freq = 0.0; + + if (set_RF_freq (target_freq, &actual_freq)) + return actual_freq; + + return 0.0; +} + + diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.h b/gnuradio-core/src/lib/io/microtune_xxxx.h new file mode 100644 index 000000000..b2646d39f --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_H +#define INCLUDED_MICROTUNE_XXXX_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling microtune {4937,4702} tuner modules + * \ingroup base + */ +class GR_CORE_API microtune_xxxx { +public: + microtune_xxxx () {} + virtual ~microtune_xxxx (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + virtual bool set_RF_freq (double freq, double *actual_freq) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + virtual bool pll_locked_p () = 0; + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + virtual double get_output_freq () = 0; + +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc new file mode 100644 index 000000000..35600ff06 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "microtune_xxxx_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "microtune_xxxx.h" +#include "ppio.h" +#include "i2c_bitbang.h" +#include "i2c_bbio_pp.h" +#include <cmath> + +static int AGC_DAC_I2C_ADDR = 0x2C; + +microtune_xxxx_eval_board::microtune_xxxx_eval_board (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_i2c = make_i2c_bitbang (make_i2c_bbio_pp (d_ppio)); + d_tuner = 0; +} + +microtune_xxxx_eval_board::~microtune_xxxx_eval_board () +{ + delete d_tuner; + d_tuner = 0; +} + + +//! is the eval board present? +bool +microtune_xxxx_eval_board::board_present_p () +{ + bool result = true; + d_ppio->lock (); + + int t = d_ppio->read_status (); + if ((t & UT_SP_SHOULD_BE_ZERO) != 0 + || (t & UT_SP_SHOULD_BE_ONE) != UT_SP_SHOULD_BE_ONE) + result = false; + + // could also see if SCL is looped back or not, but that seems like overkill + + d_ppio->unlock (); + return result; +} + +/* + * ---------------------------------------------------------------- + * AGC stuff + * + * We're using a MAX518 8-bit 5V dual dac for setting the AGC's + * ---------------------------------------------------------------- + */ +void +microtune_xxxx_eval_board::write_dac (int which, int value) +{ + unsigned char cmd[2]; + cmd[0] = which & 1; + cmd[1] = value; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +void +microtune_xxxx_eval_board::write_both_dacs (int value0, int value1) +{ + unsigned char cmd[4]; + cmd[0] = 0; + cmd[1] = value0; + cmd[2] = 1; + cmd[3] = value1; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +static int scale_volts (float volts) +{ + int n; + n = (int) rint (volts * (256 / 5.0)); + if (n < 0) + n = 0; + if (n > 255) + n = 255; + + return n; +} + +void +microtune_xxxx_eval_board::set_RF_AGC_voltage (float volts) +{ + write_dac (0, scale_volts (volts)); +} + +void +microtune_xxxx_eval_board::set_IF_AGC_voltage (float volts) +{ + write_dac (1, scale_volts (volts)); +} + +// delegate to tuner + +bool +microtune_xxxx_eval_board::set_RF_freq (double freq, double *actual_freq) +{ + return d_tuner->set_RF_freq (freq, actual_freq); +} + +double +microtune_xxxx_eval_board::set_RF_freq (double freq) +{ + return d_tuner->set_RF_freq (freq); +} + +bool +microtune_xxxx_eval_board::pll_locked_p () +{ + return d_tuner->pll_locked_p (); +} + +double +microtune_xxxx_eval_board::get_output_freq () +{ + return d_tuner->get_output_freq (); +} diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h new file mode 100644 index 000000000..7fd784ade --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h @@ -0,0 +1,98 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class microtune_xxxx; + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling microtune xxxx eval board + * \ingroup hardware + */ +class GR_CORE_API microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + +private: + void write_dac (int which, int value); + void write_both_dacs (int val0, int val1); + +protected: + ppio_sptr d_ppio; + i2c_sptr d_i2c; + microtune_xxxx *d_tuner; +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i new file mode 100644 index 000000000..8a8a59742 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); +}; diff --git a/gnuradio-core/src/lib/io/ppio.cc b/gnuradio-core/src/lib/io/ppio.cc new file mode 100644 index 000000000..a5edc539c --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.cc @@ -0,0 +1,39 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <ppio.h> +#include <ppio_ppdev.h> + +ppio::~ppio () +{ +} + +// Factory method. +// +// Right now, we've only got one subclass we like. If there were more, +// we'd instantiate the "right one" here. + +ppio_sptr +make_ppio (int which_pp) +{ + return make_ppio_ppdev (which_pp); +} diff --git a/gnuradio-core/src/lib/io/ppio.h b/gnuradio-core/src/lib/io/ppio.h new file mode 100644 index 000000000..d99f7bf79 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_PPIO_H +#define INCLUDED_PPIO_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + + +/*! + * \brief abstract class that provides low level access to parallel port bits + * \ingroup hardware + */ + +class GR_CORE_API ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +/*! + * \brief Factory method. + * + * Split out from class to make life easier for SWIG + */ + +GR_CORE_API ppio_sptr make_ppio (int which_pp); + + +#endif /* INCLUDED_PPIO_H */ + diff --git a/gnuradio-core/src/lib/io/ppio.i b/gnuradio-core/src/lib/io/ppio.i new file mode 100644 index 000000000..6b95dcf88 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.i @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + +%template(ppio_sptr) boost::shared_ptr<ppio>; + +/*! + * \brief abstract class that provides low level access to parallel port bits + */ + +class ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + + +ppio_sptr make_ppio (int which_pp); diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.cc b/gnuradio-core/src/lib/io/ppio_ppdev.cc new file mode 100644 index 000000000..f52845958 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.cc @@ -0,0 +1,321 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003,2004,2008 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ppio_ppdev.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <iostream> +#include <errno.h> +#include <stdio.h> +#include <stdexcept> +#if defined(HAVE_LINUX_PPDEV_H) +#include <sys/ioctl.h> +#include <linux/ppdev.h> +#include <linux/parport.h> +#include <sstream> +#elif defined(HAVE_DEV_PPBUS_PPI_H) +#include <sys/ioctl.h> +#include <dev/ppbus/ppi.h> +#include <dev/ppbus/ppbconf.h> +#include <sstream> +#else +// #warn "ppio_ppdev is not functional on this platform" +#endif + +// These control port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int CP_ACTIVE_LOW_BITS = 0x0B; + +// These status port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int SP_ACTIVE_LOW_BITS = 0x80; + +#if defined(HAVE_LINUX_PPDEV_H) + +// The real Linux code... + +ppio_ppdev::ppio_ppdev (int which) +{ + std::ostringstream filename; + filename << "/dev/parport" << which; + const char *c_filename = filename.str().c_str(); + + if ((d_fd = open (c_filename, O_RDWR)) < 0){ + int my_errno = errno; + perror (c_filename); + if (my_errno == ENOENT){ + std::cerr << "Does the device file " << c_filename << " exist?\n"; + std::cerr << "If not, as root execute: \n"; + std::cerr << " # mknod " << c_filename << " c 99 0\n"; + std::cerr << " # chmod 666 " << c_filename << std::endl; + } + throw std::runtime_error ("open"); + } + + int mode = IEEE1284_MODE_COMPAT; + if (ioctl (d_fd, PPSETMODE, &mode) != 0){ + perror ("ppio_ppdev: PPSETMODE"); + close (d_fd); + throw std::runtime_error ("PPSETMODE"); + } +} + +ppio_ppdev::~ppio_ppdev () +{ + close (d_fd); +} + + +void +ppio_ppdev::write_data (unsigned char v) +{ + if (ioctl (d_fd, PPWDATA, &v) != 0){ + perror ("ppio_ppdev: PPWDATA"); + throw std::runtime_error ("PPWDATA"); + } +} + +unsigned char +ppio_ppdev::read_data () +{ + unsigned char v; + + if (ioctl (d_fd, PPRDATA, &v) != 0){ + perror ("ppio_ppdev: PPRDATA"); + throw std::runtime_error ("PPRDATA"); + } + return v; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ + unsigned char ctrl = v ^ CP_ACTIVE_LOW_BITS; + if (ioctl (d_fd, PPWCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPWCONTROL"); + throw std::runtime_error ("PPWCONTROL"); + } +} + +unsigned char +ppio_ppdev::read_control () +{ + unsigned char ctrl; + if (ioctl (d_fd, PPRCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPRCONTROL"); + throw std::runtime_error ("PPRCONTROL"); + } + + return ctrl ^ CP_ACTIVE_LOW_BITS; +} + +unsigned char +ppio_ppdev::read_status () +{ + unsigned char status; + if (ioctl (d_fd, PPRSTATUS, &status) != 0){ + perror ("ppio_ppdev: PPRSTATUS"); + throw std::runtime_error ("PPRSTATUS"); + } + + return status ^ SP_ACTIVE_LOW_BITS; +} + +void +ppio_ppdev::lock () +{ + if (ioctl (d_fd, PPCLAIM) != 0){ + perror ("ppio_ppdev: PPCLAIM"); + throw std::runtime_error ("PPCLAIM"); + } +} + +void +ppio_ppdev::unlock () +{ + if (ioctl (d_fd, PPRELEASE) != 0){ + perror ("ppio_ppdev: PPRELEASE"); + throw std::runtime_error ("PPRELEASE"); + } +} + +#elif defined(HAVE_DEV_PPBUS_PPI_H) + +// The real FreeBSD code... (Could work on other BSDs as well) + +ppio_ppdev::ppio_ppdev (int which) +{ + std::ostringstream filename; + filename << "/dev/ppi" << which; + const char *c_filename = filename.str().c_str(); + if ((d_fd = open (c_filename, O_RDWR)) < 0){ + int my_errno = errno; + perror (c_filename); + throw std::runtime_error ("open"); + } + +#if 0 + int mode = IEEE1284_MODE_COMPAT; + if (ioctl (d_fd, PPSETMODE, &mode) != 0){ + perror ("ppio_ppdev: PPSETMODE"); + close (d_fd); + throw std::runtime_error ("PPSETMODE"); + } +#endif +} + +ppio_ppdev::~ppio_ppdev () +{ + close (d_fd); +} + + +void +ppio_ppdev::write_data (unsigned char v) +{ + if (ioctl (d_fd, PPISDATA, &v) != 0){ + perror ("ppio_ppdev: PPISDATA"); + throw std::runtime_error ("PPISDATA"); + } +} + +unsigned char +ppio_ppdev::read_data () +{ + unsigned char v; + + if (ioctl (d_fd, PPIGDATA, &v) != 0){ + perror ("ppio_ppdev: PPIGDATA"); + throw std::runtime_error ("PPIGDATA"); + } + return v; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ + unsigned char ctrl = v ^ CP_ACTIVE_LOW_BITS; + if (ioctl (d_fd, PPISCTRL, &ctrl) != 0){ + perror ("ppio_ppdev: PPISCTRL"); + throw std::runtime_error ("PPISCTRL"); + } +} + +unsigned char +ppio_ppdev::read_control () +{ + unsigned char ctrl; + if (ioctl (d_fd, PPIGCTRL, &ctrl) != 0){ + perror ("ppio_ppdev: PPIGCTRL"); + throw std::runtime_error ("PPIGCTRL"); + } + + return ctrl ^ CP_ACTIVE_LOW_BITS; +} + +unsigned char +ppio_ppdev::read_status () +{ + unsigned char status; + if (ioctl (d_fd, PPIGSTATUS, &status) != 0){ + perror ("ppio_ppdev: PPIGSTATUS"); + throw std::runtime_error ("PPIGSTATUS"); + } + return status ^ SP_ACTIVE_LOW_BITS; +} + +void +ppio_ppdev::lock () +{ +} + +void +ppio_ppdev::unlock () +{ +} +#else +/* Apparently, non real code */ + +ppio_ppdev::ppio_ppdev (int which) +{ + std::cerr << "ppio_ppdev: Not implemented on this platform\n"; + throw std::runtime_error ("not implmeneted"); +} + +ppio_ppdev::~ppio_ppdev () +{ +} + +void +ppio_ppdev::write_data (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_data () +{ + return 0; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_control () +{ + return 0; +} + +unsigned char +ppio_ppdev::read_status () +{ + return 0; +} + +void +ppio_ppdev::lock () +{ +} + +void +ppio_ppdev::unlock () +{ +} + +#endif + +ppio_ppdev_sptr +make_ppio_ppdev (int which) +{ + return ppio_ppdev_sptr (new ppio_ppdev (which)); +} diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.h b/gnuradio-core/src/lib/io/ppio_ppdev.h new file mode 100644 index 000000000..1f86d7e04 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_PPIO_PPDEV_H +#define INCLUDED_PPIO_PPDEV_H + +#include <gr_core_api.h> +#include <ppio.h> + +class ppio_ppdev; +typedef boost::shared_ptr<ppio_ppdev> ppio_ppdev_sptr; + +/*! + * \brief access to parallel port bits using the linux ppdev interface + * \ingroup hardware + */ + +class GR_CORE_API ppio_ppdev : public ppio { + friend GR_CORE_API ppio_ppdev_sptr make_ppio_ppdev (int which = 0); + ppio_ppdev (int which = 0); + + public: + virtual ~ppio_ppdev (); + + virtual void write_data (unsigned char v); + virtual unsigned char read_data (); + virtual void write_control (unsigned char v); + virtual unsigned char read_control (); + virtual unsigned char read_status (); + + virtual void lock (); + virtual void unlock (); + + private: + int d_fd; +}; + +ppio_ppdev_sptr +make_ppio_ppdev (int which); + + +#endif /* INCLUDED_PPIO_PPDEV_H */ + diff --git a/gnuradio-core/src/lib/io/sdr_1000.cc b/gnuradio-core/src/lib/io/sdr_1000.cc new file mode 100644 index 000000000..a8c2555e0 --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.cc @@ -0,0 +1,65 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <sdr_1000.h> +#include <ppio.h> + +sdr_1000_base::sdr_1000_base (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_shadow[0] = 0; + d_shadow[1] = 0; + d_shadow[2] = 0; + d_shadow[3] = 0; + reset (); +} + +sdr_1000_base::~sdr_1000_base () +{ +} + +void +sdr_1000_base::reset () +{ + d_ppio->lock (); + d_ppio->write_control (0x0F); + d_ppio->unlock (); + write_latch (L_EXT, 0x00, 0xff); + write_latch (L_BAND, 0x00, 0xff); + write_latch (L_DDS0, 0x80, 0xff); // hold DDS in reset + write_latch (L_DDS1, 0x00, 0xff); +} + + +void +sdr_1000_base::write_latch (int which, int value, int mask) +{ + if (!(0 <= which && which <= 3)) + return; + + d_ppio->lock (); + d_shadow[which] = (d_shadow[which] & ~mask) | (value & mask); + d_ppio->write_data (d_shadow[which]); + d_ppio->write_control (0x0F ^ (1 << which)); + d_ppio->write_control (0x0F); + d_ppio->unlock (); +} diff --git a/gnuradio-core/src/lib/io/sdr_1000.h b/gnuradio-core/src/lib/io/sdr_1000.h new file mode 100644 index 000000000..c00608a3a --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.h @@ -0,0 +1,53 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SDR_1000_H +#define INCLUDED_SDR_1000_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + + +enum { L_EXT = 0, L_BAND = 1, L_DDS0 = 2, L_DDS1 = 3 }; + +/*! + * \brief Very low level interface to SDR 1000 xcvr hardware + * \sa sdr_1000.py for a higher level interface. + * \ingroup hardware + */ +class GR_CORE_API sdr_1000_base { + ppio_sptr d_ppio; + int d_shadow[4]; // shadow latches + +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; + +#endif /* INCLUDED_SDR_1000_H */ diff --git a/gnuradio-core/src/lib/io/sdr_1000.i b/gnuradio-core/src/lib/io/sdr_1000.i new file mode 100644 index 000000000..c9b1ef560 --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +const int L_EXT = 0; +const int L_BAND = 1; +const int L_DDS0 = 2; +const int L_DDS1 = 3; + +class sdr_1000_base { +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; |