BUGFIX : Missed data causes timestamp slip

The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.

To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().

Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer.  This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.

It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
This commit is contained in:
Malcolm Robb 2014-02-22 23:11:13 +00:00
parent 24080a22b1
commit 75a4c6ee21
4 changed files with 108 additions and 48 deletions

View file

@ -81,7 +81,7 @@
#define MODES_DEFAULT_FREQ 1090000000
#define MODES_DEFAULT_WIDTH 1000
#define MODES_DEFAULT_HEIGHT 700
#define MODES_ASYNC_BUF_NUMBER 12
#define MODES_ASYNC_BUF_NUMBER 16
#define MODES_ASYNC_BUF_SIZE (16*16384) // 256k
#define MODES_ASYNC_BUF_SAMPLES (MODES_ASYNC_BUF_SIZE / 2) // Each sample is 2 bytes
#define MODES_AUTO_GAIN -100 // Use automatic gain
@ -225,15 +225,21 @@ struct aircraft {
// Program global state
struct { // Internal state
pthread_t reader_thread;
pthread_mutex_t data_mutex; // Mutex to synchronize buffer access
pthread_cond_t data_cond; // Conditional variable associated
uint16_t *data; // Raw IQ samples buffer
uint16_t *pData [MODES_ASYNC_BUF_NUMBER]; // Raw IQ sample buffers from RTL
struct timeb stSystemTimeRTL[MODES_ASYNC_BUF_NUMBER]; // System time when RTL passed us this block
int iDataIn; // Fifo input pointer
int iDataOut; // Fifo output pointer
int iDataReady; // Fifo content count
int iDataLost; // Count of missed buffers
uint16_t *pFileData; // Raw IQ samples buffer (from a File)
uint16_t *magnitude; // Magnitude vector
struct timeb stSystemTimeRTL; // System time when RTL passed us the Latest block
uint64_t timestampBlk; // Timestamp of the start of the current block
struct timeb stSystemTimeBlk; // System time when RTL passed us currently processing this block
int fd; // --ifile option file descriptor
int data_ready; // Data ready to be processed
uint32_t *icao_cache; // Recently seen ICAO addresses cache
uint16_t *maglut; // I/Q -> Magnitude lookup table
int exit; // Exit from the main loop when true
@ -403,7 +409,7 @@ void detectModeS (uint16_t *m, uint32_t mlen);
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
void displayModesMessage(struct modesMessage *mm);
void useModesMessage (struct modesMessage *mm);
void computeMagnitudeVector();
void computeMagnitudeVector(uint16_t *pData);
void decodeCPR (struct aircraft *a, int fflag, int surface);
int decodeCPRrelative (struct aircraft *a, int fflag, int surface);
void modesInitErrorInfo ();