Store computed reception time in the message struct so we don't rely on
the message being emitted immediately. Fix computation of reception time so it's more sensible (the block timestamp is some time after reception of the _end_ of the block, not the start) - this means that message-emission times are always later than message-reception times in SBS output, which is a bit more sensible. Use clock_gettime in preference to ftime.
This commit is contained in:
parent
1584955080
commit
4e177c2d64
11
demod_2000.c
11
demod_2000.c
|
@ -339,6 +339,11 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
||||||
{
|
{
|
||||||
mm.timestampMsg = Modes.timestampBlk + ((j+1) * 6);
|
mm.timestampMsg = Modes.timestampBlk + ((j+1) * 6);
|
||||||
|
|
||||||
|
// compute message receive time as block-start-time + difference in the 12MHz clock
|
||||||
|
mm.sysTimestampMsg = Modes.stSystemTimeBlk; // end of block time
|
||||||
|
mm.sysTimestampMsg.tv_nsec -= receiveclock_ns_elapsed(mm.timestampMsg, Modes.timestampBlk + MODES_ASYNC_BUF_SAMPLES * 6); // time until end of block
|
||||||
|
normalize_timespec(&mm.sysTimestampMsg);
|
||||||
|
|
||||||
// Decode the received message
|
// Decode the received message
|
||||||
decodeModeAMessage(&mm, ModeA);
|
decodeModeAMessage(&mm, ModeA);
|
||||||
|
|
||||||
|
@ -539,6 +544,12 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
||||||
|
|
||||||
// Set initial mm structure details
|
// Set initial mm structure details
|
||||||
mm.timestampMsg = Modes.timestampBlk + (j*6);
|
mm.timestampMsg = Modes.timestampBlk + (j*6);
|
||||||
|
|
||||||
|
// compute message receive time as block-start-time + difference in the 12MHz clock
|
||||||
|
mm.sysTimestampMsg = Modes.stSystemTimeBlk; // end of block time
|
||||||
|
mm.sysTimestampMsg.tv_nsec -= receiveclock_ns_elapsed(mm.timestampMsg, Modes.timestampBlk + MODES_ASYNC_BUF_SAMPLES * 6); // time until end of block
|
||||||
|
normalize_timespec(&mm.sysTimestampMsg);
|
||||||
|
|
||||||
mm.signalLevel = (365.0*60 + sigLevel + noiseLevel) * (365.0*60 + sigLevel + noiseLevel) / MAX_POWER / 60 / 60;
|
mm.signalLevel = (365.0*60 + sigLevel + noiseLevel) * (365.0*60 + sigLevel + noiseLevel) / MAX_POWER / 60 / 60;
|
||||||
|
|
||||||
// Decode the received message
|
// Decode the received message
|
||||||
|
|
|
@ -425,6 +425,12 @@ void demodulate2400(uint16_t *m, uint32_t mlen) {
|
||||||
|
|
||||||
// Set initial mm structure details
|
// Set initial mm structure details
|
||||||
mm.timestampMsg = Modes.timestampBlk + (j*5) + bestphase;
|
mm.timestampMsg = Modes.timestampBlk + (j*5) + bestphase;
|
||||||
|
|
||||||
|
// compute message receive time as block-start-time + difference in the 12MHz clock
|
||||||
|
mm.sysTimestampMsg = Modes.stSystemTimeBlk; // end of block time
|
||||||
|
mm.sysTimestampMsg.tv_nsec -= receiveclock_ns_elapsed(mm.timestampMsg, Modes.timestampBlk + MODES_ASYNC_BUF_SAMPLES * 5); // time until end of block
|
||||||
|
normalize_timespec(&mm.sysTimestampMsg);
|
||||||
|
|
||||||
mm.score = bestscore;
|
mm.score = bestscore;
|
||||||
mm.bFlags = mm.correctedbits = 0;
|
mm.bFlags = mm.correctedbits = 0;
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ void modesInit(void) {
|
||||||
{Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}
|
{Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}
|
||||||
|
|
||||||
// Initialise the Block Timers to something half sensible
|
// Initialise the Block Timers to something half sensible
|
||||||
ftime(&Modes.stSystemTimeBlk);
|
clock_gettime(CLOCK_REALTIME, &Modes.stSystemTimeBlk);
|
||||||
for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++)
|
for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++)
|
||||||
{Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;}
|
{Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;}
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||||
Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!
|
Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!
|
||||||
|
|
||||||
// Get the system time for this block
|
// Get the system time for this block
|
||||||
ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);
|
clock_gettime(CLOCK_REALTIME, &Modes.stSystemTimeRTL[Modes.iDataIn]);
|
||||||
|
|
||||||
if (len > MODES_ASYNC_BUF_SIZE) {len = MODES_ASYNC_BUF_SIZE;}
|
if (len > MODES_ASYNC_BUF_SIZE) {len = MODES_ASYNC_BUF_SIZE;}
|
||||||
|
|
||||||
|
@ -430,7 +430,7 @@ void readDataFromFile(void) {
|
||||||
Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!
|
Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!
|
||||||
|
|
||||||
// Get the system time for this block
|
// Get the system time for this block
|
||||||
ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);
|
clock_gettime(CLOCK_REALTIME, &Modes.stSystemTimeRTL[Modes.iDataIn]);
|
||||||
|
|
||||||
// Queue the new data
|
// Queue the new data
|
||||||
Modes.pData[Modes.iDataIn] = Modes.pFileData;
|
Modes.pData[Modes.iDataIn] = Modes.pFileData;
|
||||||
|
|
|
@ -71,7 +71,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -248,7 +247,7 @@ struct { // Internal state
|
||||||
pthread_mutex_t data_mutex; // Mutex to synchronize buffer access
|
pthread_mutex_t data_mutex; // Mutex to synchronize buffer access
|
||||||
pthread_cond_t data_cond; // Conditional variable associated
|
pthread_cond_t data_cond; // Conditional variable associated
|
||||||
uint16_t *pData [MODES_ASYNC_BUF_NUMBER]; // Raw IQ sample buffers from RTL
|
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
|
struct timespec stSystemTimeRTL[MODES_ASYNC_BUF_NUMBER]; // System time when RTL passed us this block
|
||||||
int iDataIn; // Fifo input pointer
|
int iDataIn; // Fifo input pointer
|
||||||
int iDataOut; // Fifo output pointer
|
int iDataOut; // Fifo output pointer
|
||||||
int iDataReady; // Fifo content count
|
int iDataReady; // Fifo content count
|
||||||
|
@ -260,7 +259,7 @@ struct { // Internal state
|
||||||
uint16_t *pFileData; // Raw IQ samples buffer (from a File)
|
uint16_t *pFileData; // Raw IQ samples buffer (from a File)
|
||||||
uint16_t *magnitude; // Magnitude vector
|
uint16_t *magnitude; // Magnitude vector
|
||||||
uint64_t timestampBlk; // Timestamp of the start of the current 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
|
struct timespec stSystemTimeBlk; // System time when RTL passed us currently processing this block
|
||||||
int fd; // --ifile option file descriptor
|
int fd; // --ifile option file descriptor
|
||||||
uint16_t *maglut; // I/Q -> Magnitude lookup table
|
uint16_t *maglut; // I/Q -> Magnitude lookup table
|
||||||
uint16_t *log10lut; // Magnitude -> log10 lookup table
|
uint16_t *log10lut; // Magnitude -> log10 lookup table
|
||||||
|
@ -367,7 +366,8 @@ struct modesMessage {
|
||||||
uint32_t crc; // Message CRC
|
uint32_t crc; // Message CRC
|
||||||
int correctedbits; // No. of bits corrected
|
int correctedbits; // No. of bits corrected
|
||||||
uint32_t addr; // Address Announced
|
uint32_t addr; // Address Announced
|
||||||
uint64_t timestampMsg; // Timestamp of the message
|
uint64_t timestampMsg; // Timestamp of the message (12MHz clock)
|
||||||
|
struct timespec sysTimestampMsg; // Timestamp of the message (system time)
|
||||||
int remote; // If set this message is from a remote station
|
int remote; // If set this message is from a remote station
|
||||||
double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power
|
double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power
|
||||||
int score; // Scoring from scoreModesMessage, if used
|
int score; // Scoring from scoreModesMessage, if used
|
||||||
|
|
41
net_io.c
41
net_io.c
|
@ -347,19 +347,19 @@ void modesSendRawOutput(struct modesMessage *mm) {
|
||||||
// The message structure mm->bFlags tells us what has been updated by this message
|
// The message structure mm->bFlags tells us what has been updated by this message
|
||||||
//
|
//
|
||||||
void modesSendSBSOutput(struct modesMessage *mm) {
|
void modesSendSBSOutput(struct modesMessage *mm) {
|
||||||
char *p = prepareWrite(&Modes.sbs_out, 200);
|
char *p;
|
||||||
uint32_t offset;
|
struct timespec now;
|
||||||
struct timeb epocTime_receive, epocTime_now;
|
|
||||||
struct tm stTime_receive, stTime_now;
|
struct tm stTime_receive, stTime_now;
|
||||||
int msgType;
|
int msgType;
|
||||||
|
|
||||||
if (!p)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// For now, suppress non-ICAO addresses
|
// For now, suppress non-ICAO addresses
|
||||||
if (mm->addr & MODES_NON_ICAO_ADDRESS)
|
if (mm->addr & MODES_NON_ICAO_ADDRESS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
p = prepareWrite(&Modes.sbs_out, 200);
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
|
||||||
//
|
//
|
||||||
// SBS BS style output checked against the following reference
|
// SBS BS style output checked against the following reference
|
||||||
// http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm - seems comprehensive
|
// http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm - seems comprehensive
|
||||||
|
@ -407,32 +407,19 @@ void modesSendSBSOutput(struct modesMessage *mm) {
|
||||||
p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr);
|
p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr);
|
||||||
|
|
||||||
// Find current system time
|
// Find current system time
|
||||||
ftime(&epocTime_now); // get the current system time & date
|
clock_gettime(CLOCK_REALTIME, &now);
|
||||||
stTime_now = *localtime(&epocTime_now.time);
|
localtime_r(&now.tv_sec, &stTime_now);
|
||||||
|
|
||||||
// Find message reception time
|
// Find message reception time
|
||||||
if (mm->timestampMsg && !mm->remote) { // Make sure the records' timestamp is valid before using it
|
localtime_r(&mm->sysTimestampMsg.tv_sec, &stTime_receive);
|
||||||
epocTime_receive = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing
|
|
||||||
offset = (int) (mm->timestampMsg - Modes.timestampBlk); // This is the time (in 12Mhz ticks) into the Block
|
|
||||||
offset = offset / 12000; // convert to milliseconds
|
|
||||||
epocTime_receive.millitm += offset; // add on the offset time to the Block start time
|
|
||||||
if (epocTime_receive.millitm > 999) { // if we've caused an overflow into the next second...
|
|
||||||
epocTime_receive.millitm -= 1000;
|
|
||||||
epocTime_receive.time ++; // ..correct the overflow
|
|
||||||
}
|
|
||||||
stTime_receive = *localtime(&epocTime_receive.time);
|
|
||||||
} else {
|
|
||||||
epocTime_receive = epocTime_now; // We don't have a usable reception time; use the current system time
|
|
||||||
stTime_receive = stTime_now;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields 7 & 8 are the message reception time and date
|
// Fields 7 & 8 are the message reception time and date
|
||||||
p += sprintf(p, "%04d/%02d/%02d,", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday);
|
p += sprintf(p, "%04d/%02d/%02d,", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday);
|
||||||
p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, epocTime_receive.millitm);
|
p += sprintf(p, "%02d:%02d:%02d.%03u,", stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, (unsigned) (mm->sysTimestampMsg.tv_nsec / 1000000U));
|
||||||
|
|
||||||
// Fields 9 & 10 are the current time and date
|
// Fields 9 & 10 are the current time and date
|
||||||
p += sprintf(p, "%04d/%02d/%02d,", (stTime_now.tm_year+1900),(stTime_now.tm_mon+1), stTime_now.tm_mday);
|
p += sprintf(p, "%04d/%02d/%02d,", (stTime_now.tm_year+1900),(stTime_now.tm_mon+1), stTime_now.tm_mday);
|
||||||
p += sprintf(p, "%02d:%02d:%02d.%03d", stTime_now.tm_hour, stTime_now.tm_min, stTime_now.tm_sec, epocTime_now.millitm);
|
p += sprintf(p, "%02d:%02d:%02d.%03u", stTime_now.tm_hour, stTime_now.tm_min, stTime_now.tm_sec, (unsigned) (now.tv_nsec / 1000000U));
|
||||||
|
|
||||||
// Field 11 is the callsign (if we have it)
|
// Field 11 is the callsign (if we have it)
|
||||||
if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);}
|
if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);}
|
||||||
|
@ -574,6 +561,9 @@ int decodeBinMessage(struct client *c, char *p) {
|
||||||
if (0x1A == ch) {p++;}
|
if (0x1A == ch) {p++;}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// record reception time as the time we read it.
|
||||||
|
clock_gettime(CLOCK_REALTIME, &mm.sysTimestampMsg);
|
||||||
|
|
||||||
ch = *p++; // Grab the signal level
|
ch = *p++; // Grab the signal level
|
||||||
mm.signalLevel = ((unsigned char)ch / 256.0);
|
mm.signalLevel = ((unsigned char)ch / 256.0);
|
||||||
mm.signalLevel = mm.signalLevel * mm.signalLevel + 1e-5;
|
mm.signalLevel = mm.signalLevel * mm.signalLevel + 1e-5;
|
||||||
|
@ -697,6 +687,9 @@ int decodeHexMessage(struct client *c, char *hex) {
|
||||||
msg[j/2] = (high << 4) | low;
|
msg[j/2] = (high << 4) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// record reception time as the time we read it.
|
||||||
|
clock_gettime(CLOCK_REALTIME, &mm.sysTimestampMsg);
|
||||||
|
|
||||||
if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC
|
if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC
|
||||||
Modes.stats_current.remote_received_modeac++;
|
Modes.stats_current.remote_received_modeac++;
|
||||||
decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
|
decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1]));
|
||||||
|
|
22
util.c
22
util.c
|
@ -62,3 +62,25 @@ uint64_t mstime(void)
|
||||||
mst += tv.tv_usec/1000;
|
mst += tv.tv_usec/1000;
|
||||||
return mst;
|
return mst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t receiveclock_ns_elapsed(uint64_t t1, uint64_t t2)
|
||||||
|
{
|
||||||
|
if (t2 < t1) {
|
||||||
|
// wrapped.
|
||||||
|
return (~(t1 - t2) + 1) * 1000U / 12U;
|
||||||
|
} else {
|
||||||
|
return (t2 - t1) * 1000U / 12U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize_timespec(struct timespec *ts)
|
||||||
|
{
|
||||||
|
if (ts->tv_nsec > 1000000000) {
|
||||||
|
ts->tv_sec += ts->tv_nsec / 1000000000;
|
||||||
|
ts->tv_nsec = ts->tv_nsec % 1000000000;
|
||||||
|
} else if (ts->tv_nsec < 0) {
|
||||||
|
long adjust = ts->tv_nsec / 1000000000 + 1;
|
||||||
|
ts->tv_sec -= adjust;
|
||||||
|
ts->tv_nsec = (ts->tv_nsec + 1000000000 * adjust) % 1000000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
util.h
13
util.h
|
@ -22,6 +22,19 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Returns system time in milliseconds */
|
||||||
uint64_t mstime(void);
|
uint64_t mstime(void);
|
||||||
|
|
||||||
|
/* Returns the time elapsed, in nanoseconds, from t1 to t2,
|
||||||
|
* where t1 and t2 are 12MHz counters,
|
||||||
|
* accounting for wrapping.
|
||||||
|
*/
|
||||||
|
uint64_t receiveclock_ns_elapsed(uint64_t t1, uint64_t t2);
|
||||||
|
|
||||||
|
/* Normalize the value in ts so that ts->nsec lies in
|
||||||
|
* [0,999999999]
|
||||||
|
*/
|
||||||
|
struct timespec;
|
||||||
|
void normalize_timespec(struct timespec *ts);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue