Fix SIGTERM handling and tidy RspDuo

This commit is contained in:
30hours 2024-03-23 15:59:16 +00:00
parent 261496303e
commit f4a4ffba41
9 changed files with 132 additions and 205 deletions

View file

@ -212,3 +212,7 @@ const server_iqdata = net.createServer((socket)=>{
}); });
server_iqdata.listen(config.network.ports.iqdata); server_iqdata.listen(config.network.ports.iqdata);
process.on('SIGTERM', () => {
console.log('SIGTERM signal received.');
process.exit(0);
});

View file

@ -19,8 +19,7 @@ services:
- /dev/usb:/dev/usb:rw - /dev/usb:/dev/usb:rw
network_mode: host network_mode: host
privileged: true privileged: true
command: > command: "/blah2/bin/blah2 -c config/config.yml"
sh -c "/blah2/bin/blah2 -c config/config.yml"
container_name: blah2 container_name: blah2
blah2_web: blah2_web:
@ -41,6 +40,5 @@ services:
volumes: volumes:
- ./config:/usr/src/app/config - ./config:/usr/src/app/config
network_mode: host network_mode: host
command: > command: "node server.js /usr/src/app/config/config.yml"
sh -c "node server.js /usr/src/app/config/config.yml"
container_name: blah2-api container_name: blah2-api

View file

