Initial commit based on common repo commit ffeb9c9b

This commit is contained in:
2021-04-22 15:57:00 +02:00
commit 8b2a408e6f
107 changed files with 61542 additions and 0 deletions

View File

@ -0,0 +1,75 @@
/*****************************************************************************
* encoder.h
*
* Abstract Encoder interface
*
* (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)
*****************************************************************************/
#ifndef CAPS_MSEED_ENCODER_H
#define CAPS_MSEED_ENCODER_H
#include "packet.h"
#include "spclock.h"
#include <gempa/caps/datetime.h>
#include <gempa/caps/pluginpacket.h>
#include <list>
#include <sys/types.h>
namespace Gempa {
namespace CAPS {
class Encoder {
public:
Encoder(int freqn, int freqd) : _clk(freqn, freqd),
_sampleCount(0), _timingQuality(-1) {}
virtual ~Encoder() {}
virtual void push(void *sample) = 0;
virtual void flush() = 0;
virtual void reset() { _sampleCount = 0; }
virtual int type() const = 0;
const SPClock& clk() { return _clk; }
void setStartTime(const SPClock::INT_TIME &time) { _clk.sync_time(time); }
const SPClock::INT_TIME currentTime() const { return _clk.get_time(0); }
int timingQuality() { return _timingQuality; }
void setTimingQuality(int quality) { _timingQuality = quality; }
PacketPtr pop() {
if ( _packetQueue.empty() ) return PacketPtr();
PacketPtr rec = _packetQueue.front();
_packetQueue.pop_front();
return rec;
}
protected:
typedef std::list<PacketPtr> PacketQueue;
SPClock _clk;
int _sampleCount;
PacketQueue _packetQueue;
int _timingQuality;
};
}
}
#endif // __ENCODER_H__

View File

@ -0,0 +1,162 @@
/*****************************************************************************
* 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();
}
}
}

View File

@ -0,0 +1,90 @@
/*****************************************************************************
* mseed.h
*
* 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)
*****************************************************************************/
#ifndef CAPS_MSEED_MSEED_H
#define CAPS_MSEED_MSEED_H
#include "packet.h"
#include "spclock.h"
#include <gempa/caps/mseedpacket.h>
#include <string>
namespace Gempa {
namespace CAPS {
/* SEED data encoding types */
enum SEEDDataEncodingType {
DE_ASCII = 0,
DE_INT16 = 1,
DE_INT32 = 3,
DE_FLOAT32 = 4,
DE_FLOAT64 = 5,
DE_STEIM1 = 10,
DE_STEIM2 = 11,
DE_GEOSCOPE24 = 12,
DE_GEOSCOPE163 = 13,
DE_GEOSCOPE164 = 14,
DE_CDSN = 16,
DE_SRO = 30,
DE_DWWSSN = 32
};
struct MSEEDFormat {
MSEEDFormat(const std::string &networkCode, const std::string &stationCode,
const std::string &locationCode, const std::string &channelCode,
unsigned short freqn, unsigned short freqd,
unsigned short packtype_init,
uint8_t recLen);
template<class T>
MSEEDEncoderPacket<T>
get_packet(const SPClock::INT_TIME &it, int usec_correction, int timing_quality) {
void *dataptr = NULL;
int datalen = 0;
unsigned int size = 0;
MSEEDDataRecord *rec = get_buffer(it, usec_correction, timing_quality, dataptr, datalen);
return MSEEDEncoderPacket<T>(rec, size, dataptr, datalen);
}
MSEEDDataRecord *get_buffer(const SPClock::INT_TIME &it, int usec_correction,
int timing_quality,
void *&dataptr, int &datalen);
void updateBuffer(MSEEDDataRecord *rec, int samples, int frames);
std::string networkCode;
std::string stationCode;
std::string locationCode;
std::string channelCode;
int sample_rate_factor;
int sample_rate_multiplier;
unsigned short packType;
int timingQuality;
uint8_t recordLength;
};
}
}
#endif

View File

