diff --git a/CMakeLists.txt b/CMakeLists.txt
old mode 100644
new mode 100755
index 60f195bbf..965220002
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,6 +76,7 @@ include(GrVersion)
set(GR_REQUIRED_COMPONENTS RUNTIME ANALOG BLOCKS DIGITAL FILTER FFT PMT)
find_package(Gnuradio REQUIRED COMPONENTS runtime analog blocks digital filter fft)
+
if(Gnuradio_VERSION VERSION_LESS "3.8")
find_package(Volk)
endif()
@@ -140,6 +141,19 @@ find_package(GnuradioUHD)
find_package(GnuradioOsmosdr)
find_package(LibHackRF)
find_package(LibUHD)
+find_library(IIO_LIBRARIES iio)
+find_path(IIO_INCLUDE_DIRS iio.h)
+find_package(GnuradioIIO)
+if (GR_IIO_FOUND)
+ message(STATUS "GR-IIO Found! Adding IIO support")
+ set(BUILD_WITH_GR_IIO TRUE)
+ add_compile_definitions(GnuradioIIO_FOUND=1)
+ set(GR_REQUIRED_COMPONENTS RUNTIME ANALOG BLOCKS DIGITAL FILTER FFT PMT IIO)
+ find_package(Gnuradio REQUIRED COMPONENTS iio)
+else()
+ message(STATUS "Gnuradio-IIO or a dependency Not Found! Skipping IIO support")
+endif()
+
find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED)
if (STREAMER)
@@ -387,5 +401,8 @@ if(NOT Gnuradio_VERSION VERSION_LESS "3.8")
)
endif()
+if (GR_IIO_FOUND)
+ target_link_libraries(trunk-recorder gnuradio::gnuradio-iio)
+endif()
install(TARGETS trunk-recorder RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/Dockerfile b/Dockerfile
index 16ad4ab04..4e323ae36 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -36,7 +36,11 @@ RUN apt-get update && \
wget \
python3-six \
openssh-client \
- ffmpeg
+ ffmpeg \
+ libiio-dev \
+ libiio-utils \
+ libad9361-dev \
+ libgnuradio-iio3.10.9t64
WORKDIR /src
@@ -50,7 +54,8 @@ RUN cmake .. && make -j$(nproc) && make DESTDIR=/newroot install
FROM ubuntu:24.04
RUN apt-get update && apt-get -y upgrade && apt-get install --no-install-recommends -y ca-certificates gr-funcube gr-iqbal curl wget libboost-log1.83.0 \
libboost-chrono1.83.0t64 libgnuradio-digital3.10.9t64 libgnuradio-analog3.10.9t64 libgnuradio-filter3.10.9t64 libgnuradio-network3.10.9t64 \
- libgnuradio-uhd3.10.9t64 libgnuradio-osmosdr0.2.0t64 libsoapysdr0.8 soapysdr0.8-module-all libairspyhf1 libfreesrp0 librtlsdr2 libxtrx0 sox fdkaac docker.io && \
+ libgnuradio-uhd3.10.9t64 libgnuradio-osmosdr0.2.0t64 libiio-dev libiio-utils libad9361-dev libgnuradio-iio3.10.9t64 libsoapysdr0.8 \
+ soapysdr0.8-module-all libairspyhf1 libfreesrp0 librtlsdr2 libxtrx0 sox fdkaac docker.io && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /usr/share/{doc,man,info} && rm -rf /usr/local/share/{doc,man,info}
diff --git a/cmake/Modules/FindGnuradioIIO.cmake b/cmake/Modules/FindGnuradioIIO.cmake
new file mode 100644
index 000000000..45419412c
--- /dev/null
+++ b/cmake/Modules/FindGnuradioIIO.cmake
@@ -0,0 +1,38 @@
+PKG_CHECK_MODULES(PC_GNURADIO_IIO gnuradio-iio)
+
+FIND_PATH(
+ GNURADIO_IIO_INCLUDE_DIRS
+ NAMES gnuradio/iio/api.h
+ HINTS $ENV{GNURADIO_IIO_DIR}/include
+ ${PC_GNURADIO_IIO_INCLUDEDIR}
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GNURADIO_IIO_LIBRARIES
+ NAME gnuradio-iio
+ HINTS $ENV{GNURADIO_IIO_DIR}/lib
+ ${PC_GNURADIO_IIO_LIBDIR}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+pkg_check_modules(PC_IIO libiio)
+
+pkg_check_modules(PC_AD9361 libad9361)
+
+# pkg_check_modules(PC_GR_IIO gnuradio-iio)
+
+if (GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES AND PC_IIO_FOUND AND PC_AD9361_FOUND)
+ set(GR_IIO_FOUND TRUE CACHE INTERNAL "gnuradio-iio found")
+ message(STATUS "Found gnuradio-iio: ${GNURADIO_IIO_INCLUDE_DIRS}, ${GNURADIO_IIO_LIBRARIES}")
+else(GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES AND PC_IIO_FOUND AND PC_AD9361_FOUND)
+ set(GR_IIO_FOUND FALSE CACHE INTERNAL "gnuradio-uhd found")
+endif(GNURADIO_IIO_INCLUDE_DIRS AND GNURADIO_IIO_LIBRARIES AND PC_IIO_FOUND AND PC_AD9361_FOUND)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GnuradioIIO DEFAULT_MSG GNURADIO_IIO_LIBRARIES GNURADIO_IIO_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_IIO_LIBRARIES GNURADIO_IIO_INCLUDE_DIRS)
diff --git a/docs/CONFIGURE.md b/docs/CONFIGURE.md
index 6658ae882..fad51f34a 100644
--- a/docs/CONFIGURE.md
+++ b/docs/CONFIGURE.md
@@ -155,12 +155,12 @@ There is a list of available Plugins [here](./Plugins.md).
## Source Object
-### USRP or OSMOSDR Sources
+### USRP, OSMOSDR or IIO Sources
| Key | Required | Default Value | Type | Description |
| :--------------- | :------: | :-----------: | --------------------------- | ------------------------------------------------------------ |
-| driver | ✓ | | **"usrp"**, **"osmosdr"** | The GNURadio block you wish to use for the SDR. |
-| device | | | **string**
See the [osmosdr page](http://sdr.osmocom.org/trac/wiki/GrOsmoSDR) for supported devices and parameters. | Osmosdr device name and possibly serial number or index of the device.
You only need to do add this key if there are more than one osmosdr devices being used.
Example: `bladerf=00001` for BladeRF with serial 00001 or `rtl=00923838` for RTL-SDR with serial 00923838, just `airspy` for an airspy.
It seems that when you have 5 or more RTLSDRs on one system you need to decrease the buffer size. I think it has something to do with the driver. Try adding buflen: `"device": "rtl=serial_num,buflen=65536"`, there should be no space between the comma and `buflen`. |
+| driver | ✓ | | **"usrp"**, **"osmosdr"**, **"iio"** | The GNURadio block you wish to use for the SDR. |
+| device | | | **string**
See the [osmosdr page](http://sdr.osmocom.org/trac/wiki/GrOsmoSDR) for supported devices and parameters. | Osmosdr device name and possibly serial number or index of the device.
You only need to do add this key if there are more than one osmosdr devices being used.
Example: `bladerf=00001` for BladeRF with serial 00001 or `rtl=00923838` for RTL-SDR with serial 00923838, just `airspy` for an airspy.
It seems that when you have 5 or more RTLSDRs on one system you need to decrease the buffer size. I think it has something to do with the driver. Try adding buflen: `"device": "rtl=serial_num,buflen=65536"`, there should be no space between the comma and `buflen`.
For iio devices, `"ip:192.168.1.5,65536"` or `"usb:1.3.5,65536"` can be used, depending on if you are connecting over ethernet or USB. `iio_info -S` will scan for iio devices and give you the ip address or usb device number. The number after the comma is the buffer length.|
| center | ✓ | | number | The center frequency in Hz to tune the SDR to |
| rate | ✓ | | number | The sampling rate to set the SDR to, in samples / second |
| error | | 0 | number | The tuning error for the SDR, in Hz. This is the difference between the target value and the actual value. So if you wanted to recv 856MHz but you had to tune your SDR to 855MHz (when set to 0ppm) to actually receive it, you would set this to -1000000. You should also probably get a new SDR if it is off by this much. |
@@ -169,7 +169,7 @@ There is a list of available Plugins [here](./Plugins.md).
| analogRecorders | | | number | The number of Analog Recorder to have attached to this source. The same as Digital Recorders except for Analog Voice channels. *This is only required for Trunk systems. Channels in Conventional systems have dedicated recorders and do not need to be included here.* |
| signalDetectorThreshold | | | number | If set, a static threshold will be used for the Signal Detector on all conventional recorder. Otherwise, the threshold value for the noise floor will be automatically be determined. Only set this is you are having problems. The value is in dB, but is generally higher than the Squelch value because the power is measured differently |
| ppm | | 0 | number | The tuning error for the SDR in ppm (parts per million), as an alternative to `error` above. Use a program like GQRX to find an accurate value. |
-| agc | | false | **true** / **false** | Whether or not to enable the SDR's automatic gain control (if supported). This is false by default. It is not recommended to set this as it often yields worse performance compared to a manual gain setting. |
+| agc | | false | **true** / **false** | Whether or not to enable the SDR's automatic gain control (if supported). This is false by default. It is not recommended to set this as it often yields worse performance compared to a manual gain setting. On iio devices this will enable "fast_attack" agc mode. |
| gainSettings | | | { "stageName": value} | Set the gain for any stage. The value for this setting should be passed as an object, where the key specifies the name of the gain stage and the value is the amount of gain in dB. For example:
````"gainSettings": { "IF": 10, "BB": 11.9},```` |
| ifGain | | | number | *AirSpy/hackrf only* sets the **IF** gain. |
| bbGain | | | number | *hackrf only* sets the **BB** gain. |
diff --git a/docs/Install/INSTALL-LINUX.md b/docs/Install/INSTALL-LINUX.md
index bef1518fb..aec32fc66 100644
--- a/docs/Install/INSTALL-LINUX.md
+++ b/docs/Install/INSTALL-LINUX.md
@@ -23,6 +23,10 @@ If you are using a HackRF:
sudo apt install -y hackrf libhackrf-dev libhackrf0
```
+If you are using an IIO device (Pluto, LibreSDR, fmcomms2/3/4, etc):
+```bash
+sudo apt install -y libad9361-dev libiio-dev libiio-utils libgnuradio-iio*
+```
### Ubuntu 22.04
@@ -36,6 +40,10 @@ If you are using a HackRF:
sudo apt install -y hackrf libhackrf-dev libhackrf0
```
+If you are using an IIO device (Pluto, LibreSDR, fmcomms2/3/4, etc):
+```bash
+sudo apt install -y libad9361-dev libiio-dev libiio-utils libgnuradio-iio*
+```
### Ubuntu 21.04
@@ -50,6 +58,10 @@ If you are using a HackRF:
sudo apt install -y hackrf libhackrf-dev libhackrf0
```
+If you are using an IIO device (Pluto, LibreSDR, fmcomms2/3/4, etc):
+```bash
+sudo apt install -y libad9361-dev libiio-dev libiio-utils libgnuradio-iio*
+```
### Ubuntu 20.x
@@ -63,6 +75,11 @@ If you are using a HackRF:
sudo apt install -y hackrf libhackrf-dev libhackrf0
```
+If you are using an IIO device (Pluto, LibreSDR, fmcomms2/3/4, etc):
+```bash
+sudo apt install -y libad9361-dev libiio-dev libiio-utils libgnuradio-iio*
+```
+
### Older Ubuntu Versions...
These instructions should work on Ubuntu 16.x to 17.x, including Debian 9 and 10.
diff --git a/examples/config-iio.json b/examples/config-iio.json
new file mode 100644
index 000000000..012a361fa
--- /dev/null
+++ b/examples/config-iio.json
@@ -0,0 +1,32 @@
+ {
+ "ver": 2,
+ "sources": [
+ {
+ "center": 857000000.0,
+ "rate": 8000000,
+ "error": 0,
+ "gain": 65,
+ "digitalRecorders": 6,
+ "driver": "iio",
+ "device": "ip:10.10.1.222,1048576"
+ },
+ {
+ "center": 773000000.0,
+ "rate": 8000000,
+ "error": 0,
+ "gain": 65,
+ "digitalRecorders": 6,
+ "driver": "iio",
+ "device": "usb:1.3.5,1048576"
+ }
+
+ ],
+ "systems": [
+ {
+ "type": "p25",
+ "control_channels": [ 772281250 ],
+ "talkgroupsFile": "talkgroups.csv",
+ "modulation": "qpsk"
+ }
+ ]
+}
diff --git a/trunk-recorder/config.cc b/trunk-recorder/config.cc
old mode 100644
new mode 100755
index a2d2a17c5..085114fb9
--- a/trunk-recorder/config.cc
+++ b/trunk-recorder/config.cc
@@ -451,8 +451,8 @@ bool load_config(string config_file, Config &config, gr::top_block_sptr &tb, std
bool gain_set = false;
std::string driver = element.value("driver", "");
- if ((driver != "osmosdr") && (driver != "usrp") && (driver != "sigmf") && (driver != "iqfile")) {
- BOOST_LOG_TRIVIAL(error) << "Driver specified in config.json not recognized, needs to be osmosdr, sigmf, iqfile or usrp";
+ if ((driver != "osmosdr") && (driver != "usrp") && (driver != "sigmf") && (driver != "iqfile") && (driver != "iio")) {
+ BOOST_LOG_TRIVIAL(error) << "Driver specified in config.json not recognized, needs to be osmosdr, sigmf, iqfile, usrp, or iio";
return false;
}
diff --git a/trunk-recorder/recorders/p25_recorder_impl.cc b/trunk-recorder/recorders/p25_recorder_impl.cc
index 81585fe24..56ae0ca28 100644
--- a/trunk-recorder/recorders/p25_recorder_impl.cc
+++ b/trunk-recorder/recorders/p25_recorder_impl.cc
@@ -44,6 +44,11 @@ void p25_recorder_impl::initialize(Source *src) {
timestamp = time(NULL);
starttime = time(NULL);
+ BOOST_LOG_TRIVIAL(info) << "p25_recorder.cc: Initializing P25 Recorder Num [" << rec_num << "]\tType: " << (conventional ? "Conventional" : "Trunked") << "\tQPSK: " << qpsk_mod;
+ BOOST_LOG_TRIVIAL(info) << "p25_recorder.cc: Center Freq:\t" << format_freq(center_freq) << "\tInput Rate: " << input_rate;
+ BOOST_LOG_TRIVIAL(info) << "p25_recorder.cc: Silence Frames: " << silence_frames << "\tSoft Vocoder: " << d_soft_vocoder;
+ BOOST_LOG_TRIVIAL(info) << "p25_recorder.cc: Squelch DB: " << squelch_db;
+
if (config == NULL) {
this->set_enable_audio_streaming(false);
} else {
diff --git a/trunk-recorder/source.cc b/trunk-recorder/source.cc
old mode 100644
new mode 100755
index 2dcb689d1..825903581
--- a/trunk-recorder/source.cc
+++ b/trunk-recorder/source.cc
@@ -46,6 +46,7 @@ Source::Source(double c, double r, double e, std::string drv, std::string dev, C
rate = r;
center = c;
error = e;
+ bufLength = 0;
set_min_max();
driver = drv;
device = dev;
@@ -68,6 +69,7 @@ Source::Source(double c, double r, double e, std::string drv, std::string dev, C
autotune_source = false;
autotune_manager = new AutotuneManager(this);
+
recorder_selector = gr::blocks::selector::make(sizeof(gr_complex), 0, 0);
// parameters for signal_detector_cvf
@@ -146,6 +148,51 @@ Source::Source(double c, double r, double e, std::string drv, std::string dev, C
source_block = usrp_src;
}
+
+#ifdef GnuradioIIO_FOUND
+ if (driver == "iio") {
+ std::vector enable_channels{1,1,0,0};
+ BOOST_LOG_TRIVIAL(info) << "SOURCE TYPE IIO";
+
+ // check to see if device string has bufferLength, and if so, split them
+ std::string dev = device;
+ bufLength = 32768;
+
+ if (device.find(",")) {
+ dev = device.substr(0,device.find(","));
+ bufLength = std::stoul(device.substr(device.find(",") + 1, device.length()));
+ }
+
+ BOOST_LOG_TRIVIAL(info) << "Device: " << dev;
+ BOOST_LOG_TRIVIAL(info) << "Buffer Length: " << bufLength;
+
+ gr::iio::fmcomms2_source::sptr iio_src;
+ iio_src = gr::iio::fmcomms2_source::make(dev, enable_channels, bufLength);
+ iio_src->set_len_tag_key("");
+ iio_src->set_gain_mode(0, "manual");
+ iio_src->set_gain(0, gain);
+
+ BOOST_LOG_TRIVIAL(info) << "Tuning to " << format_freq(center + error);
+ iio_src->set_frequency(center + error);
+
+
+ BOOST_LOG_TRIVIAL(info) << "Setting sample rate to: " << FormatSamplingRate(rate);
+ iio_src->set_samplerate(rate);
+ actual_rate = rate;
+
+ iio_src->set_quadrature(true);
+ iio_src->set_rfdc(true);
+ iio_src->set_bbdc(true);
+ iio_src->set_filter_params("Auto", "", 0.0, 0.0);
+
+
+
+ source_block = iio_src;
+ }
+#else // GnuradioIIO_FOUND
+ BOOST_LOG_TRIVIAL(fatal) << "Trunk-recorder was not compiled with IIO enabled.";
+ exit(1);
+#endif //GnuradioIIO_FOUND
}
void Source::set_iq_source(std::string iq_file, bool repeat, double center, double rate) {
@@ -329,6 +376,17 @@ void Source::set_gain(double r) {
gain = r;
cast_to_usrp_sptr(source_block)->set_gain(gain);
}
+
+#ifdef GnuradioIIO_FOUND
+ if (driver == "iio") {
+ gain = r;
+ cast_to_iio_sptr(source_block)->set_gain(0, gain);
+ BOOST_LOG_TRIVIAL(info) << "Gain set to: " << gain;
+ }
+#else // GnuradioIIO_FOUND
+ BOOST_LOG_TRIVIAL(fatal) << "Trunk-recorder was not compiled with IIO enabled.";
+ exit(1);
+#endif //GnuradioIIO_FOUND
}
void Source::add_gain_stage(std::string stage_name, double value) {
@@ -380,7 +438,21 @@ void Source::set_gain_mode(bool m) {
} else {
BOOST_LOG_TRIVIAL(info) << "Auto gain control is OFF";
}
+
+ }
+#ifdef GnuradioIIO_FOUND
+ else if (driver == "iio") {
+ gain_mode = m;
+ if (gain_mode) {
+ cast_to_iio_sptr(source_block)->set_gain_mode(0, "fast_attack");
+ } else {
+ cast_to_iio_sptr(source_block)->set_gain_mode(0, "manual");
+ }
}
+#else // GnuradioIIO_FOUND
+ BOOST_LOG_TRIVIAL(fatal) << "Trunk-recorder was not compiled with IIO enabled.";
+ exit(1);
+#endif
}
double Source::get_if_gain() {
diff --git a/trunk-recorder/source.h b/trunk-recorder/source.h
old mode 100644
new mode 100755
index 7fd43e7f1..e158da6ff
--- a/trunk-recorder/source.h
+++ b/trunk-recorder/source.h
@@ -13,6 +13,9 @@
#include
#include
#include
+#ifdef GnuradioIIO_FOUND
+ #include
+#endif
#include
#include
#include
@@ -53,6 +56,7 @@ class Source {
int debug_recorder_port;
int next_selector_port;
int silence_frames;
+ unsigned long bufLength;
Config *config;
bool autotune_source;
@@ -167,6 +171,11 @@ class Source {
inline gr::uhd::usrp_source::sptr cast_to_usrp_sptr(gr::basic_block_sptr p) {
return boost::dynamic_pointer_cast(p);
}
+#ifdef GnuradioIIO_FOUND
+ inline gr::iio::fmcomms2_source::sptr cast_to_iio_sptr(gr::basic_block_sptr p) {
+ return boost::dynamic_pointer_cast, gr::basic_block>(p);
+ }
+#endif // GnuradioIIO_FOUND
#else
inline osmosdr::source::sptr cast_to_osmo_sptr(gr::basic_block_sptr p) {
return std::dynamic_pointer_cast(p);
@@ -174,6 +183,12 @@ class Source {
inline gr::uhd::usrp_source::sptr cast_to_usrp_sptr(gr::basic_block_sptr p) {
return std::dynamic_pointer_cast(p);
}
+#ifdef GnuradioIIO_FOUND
+ inline gr::iio::fmcomms2_source::sptr cast_to_iio_sptr(gr::basic_block_sptr p) {
+ return std::dynamic_pointer_cast, gr::basic_block>(p);
+ }
+#endif // GnuradioIIO_FOUND
+
#endif
};
#endif