/* 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::Open(jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing, int inchannels, int outchannels, bool monitor, const char* capture_driver_name, const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency) { //cout<<"JackIIODriver::Open\n"; int ret=JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); if (ret!=NO_ERROR) // check whether the JackAudioDriver opened OK return ret; ret=iio.enable(true); // start the DMA return ret; } int JackIIODriver::Close() { //cout<<"JackIIODriver::Close\n"; iio.enable(false); // stop the DMA return JackAudioDriver::Close(); } 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; // This is left here for future debugging. // 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 capture ch. cnt = %ld IIO capture ch. cnt = %ld", fCaptureChannels, maxAvailChCnt); 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()); goto initError; } 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()); goto initError; } 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 colCnt=(int)ceil((float)inChCnt/(float)iio_driver->iio[0].getChCnt()); // check whether we require less then the available number of channels 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."); goto initError; } 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) goto initError; 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, (jack_nframes_t)fs, capture, playback, inChCnt, outChCnt, monitor, "iio:device", "iio:device", inputLatency, outputLatency)!=0) { delete threaded_driver; delete iio_driver; return 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"); return threaded_driver; initError: // error during intialisation, delete and return NULL delete iio_driver; return NULL; } #ifdef __cplusplus } #endif