⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comedi_sink_s.cc

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 CC
字号:
/* -*- 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 <sys/mman.h>#include <comedi_sink_s.h>#include <gr_io_signature.h>#include <stdio.h>#include <errno.h>#include <iostream>#include <stdexcept>#include <gri_comedi.h>/* * 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_sptrcomedi_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; i++){    chanlist[i]=CR_PACK(i,range,aref);  }  comedi_cmd cmd;  int ret;  ret = comedi_get_cmd_generic_timed(d_dev,d_subdevice,&cmd,(unsigned int)(1e9/sampling_freq));  if(ret<0)    bail ("comedi_get_cmd_generic_timed", comedi_errno());  // TODO: check period_ns is not to far off sampling_freq  d_buffer_size = comedi_get_buffer_size(d_dev, d_subdevice);  if (d_buffer_size <= 0)    bail ("comedi_get_buffer_size", comedi_errno());  d_map = mmap(NULL,d_buffer_size,PROT_WRITE,MAP_SHARED,comedi_fileno(d_dev),0);  if (d_map == MAP_FAILED)    bail ("mmap", errno);  cmd.chanlist = chanlist;  cmd.chanlist_len = d_n_chan;  cmd.scan_end_arg = d_n_chan;  cmd.stop_src=TRIG_NONE;  cmd.stop_arg=0;  /* comedi_command_test() tests a command to see if the   * trigger sources and arguments are valid for the subdevice.   * If a trigger source is invalid, it will be logically ANDed   * with valid values (trigger sources are actually bitmasks),   * which may or may not result in a valid trigger source.   * If an argument is invalid, it will be adjusted to the   * nearest valid value.  In this way, for many commands, you   * can test it multiple times until it passes.  Typically,   * if you can't get a valid command in two tests, the original   * command wasn't specified very well. */  ret = comedi_command_test(d_dev,&cmd);  if(ret<0)    bail ("comedi_command_test", comedi_errno());  ret = comedi_command_test(d_dev,&cmd);  if(ret<0)    bail ("comedi_command_test", comedi_errno());  /* start the command */  ret = comedi_command(d_dev,&cmd);  if(ret<0)    bail ("comedi_command", comedi_errno());  set_output_multiple (d_n_chan*sizeof(sampl_t));  assert(sizeof(sampl_t) == sizeof(short));  set_output_signature (gr_make_io_signature (1, 1, sizeof (sampl_t)));}boolcomedi_sink_s::check_topology (int ninputs, int noutputs){  if (ninputs > 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);}intcomedi_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);i<d_buf_front/sizeof(sampl_t);i++){      int chan = i%d_n_chan;      int i_idx = noutput_items-work_left/d_n_chan/sizeof(sampl_t)+(i-d_buf_back/sizeof(sampl_t))/d_n_chan;      pbuf[i%(d_buffer_size/sizeof(sampl_t))] = input_items[chan]==0 ? 0 :			(int)((short*)(input_items[chan]))[i_idx] + 32767;    }    // FIXME: how to tell comedi the buffer is *written* ?    ret = comedi_mark_buffer_read(d_dev,d_subdevice,d_buf_front-d_buf_back);    if(ret<0)      bail ("comedi_mark_buffer_read", comedi_errno());    work_left -= d_buf_front-d_buf_back;    d_buf_back = d_buf_front;  } while(work_left>0);  return noutput_items;}voidcomedi_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));}voidcomedi_sink_s::bail (const char *msg, int err) throw (std::runtime_error){  output_error_msg (msg, err);  throw std::runtime_error ("comedi_sink_s");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -