Skip to content

Commit

Permalink
Add support for HackRF.
Browse files Browse the repository at this point in the history
  • Loading branch information
nqbit committed Apr 9, 2022
1 parent 9f21e52 commit d73b6df
Show file tree
Hide file tree
Showing 10 changed files with 385 additions and 37 deletions.
14 changes: 8 additions & 6 deletions docs/commands/goesrecv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ Demodulate and decode signal into packet stream.
See :ref:`minimal_receiver` for an example setup.

You can use goesrecv with an RTL-SDR_ (make sure you have one with the
R820T tuner chip), or an Airspy_ (confirmed to work with the Mini).
The raw signal is then processed by the demodulator and turned into a
stream of 1s and 0s. This is then passed to the decoder where the
bitstream is synchronized and error correction is applied. Every valid
packet is then forwarded to downstream tools (e.g. goeslrit or
goesproc).
R820T tuner chip), an Airspy_ (confirmed to work with the Mini), or a
HackRf_ (confirmed to work with a HackRf One). The raw signal is then
processed by the demodulator and turned into a stream of 1s and 0s. This
is then passed to the decoder where the bitstream is synchronized and
error correction is applied. Every valid packet is then forwarded to
downstream tools (e.g. goeslrit or goesproc).

.. _rtl-sdr:
https://rtlsdr.org/
.. _airspy:
https://airspy.com/
.. _hackrf:
https://greatscottgadgets.com/hackrf/

Options
=======
Expand Down
3 changes: 2 additions & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ Install system dependencies:
If you want to run goesrecv on this machine, you also have to install
the development packages of the drivers the SDRs you want to use;
``librtlsdr-dev`` for an RTL-SDR, ``libairspy-dev`` for an Airspy.
``librtlsdr-dev`` for an RTL-SDR, ``libairspy-dev`` for an Airspy,
and ``libhackrf-dev`` for a HackRf.

Now you can build and install goestools:

Expand Down
8 changes: 8 additions & 0 deletions etc/goesrecv.conf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ source = "airspy"
# bias_tee = false
# device_index = 0

# [hackrf]
# frequency = 1694100000
# sample_rate = 8000000
# if_gain = 32
# bb_gain = 34
# rf_amp_enabled = true
# bias_tee = false

