Compare commits
2 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e2494c2159 | |
|
|
8001832de2 |
4
Makefile
4
Makefile
|
|
@ -35,6 +35,10 @@ ifeq ($(BLADERF), yes)
|
|||
LIBS_SDR += $(shell pkg-config --libs libbladeRF)
|
||||
endif
|
||||
|
||||
SDR_OBJ += sdr_soapy.o
|
||||
CFLAGS += $(shell pkg-config --cflags SoapySDR)
|
||||
LIBS_SDR += $(shell pkg-config --libs SoapySDR)
|
||||
|
||||
all: dump1090 view1090
|
||||
|
||||
%.o: %.c *.h
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ typedef enum {
|
|||
//======================== structure declarations =========================
|
||||
|
||||
typedef enum {
|
||||
SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF
|
||||
SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_SOAPY
|
||||
} sdr_type_t;
|
||||
|
||||
// Structure representing one magnitude buffer
|
||||
|
|
|
|||
3
sdr.c
3
sdr.c
|
|
@ -28,6 +28,8 @@
|
|||
# include "sdr_bladerf.h"
|
||||
#endif
|
||||
|
||||
#include "sdr_soapy.h"
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
sdr_type_t sdr_type;
|
||||
|
|
@ -85,6 +87,7 @@ static sdr_handler sdr_handlers[] = {
|
|||
{ "bladerf", SDR_BLADERF, bladeRFInitConfig, bladeRFShowHelp, bladeRFHandleOption, bladeRFOpen, bladeRFRun, bladeRFClose },
|
||||
#endif
|
||||
|
||||
{ "soapy", SDR_SOAPY, soapyInitConfig, soapyShowHelp, soapyHandleOption, soapyOpen, soapyRun, soapyClose },
|
||||
{ "ifile", SDR_IFILE, ifileInitConfig, ifileShowHelp, ifileHandleOption, ifileOpen, ifileRun, ifileClose },
|
||||
{ "none", SDR_NONE, noInitConfig, noShowHelp, noHandleOption, noOpen, noRun, noClose },
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
||||
//
|
||||
// sdr_soapy.c: SoapySDR support
|
||||
//
|
||||
// Copyright (c) 2014-2017 Oliver Jowett <oliver@mutability.co.uk>
|
||||
// Copyright (c) 2017 FlightAware LLC
|
||||
//
|
||||
// This file is free software: you may copy, redistribute and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation, either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "dump1090.h"
|
||||
#include "sdr_soapy.h"
|
||||
|
||||
#include <SoapySDR/Device.h>
|
||||
#include <SoapySDR/Formats.h>
|
||||
static struct {
|
||||
SoapySDRDevice *dev;
|
||||
SoapySDRStream *stream;
|
||||
|
||||
iq_convert_fn converter;
|
||||
struct converter_state *converter_state;
|
||||
} SOAPY;
|
||||
|
||||
//
|
||||
// =============================== SoapySDR handling ==========================
|
||||
//
|
||||
|
||||
void soapyInitConfig()
|
||||
{
|
||||
SOAPY.dev = NULL;
|
||||
SOAPY.stream = NULL;
|
||||
SOAPY.converter = NULL;
|
||||
SOAPY.converter_state = NULL;
|
||||
}
|
||||
|
||||
void soapyShowHelp()
|
||||
{
|
||||
printf(" SoapySDR-specific options (use with --device-type soapy)\n");
|
||||
printf("\n");
|
||||
printf("--device <string> select/configure device\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bool soapyHandleOption(int argc, char **argv, int *jptr)
|
||||
{
|
||||
MODES_NOTUSED(argc);
|
||||
MODES_NOTUSED(argv);
|
||||
MODES_NOTUSED(jptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool soapyOpen(void)
|
||||
{
|
||||
size_t length;
|
||||
SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length);
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
printf("Found device #%d: ", (int)i);
|
||||
for (size_t j = 0; j < results[i].size; j++)
|
||||
{
|
||||
printf("%s=%s, ", results[i].keys[j], results[i].vals[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
SoapySDRKwargsList_clear(results, length);
|
||||
|
||||
SOAPY.dev = SoapySDRDevice_makeStrArgs(Modes.dev_name);
|
||||
if (!SOAPY.dev) {
|
||||
fprintf(stderr, "soapy: failed to create device: %s\n", SoapySDRDevice_lastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SoapySDRKwargs result = SoapySDRDevice_getHardwareInfo(SOAPY.dev);
|
||||
for (size_t i = 0; i < result.size; ++i) {
|
||||
printf("%s=%s\n", result.keys[i], result.vals[i]);
|
||||
}
|
||||
SoapySDRKwargs_clear(&result);
|
||||
|
||||
if (SoapySDRDevice_setSampleRate(SOAPY.dev, SOAPY_SDR_RX, 0, Modes.sample_rate) != 0) {
|
||||
fprintf(stderr, "soapy: setSampleRate failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setFrequency(SOAPY.dev, SOAPY_SDR_RX, 0, Modes.freq, NULL) != 0) {
|
||||
fprintf(stderr, "soapy: setFrequency failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setGain(SOAPY.dev, SOAPY_SDR_RX, 0, Modes.gain / 10.0) != 0) {
|
||||
fprintf(stderr, "soapy: setGain failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setBandwidth(SOAPY.dev, SOAPY_SDR_RX, 0, 3.0e6) != 0) {
|
||||
fprintf(stderr, "soapy: setBandwidth failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_setAntenna(SOAPY.dev, SOAPY_SDR_RX, 0, "LNAW") != 0) {
|
||||
fprintf(stderr, "soapy: setAntenna failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
fprintf(stderr, "soapy: frequency is %.1f MHz\n",
|
||||
SoapySDRDevice_getFrequency(SOAPY.dev, SOAPY_SDR_RX, 0) / 1e6);
|
||||
fprintf(stderr, "soapy: sample rate is %.1f MHz\n",
|
||||
SoapySDRDevice_getSampleRate(SOAPY.dev, SOAPY_SDR_RX, 0) / 1e6);
|
||||
fprintf(stderr, "soapy: bandwidth is %.1f MHz\n",
|
||||
SoapySDRDevice_getBandwidth(SOAPY.dev, SOAPY_SDR_RX, 0) / 1e6);
|
||||
fprintf(stderr, "soapy: gain mode is %d\n",
|
||||
SoapySDRDevice_getGainMode(SOAPY.dev, SOAPY_SDR_RX, 0));
|
||||
fprintf(stderr, "soapy: gain is %.1f dB\n",
|
||||
SoapySDRDevice_getGain(SOAPY.dev, SOAPY_SDR_RX, 0));
|
||||
fprintf(stderr, "soapy: antenna is %s\n",
|
||||
SoapySDRDevice_getAntenna(SOAPY.dev, SOAPY_SDR_RX, 0));
|
||||
|
||||
size_t channels[1] = { 0 };
|
||||
if (SoapySDRDevice_setupStream(SOAPY.dev, &SOAPY.stream, SOAPY_SDR_RX, SOAPY_SDR_CS16, channels, 1, NULL) != 0) {
|
||||
fprintf(stderr, "soapy: setupStream failed: %s\n", SoapySDRDevice_lastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
SOAPY.converter = init_converter(INPUT_SC16,
|
||||
Modes.sample_rate,
|
||||
Modes.dc_filter,
|
||||
&SOAPY.converter_state);
|
||||
if (!SOAPY.converter) {
|
||||
fprintf(stderr, "soapy: can't initialize sample converter\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (SOAPY.dev != NULL) {
|
||||
SoapySDRDevice_unmake(SOAPY.dev);
|
||||
SOAPY.dev = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void soapyRun()
|
||||
{
|
||||
if (!SOAPY.dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SoapySDRDevice_activateStream(SOAPY.dev, SOAPY.stream, 0, 0, 0) != 0) {
|
||||
fprintf(stderr, "soapy: activateStream failed: %s\n", SoapySDRDevice_lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
void *buffers[1];
|
||||
const int buffer_elements = 131072;
|
||||
buffers[0] = malloc(buffer_elements * 4);
|
||||
|
||||
while (!Modes.exit) {
|
||||
int flags;
|
||||
long long timeNs;
|
||||
int sample_count = SoapySDRDevice_readStream(SOAPY.dev, SOAPY.stream, buffers, buffer_elements, &flags, &timeNs, 5000000);
|
||||
if (sample_count <= 0) {
|
||||
fprintf(stderr, "soapy: readStream failed: %s\n", SoapySDRDevice_lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&Modes.data_mutex);
|
||||
unsigned next_free_buffer = (Modes.first_free_buffer + 1) % MODES_MAG_BUFFERS;
|
||||
if (next_free_buffer == Modes.first_filled_buffer) {
|
||||
// drop it
|
||||
fprintf(stderr, "fifo full\n");
|
||||
pthread_mutex_unlock(&Modes.data_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct mag_buf *outbuf = &Modes.mag_buffers[Modes.first_free_buffer];
|
||||
struct mag_buf *lastbuf = &Modes.mag_buffers[(Modes.first_free_buffer + MODES_MAG_BUFFERS - 1) % MODES_MAG_BUFFERS];
|
||||
pthread_mutex_unlock(&Modes.data_mutex);
|
||||
|
||||
// Copy trailing data from last block
|
||||
memcpy(outbuf->data, lastbuf->data + lastbuf->length, Modes.trailing_samples * sizeof(uint16_t));
|
||||
SOAPY.converter(buffers[0], &outbuf->data[Modes.trailing_samples], sample_count,
|
||||
SOAPY.converter_state, &outbuf->mean_level, &outbuf->mean_power);
|
||||
outbuf->dropped = 0;
|
||||
outbuf->length = sample_count;
|
||||
|
||||
pthread_mutex_lock(&Modes.data_mutex);
|
||||
Modes.mag_buffers[next_free_buffer].dropped = 0;
|
||||
Modes.mag_buffers[next_free_buffer].length = 0;
|
||||
Modes.first_free_buffer = next_free_buffer;
|
||||
pthread_cond_signal(&Modes.data_cond);
|
||||
pthread_mutex_unlock(&Modes.data_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void soapyClose()
|
||||
{
|
||||
fprintf(stderr, "close stream\n");
|
||||
if (SOAPY.stream) {
|
||||
SoapySDRDevice_closeStream(SOAPY.dev, SOAPY.stream);
|
||||
SOAPY.stream = NULL;
|
||||
}
|
||||
|
||||
fprintf(stderr, "close device\n");
|
||||
if (SOAPY.dev) {
|
||||
SoapySDRDevice_unmake(SOAPY.dev);
|
||||
SOAPY.dev = NULL;
|
||||
}
|
||||
|
||||
if (SOAPY.converter) {
|
||||
cleanup_converter(SOAPY.converter_state);
|
||||
SOAPY.converter = NULL;
|
||||
SOAPY.converter_state = NULL;
|
||||
}
|
||||
|
||||
fprintf(stderr, "all done\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
||||
//
|
||||
// sdr_soapy.h: SoapySDR dongle support (header)
|
||||
//
|
||||
// Copyright (c) 2016-2017 Oliver Jowett <oliver@mutability.co.uk>
|
||||
// Copyright (c) 2017 FlightAware LLC
|
||||
//
|
||||
// This file is free software: you may copy, redistribute and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation, either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SDR_SOAPY_H
|
||||
#define SDR_SOAPY_H
|
||||
|
||||
void soapyInitConfig();
|
||||
void soapyShowHelp();
|
||||
bool soapyOpen();
|
||||
void soapyRun();
|
||||
void soapyClose();
|
||||
bool soapyHandleOption(int argc, char **argv, int *jptr);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue