From 95fe79650cf58e1b68f2925b240da412b6112ee3 Mon Sep 17 00:00:00 2001 From: hexameron Date: Sun, 17 May 2015 16:48:51 +0000 Subject: [PATCH] Basic MSI support. --- plugins/samplesource/v4l-msi/v4linput.cpp | 6 +-- plugins/samplesource/v4l-msi/v4lsource.cpp | 47 ++++++++++++---------- plugins/samplesource/v4l-msi/v4lthread.h | 5 ++- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/plugins/samplesource/v4l-msi/v4linput.cpp b/plugins/samplesource/v4l-msi/v4linput.cpp index 074c8f38b..b8e124a8b 100644 --- a/plugins/samplesource/v4l-msi/v4linput.cpp +++ b/plugins/samplesource/v4l-msi/v4linput.cpp @@ -122,7 +122,8 @@ const QString& V4LInput::getDeviceDescription() const int V4LInput::getSampleRate() const { - int result = SAMPLERATE / 4; + // The output rate is lower than the device rate + int result = SAMPLERATE / 2; return result; } @@ -153,8 +154,7 @@ void V4LInput::applySettings(const GeneralSettings& generalSettings, const Setti } if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) { - m_V4LThread->set_center_freq( (double)(generalSettings.m_centerFrequency - + (SAMPLERATE / 4) )); + m_V4LThread->set_center_freq( (double)generalSettings.m_centerFrequency ); } m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency; #if 0 diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index 0d4a5fd08..d918974f8 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -45,6 +45,7 @@ #define V4L2_PIX_FMT_SDR_U8 v4l2_fourcc('C', 'U', '0', '8') /* unsigned 8-bit Complex*/ #define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('C', 'U', '1', '6') /* unsigned 16-bit Complex*/ +#define V4L2_PIX_FMT_SDR_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* signed 14-bit Complex*/ #define CLEAR(x) memset(&(x), 0, sizeof(x)) @@ -78,9 +79,8 @@ V4LThread::OpenSource(const char *filename) return; } - pixelformat = V4L2_PIX_FMT_SDR_U8; - // RTLSDR has limited ioctls in 3.18, expect fail. - qCritical("Want Pixelformat : CU08"); + pixelformat = V4L2_PIX_FMT_SDR_CS14LE; + qCritical("Want Pixelformat : S14"); CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_SDR_CAPTURE; fmt.fmt.sdr.pixelformat = pixelformat; @@ -120,7 +120,7 @@ V4LThread::OpenSource(const char *filename) } set_sample_rate((double)SAMPLERATE); - set_center_freq( centerFreq + (SAMPLERATE / 4) ); + set_center_freq( (double)centerFreq ); // start streaming type = V4L2_BUF_TYPE_SDR_CAPTURE; xioctl(fd, VIDIOC_STREAMON, &type); @@ -151,7 +151,7 @@ V4LThread::set_sample_rate(double samp_rate) memset (&frequency, 0, sizeof(frequency)); frequency.tuner = 0; frequency.type = V4L2_TUNER_ADC; - frequency.frequency = samp_rate / 1; + frequency.frequency = samp_rate; xioctl(fd, VIDIOC_S_FREQUENCY, &frequency); @@ -225,33 +225,36 @@ V4LThread::work(int noutput_items) struct timeval tv; struct v4l2_buffer buf; fd_set fds; - qint16 xreal, yimag; - uint8_t* b; + int xreal, yimag; + uint16_t* b; SampleVector::iterator it; unsigned int pos = 0; - // in is 4*8bit*2(IQ), 8 bytes; out is 1*16bit*2(IQ) , 4bytes + // MSI format is 252 sample pairs : 63 * 4 it = m_convertBuffer.begin(); - if (recebuf_len > 0) { - b = (uint8_t *) recebuf_ptr; - unsigned int len = noutput_items * 8; - if (len > recebuf_len) - len = recebuf_len; - for (pos = 0; pos < len - 7; pos += 8) { - xreal = b[pos+0] - b[pos+3] + b[pos+7] - b[pos+4]; - yimag = b[pos+1] - b[pos+5] + b[pos+2] - b[pos+6]; - Sample s( xreal << 3, yimag << 3 ); + if (recebuf_len >= 8) { // in bytes + b = (uint16_t *) recebuf_ptr; + unsigned int len = 4 * noutput_items; // decimation (i+q * 2 : cmplx) + if (len * 2 > recebuf_len) + len = recebuf_len / 2; + // Decimate by two for lower cpu usage + for (pos = 0; pos < len - 3; pos += 4) { + xreal = (qint16)(b[pos+0]<<2) + (qint16)(b[pos+2]<<2); + // + (qint16)(b[pos+4]<<2) + (qint16)(b[pos+6]<<2); + yimag = (qint16)(b[pos+1]<<2) + (qint16)(b[pos+3]<<2); + // + (int)(b[pos+5]<<2) + (int)(b[pos+7]<<2); + Sample s( (qint16)(xreal >> 2) , (qint16)(yimag>>2) ); *it = s; it++; } m_sampleFifo->write(m_convertBuffer.begin(), it); - recebuf_len -= pos; - recebuf_ptr = (void*)(b + pos); + recebuf_len -= pos * 2; // size of int16 + recebuf_ptr = (void*)(b + pos); } // return now if there is still data in buffer, else free buffer and get another. if (recebuf_len >= 8) - return pos / 8; - { // frre buffer, if there was one. + return pos / 4; + { // free buffer, if there was one. if (pos > 0) { CLEAR(buf); buf.type = V4L2_BUF_TYPE_SDR_CAPTURE; @@ -287,5 +290,5 @@ V4LThread::work(int noutput_items) recebuf_len = buf.bytesused; recebuf_mmap_index = buf.index; } - return pos / 8; + return pos / 4; } diff --git a/plugins/samplesource/v4l-msi/v4lthread.h b/plugins/samplesource/v4l-msi/v4lthread.h index cf4318761..4c9c80726 100644 --- a/plugins/samplesource/v4l-msi/v4lthread.h +++ b/plugins/samplesource/v4l-msi/v4lthread.h @@ -24,8 +24,9 @@ #include "dsp/samplefifo.h" #include "dsp/inthalfbandfilter.h" -#define SAMPLERATE 1024000 -#define BLOCKSIZE 4096 +// lowest samplerate in the kernel is 1.2M, but this works better +#define SAMPLERATE 1536000 +#define BLOCKSIZE 8192 class V4LThread : public QThread { Q_OBJECT