/* 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