From 95fe79650cf58e1b68f2925b240da412b6112ee3 Mon Sep 17 00:00:00 2001 From: hexameron Date: Sun, 17 May 2015 16:48:51 +0000 Subject: [PATCH 1/6] 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 From f2c1b6e11e6f342da6d552ab96adf96e54836304 Mon Sep 17 00:00:00 2001 From: John Greb Date: Mon, 18 May 2015 15:18:00 +0100 Subject: [PATCH 2/6] Decimate more. --- plugins/channel/CMakeLists.txt | 2 +- plugins/samplesource/v4l-msi/v4linput.cpp | 4 ++-- plugins/samplesource/v4l-msi/v4lplugin.cpp | 5 ++--- plugins/samplesource/v4l-msi/v4lsource.cpp | 25 +++++++++++----------- plugins/samplesource/v4l-msi/v4lthread.h | 1 + 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/plugins/channel/CMakeLists.txt b/plugins/channel/CMakeLists.txt index a57fa036d..5cd68fdc7 100644 --- a/plugins/channel/CMakeLists.txt +++ b/plugins/channel/CMakeLists.txt @@ -1,7 +1,7 @@ project(demod) add_subdirectory(lora) -add_subdirectory(nfm) +add_subdirectory(nfm_testing) add_subdirectory(ssb) add_subdirectory(tcpsrc) add_subdirectory(usb) diff --git a/plugins/samplesource/v4l-msi/v4linput.cpp b/plugins/samplesource/v4l-msi/v4linput.cpp index b8e124a8b..79af7b3c6 100644 --- a/plugins/samplesource/v4l-msi/v4linput.cpp +++ b/plugins/samplesource/v4l-msi/v4linput.cpp @@ -94,7 +94,7 @@ bool V4LInput::startInput(int device) return false; } - m_deviceDescription = QString("RTL-SDR /dev/swradio0"); + m_deviceDescription = QString("SDRplay /dev/swradio0"); qDebug("V4LInput: start"); //MsgReportV4L::create(m_gains)->submit(m_guiMessageQueue); @@ -123,7 +123,7 @@ const QString& V4LInput::getDeviceDescription() const int V4LInput::getSampleRate() const { // The output rate is lower than the device rate - int result = SAMPLERATE / 2; + int result = SAMPLERATE / 4; return result; } diff --git a/plugins/samplesource/v4l-msi/v4lplugin.cpp b/plugins/samplesource/v4l-msi/v4lplugin.cpp index 4412f19d1..6525dbd39 100644 --- a/plugins/samplesource/v4l-msi/v4lplugin.cpp +++ b/plugins/samplesource/v4l-msi/v4lplugin.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "plugin/pluginapi.h" #include "util/simpleserializer.h" #include "v4lplugin.h" @@ -8,7 +7,7 @@ const PluginDescriptor V4LPlugin::m_pluginDescriptor = { QString("V4L Input"), - QString("3.18"), + QString("4.0"), QString("(c) 2014 John Greb"), QString("http://palosaari.fi/linux/"), true, @@ -36,7 +35,7 @@ PluginInterface::SampleSourceDevices V4LPlugin::enumSampleSources() { SampleSourceDevices result; - QString displayedName(QString("Kernel Source #1")); + QString displayedName(QString("Linux V4L (SDRplay)")); SimpleSerializer s(1); s.writeS32(1, 0); result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.v4l", s.final())); diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index d918974f8..e86a61b93 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -218,6 +218,7 @@ V4LThread::set_tuner_gain(double gain) return; } +#define CASTUP (int)(qint16) int V4LThread::work(int noutput_items) { @@ -230,20 +231,20 @@ V4LThread::work(int noutput_items) SampleVector::iterator it; unsigned int pos = 0; - // MSI format is 252 sample pairs : 63 * 4 + // MSI format is 252 sample pairs :( 63 * 4) * 4bytes it = m_convertBuffer.begin(); - if (recebuf_len >= 8) { // in bytes + if (recebuf_len >= 16) { // in bytes b = (uint16_t *) recebuf_ptr; - unsigned int len = 4 * noutput_items; // decimation (i+q * 2 : cmplx) + unsigned int len = 8 * noutput_items; // decimation (i+q * 4 : 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) ); + for (pos = 0; pos < len - 7; pos += 8) { + xreal = CASTUP(b[pos+0]<<2) + CASTUP(b[pos+2]<<2) + + CASTUP(b[pos+4]<<2) + CASTUP(b[pos+6]<<2); + yimag = CASTUP(b[pos+1]<<2) + CASTUP(b[pos+3]<<2) + + CASTUP(b[pos+5]<<2) + CASTUP(b[pos+7]<<2); + Sample s( (qint16)(xreal >> 2) , (qint16)(yimag >> 2) ); *it = s; it++; } @@ -252,8 +253,8 @@ V4LThread::work(int noutput_items) 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 / 4; + if (recebuf_len >= 16) + return pos / 8; { // free buffer, if there was one. if (pos > 0) { CLEAR(buf); @@ -290,5 +291,5 @@ V4LThread::work(int noutput_items) recebuf_len = buf.bytesused; recebuf_mmap_index = buf.index; } - return pos / 4; + return pos / 8; } diff --git a/plugins/samplesource/v4l-msi/v4lthread.h b/plugins/samplesource/v4l-msi/v4lthread.h index 4c9c80726..365969f05 100644 --- a/plugins/samplesource/v4l-msi/v4lthread.h +++ b/plugins/samplesource/v4l-msi/v4lthread.h @@ -26,6 +26,7 @@ // lowest samplerate in the kernel is 1.2M, but this works better #define SAMPLERATE 1536000 +//#define SAMPLERATE 768000 #define BLOCKSIZE 8192 class V4LThread : public QThread { From 6547711c162e3da052d7b747f73a8364db468a62 Mon Sep 17 00:00:00 2001 From: John Greb Date: Mon, 18 May 2015 21:43:04 +0100 Subject: [PATCH 3/6] Broken. --- plugins/samplesource/v4l-msi/v4lsource.cpp | 33 +++++++++++----------- plugins/samplesource/v4l-msi/v4lthread.h | 1 - 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index e86a61b93..41b053aab 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -78,14 +78,16 @@ V4LThread::OpenSource(const char *filename) qCritical("Cannot open /dev/swradio0 :%d", fd); return; } + // sampletype depends on samplerate. Set that first + set_sample_rate((double)SAMPLERATE); + set_center_freq( (double)centerFreq ); pixelformat = V4L2_PIX_FMT_SDR_CS14LE; - qCritical("Want Pixelformat : S14"); CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_SDR_CAPTURE; fmt.fmt.sdr.pixelformat = pixelformat; - xioctl(fd, VIDIOC_S_FMT, &fmt); - qCritical("Got Pixelformat : %4.4s", (char *)&fmt.fmt.sdr.pixelformat); + xioctl(fd, VIDIOC_G_FMT, &fmt); + qCritical(" Expecting format CS14LE, got : %4.4s", (char *)&fmt.fmt.sdr.pixelformat); CLEAR(req); req.count = 8; @@ -118,9 +120,6 @@ V4LThread::OpenSource(const char *filename) buf.index = i; xioctl(fd, VIDIOC_QBUF, &buf); } - - set_sample_rate((double)SAMPLERATE); - set_center_freq( (double)centerFreq ); // start streaming type = V4L2_BUF_TYPE_SDR_CAPTURE; xioctl(fd, VIDIOC_STREAMON, &type); @@ -233,17 +232,19 @@ V4LThread::work(int noutput_items) unsigned int pos = 0; // MSI format is 252 sample pairs :( 63 * 4) * 4bytes it = m_convertBuffer.begin(); - if (recebuf_len >= 16) { // in bytes + if (recebuf_len >= 8) { // in bytes b = (uint16_t *) recebuf_ptr; unsigned int len = 8 * noutput_items; // decimation (i+q * 4 : cmplx) if (len * 2 > recebuf_len) len = recebuf_len / 2; - // Decimate by two for lower cpu usage - for (pos = 0; pos < len - 7; pos += 8) { - xreal = CASTUP(b[pos+0]<<2) + CASTUP(b[pos+2]<<2) - + CASTUP(b[pos+4]<<2) + CASTUP(b[pos+6]<<2); - yimag = CASTUP(b[pos+1]<<2) + CASTUP(b[pos+3]<<2) - + CASTUP(b[pos+5]<<2) + CASTUP(b[pos+7]<<2); + // Decimate by four for lower cpu usage + // ??? seems to have gone a bit wrong. + for (pos = 0; pos < len - 3; pos += 4) { + xreal = CASTUP(b[pos+0]<<2) + CASTUP(b[pos+1]<<2) + + CASTUP(b[pos+2]<<2) + CASTUP(b[pos+3]<<2); + yimag = 0; + //CASTUP(b[pos+1]<<2) + CASTUP(b[pos+3]<<2) + //+ CASTUP(b[pos+5]<<2) + CASTUP(b[pos+7]<<2); Sample s( (qint16)(xreal >> 2) , (qint16)(yimag >> 2) ); *it = s; it++; @@ -253,8 +254,8 @@ V4LThread::work(int noutput_items) recebuf_ptr = (void*)(b + pos); } // return now if there is still data in buffer, else free buffer and get another. - if (recebuf_len >= 16) - return pos / 8; + if (recebuf_len >= 8) + return pos / 4; { // free buffer, if there was one. if (pos > 0) { CLEAR(buf); @@ -291,5 +292,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 365969f05..4c9c80726 100644 --- a/plugins/samplesource/v4l-msi/v4lthread.h +++ b/plugins/samplesource/v4l-msi/v4lthread.h @@ -26,7 +26,6 @@ // lowest samplerate in the kernel is 1.2M, but this works better #define SAMPLERATE 1536000 -//#define SAMPLERATE 768000 #define BLOCKSIZE 8192 class V4LThread : public QThread { From 5b475a5331735ff010931a1996193a30548b0d01 Mon Sep 17 00:00:00 2001 From: John Greb Date: Wed, 20 May 2015 18:43:01 +0100 Subject: [PATCH 4/6] Try setting Gain & Bandwidth. --- plugins/channel/CMakeLists.txt | 2 +- plugins/samplesource/v4l-msi/v4linput.cpp | 6 ++-- plugins/samplesource/v4l-msi/v4lsource.cpp | 34 +++++++++++----------- plugins/samplesource/v4l-msi/v4lthread.h | 1 + 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/plugins/channel/CMakeLists.txt b/plugins/channel/CMakeLists.txt index 5cd68fdc7..a57fa036d 100644 --- a/plugins/channel/CMakeLists.txt +++ b/plugins/channel/CMakeLists.txt @@ -1,7 +1,7 @@ project(demod) add_subdirectory(lora) -add_subdirectory(nfm_testing) +add_subdirectory(nfm) add_subdirectory(ssb) add_subdirectory(tcpsrc) add_subdirectory(usb) diff --git a/plugins/samplesource/v4l-msi/v4linput.cpp b/plugins/samplesource/v4l-msi/v4linput.cpp index 79af7b3c6..58c8894d1 100644 --- a/plugins/samplesource/v4l-msi/v4linput.cpp +++ b/plugins/samplesource/v4l-msi/v4linput.cpp @@ -26,13 +26,13 @@ MESSAGE_CLASS_DEFINITION(V4LInput::MsgConfigureV4L, Message) MESSAGE_CLASS_DEFINITION(V4LInput::MsgReportV4L, Message) V4LInput::Settings::Settings() : - m_gain(0) + m_gain(6) { } void V4LInput::Settings::resetToDefaults() { - m_gain = 0; + m_gain = 6; } QByteArray V4LInput::Settings::serialize() const @@ -53,7 +53,7 @@ bool V4LInput::Settings::deserialize(const QByteArray& data) } if(d.getVersion() == 1) { - d.readS32(1, &m_gain, 0); + d.readS32(1, &m_gain, 6); //d.readS32(2, &m_samplerate, 0); return true; } else { diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index 41b053aab..fb6d597fd 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -64,7 +64,6 @@ static void xioctl(int fh, unsigned long int request, void *arg) void V4LThread::OpenSource(const char *filename) { - struct v4l2_format fmt; struct v4l2_buffer buf; struct v4l2_requestbuffers req; enum v4l2_buf_type type; @@ -79,16 +78,19 @@ V4LThread::OpenSource(const char *filename) return; } // sampletype depends on samplerate. Set that first - set_sample_rate((double)SAMPLERATE); + set_sample_rate( (double)SAMPLERATE ); set_center_freq( (double)centerFreq ); - + set_bandwidth( (double)IF_BANDWIDTH ); + set_tuner_gain( (double) 6.0); +#if 0 + struct v4l2_format fmt; pixelformat = V4L2_PIX_FMT_SDR_CS14LE; CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_SDR_CAPTURE; fmt.fmt.sdr.pixelformat = pixelformat; - xioctl(fd, VIDIOC_G_FMT, &fmt); + xioctl(fd, VIDIOC_S_FMT, &fmt); qCritical(" Expecting format CS14LE, got : %4.4s", (char *)&fmt.fmt.sdr.pixelformat); - +#endif CLEAR(req); req.count = 8; req.type = V4L2_BUF_TYPE_SDR_CAPTURE; @@ -232,30 +234,28 @@ V4LThread::work(int noutput_items) unsigned int pos = 0; // MSI format is 252 sample pairs :( 63 * 4) * 4bytes it = m_convertBuffer.begin(); - if (recebuf_len >= 8) { // in bytes + if (recebuf_len >= 16) { // in bytes b = (uint16_t *) recebuf_ptr; unsigned int len = 8 * noutput_items; // decimation (i+q * 4 : cmplx) if (len * 2 > recebuf_len) len = recebuf_len / 2; // Decimate by four for lower cpu usage - // ??? seems to have gone a bit wrong. - for (pos = 0; pos < len - 3; pos += 4) { - xreal = CASTUP(b[pos+0]<<2) + CASTUP(b[pos+1]<<2) - + CASTUP(b[pos+2]<<2) + CASTUP(b[pos+3]<<2); - yimag = 0; - //CASTUP(b[pos+1]<<2) + CASTUP(b[pos+3]<<2) - //+ CASTUP(b[pos+5]<<2) + CASTUP(b[pos+7]<<2); + for (pos = 0; pos < len - 7; pos += 8) { + xreal = CASTUP(b[pos+0]<<2) + CASTUP(b[pos+2]<<2) + + CASTUP(b[pos+4]<<2) + CASTUP(b[pos+6]<<2); + yimag = CASTUP(b[pos+1]<<2) + CASTUP(b[pos+3]<<2) + + CASTUP(b[pos+5]<<2) + CASTUP(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 * 2; // size of int16 - recebuf_ptr = (void*)(b + pos); + recebuf_ptr = &b[pos]; } // return now if there is still data in buffer, else free buffer and get another. - if (recebuf_len >= 8) - return pos / 4; + if (recebuf_len >= 16) + return pos / 8; { // free buffer, if there was one. if (pos > 0) { CLEAR(buf); @@ -292,5 +292,5 @@ V4LThread::work(int noutput_items) recebuf_len = buf.bytesused; recebuf_mmap_index = buf.index; } - return pos / 4; + return pos / 8; } diff --git a/plugins/samplesource/v4l-msi/v4lthread.h b/plugins/samplesource/v4l-msi/v4lthread.h index 4c9c80726..746242b71 100644 --- a/plugins/samplesource/v4l-msi/v4lthread.h +++ b/plugins/samplesource/v4l-msi/v4lthread.h @@ -26,6 +26,7 @@ // lowest samplerate in the kernel is 1.2M, but this works better #define SAMPLERATE 1536000 +#define IF_BANDWIDTH 300000 #define BLOCKSIZE 8192 class V4LThread : public QThread { From c46e841a4844c8127363a3802a5718d87b5c6368 Mon Sep 17 00:00:00 2001 From: hexameron Date: Thu, 21 May 2015 15:32:18 +0000 Subject: [PATCH 5/6] Correct V4L control IDs. --- plugins/samplesource/v4l-msi/v4lsource.cpp | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index fb6d597fd..f3b6b896a 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -29,19 +29,13 @@ #include #include -/* Control classes */ -#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ -/* User-class control IDs */ -#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) -#define V4L2_CID_USER_BASE V4L2_CID_BASE - -#define CID_SAMPLING_MODE ((V4L2_CID_USER_BASE | 0xf000) + 0) -#define CID_SAMPLING_RATE ((V4L2_CID_USER_BASE | 0xf000) + 1) -#define CID_SAMPLING_RESOLUTION ((V4L2_CID_USER_BASE | 0xf000) + 2) -#define CID_TUNER_RF ((V4L2_CID_USER_BASE | 0xf000) + 10) -#define CID_TUNER_BW ((V4L2_CID_USER_BASE | 0xf000) + 11) -#define CID_TUNER_IF ((V4L2_CID_USER_BASE | 0xf000) + 12) -#define CID_TUNER_GAIN ((V4L2_CID_USER_BASE | 0xf000) + 13) +#define CID_CLASS_RF (0x00a20000) +#define CID_RF_TUNER_CLASS_BASE (0x00a20900) +#define CID_TUNER_BW_AUTO (CID_RF_TUNER_CLASS_BASE + 11) +#define CID_TUNER_BW (CID_RF_TUNER_CLASS_BASE + 12) +#define CID_TUNER_LNA_GAIN (CID_RF_TUNER_CLASS_BASE + 42) +#define CID_TUNER_MIXER_GAIN (CID_RF_TUNER_CLASS_BASE + 52) +#define CID_TUNER_IF_GAIN (CID_RF_TUNER_CLASS_BASE + 62) #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*/ @@ -77,12 +71,11 @@ V4LThread::OpenSource(const char *filename) qCritical("Cannot open /dev/swradio0 :%d", fd); return; } - // sampletype depends on samplerate. Set that first set_sample_rate( (double)SAMPLERATE ); set_center_freq( (double)centerFreq ); set_bandwidth( (double)IF_BANDWIDTH ); set_tuner_gain( (double) 6.0); -#if 0 + struct v4l2_format fmt; pixelformat = V4L2_PIX_FMT_SDR_CS14LE; CLEAR(fmt); @@ -90,7 +83,7 @@ V4LThread::OpenSource(const char *filename) fmt.fmt.sdr.pixelformat = pixelformat; xioctl(fd, VIDIOC_S_FMT, &fmt); qCritical(" Expecting format CS14LE, got : %4.4s", (char *)&fmt.fmt.sdr.pixelformat); -#endif + CLEAR(req); req.count = 8; req.type = V4L2_BUF_TYPE_SDR_CAPTURE; @@ -159,7 +152,7 @@ V4LThread::set_sample_rate(double samp_rate) return; } -// Cannot change freq while streaming in Linux 4.0 +// Cannot change freq while streaming void V4LThread::set_center_freq(double freq) { @@ -183,15 +176,25 @@ V4LThread::set_bandwidth(double bandwidth) struct v4l2_ext_controls ext_ctrls; struct v4l2_ext_control ext_ctrl; + if (fd <= 0) + return; + + memset (&ext_ctrl, 0, sizeof(ext_ctrl)); + ext_ctrl.id = CID_TUNER_BW_AUTO; + ext_ctrl.value = 0; + memset (&ext_ctrls, 0, sizeof(ext_ctrls)); + ext_ctrls.ctrl_class = CID_CLASS_RF; + ext_ctrls.count = 1; + ext_ctrls.controls = &ext_ctrl; + xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); + memset (&ext_ctrl, 0, sizeof(ext_ctrl)); ext_ctrl.id = CID_TUNER_BW; ext_ctrl.value = bandwidth; - memset (&ext_ctrls, 0, sizeof(ext_ctrls)); - ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_USER; + ext_ctrls.ctrl_class = CID_CLASS_RF; ext_ctrls.count = 1; ext_ctrls.controls = &ext_ctrl; - xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); return; @@ -206,16 +209,13 @@ V4LThread::set_tuner_gain(double gain) if (fd <= 0) return; memset (&ext_ctrl, 0, sizeof(ext_ctrl)); - ext_ctrl.id = CID_TUNER_GAIN; + ext_ctrl.id = CID_TUNER_IF_GAIN; ext_ctrl.value = gain; - memset (&ext_ctrls, 0, sizeof(ext_ctrls)); - ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_USER; + ext_ctrls.ctrl_class = CID_CLASS_RF; ext_ctrls.count = 1; ext_ctrls.controls = &ext_ctrl; - xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); - return; } From 00ed2c20044a61aedd7a2dffc42edfaaa9f33db8 Mon Sep 17 00:00:00 2001 From: hexameron Date: Thu, 21 May 2015 18:09:12 +0000 Subject: [PATCH 6/6] Gain settings. --- plugins/samplesource/v4l-msi/v4lgui.cpp | 58 ++++++++++------------ plugins/samplesource/v4l-msi/v4lgui.h | 4 +- plugins/samplesource/v4l-msi/v4lgui.ui | 30 +++++++---- plugins/samplesource/v4l-msi/v4linput.cpp | 23 ++++++--- plugins/samplesource/v4l-msi/v4linput.h | 23 +-------- plugins/samplesource/v4l-msi/v4lplugin.cpp | 4 +- plugins/samplesource/v4l-msi/v4lsource.cpp | 30 ++++++++--- plugins/samplesource/v4l-msi/v4lthread.h | 1 + 8 files changed, 93 insertions(+), 80 deletions(-) diff --git a/plugins/samplesource/v4l-msi/v4lgui.cpp b/plugins/samplesource/v4l-msi/v4lgui.cpp index 802764536..e1f13b5b9 100644 --- a/plugins/samplesource/v4l-msi/v4lgui.cpp +++ b/plugins/samplesource/v4l-msi/v4lgui.cpp @@ -10,7 +10,7 @@ V4LGui::V4LGui(PluginAPI* pluginAPI, QWidget* parent) : m_sampleSource(NULL) { ui->setupUi(this); - ui->centerFrequency->setValueRange(7, 20000U, 2200000U); + ui->centerFrequency->setValueRange(7, 50000U, 1999000U); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); displaySettings(); @@ -82,37 +82,15 @@ bool V4LGui::deserialize(const QByteArray& data) bool V4LGui::handleMessage(Message* message) { - if(V4LInput::MsgReportV4L::match(message)) { - m_gains = ((V4LInput::MsgReportV4L*)message)->getGains(); - displaySettings(); - message->completed(); - return true; - } else { - return false; - } + return false; } void V4LGui::displaySettings() { ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000); - if(m_gains.size() > 0) { - int dist = abs(m_settings.m_gain - m_gains[0]); - int pos = 0; - for(uint i = 1; i < m_gains.size(); i++) { - if(abs(m_settings.m_gain - m_gains[i]) < dist) { - dist = abs(m_settings.m_gain - m_gains[i]); - pos = i; - } - } - ui->gainText->setText(tr("%1.%2").arg(m_gains[pos] / 10).arg(abs(m_gains[pos] % 10))); - ui->gain->setMaximum(m_gains.size() - 1); - ui->gain->setEnabled(true); - ui->gain->setValue(pos); - } else { - ui->gain->setMaximum(0); - ui->gain->setEnabled(false); - ui->gain->setValue(0); - } + ui->ifgain->setValue(1); + ui->checkBoxL->setChecked(m_settings.m_lna); + ui->checkBoxM->setChecked(m_settings.m_mix); } void V4LGui::sendSettings() @@ -127,12 +105,12 @@ void V4LGui::on_centerFrequency_changed(quint64 value) sendSettings(); } -void V4LGui::on_gain_valueChanged(int value) +void V4LGui::on_ifgain_valueChanged(int value) { - if(value > (int)m_gains.size()) + if(value > 8) return; - int gain = m_gains[value]; - ui->gainText->setText(tr("%1.%2").arg(gain / 10).arg(abs(gain % 10))); + int gain = value * 6; + ui->gainText->setText( tr("%1").arg(gain) ); m_settings.m_gain = gain; sendSettings(); } @@ -143,3 +121,21 @@ void V4LGui::updateHardware() message->submit(m_pluginAPI->getDSPEngineMessageQueue()); m_updateTimer.stop(); } + +void V4LGui::on_checkBoxL_stateChanged(int state) +{ + if (state == Qt::Checked) + m_settings.m_lna = 1; + else + m_settings.m_lna = 0; + sendSettings(); +} + +void V4LGui::on_checkBoxM_stateChanged(int state) +{ + if (state == Qt::Checked) + m_settings.m_mix = 1; + else + m_settings.m_mix = 0; + sendSettings(); +} diff --git a/plugins/samplesource/v4l-msi/v4lgui.h b/plugins/samplesource/v4l-msi/v4lgui.h index 448c97dee..c443ac424 100644 --- a/plugins/samplesource/v4l-msi/v4lgui.h +++ b/plugins/samplesource/v4l-msi/v4lgui.h @@ -44,7 +44,9 @@ private: private slots: void on_centerFrequency_changed(quint64 value); - void on_gain_valueChanged(int value); + void on_ifgain_valueChanged(int value); + void on_checkBoxL_stateChanged(int state); + void on_checkBoxM_stateChanged(int state); void updateHardware(); }; diff --git a/plugins/samplesource/v4l-msi/v4lgui.ui b/plugins/samplesource/v4l-msi/v4lgui.ui index 9254a4a50..6ecfdaa85 100644 --- a/plugins/samplesource/v4l-msi/v4lgui.ui +++ b/plugins/samplesource/v4l-msi/v4lgui.ui @@ -107,6 +107,24 @@ + + + + + + LNA AMP + + + + + + + Mix AMP + + + + + @@ -126,18 +144,12 @@ - - - false - + - LNA amplification + IF amplification - 0 - - - 1 + 8 Qt::Horizontal diff --git a/plugins/samplesource/v4l-msi/v4linput.cpp b/plugins/samplesource/v4l-msi/v4linput.cpp index 58c8894d1..57584b894 100644 --- a/plugins/samplesource/v4l-msi/v4linput.cpp +++ b/plugins/samplesource/v4l-msi/v4linput.cpp @@ -23,16 +23,19 @@ #include "util/simpleserializer.h" MESSAGE_CLASS_DEFINITION(V4LInput::MsgConfigureV4L, Message) -MESSAGE_CLASS_DEFINITION(V4LInput::MsgReportV4L, Message) V4LInput::Settings::Settings() : - m_gain(6) + m_gain(1), + m_lna(0), + m_mix(0) { } void V4LInput::Settings::resetToDefaults() { - m_gain = 6; + m_gain = 1; + m_lna = 0; + m_mix = 0; } QByteArray V4LInput::Settings::serialize() const @@ -53,7 +56,7 @@ bool V4LInput::Settings::deserialize(const QByteArray& data) } if(d.getVersion() == 1) { - d.readS32(1, &m_gain, 6); + d.readS32(1, &m_gain, 1); //d.readS32(2, &m_samplerate, 0); return true; } else { @@ -155,13 +158,19 @@ 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 ); + m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency; } - m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency; -#if 0 + if((m_settings.m_gain != settings.m_gain) || force) { m_settings.m_gain = settings.m_gain; m_V4LThread->set_tuner_gain((double)m_settings.m_gain); } -#endif + + if((m_settings.m_lna != settings.m_lna) || (m_settings.m_mix != settings.m_mix) || force) { + m_settings.m_lna = settings.m_lna; + m_settings.m_mix = settings.m_mix; + m_V4LThread->set_amps(1, m_settings.m_lna); + m_V4LThread->set_amps(0, m_settings.m_mix); + } } diff --git a/plugins/samplesource/v4l-msi/v4linput.h b/plugins/samplesource/v4l-msi/v4linput.h index 680d65c53..a56f2bf4c 100644 --- a/plugins/samplesource/v4l-msi/v4linput.h +++ b/plugins/samplesource/v4l-msi/v4linput.h @@ -31,7 +31,7 @@ class V4LThread; class V4LInput : public SampleSource { public: struct Settings { - qint32 m_gain; + qint32 m_gain, m_lna, m_mix; Settings(); void resetToDefaults(); @@ -62,26 +62,6 @@ public: { } }; - class MsgReportV4L : public Message { - MESSAGE_CLASS_DECLARATION - - public: - const std::vector& getGains() const { return m_gains; } - - static MsgReportV4L* create(const std::vector& gains) - { - return new MsgReportV4L(gains); - } - - protected: - std::vector m_gains; - - MsgReportV4L(const std::vector& gains) : - Message(), - m_gains(gains) - { } - }; - V4LInput(MessageQueue* msgQueueToGUI); ~V4LInput(); @@ -98,7 +78,6 @@ private: Settings m_settings; V4LThread* m_V4LThread; QString m_deviceDescription; - std::vector m_gains; void applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force); }; diff --git a/plugins/samplesource/v4l-msi/v4lplugin.cpp b/plugins/samplesource/v4l-msi/v4lplugin.cpp index 6525dbd39..1d9546075 100644 --- a/plugins/samplesource/v4l-msi/v4lplugin.cpp +++ b/plugins/samplesource/v4l-msi/v4lplugin.cpp @@ -6,9 +6,9 @@ #include "v4lgui.h" const PluginDescriptor V4LPlugin::m_pluginDescriptor = { - QString("V4L Input"), + QString("V4L SDRplay Input"), QString("4.0"), - QString("(c) 2014 John Greb"), + QString("(c) 2015 John Greb"), QString("http://palosaari.fi/linux/"), true, QString("github.com/hexameron/rtl-sdrangelove") diff --git a/plugins/samplesource/v4l-msi/v4lsource.cpp b/plugins/samplesource/v4l-msi/v4lsource.cpp index f3b6b896a..7e1b8fc31 100644 --- a/plugins/samplesource/v4l-msi/v4lsource.cpp +++ b/plugins/samplesource/v4l-msi/v4lsource.cpp @@ -146,10 +146,7 @@ V4LThread::set_sample_rate(double samp_rate) frequency.tuner = 0; frequency.type = V4L2_TUNER_ADC; frequency.frequency = samp_rate; - xioctl(fd, VIDIOC_S_FREQUENCY, &frequency); - - return; } // Cannot change freq while streaming @@ -164,10 +161,7 @@ V4LThread::set_center_freq(double freq) frequency.tuner = 1; frequency.type = V4L2_TUNER_RF; frequency.frequency = freq; - xioctl(fd, VIDIOC_S_FREQUENCY, &frequency); - - return; } void @@ -196,8 +190,6 @@ V4LThread::set_bandwidth(double bandwidth) ext_ctrls.count = 1; ext_ctrls.controls = &ext_ctrl; xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); - - return; } void @@ -216,7 +208,29 @@ V4LThread::set_tuner_gain(double gain) ext_ctrls.count = 1; ext_ctrls.controls = &ext_ctrl; xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); + } + + +void +V4LThread::set_amps(bool lna, bool on) + { + struct v4l2_ext_controls ext_ctrls; + struct v4l2_ext_control ext_ctrl; + + if (fd <= 0) return; + + memset (&ext_ctrl, 0, sizeof(ext_ctrl)); + memset (&ext_ctrls, 0, sizeof(ext_ctrls)); + if (lna) + ext_ctrl.id = CID_TUNER_LNA_GAIN; + else + ext_ctrl.id = CID_TUNER_MIXER_GAIN; + ext_ctrl.value = on; + ext_ctrls.ctrl_class = CID_CLASS_RF; + ext_ctrls.count = 1; + ext_ctrls.controls = &ext_ctrl; + xioctl(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls); } #define CASTUP (int)(qint16) diff --git a/plugins/samplesource/v4l-msi/v4lthread.h b/plugins/samplesource/v4l-msi/v4lthread.h index 746242b71..834e98460 100644 --- a/plugins/samplesource/v4l-msi/v4lthread.h +++ b/plugins/samplesource/v4l-msi/v4lthread.h @@ -43,6 +43,7 @@ public: void set_center_freq(double freq); void set_bandwidth(double bandwidth); void set_tuner_gain(double gain); + void set_amps(bool lna, bool on); int work(int n_items); private: int fd;