Skip to content

Commit d73b6df

Browse files
committed
Add support for HackRF.
1 parent 9f21e52 commit d73b6df

File tree

10 files changed

+385
-37
lines changed

10 files changed

+385
-37
lines changed

docs/commands/goesrecv.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,19 @@ Demodulate and decode signal into packet stream.
1313
See :ref:`minimal_receiver` for an example setup.
1414

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

2323
.. _rtl-sdr:
2424
https://rtlsdr.org/
2525
.. _airspy:
2626
https://airspy.com/
27+
.. _hackrf:
28+
https://greatscottgadgets.com/hackrf/
2729

2830
Options
2931
=======

docs/installation.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ Install system dependencies:
5151
5252
If you want to run goesrecv on this machine, you also have to install
5353
the development packages of the drivers the SDRs you want to use;
54-
``librtlsdr-dev`` for an RTL-SDR, ``libairspy-dev`` for an Airspy.
54+
``librtlsdr-dev`` for an RTL-SDR, ``libairspy-dev`` for an Airspy,
55+
and ``libhackrf-dev`` for a HackRf.
5556

5657
Now you can build and install goestools:
5758

etc/goesrecv.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ source = "airspy"
3333
# bias_tee = false
3434
# device_index = 0
3535

36+
# [hackrf]
37+
# frequency = 1694100000
38+
# sample_rate = 8000000
39+
# if_gain = 32
40+
# bb_gain = 34
41+
# rf_amp_enabled = true
42+
# bias_tee = false
43+
3644
# [nanomsg]
3745
# sample_rate = 2400000
3846
# connect = "tcp://1.2.3.4:5005"

