Skip to content

Commit

Permalink
Round FSDH start time to nearest tenths of milliseconds and make rang…
Browse files Browse the repository at this point in the history
…e of microsecond offset between -50 and +49. Fixes bug in microsecond offset calculation before Jan 1, 1970
  • Loading branch information
Chad Trabant committed Aug 1, 2015
1 parent a2d2dd6 commit aa5c34c
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 27 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
2015.213: 2.17
- Round Fixed Section Data Header start time values to the nearest
tenth of millisecond and restrict the microsecond offset value
to a range between -50 and +49 as recommended in SEED. Previously
start times were truncated at tenths of millisecond resolution
and the microsecond offset value was between 0 and +99. This also
addresses a bug where microsecond offsets were off by 100ms for times
before Jan 1 1970. Thanks to Lion Krischer for reporting.

Note to future hackers: the definition of HPTMODULUS governing the
time tick interval for high precision time values implies that this
tick interval may be changed. In reality, this should not be changed
from the default, microsecond tick value without thorough testing.
Some logic is know to be dependent on the microsecond tick.

2015.134: 2.16m
- Add defines for needed integer types and macros from inttypes.h
missing in older MSVC versions. MSVC 2010 and later appear to have
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# CFLAGS : Specify compiler options to use

MAJOR_VER = 2
MINOR_VER = 16
MINOR_VER = 17
CURRENT_VER = $(MAJOR_VER).$(MINOR_VER)
COMPAT_VER = $(MAJOR_VER).$(MINOR_VER)

Expand Down
42 changes: 41 additions & 1 deletion genutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* ORFEUS/EC-Project MEREDIAN
* IRIS Data Management Center
*
* modified: 2015.108
* modified: 2015.213
***************************************************************************/

#include <stdio.h>
Expand Down Expand Up @@ -589,6 +589,46 @@ ms_btime2seedtimestr (BTime *btime, char *seedtimestr)
} /* End of ms_btime2seedtimestr() */


/***************************************************************************
* ms_hptime2tomsusecoffset:
*
* Convert a high precision epoch time to a time value in tenths of
* milliseconds (aka toms) and a microsecond offset (aka usecoffset).
*
* The tenths of milliseconds value will be rounded to the nearest
* value having a microsecond offset value between -50 to +49.
*
* Returns 0 on success and -1 on error.
***************************************************************************/
int
ms_hptime2tomsusecoffset (hptime_t hptime, hptime_t *toms, int8_t *usecoffset)
{
if ( toms == NULL || usecoffset == NULL )
return -1;

/* Split time into tenths of milliseconds and microseconds */
*toms = hptime / (HPTMODULUS / 10000);
*usecoffset = hptime - (*toms * (HPTMODULUS / 10000));

/* Round tenths and adjust microsecond offset to -50 to +49 range */
if ( *usecoffset > 49 && *usecoffset < 100 )
{
*toms += 1;
*usecoffset -= 100;
}
else if ( *usecoffset < -50 && *usecoffset > -100 )
{
*toms -= 1;
*usecoffset += 100;
}

/* Convert tenths of milliseconds to be in hptime_t (HPTMODULUS) units */
*toms *= (HPTMODULUS / 10000);

return 0;
} /* End of ms_hptime2tomsusecoffset() */


/***************************************************************************
* ms_hptime2btime:
*
Expand Down
5 changes: 3 additions & 2 deletions libmseed.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ extern "C" {

#include "lmplatform.h"

#define LIBMSEED_VERSION "2.16m"
#define LIBMSEED_RELEASE "2015.134"
#define LIBMSEED_VERSION "2.17"
#define LIBMSEED_RELEASE "2015.213"

#define MINRECLEN 128 /* Minimum Mini-SEED record length, 2^7 bytes */
/* Note: the SEED specification minimum is 256 */
Expand Down Expand Up @@ -658,6 +658,7 @@ extern hptime_t ms_btime2hptime (BTime *btime);
extern char* ms_btime2isotimestr (BTime *btime, char *isotimestr);
extern char* ms_btime2mdtimestr (BTime *btime, char *mdtimestr);
extern char* ms_btime2seedtimestr (BTime *btime, char *seedtimestr);
extern int ms_hptime2tomsusecoffset (hptime_t hptime, hptime_t *toms, int8_t *usecoffset);
extern int ms_hptime2btime (hptime_t hptime, BTime *btime);
extern char* ms_hptime2isotimestr (hptime_t hptime, char *isotimestr, flag subsecond);
extern char* ms_hptime2mdtimestr (hptime_t hptime, char *mdtimestr, flag subsecond);
Expand Down
20 changes: 9 additions & 11 deletions msrutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* ORFEUS/EC-Project MEREDIAN
* IRIS Data Management Center
*
* modified: 2015.108
* modified: 2015.213
***************************************************************************/

