2021-12-19 12:09:07 +00:00
|
|
|
#include <SoapySDR/Version.hpp>
|
|
|
|
#include <SoapySDR/Modules.hpp>
|
|
|
|
#include <SoapySDR/Registry.hpp>
|
|
|
|
#include <SoapySDR/Device.hpp>
|
|
|
|
#include <SoapySDR/ConverterRegistry.hpp>
|
2021-12-22 22:30:28 +00:00
|
|
|
|
|
|
|
#include <algorithm>
|
2021-12-19 12:09:07 +00:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <iostream>
|
|
|
|
#include <iomanip>
|
2023-02-16 12:52:40 +00:00
|
|
|
#include <chrono>
|
2021-12-19 12:09:07 +00:00
|
|
|
#include <csignal>
|
|
|
|
#include <chrono>
|
|
|
|
#include <thread>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2021-12-27 22:58:59 +00:00
|
|
|
#include <Iir.h>
|
2021-12-22 22:30:28 +00:00
|
|
|
#include "modes.h"
|
2021-12-19 12:09:07 +00:00
|
|
|
|
2021-12-27 22:58:59 +00:00
|
|
|
|
2023-06-13 06:41:12 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int16_t i;
|
|
|
|
int16_t q;
|
|
|
|
} complex_sample_16_t;
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
//=================================================================================
|
2021-12-19 12:09:07 +00:00
|
|
|
static void printBanner(void)
|
|
|
|
{
|
|
|
|
std::cout << "######################################################" << std::endl;
|
|
|
|
std::cout << "## CaribouLite DUMP1090 - ADS-B Receiver ##" << std::endl;
|
|
|
|
std::cout << "######################################################" << std::endl;
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
//=================================================================================
|
2021-12-19 12:09:07 +00:00
|
|
|
static sig_atomic_t loopDone = false;
|
|
|
|
static void sigIntHandler(const int)
|
|
|
|
{
|
|
|
|
loopDone = true;
|
|
|
|
}
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
//=================================================================================
|
2021-12-22 22:30:28 +00:00
|
|
|
void onModeSMessage(mode_s_t *self, struct mode_s_msg *mm)
|
|
|
|
{
|
2022-04-21 10:04:08 +00:00
|
|
|
mode_s_display_message(mm);
|
|
|
|
printf("\n");
|
2021-12-27 22:58:59 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
//=================================================================================
|
2021-12-27 22:58:59 +00:00
|
|
|
// Turn I/Q samples pointed by `data` into the magnitude vector pointed by `mag`
|
2023-06-13 06:41:12 +00:00
|
|
|
void CalculateMagnitudeVector(complex_sample_16_t *data, uint16_t *mag, uint32_t num_samples)
|
2021-12-27 22:58:59 +00:00
|
|
|
{
|
|
|
|
uint32_t k;
|
2022-04-20 19:39:36 +00:00
|
|
|
float i, q;
|
2021-12-27 22:58:59 +00:00
|
|
|
int t = 0;
|
2023-06-13 06:41:12 +00:00
|
|
|
for (k=0; k<num_samples; k+=1)
|
2021-12-27 22:58:59 +00:00
|
|
|
{
|
2023-06-13 06:41:12 +00:00
|
|
|
float i = (float)data[k].i;
|
|
|
|
float q = (float)data[k].q;
|
2021-12-27 22:58:59 +00:00
|
|
|
|
2023-06-13 06:41:12 +00:00
|
|
|
mag[k]=(uint16_t)sqrtf(i*i + q*q);
|
2021-12-27 22:58:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
//=================================================================================
|
2023-06-13 07:36:20 +00:00
|
|
|
void runSoapyProcess( SoapySDR::Device *device, SoapySDR::Stream *stream, const size_t elemSize)
|
2021-12-19 12:09:07 +00:00
|
|
|
{
|
2022-04-21 10:04:08 +00:00
|
|
|
// allocate buffers for the stream read/write
|
2021-12-19 12:09:07 +00:00
|
|
|
const size_t numElems = device->getStreamMTU(stream);
|
2023-07-09 11:33:37 +00:00
|
|
|
complex_sample_16_t* samples = (complex_sample_16_t*)malloc(sizeof(complex_sample_16_t)*numElems*2);
|
|
|
|
uint16_t* mag = (uint16_t*)malloc(sizeof(uint16_t)*numElems*2);
|
2021-12-19 12:09:07 +00:00
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
// MODE-S
|
|
|
|
mode_s_t state;
|
|
|
|
mode_s_init(&state);
|
2021-12-22 22:30:28 +00:00
|
|
|
|
2021-12-19 12:09:07 +00:00
|
|
|
std::cout << "Starting stream loop, press Ctrl+C to exit..." << std::endl;
|
|
|
|
device->activateStream(stream);
|
|
|
|
signal(SIGINT, sigIntHandler);
|
2023-06-13 07:36:20 +00:00
|
|
|
|
|
|
|
// Main Processing Loop
|
2021-12-19 12:09:07 +00:00
|
|
|
while (not loopDone)
|
|
|
|
{
|
2023-07-09 11:33:37 +00:00
|
|
|
long long timeUS = 2000000;
|
2023-06-13 07:36:20 +00:00
|
|
|
int flags = 0;
|
2023-06-13 06:41:12 +00:00
|
|
|
int numSamplesRead = device->readStream(stream, (void* const*)&samples, numElems, flags, timeUS);
|
2023-06-13 07:36:20 +00:00
|
|
|
if (numSamplesRead < 0)
|
2021-12-19 12:09:07 +00:00
|
|
|
{
|
2023-06-13 06:41:12 +00:00
|
|
|
//std::cerr << "Unexpected stream error " << numSamplesRead << std::endl;
|
2023-02-16 12:52:40 +00:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
|
|
continue;
|
2021-12-19 12:09:07 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
switch (numSamplesRead)
|
|
|
|
{
|
|
|
|
case SOAPY_SDR_TIMEOUT:
|
|
|
|
case SOAPY_SDR_OVERFLOW:
|
|
|
|
case SOAPY_SDR_UNDERFLOW:
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-12-22 22:30:28 +00:00
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
// Proceed to DSP - compute the magnitude of the signal
|
|
|
|
CalculateMagnitudeVector(samples, mag, numSamplesRead);
|
2021-12-19 12:09:07 +00:00
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
// detect Mode S messages in the signal and call on_msg with each message
|
|
|
|
mode_s_detect(&state, mag, numSamplesRead, onModeSMessage);
|
2021-12-19 12:09:07 +00:00
|
|
|
}
|
|
|
|
device->deactivateStream(stream);
|
2022-04-21 10:04:08 +00:00
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
// free memory
|
|
|
|
free(samples);
|
|
|
|
free(mag);
|
2021-12-19 12:09:07 +00:00
|
|
|
}
|
|
|
|
|
2021-12-22 22:30:28 +00:00
|
|
|
|
2021-12-19 12:09:07 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* Main entry point
|
|
|
|
**********************************************************************/
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2023-07-09 11:33:37 +00:00
|
|
|
SoapySDR::ModuleManager mm(false);
|
2021-12-19 12:09:07 +00:00
|
|
|
SoapySDR::Device *device(nullptr);
|
|
|
|
std::vector<size_t> channels;
|
2022-04-20 19:39:36 +00:00
|
|
|
std::string argStr = "driver=Cariboulite,channel=HiF";
|
2021-12-19 12:09:07 +00:00
|
|
|
double fullScale = 0.0;
|
|
|
|
|
|
|
|
printBanner();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
device = SoapySDR::Device::make(argStr);
|
2023-06-13 07:36:20 +00:00
|
|
|
if (device == NULL)
|
|
|
|
{
|
|
|
|
std::cerr << "Initialization Error" << std::endl;
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2021-12-19 12:09:07 +00:00
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
// set the sample rate, frequency, ...
|
2023-06-13 06:41:12 +00:00
|
|
|
device->setSampleRate(SOAPY_SDR_RX, 0, 2e6); // needs to be sampled at 2MSPS
|
2023-06-13 07:36:20 +00:00
|
|
|
device->setBandwidth(SOAPY_SDR_RX, 0, 200e5);
|
|
|
|
device->setGainMode(SOAPY_SDR_RX, 0, false);
|
|
|
|
device->setGain(SOAPY_SDR_RX, 0, 50);
|
|
|
|
device->setFrequency(SOAPY_SDR_RX, 0, 1090e6);
|
2021-12-22 22:30:28 +00:00
|
|
|
|
2023-06-13 07:36:20 +00:00
|
|
|
// create the stream, use the native format
|
2022-04-21 10:04:08 +00:00
|
|
|
const auto format = device->getNativeStreamFormat(SOAPY_SDR_RX, 0, fullScale);
|
2021-12-19 12:09:07 +00:00
|
|
|
const size_t elemSize = SoapySDR::formatToSize(format);
|
|
|
|
auto stream = device->setupStream(SOAPY_SDR_RX, format, channels);
|
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
// run the rate test one setup is complete
|
2023-06-13 07:36:20 +00:00
|
|
|
std::cout << std::endl << "Running Soapy process with CaribouLite Config:" << std::endl;
|
2022-04-21 10:04:08 +00:00
|
|
|
std::cout << " Stream format: " << format << std::endl;
|
|
|
|
std::cout << " Channel: HiF" << std::endl;
|
|
|
|
std::cout << " Sample size: " << elemSize << " bytes" << std::endl;
|
|
|
|
runSoapyProcess(device, stream, elemSize);
|
2021-12-19 12:09:07 +00:00
|
|
|
|
2022-04-21 10:04:08 +00:00
|
|
|
// cleanup stream and device
|
2021-12-19 12:09:07 +00:00
|
|
|
device->closeStream(stream);
|
|
|
|
SoapySDR::Device::unmake(device);
|
|
|
|
}
|
|
|
|
catch (const std::exception &ex)
|
|
|
|
{
|
|
|
|
std::cerr << "Error " << ex.what() << std::endl;
|
|
|
|
SoapySDR::Device::unmake(device);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|