diff --git a/linux/iio/JackIIODriver.cpp b/linux/iio/JackIIODriver.cpp new file mode 100644 index 00000000..0bff9191 --- /dev/null +++ b/linux/iio/JackIIODriver.cpp @@ -0,0 +1,233 @@ +/* +Copyright (C) 2013 Matt Flax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackIIODriver.h" +#include "driver_interface.h" +#include "JackEngineControl.h" +#include "JackGraphManager.h" + +#include + +#define IIO_DEFAULT_CHIP "AD7476A" ///< The default IIO recording chip to look for. +#define IIO_DEFAULT_READ_FS 1.e6 ///< The default IIO sample rate for the default chip. +#define IIO_DEFAULT_PERIOD_SIZE 2048 ///< The default period size is in the ms range +#define IIO_DEFAULT_PERIOD_COUNT 2 ///< The default number of periods +#define IIO_DEFAULT_CAPUTURE_PORT_COUNT MAXINT ///< The default number of capture ports is exceedingly big, trimmed down to a realistic size in driver_initialize +//#define IIO_SAFETY_FACTOR 2./3. ///< The default safety factor, allow consumption of this fraction of the available DMA buffer before we don't allow the driver to continue. +#define IIO_SAFETY_FACTOR 1. ///< The default safety factor, allow consumption of this fraction of the available DMA buffer before we don't allow the driver to continue. + +namespace Jack { + +int JackIIODriver::Attach() { + //cout<<"JackIIODriver::Attach\n"; + JackAudioDriver::SetSampleRate((jack_nframes_t)IIO_DEFAULT_READ_FS); + + int ret; + if ((ret=iio.enable(true))!=NO_ERROR) { // start the DMA + iio.close(); + return ret; + } + return JackAudioDriver::Attach(); +} + +int JackIIODriver::Detach() { + //cout<<"JackIIODriver::Detach\n"; + iio.enable(false); // stop the DMA + return JackAudioDriver::Detach(); +} + +int JackIIODriver::Read() { + //cout<<"JackIIODriver::Read\n"; + + if (iio.getDeviceCnt()<1) { + jack_error("JackIIODriver:: No IIO devices are present "); + return -1; + } + uint devChCnt=iio[0].getChCnt(); // the number of channels per device + + jack_nframes_t nframes=data.rows()/devChCnt; + if (nframes != fEngineControl->fBufferSize) + jack_error("JackIIODriver::Read warning : Jack period size = %ld IIO period size = %ld", fEngineControl->fBufferSize, nframes); + +// cout<<"processing buffer size : "<fBufferSize<maxAvailChCnt) + jack_error("JackIIODriver::Read warning : Jack period size = %ld IIO period size = %ld", fEngineControl->fBufferSize, nframes); + + for (int i = 0; i < fCaptureChannels; i++) { + int col=i/devChCnt; // find the column and offset to read from + int rowOffset=i%devChCnt; + if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) { + jack_default_audio_sample_t *dest=GetInputBuffer(i); + + for (jack_nframes_t j=0; jdata; + + switch (param->character) { + case 'C': // we are specifying a new chip name + chipName = param->value.str; + break; + case 'i': // we are specifying the number of capture channels + inChCnt = param->value.ui; + break; + case 'p': + periodSize = param->value.ui; + break; + case 'n': + periodCount = param->value.ui; + break; + } + } + + // create the driver which contains the IIO class + Jack::JackIIODriver* iio_driver = new Jack::JackIIODriver("system", "iio_pcm", engine, table); + if (!iio_driver) { + jack_error("\nHave you run out of memory ? I tried to create the IIO driver in memory but failed!\n"); + return NULL; + } + + // interrogate the available iio devices searching for the chip name + if (iio_driver->iio.findDevicesByChipName(chipName)!=NO_ERROR) { // find all devices with a particular chip which are present. + jack_error("\nThe iio driver found no devices by the name %s\n", chipName.c_str()); + delete iio_driver; + return NULL; + } + + if (iio_driver->iio.getDeviceCnt()<1) { // If there are no devices found by that chip name, then indicate. + jack_error("\nThe iio driver found no devices by the name %s\n", chipName.c_str()); + delete iio_driver; + return NULL; + } + + iio_driver->iio.printInfo(); // print out detail about the devices which were found ... + + // if the available number of ports is less then the requested number, then restrict to the number of physical ports. + if (iio_driver->iio.getChCnt()iio.getChCnt(); + + // resize the data buffer column count to match the device count + int colCnt=(int)ceil((float)inChCnt/(float)iio_driver->iio[0].getChCnt()); // check whether we require less then the available number of channels + int ret=iio_driver->iio.getReadArray(periodSize, iio_driver->data); // resize the array to be able to read enough memory + if (ret!=NO_ERROR) { + jack_error("iio::getReadArray couldn't create the data buffer, indicating the problem."); + delete iio_driver; + return NULL; + } + if (iio_driver->data.cols()>colCnt) // resize the data columns to match the specified number of columns (channels / channels per device) + iio_driver->data.resize(iio_driver->data.rows(), colCnt); + + ret=iio_driver->iio.open(periodCount, periodSize); // try to open all IIO devices + if (ret!=NO_ERROR) + delete iio_driver; + return NULL; + + Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(iio_driver); + if (threaded_driver) { + bool capture=true, playback=false, monitor=false; + int outChCnt=0; + jack_nframes_t inputLatency = periodSize*periodCount, outputLatency=0; + // Special open for OSS driver... + if (iio_driver->Open(periodSize, periodCount, capture, playback, inChCnt, outChCnt, monitor, "iio:device", "iio:device", inputLatency, outputLatency)!=0) { + delete threaded_driver; + threaded_driver=NULL; + } + } else + jack_error("\nHave you run out of memory ? I tried to create Jack's standard threaded driver in memory but failed! The good news is that you had enough memory to create the IIO driver.\n"); + + if (!threaded_driver) { // handle the case that the threaded_driver was not created succ. + delete iio_driver; + iio_driver=NULL; + } + + return threaded_driver; +} + +#ifdef __cplusplus +} +#endif diff --git a/linux/iio/JackIIODriver.h b/linux/iio/JackIIODriver.h new file mode 100644 index 00000000..8557bcac --- /dev/null +++ b/linux/iio/JackIIODriver.h @@ -0,0 +1,69 @@ +/* +Copyright (C) 2013 Matt Flax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef JACKIIODRIVER_H +#define JACKIIODRIVER_H + +#include "JackAudioDriver.h" +#include "JackThreadedDriver.h" + +#include + +namespace Jack { + +/** The Linux Industrial IO (IIO) subsystem driver for Jack. +Currently this driver only supports capture. +*/ +class JackIIODriver : public JackAudioDriver { + +public: + IIOMMap iio; ///< The actual IIO devices + Eigen::Array data; ///< When we grab a mmapped buffer, store it here. + + /** Constructor + */ + JackIIODriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) : JackAudioDriver(name, alias, engine, table) { + } + + /** Destructor + */ + virtual ~JackIIODriver() { + } + +// virtual int Process(){ +//// cout<<"JackIIODriver::Process\n"; +// return JackAudioDriver::Process(); +// } +// + virtual int Attach(); ///< Enables the IIO system. + + virtual int Detach(); ///< Disables the IIO system. + + virtual int Read(); ///< Read from the IIO sysetm and load the jack buffers + + virtual int Write(); ///< Not implemented. + + virtual int SetBufferSize(jack_nframes_t buffer_size){ + cout<<"JackIIODriver::SetBufferSize("<