source: trunk/src/libsrc/util/psn4putaway.c @ 5054

Revision 5054, 25.3 KB checked in by cochrane, 7 years ago (diff)

Fixed a problem with saving more then one PSN Event file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* PSN4PutAway.c - Save data to PSN Type 4 Event Files
2   Created Dec 14 2005 by Larry Cochrane, Redwood City, PSN
3   Updated July 8 2006 - Replaced TRACE_HEADER with TRACE2_HEADER
4   Updated Jan 26 2012 - Fixed problem with saving more then one file
5 */
6
7/************************************/
8/** #includes                      **/
9/************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <errno.h>
14#include <earthworm.h>
15#include <time.h>
16#include <trace_buf.h>
17#include <swap.h>
18#include <pa_subs.h>
19#include <time_ew.h>
20#include <math.h>
21
22#ifndef WIN32
23#define WORD unsigned short
24#define BYTE unsigned char
25#define UINT unsigned int                       // needs to be 4 bytes
26#endif
27
28#include <psn4putaway.h>
29
30static char *DataloggerString = "Earthworm 7.x";
31
32static PSNType4 PsnHeader;              /* header that get saves to disk */
33static long *BufferLong = 0;    /* buffer for storing output before writing */
34static short *BufferShort = 0;  /* write out data as short integers */
35static float *BufferFloat = 0;  /* write out data as float */
36static char FileNameRoot[256];          /* holds the file name we will be using */
37static char SaveDir[256];               /* holds the directory we will be using */
38static int GoodData = 0;                /* used to check for deleting empty file */
39static char StaLocation[256];   /* station location string */
40static char SensorInfo[256];    /* sensor info string */
41static ChannelInfo ChanInfo;    /* holds additional info about the channel */
42
43static void MakeHdrTime( DateTime *, double );
44static void ReadStationFile( char *scnl, PSNType4 *hdr, int debug  );
45static void ParseLine( char *, char *, char * );
46static char *SkipSpace( char *string );
47static int Strib( char *string );
48static void SwapPsnHeader( PSNType4 * );
49static void SwapPsnVarHeader( VarHeader * );
50static void SwapChanInfo( ChannelInfo *);
51static WORD CalcFileCRC( FILE *fp, int length );
52static void CalcCRC16(WORD *crc, BYTE *cp, int cnt);
53
54/* Initialization function,
55*       This is the Put Away startup intializer. This is called when    *
56*       the system first comes up. Here is a chance to look around      *
57*       and see if it's possible to do business, and to complain        *
58*       if not ,BEFORE an event has to be processed.                    *
59*/
60int PSN4PA_init( long OutBufferLen, char *OutDir, char *OutputFormat, int debug )
61{
62        int len;
63
64        if( ( BufferLong = (long *)malloc( OutBufferLen * sizeof (char) ) ) == NULL )  {
65                logit ("et", "PSN4PA_init: couldn't malloc BufferLong\n");
66                return EW_FAILURE;
67        }
68        if( ( BufferFloat = (float *)malloc( OutBufferLen * sizeof (char) ) ) == NULL )  {
69                logit ("et", "PSN4PA_init: couldn't malloc BufferLong\n");
70                return EW_FAILURE;
71        }
72        if( ( BufferShort = (short *)malloc( OutBufferLen * sizeof (char) ) ) == NULL )  {
73                logit ("et", "PSN4PA_init: couldn't malloc BufferShort\n");
74                return EW_FAILURE;
75        }
76
77        strcpy( SaveDir, OutDir );
78
79        /* remove trailing '\' char in the directory string */
80        len = strlen( SaveDir );
81        if( len > 2 && ( SaveDir[len-1] == '\\' ||  SaveDir[len-1] == '/' ) )
82                SaveDir[len-1] = 0;
83
84        /* Make sure that the top level output directory exists */
85        CreateDir( SaveDir );
86
87        return EW_SUCCESS;
88}
89
90/****************************************************************************
91* This is the Put Away event initializer. It's called when a snippet        *
92* has been received, and is about to be processed.                                                      *
93* It gets to see the pointer to the TraceRequest array,                                         *
94* and the number of loaded trace structures.                                                            *
95*****************************************************************************/
96int PSN4PA_next_ev( TRACE_REQ *ptrReq, char *EventDate, char *EventTime, int debug )
97{
98        char toDir[ 256 ];
99       
100        sprintf( toDir, "%s\\%-4.4s", SaveDir, &EventDate[2] );
101        CreateDir( toDir );
102
103        sprintf( FileNameRoot, "%s\\%-6.6s.%-6.6s", toDir, &EventDate[2], EventTime );
104               
105        if( debug )
106                logit ("t", "PSN 4 Root File Name %s\n", FileNameRoot );
107
108        GoodData = 0;
109        return(EW_SUCCESS);
110}
111
112/*****************************************************************************
113 * This is the working entry point into the disposal system. This routine        *
114 * gets called for each trace snippet which has been recovered. It gets          *
115 * to see the corresponding SNIPPET structure, and the event id                          *
116 *****************************************************************************/
117/* Process one channel of data */
118int PSN4PA_next( TRACE_REQ *getThis, double GapThresh, long OutBufferLen, int debug)
119{
120        TRACE2_HEADER *wf;
121        PSNType4 *hdr = &PsnHeader;
122        short *s_data, s;
123        long *l_data, l;
124        float *f_data, f;
125        char *msg_p;                            /* pointer into tracebuf data */
126        char datatype;
127        int qual, j, data_size;
128        int gap_count = 0;
129        long nsamp, nfill;
130        long nfill_max = 0l;
131        long nsamp_this_scnl = 0l;
132        long this_size;
133        double begintime, starttime, endtime;
134        double samprate;
135        long fill = 0l;
136        char scnl[80], fname[ 256 ];
137        double min, max, mean;
138        int len, varLen, crcLen;
139        VarHeader varHdr;
140        int swap = FALSE;
141        WORD crc;
142        FILE *psnFile = 0;              /* file pointer used to write out event file */
143
144#if defined (_SPARC)
145        swap = TRUE;
146#endif
147
148        /* Check arguments */
149        if( getThis == NULL )  {
150                logit ("et", "PSN4PA_next: invalid argument passed in.\n");
151                return EW_FAILURE;
152        }
153
154        memset( hdr, 0, sizeof( PSNType4 ) );
155
156        if( (msg_p = getThis->pBuf) == NULL )  {         /* pointer to first message */
157                logit ("et", "PSN4PA_next: Message buffer is NULL.\n");
158                return EW_FAILURE;
159        }
160        wf = (TRACE2_HEADER *)msg_p;
161
162        if( !strncmp( wf->loc, "--", 2 ) || !strncmp( wf->loc, "NC", 2 ) )
163                sprintf( fname, "%s.%s.%s.%s.PSN", FileNameRoot, wf->sta, wf->chan, wf->net );
164        else
165                sprintf( fname, "%s.%s.%s.%s.%s.PSN", FileNameRoot, wf->sta, wf->chan, wf->net, wf->loc );
166        if( debug == 1 )
167                logit ("t", "Opening PSN Type 4 file %s\n", fname );
168
169        if( ! ( psnFile = fopen( fname, "w+b" ) ) )  {
170                logit ("et", "PSN4PA_init: couldn't open output file %s\n", fname );
171                return EW_FAILURE;
172        }
173       
174        /* Look at the first TRACE2_HEADER and get set up of action */
175        if (WaveMsg2MakeLocal(wf) < 0)  {
176                logit("et", "PSN4PA_next: unknown trace data type: %s\n", wf->datatype);
177                fclose( psnFile );
178                return( EW_FAILURE );
179        }
180        nsamp = wf->nsamp;
181        starttime = wf->starttime;
182        endtime = wf->endtime;
183        samprate = wf->samprate;
184        if (samprate < 0.01 ) {
185                logit("et", "unreasonable sample rate (%f) for <%s.%s.%s>\n", samprate,
186                        wf->sta, wf->chan, wf->net);
187                fclose( psnFile );
188                return( EW_FAILURE );
189        }
190        begintime = starttime;
191        datatype = 'n';
192        if( wf->datatype[0] == 's' || wf->datatype[0] == 'i' )  {
193                if(wf->datatype[1] == '2')
194                        datatype = 's';
195                else if(wf->datatype[1] == '4')
196                        datatype = 'l';
197        }
198        else if( wf->datatype[0] == 't' || wf->datatype[0] == 'f' && wf->datatype[1] == '4' )
199                datatype = 'f';
200
201        if (datatype == 'n')  {
202                logit("et", "PSN4PA_next: unsupported datatype: %s\n", datatype);
203                fclose( psnFile );
204                return( EW_FAILURE );
205        }
206
207        if (debug == 1)
208                logit("et", "PSN4PA_next: working on <%s/%s/%s> datatype: %c\n",
209                        wf->sta, wf->chan, wf->net, datatype );
210
211        min = 999999999.0;
212        max = -999999999.0;
213        mean = 0.0;
214
215        /* loop through all the messages for this s-c-n */
216        while (1) {
217                /* advance message pointer to the data */
218                msg_p += sizeof(TRACE2_HEADER);
219
220                /* check for sufficient memory in output buffer */
221                this_size = (nsamp_this_scnl + nsamp ) * sizeof(long);
222                if ( OutBufferLen < this_size )  {
223                        logit( "et", "out of space for <%s.%s.%s>; saving long trace.\n",
224                                 wf->sta, wf->chan, wf->net);
225                        break;
226                }
227
228                switch( datatype )
229                {
230                case 's':
231                        s_data = (short *)msg_p;
232                        for ( j = 0; j < nsamp ; j++, nsamp_this_scnl++ )  {
233                                s = s_data[j];
234                                if( s > max )
235                                        max = s;
236                                if( s < min )
237                                        min = s;
238                                mean += s;
239                                BufferLong[nsamp_this_scnl] = (long)s;
240                        }
241                        msg_p += sizeof(short) * nsamp;
242                        break;
243                case 'l':
244                        l_data = (long *)msg_p;
245                        for ( j = 0; j < nsamp; j++, nsamp_this_scnl++ )  {
246                                l = l_data[j];
247                                if( l > max )
248                                        max = l;
249                                if( l < min )
250                                        min = l;
251                                BufferLong[nsamp_this_scnl] = l;
252                        }
253                        msg_p += sizeof(long) * nsamp;
254                        break;
255                case 'f':
256                        f_data = (float *)msg_p;
257                        for ( j = 0; j < nsamp; j++, nsamp_this_scnl++ )  {
258                                f = f_data[j];
259                                if( f > max )
260                                        max = f;
261                                if( f < min )
262                                        min = f;
263                                BufferFloat[nsamp_this_scnl] = f;
264                        }
265                        msg_p += sizeof(float) * nsamp;
266                        break;
267                }
268
269                /* End-check based on length of snippet buffer */
270                if ((long) msg_p >= ((long) getThis->actLen + (long) getThis->pBuf) )  {
271                        if (debug == 1)
272                                logit ("", "Setting done for <%s.%s.%s>\n", wf->sta, wf->chan, wf->net);
273                        break; /* Break out of the while(1) loop 'cuz we're done */
274                }
275
276                /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
277                 * and check for gaps.  */
278                wf = (TRACE2_HEADER *) msg_p;
279                if (WaveMsg2MakeLocal(wf) < 0)  {
280                        logit("et", "PSN4PA_next: unknown trace data type: %s\n",
281                                                wf->datatype);
282                        fclose( psnFile );
283                        return( EW_FAILURE );
284                }
285                qual = wf->quality[0];          // Get time reference quality
286                nsamp = wf->nsamp;
287                starttime = wf->starttime;
288                /* starttime is set for new packet; endtime is still set for old packet */
289                if ( endtime + ( 1.0/samprate ) * GapThresh < starttime ) {
290                        /* there's a gap, so fill it */
291                        logit("et", "gap in %s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
292                                                endtime, starttime - endtime);
293                        nfill = (long) (samprate * (starttime - endtime) - 1);
294                        if ( (nsamp_this_scnl + nfill) * (long)sizeof(long) > OutBufferLen ) {
295                                logit("et", "bogus gap (%d); skipping\n", nfill);
296                                fclose( psnFile );
297                                return(EW_FAILURE);
298                        }
299                        /* do the filling */
300                        for ( j = 0; j < nfill; j++, nsamp_this_scnl ++ )
301                                BufferLong[nsamp_this_scnl] = fill;
302                        /* keep track of how many gaps and the largest one */
303                        gap_count++;
304                        if (nfill_max < nfill)
305                                nfill_max = nfill;
306                }
307                /* Advance endtime to the new packet;                           *
308                 * process this packet in the next iteration */
309                endtime = wf->endtime;
310        } /* while(1) */
311
312        if ( datatype == 's' )  {
313                for (j = 0; j < nsamp_this_scnl; j++)
314                        BufferShort[j] = (short)BufferLong[j];
315        }
316
317        /* now make the PSN header */
318        memcpy(hdr->headerID, "PSNTYPE4", 8);
319
320        /* Make the SCN test string and then try and find it in the station.lst file */
321        sprintf(scnl, "%s.%s.%s.%s", wf->sta, wf->chan, wf->net, wf->loc );
322        ReadStationFile( scnl, hdr, debug );
323
324        /* set the time of the first sample of data */
325        MakeHdrTime( &hdr->startTime, begintime );
326
327        /* calculate the size of the variable header section of the event file */
328        varLen = 0;
329        if( len = strlen( StaLocation) )
330                varLen += ( len + 1 + sizeof( VarHeader) );
331        if( len = strlen( SensorInfo) )
332                varLen += ( len + 1 + sizeof( VarHeader) );
333        if( ChanInfo.sensorOutVolt != 0.0 || ChanInfo.ampGain != 0.0 ||
334                        ChanInfo.adcInputVolt != 0.0 )
335                varLen += ( sizeof( ChannelInfo ) + sizeof( VarHeader ) );
336        if( len = strlen( DataloggerString ) )
337                varLen += ( len + 1 + sizeof( VarHeader) );
338        hdr->variableHdrLength = varLen;
339        hdr->sampleCount = nsamp_this_scnl;
340        hdr->spsRate = wf->samprate;
341        hdr->maximum = max;
342        hdr->minimum = min;
343        hdr->mean = mean / (double)nsamp_this_scnl;
344        if( ! (qual & TIME_TAG_QUESTIONABLE) )
345                hdr->timeRefStatus = 'L';
346        if( datatype == 's' )
347                hdr->sampleType = 0;
348        else if( datatype == 'l' )
349                hdr->sampleType = 1;
350        else
351                hdr->sampleType = 2;
352
353        if( strlen( wf->sta ) >= 6)
354                strncpy(hdr->name, wf->sta, 6 );
355        else
356                strcpy(hdr->name, wf->sta );
357
358        if( strlen( wf->chan ) >= 3 )
359                strncpy(hdr->compName, wf->chan, 3 );
360        else
361                strcpy(hdr->compName, wf->chan );
362
363        if( strlen( wf->net ) >= 6 )
364                strncpy(hdr->network, wf->net, 6);
365        else
366                strcpy( hdr->network, wf->net );
367
368        if( datatype == 's' )
369                data_size = nsamp_this_scnl * sizeof(short);
370        else if( datatype == 'l')
371                data_size = nsamp_this_scnl * sizeof(long);
372        else
373                data_size = nsamp_this_scnl * sizeof(float);
374
375        crcLen = sizeof( PSNType4 ) + hdr->variableHdrLength + data_size;
376
377        if( swap )
378                SwapPsnHeader( hdr );
379
380        /* now write the main header */
381        if( fwrite( (void *)hdr, 1, sizeof(PSNType4), psnFile ) != sizeof(PSNType4) )  {
382                logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
383                fclose( psnFile );
384                return EW_FAILURE;
385        }
386
387        /* now save any variable header blocks */
388        if( len = strlen( StaLocation ) )  {
389                ++len;
390                varHdr.checkNumber = 0x55;
391                varHdr.id = 1;
392                varHdr.length = len;
393                if( swap )
394                        SwapPsnVarHeader( &varHdr );
395                if(fwrite(&varHdr, 1, sizeof(VarHeader), psnFile ) != (UINT)sizeof(VarHeader) )  {
396                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
397                        fclose( psnFile );
398                        return EW_FAILURE;
399                }
400                if(fwrite( StaLocation, 1, len, psnFile ) != (UINT)len )  {
401                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
402                        fclose( psnFile );
403                        return EW_FAILURE;
404                }
405        }
406
407        if( len = strlen( SensorInfo ) )  {
408                ++len;
409                varHdr.checkNumber = 0x55;
410                varHdr.id = 2;
411                varHdr.length = len;
412                if( swap )
413                        SwapPsnVarHeader( &varHdr );
414                if(fwrite(&varHdr, 1, sizeof(VarHeader), psnFile ) != (UINT)sizeof(VarHeader) )  {
415                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
416                        fclose( psnFile );
417                        return EW_FAILURE;
418                }
419                if( fwrite( SensorInfo, 1, len, psnFile ) != (UINT)len )  {
420                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
421                        fclose( psnFile );
422                        return EW_FAILURE;
423                }
424        }
425
426        if( len = strlen( DataloggerString ) )  {
427                ++len;
428                varHdr.checkNumber = 0x55;
429                varHdr.id = 7;
430                varHdr.length = len;
431                if( swap )
432                        SwapPsnVarHeader( &varHdr );
433                if(fwrite(&varHdr, 1, sizeof(VarHeader), psnFile ) != (UINT)sizeof(VarHeader) )  {
434                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
435                        fclose( psnFile );
436                        return EW_FAILURE;
437                }
438                if( fwrite( DataloggerString, 1, len, psnFile ) != (UINT)len )  {
439                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
440                        fclose( psnFile );
441                        return EW_FAILURE;
442                }
443        }
444
445        if( ChanInfo.sensorOutVolt != 0.0 || ChanInfo.ampGain != 0.0 ||
446                                ChanInfo.adcInputVolt != 0.0 )  {
447                varHdr.checkNumber = 0x55;
448                varHdr.id = 11;
449                varHdr.length = sizeof( ChannelInfo );
450                if( swap )
451                        SwapPsnVarHeader( &varHdr );
452                if(fwrite(&varHdr, 1, sizeof(VarHeader), psnFile ) != sizeof( VarHeader ) )  {
453                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
454                        fclose( psnFile );
455                        return EW_FAILURE;
456                }
457                if( swap )
458                        SwapChanInfo( &ChanInfo );
459
460                if( fwrite( &ChanInfo, 1, sizeof( ChannelInfo ), psnFile ) != sizeof( ChannelInfo ) )  {
461                        logit ("et", "PSN4PA_next: error writing PSN4 Header. \n");
462                        fclose( psnFile );
463                        return EW_FAILURE;
464                }
465        }
466
467        /* Convert to the appropriate output format */
468        if( swap )  {
469                /* we are on sparc, data will be read on intel */
470                for (j = 0; j < nsamp_this_scnl; j++)  {
471                        if(datatype == 's' )
472                                SwapShort( &BufferShort[j] );
473                        else if( datatype == 'l' )
474                                SwapLong( &BufferLong[j] );
475                        else if( datatype == 'f' )
476                                SwapFloat( &BufferFloat[j] );
477                }
478        }
479
480        if (debug == 1 )
481            logit ("", "Writing %d bytes of trace data\n", data_size );
482
483        if( datatype == 's' )  {
484                if ((long)fwrite ((void *) BufferShort, sizeof (char), data_size, psnFile ) !=
485                                data_size )  {
486                        logit ("et", "PSN4PA_next: error writing short TRACE data. \n");
487                        fclose( psnFile );
488                        return EW_FAILURE;
489                }
490        }
491        else if( datatype == 'l' ) {
492                if( (long)fwrite ((void *) BufferLong, sizeof (char), data_size, psnFile ) !=
493                                data_size )  {
494                        logit ("et", "PSN4PA_next: error writing long TRACE data. \n");
495                        fclose( psnFile );
496                        return EW_FAILURE;
497                }
498        }
499        else  {         // write out float data
500                if( (long)fwrite ((void *) BufferFloat, sizeof (char), data_size, psnFile ) !=
501                                data_size )  {
502                        logit ("et", "PSN4PA_next: error writing long TRACE data. \n");
503                        fclose( psnFile );
504                        return EW_FAILURE;
505                }
506        }
507
508        crc = CalcFileCRC( psnFile, crcLen );
509        if( swap )
510                SwapShort( &crc );
511        if( fwrite(&crc, 1, sizeof(short), psnFile ) != sizeof(short))
512                logit ("et", "PSN4PA_next: error writing crc. \n");
513        GoodData = TRUE;
514        fclose( psnFile );
515        return EW_SUCCESS;
516}
517
518/************************************************************************
519* This is the Put Away end event routine. It's called after we've               *
520* finished processing one event.                                                                                *
521*************************************************************************/
522int PSN4PA_end_ev(int debug)
523{
524        return(EW_SUCCESS);
525}
526
527
528/************************************************************************
529* This is the Put Away close routine. It's called after when            *
530* we're being shut down.                                                                                    *
531*************************************************************************/
532int PSN4PA_close(int debug)
533{
534        if( BufferLong )
535                free( (char *)BufferLong );
536        if( BufferShort )
537                free( (char *)BufferShort );
538        if( BufferFloat )
539                free( (char *)BufferFloat );
540
541        return(EW_SUCCESS);
542}
543
544/* Make a PSN Type 4 header time based on the start time  */
545static void MakeHdrTime( DateTime *ti, double startTime )
546{
547        struct tm *tme;
548        time_t ltime = (time_t)startTime;
549        double frac, secs;
550
551        /* gmt time makes months from 0 - 11 */
552        tme = gmtime( &ltime );
553        ti->year = (WORD)tme->tm_year + 1900;
554        ti->month = (char)(tme->tm_mon + 1);
555        ti->day = (char)tme->tm_mday;
556        ti->hour = (char)tme->tm_hour;
557        ti->minute = (char)tme->tm_min;
558        ti->second = (char)tme->tm_sec;
559        frac = modf( startTime, &secs );
560        ti->nanoseconds = (int)( frac * 1000000000 );
561}
562
563/* Read the station.lst file. This file is currently located
564   in the directory defined by the system variable "EW_PARAMS" */
565static void ReadStationFile( char *scnl, PSNType4 *hdr, int debug  )
566{
567        char *dir = getenv( "EW_PARAMS" ), buff[256], fname[256];
568        char scnlSearch[64], key[256], data[256], *ptr;
569        int found = 0;
570        FILE *fp;
571
572        StaLocation[0] = SensorInfo[0] = 0;
573        ChanInfo.sensorOutVolt = ChanInfo.ampGain = ChanInfo.adcInputVolt = 0;
574
575        if( debug )
576                logit("t", "Start ReadStationFile - Looking for %s\n", scnl );
577
578        if( !dir )  {
579                if( debug == 1 )
580                        logit("et", "Environment variable EW_PARAMS not found\n");
581                return;
582        }
583
584        /* Make the file name and try and open the file */
585        sprintf(fname, "%s\\station.lst", dir );
586        if( ! (fp = fopen( fname, "r" ) ) )  {
587                if( debug == 1 )
588                        logit("et", "Station information file %s not found\n", fname );
589                return;
590        }
591
592        /* Make the search string and then look for the SCNL in the file */
593        sprintf( scnlSearch, "[%s]", scnl );
594        while( fgets( buff, 256, fp ) )   {
595                if( buff[0] == '#' || buff[0] == ';' || buff[0] == '!' )
596                        continue;
597                Strib( buff );
598                ptr = SkipSpace( buff );
599                if( strcmp( scnlSearch, ptr ) )
600                        continue;
601                found = TRUE;
602                break;
603        }
604        if( !found )  {
605                fclose( fp );
606                if( debug )
607                        logit("et", "Station information not found\n" );
608                return;
609        }
610
611        if( debug )
612                logit("et", "Station information found\n" );
613
614        /* We found the SCNL so now get the key=data pairs from the file */
615        while( fgets( buff, 256, fp ) )  {
616                if( buff[0] == '#' || buff[0] == ';' || buff[0] == '!' )        // comment
617                        continue;
618                Strib( buff );
619                ptr = SkipSpace( buff );
620                if( ptr[0] == '[' )                             // if next SCNL we are done.
621                        break;
622
623                ParseLine( key, data, ptr );    // get key and data
624
625                if( !strcmp( key, "latitude" ) )  {
626                        hdr->latitude = atof( data );
627                        continue;
628                }
629                if( !strcmp( key, "longitude" ) )  {
630                        hdr->longitude = atof( data );
631                        continue;
632                }
633                if( !strcmp( key, "elevation" ) )  {
634                        hdr->elevation = atof( data );
635                        continue;
636                }
637                if( !strcmp( key, "orientation" ) )  {
638                        hdr->compOrientation = data[0];
639                        continue;
640                }
641                if( !strcmp( key, "incident" ) )  {
642                        hdr->compIncident = atof( data );
643                        continue;
644                }
645                if( !strcmp( key, "azimuth" ) )  {
646                        hdr->compAzimuth = atof( data );
647                        continue;
648                }
649                if( !strcmp( key, "sensortype" ) )  {
650                        if( data[0] == 'A' )
651                                hdr->sensorType = 1;
652                        else if( data[0] == 'V' )
653                                hdr->sensorType = 2;
654                        else if( data[0] == 'D' )
655                                hdr->sensorType = 3;
656                        continue;
657                }
658                if( !strcmp( key, "sensitivity" ) )  {
659                        hdr->sensitivity = atof( data );
660                        continue;
661                }
662                if( !strcmp( key, "referencetype" ) )  {
663                        hdr->timeRefType[0] = data[0];
664                        hdr->timeRefType[1] = data[1];
665                        hdr->timeRefType[2] = data[2];
666                        continue;
667                }
668                if( !strcmp( key, "adbits" ) )  {
669                        hdr->atodBits = (short)atoi( data );
670                        continue;
671                }
672                if( !strcmp( key, "magcorrection" ) )  {
673                        hdr->magCorr = atof( data );
674                        continue;
675                }
676                if( !strcmp( key, "stationlocation" ) )  {
677                        strcpy( StaLocation, data );
678                        continue;
679                }
680                if( !strcmp( key, "sensorinformation" ) )  {
681                        strcpy( SensorInfo, data );
682                        continue;
683                }
684                if( !strcmp( key, "sensoroutputvoltage" ) )  {
685                        ChanInfo.sensorOutVolt = atof( data );
686                        continue;
687                }
688                if( !strcmp( key, "amplifiergain" ) )  {
689                        ChanInfo.ampGain = atof( data );
690                        continue;
691                }
692                if( !strcmp( key, "adcinputvoltage" ) )  {
693                        ChanInfo.adcInputVolt = atof( data );
694                        continue;
695                }
696                if( debug )
697                        logit("", "Unknown Key in station.lst file = %s\n", key );
698        }
699        fclose( fp );
700}
701
702/* Parse the line from the ReadStationFile above. Returns the key and data
703   parts of the string */
704void ParseLine( char *key, char *data, char *string )
705{
706        char *ptr;
707
708        *key = 0;
709        *data = 0;
710        ptr = strchr( string, '=' );    // find the = between key and data
711        if( ptr == NULL )
712                return;
713        *ptr = 0;
714        strcpy( key, string );                  // get the key
715        Strib( key );
716        _strlwr( key );
717        ++ptr;
718        ptr = SkipSpace( ptr );
719        strcpy( data, ptr );                    // get the data
720}
721
722/* Skip any white spaces in a string */
723static char *SkipSpace( char *string )
724{
725        while( *string )  {
726                if( *string != ' ' && *string != '\t' )
727                        return string;
728                ++string;
729        }
730        return string;
731}
732
733/* Strip trailing blanks and newlines from string. */
734static int Strib( char *string )
735{
736        int i, length;
737
738        length = strlen( string );
739        if ( length )  {
740    for ( i = length-1; i >= 0; i-- )  {
741                if ( string[i] == ' ' || string[i] == '\n' || string[i] == '\r' )
742                        string[i] = '\0';
743        else
744                        return ( i+1 );
745        }
746        }
747        else
748        return length;
749        return i+1;
750}
751
752/* Swap the main PSN Type 4 header information structure */
753static void SwapPsnHeader( PSNType4 *hdr )
754{
755        SwapLong( &hdr->variableHdrLength );
756        SwapShort( &hdr->startTime.year );
757        SwapLong( &hdr->startTime.nanoseconds );
758        SwapDouble( &hdr->startTimeOffset );
759        SwapDouble( &hdr->spsRate );
760        SwapLong( &hdr->sampleCount );
761        SwapLong( &hdr->flags );
762        SwapDouble( &hdr->compIncident );
763        SwapDouble( &hdr->compAzimuth );
764        SwapDouble( &hdr->latitude );
765        SwapDouble( &hdr->longitude );
766        SwapDouble( &hdr->elevation );
767        SwapDouble( &hdr->sensitivity );
768        SwapDouble( &hdr->magCorr );
769        SwapShort( &hdr->atodBits );
770        SwapDouble( &hdr->minimum );
771        SwapDouble( &hdr->maximum );
772        SwapDouble( &hdr->mean );
773}
774
775/* Swap the variable header information structure */
776static void SwapPsnVarHeader( VarHeader *var )
777{
778        SwapLong( &var->length );
779}
780
781/* Swap the channel information structure */
782static void SwapChanInfo( ChannelInfo *chan )
783{
784        SwapDouble( &chan->sensorOutVolt );
785        SwapDouble( &chan->ampGain );
786        SwapDouble( &chan->adcInputVolt );
787}
788
789/* The following are used to calculate the CRC of the event file */
790
791static WORD CalcFileCRC( FILE *fp, int length )
792{
793        BYTE buff[512];
794        WORD crc = 0;
795        int cnt, len;
796        long pos = ftell(fp);
797
798        fseek(fp, 0, SEEK_SET);
799        while( length )  {
800                if( length > 512 )
801                        len = 512;
802                else
803                        len = length;
804                cnt = fread( buff, 1, len, fp );
805                if( !cnt )
806                        logit("et", "Error calculating PSN file CRC. Read error\n");
807                CalcCRC16( &crc, buff, cnt );
808                length -= len;
809        }
810        fseek(fp, pos, SEEK_SET);
811        return crc ;
812}
813
814#define P       0x1021
815#define W       16
816#define B       8
817
818static WORD crctab[1 << B] = {
819    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
820    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
821    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
822    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
823    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
824    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
825    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
826    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
827    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
828    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
829    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
830    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
831    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
832    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
833    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
834    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
835    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
836    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
837    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
838    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
839    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
840    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
841    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
842    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
843    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
844    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
845    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
846    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
847    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
848    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
849    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
850    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
851};
852
853static void CalcCRC16(WORD *crc, BYTE *cp, int cnt)
854{
855        while(cnt--)
856                *crc = (*crc << B) ^ crctab[(*crc>>(W - B)) ^ *cp++];
857}
Note: See TracBrowser for help on using the repository browser.