scripts/setup_raspbian.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ urls() {
2323
scripts/list_raspbian_urls.py \
2424
librtlsdr-dev \
2525
libairspy-dev \
26+
libhackrf-dev \
2627
libusb-1.0-0-dev \
2728
libudev1 \
2829
zlib1g-dev \

src/goesrecv/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ else()
2929
target_link_libraries(rtlsdr_source ${RTLSDR_LIBRARIES} publisher stdc++)
3030
endif()
3131

32+
pkg_check_modules(HACKRF libhackrf)
33+
if(NOT HACKRF_FOUND)
34+
message(WARNING "Unable to find libhackrf")
35+
else()
36+
add_library(hackrf_source hackrf_source.cc)
37+
target_link_libraries(hackrf_source ${HACKRF_LIBRARIES} publisher stdc++)
38+
endif()
39+
3240
add_library(nanomsg_source nanomsg_source.cc)
3341
target_link_libraries(nanomsg_source nanomsg publisher stdc++)
3442

@@ -60,6 +68,7 @@ target_link_libraries(goesrecv clock_recovery)
6068
target_link_libraries(goesrecv quantize)
6169
target_link_libraries(goesrecv nanomsg_source)
6270
target_link_libraries(goesrecv version)
71+
6372
if(AIRSPY_FOUND)
6473
target_compile_definitions(goesrecv PUBLIC -DBUILD_AIRSPY)
6574
target_link_libraries(goesrecv airspy_source)
@@ -68,6 +77,10 @@ if(RTLSDR_FOUND)
6877
target_compile_definitions(goesrecv PUBLIC -DBUILD_RTLSDR)
6978
target_link_libraries(goesrecv rtlsdr_source)
7079
endif()
80+
if(HACKRF_FOUND)
81+
target_compile_definitions(goesrecv PUBLIC -DBUILD_HACKRF)
82+
target_link_libraries(goesrecv hackrf_source)
83+
endif()
7184

7285
add_executable(benchmark benchmark.cc)
7386
target_link_libraries(benchmark pthread)

src/goesrecv/config.cc

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#include "config.h"
22

3+
#include <toml/toml.h>
4+
35
#include <iostream>
46
#include <sstream>
57
#include <stdexcept>
68

7-
#include <toml/toml.h>
8-
99
namespace {
1010

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

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

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

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

8488
Config::StatsPublisher out;
@@ -198,6 +202,51 @@ void loadRTLSDRSource(Config::RTLSDR& out, const toml::Value& v) {
198202
}
199203
}
200204

205+
void loadHackRfSource(Config::HackRf& out, const toml::Value& v) {
206+
const auto& table = v.as<toml::Table>();
207+
for (const auto& it : table) {
208+
const auto& key = it.first;
209+
const auto& value = it.second;
210+
211+
if (key == "frequency") {
212+
out.frequency = value.as<int>();
213+
continue;
214+
}
215+
216+
if (key == "sample_rate") {
217+
out.sampleRate = value.as<int>();
218+
continue;
219+
}
220+
221+
if (key == "if_gain") {
222+
out.if_gain = value.as<int>();
223+
continue;
224+
}
225+
226+
if (key == "bb_gain") {
227+
out.bb_gain = value.as<int>();
228+
continue;
229+
}
230+
231+
if (key == "rf_amp_enabled") {
232+
out.rf_amp_enabled = value.as<bool>();
233+
continue;
234+
}
235+
236+
if (key == "sample_publisher") {
237+
out.samplePublisher = createSamplePublisher(value);
238+
continue;
239+
}
240+
241+
if (key == "bias_tee") {
242+
out.bias_tee = value.as<bool>();
243+
continue;
244+
}
245+
246+
throwInvalidKey(key);
247+
}
248+
}
249+
201250
void loadNanomsgSource(Config::Nanomsg& out, const toml::Value& v) {
202251
const auto& table = v.as<toml::Table>();
203252
for (const auto& it : table) {
@@ -241,12 +290,12 @@ void loadAGC(Config::AGC& out, const toml::Value& v) {
241290
const auto& value = it.second;
242291

243292
if (key == "min") {
244-
out.min = (float) value.as<double>();
293+
out.min = (float)value.as<double>();
245294
continue;
246295
}
247296

248297
if (key == "max") {
249-
out.max = (float) value.as<double>();
298+
out.max = (float)value.as<double>();
250299
continue;
251300
}
252301

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

268317
if (key == "max_deviation") {
269-
out.maxDeviation = (int) value.as<double>();
318+
out.maxDeviation = (int)value.as<double>();
270319
if (out.maxDeviation <= 0) {
271320
throw std::invalid_argument("Expected 'max_deviation' to be positive");
272321
}
@@ -362,7 +411,7 @@ void loadMonitor(Config::Monitor& out, const toml::Value& v) {
362411
}
363412
}
364413

365-
} // namespace
414+
} // namespace
366415

367416
Config Config::load(const std::string& file) {
368417
Config out;
@@ -392,6 +441,11 @@ Config Config::load(const std::string& file) {
392441
continue;
393442
}
394443

444+
if (key == "hackrf") {
445+
loadHackRfSource(out.hackrf, value);
446+
continue;
447+
}
448+
395449
if (key == "nanomsg") {
396450
loadNanomsgSource(out.nanomsg, value);
397451
continue;
@@ -446,10 +500,12 @@ Config Config::load(const std::string& file) {
446500
if (out.demodulator.downlinkType == "lrit") {
447501
setIfZero(out.airspy.frequency, 1691000000u);
448502
setIfZero(out.rtlsdr.frequency, 1691000000u);
503+
setIfZero(out.hackrf.frequency, 1691000000u);
449504
}
450505
if (out.demodulator.downlinkType == "hrit") {
451506
setIfZero(out.airspy.frequency, 1694100000u);
452507
setIfZero(out.rtlsdr.frequency, 1694100000u);
508+
setIfZero(out.hackrf.frequency, 1694100000u);
453509
}
454510

455511
return out;

src/goesrecv/config.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,30 @@ struct Config {
4444
bool bias_tee = 0;
4545

4646
std::unique_ptr<SamplePublisher> samplePublisher;
47-
};
47+
};
4848

4949
Airspy airspy;
5050

51+
struct HackRf {
52+
uint32_t frequency = 0;
53+
uint32_t sampleRate = 0;
54+
55+
// Applies to the tuner IF gain setting
56+
uint8_t if_gain = 8;
57+
58+
// Applies to the tuner BB gain setting
59+
uint8_t bb_gain = 30;
60+
61+
// Enables or disables the RF amplifier
62+
bool rf_amp_enabled = 0;
63+
64+
bool bias_tee = 0;
65+
66+
std::unique_ptr<SamplePublisher> samplePublisher;
67+
};
68+
69+
HackRf hackrf;
70+
5171
struct RTLSDR {
5272
uint32_t frequency = 0;
5373
uint32_t sampleRate = 0;

0 commit comments

Comments
 (0)