/* -*- 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include /* * comedi_sink_s is untested because I don't own appropriate hardware. * Feedback is welcome! --SF */ static std::string default_device_name () { return "/dev/comedi0"; } // ---------------------------------------------------------------- comedi_sink_s_sptr comedi_make_sink_s (int sampling_freq, const std::string dev) { return comedi_sink_s_sptr (new comedi_sink_s (sampling_freq, dev)); } comedi_sink_s::comedi_sink_s (int sampling_freq, const std::string device_name) : gr_sync_block ("comedi_sink_s", gr_make_io_signature (0, 0, 0), gr_make_io_signature (0, 0, 0)), d_sampling_freq (sampling_freq), d_device_name (device_name.empty() ? default_device_name() : device_name), d_dev (0), d_subdevice (COMEDI_SUBD_AO), d_n_chan (1), // number of input channels d_map (0), d_buffer_size (0), d_buf_front (0), d_buf_back (0) { int aref=AREF_GROUND; int range=0; d_dev = comedi_open(d_device_name.c_str()); if (d_dev == 0){ comedi_perror(d_device_name.c_str()); throw std::runtime_error ("comedi_sink_s"); } unsigned int chanlist[256]; for(int i=0; i d_n_chan) throw std::runtime_error ("comedi_sink_s"); return true; } comedi_sink_s::~comedi_sink_s () { if (d_map) { munmap(d_map, d_buffer_size); d_map = 0; } comedi_close(d_dev); } int comedi_sink_s::work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { int ret; int work_left = noutput_items * sizeof(sampl_t) * d_n_chan; sampl_t *pbuf = (sampl_t*)d_map; do { do { ret = comedi_get_buffer_contents(d_dev,d_subdevice); if (ret < 0) bail ("comedi_get_buffer_contents", comedi_errno()); assert(ret % sizeof(sampl_t) == 0); assert(work_left % sizeof(sampl_t) == 0); ret = std::min(ret, work_left); d_buf_front += ret; assert(d_buffer_size%d_n_chan == 0); if (d_buf_front-d_buf_back > (unsigned)d_buffer_size) { d_buf_front+=d_buffer_size; d_buf_back +=d_buffer_size; } if(d_buf_front==d_buf_back){ usleep(1000000*std::min(work_left,d_buffer_size/2)/(d_sampling_freq*sizeof(sampl_t)*d_n_chan)); continue; } } while (d_buf_front==d_buf_back); for(unsigned i=d_buf_back/sizeof(sampl_t);i0); return noutput_items; } void comedi_sink_s::output_error_msg (const char *msg, int err) { fprintf (stderr, "comedi_sink_s[%s]: %s: %s\n", d_device_name.c_str(), msg, comedi_strerror(err)); } void comedi_sink_s::bail (const char *msg, int err) throw (std::runtime_error) { output_error_msg (msg, err); throw std::runtime_error ("comedi_sink_s"); }