You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.9 KiB
C++

/*****************************************************************************
* mseed.cpp
*
* Mini-SEED format implementation
*
* (c) 2000 Andres Heinloo, GFZ Potsdam
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any later
* version. For more information, see http://www.gnu.org/
*
* ================
* Change log
* ===============
*
* 01.01.2013 Adapted code to CAPS client library requirements (gempa GmbH)
*****************************************************************************/
#include <gempa/caps/mseedpacket.h>
#include <gempa/caps/rawpacket.h>
#include "mseed.h"
#include "slink.h"
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <stdint.h>
#include <netinet/in.h>
namespace Gempa {
namespace CAPS {
MSEEDFormat::MSEEDFormat(const std::string &netcode, const std::string &stacode,
const std::string &loccode, const std::string &chacode,
unsigned short freqn, unsigned short freqd,
unsigned short packtype_init,
uint8_t recordLength)
: networkCode(netcode), stationCode(stacode), locationCode(loccode),
channelCode(chacode), packType(packtype_init), recordLength(recordLength)
{
if(freqn == 0 || freqd == 0) {
sample_rate_factor = 0;
sample_rate_multiplier = 0;
}
else if(!(freqn % freqd)) {
sample_rate_factor = freqn / freqd;
sample_rate_multiplier = 1;
}
else if(!(freqd % freqn)) {
sample_rate_factor = -freqd / freqn;
sample_rate_multiplier = 1;
}
else {
sample_rate_factor = -freqd;
sample_rate_multiplier = freqn;
}
}
MSEEDDataRecord *MSEEDFormat::get_buffer(const SPClock::INT_TIME &it, int usec_correction,
int timing_quality, void *&dataptr, int &datalen) {
size_t buflen = 1 << recordLength;
MSEEDDataRecord *record = new MSEEDDataRecord();
record->data()->resize(buflen);
char *buf = record->data()->data();
int n;
sl_fsdh_s* fsdh = (sl_fsdh_s *)buf;
memset(fsdh, 0, buflen);
const int start_frames = (sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s) +
sizeof(sl_blkt_1001_s) + 63) & 0xffffffc0; // align to 64 bytes
dataptr = (void *)((char *) fsdh + start_frames);
datalen = buflen - start_frames;
fsdh->dhq_indicator = 'D';
fsdh->reserved = ' ';
strncpy(fsdh->station, stationCode.c_str(), 5);
if((n = stationCode.length()) < 5) memset(fsdh->station + n, 32, 5 - n);
strncpy(fsdh->location, locationCode.c_str(), 2);
if((n = locationCode.length()) < 2) memset(fsdh->location + n, 32, 2 - n);
strncpy(fsdh->channel, channelCode.c_str(), 3);
if((n = channelCode.length()) < 3) memset(fsdh->channel + n, 32, 3 - n);
strncpy(fsdh->network, networkCode.c_str(), 2);
if((n = networkCode.length()) < 2) memset(fsdh->network + n, 32, 2 - n);
int year, doy, hour, min, sec;
it.get2(&year, &doy, &hour, &min, &sec);
fsdh->start_time.year = htons(year);
fsdh->start_time.day = htons(doy+1);
fsdh->start_time.hour = hour;
fsdh->start_time.min = min;
fsdh->start_time.sec = sec;
fsdh->start_time.fract = htons(it.microseconds() / 100);
fsdh->samprate_fact = (int16_t)htons(sample_rate_factor);
fsdh->samprate_mult = (int16_t)htons(sample_rate_multiplier);
fsdh->num_blockettes = 1;
div_t d_corr = div(usec_correction + ((usec_correction < 0) ? -50: 50), 100);
fsdh->time_correct = (int32_t)htonl(d_corr.quot);
fsdh->begin_data = htons(start_frames);
fsdh->begin_blockette = htons(sizeof(sl_fsdh_s));
sl_blkt_1000_s* blkt_1000 = (sl_blkt_1000_s *)((char *) fsdh + sizeof(sl_fsdh_s));
blkt_1000->blkt_type = htons(1000); // Data Only SEED Blockette
blkt_1000->encoding = packType;
blkt_1000->word_swap = 1; // big endian
blkt_1000->rec_len = recordLength; // 9 = 512 bytes
if ( timing_quality >= 0 ) {
blkt_1000->next_blkt = htons(sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
++fsdh->num_blockettes;
sl_blkt_1001_s* blkt_1001 = (sl_blkt_1001_s *)((char *) fsdh +
sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
blkt_1001->blkt_type = htons(1001); // Data Extension Blockette
blkt_1001->timing_qual = timing_quality;
blkt_1001->usec = 0;
}
return record;
}
void MSEEDFormat::updateBuffer(MSEEDDataRecord *rec, int samples, int frames) {
sl_fsdh_s* fsdh = (sl_fsdh_s *)rec->data()->data();
char temp[7];
sprintf(temp, "%06d", (int)0);
memcpy(fsdh->sequence_number,temp,6);
fsdh->dhq_indicator = 'D';
fsdh->num_samples = htons(samples);
sl_blkt_1000_s* blkt_1000 = (sl_blkt_1000_s *)((char *) fsdh + sizeof(sl_fsdh_s));
if ( ntohs(blkt_1000->next_blkt) != 0 ) {
sl_blkt_1001_s* blkt_1001 = (sl_blkt_1001_s *)((char *) fsdh +
sizeof(sl_fsdh_s) + sizeof(sl_blkt_1000_s));
blkt_1001->frame_cnt = frames;
}
rec->unpackHeader();
}
}
}