diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c250ca..1e76e35 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,9 +19,14 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++11")
# Add the local Find*.cmake scripts
LIST (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
-FIND_PACKAGE( RTLSDR REQUIRED )
-INCLUDE_DIRECTORIES("${RTLSDR_INCLUDE_DIR}")
-
+FIND_PACKAGE(SoapySDR NO_MODULE)
+if (SOAPYSDR_FOUND)
+ INCLUDE_DIRECTORIES("${LIBSOAPYSDR_INCLUDE_DIR}")
+endif ()
+FIND_PACKAGE(avro NO_MODULE)
+if (AVRO_FOUND)
+ INCLUDE_DIRECTORIES("${AVRO_INCLUDE_DIR}")
+endif ()
# liquid, avro, ssl, crypto
@@ -29,8 +34,7 @@ configure_file( version_config.h.in generated/version_config.h )
#ADD_SUBDIRECTORY(drivers/rtlsdr/converter/)
-set(SOURCE_FILES main.cpp drivers/Driver.h drivers/rtlsdr/rtlsdrDriver.cpp drivers/rtlsdr/rtlsdrDriver.h
- drivers/rtlsdr/converter/converter.c drivers/rtlsdr/converter/converter.h
+set(SOURCE_FILES main.cpp drivers/Driver.h drivers/soapysdr/soapyDriver.cpp drivers/soapysdr/soapyDriver.h
context/ElectrosenseContext.cpp context/ElectrosenseContext.h
drivers/common/SequentialHopping.cpp drivers/common/SequentialHopping.h
types/SpectrumSegment.cpp types/SpectrumSegment.h ProcessingBlocks/RemoveDC.cpp ProcessingBlocks/RemoveDC.h
@@ -40,9 +44,12 @@ set(SOURCE_FILES main.cpp drivers/Driver.h drivers/rtlsdr/rtlsdrDriver.cpp drive
misc/TLS.cpp misc/TLS.h misc/TCP.cpp misc/TCP.h MiscBlocks/IQSink.cpp MiscBlocks/IQSink.h)
add_executable(es_sensor ${SOURCE_FILES})
+list(APPEND SoapySDR_LIBRARIES -pthread)
+list(APPEND AVRO_LIBRARIES -pthread)
+
target_link_libraries(es_sensor
- ${RTLSDR_LIBRARY}
+ SoapySDR
pthread
dl
liquid
@@ -52,7 +59,7 @@ target_link_libraries(es_sensor
)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/es_sensor DESTINATION /usr/share/electrosense/bin/)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/es_sensor DESTINATION /usr/share/electrosense/bin/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/schemas/rtl-spec.avsc DESTINATION /usr/share/electrosense/schemas/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/schemas/iq-spec.avsc DESTINATION /usr/share/electrosense/schemas/)
diff --git a/drivers/soapysdr/soapyDriver.cpp b/drivers/soapysdr/soapyDriver.cpp
new file mode 100644
index 0000000..9403369
--- /dev/null
+++ b/drivers/soapysdr/soapyDriver.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2018 by IMDEA Networks Institute
+ *
+ * This file is part of Electrosense.
+ *
+ * Electrosense 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Electrosense 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 RTL-Spec. If not, see .
+ *
+ * Authors:
+ * Roberto Calvo-Palomino
+ *
+ */
+
+
+#include "soapyDriver.h"
+#include
+#include
+#include
+#include
+
+namespace electrosense {
+
+
+soapyDriver::soapyDriver() {
+
+ mQueueOut = new ReaderWriterQueue(100);
+}
+
+
+int soapyDriver::open(std::string device) {
+ // rtlsdr lib expects to have integer id for identifying the device
+
+ int device_index = -1;
+ SoapySDR::KwargsList list = SoapySDR::Device::enumerate(device);
+ int n_rtlsdr = list.size();
+
+ if (n_rtlsdr==0) {
+ std::cerr << "* Error: no RTL-SDR USB devices found" << std::endl;
+ throw std::logic_error("Fatal Error");
+ }
+
+ // Choose which device to use
+ if ((n_rtlsdr==1)) {
+ device_index=0;
+ std::cout << "Device index " << device_index << ": [Device: " << list[device_index]["device"] << "] [Product: " << list[device_index]["driver"] << "] [URI: " << list[device_index]["uri"] << "]" << std::endl;
+ }
+ if ((device_index<0)||(device_index>=n_rtlsdr)) {
+ std::cerr << "Error: must specify which USB device to use with --device-index" << std::endl;
+ std::cerr << "Found the following USB devices:" << std::endl;
+ for (int t=0;tgetSamplingRate();
+
+ // Sampling frequency
+ mDevice->setSampleRate(SOAPY_SDR_RX,0,samplingRate);
+ mDevice->setBandwidth(SOAPY_SDR_RX,0,samplingRate);
+
+ int frequency = 24e6; // default value
+ mDevice->setFrequency(SOAPY_SDR_RX,0,frequency);
+
+ double gain = ElectrosenseContext::getInstance()->getGain();
+ mDevice->setGainMode(SOAPY_SDR_RX,0,false);
+
+ mDevice->setGain(SOAPY_SDR_RX,0,gain);
+ gain = mDevice->getGain(SOAPY_SDR_RX,0);
+
+
+ std::cout << "[*] Initializing dongle with following configuration: " << std::endl;
+ std::cout << "\t Center Frequency: " << frequency << " Hz" << std::endl;
+ std::cout << "\t Sampling Rate: " << samplingRate << " samples/sec" << std::endl;
+ std::cout << "\t Gain: " << gain << " dB" << std::endl;
+
+ return 1;
+
+}
+
+
+int soapyDriver::close () {
+ return 1;
+}
+
+
+void timespec_diff(struct timespec *start, struct timespec *stop,
+ struct timespec *result)
+{
+ if ((stop->tv_nsec - start->tv_nsec) < 0) {
+ result->tv_sec = stop->tv_sec - start->tv_sec - 1;
+ result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
+ } else {
+ result->tv_sec = stop->tv_sec - start->tv_sec;
+ result->tv_nsec = stop->tv_nsec - start->tv_nsec;
+ }
+
+ return;
+}
+
+bool soapyDriver::isRunning () {
+ return mRunning;
+}
+
+static void *aux_thread (void *arg) {
+ soapyDriver *sd_t = (soapyDriver *) arg;
+ sd_t->SyncSampling();
+ pthread_exit(NULL);
+}
+
+
+void soapyDriver::run () {
+ mRunning = true;
+ pthread_t myth;
+ pthread_create ( &myth, NULL, aux_thread, (void *)this );
+ pthread_join(myth,NULL);
+ mRunning = false;
+}
+
+void soapyDriver::SyncSampling() {
+
+ const int BULK_TRANSFER_MULTIPLE = 512;
+ struct timespec start_time;
+ clock_gettime(CLOCK_REALTIME, &start_time);
+
+ std::cout << "soapyDriver::run" << std::endl;
+
+ mSeqHopping = new SequentialHopping();
+ uint64_t center_freq=0, previous_freq=0, fft_size=0, slen=0;
+
+ std::complex *iq_buf = NULL;
+
+ while (mRunning)
+ {
+
+ // Introduce here the concept of segment per band (before jumping).
+
+ center_freq = mSeqHopping->nextHop();
+
+ if (previous_freq != center_freq)
+ {
+ previous_freq = center_freq;
+
+ mDevice->setFrequency(SOAPY_SDR_RX,0,center_freq);
+
+// // Reset the buffer
+ if (mStream != 0)
+ {
+ mDevice->deactivateStream(mStream,0,0);
+ mDevice->closeStream(mStream);
+ }
+ mStream=mDevice->setupStream(SOAPY_SDR_RX,"CF32");
+ mDevice->activateStream(mStream);
+
+
+
+ }
+
+ unsigned int current_fft_size = 1<getLog2FftSize();
+
+ if (fft_size != current_fft_size)
+ {
+
+ fft_size = current_fft_size;
+
+ slen = ((current_fft_size-ElectrosenseContext::getInstance()->getSoverlap()) *
+ ElectrosenseContext::getInstance()->getAvgFactor()+ElectrosenseContext::getInstance()->getSoverlap())*2;
+
+
+ if(slen % BULK_TRANSFER_MULTIPLE != 0)
+ slen = slen + (BULK_TRANSFER_MULTIPLE - (slen % BULK_TRANSFER_MULTIPLE));
+
+ iq_buf = (std::complex *) realloc(iq_buf,slen*sizeof(std::complex));
+
+ }
+ std::vector iqbufs(1);
+ iqbufs[0] = iq_buf;
+
+ struct timespec current_time;
+ clock_gettime(CLOCK_REALTIME, ¤t_time);
+
+ int flags;
+ long long timeNs;
+ int r = mDevice->readStream(mStream,iqbufs.data(),slen,flags,timeNs,100000);
+ if(r <= 0 ){
+ fprintf(stderr, "WARNING: Synchronous read failed.\n");
+ std::cout << r << " " << slen << std::endl;
+ mRunning = false;
+ }
+
+ std::vector> iq_vector;
+
+ for (unsigned int i=0; igetAvgFactor(); i++) {
+
+ iq_vector.clear();
+
+ for (unsigned int j = 0; j < current_fft_size*2; j ++) {
+
+ // Every segment overlaps getSoverlap() samples in time domain.
+
+ iq_vector.push_back(
+ iq_buf[j+i*(current_fft_size-ElectrosenseContext::getInstance()->getSoverlap())*2]);
+
+ }
+
+ //TODO: Id should be the ethernet MAC
+
+ SpectrumSegment *segment = new SpectrumSegment(-1000, current_time, center_freq,
+ ElectrosenseContext::getInstance()->getSamplingRate(),
+ iq_vector);
+ mQueueOut->enqueue(segment);
+
+ }
+ struct timespec diff;
+ timespec_diff(&start_time, ¤t_time, &diff);
+ if (diff.tv_sec > ElectrosenseContext::getInstance()->getMonitorTime() &&
+ ElectrosenseContext::getInstance()->getMonitorTime()!= 0)
+ {
+ std::cout << "sampling done" << std::endl;
+ mRunning = false;
+ }
+ }
+
+ delete(mSeqHopping);
+
+}
+
+
+
+
+int soapyDriver::stop()
+{
+ mRunning = false;
+ waitForThread();
+
+ // Workaround: RPi does not work properly the cancellation of the async task
+ if (ElectrosenseContext::getInstance()->getPipeline().compare("PSD") ==0 ) {
+ SoapySDR::Device::unmake(mDevice);
+ mDevice = NULL;
+ }
+
+ return 1;
+}
+}
diff --git a/drivers/soapysdr/soapyDriver.h b/drivers/soapysdr/soapyDriver.h
new file mode 100644
index 0000000..524cdde
--- /dev/null
+++ b/drivers/soapysdr/soapyDriver.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 by IMDEA Networks Institute
+ *
+ * This file is part of Electrosense.
+ *
+ * Electrosense 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Electrosense 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 RTL-Spec. If not, see .
+ *
+ * Authors:
+ * Roberto Calvo-Palomino
+ *
+ */
+#ifndef ES_SENSOR_RTLSDR_H
+#define ES_SENSOR_RTLSDR_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../Driver.h"
+#include "../Component.h"
+#include "../Communication.h"
+#include "soapyDriver.h"
+#include "../../context/ElectrosenseContext.h"
+#include "../common/SequentialHopping.h"
+
+// Workaround issue #4 , complex.h breaks openssl's RSA library
+// include RSA before any mention to complex.h
+#include "../../types/SpectrumSegment.h"
+#include
+
+namespace electrosense {
+
+
+
+ class soapyDriver: public Driver, public Component, public Communication {
+
+ public:
+
+ soapyDriver();
+
+ ~soapyDriver();
+
+ // Open the device
+ int open(std::string deviceId);
+
+ // Close the device
+ int close();
+
+ // Stop
+ int stop();
+
+ // Running
+ bool isRunning ();
+
+ void SyncSampling();
+
+ ReaderWriterQueue* getQueueIn() { return NULL; }
+ void setQueueIn (ReaderWriterQueue* QueueIn ) {};
+
+ ReaderWriterQueue* getQueueOut() { return mQueueOut; };
+ void setQueueOut (ReaderWriterQueue* QueueOut) {};
+
+ std::string getNameId () { return std::string("soapyDriver"); };
+
+
+ private:
+
+
+ // Run the driver in the thread
+ void run();
+
+ bool mRunning;
+
+ int mDeviceId;
+
+ SoapySDR::Device * mDevice;
+ SoapySDR::Stream * mStream;
+
+ SequentialHopping* mSeqHopping;
+
+ ReaderWriterQueue* mQueueOut;
+
+
+
+ std::vector> m_capbuf_raw;
+
+ };
+
+}
+
+#endif //ES_SENSOR_RTLSDR_H
diff --git a/main.cpp b/main.cpp
index 9e001c6..6c83e74 100644
--- a/main.cpp
+++ b/main.cpp
@@ -35,10 +35,10 @@
#include "MiscBlocks/FileSink.h"
#include "MiscBlocks/IQSink.h"
-#include "generated/version_config.h"
+#include "build/generated/version_config.h"
#include "context/ElectrosenseContext.h"
-#include "drivers/rtlsdr/rtlsdrDriver.h"
+#include "drivers/soapysdr/soapyDriver.h"
#include "drivers/Component.h"
#include "ProcessingBlocks/RemoveDC.h"
@@ -304,7 +304,7 @@ int main( int argc, char* argv[] ) {
electrosense::Averaging *avgBlock;
// RTL-SDR Driver
- auto *rtlDriver = new electrosense::rtlsdrDriver();
+ auto *rtlDriver = new electrosense::soapyDriver();
vComponents.push_back(rtlDriver);
rtlDriver->open("0");