@ -0,0 +1,44 @@
/***************************************************************************
* Copyright (C) 2012 by gempa GmbH *
* *
* All Rights Reserved. *
* *
* NOTICE: All information contained herein is, and remains *
* the property of gempa GmbH and its suppliers, if any. The intellectual *
* and technical concepts contained herein are proprietary to gempa GmbH *
* and its suppliers. *
* Dissemination of this information or reproduction of this material *
* is strictly forbidden unless prior written permission is obtained *
* from gempa GmbH. *
***************************************************************************/
#ifndef CAPS_MSEED_PACKET_H
#define CAPS_MSEED_PACKET_H
#include <gempa/caps/mseedpacket.h>
#include <string>
namespace Gempa {
namespace CAPS {
template<typename T> struct MSEEDEncoderPacket {
MSEEDEncoderPacket(): record(NULL), data(NULL), datalen(0) {}
MSEEDEncoderPacket(MSEEDDataRecord *rec, unsigned int size_init,
void *data_init, unsigned short datalen_init)
: record(rec), data(static_cast<T*>(data_init)),
datalen(datalen_init) {}
~MSEEDEncoderPacket() {}
void reset() { record = NULL; data = NULL; datalen = 0; }
bool valid() const { return record != NULL; }
MSEEDDataRecord *record;
T *data;
unsigned short datalen;
};
}
}
#endif

View File

