diff --git a/demod_2000.c b/demod_2000.c index 0c59958..4fef969 100644 --- a/demod_2000.c +++ b/demod_2000.c @@ -339,6 +339,11 @@ void demodulate2000(uint16_t *m, uint32_t mlen) { { 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 decodeModeAMessage(&mm, ModeA); @@ -539,6 +544,12 @@ void demodulate2000(uint16_t *m, uint32_t mlen) { // Set initial mm structure details 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; // Decode the received message diff --git a/demod_2400.c b/demod_2400.c index b98cf0d..0cd844a 100644 --- a/demod_2400.c +++ b/demod_2400.c @@ -425,6 +425,12 @@ void demodulate2400(uint16_t *m, uint32_t mlen) { // Set initial mm structure details 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.bFlags = mm.correctedbits = 0; diff --git a/dump1090.c b/dump1090.c index cf8c139..f0b13b9 100644 --- a/dump1090.c +++ b/dump1090.c @@ -173,7 +173,7 @@ void modesInit(void) { {Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;} // 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++) {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!!! // 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;} @@ -430,7 +430,7 @@ void readDataFromFile(void) { Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!! // Get the system time for this block - ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]); + clock_gettime(CLOCK_REALTIME, &Modes.stSystemTimeRTL[Modes.iDataIn]); // Queue the new data Modes.pData[Modes.iDataIn] = Modes.pFileData; diff --git a/dump1090.h b/dump1090.h index 5395e8f..e9487dc 100644 --- a/dump1090.h +++ b/dump1090.h @@ -71,7 +71,6 @@ #include #include #include - #include #include #include #include @@ -248,7 +247,7 @@ struct { // Internal state pthread_mutex_t data_mutex; // Mutex to synchronize buffer access pthread_cond_t data_cond; // Conditional variable associated 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 iDataOut; // Fifo output pointer int iDataReady; // Fifo content count @@ -260,7 +259,7 @@ struct { // Internal state uint16_t *pFileData; // Raw IQ samples buffer (from a File) uint16_t *magnitude; // Magnitude vector 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 uint16_t *maglut; // I/Q -> Magnitude lookup table uint16_t *log10lut; // Magnitude -> log10 lookup table @@ -367,7 +366,8 @@ struct modesMessage { uint32_t crc; // Message CRC int correctedbits; // No. of bits corrected 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 double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power int score; // Scoring from scoreModesMessage, if used diff --git a/net_io.c b/net_io.c index c328c85..7ecbab2 100644 --- a/net_io.c +++ b/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 // void modesSendSBSOutput(struct modesMessage *mm) { - char *p = prepareWrite(&Modes.sbs_out, 200); - uint32_t offset; - struct timeb epocTime_receive, epocTime_now; + char *p; + struct timespec now; struct tm stTime_receive, stTime_now; int msgType; - if (!p) - return; - // For now, suppress non-ICAO addresses if (mm->addr & MODES_NON_ICAO_ADDRESS) return; + p = prepareWrite(&Modes.sbs_out, 200); + if (!p) + return; + // // SBS BS style output checked against the following reference // 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); // Find current system time - ftime(&epocTime_now); // get the current system time & date - stTime_now = *localtime(&epocTime_now.time); + clock_gettime(CLOCK_REALTIME, &now); + localtime_r(&now.tv_sec, &stTime_now); // Find message reception time - if (mm->timestampMsg && !mm->remote) { // Make sure the records' timestamp is valid before using it - 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; - } + localtime_r(&mm->sysTimestampMsg.tv_sec, &stTime_receive); // 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, "%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 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) 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++;} } + // record reception time as the time we read it. + clock_gettime(CLOCK_REALTIME, &mm.sysTimestampMsg); + ch = *p++; // Grab the signal level mm.signalLevel = ((unsigned char)ch / 256.0); 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; } + // record reception time as the time we read it. + clock_gettime(CLOCK_REALTIME, &mm.sysTimestampMsg); + if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC Modes.stats_current.remote_received_modeac++; decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1])); diff --git a/util.c b/util.c index b7e1887..d745c58 100644 --- a/util.c +++ b/util.c @@ -62,3 +62,25 @@ uint64_t mstime(void) mst += tv.tv_usec/1000; 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; + } +} diff --git a/util.h b/util.h index 6526b7b..3cb022a 100644 --- a/util.h +++ b/util.h @@ -22,6 +22,19 @@ #include +/* Returns system time in milliseconds */ 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