#include <stdio.h>
Expand Down Expand Up @@ -257,6 +257,8 @@ int
msr_normalize_header ( MSRecord *msr, flag verbose )
{
struct blkt_link_s *cur_blkt;
hptime_t hptimems;
int8_t usecoffset;
char seqnum[7];
int offset = 0;
int blktcnt = 0;
Expand All @@ -266,6 +268,9 @@ msr_normalize_header ( MSRecord *msr, flag verbose )
if ( ! msr )
return -1;

/* Get start time rounded to tenths of milliseconds and microsecond offset */
ms_hptime2tomsusecoffset (msr->starttime, &hptimems, &usecoffset);

/* Update values in fixed section of data header */
if ( msr->fsdh )
{
Expand All @@ -285,7 +290,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose )
ms_strncpopen (msr->fsdh->station, msr->station, 5);
ms_strncpopen (msr->fsdh->location, msr->location, 2);
ms_strncpopen (msr->fsdh->channel, msr->channel, 3);
ms_hptime2btime (msr->starttime, &(msr->fsdh->start_time));
ms_hptime2btime (hptimems, &(msr->fsdh->start_time));

/* When the sampling rate is <= 32767 Hertz determine the factor
* and multipler through rational approximation. For higher rates
Expand All @@ -311,7 +316,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose )
msr->fsdh->blockette_offset = 0;
}

/* Traverse blockette chain and performs necessary updates*/
/* Traverse blockette chain and perform necessary updates*/
cur_blkt = msr->blkts;

if ( cur_blkt && verbose > 2 )
Expand Down Expand Up @@ -352,14 +357,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose )

else if ( cur_blkt->blkt_type == 1001 )
{
hptime_t sec, usec;

/* Insert microseconds offset */
sec = msr->starttime / (HPTMODULUS / 10000);
usec = msr->starttime - (sec * (HPTMODULUS / 10000));
usec /= (HPTMODULUS / 1000000);

msr->Blkt1001->usec = (int8_t) usec;
msr->Blkt1001->usec = usecoffset;
offset += sizeof (struct blkt_1001_s);
}

Expand Down
22 changes: 10 additions & 12 deletions pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Written by Chad Trabant,
* IRIS Data Management Center
*
* modified: 2015.062
* modified: 2015.213
***************************************************************************/

#include <stdio.h>
Expand Down Expand Up @@ -847,6 +847,8 @@ msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag,
struct blkt_1001_s *blkt1001, flag verbose )
{
struct fsdh_s *fsdh;
hptime_t hptimems;
int8_t usecoffset;
char seqnum[7];

if ( ! msr || ! rawrec )
Expand All @@ -861,30 +863,26 @@ msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag,
snprintf (seqnum, 7, "%06d", msr->sequence_number);
memcpy (fsdh->sequence_number, seqnum, 6);

/* Get start time rounded to tenths of milliseconds and microsecond offset */
ms_hptime2tomsusecoffset (msr->starttime, &hptimems, &usecoffset);

/* Update fixed-section start time */
ms_hptime2btime (msr->starttime, &(fsdh->start_time));
ms_hptime2btime (hptimems, &(fsdh->start_time));

/* Swap byte order? */
if ( swapflag )
{
MS_SWAPBTIME (&fsdh->start_time);
}

/* Update microseconds if Blockette 1001 is present */
/* Update microsecond offset value if Blockette 1001 is present */
if ( msr->Blkt1001 && blkt1001 )
{
hptime_t sec, usec;

/* Calculate microseconds offset */
sec = msr->starttime / (HPTMODULUS / 10000);
usec = msr->starttime - (sec * (HPTMODULUS / 10000));
usec /= (HPTMODULUS / 1000000);

/* Update microseconds offset in blockette chain entry */
msr->Blkt1001->usec = (int8_t) usec;
msr->Blkt1001->usec = usecoffset;

/* Update microseconds offset in packed header */
blkt1001->usec = (int8_t) usec;
blkt1001->usec = usecoffset;
}

return 0;
Expand Down

0 comments on commit aa5c34c

Please sign in to comment.