@ -0,0 +1,131 @@
/*****************************************************************************
* slink.h
*
* SeedLink protocol constants
*
* Token from libslink
*
* 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)
*****************************************************************************/
#ifndef CAPS_MSEED_SLINK_H
#define CAPS_MSEED_SLINK_H
#ifdef __cplusplus
extern "C" {
#endif
/* Portability to the XScale (ARM) architecture
* requires a packed attribute in certain places
* but this only works with GCC for now.
*/
#if defined (__GNUC__)
#define SLP_PACKED __attribute__ ((packed))
#else
#define SLP_PACKED
#endif
#define SIGNATURE "SL" /* SeedLink header signature */
#define INFOSIGNATURE "SLINFO" /* SeedLink INFO packet signature */
/* SeedLink packet types */
#define SLDATA 0 /* waveform data record */
#define SLDET 1 /* detection record */
#define SLCAL 2 /* calibration record */
#define SLTIM 3 /* timing record */
#define SLMSG 4 /* message record */
#define SLBLK 5 /* general record */
#define SLNUM 6 /* used as the error indicator (same as SLCHA) */
#define SLCHA 6 /* for requesting channel info or detectors */
#define SLINF 7 /* a non-terminating XML formatted message in a miniSEED
log record, used for INFO responses */
#define SLINFT 8 /* a terminating XML formatted message in a miniSEED log
record, used for INFO responses */
#define SLKEEP 9 /* an XML formatted message in a miniSEED log
record, used for keepalive/heartbeat responses */
/* SEED binary time (10 bytes) */
struct sl_btime_s
{
uint16_t year;
uint16_t day;
uint8_t hour;
uint8_t min;
uint8_t sec;
uint8_t unused;
uint16_t fract;
} SLP_PACKED;
/* Fixed section data of header (48 bytes) */
struct sl_fsdh_s
{
char sequence_number[6];
char dhq_indicator;
char reserved;
char station[5];
char location[2];
char channel[3];
char network[2];
struct sl_btime_s start_time;
uint16_t num_samples;
int16_t samprate_fact;
int16_t samprate_mult;
uint8_t act_flags;
uint8_t io_flags;
uint8_t dq_flags;
uint8_t num_blockettes;
int32_t time_correct;
uint16_t begin_data;
uint16_t begin_blockette;
} SLP_PACKED;
/* 1000 Blockette (8 bytes) */
struct sl_blkt_1000_s
{
uint16_t blkt_type;
uint16_t next_blkt;
uint8_t encoding;
uint8_t word_swap;
uint8_t rec_len;
uint8_t reserved;
} SLP_PACKED;
/* 1001 Blockette (8 bytes) */
struct sl_blkt_1001_s
{
uint16_t blkt_type;
uint16_t next_blkt;
int8_t timing_qual;
int8_t usec;
uint8_t reserved;
int8_t frame_cnt;
} SLP_PACKED;
/* Generic struct for head of blockettes */
struct sl_blkt_head_s
{
uint16_t blkt_type;
uint16_t next_blkt;
} SLP_PACKED;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,78 @@
/*****************************************************************************
* spclock.h
*
* Stream Processor Clock
*
* (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)
*****************************************************************************/
#ifndef CAPS_MSEED_SPCLOCK_H
#define CAPS_MSEED_SPCLOCK_H
#include <gempa/caps/datetime.h>
namespace Gempa {
namespace CAPS {
class SPClock
{
public:
typedef Gempa::CAPS::Time INT_TIME;
private:
INT_TIME itime;
int ticks;
int corr;
public:
const int freqn;
const int freqd;
SPClock(int freqn_init, int freqd_init): ticks(0), corr(0),
freqn(freqn_init), freqd(freqd_init)
{}
void sync_time(const INT_TIME &time)
{
itime = time;
ticks = 0;
corr = 0;
}
void tick()
{
++ticks;
}
INT_TIME get_time(int tick_diff) const
{
int64_t correctness = (double)freqd / (double)freqn * 1000000 * (ticks - tick_diff - corr);
return itime + Gempa::CAPS::TimeSpan(long(correctness/1000000),long(correctness%1000000));
}
int correction() const
{
return corr;
}
};
}
}
#endif // SPCLOCK_H

View File

@ -0,0 +1,90 @@
/*****************************************************************************
* steim1.h
*
* Steim1 encoder
*
* (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)
*****************************************************************************/
#ifndef CAPS_MSEED_STEIM1_H
#define CAPS_MSEED_STEIM1_H
#include "encoder.h"
#include "mseed.h"
namespace Gempa {
namespace CAPS {
//*****************************************************************************
// Steim1Frame
//*****************************************************************************
struct Steim1Frame {
u_int32_t nibble_word;
u_int32_t sample_word[15];
};
//*****************************************************************************
// Steim1Encoder
//*****************************************************************************
template<typename T>
class Steim1Encoder: public Encoder {
private:
MSEEDFormat *format;
int frame_count;
int bp;
int fp;
int spw;
int32_t last_sample;
int32_t buf[5];
u_int32_t nibble_word;
MSEEDEncoderPacket<Steim1Frame> current_packet;
void update_spw(int bp);
void store(int32_t value);
void init_packet();
void finish_packet();
void update_packet();
MSEEDEncoderPacket<Steim1Frame> get_packet() {
return format->get_packet<Steim1Frame>(_clk.get_time(bp),
_clk.correction(), _timingQuality);
}
void queue_packet(MSEEDEncoderPacket<Steim1Frame> &pckt);
int number_of_frames(const MSEEDEncoderPacket<Steim1Frame> &packet) {
return (packet.datalen >> 6);
}
public:
Steim1Encoder(MSEEDFormat *format, int freqn, int freqd)
: Encoder(freqn, freqd), format(format), frame_count(0),
bp(0), fp(0), spw(4), last_sample(0), nibble_word(0) {}
virtual ~Steim1Encoder();
virtual void flush();
virtual void push(void *value);
virtual int type() const { return DE_STEIM1; }
};
}
}
#include "steim1.ipp"
#endif // __STEIM1_H__

View File

@ -0,0 +1,184 @@
/*****************************************************************************
* steim1.cc
*
* Steim1 encoder
*
* (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 <netinet/in.h>
#include <iostream>
#include <iomanip>
#include <algorithm>
namespace Gempa {
namespace CAPS {
template<typename T> Steim1Encoder<T>::~Steim1Encoder() {
if ( format != NULL ) delete format;
}
template<typename T> void Steim1Encoder<T>::update_spw(int bp) {
int spw1 = 4;
assert(bp < 4);
if(buf[bp] < -32768 || buf[bp] > 32767) spw1 = 1;
else if(buf[bp] < -128 || buf[bp] > 127) spw1 = 2;
if(spw1 < spw) spw = spw1;
}
template<typename T> void Steim1Encoder<T>::store(int32_t value) {
assert(bp < 4);
buf[bp] = value - last_sample;
last_sample = value;
update_spw(bp);
++bp;
}
template<typename T> void Steim1Encoder<T>::init_packet() {
int i;
int32_t begin_sample = last_sample;
for(i = 1; i < bp; ++i) {
begin_sample -= buf[i];
}
reset();
current_packet.data[0].sample_word[0] = htonl(begin_sample);
frame_count = 0;
nibble_word = 0;
fp = 2;
}
template<typename T> void Steim1Encoder<T>::finish_packet() {
int i;
int32_t end_sample = last_sample;
for(i = 0; i < bp; ++i) {
end_sample -= buf[i];
}
current_packet.data[0].sample_word[1] = htonl(end_sample);
}
template<typename T> void Steim1Encoder<T>::update_packet() {
unsigned int nibble = 0;
u_int32_t sample_word = 0;
assert(bp < 5);
int used = bp;
while(used > spw) {
--used;
spw = 4;
for(int i = 0; i < used; ++i) update_spw(i);
}
while(used < spw) spw >>= 1;
used = spw;
switch(spw) {
case 4:
nibble = 1;
sample_word = ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) |
((buf[2] & 0xff) << 8) | (buf[3] & 0xff);
break;
case 2:
nibble = 2;
sample_word = ((buf[0] & 0xffff) << 16) | (buf[1] & 0xffff);
break;
case 1:
nibble = 3;
sample_word = buf[0];
break;
default:
assert(0);
}
nibble_word |= (nibble << (30 - ((fp + 1) << 1)));
spw = 4;
for(int i = 0; i < bp - used; ++i) {
buf[i] = buf[i + used];
update_spw(i);
}
bp -= used;
_sampleCount += used;
current_packet.data[frame_count].nibble_word = htonl(nibble_word);
current_packet.data[frame_count].sample_word[fp] = htonl(sample_word);
if(++fp < 15) return;
nibble_word = 0;
fp = 0;
++frame_count;
return;
}
template<typename T> void Steim1Encoder<T>::queue_packet(MSEEDEncoderPacket<Steim1Frame> &pckt) {
format->updateBuffer(pckt.record, _sampleCount, frame_count + (fp > 0));
Packet *packet = new Packet(DataRecordPtr(pckt.record), format->networkCode, format->stationCode,
format->locationCode, format->channelCode);
_packetQueue.push_back(PacketPtr(packet));
pckt.reset();
reset();
}
template<typename T> void Steim1Encoder<T>::push(void *value) {
int32_t sample_val = *static_cast<T*>(value);
store(sample_val);
_clk.tick();
while(bp >= spw) {
if(!current_packet.valid()) {
current_packet = get_packet();
init_packet();
}
update_packet();
if(frame_count == number_of_frames(current_packet)) {
finish_packet();
queue_packet(current_packet);
}
}
}
template<typename T> void Steim1Encoder<T>::flush() {
while(bp) {
if(!current_packet.valid()) {
current_packet = get_packet();
init_packet();
}
update_packet();
if(frame_count == number_of_frames(current_packet)) {
finish_packet();
queue_packet(current_packet);
}
}
if(current_packet.valid()) {
finish_packet();
queue_packet(current_packet);
}
}
}
}

View File

@ -0,0 +1,94 @@
/*****************************************************************************
* steim2.h
*
* Steim2 encoder
*
* (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)
*****************************************************************************/
#ifndef CAPS_MSEED_STEIM2_H
#define CAPS_MSEED_STEIM2_H
#include "encoder.h"
#include "mseed.h"
namespace Gempa {
namespace CAPS {
//*****************************************************************************
// Steim2Frame
//*****************************************************************************
struct Steim2Frame {
u_int32_t nibble_word;
u_int32_t sample_word[15];
};
//*****************************************************************************
// Steim2Encoder
//*****************************************************************************
template<typename T>
class Steim2Encoder : public Encoder {
public:
Steim2Encoder(MSEEDFormat *format, int freqn, int freqd)
: Encoder(freqn, freqd), format(format), frame_count(0),
bp(0), fp(0), spw(4), last_sample(0), nibble_word(0) {
}
virtual ~Steim2Encoder();
virtual void flush();
virtual void push(void *value);
virtual int type() const { return DE_STEIM2; }
private:
void update_spw(int bp);
void store(int32_t value);
void init_packet();
void finish_packet();
void update_packet();
MSEEDEncoderPacket<Steim2Frame> get_packet() {
return format->get_packet<Steim2Frame>(_clk.get_time(bp),
_clk.correction(), _timingQuality);
}
void queue_packet(MSEEDEncoderPacket<Steim2Frame> &pckt);
int number_of_frames(const MSEEDEncoderPacket<Steim2Frame> &packet) {
return (packet.datalen >> 6);
}
private:
MSEEDFormat *format;
int frame_count;
int bp;
int fp;
int32_t last_s;
int spw;
int32_t last_sample;
int32_t buf[8];
u_int32_t nibble_word;
MSEEDEncoderPacket<Steim2Frame> current_packet;
};
}
}
#include "steim2.ipp"
#endif // __STEIM2_H__

View File

@ -0,0 +1,241 @@
/*****************************************************************************
* steim2.cc
*
* Steim2 encoder
*
* (c) 2004 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 "../log.h"
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <assert.h>
#include <netinet/in.h>
namespace Gempa {
namespace CAPS {
template<typename T> Steim2Encoder<T>::~Steim2Encoder() {
if ( format != NULL ) delete format;
}
template<typename T> void Steim2Encoder<T>::update_spw(int bp) {
assert(bp < 7);
if(buf[bp] < -536870912) {
CAPS_WARNING("%s.%s.%s.%s: value %d is too large for Steim2 encoding",
format->networkCode.c_str(), format->stationCode.c_str(),
format->locationCode.c_str(), format->channelCode.c_str(),
buf[bp]);
buf[bp] = -536870912;
spw = 1;
return;
}
if(buf[bp] > 536870911) {
CAPS_WARNING("%s.%s.%s.%s: value %d is too large for Steim2 encoding",
format->networkCode.c_str(), format->stationCode.c_str(),
format->locationCode.c_str(), format->channelCode.c_str(),
buf[bp]);
buf[bp] = 536870911;
spw = 1;
return;
}
int spw1 = 7;
if(buf[bp] < -16384 || buf[bp] > 16383) spw1 = 1;
else if(buf[bp] < -512 || buf[bp] > 511) spw1 = 2;
else if(buf[bp] < -128 || buf[bp] > 127) spw1 = 3;
else if(buf[bp] < -32 || buf[bp] > 31) spw1 = 4;
else if(buf[bp] < -16 || buf[bp] > 15) spw1 = 5;
else if(buf[bp] < -8 || buf[bp] > 7) spw1 = 6;
if(spw1 < spw) spw = spw1;
}
template<typename T> void Steim2Encoder<T>::store(int32_t value) {
assert(bp < 7);
buf[bp] = value - last_sample;
last_sample = value;
update_spw(bp);
++bp;
}
template<typename T> void Steim2Encoder<T>::init_packet() {
int i;
int32_t begin_sample = last_sample;
for(i = 1; i < bp; ++i) {
begin_sample -= buf[i];
}
reset();
current_packet.data[0].sample_word[0] = htonl(begin_sample);
frame_count = 0;
nibble_word = 0;
fp = 2;
}
template<typename T> void Steim2Encoder<T>::finish_packet() {
int i;
int32_t end_sample = last_sample;
for(i = 0; i < bp; ++i) {
end_sample -= buf[i];
}
current_packet.data[0].sample_word[1] = htonl(end_sample);
}
template<typename T> void Steim2Encoder<T>::update_packet() {
unsigned int nibble = 0;
u_int32_t sample_word = 0;
assert(bp < 8);
int used = bp;
while(used > spw) {
--used;
spw = 7;
for(int i = 0; i < used; ++i) update_spw(i);
}
spw = used;
switch(spw) {
case 7:
nibble = 3;
sample_word = (2U << 30) | ((buf[0] & 0xf) << 24) |
((buf[1] & 0xf) << 20) | ((buf[2] & 0xf) << 16) |
((buf[3] & 0xf) << 12) | ((buf[4] & 0xf) << 8) |
((buf[5] & 0xf) << 4) | (buf[6] & 0xf);
break;
case 6:
nibble = 3;
sample_word = (1U << 30) | ((buf[0] & 0x1f) << 25) |
((buf[1] & 0x1f) << 20) | ((buf[2] & 0x1f) << 15) |
((buf[3] & 0x1f) << 10) | ((buf[4] & 0x1f) << 5) |
(buf[5] & 0x1f);
break;
case 5:
nibble = 3;
sample_word = ((buf[0] & 0x3f) << 24) | ((buf[1] & 0x3f) << 18) |
((buf[2] & 0x3f) << 12) | ((buf[3] & 0x3f) << 6) |
(buf[4] & 0x3f);
break;
case 4:
nibble = 1;
sample_word = ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) |
((buf[2] & 0xff) << 8) | (buf[3] & 0xff);
break;
case 3:
nibble = 2;
sample_word = (3U << 30) | ((buf[0] & 0x3ff) << 20) |
((buf[1] & 0x3ff) << 10) | (buf[2] & 0x3ff);
break;
case 2:
nibble = 2;
sample_word = (2U << 30) | ((buf[0] & 0x7fff) << 15) |
(buf[1] & 0x7fff);
break;
case 1:
nibble = 2;
sample_word = (1U << 30) | (buf[0] & 0x3fffffff);
break;
default:
assert(0);
break;
}
nibble_word |= (nibble << (30 - ((fp + 1) << 1)));
spw = 7;
for(int i = 0; i < bp - used; ++i) {
buf[i] = buf[i + used];
update_spw(i);
}
bp -= used;
_sampleCount += used;
current_packet.data[frame_count].nibble_word = htonl(nibble_word);
current_packet.data[frame_count].sample_word[fp] = htonl(sample_word);
if(++fp < 15) return;
nibble_word = 0;
fp = 0;
++frame_count;
return;
}
template<typename T> void Steim2Encoder<T>::queue_packet(MSEEDEncoderPacket<Steim2Frame> &pckt) {
format->updateBuffer(pckt.record, _sampleCount, frame_count + (fp > 0));
Packet *packet = new Packet(DataRecordPtr(pckt.record), format->networkCode, format->stationCode,
format->locationCode, format->channelCode);
_packetQueue.push_back(PacketPtr(packet));
pckt.reset();
reset();
}
template<typename T> void Steim2Encoder<T>::push(void *value) {
int32_t sample_val = *static_cast<T*>(value);
store(sample_val);
_clk.tick();
while ( bp >= spw ) {
if( !current_packet.valid() ) {
current_packet = get_packet();
init_packet();
}
update_packet();
if ( frame_count == number_of_frames(current_packet) ) {
finish_packet();
queue_packet(current_packet);
}
}
}
template<typename T> void Steim2Encoder<T>::flush() {
while ( bp ) {
if ( !current_packet.valid() ) {
current_packet = get_packet();
init_packet();
}
update_packet();
if( frame_count == number_of_frames(current_packet) ) {
finish_packet();
queue_packet(current_packet);
}
}
if ( current_packet.valid() ) {
finish_packet();
queue_packet(current_packet);
}
}
}
}

View File

@ -0,0 +1,84 @@
/***************************************************************************
* Copyright (C) 2013 by gempa GmbH *
* *
* All Rights Reserved. *
* *
* NOTICE: All information contained herein is, and remains *
* the property of gempa GmbH and its suppliers, if any. The intellectual *
* and technical concepts contained herein are proprietary to gempa GmbH *
* and its suppliers. *
* Dissemination of this information or reproduction of this material *
* is strictly forbidden unless prior written permission is obtained *
* from gempa GmbH. *
***************************************************************************/
#ifndef CAPS_MSEED_UNCOMPRESSED_H
#define CAPS_MSEED_UNCOMPRESSED_H
#include "encoder.h"
#include "mseed.h"
#include <gempa/caps/endianess.h>
#include <iostream>
#include <netinet/in.h>
namespace Gempa {
namespace CAPS {
template<typename T> class UncompressedMSEED : public Encoder {
MSEEDEncoderPacket<T> get_packet() {
return _format->get_packet<T>(_clk.get_time(-_bp),
_clk.correction(), _timingQuality);
}
void queue_packet(MSEEDEncoderPacket<T> &pckt) {
_format->updateBuffer(pckt.record, _sampleCount, 1);
Packet *packet = new Packet(DataRecordPtr(pckt.record), _format->networkCode, _format->stationCode,
_format->locationCode, _format->channelCode);
_packetQueue.push_back(PacketPtr(packet));
pckt.reset();
reset();
}
public:
UncompressedMSEED(MSEEDFormat *format, int freqn, int freqd)
: Encoder(freqn, freqd),
_format(format), _bp(0) {
}
virtual ~UncompressedMSEED() { if ( _format ) delete _format; }
virtual void flush() {
if ( _current_packet.valid() ) {
queue_packet(_current_packet);
}
}
virtual void push(void *value) {
if ( !_current_packet.valid() )
_current_packet = get_packet();
else if ( _sampleCount * sizeof(T) >= _current_packet.datalen ) {
flush();
_current_packet = get_packet();
}
_current_packet.data[_sampleCount] =
Gempa::CAPS::Endianess::Converter::ToBigEndian<T>(*(T*)value);
++_sampleCount;
++_bp;
}
virtual int type() const { return _format->packType; }
private:
MSEEDFormat *_format;
MSEEDEncoderPacket<T> _current_packet;
int _bp;
};
}
}
#endif // __STEIM1_H__