1 /***************************************************************************
4 * Generic routines to operate on Mini-SEED records.
6 * Written by Chad Trabant
7 * ORFEUS/EC-Project MEREDIAN
8 * IRIS Data Management Center
11 ***************************************************************************/
21 /***************************************************************************
24 * Initialize and return an MSRecord struct, allocating memory if
25 * needed. If memory for the fsdh and datasamples fields has been
26 * allocated the pointers will be retained for reuse. If a blockette
27 * chain is present all associated memory will be released.
29 * Returns a pointer to a MSRecord struct on success or NULL on error.
30 ***************************************************************************/
32 msr_init ( MSRecord
*msr
)
35 void *datasamples
= 0;
39 msr
= (MSRecord
*) malloc (sizeof(MSRecord
));
44 datasamples
= msr
->datasamples
;
47 msr_free_blktchain (msr
);
55 ms_log (2, "msr_init(): Cannot allocate memory\n");
59 memset (msr
, 0, sizeof (MSRecord
));
62 msr
->datasamples
= datasamples
;
70 } /* End of msr_init() */
73 /***************************************************************************
76 * Free all memory associated with a MSRecord struct.
77 ***************************************************************************/
79 msr_free ( MSRecord
**ppmsr
)
81 if ( ppmsr
!= NULL
&& *ppmsr
!= 0 )
83 /* Free fixed section header if populated */
85 free ((*ppmsr
)->fsdh
);
87 /* Free blockette chain if populated */
88 if ( (*ppmsr
)->blkts
)
89 msr_free_blktchain (*ppmsr
);
91 /* Free datasamples if present */
92 if ( (*ppmsr
)->datasamples
)
93 free ((*ppmsr
)->datasamples
);
95 /* Free stream processing state if present */
96 if ( (*ppmsr
)->ststate
)
97 free ((*ppmsr
)->ststate
);
103 } /* End of msr_free() */
106 /***************************************************************************
107 * msr_free_blktchain:
109 * Free all memory associated with a blockette chain in a MSRecord
110 * struct and set MSRecord->blkts to NULL. Also reset the shortcut
111 * blockette pointers.
112 ***************************************************************************/
114 msr_free_blktchain ( MSRecord
*msr
)
120 BlktLink
*bc
= msr
->blkts
;
142 } /* End of msr_free_blktchain() */
145 /***************************************************************************
148 * Add a blockette to the blockette chain of an MSRecord. 'blktdata'
149 * should be the body of the blockette type 'blkttype' of 'length'
150 * bytes without the blockette header (type and next offsets). The
151 * 'chainpos' value controls which end of the chain the blockette is
152 * added to. If 'chainpos' is 0 the blockette will be added to the
153 * end of the chain (last blockette), other wise it will be added to
154 * the beginning of the chain (first blockette).
156 * Returns a pointer to the BlktLink added to the chain on success and
158 ***************************************************************************/
160 msr_addblockette (MSRecord
*msr
, char *blktdata
, int length
, int blkttype
,
174 blkt
= (BlktLink
*) malloc (sizeof(BlktLink
));
176 blkt
->next
= msr
->blkts
;
181 /* Find the last blockette */
182 while ( blkt
&& blkt
->next
)
187 blkt
->next
= (BlktLink
*) malloc (sizeof(BlktLink
));
195 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
201 msr
->blkts
= (BlktLink
*) malloc (sizeof(BlktLink
));
203 if ( msr
->blkts
== NULL
)
205 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
213 blkt
->blktoffset
= 0;
214 blkt
->blkt_type
= blkttype
;
217 blkt
->blktdata
= (char *) malloc (length
);
219 if ( blkt
->blktdata
== NULL
)
221 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
225 memcpy (blkt
->blktdata
, blktdata
, length
);
226 blkt
->blktdatalen
= length
;
228 /* Setup the shortcut pointer for common blockettes */
232 msr
->Blkt100
= blkt
->blktdata
;
235 msr
->Blkt1000
= blkt
->blktdata
;
238 msr
->Blkt1001
= blkt
->blktdata
;
243 } /* End of msr_addblockette() */
246 /***************************************************************************
247 * msr_normalize_header:
249 * Normalize header values between the MSRecord struct and the
250 * associated fixed-section of the header and blockettes. Essentially
251 * this updates the SEED structured data in the MSRecord.fsdh struct
252 * and MSRecord.blkts chain with values stored at the MSRecord level.
254 * Returns the header length in bytes on success or -1 on error.
255 ***************************************************************************/
257 msr_normalize_header ( MSRecord
*msr
, flag verbose
)
259 struct blkt_link_s
*cur_blkt
;
271 /* Get start time rounded to tenths of milliseconds and microsecond offset */
272 ms_hptime2tomsusecoffset (msr
->starttime
, &hptimems
, &usecoffset
);
274 /* Update values in fixed section of data header */
278 ms_log (1, "Normalizing fixed section of data header\n");
280 /* Roll-over sequence number if necessary */
281 if ( msr
->sequence_number
> 999999 )
282 msr
->sequence_number
= 1;
284 /* Update values in the MSRecord.fsdh struct */
285 snprintf (seqnum
, 7, "%06d", msr
->sequence_number
);
286 memcpy (msr
->fsdh
->sequence_number
, seqnum
, 6);
287 msr
->fsdh
->dataquality
= msr
->dataquality
;
288 msr
->fsdh
->reserved
= ' ';
289 ms_strncpopen (msr
->fsdh
->network
, msr
->network
, 2);
290 ms_strncpopen (msr
->fsdh
->station
, msr
->station
, 5);
291 ms_strncpopen (msr
->fsdh
->location
, msr
->location
, 2);
292 ms_strncpopen (msr
->fsdh
->channel
, msr
->channel
, 3);
293 ms_hptime2btime (hptimems
, &(msr
->fsdh
->start_time
));
295 /* When the sampling rate is <= 32767 Hertz determine the factor
296 * and multipler through rational approximation. For higher rates
297 * set the factor and multiplier to 0. */
298 if ( msr
->samprate
<= 32767.0 )
300 ms_genfactmult (msr
->samprate
, &(msr
->fsdh
->samprate_fact
), &(msr
->fsdh
->samprate_mult
));
305 ms_log (1, "Sampling rate too high to approximate factor & multiplier: %g\n",
307 msr
->fsdh
->samprate_fact
= 0;
308 msr
->fsdh
->samprate_mult
= 0;
314 msr
->fsdh
->blockette_offset
= offset
;
316 msr
->fsdh
->blockette_offset
= 0;
319 /* Traverse blockette chain and perform necessary updates*/
320 cur_blkt
= msr
->blkts
;
322 if ( cur_blkt
&& verbose
> 2 )
323 ms_log (1, "Normalizing blockette chain\n");
329 if ( cur_blkt
->blkt_type
== 100 && msr
->Blkt100
)
331 msr
->Blkt100
->samprate
= (float)msr
->samprate
;
332 offset
+= sizeof (struct blkt_100_s
);
334 else if ( cur_blkt
->blkt_type
== 1000 && msr
->Blkt1000
)
336 msr
->Blkt1000
->byteorder
= msr
->byteorder
;
337 msr
->Blkt1000
->encoding
= msr
->encoding
;
339 /* Calculate the record length as an exponent of 2 */
340 for (reclenfind
=1, reclenexp
=1; reclenfind
<= MAXRECLEN
; reclenexp
++)
343 if ( reclenfind
== msr
->reclen
) break;
346 if ( reclenfind
!= msr
->reclen
)
348 ms_log (2, "msr_normalize_header(): Record length %d is not a power of 2\n",
353 msr
->Blkt1000
->reclen
= reclenexp
;
355 offset
+= sizeof (struct blkt_1000_s
);
358 else if ( cur_blkt
->blkt_type
== 1001 )
360 msr
->Blkt1001
->usec
= usecoffset
;
361 offset
+= sizeof (struct blkt_1001_s
);
365 cur_blkt
= cur_blkt
->next
;
369 msr
->fsdh
->numblockettes
= blktcnt
;
372 } /* End of msr_normalize_header() */
375 /***************************************************************************
378 * Duplicate an MSRecord struct
379 * including the fixed-section data
380 * header and blockette chain. If
381 * the datadup flag is true and the
382 * source MSRecord has associated
383 * data samples copy them as well.
385 * Returns a pointer to a new MSRecord on success and NULL on error.
386 ***************************************************************************/
388 msr_duplicate (MSRecord
*msr
, flag datadup
)
390 MSRecord
*dupmsr
= 0;
396 /* Allocate target MSRecord structure */
397 if ( (dupmsr
= msr_init (NULL
)) == NULL
)
400 /* Copy MSRecord structure */
401 memcpy (dupmsr
, msr
, sizeof(MSRecord
));
403 /* Copy fixed-section data header structure */
406 /* Allocate memory for new FSDH structure */
407 if ( (dupmsr
->fsdh
= (struct fsdh_s
*) malloc (sizeof(struct fsdh_s
))) == NULL
)
409 ms_log (2, "msr_duplicate(): Error allocating memory\n");
414 /* Copy the contents */
415 memcpy (dupmsr
->fsdh
, msr
->fsdh
, sizeof(struct fsdh_s
));
418 /* Copy the blockette chain */
421 BlktLink
*blkt
= msr
->blkts
;
422 BlktLink
*next
= NULL
;
429 /* Add blockette to chain of new MSRecord */
430 if ( msr_addblockette (dupmsr
, blkt
->blktdata
, blkt
->blktdatalen
,
431 blkt
->blkt_type
, 0) == NULL
)
433 ms_log (2, "msr_duplicate(): Error adding blockettes\n");
442 /* Copy data samples if requested and available */
443 if ( datadup
&& msr
->datasamples
)
445 /* Determine size of samples in bytes */
446 samplesize
= ms_samplesize (msr
->sampletype
);
448 if ( samplesize
== 0 )
450 ms_log (2, "msr_duplicate(): unrecognized sample type: '%c'\n",
456 /* Allocate memory for new data array */
457 if ( (dupmsr
->datasamples
= (void *) malloc ((size_t)(msr
->numsamples
* samplesize
))) == NULL
)
459 ms_log (2, "msr_duplicate(): Error allocating memory\n");
464 /* Copy the data array */
465 memcpy (dupmsr
->datasamples
, msr
->datasamples
, ((size_t)(msr
->numsamples
* samplesize
)));
467 /* Otherwise make sure the sample array and count are zero */
470 dupmsr
->datasamples
= 0;
471 dupmsr
->numsamples
= 0;
475 } /* End of msr_duplicate() */
478 /***************************************************************************
481 * Calculate and return a double precision sample rate for the
482 * specified MSRecord. If a Blockette 100 was included and parsed,
483 * the "Actual sample rate" (field 3) will be returned, otherwise a
484 * nominal sample rate will be calculated from the sample rate factor
485 * and multiplier in the fixed section data header.
487 * Returns the positive sample rate on success and -1.0 on error.
488 ***************************************************************************/
490 msr_samprate (MSRecord
*msr
)
496 return (double) msr
->Blkt100
->samprate
;
498 return msr_nomsamprate (msr
);
499 } /* End of msr_samprate() */
502 /***************************************************************************
505 * Calculate a double precision nominal sample rate from the sample
506 * rate factor and multiplier in the FSDH struct of the specified
509 * Returns the positive sample rate on success and -1.0 on error.
510 ***************************************************************************/
512 msr_nomsamprate (MSRecord
*msr
)
517 return ms_nomsamprate (msr
->fsdh
->samprate_fact
, msr
->fsdh
->samprate_mult
);
518 } /* End of msr_nomsamprate() */
521 /***************************************************************************
524 * Convert a btime struct of a FSDH struct of a MSRecord (the record
525 * start time) into a high precision epoch time and apply time
526 * corrections if any are specified in the header and bit 1 of the
527 * activity flags indicates that it has not already been applied. If
528 * a Blockette 1001 is included and has been parsed the microseconds
529 * of field 4 are also applied.
531 * Returns a high precision epoch time on success and HPTERROR on
533 ***************************************************************************/
535 msr_starttime (MSRecord
*msr
)
537 hptime_t starttime
= msr_starttime_uc (msr
);
539 if ( ! msr
|| starttime
== HPTERROR
)
542 /* Check if a correction is included and if it has been applied,
543 bit 1 of activity flags indicates if it has been appiled */
545 if ( msr
->fsdh
->time_correct
!= 0 &&
546 ! (msr
->fsdh
->act_flags
& 0x02) )
548 starttime
+= (hptime_t
) msr
->fsdh
->time_correct
* (HPTMODULUS
/ 10000);
551 /* Apply microsecond precision in a parsed Blockette 1001 */
554 starttime
+= (hptime_t
) msr
->Blkt1001
->usec
* (HPTMODULUS
/ 1000000);
558 } /* End of msr_starttime() */
561 /***************************************************************************
564 * Convert a btime struct of a FSDH struct of a MSRecord (the record
565 * start time) into a high precision epoch time. This time has no
566 * correction(s) applied to it.
568 * Returns a high precision epoch time on success and HPTERROR on
570 ***************************************************************************/
572 msr_starttime_uc (MSRecord
*msr
)
580 return ms_btime2hptime (&msr
->fsdh
->start_time
);
581 } /* End of msr_starttime_uc() */
584 /***************************************************************************
587 * Calculate the time of the last sample in the record; this is the
588 * actual last sample time and *not* the time "covered" by the last
591 * Returns the time of the last sample as a high precision epoch time
592 * on success and HPTERROR on error.
593 ***************************************************************************/
595 msr_endtime (MSRecord
*msr
)
598 LeapSecond
*lslist
= leapsecondlist
;
603 if ( msr
->samprate
> 0.0 && msr
->samplecnt
> 0 )
604 span
= (hptime_t
)(((double) (msr
->samplecnt
- 1) / msr
->samprate
* HPTMODULUS
) + 0.5);
606 /* Check if the record contains a leap second, if list is available */
611 if ( lslist
->leapsecond
> msr
->starttime
&&
612 lslist
->leapsecond
< (msr
->starttime
+ span
) )
618 lslist
= lslist
->next
;
623 /* If a positive leap second occurred during this record as denoted by
624 * bit 4 of the activity flags being set, reduce the end time to match
625 * the now shifted UTC time. */
627 if ( msr
->fsdh
->act_flags
& 0x10 )
631 return (msr
->starttime
+ span
);
632 } /* End of msr_endtime() */
635 /***************************************************************************
638 * Generate a source name string for a specified MSRecord in the
639 * format: 'NET_STA_LOC_CHAN' or, if the quality flag is true:
640 * 'NET_STA_LOC_CHAN_QUAL'. The passed srcname must have enough room
641 * for the resulting string.
643 * Returns a pointer to the resulting string or NULL on error.
644 ***************************************************************************/
646 msr_srcname (MSRecord
*msr
, char *srcname
, flag quality
)
651 if ( ! msr
|| ! srcname
)
654 /* Build the source name string */
656 while ( *cp
) { *src
++ = *cp
++; }
659 while ( *cp
) { *src
++ = *cp
++; }
662 while ( *cp
) { *src
++ = *cp
++; }
665 while ( *cp
) { *src
++ = *cp
++; }
670 *src
++ = msr
->dataquality
;
676 } /* End of msr_srcname() */
679 /***************************************************************************
682 * Prints header values in an MSRecord struct, if 'details' is greater
683 * than 0 then detailed information about each blockette is printed.
684 * If 'details' is greater than 1 very detailed information is
685 * printed. If no FSDH (msr->fsdh) is present only a single line with
686 * basic information is printed.
687 ***************************************************************************/
689 msr_print (MSRecord
*msr
, flag details
)
700 /* Generate a source name string */
702 msr_srcname (msr
, srcname
, 0);
704 /* Generate a start time string */
705 ms_hptime2seedtimestr (msr
->starttime
, time
, 1);
707 /* Report information in the fixed header */
708 if ( details
> 0 && msr
->fsdh
)
710 nomsamprate
= msr_nomsamprate (msr
);
712 ms_log (0, "%s, %06d, %c\n", srcname
, msr
->sequence_number
, msr
->dataquality
);
713 ms_log (0, " start time: %s\n", time
);
714 ms_log (0, " number of samples: %d\n", msr
->fsdh
->numsamples
);
715 ms_log (0, " sample rate factor: %d (%.10g samples per second)\n",
716 msr
->fsdh
->samprate_fact
, nomsamprate
);
717 ms_log (0, " sample rate multiplier: %d\n", msr
->fsdh
->samprate_mult
);
722 b
= msr
->fsdh
->act_flags
;
723 ms_log (0, " activity flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
724 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
725 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
726 if ( b
& 0x01 ) ms_log (0, " [Bit 0] Calibration signals present\n");
727 if ( b
& 0x02 ) ms_log (0, " [Bit 1] Time correction applied\n");
728 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Beginning of an event, station trigger\n");
729 if ( b
& 0x08 ) ms_log (0, " [Bit 3] End of an event, station detrigger\n");
730 if ( b
& 0x10 ) ms_log (0, " [Bit 4] A positive leap second happened in this record\n");
731 if ( b
& 0x20 ) ms_log (0, " [Bit 5] A negative leap second happened in this record\n");
732 if ( b
& 0x40 ) ms_log (0, " [Bit 6] Event in progress\n");
733 if ( b
& 0x80 ) ms_log (0, " [Bit 7] Undefined bit set\n");
735 /* I/O and clock flags */
736 b
= msr
->fsdh
->io_flags
;
737 ms_log (0, " I/O and clock flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
738 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
739 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
740 if ( b
& 0x01 ) ms_log (0, " [Bit 0] Station volume parity error possibly present\n");
741 if ( b
& 0x02 ) ms_log (0, " [Bit 1] Long record read (possibly no problem)\n");
742 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Short record read (record padded)\n");
743 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Start of time series\n");
744 if ( b
& 0x10 ) ms_log (0, " [Bit 4] End of time series\n");
745 if ( b
& 0x20 ) ms_log (0, " [Bit 5] Clock locked\n");
746 if ( b
& 0x40 ) ms_log (0, " [Bit 6] Undefined bit set\n");
747 if ( b
& 0x80 ) ms_log (0, " [Bit 7] Undefined bit set\n");
749 /* Data quality flags */
750 b
= msr
->fsdh
->dq_flags
;
751 ms_log (0, " data quality flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
752 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
753 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
754 if ( b
& 0x01 ) ms_log (0, " [Bit 0] Amplifier saturation detected\n");
755 if ( b
& 0x02 ) ms_log (0, " [Bit 1] Digitizer clipping detected\n");
756 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Spikes detected\n");
757 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Glitches detected\n");
758 if ( b
& 0x10 ) ms_log (0, " [Bit 4] Missing/padded data present\n");
759 if ( b
& 0x20 ) ms_log (0, " [Bit 5] Telemetry synchronization error\n");
760 if ( b
& 0x40 ) ms_log (0, " [Bit 6] A digital filter may be charging\n");
761 if ( b
& 0x80 ) ms_log (0, " [Bit 7] Time tag is questionable\n");
764 ms_log (0, " number of blockettes: %d\n", msr
->fsdh
->numblockettes
);
765 ms_log (0, " time correction: %ld\n", (long int) msr
->fsdh
->time_correct
);
766 ms_log (0, " data offset: %d\n", msr
->fsdh
->data_offset
);
767 ms_log (0, " first blockette offset: %d\n", msr
->fsdh
->blockette_offset
);
771 ms_log (0, "%s, %06d, %c, %d, %"PRId64
" samples, %-.10g Hz, %s\n",
772 srcname
, msr
->sequence_number
, msr
->dataquality
,
773 msr
->reclen
, msr
->samplecnt
, msr
->samprate
, time
);
776 /* Report information in the blockette chain */
777 if ( details
> 0 && msr
->blkts
)
779 BlktLink
*cur_blkt
= msr
->blkts
;
783 if ( cur_blkt
->blkt_type
== 100 )
785 struct blkt_100_s
*blkt_100
= (struct blkt_100_s
*) cur_blkt
->blktdata
;
787 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
788 ms_blktdesc(cur_blkt
->blkt_type
));
789 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
790 ms_log (0, " actual sample rate: %.10g\n", blkt_100
->samprate
);
795 ms_log (0, " undefined flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
796 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
797 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
799 ms_log (0, " reserved bytes (3): %u,%u,%u\n",
800 blkt_100
->reserved
[0], blkt_100
->reserved
[1], blkt_100
->reserved
[2]);
804 else if ( cur_blkt
->blkt_type
== 200 )
806 struct blkt_200_s
*blkt_200
= (struct blkt_200_s
*) cur_blkt
->blktdata
;
808 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
809 ms_blktdesc(cur_blkt
->blkt_type
));
810 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
811 ms_log (0, " signal amplitude: %g\n", blkt_200
->amplitude
);
812 ms_log (0, " signal period: %g\n", blkt_200
->period
);
813 ms_log (0, " background estimate: %g\n", blkt_200
->background_estimate
);
818 ms_log (0, " event detection flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
819 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
820 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
821 if ( b
& 0x01 ) ms_log (0, " [Bit 0] 1: Dilatation wave\n");
822 else ms_log (0, " [Bit 0] 0: Compression wave\n");
823 if ( b
& 0x02 ) ms_log (0, " [Bit 1] 1: Units after deconvolution\n");
824 else ms_log (0, " [Bit 1] 0: Units are digital counts\n");
825 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Bit 0 is undetermined\n");
826 ms_log (0, " reserved byte: %u\n", blkt_200
->reserved
);
829 ms_btime2seedtimestr (&blkt_200
->time
, time
);
830 ms_log (0, " signal onset time: %s\n", time
);
831 ms_log (0, " detector name: %.24s\n", blkt_200
->detector
);
834 else if ( cur_blkt
->blkt_type
== 201 )
836 struct blkt_201_s
*blkt_201
= (struct blkt_201_s
*) cur_blkt
->blktdata
;
838 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
839 ms_blktdesc(cur_blkt
->blkt_type
));
840 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
841 ms_log (0, " signal amplitude: %g\n", blkt_201
->amplitude
);
842 ms_log (0, " signal period: %g\n", blkt_201
->period
);
843 ms_log (0, " background estimate: %g\n", blkt_201
->background_estimate
);
846 ms_log (0, " event detection flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
847 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
848 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
849 if ( b
& 0x01 ) ms_log (0, " [Bit 0] 1: Dilation wave\n");
850 else ms_log (0, " [Bit 0] 0: Compression wave\n");
853 ms_log (0, " reserved byte: %u\n", blkt_201
->reserved
);
854 ms_btime2seedtimestr (&blkt_201
->time
, time
);
855 ms_log (0, " signal onset time: %s\n", time
);
856 ms_log (0, " SNR values: ");
857 for (idx
=0; idx
< 6; idx
++) ms_log (0, "%u ", blkt_201
->snr_values
[idx
]);
859 ms_log (0, " loopback value: %u\n", blkt_201
->loopback
);
860 ms_log (0, " pick algorithm: %u\n", blkt_201
->pick_algorithm
);
861 ms_log (0, " detector name: %.24s\n", blkt_201
->detector
);
864 else if ( cur_blkt
->blkt_type
== 300 )
866 struct blkt_300_s
*blkt_300
= (struct blkt_300_s
*) cur_blkt
->blktdata
;
868 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
869 ms_blktdesc(cur_blkt
->blkt_type
));
870 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
871 ms_btime2seedtimestr (&blkt_300
->time
, time
);
872 ms_log (0, " calibration start time: %s\n", time
);
873 ms_log (0, " number of calibrations: %u\n", blkt_300
->numcalibrations
);
876 ms_log (0, " calibration flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
877 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
878 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
879 if ( b
& 0x01 ) ms_log (0, " [Bit 0] First pulse is positive\n");
880 if ( b
& 0x02 ) ms_log (0, " [Bit 1] Calibration's alternate sign\n");
881 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Calibration was automatic\n");
882 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Calibration continued from previous record(s)\n");
884 ms_log (0, " step duration: %u\n", blkt_300
->step_duration
);
885 ms_log (0, " interval duration: %u\n", blkt_300
->interval_duration
);
886 ms_log (0, " signal amplitude: %g\n", blkt_300
->amplitude
);
887 ms_log (0, " input signal channel: %.3s", blkt_300
->input_channel
);
889 ms_log (0, " reserved byte: %u\n", blkt_300
->reserved
);
890 ms_log (0, " reference amplitude: %u\n", blkt_300
->reference_amplitude
);
891 ms_log (0, " coupling: %.12s\n", blkt_300
->coupling
);
892 ms_log (0, " rolloff: %.12s\n", blkt_300
->rolloff
);
895 else if ( cur_blkt
->blkt_type
== 310 )
897 struct blkt_310_s
*blkt_310
= (struct blkt_310_s
*) cur_blkt
->blktdata
;
899 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
900 ms_blktdesc(cur_blkt
->blkt_type
));
901 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
902 ms_btime2seedtimestr (&blkt_310
->time
, time
);
903 ms_log (0, " calibration start time: %s\n", time
);
905 ms_log (0, " reserved byte: %u\n", blkt_310
->reserved1
);
908 ms_log (0, " calibration flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
909 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
910 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
911 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Calibration was automatic\n");
912 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Calibration continued from previous record(s)\n");
913 if ( b
& 0x10 ) ms_log (0, " [Bit 4] Peak-to-peak amplitude\n");
914 if ( b
& 0x20 ) ms_log (0, " [Bit 5] Zero-to-peak amplitude\n");
915 if ( b
& 0x40 ) ms_log (0, " [Bit 6] RMS amplitude\n");
917 ms_log (0, " calibration duration: %u\n", blkt_310
->duration
);
918 ms_log (0, " signal period: %g\n", blkt_310
->period
);
919 ms_log (0, " signal amplitude: %g\n", blkt_310
->amplitude
);
920 ms_log (0, " input signal channel: %.3s", blkt_310
->input_channel
);
922 ms_log (0, " reserved byte: %u\n", blkt_310
->reserved2
);
923 ms_log (0, " reference amplitude: %u\n", blkt_310
->reference_amplitude
);
924 ms_log (0, " coupling: %.12s\n", blkt_310
->coupling
);
925 ms_log (0, " rolloff: %.12s\n", blkt_310
->rolloff
);
928 else if ( cur_blkt
->blkt_type
== 320 )
930 struct blkt_320_s
*blkt_320
= (struct blkt_320_s
*) cur_blkt
->blktdata
;
932 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
933 ms_blktdesc(cur_blkt
->blkt_type
));
934 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
935 ms_btime2seedtimestr (&blkt_320
->time
, time
);
936 ms_log (0, " calibration start time: %s\n", time
);
938 ms_log (0, " reserved byte: %u\n", blkt_320
->reserved1
);
941 ms_log (0, " calibration flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
942 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
943 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
944 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Calibration was automatic\n");
945 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Calibration continued from previous record(s)\n");
946 if ( b
& 0x10 ) ms_log (0, " [Bit 4] Random amplitudes\n");
948 ms_log (0, " calibration duration: %u\n", blkt_320
->duration
);
949 ms_log (0, " peak-to-peak amplitude: %g\n", blkt_320
->ptp_amplitude
);
950 ms_log (0, " input signal channel: %.3s", blkt_320
->input_channel
);
952 ms_log (0, " reserved byte: %u\n", blkt_320
->reserved2
);
953 ms_log (0, " reference amplitude: %u\n", blkt_320
->reference_amplitude
);
954 ms_log (0, " coupling: %.12s\n", blkt_320
->coupling
);
955 ms_log (0, " rolloff: %.12s\n", blkt_320
->rolloff
);
956 ms_log (0, " noise type: %.8s\n", blkt_320
->noise_type
);
959 else if ( cur_blkt
->blkt_type
== 390 )
961 struct blkt_390_s
*blkt_390
= (struct blkt_390_s
*) cur_blkt
->blktdata
;
963 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
964 ms_blktdesc(cur_blkt
->blkt_type
));
965 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
966 ms_btime2seedtimestr (&blkt_390
->time
, time
);
967 ms_log (0, " calibration start time: %s\n", time
);
969 ms_log (0, " reserved byte: %u\n", blkt_390
->reserved1
);
972 ms_log (0, " calibration flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
973 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
974 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
975 if ( b
& 0x04 ) ms_log (0, " [Bit 2] Calibration was automatic\n");
976 if ( b
& 0x08 ) ms_log (0, " [Bit 3] Calibration continued from previous record(s)\n");
978 ms_log (0, " calibration duration: %u\n", blkt_390
->duration
);
979 ms_log (0, " signal amplitude: %g\n", blkt_390
->amplitude
);
980 ms_log (0, " input signal channel: %.3s", blkt_390
->input_channel
);
982 ms_log (0, " reserved byte: %u\n", blkt_390
->reserved2
);
985 else if ( cur_blkt
->blkt_type
== 395 )
987 struct blkt_395_s
*blkt_395
= (struct blkt_395_s
*) cur_blkt
->blktdata
;
989 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
990 ms_blktdesc(cur_blkt
->blkt_type
));
991 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
992 ms_btime2seedtimestr (&blkt_395
->time
, time
);
993 ms_log (0, " calibration end time: %s\n", time
);
995 ms_log (0, " reserved bytes (2): %u,%u\n",
996 blkt_395
->reserved
[0], blkt_395
->reserved
[1]);
999 else if ( cur_blkt
->blkt_type
== 400 )
1001 struct blkt_400_s
*blkt_400
= (struct blkt_400_s
*) cur_blkt
->blktdata
;
1003 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
1004 ms_blktdesc(cur_blkt
->blkt_type
));
1005 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1006 ms_log (0, " beam azimuth (degrees): %g\n", blkt_400
->azimuth
);
1007 ms_log (0, " beam slowness (sec/degree): %g\n", blkt_400
->slowness
);
1008 ms_log (0, " configuration: %u\n", blkt_400
->configuration
);
1010 ms_log (0, " reserved bytes (2): %u,%u\n",
1011 blkt_400
->reserved
[0], blkt_400
->reserved
[1]);
1014 else if ( cur_blkt
->blkt_type
== 405 )
1016 struct blkt_405_s
*blkt_405
= (struct blkt_405_s
*) cur_blkt
->blktdata
;
1018 ms_log (0, " BLOCKETTE %u: (%s, incomplete)\n", cur_blkt
->blkt_type
,
1019 ms_blktdesc(cur_blkt
->blkt_type
));
1020 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1021 ms_log (0, " first delay value: %u\n", blkt_405
->delay_values
[0]);
1024 else if ( cur_blkt
->blkt_type
== 500 )
1026 struct blkt_500_s
*blkt_500
= (struct blkt_500_s
*) cur_blkt
->blktdata
;
1028 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
1029 ms_blktdesc(cur_blkt
->blkt_type
));
1030 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1031 ms_log (0, " VCO correction: %g%%\n", blkt_500
->vco_correction
);
1032 ms_btime2seedtimestr (&blkt_500
->time
, time
);
1033 ms_log (0, " time of exception: %s\n", time
);
1034 ms_log (0, " usec: %d\n", blkt_500
->usec
);
1035 ms_log (0, " reception quality: %u%%\n", blkt_500
->reception_qual
);
1036 ms_log (0, " exception count: %u\n", blkt_500
->exception_count
);
1037 ms_log (0, " exception type: %.16s\n", blkt_500
->exception_type
);
1038 ms_log (0, " clock model: %.32s\n", blkt_500
->clock_model
);
1039 ms_log (0, " clock status: %.128s\n", blkt_500
->clock_status
);
1042 else if ( cur_blkt
->blkt_type
== 1000 )
1044 struct blkt_1000_s
*blkt_1000
= (struct blkt_1000_s
*) cur_blkt
->blktdata
;
1048 /* Calculate record size in bytes as 2^(blkt_1000->rec_len) */
1049 recsize
= (unsigned int) 1 << blkt_1000
->reclen
;
1051 /* Big or little endian? */
1052 if (blkt_1000
->byteorder
== 0)
1053 strncpy (order
, "Little endian", sizeof(order
)-1);
1054 else if (blkt_1000
->byteorder
== 1)
1055 strncpy (order
, "Big endian", sizeof(order
)-1);
1057 strncpy (order
, "Unknown value", sizeof(order
)-1);
1059 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
1060 ms_blktdesc(cur_blkt
->blkt_type
));
1061 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1062 ms_log (0, " encoding: %s (val:%u)\n",
1063 (char *) ms_encodingstr (blkt_1000
->encoding
), blkt_1000
->encoding
);
1064 ms_log (0, " byte order: %s (val:%u)\n",
1065 order
, blkt_1000
->byteorder
);
1066 ms_log (0, " record length: %d (val:%u)\n",
1067 recsize
, blkt_1000
->reclen
);
1070 ms_log (0, " reserved byte: %u\n", blkt_1000
->reserved
);
1073 else if ( cur_blkt
->blkt_type
== 1001 )
1075 struct blkt_1001_s
*blkt_1001
= (struct blkt_1001_s
*) cur_blkt
->blktdata
;
1077 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
1078 ms_blktdesc(cur_blkt
->blkt_type
));
1079 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1080 ms_log (0, " timing quality: %u%%\n", blkt_1001
->timing_qual
);
1081 ms_log (0, " micro second: %d\n", blkt_1001
->usec
);
1084 ms_log (0, " reserved byte: %u\n", blkt_1001
->reserved
);
1086 ms_log (0, " frame count: %u\n", blkt_1001
->framecnt
);
1089 else if ( cur_blkt
->blkt_type
== 2000 )
1091 struct blkt_2000_s
*blkt_2000
= (struct blkt_2000_s
*) cur_blkt
->blktdata
;
1094 /* Big or little endian? */
1095 if (blkt_2000
->byteorder
== 0)
1096 strncpy (order
, "Little endian", sizeof(order
)-1);
1097 else if (blkt_2000
->byteorder
== 1)
1098 strncpy (order
, "Big endian", sizeof(order
)-1);
1100 strncpy (order
, "Unknown value", sizeof(order
)-1);
1102 ms_log (0, " BLOCKETTE %u: (%s)\n", cur_blkt
->blkt_type
,
1103 ms_blktdesc(cur_blkt
->blkt_type
));
1104 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1105 ms_log (0, " blockette length: %u\n", blkt_2000
->length
);
1106 ms_log (0, " data offset: %u\n", blkt_2000
->data_offset
);
1107 ms_log (0, " record number: %u\n", blkt_2000
->recnum
);
1108 ms_log (0, " byte order: %s (val:%u)\n",
1109 order
, blkt_2000
->byteorder
);
1110 b
= blkt_2000
->flags
;
1111 ms_log (0, " data flags: [%u%u%u%u%u%u%u%u] 8 bits\n",
1112 bit(b
,0x01), bit(b
,0x02), bit(b
,0x04), bit(b
,0x08),
1113 bit(b
,0x10), bit(b
,0x20), bit(b
,0x40), bit(b
,0x80));
1117 if ( b
& 0x01 ) ms_log (0, " [Bit 0] 1: Stream oriented\n");
1118 else ms_log (0, " [Bit 0] 0: Record oriented\n");
1119 if ( b
& 0x02 ) ms_log (0, " [Bit 1] 1: Blockette 2000s may NOT be packaged\n");
1120 else ms_log (0, " [Bit 1] 0: Blockette 2000s may be packaged\n");
1121 if ( ! (b
& 0x04) && ! (b
& 0x08) )
1122 ms_log (0, " [Bits 2-3] 00: Complete blockette\n");
1123 else if ( ! (b
& 0x04) && (b
& 0x08) )
1124 ms_log (0, " [Bits 2-3] 01: First blockette in span\n");
1125 else if ( (b
& 0x04) && (b
& 0x08) )
1126 ms_log (0, " [Bits 2-3] 11: Continuation blockette in span\n");
1127 else if ( (b
& 0x04) && ! (b
& 0x08) )
1128 ms_log (0, " [Bits 2-3] 10: Final blockette in span\n");
1129 if ( ! (b
& 0x10) && ! (b
& 0x20) )
1130 ms_log (0, " [Bits 4-5] 00: Not file oriented\n");
1131 else if ( ! (b
& 0x10) && (b
& 0x20) )
1132 ms_log (0, " [Bits 4-5] 01: First blockette of file\n");
1133 else if ( (b
& 0x10) && ! (b
& 0x20) )
1134 ms_log (0, " [Bits 4-5] 10: Continuation of file\n");
1135 else if ( (b
& 0x10) && (b
& 0x20) )
1136 ms_log (0, " [Bits 4-5] 11: Last blockette of file\n");
1139 ms_log (0, " number of headers: %u\n", blkt_2000
->numheaders
);
1141 /* Crude display of the opaque data headers */
1143 ms_log (0, " headers: %.*s\n",
1144 (blkt_2000
->data_offset
- 15), blkt_2000
->payload
);
1149 ms_log (0, " BLOCKETTE %u: (%s, not parsed)\n", cur_blkt
->blkt_type
,
1150 ms_blktdesc(cur_blkt
->blkt_type
));
1151 ms_log (0, " next blockette: %u\n", cur_blkt
->next_blkt
);
1154 cur_blkt
= cur_blkt
->next
;
1157 } /* End of msr_print() */
1160 /***************************************************************************
1163 * Calculate the latency based on the host time in UTC accounting for
1164 * the time covered using the number of samples and sample rate; in
1165 * other words, the difference between the host time and the time of
1166 * the last sample in the specified Mini-SEED record.
1168 * Double precision is returned, but the true precision is dependent
1169 * on the accuracy of the host system clock among other things.
1171 * Returns seconds of latency or 0.0 on error (indistinguishable from
1173 ***************************************************************************/
1175 msr_host_latency (MSRecord
*msr
)
1177 double span
= 0.0; /* Time covered by the samples */
1178 double epoch
; /* Current epoch time */
1179 double latency
= 0.0;
1185 /* Calculate the time covered by the samples */
1186 if ( msr
->samprate
> 0.0 && msr
->samplecnt
> 0 )
1187 span
= (1.0 / msr
->samprate
) * (msr
->samplecnt
- 1);
1189 /* Grab UTC time according to the system clock */
1190 epoch
= (double) time(&tv
);
1192 /* Now calculate the latency */
1193 latency
= epoch
- ((double) msr
->starttime
/ HPTMODULUS
) - span
;
1196 } /* End of msr_host_latency() */