mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-27 06:08:37 -05:00
Restart the device automatically if stuck with read stream errors
This commit is contained in:
parent
c64baab99d
commit
acc6d2a31d
@ -84,7 +84,7 @@ static int audioCallback(void *outputBuffer, void * /* inputBuffer */, unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
std::cout << "Audio buffer underflow.." << (src->underflowCount++) << std::endl;
|
std::cout << "Audio buffer underflow.." << (src->underflowCount++) << std::endl << std::flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src->boundThreads.empty()) {
|
if (src->boundThreads.empty()) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <SoapySDR/Logger.h>
|
#include <SoapySDR/Logger.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#define TARGET_DISPLAY_FPS 60
|
#define TARGET_DISPLAY_FPS 60
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ void SDRThread::assureBufferMinSize(SDRThreadIQData * dataOut, size_t minSize) {
|
|||||||
//Called in an infinite loop, read SaopySDR device to build
|
//Called in an infinite loop, read SaopySDR device to build
|
||||||
// a 'this.numElems' sized batch of samples (SDRThreadIQData) and push it into iqDataOutQueue.
|
// a 'this.numElems' sized batch of samples (SDRThreadIQData) and push it into iqDataOutQueue.
|
||||||
//this batch of samples is built to represent 1 frame / TARGET_DISPLAY_FPS.
|
//this batch of samples is built to represent 1 frame / TARGET_DISPLAY_FPS.
|
||||||
void SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
|
int SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
|
||||||
int flags;
|
int flags;
|
||||||
long long timeNs;
|
long long timeNs;
|
||||||
|
|
||||||
@ -234,6 +235,8 @@ void SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
|
|||||||
}
|
}
|
||||||
} //end if numOverflow > 0
|
} //end if numOverflow > 0
|
||||||
|
|
||||||
|
int readStreamCode = 0;
|
||||||
|
|
||||||
//2. attempt readStream() at most nElems, by mtElems-sized chunks, append in dataOut->data directly.
|
//2. attempt readStream() at most nElems, by mtElems-sized chunks, append in dataOut->data directly.
|
||||||
while (n_read < nElems && !stopping) {
|
while (n_read < nElems && !stopping) {
|
||||||
|
|
||||||
@ -241,6 +244,8 @@ void SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
|
|||||||
//from which SoapySDR effectively returns n_stream_read.
|
//from which SoapySDR effectively returns n_stream_read.
|
||||||
int n_stream_read = device->readStream(stream, buffs, mtElems, flags, timeNs);
|
int n_stream_read = device->readStream(stream, buffs, mtElems, flags, timeNs);
|
||||||
|
|
||||||
|
readStreamCode = n_stream_read;
|
||||||
|
|
||||||
//if the n_stream_read <= 0, bail out from reading.
|
//if the n_stream_read <= 0, bail out from reading.
|
||||||
if (n_stream_read == 0) {
|
if (n_stream_read == 0) {
|
||||||
std::cout << "SDRThread::readStream(): 2. SoapySDR read blocking..." << std::endl;
|
std::cout << "SDRThread::readStream(): 2. SoapySDR read blocking..." << std::endl;
|
||||||
@ -362,10 +367,15 @@ void SDRThread::readStream(SDRThreadIQDataQueuePtr iqDataOutQueue) {
|
|||||||
//saturation, let a chance to the other threads to consume the existing samples
|
//saturation, let a chance to the other threads to consume the existing samples
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return readStreamCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SDRThread::readLoop() {
|
void SDRThread::readLoop() {
|
||||||
|
|
||||||
|
#define STREAM_READ_WATCHDOG_S (2)
|
||||||
|
|
||||||
SDRThreadIQDataQueuePtr iqDataOutQueue = std::static_pointer_cast<SDRThreadIQDataQueue>( getOutputQueue("IQDataOutput"));
|
SDRThreadIQDataQueuePtr iqDataOutQueue = std::static_pointer_cast<SDRThreadIQDataQueue>( getOutputQueue("IQDataOutput"));
|
||||||
|
|
||||||
if (iqDataOutQueue == nullptr) {
|
if (iqDataOutQueue == nullptr) {
|
||||||
@ -374,10 +384,35 @@ void SDRThread::readLoop() {
|
|||||||
|
|
||||||
updateGains();
|
updateGains();
|
||||||
|
|
||||||
|
auto streamWatchDog = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
while (!stopping.load()) {
|
while (!stopping.load()) {
|
||||||
|
|
||||||
updateSettings();
|
updateSettings();
|
||||||
readStream(iqDataOutQueue);
|
|
||||||
|
if (readStream(iqDataOutQueue) > 0) {
|
||||||
|
// record the date of the last good read.
|
||||||
|
streamWatchDog = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
//check watchdog value: if the date is too old, deinit end init the device.
|
||||||
|
std::chrono::duration<double> diff = now - streamWatchDog;
|
||||||
|
|
||||||
|
if (diff.count() > STREAM_READ_WATCHDOG_S) {
|
||||||
|
|
||||||
|
std::cout << "SDRThread::readStream(): Restarting stream after too many read erros..." << std::endl << std::flush;
|
||||||
|
|
||||||
|
deinit();
|
||||||
|
init();
|
||||||
|
|
||||||
|
streamWatchDog = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
std::cout << "SDRThread::readStream(): stream restarted." << std::endl << std::flush;
|
||||||
|
}
|
||||||
|
} //End while
|
||||||
|
|
||||||
iqDataOutQueue->flush();
|
iqDataOutQueue->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +47,17 @@ class SDRThread : public IOThread {
|
|||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
void deinit();
|
void deinit();
|
||||||
void readStream(SDRThreadIQDataQueuePtr iqDataOutQueue);
|
|
||||||
|
//returns the SoapyDevice readStream return value,
|
||||||
|
//i.e if >= 0 the numbre of samples read, else if < 0 an error code.
|
||||||
|
int readStream(SDRThreadIQDataQueuePtr iqDataOutQueue);
|
||||||
|
|
||||||
void readLoop();
|
void readLoop();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SDRThread();
|
SDRThread();
|
||||||
~SDRThread();
|
~SDRThread();
|
||||||
|
|
||||||
enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_INITIALIZED, SDR_THREAD_FAILED};
|
enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_INITIALIZED, SDR_THREAD_FAILED};
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
Loading…
Reference in New Issue
Block a user