# [nanomsg]
# sample_rate = 2400000
# connect = "tcp://1.2.3.4:5005"
Expand Down
1 change: 1 addition & 0 deletions scripts/setup_raspbian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ urls() {
scripts/list_raspbian_urls.py \
librtlsdr-dev \
libairspy-dev \
libhackrf-dev \
libusb-1.0-0-dev \
libudev1 \
zlib1g-dev \
Expand Down
13 changes: 13 additions & 0 deletions src/goesrecv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ else()
target_link_libraries(rtlsdr_source ${RTLSDR_LIBRARIES} publisher stdc++)
endif()

pkg_check_modules(HACKRF libhackrf)
if(NOT HACKRF_FOUND)
message(WARNING "Unable to find libhackrf")
else()
add_library(hackrf_source hackrf_source.cc)
target_link_libraries(hackrf_source ${HACKRF_LIBRARIES} publisher stdc++)
endif()

add_library(nanomsg_source nanomsg_source.cc)
target_link_libraries(nanomsg_source nanomsg publisher stdc++)

Expand Down Expand Up @@ -60,6 +68,7 @@ target_link_libraries(goesrecv clock_recovery)
target_link_libraries(goesrecv quantize)
target_link_libraries(goesrecv nanomsg_source)
target_link_libraries(goesrecv version)

if(AIRSPY_FOUND)
target_compile_definitions(goesrecv PUBLIC -DBUILD_AIRSPY)
target_link_libraries(goesrecv airspy_source)
Expand All @@ -68,6 +77,10 @@ if(RTLSDR_FOUND)
target_compile_definitions(goesrecv PUBLIC -DBUILD_RTLSDR)
target_link_libraries(goesrecv rtlsdr_source)
endif()
if(HACKRF_FOUND)
target_compile_definitions(goesrecv PUBLIC -DBUILD_HACKRF)
target_link_libraries(goesrecv hackrf_source)
endif()

add_executable(benchmark benchmark.cc)
target_link_libraries(benchmark pthread)
Expand Down
76 changes: 66 additions & 10 deletions src/goesrecv/config.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include "config.h"

#include <toml/toml.h>

#include <iostream>
#include <sstream>
#include <stdexcept>

#include <toml/toml.h>

namespace {

void throwInvalidKey(const std::string& key) {
Expand All @@ -24,7 +24,8 @@ void setIfZero(T& out, T value) {
std::unique_ptr<SamplePublisher> createSamplePublisher(const toml::Value& v) {
auto bind = v.find("bind");
if (!bind) {
throw std::invalid_argument("Expected publisher section to have \"bind\" key");
throw std::invalid_argument(
"Expected publisher section to have \"bind\" key");
}

// Only need bind value to create publisher
Expand All @@ -42,7 +43,8 @@ std::unique_ptr<SamplePublisher> createSamplePublisher(const toml::Value& v) {
std::unique_ptr<SoftBitPublisher> createSoftBitPublisher(const toml::Value& v) {
auto bind = v.find("bind");
if (!bind) {
throw std::invalid_argument("Expected publisher section to have \"bind\" key");
throw std::invalid_argument(
"Expected publisher section to have \"bind\" key");
}

// Only need bind value to create publisher
Expand All @@ -60,7 +62,8 @@ std::unique_ptr<SoftBitPublisher> createSoftBitPublisher(const toml::Value& v) {
std::unique_ptr<PacketPublisher> createPacketPublisher(const toml::Value& v) {
auto bind = v.find("bind");
if (!bind) {
throw std::invalid_argument("Expected publisher section to have \"bind\" key");
throw std::invalid_argument(
"Expected publisher section to have \"bind\" key");
}

// Only need bind value to create publisher
Expand All @@ -78,7 +81,8 @@ std::unique_ptr<PacketPublisher> createPacketPublisher(const toml::Value& v) {
Config::StatsPublisher createStatsPublisher(const toml::Value& v) {
auto bind = v.find("bind");
if (!bind) {
throw std::invalid_argument("Expected publisher section to have \"bind\" key");
throw std::invalid_argument(
"Expected publisher section to have \"bind\" key");
}

Config::StatsPublisher out;
Expand Down Expand Up @@ -198,6 +202,51 @@ void loadRTLSDRSource(Config::RTLSDR& out, const toml::Value& v) {
}
}

void loadHackRfSource(Config::HackRf& out, const toml::Value& v) {
const auto& table = v.as<toml::Table>();
for (const auto& it : table) {
const auto& key = it.first;
const auto& value = it.second;

if (key == "frequency") {
out.frequency = value.as<int>();
continue;
}

if (key == "sample_rate") {
out.sampleRate = value.as<int>();
continue;
}

if (key == "if_gain") {
out.if_gain = value.as<int>();
continue;
}

if (key == "bb_gain") {
out.bb_gain = value.as<int>();
continue;
}

if (key == "rf_amp_enabled") {
out.rf_amp_enabled = value.as<bool>();
continue;
}

if (key == "sample_publisher") {
out.samplePublisher = createSamplePublisher(value);
continue;
}

if (key == "bias_tee") {
out.bias_tee = value.as<bool>();
continue;
}

throwInvalidKey(key);
}
}

void loadNanomsgSource(Config::Nanomsg& out, const toml::Value& v) {
const auto& table = v.as<toml::Table>();
for (const auto& it : table) {
Expand Down Expand Up @@ -241,12 +290,12 @@ void loadAGC(Config::AGC& out, const toml::Value& v) {
const auto& value = it.second;

if (key == "min") {
out.min = (float) value.as<double>();
out.min = (float)value.as<double>();
continue;
}

if (key == "max") {
out.max = (float) value.as<double>();
out.max = (float)value.as<double>();
continue;
}

Expand All @@ -266,7 +315,7 @@ void loadCostas(Config::Costas& out, const toml::Value& v) {
const auto& value = it.second;

if (key == "max_deviation") {
out.maxDeviation = (int) value.as<double>();
out.maxDeviation = (int)value.as<double>();
if (out.maxDeviation <= 0) {
throw std::invalid_argument("Expected 'max_deviation' to be positive");
}
Expand Down Expand Up @@ -362,7 +411,7 @@ void loadMonitor(Config::Monitor& out, const toml::Value& v) {
}
}

} // namespace
} // namespace

Config Config::load(const std::string& file) {
Config out;
Expand Down Expand Up @@ -392,6 +441,11 @@ Config Config::load(const std::string& file) {
continue;
}

if (key == "hackrf") {
loadHackRfSource(out.hackrf, value);
continue;
}

if (key == "nanomsg") {
loadNanomsgSource(out.nanomsg, value);
continue;
Expand Down Expand Up @@ -446,10 +500,12 @@ Config Config::load(const std::string& file) {
if (out.demodulator.downlinkType == "lrit") {
setIfZero(out.airspy.frequency, 1691000000u);
setIfZero(out.rtlsdr.frequency, 1691000000u);
setIfZero(out.hackrf.frequency, 1691000000u);
}
if (out.demodulator.downlinkType == "hrit") {
setIfZero(out.airspy.frequency, 1694100000u);
setIfZero(out.rtlsdr.frequency, 1694100000u);
setIfZero(out.hackrf.frequency, 1694100000u);
}

return out;
Expand Down
22 changes: 21 additions & 1 deletion src/goesrecv/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,30 @@ struct Config {
bool bias_tee = 0;

std::unique_ptr<SamplePublisher> samplePublisher;
};
};

Airspy airspy;

struct HackRf {
uint32_t frequency = 0;
uint32_t sampleRate = 0;

// Applies to the tuner IF gain setting
uint8_t if_gain = 8;

// Applies to the tuner BB gain setting
uint8_t bb_gain = 30;

// Enables or disables the RF amplifier
bool rf_amp_enabled = 0;

bool bias_tee = 0;

std::unique_ptr<SamplePublisher> samplePublisher;
};

HackRf hackrf;

struct RTLSDR {
uint32_t frequency = 0;
uint32_t sampleRate = 0;
Expand Down
Loading

0 comments on commit d73b6df

Please sign in to comment.