@ -31,8 +31,11 @@
#include <chrono> #include <chrono>
#include <sys/time.h> #include <sys/time.h>
#include <signal.h> #include <signal.h>
#include <atomic>
#include <iostream> #include <iostream>
Capture *CAPTURE_POINTER = NULL;
void signal_callback_handler(int signum); void signal_callback_handler(int signum);
void getopt_print_help(); void getopt_print_help();
std::string getopt_process(int argc, char **argv); std::string getopt_process(int argc, char **argv);
@ -46,7 +49,7 @@ void timing_helper(std::vector<std::string>& timing_name,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// input handling // input handling
signal(SIGINT, signal_callback_handler); signal(SIGTERM, signal_callback_handler);
std::string file = getopt_process(argc, argv); std::string file = getopt_process(argc, argv);
std::ifstream filePath(file); std::ifstream filePath(file);
if (!filePath.is_open()) if (!filePath.is_open())
@ -75,6 +78,7 @@ int main(int argc, char **argv)
tree["network"]["ip"] >> ip_capture; tree["network"]["ip"] >> ip_capture;
tree["network"]["ports"]["api"] >> port_capture; tree["network"]["ports"]["api"] >> port_capture;
Capture *capture = new Capture(type, fs, fc, path); Capture *capture = new Capture(type, fs, fc, path);
CAPTURE_POINTER = capture;
if (state) if (state)
{ {
capture->set_replay(loop, replayFile); capture->set_replay(loop, replayFile);
@ -112,6 +116,7 @@ int main(int argc, char **argv)
fftw_plan_with_nthreads(4); fftw_plan_with_nthreads(4);
// setup socket // setup socket
sleep(5);
uint16_t port_map, port_detection, port_timestamp, uint16_t port_map, port_detection, port_timestamp,
port_timing, port_iqdata, port_track; port_timing, port_iqdata, port_track;
std::string ip; std::string ip;
@ -308,9 +313,15 @@ int main(int argc, char **argv)
} }
void signal_callback_handler(int signum) { void signal_callback_handler(int signum) {
std::cout << std::endl;
std::cout << "Caught signal " << signum << std::endl; std::cout << "Caught signal " << signum << std::endl;
exit(signum); if (CAPTURE_POINTER != nullptr)
{
CAPTURE_POINTER->device->kill();
}
else
{
exit(0);
}
} }
void getopt_print_help() void getopt_print_help()

View file

@ -24,7 +24,7 @@ void Capture::process(IqData *buffer1, IqData *buffer2, c4::yml::NodeRef config,
{ {
std::cout << "Setting up device " + type << std::endl; std::cout << "Setting up device " + type << std::endl;
std::unique_ptr<Source> device = factory_source(type, config); device = factory_source(type, config);
// capture status thread // capture status thread
std::thread t1([&]{ std::thread t1([&]{

View file

@ -47,6 +47,9 @@ public:
/// @brief Absolute path to IQ save location. /// @brief Absolute path to IQ save location.
std::string path; std::string path;
/// @brief Pointer to capture device.
std::unique_ptr<Source> device;
/// @brief Constructor. /// @brief Constructor.
/// @param type The capture device type. /// @param type The capture device type.
/// @param fs Sampling frequency (Hz). /// @param fs Sampling frequency (Hz).

View file

@ -61,3 +61,12 @@ void Source::close_file()
std::ofstream blankFile; std::ofstream blankFile;
std::swap(saveIqFile, blankFile); std::swap(saveIqFile, blankFile);
} }
void Source::kill()
{
if (type == "RspDuo")
{
stop();
}
exit(0);
}

View file

@ -9,6 +9,7 @@
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include <fstream> #include <fstream>
#include <atomic>
#include "data/IqData.h" #include "data/IqData.h"
class Source class Source
@ -79,6 +80,10 @@ public:
/// @return Void. /// @return Void.
void close_file(); void close_file();
/// @brief Graceful handler for SIGTERM.
/// @return Void.
void kill();
}; };
#endif #endif

View file

@ -14,9 +14,6 @@
// class static constants // class static constants
const double RspDuo::MAX_FREQUENCY_NR = 2000000000; const double RspDuo::MAX_FREQUENCY_NR = 2000000000;
const uint8_t RspDuo::DEF_DECIMATION_NR = 1; const uint8_t RspDuo::DEF_DECIMATION_NR = 1;
const int RspDuo::DEF_WAIT_TIME_NR = 0; // default wait time before recording
const int RspDuo::DEF_CHUNK_TIME_NR = 0; // default chunk time of recording
const int RspDuo::MAX_RUN_TIME_NR = 86400; // max run time of recording
const int RspDuo::DEF_AGC_BANDWIDTH_NR = 50; // default agc bandwidth const int RspDuo::DEF_AGC_BANDWIDTH_NR = 50; // default agc bandwidth
const int RspDuo::MIN_AGC_SET_POINT_NR = -72; // min agc set point const int RspDuo::MIN_AGC_SET_POINT_NR = -72; // min agc set point
const int RspDuo::DEF_AGC_SET_POINT_NR = -60; // default agc set point const int RspDuo::DEF_AGC_SET_POINT_NR = -60; // default agc set point
@ -25,7 +22,6 @@ const int RspDuo::DEF_GAIN_REDUCTION_NR = 40; // default gain reduction
const int RspDuo::MAX_GAIN_REDUCTION_NR = 60; // max gain reduction const int RspDuo::MAX_GAIN_REDUCTION_NR = 60; // max gain reduction
const int RspDuo::DEF_LNA_STATE_NR = 4; // default lna state const int RspDuo::DEF_LNA_STATE_NR = 4; // default lna state
const int RspDuo::MAX_LNA_STATE_NR = 9; // max lna state const int RspDuo::MAX_LNA_STATE_NR = 9; // max lna state
const int RspDuo::DEF_SAMPLE_FREQUENCY_NR = 6000000; // default sample frequency
const int RspDuo::DEF_SAMPLE_RATE_NR = 2000000; // default sample rate const int RspDuo::DEF_SAMPLE_RATE_NR = 2000000; // default sample rate
// global variables (SDRPlay) // global variables (SDRPlay)
@ -37,23 +33,16 @@ sdrplay_api_CallbackFnsT cbFns;
sdrplay_api_RxChannelParamsT *chParams; sdrplay_api_RxChannelParamsT *chParams;
// global variables // global variables
//FILE *out_file_fp = NULL;
FILE *file_replay = NULL; FILE *file_replay = NULL;
short *buffer_16_ar = NULL; short *buffer_16_ar = NULL;
struct timeval current_tm = {0, 0};
struct timeval start_tm = {0, 0};
struct timeval chunk_tm = {0, 0};
struct timeval finish_tm = {0, 0};
uint32_t frames_nr = 0; uint32_t frames_nr = 0;
std::string file; std::string file;
short max_a_nr = 0; short max_a_nr = 0;
short max_b_nr = 0; short max_b_nr = 0;
bool run_fg = true; bool run_fg = true;
bool stats_fg = true; bool stats_fg = true;
bool write_fg = true;
bool *capture_fg; bool *capture_fg;
std::ofstream* saveIqFileLocal; std::ofstream* saveIqFileLocal;
int wait_time_nr = 2;
IqData *buffer1; IqData *buffer1;
IqData *buffer2; IqData *buffer2;
@ -64,17 +53,12 @@ RspDuo::RspDuo(std::string _type, uint32_t _fc, uint32_t _fs,
{ {
nDecimation = DEF_DECIMATION_NR; nDecimation = DEF_DECIMATION_NR;
usb_bulk_fg = false; usb_bulk_fg = false;
small_verbose_fg = false;
more_verbose_fg = false;
agc_bandwidth_nr = DEF_AGC_BANDWIDTH_NR; agc_bandwidth_nr = DEF_AGC_BANDWIDTH_NR;
agc_set_point_nr = DEF_AGC_SET_POINT_NR; agc_set_point_nr = DEF_AGC_SET_POINT_NR;
gain_reduction_nr = DEF_GAIN_REDUCTION_NR; gain_reduction_nr = DEF_GAIN_REDUCTION_NR;
lna_state_nr = DEF_LNA_STATE_NR; lna_state_nr = DEF_LNA_STATE_NR;
rf_notch_fg = false; rf_notch_fg = false;
dab_notch_fg = false; dab_notch_fg = false;
chunk_time_nr = DEF_CHUNK_TIME_NR;
//out_file_fp = saveIqFile;
capture_fg = saveIq; capture_fg = saveIq;
saveIqFileLocal = &saveIqFile; saveIqFileLocal = &saveIqFile;
} }
@ -90,7 +74,6 @@ void RspDuo::start()
void RspDuo::stop() void RspDuo::stop()
{ {
uninitialise_device(); uninitialise_device();
finish();
} }
void RspDuo::process(IqData *_buffer1, IqData *_buffer2) void RspDuo::process(IqData *_buffer1, IqData *_buffer2)
@ -103,13 +86,13 @@ void RspDuo::process(IqData *_buffer1, IqData *_buffer2)
// control loop // control loop
while (run_fg) while (run_fg)
{ {
if (write_fg) if (stats_fg)
{ {
fprintf(stderr, "Info - control_loop - frames_nr: %d max_a_nr: %d max_b_nr: %d\n", frames_nr, max_a_nr, max_b_nr); std::cerr << "[RspDuo] frames_nr: " << frames_nr <<
" max_a_nr: " << max_a_nr << " max_b_nr: " << max_b_nr << std::endl;
max_a_nr = 0; max_a_nr = 0;
max_b_nr = 0; max_b_nr = 0;
} }
sleep(1); sleep(1);
} }
} }
@ -129,141 +112,100 @@ void RspDuo::replay(IqData *_buffer1, IqData *_buffer2, std::string _file, bool
rv = fread(&q1, 1, sizeof(short), file_replay); rv = fread(&q1, 1, sizeof(short), file_replay);
rv = fread(&i2, 1, sizeof(short), file_replay); rv = fread(&i2, 1, sizeof(short), file_replay);
rv = fread(&q2, 1, sizeof(short), file_replay); rv = fread(&q2, 1, sizeof(short), file_replay);
buffer1->lock(); buffer1->lock();
buffer2->lock(); buffer2->lock();
if (buffer1->get_length() < buffer1->get_n()) if (buffer1->get_length() < buffer1->get_n())
{ {
buffer1->push_back({(double)i1, (double)q1}); buffer1->push_back({(double)i1, (double)q1});
buffer2->push_back({(double)i2, (double)q2}); buffer2->push_back({(double)i2, (double)q2});
} }
buffer1->unlock(); buffer1->unlock();
buffer2->unlock(); buffer2->unlock();
}
} }
} void RspDuo::validate() {
void RspDuo::validate()
{
// validate decimation // validate decimation
if (this->nDecimation != 1 && this->nDecimation != 2 && this->nDecimation != 4 && if (nDecimation != 1 && nDecimation != 2 && nDecimation != 4 &&
this->nDecimation != 8 && this->nDecimation != 16 && this->nDecimation != 32) nDecimation != 8 && nDecimation != 16 && nDecimation != 32) {
{ std::cerr << "Error: Decimation must be in 1, 2, 4, 8, 16, 32" << std::endl;
fprintf(stderr, "Error - read_command_line - decimation must be in 1, 2, 4, 8, 16, 32\n");
exit(1); exit(1);
} }
// validate fc // validate fc
if (this->fc < 1 || this->fc > MAX_FREQUENCY_NR) if (fc < 1 || fc > MAX_FREQUENCY_NR) {
{ std::cerr << "Error: Frequency must be between 1 and " << MAX_FREQUENCY_NR << std::endl;
fprintf(stderr, "Error - read_command_line - frequency must be between 1 and %.1f\n", MAX_FREQUENCY_NR);
exit(1); exit(1);
} }
// validate agc // validate agc
if (agc_bandwidth_nr != 0 && agc_bandwidth_nr != 5 && agc_bandwidth_nr != 50 && agc_bandwidth_nr != 100) if (agc_bandwidth_nr != 0 && agc_bandwidth_nr != 5 && agc_bandwidth_nr != 50 && agc_bandwidth_nr != 100) {
{ std::cerr << "Error: AGC bandwidth must be in 0, 5, 50, 100" << std::endl;
fprintf(stderr, "Error - read_command_line - agc bandwidth must be in 0, 5, 50, 100\n");
exit(1); exit(1);
} }
if (agc_set_point_nr > 0 || agc_set_point_nr < MIN_AGC_SET_POINT_NR) if (agc_set_point_nr > 0 || agc_set_point_nr < MIN_AGC_SET_POINT_NR) {
{ std::cerr << "Error: AGC set point must be between " << MIN_AGC_SET_POINT_NR << " and 0" << std::endl;
fprintf(stderr, "Error - read_command_line - agc set point must be between %d and 0\n", MIN_AGC_SET_POINT_NR);
exit(1); exit(1);
} }
// validate LNA // validate LNA
if (gain_reduction_nr < MIN_GAIN_REDUCTION_NR || gain_reduction_nr > MAX_GAIN_REDUCTION_NR) if (gain_reduction_nr < MIN_GAIN_REDUCTION_NR || gain_reduction_nr > MAX_GAIN_REDUCTION_NR) {
{ std::cerr << "Error: Gain reduction must be between " << MIN_GAIN_REDUCTION_NR << " and " << MAX_GAIN_REDUCTION_NR << std::endl;
fprintf(stderr, "Error - read_command_line - gain reduction must be between %d and %d\n", MIN_GAIN_REDUCTION_NR, MAX_GAIN_REDUCTION_NR);
exit(1); exit(1);
} }
if (lna_state_nr < 1 || lna_state_nr > MAX_LNA_STATE_NR) if (lna_state_nr < 1 || lna_state_nr > MAX_LNA_STATE_NR) {
{ std::cerr << "Error: LNA state must be between 1 and " << MAX_LNA_STATE_NR << std::endl;
fprintf(stderr, "Error - read_command_line - lna state must be between 1 and %d\n", MAX_LNA_STATE_NR);
exit(1); exit(1);
} }
// validate notch filters // validate notch filters
// validate wait/chunk
if (wait_time_nr < 0 || wait_time_nr > MAX_RUN_TIME_NR)
{
fprintf(stderr, "Error - read_command_line - wait time must be between 0 and %d\n", MAX_RUN_TIME_NR);
exit(1);
}
if (chunk_time_nr < 0 || chunk_time_nr > MAX_RUN_TIME_NR)
{
fprintf(stderr, "Error - read_command_line - chunk time must be between 0 and %d\n", MAX_RUN_TIME_NR);
exit(1);
}
// validate the command line options - other
if (small_verbose_fg && more_verbose_fg)
{
fprintf(stderr, "Error - read_command_line - use only one of -v/-V\n");
exit(1);
}
// print them out // print them out
fprintf(stderr, "\n"); std::cerr << "[RspDuo] Print config" << std::endl;
fprintf(stderr, "fc (Hz) : %d\n", this->fc); std::cerr << "fc (Hz) : " << fc << std::endl;
fprintf(stderr, "file : %s\n", file.c_str()); std::cerr << "fs (Hz) : " << fs << std::endl;
fprintf(stderr, "wait_time_nr (s) : %d\n", wait_time_nr); std::cerr << "file : " << file.c_str() << std::endl;
fprintf(stderr, "chunk_time_nr (s) : %d\n", chunk_time_nr); std::cerr << "agc_bandwidth_nr (Hz) : " << agc_bandwidth_nr << std::endl;
fprintf(stderr, "agc_bandwidth_nr (Hz) : %d\n", agc_bandwidth_nr); std::cerr << "agc_set_point_nr (dBfs) : " << agc_set_point_nr << std::endl;
fprintf(stderr, "agc_set_point_nr (dBfs) : %d\n", agc_set_point_nr); std::cerr << "gain_reduction_nr (dB) : " << gain_reduction_nr << std::endl;
fprintf(stderr, "gain_reduction_nr (dB) : %d\n", gain_reduction_nr); std::cerr << "lna_state_nr : " << lna_state_nr << std::endl;
fprintf(stderr, "lna_state_nr : %d\n", lna_state_nr); std::cerr << "N_DECIMATION : " << nDecimation << std::endl;
fprintf(stderr, "N_DECIMATION : %d\n", this->nDecimation); std::cerr << "rf_notch_fg : " << (rf_notch_fg ? "true" : "false") << std::endl;
fprintf(stderr, "rf_notch_fg : %s\n", rf_notch_fg ? "true" : "false"); std::cerr << "dab_notch_fg : " << (dab_notch_fg ? "true" : "false") << std::endl;
fprintf(stderr, "dab_notch_fg : %s\n", dab_notch_fg ? "true" : "false"); std::cerr << "usb_bulk_fg : " << (usb_bulk_fg ? "true" : "false") << std::endl;
fprintf(stderr, "usb_bulk_fg : %s\n", usb_bulk_fg ? "true" : "false"); std::cerr << "stats_fg : " << (stats_fg ? "true" : "false") << std::endl;
fprintf(stderr, "stats_fg : %s\n", stats_fg ? "true" : "false"); std::cerr << "\n";
fprintf(stderr, "small_verbose_fg : %s\n", small_verbose_fg ? "true" : "false");
fprintf(stderr, "more_verbose_fg : %s\n", more_verbose_fg ? "true" : "false");
fprintf(stderr, "\n");
return;
} }
void RspDuo::open_api() void RspDuo::open_api()
{ {
float ver = 0.0; float ver = 0.0;
// open the sdrplay api // open the sdrplay api
if ((err = sdrplay_api_Open()) != sdrplay_api_Success) if ((err = sdrplay_api_Open()) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_Open failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: API open failed " << sdrplay_api_GetErrorString(err) << std::endl;
exit(1); exit(1);
} }
// enable debug logging output // enable debug logging output
if ((err = sdrplay_api_DebugEnable(NULL, sdrplay_api_DbgLvl_Verbose)) != sdrplay_api_Success) if ((err = sdrplay_api_DebugEnable(NULL, sdrplay_api_DbgLvl_Verbose)) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_DebugEnable failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: Debug enable failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
// check api versions match // check api versions match
if ((err = sdrplay_api_ApiVersion(&ver)) != sdrplay_api_Success) if ((err = sdrplay_api_ApiVersion(&ver)) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_ApiVersion failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: Set API version failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
if (ver != SDRPLAY_API_VERSION) if (ver != SDRPLAY_API_VERSION)
{ {
fprintf(stderr, "Error - open_api - API versions do not match (local=%.2f dll=%.2f)\n", SDRPLAY_API_VERSION, ver); std::cerr << "Error: API versions do not match, local= " << SDRPLAY_API_VERSION << "API= " << ver << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
return;
} }
void RspDuo::get_device() void RspDuo::get_device()
@ -275,7 +217,7 @@ void RspDuo::get_device()
// lock api while device selection is performed // lock api while device selection is performed
if ((err = sdrplay_api_LockDeviceApi()) != sdrplay_api_Success) if ((err = sdrplay_api_LockDeviceApi()) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_LockDeviceApi failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: Lock API during device selection failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -283,17 +225,17 @@ void RspDuo::get_device()
// fetch list of available devices // fetch list of available devices
if ((err = sdrplay_api_GetDevices(devs, &ndev, sizeof(devs) / sizeof(sdrplay_api_DeviceT))) != sdrplay_api_Success) if ((err = sdrplay_api_GetDevices(devs, &ndev, sizeof(devs) / sizeof(sdrplay_api_DeviceT))) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_GetDevices failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: sdrplay_api_GetDevices failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_UnlockDeviceApi(); sdrplay_api_UnlockDeviceApi();
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
fprintf(stderr, "Info - get_device - MaxDevs=%ld NumDevs=%d\n", sizeof(devs) / sizeof(sdrplay_api_DeviceT), ndev); std::cerr << "[RspDuo] MaxDevs=" << sizeof(devs) / sizeof(sdrplay_api_DeviceT) << " NumDevs=" << ndev << std::endl;
if (ndev == 0) if (ndev == 0)
{ {
fprintf(stderr, "Error - get_device - no devices found\n"); std::cerr << "Error: No devices found" << std::endl;
sdrplay_api_UnlockDeviceApi(); sdrplay_api_UnlockDeviceApi();
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
@ -305,15 +247,13 @@ void RspDuo::get_device()
if (devs[i].hwVer == SDRPLAY_RSPduo_ID) if (devs[i].hwVer == SDRPLAY_RSPduo_ID)
{ {
chosenIdx = i; chosenIdx = i;
fprintf(stderr, "Info - get_device - Dev%d: SerNo=%s hwVer=%d tuner=0x%.2x rspDuoMode=0x%.2x\n",
i, devs[i].SerNo, devs[i].hwVer, devs[i].tuner, devs[i].rspDuoMode);
break; break;
} }
} }
if (i == ndev) if (i == ndev)
{ {
fprintf(stderr, "Error - get_device - could not find a suitable RSPduo device to open\n"); std::cerr << "Error: Could not find a suitable RSPduo device to open" << std::endl;
sdrplay_api_UnlockDeviceApi(); sdrplay_api_UnlockDeviceApi();
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
@ -321,20 +261,20 @@ void RspDuo::get_device()
chosenDevice = &devs[chosenIdx]; chosenDevice = &devs[chosenIdx];
fprintf(stderr, "Info - get_device - chosenDevice=%d\n", chosenIdx);
// set operating mode // set operating mode
chosenDevice->tuner = sdrplay_api_Tuner_Both; chosenDevice->tuner = sdrplay_api_Tuner_Both;
chosenDevice->rspDuoMode = sdrplay_api_RspDuoMode_Dual_Tuner; chosenDevice->rspDuoMode = sdrplay_api_RspDuoMode_Dual_Tuner;
chosenDevice->rspDuoSampleFreq = DEF_SAMPLE_FREQUENCY_NR;
fprintf(stderr, "Info - get_device - Dev%d: selected rspDuoMode=0x%.2x tuner=0x%.2x rspDuoSampleFreq=%.1f\n", std::cerr << "[RspDuo] Device ID " << chosenIdx << std::endl;
chosenIdx, chosenDevice->rspDuoMode, chosenDevice->tuner, chosenDevice->rspDuoSampleFreq); std::cerr << "[RspDuo] Serial Number " << devs[i].SerNo << std::endl;
std::cerr << "[RspDuo] Hardware Version " << std::to_string(devs[i].hwVer) << std::endl;
std::cerr << "[RspDuo] Tuner " << std::hex << chosenDevice->tuner << std::dec << std::endl;
std::cerr << "[RspDuo] RspDuoMode " << std::hex << chosenDevice->rspDuoMode << std::dec << std::endl;
// select chosen device // select chosen device
if ((err = sdrplay_api_SelectDevice(chosenDevice)) != sdrplay_api_Success) if ((err = sdrplay_api_SelectDevice(chosenDevice)) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_SelectDevice failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: Select device failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_UnlockDeviceApi(); sdrplay_api_UnlockDeviceApi();
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
@ -343,7 +283,7 @@ void RspDuo::get_device()
// unlock api now that device is selected // unlock api now that device is selected
if ((err = sdrplay_api_UnlockDeviceApi()) != sdrplay_api_Success) if ((err = sdrplay_api_UnlockDeviceApi()) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_UnlockDeviceApi failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: Unlock device API failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -356,7 +296,7 @@ void RspDuo::set_device_parameters()
// retrieve device parameters so they can be changed if wanted // retrieve device parameters so they can be changed if wanted
if ((err = sdrplay_api_GetDeviceParams(chosenDevice->dev, &deviceParams)) != sdrplay_api_Success) if ((err = sdrplay_api_GetDeviceParams(chosenDevice->dev, &deviceParams)) != sdrplay_api_Success)
{ {
std::cerr << "Error - sdrplay_api_GetDeviceParams failed " + std::string(sdrplay_api_GetErrorString(err)) << std::endl; std::cout << "Error: sdrplay_api_GetDeviceParams failed " + std::string(sdrplay_api_GetErrorString(err)) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -364,7 +304,7 @@ void RspDuo::set_device_parameters()
// check for NULL pointer before changing settings // check for NULL pointer before changing settings
if (deviceParams == NULL) if (deviceParams == NULL)
{ {
std::cerr << "Error - sdrplay_api_GetDeviceParams returned NULL deviceParams pointer" << std::endl; std::cout << "Error: Device parameters pointer is null" << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -385,13 +325,13 @@ void RspDuo::set_device_parameters()
// check for NULL pointer before changing settings // check for NULL pointer before changing settings
if (chParams == NULL) if (chParams == NULL)
{ {
std::cerr << "Error - sdrplay_api_GetDeviceParams returned NULL chParams pointer" << std::endl; std::cerr << "Error: Channel parameters pointer is null" << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
// set center frequency // set center frequency
chParams->tunerParams.rfFreq.rfHz = this->fc; chParams->tunerParams.rfFreq.rfHz = fc;
// set AGC // set AGC
chParams->ctrlParams.agc.enable = sdrplay_api_AGC_DISABLE; chParams->ctrlParams.agc.enable = sdrplay_api_AGC_DISABLE;
@ -418,21 +358,21 @@ void RspDuo::set_device_parameters()
// set decimation and IF frequency and analog bandwidth // set decimation and IF frequency and analog bandwidth
chParams->ctrlParams.decimation.enable = 1; chParams->ctrlParams.decimation.enable = 1;
chParams->ctrlParams.decimation.decimationFactor = this->nDecimation; chParams->ctrlParams.decimation.decimationFactor = nDecimation;
chParams->tunerParams.ifType = sdrplay_api_IF_1_620; chParams->tunerParams.ifType = sdrplay_api_IF_1_620;
chParams->tunerParams.bwType = sdrplay_api_BW_1_536; chParams->tunerParams.bwType = sdrplay_api_BW_1_536;
if (this->nDecimation == 4) if (nDecimation == 4)
{ {
// 2 MSa/s / 4 = 500 kHz // 2 MSa/s / 4 = 500 kHz
chParams->tunerParams.bwType = sdrplay_api_BW_0_600; chParams->tunerParams.bwType = sdrplay_api_BW_0_600;
} }
else if (this->nDecimation == 8) else if (nDecimation == 8)
{ {
// 2 MSa/s / 8 = 250 kHz // 2 MSa/s / 8 = 250 kHz
chParams->tunerParams.bwType = sdrplay_api_BW_0_300; chParams->tunerParams.bwType = sdrplay_api_BW_0_300;
} }
else if (this->nDecimation == 16 || this->nDecimation == 32) else if (nDecimation == 16 || nDecimation == 32)
{ {
// 2 MSa/s / 16 = 125 kHz // 2 MSa/s / 16 = 125 kHz
// 2 MSa/s / 32 = 62.5 kHz // 2 MSa/s / 32 = 62.5 kHz
@ -462,7 +402,7 @@ void RspDuo::stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT
if (buffer_16_ar == NULL) if (buffer_16_ar == NULL)
{ {
std::cerr << "Error - stream_a_callback - malloc failed" << std::endl; std::cout << "Error: stream_a_callback, malloc failed" << std::endl;
run_fg = false; run_fg = false;
return; return;
} }
@ -479,7 +419,7 @@ void RspDuo::stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT
} }
// find max for stats // find max for stats
if (stats_fg && write_fg) if (stats_fg)
{ {
for (i = 0; i < numSamples; i++) for (i = 0; i < numSamples; i++)
{ {
@ -520,24 +460,15 @@ void RspDuo::stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT
buffer1->unlock(); buffer1->unlock();
buffer2->unlock(); buffer2->unlock();
// decide if to write data
gettimeofday(&current_tm, NULL);
// write if over start time
if (start_tm.tv_sec + wait_time_nr <= current_tm.tv_sec)
{
write_fg = true;
}
// write data to file // write data to file
if (*capture_fg && write_fg) if (*capture_fg)
{ {
saveIqFileLocal->write(reinterpret_cast<char*>(buffer_16_ar), saveIqFileLocal->write(reinterpret_cast<char*>(buffer_16_ar),
sizeof(short) * numSamples * 4); sizeof(short) * numSamples * 4);
if (!(*saveIqFileLocal)) if (!(*saveIqFileLocal))
{ {
std::cerr << "Error - stream_b_callback - not enough samples received" << std::endl; std::cout << "Error: stream_b_callback, not enough samples received" << std::endl;
free(buffer_16_ar); free(buffer_16_ar);
run_fg = false; run_fg = false;
return; return;
@ -549,7 +480,7 @@ void RspDuo::stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT
free(buffer_16_ar); free(buffer_16_ar);
// find max for stats // find max for stats
if (stats_fg && write_fg) if (stats_fg)
{ {
for (i = 0; i < numSamples; i++) for (i = 0; i < numSamples; i++)
{ {
@ -565,29 +496,32 @@ void RspDuo::stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT
void RspDuo::event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext) void RspDuo::event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext)
{ {
std::string tuner_str = (tuner == sdrplay_api_Tuner_A) ? "sdrplay_api_Tuner_A" : "sdrplay_api_Tuner_B";
switch (eventId) switch (eventId)
{ {
case sdrplay_api_GainChange: case sdrplay_api_GainChange:
fprintf(stderr, "Info - event_callback - GainChange tuner=%s gRdB=%d lnaGRdB=%d systemGain=%.2f\n", std::cerr << "[RspDuo] Gain change, tuner=" << tuner_str << " ";
(tuner == sdrplay_api_Tuner_A) ? "sdrplay_api_Tuner_A" : "sdrplay_api_Tuner_B", std::cerr << "gRdB=" << params->gainParams.gRdB << " ";
params->gainParams.gRdB, params->gainParams.lnaGRdB, params->gainParams.currGain); std::cerr << "lnaGRdB=" << params->gainParams.lnaGRdB << " ";
std::cerr << "systemGain=" << params->gainParams.currGain << std::endl;
break; break;
case sdrplay_api_PowerOverloadChange: case sdrplay_api_PowerOverloadChange:
fprintf(stderr, "Info - event_callback - PowerOverloadChange tuner=%s powerOverloadChangeType=%s\n", std::cerr << "[RspDuo] PowerOverloadChange, tuner=" << tuner_str << " ";
(tuner == sdrplay_api_Tuner_A) ? "sdrplay_api_Tuner_A" : "sdrplay_api_Tuner_B", std::cerr << "powerOverloadChangeType=" <<
(params->powerOverloadParams.powerOverloadChangeType == sdrplay_api_Overload_Detected) ? "sdrplay_api_Overload_Detected" : "sdrplay_api_Overload_Corrected"); ((params->powerOverloadParams.powerOverloadChangeType
== sdrplay_api_Overload_Detected) ? "sdrplay_api_Overload_Detected" :
"sdrplay_api_Overload_Corrected") << std::endl;
// send update message to acknowledge power overload message received // send update message to acknowledge power overload message received
sdrplay_api_Update(chosenDevice->dev, tuner, sdrplay_api_Update_Ctrl_OverloadMsgAck, sdrplay_api_Update_Ext1_None); sdrplay_api_Update(chosenDevice->dev, tuner, sdrplay_api_Update_Ctrl_OverloadMsgAck, sdrplay_api_Update_Ext1_None);
break; break;
case sdrplay_api_DeviceRemoved: case sdrplay_api_DeviceRemoved:
fprintf(stderr, "Info - event_callback - device removed\n"); std::cerr << "[RspDuo] Device removed" << std::endl;
break; break;
default: default:
fprintf(stderr, "Info - event_callback - unknown event %d\n", eventId); std::cerr << "[RspDuo] Unknown event " << eventId << std::endl;
break; break;
} }
} }
@ -596,7 +530,7 @@ void RspDuo::initialise_device()
{ {
if ((err = sdrplay_api_Init(chosenDevice->dev, &cbFns, NULL)) != sdrplay_api_Success) if ((err = sdrplay_api_Init(chosenDevice->dev, &cbFns, NULL)) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_Init failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: sdrplay_api_Init failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -606,7 +540,7 @@ void RspDuo::uninitialise_device()
{ {
if ((err = sdrplay_api_Uninit(chosenDevice->dev)) != sdrplay_api_Success) if ((err = sdrplay_api_Uninit(chosenDevice->dev)) != sdrplay_api_Success)
{ {
fprintf(stderr, "Error - sdrplay_api_Uninit failed %s\n", sdrplay_api_GetErrorString(err)); std::cerr << "Error: sdrplay_api_Uninit failed " << sdrplay_api_GetErrorString(err) << std::endl;
sdrplay_api_Close(); sdrplay_api_Close();
exit(1); exit(1);
} }
@ -615,22 +549,3 @@ void RspDuo::uninitialise_device()
sdrplay_api_UnlockDeviceApi(); sdrplay_api_UnlockDeviceApi();
sdrplay_api_Close(); sdrplay_api_Close();
} }
void RspDuo::finish()
{
char time_tx[BUFFER_SIZE_NR];
// close files
close_file();
// get finish date and time
gettimeofday(&finish_tm, NULL);
strftime(time_tx, sizeof(time_tx), "%d %b %Y %H:%M:%S", localtime(&finish_tm.tv_sec));
fprintf(stderr, "\n");
fprintf(stderr, "Info - finish - finish_tm: %s.%03ld\n", time_tx, finish_tm.tv_usec / 1000);
fprintf(stderr, "Info - finish - frames_nr: %d\n", frames_nr);
return;
}

View file

@ -31,8 +31,6 @@
class RspDuo : public Source class RspDuo : public Source
{ {
private: private:
/// @brief chunk time of recording (s)
int chunk_time_nr;
/// @brief AGC bandwidth (Hz) /// @brief AGC bandwidth (Hz)
int agc_bandwidth_nr; int agc_bandwidth_nr;
/// @brief AGC set point (dBfs) /// @brief AGC set point (dBfs)
@ -49,21 +47,11 @@ private:
bool dab_notch_fg; bool dab_notch_fg;
/// @brief USB bulk transfer mode. /// @brief USB bulk transfer mode.
bool usb_bulk_fg; bool usb_bulk_fg;
/// @brief Debugging.
bool small_verbose_fg;
/// @brief Debugging.
bool more_verbose_fg;
/// @brief Maximum frequency (Hz). /// @brief Maximum frequency (Hz).
static const double MAX_FREQUENCY_NR; static const double MAX_FREQUENCY_NR;
/// @brief Default decimation. /// @brief Default decimation.
static const uint8_t DEF_DECIMATION_NR; static const uint8_t DEF_DECIMATION_NR;
/// @brief Default wait time before recording.
static const int DEF_WAIT_TIME_NR;
/// @brief Default chunk time of recording.
static const int DEF_CHUNK_TIME_NR;
/// @brief Maximum run time of recording.
static const int MAX_RUN_TIME_NR;
/// @brief Default AGC bandwidth. /// @brief Default AGC bandwidth.
static const int DEF_AGC_BANDWIDTH_NR; static const int DEF_AGC_BANDWIDTH_NR;
/// @brief Minimum AGC set point. /// @brief Minimum AGC set point.
@ -80,8 +68,6 @@ private:
static const int DEF_LNA_STATE_NR; static const int DEF_LNA_STATE_NR;
/// @brief Max LNA state. /// @brief Max LNA state.
static const int MAX_LNA_STATE_NR; static const int MAX_LNA_STATE_NR;
/// @brief Default sample frequency.
static const int DEF_SAMPLE_FREQUENCY_NR;
/// @brief Default sample rate. /// @brief Default sample rate.
static const int DEF_SAMPLE_RATE_NR; static const int DEF_SAMPLE_RATE_NR;
@ -174,10 +160,6 @@ private:
/// @return Void. /// @return Void.
void uninitialise_device(); void uninitialise_device();
/// @brief Internal method to gracefully stop capture..
/// @return Void.
void finish();
public: public:
/// @brief Constructor. /// @brief Constructor.
/// @param fc Center frequency (Hz). /// @param fc Center frequency (Hz).