Show the file size of the files in the tmp_dir on the LCD.
[ruwai.git] / software / c++ / ruwaicom / src / libmseed / msrutils.c
blob876e9ab21a4c50f4c50a0673158959156c61ffe0
1 /***************************************************************************
2 * msrutils.c:
4 * Generic routines to operate on Mini-SEED records.
6 * Written by Chad Trabant
7 * ORFEUS/EC-Project MEREDIAN
8 * IRIS Data Management Center
10 * modified: 2015.213
11 ***************************************************************************/
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
18 #include "libmseed.h"
21 /***************************************************************************
22 * msr_init:
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 ***************************************************************************/
31 MSRecord *
32 msr_init ( MSRecord *msr )
34 void *fsdh = 0;
35 void *datasamples = 0;
37 if ( ! msr )
39 msr = (MSRecord *) malloc (sizeof(MSRecord));
41 else
43 fsdh = msr->fsdh;
44 datasamples = msr->datasamples;
46 if ( msr->blkts )
47 msr_free_blktchain (msr);
49 if ( msr->ststate )
50 free (msr->ststate);
53 if ( msr == NULL )
55 ms_log (2, "msr_init(): Cannot allocate memory\n");
56 return NULL;
59 memset (msr, 0, sizeof (MSRecord));
61 msr->fsdh = fsdh;
62 msr->datasamples = datasamples;
64 msr->reclen = -1;
65 msr->samplecnt = -1;
66 msr->byteorder = -1;
67 msr->encoding = -1;
69 return msr;
70 } /* End of msr_init() */
73 /***************************************************************************
74 * msr_free:
76 * Free all memory associated with a MSRecord struct.
77 ***************************************************************************/
78 void
79 msr_free ( MSRecord **ppmsr )
81 if ( ppmsr != NULL && *ppmsr != 0 )
83 /* Free fixed section header if populated */
84 if ( (*ppmsr)->fsdh )
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);
99 free (*ppmsr);
101 *ppmsr = NULL;
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 ***************************************************************************/
113 void
114 msr_free_blktchain ( MSRecord *msr )
116 if ( msr )
118 if ( msr->blkts )
120 BlktLink *bc = msr->blkts;
121 BlktLink *nb = NULL;
123 while ( bc )
125 nb = bc->next;
127 if ( bc->blktdata )
128 free (bc->blktdata);
130 free (bc);
132 bc = nb;
135 msr->blkts = 0;
138 msr->Blkt100 = 0;
139 msr->Blkt1000 = 0;
140 msr->Blkt1001 = 0;
142 } /* End of msr_free_blktchain() */
145 /***************************************************************************
146 * msr_addblockette:
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
157 * NULL on error.
158 ***************************************************************************/
159 BlktLink *
160 msr_addblockette (MSRecord *msr, char *blktdata, int length, int blkttype,
161 int chainpos)
163 BlktLink *blkt;
165 if ( ! msr )
166 return NULL;
168 blkt = msr->blkts;
170 if ( blkt )
172 if ( chainpos != 0 )
174 blkt = (BlktLink *) malloc (sizeof(BlktLink));
176 blkt->next = msr->blkts;
177 msr->blkts = blkt;
179 else
181 /* Find the last blockette */
182 while ( blkt && blkt->next )
184 blkt = blkt->next;
187 blkt->next = (BlktLink *) malloc (sizeof(BlktLink));
189 blkt = blkt->next;
190 blkt->next = 0;
193 if ( blkt == NULL )
195 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
196 return NULL;
199 else
201 msr->blkts = (BlktLink *) malloc (sizeof(BlktLink));
203 if ( msr->blkts == NULL )
205 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
206 return NULL;
209 blkt = msr->blkts;
210 blkt->next = 0;
213 blkt->blktoffset = 0;
214 blkt->blkt_type = blkttype;
215 blkt->next_blkt = 0;
217 blkt->blktdata = (char *) malloc (length);
219 if ( blkt->blktdata == NULL )
221 ms_log (2, "msr_addblockette(): Cannot allocate memory\n");
222 return NULL;
225 memcpy (blkt->blktdata, blktdata, length);
226 blkt->blktdatalen = length;
228 /* Setup the shortcut pointer for common blockettes */
229 switch ( blkttype )
231 case 100:
232 msr->Blkt100 = blkt->blktdata;
233 break;
234 case 1000:
235 msr->Blkt1000 = blkt->blktdata;
236 break;
237 case 1001:
238 msr->Blkt1001 = blkt->blktdata;
239 break;
242 return blkt;
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;
260 hptime_t hptimems;
261 int8_t usecoffset;
262 char seqnum[7];
263 int offset = 0;
264 int blktcnt = 0;
265 int reclenexp = 0;
266 int reclenfind;
268 if ( ! msr )
269 return -1;
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 */
275 if ( msr->fsdh )
277 if ( verbose > 2 )
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));
302 else
304 if ( verbose > 1 )
305 ms_log (1, "Sampling rate too high to approximate factor & multiplier: %g\n",
306 msr->samprate);
307 msr->fsdh->samprate_fact = 0;
308 msr->fsdh->samprate_mult = 0;
311 offset += 48;
313 if ( msr->blkts )
314 msr->fsdh->blockette_offset = offset;
315 else
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");
325 while ( cur_blkt )
327 offset += 4;
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++)
342 reclenfind *= 2;
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",
349 msr->reclen);
350 return -1;
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);
364 blktcnt++;
365 cur_blkt = cur_blkt->next;
368 if ( msr->fsdh )
369 msr->fsdh->numblockettes = blktcnt;
371 return offset;
372 } /* End of msr_normalize_header() */
375 /***************************************************************************
376 * msr_duplicate:
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 ***************************************************************************/
387 MSRecord *
388 msr_duplicate (MSRecord *msr, flag datadup)
390 MSRecord *dupmsr = 0;
391 int samplesize = 0;
393 if ( ! msr )
394 return NULL;
396 /* Allocate target MSRecord structure */
397 if ( (dupmsr = msr_init (NULL)) == NULL )
398 return NULL;
400 /* Copy MSRecord structure */
401 memcpy (dupmsr, msr, sizeof(MSRecord));
403 /* Copy fixed-section data header structure */
404 if ( msr->fsdh )
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");
410 free (dupmsr);
411 return NULL;
414 /* Copy the contents */
415 memcpy (dupmsr->fsdh, msr->fsdh, sizeof(struct fsdh_s));
418 /* Copy the blockette chain */
419 if ( msr->blkts )
421 BlktLink *blkt = msr->blkts;
422 BlktLink *next = NULL;
424 dupmsr->blkts = 0;
425 while ( blkt )
427 next = blkt->next;
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");
434 msr_free (&dupmsr);
435 return NULL;
438 blkt = next;
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",
451 msr->sampletype);
452 free (dupmsr);
453 return NULL;
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");
460 free (dupmsr);
461 return NULL;
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 */
468 else
470 dupmsr->datasamples = 0;
471 dupmsr->numsamples = 0;
474 return dupmsr;
475 } /* End of msr_duplicate() */
478 /***************************************************************************
479 * msr_samprate:
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 ***************************************************************************/
489 double
490 msr_samprate (MSRecord *msr)
492 if ( ! msr )
493 return -1.0;
495 if ( msr->Blkt100 )
496 return (double) msr->Blkt100->samprate;
497 else
498 return msr_nomsamprate (msr);
499 } /* End of msr_samprate() */
502 /***************************************************************************
503 * msr_nomsamprate:
505 * Calculate a double precision nominal sample rate from the sample
506 * rate factor and multiplier in the FSDH struct of the specified
507 * MSRecord.
509 * Returns the positive sample rate on success and -1.0 on error.
510 ***************************************************************************/
511 double
512 msr_nomsamprate (MSRecord *msr)
514 if ( ! msr )
515 return -1.0;
517 return ms_nomsamprate (msr->fsdh->samprate_fact, msr->fsdh->samprate_mult);
518 } /* End of msr_nomsamprate() */
521 /***************************************************************************
522 * msr_starttime:
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
532 * error.
533 ***************************************************************************/
534 hptime_t
535 msr_starttime (MSRecord *msr)
537 hptime_t starttime = msr_starttime_uc (msr);
539 if ( ! msr || starttime == HPTERROR )
540 return 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 */
552 if ( msr->Blkt1001 )
554 starttime += (hptime_t) msr->Blkt1001->usec * (HPTMODULUS / 1000000);
557 return starttime;
558 } /* End of msr_starttime() */
561 /***************************************************************************
562 * msr_starttime_uc:
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
569 * error.
570 ***************************************************************************/
571 hptime_t
572 msr_starttime_uc (MSRecord *msr)
574 if ( ! msr )
575 return HPTERROR;
577 if ( ! msr->fsdh )
578 return HPTERROR;
580 return ms_btime2hptime (&msr->fsdh->start_time);
581 } /* End of msr_starttime_uc() */
584 /***************************************************************************
585 * msr_endtime:
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
589 * sample.
591 * Returns the time of the last sample as a high precision epoch time
592 * on success and HPTERROR on error.
593 ***************************************************************************/
594 hptime_t
595 msr_endtime (MSRecord *msr)
597 hptime_t span = 0;
598 LeapSecond *lslist = leapsecondlist;
600 if ( ! msr )
601 return HPTERROR;
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 */
607 if ( lslist )
609 while ( lslist )
611 if ( lslist->leapsecond > msr->starttime &&
612 lslist->leapsecond < (msr->starttime + span) )
614 span -= HPTMODULUS;
615 break;
618 lslist = lslist->next;
621 else
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. */
626 if ( msr->fsdh )
627 if ( msr->fsdh->act_flags & 0x10 )
628 span -= HPTMODULUS;
631 return (msr->starttime + span);
632 } /* End of msr_endtime() */
635 /***************************************************************************
636 * msr_srcname:
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 ***************************************************************************/
645 char *
646 msr_srcname (MSRecord *msr, char *srcname, flag quality)
648 char *src = srcname;
649 char *cp = srcname;
651 if ( ! msr || ! srcname )
652 return NULL;
654 /* Build the source name string */
655 cp = msr->network;
656 while ( *cp ) { *src++ = *cp++; }
657 *src++ = '_';
658 cp = msr->station;
659 while ( *cp ) { *src++ = *cp++; }
660 *src++ = '_';
661 cp = msr->location;
662 while ( *cp ) { *src++ = *cp++; }
663 *src++ = '_';
664 cp = msr->channel;
665 while ( *cp ) { *src++ = *cp++; }
667 if ( quality )
669 *src++ = '_';
670 *src++ = msr->dataquality;
673 *src = '\0';
675 return srcname;
676 } /* End of msr_srcname() */
679 /***************************************************************************
680 * msr_print:
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 ***************************************************************************/
688 void
689 msr_print (MSRecord *msr, flag details)
691 double nomsamprate;
692 char srcname[50];
693 char time[25];
694 char b;
695 int idx;
697 if ( ! msr )
698 return;
700 /* Generate a source name string */
701 srcname[0] = '\0';
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);
719 if ( details > 1 )
721 /* Activity flags */
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);
769 else
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;
781 while ( cur_blkt )
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);
792 if ( details > 1 )
794 b = blkt_100->flags;
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);
815 if ( details > 1 )
817 b = blkt_200->flags;
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);
845 b = blkt_201->flags;
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");
852 if ( details > 1 )
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]);
858 ms_log (0, "\n");
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);
875 b = blkt_300->flags;
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);
888 if ( details > 1 )
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);
904 if ( details > 1 )
905 ms_log (0, " reserved byte: %u\n", blkt_310->reserved1);
907 b = blkt_310->flags;
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);
921 if ( details > 1 )
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);
937 if ( details > 1 )
938 ms_log (0, " reserved byte: %u\n", blkt_320->reserved1);
940 b = blkt_320->flags;
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);
951 if ( details > 1 )
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);
968 if ( details > 1 )
969 ms_log (0, " reserved byte: %u\n", blkt_390->reserved1);
971 b = blkt_390->flags;
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);
981 if ( details > 1 )
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);
994 if ( details > 1 )
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);
1009 if ( details > 1 )
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;
1045 int recsize;
1046 char order[40];
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);
1056 else
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);
1069 if ( details > 1 )
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);
1083 if ( details > 1 )
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;
1092 char order[40];
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);
1099 else
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));
1115 if ( details > 1 )
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 */
1142 if ( details > 1 )
1143 ms_log (0, " headers: %.*s\n",
1144 (blkt_2000->data_offset - 15), blkt_2000->payload);
1147 else
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 /***************************************************************************
1161 * msr_host_latency:
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
1172 * 0.0 latency).
1173 ***************************************************************************/
1174 double
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;
1180 time_t tv;
1182 if ( msr == NULL )
1183 return 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;
1195 return latency;
1196 } /* End of msr_host_latency() */