/****************************************************************************/ /* Copyright 1991 MBARI */ /****************************************************************************/ /* $Header: decode.c,v 3.0 99/05/12 10:11:23 bobh Exp $ */ /* Summary : Program to decode an OASIS binary file */ /* Filename : decode.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 3.0 $ */ /* Created : 12/05/91 */ /****************************************************************************/ /* Modification History: */ /* 05dec91 rah - created */ /* $Log: decode.c,v $ * Revision 3.0 99/05/12 10:11:23 10:11:23 bobh (Bob Herlien) * Added tstring, misc changes * * Revision 2.9 98/08/24 13:45:50 13:45:50 bobh (Bob Herlien) * Archiving sources after M2/M3 & Eqpac deployments of 1998 * * Revision 2.8 98/03/17 11:11:36 11:11:36 bobh (Bob Herlien) * Archiving sources prior to porting to DOS/Windows * * Revision 2.7 97/09/09 09:51:40 09:51:40 bobh (Bob Herlien) * Archiving various changes * * Revision 2.6 96/05/30 15:07:25 15:07:25 bobh (Bob Herlien) * Update for version in use during 1995-6 deployment * * Revision 2.5 94/12/15 10:58:59 10:58:59 hebo (Bob Herlien) * Accumlated minor changes, mainly due to move to tsunami * * Revision 2.4 94/01/21 14:35:34 14:35:34 hebo (Bob Herlien) * Added support for date ranges in cfg file * * Revision 2.3 94/01/17 11:09:31 11:09:31 hebo (Bob Herlien) * Misc changes * * Revision 2.2 93/09/17 10:59:04 10:59:04 hebo (Bob Herlien) * Changed method of finding config file based on name of data file. * * Revision 2.1 92/09/04 13:38:18 13:38:18 hebo (Bob Herlien) * Read CTD pressure from calibration file if no CTD pressure sensor. * * Revision 2.0 92/08/31 15:35:26 15:35:26 hebo (Bob Herlien) * Auguest 1992 Deployment. Changed to allow multiple sensors of same type. * * Revision 1.3 92/06/15 09:07:23 09:07:23 hebo (Bob Herlien) * *** empty log message *** * * Revision 1.2 92/05/12 18:18:39 18:18:39 hebo (Bob Herlien) * Added spectroradiometer decoding (spec.c) * * Revision 1.1 92/03/16 15:42:08 15:42:08 hebo (Bob Herlien) * Ignore leading blanks on "begin" line * * Revision 1.0 92/02/25 10:46:58 10:46:58 hebo (Bob Herlien) * Initial revision */ /****************************************************************************/ #include /* Standard I/O */ #include /* For exit() */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* Time */ #include /* OASIS controller definitions */ #include /* for memcpy() */ #include /* for sqrt() */ #include /* for isspace() */ #include /* for strcmp() */ #define BUFSIZE 2048 /* Size of sample buffer */ #define ANALOG_CHANS 8 /* Number of analog channels */ #define PAR_CHAN 0 /* Analog channel number for PARs */ #define DEC(c) (((c) - ' ') & 0x3f) /* uudecode macro */ /********************************/ /* External Functions */ /********************************/ Extern FILE *openDataFile( char *name ); Extern Int32 get_begin_line( FILE *fd ); Extern Int32 getRecHdr( Byte *buf, Int len, FILE *fd, FileType ftype ); Extern Int32 readDataFile( Byte *buf, Int len, FILE *fd, FileType ftype ); Extern char *get_can_name( char *dataname ); Extern Status read_cfg( char **cfgname ); Extern Status decode_atlas( Byte *atdata, Int atlen, AtlasDecode *adp, AtlasCal *acp ); Extern Status decode_ctd( Byte *ctddata, Int len, CTDDecode *cdp, CTDCal *ccp ); Extern Status decode_no3( Byte *no3data, Int len, No3Decode *no3dp, No3Cal *no3cp ); Extern Status decode_prr( Byte *spdata, Int len, PrrDecode *sdp, SpecCal *scp ); Extern Status decode_spectro( Byte *spdata, Int splen, SpecDecode *sdp, SpecCal *scp ); Extern Status decode_satlantic( Byte *satdata, Int len, SatlanticDecode sdp, SatlanticCal *scp ); Extern Status decode_ac9( Ac9Data *ac9data, Int len, Ac9Decode *ac9 ); Extern Nat16 getIntelword( Byte *p ); Extern Nat32 getIntellong( Byte *p ); Extern Nat16 getMotword( Byte *p ); Extern Nat16 getHdrWord( Byte *p, FileType ftype ); Extern Nat32 getHdrLong( Byte *p, FileType ftype ); #ifdef WIN32 Extern Int getopt( Int argc, char **argv, char *fmt ); #endif /********************************/ /* External Data */ /********************************/ Extern char *optarg; /* Option argument from getopt() */ Extern Int optind; /* Option index from getopt() */ Extern AtlasCal atlas_cal; /* ATLAS calibration */ Extern Analog analog[]; /* Analog calibration */ Extern CTDCal ctd_cal[]; /* Structs to hold CTD calibrations */ Extern No3Cal no3_cal[]; /* Structs to hold NO3 calibrations */ Extern SpecCal spec_cal[]; /* Structs to hold Spect calibrations*/ Extern SatlanticCal satlantic_cal; /* Struct to hold Satlantic cal */ Extern GndFltCal gfCal[]; /* Gnd fault board cals */ Extern Int oasisAnalogChan; /* Analog channel number for oasis */ /********************************/ /* Global Data */ /********************************/ Global Int itime; /* Integer year/day as yyddd */ /********************************/ /* Module Local Data */ /********************************/ MLocal Byte buffer[BUFSIZE]; /* Decoded data buffer */ MLocal AtlasDecode atlas; /* Buffer for decoded ATLAS data */ MLocal FileType fileType = FT_UUENCODE; /* Input file type */ MLocal Int32 gmt_offset = 0; MLocal MBool dolocaltime = TRUE; /* Output local (not GMT) time */ MLocal MBool outputRaw = FALSE; /* Output raw binary */ MLocal MBool donumber = FALSE; /* Output log numbers */ MLocal MBool decode_all = TRUE; /* Decode all sensors */ MLocal MBool decode_sensor[SENSORS]; /* TRUE to decode particular sensor */ MLocal SpecDecode spec; /* Struct to hold decoded Spect data*/ MLocal PrrDecode specprr; /* Decoded PRR Spectro data */ /* File names */ MLocal char *cfgp = NULL; /* Ptr to name of OASIS config file */ MLocal char *sensor_names[] = { "Empty", "OASIS", "ATLAS", "OASIS", "PAR", "CTD", "Spectro", "ADCP", "GPS", "Modem", "pCO2", "CTD2", "CTD3", "Spectro10", "Spectro20", "Nitrate", "Nitrate2", "SpecPRR", "Satlantic", "GPS", "NRL", "Oxygen", "Fluorometer", "Transmissometer", "NO3", "NO3.2", "AC9", "CO2Pump", "H2OPump", "Shutter0", "Shutter1", "SpecPRRVolts", "Metsys", "TString", "GF", "MicroCat", "GPS" }; MLocal char *ac9ChanNames[] = { "a650", "a676", "a715", "c510", "c555", "c630", "a412", "a440", "a488", "c650", "c676", "c715", "a510", "a555", "a630", "c412", "c440", "c488" }; /********************************/ /* Forward Declarations */ /********************************/ MBool process_command_line ( Int argc, char **argv ); Void use_msg( char *s ); Void decode_file( char *s ); Void print_header( LogRecHdr *hdrp, char *ident ); Void printbytes( Byte *s, Int len ); Void printwords( Byte *p, Int len ); Void print_ascii( Int len, MBool strip_nl, MBool convert_cr ); Void print_analog( Int chan, Int nchans ); Void sensor_error( Status err ); Status print_ctd( Int len, CTDCal *ccp ); Status print_gps( Int len ); Status print_gps_type2( Int len ); Status print_gps_type3( Int len ); Status print_spec( Int len, SpecCal *scp ); Status print_spec_prr( Int len, SpecCal *scp ); Status print_satlantic( Int len, SatlanticCal *scp ); Status print_adcpv1( Void ); Status print_ac9( Int len ); Status print_nitrate_decoded( Int len, No3Cal *no3cp ); Void print_shutter( Byte *p, Int len ); Void print_gndflt( Byte *p, Int len, GndFltCal *gfp ); Void print_tstring( char *buffer, Int len ); /************************************************************************/ /* Function : main */ /* Purpose : Main routine */ /* Inputs : argc, argv */ /* Outputs : none */ /************************************************************************/ Void main( Int argc, char *argv[] ) { Int i; char *filename, *cp; if ( !process_command_line(argc, argv) ) { use_msg(argv[0]); exit( 1 ); } for ( i = optind; i < argc; i++ ) { filename = argv[i]; get_can_name( filename ); cp = cfgp; if ( read_cfg(&cp) != OK ) printf("Can't read configuration file \"%s\"\n", cp); else decode_file( filename ); } exit( 0 ); } /* main() */ /************************************************************************/ /* Function : decode_file */ /* Purpose : Decode one data file, print results to stdout */ /* Inputs : File name */ /* Outputs : none */ /************************************************************************/ Void decode_file( char *filename ) { Int32 cc, len, len_got; FILE *fd; struct tm *tp; MBool did_err_msg; Status rtn; Int32 err, blknum; Nat32 diskerr; LogRecHdr hdr; if ( (fd = openDataFile(filename)) == (FILE *)NULL ) return; blknum = 0; if ( fileType == FT_UUENCODE ) if ( (blknum = get_begin_line(fd)) < 0 ) { printf("No begin line in %s\n", filename); fclose( fd ); return; } else if (donumber) printf("Block %d\n", blknum); did_err_msg = FALSE; while ( (cc = getRecHdr(buffer, sizeof(buffer), fd, fileType)) != EOF ) { if ( (cc == UUEND) && (fileType == FT_UUENCODE) ) { blknum = get_begin_line(fd); if ( blknum < 0 ) break; else { if (donumber) printf("Block %d\n", blknum); continue; } } if ( cc == 0 ) continue; did_err_msg = FALSE; hdr.log_type = buffer[0]; hdr.log_nmbr = getHdrWord(&buffer[1], fileType); hdr.log_len = getHdrWord(&buffer[3], fileType); hdr.log_time = getHdrLong(&buffer[5], fileType); tp = gmtime( (time_t *)&hdr.log_time ); itime = (1000 * tp->tm_year) + tp->tm_yday + 1; len_got = cc - 9; /* compute amount of log data gotten*/ if ( len_got > 0 ) memmove( buffer, buffer + 9, sizeof(buffer) - 9 ); else if ( len_got < 0 ) /* Move log data to start of buffer*/ { printf("Incomplete record header\n"); continue; } if ( (len = hdr.log_len) >= (Int32)sizeof(buffer) ) { /* Get size of log data */ len = sizeof(buffer); printf("Record too long in %s, record %d. Truncating.\n", filename, hdr.log_nmbr); continue; } if ( len_got < len ) { len_got += readDataFile(buffer+len_got, len-len_got, fd, fileType); if ( len_got != len) { if ( !did_err_msg ) printf("Bad record in %s block %d record %d\n", filename, blknum, hdr.log_nmbr); did_err_msg = TRUE; continue; } did_err_msg = FALSE; } if ( !decode_all && !((hdr.log_type < SENSORS) && decode_sensor[hdr.log_type]) ) continue; if ( hdr.log_type < SENSORS ) print_header( &hdr, sensor_names[hdr.log_type] ); if ( outputRaw ) { if ( hdr.log_type == LOG_ERROR ) print_header( &hdr, "Error" ); printbytes( buffer, len ); continue; } switch( hdr.log_type ) { case LOG_EMPTY: printbytes(buffer, len); break; case OASIS_STAT: if ( getIntelword(buffer) ) printf("On\n"); else printf("Off\n"); break; case ATLAS: if ( (rtn = decode_atlas(buffer, len, &atlas, &atlas_cal)) != OK ) { sensor_error( rtn ); break; } printf("Time %9.5f Air %6.3f SST %6.3f\n", atlas.atd_time, atlas.atd_air, atlas.atd_sst); printf(" "); for ( cc = 0; cc < TEMPS; cc++ ) printf("%6.3f ", atlas.atd_temp[cc]); printf("\n Press %6.2f %6.2f RH %5.2f", atlas.atd_press[0], atlas.atd_press[1], atlas.atd_rh); printf(" Wind %6.3f m/s toward %5.1f\n", atlas.atd_windspd, atlas.atd_winddir); printf(" Compass %3.0f Vane %3.0f Raw dirctn %3.0f Raw speed %5.2f\n", atlas.atd_compass, atlas.atd_vane, atlas.atd_rawdir, atlas.atd_rawspeed); break; case OASIS_CAN: print_analog( oasisAnalogChan, len/2 ); break; case PAR: print_analog( PAR_CHAN, len/2 ); break; case CTD: print_ctd( len, &ctd_cal[CTD_CAL] ); break; case CTD2: print_ctd( len, &ctd_cal[CTD2_CAL] ); break; case CTD3: print_ctd( len, &ctd_cal[CTD3_CAL] ); break; case SPECTRO: print_spec( len, &spec_cal[SPECTRO_CAL] ); break; case SPECTRO2: print_spec( len, &spec_cal[SPECTRO2_CAL] ); break; case SPECTRO3: print_spec( len, &spec_cal[SPECTRO3_CAL] ); break; case SPEC_PRR: print_spec_prr( len, &spec_cal[SPECPRR_CAL] ); break; case ADCP: print_adcpv1(); printbytes( buffer, len ); break; case GPS: print_gps( len ); break; case GPS_TYPE2: print_gps_type2( len ); break; case GPS_TYPE3: print_gps_type3( len ); break; case PCO2: print_ascii(len, TRUE, FALSE); break; case NO3: print_ascii(len, FALSE, FALSE); print_nitrate_decoded( len, &no3_cal[NO3_CAL] ); break; case NO32: print_ascii(len, FALSE, FALSE); print_nitrate_decoded( len, &no3_cal[NO3_CAL2] ); break; case SATLANTIC: print_satlantic( len, &satlantic_cal ); break; case NRL: print_ascii(len, FALSE, FALSE); break; case O2: print_ascii(len, TRUE, FALSE); break; case FLUOR: print_analog( FLUOR_CHAN, len/2 ); break; case TRANSMISS: print_analog( TRANSMISS_CHAN, len/2 ); break; case CO2_PUMP: case H2O_PUMP: if ( buffer[0] ) printf("On\n"); else printf("Off\n"); break; case AC9: print_ac9( len ); break; case SHUTTER0: case SHUTTER1: print_shutter(buffer, len); break; case METSYS: print_ascii(len, TRUE, FALSE); break; case TSTRING: print_tstring(buffer, len); break; case GNDFAULT: print_gndflt( buffer, len, gfCal ); break; case MICROCAT: print_ascii(len, FALSE, TRUE); break; case LOG_ERROR: cc = getIntelword(buffer); if ( cc & 0x8000 ) { cc &= 0x7fff; print_header(&hdr, "OASIS Error"); if ( cc & RAM_ERR ) printf("RAM_init "); if ( cc & LOG_ERR ) printf("LOG_memory_bad "); if ( cc & CLOCK_ERR ) printf("Clock_failure "); if ( cc & INT_ERR ) printf("Spurious_interrupt "); if ( cc & RESTART_ERR ) printf("Restarted "); if ( cc & COMM_ERR ) printf("24hr_silence"); if ( cc & DISK_ERR ) printf("Disk Write Error "); if ( cc & ARGOS_ERR ) printf("ARGOS Error "); printf("\n"); } else { if ( cc >= SENSORS ) printf("Unknown Error type\n"); else { printf( sensor_names[cc] ); print_header( &hdr, " Error" ); err = (Int16)getIntelword( buffer + 2 ); switch ( err ) { case TMOUT_ERR: printf("Timeout\n"); break; case MALLOC_ERR: printf("No malloc space\n"); break; case NO_DATA: printf("No Data\n"); break; case BAD_DATA: printf("Bad Data\n"); break; case CKSUM_ERR: printf("Checksum Error\n"); break; case SYNC_ERR: printf("Sync Error\n"); break; case NOT_AVAIL_ERR: printf("Not Available\n"); break; case GPS_OOPS: if ( cc == GPS_TYPE2 ) { printf("No first fix.\n"); break; } default: printf("Unknown type %#x\n", (int)err); } } } break; case LOG_COMMENT: print_header( &hdr, "Comment"); for ( cc = 0; cc < len; cc++ ) putchar( buffer[cc] ); printf("\n"); break; case LOG_BIN: switch( cc = getIntelword(buffer) ) { case SPECTRO: case SPECTRO2: case SPECTRO3: printf( sensor_names[cc] ); print_header( &hdr, " V cmd" ); printbytes( &buffer[2], len - 2 ); break; default: print_header( &hdr, "Binary Comment" ); printbytes( buffer, len ); } break; case LOG_DISK_ERROR: print_header( &hdr, "Disk Error"); diskerr = (Nat32)getIntelword( buffer ); printf( "Rtn code %#x\n", (int)diskerr ); break; default: print_header( &hdr, "Unknown" ); printf("\n"); } } fclose( fd ); } /* decode_file() */ /************************************************************************/ /* Function : use_msg */ /* Purpose : Print Usage Message */ /* Inputs : Name of program */ /* Outputs : None */ /************************************************************************/ Void use_msg( char *s ) { fprintf( stderr, "Usage: %s [-b] [-c cfg_file] [-i instrument] [-g[offset]] [-h] [-l] [-n] [-r]\n", s ); fprintf( stderr, "-c cfg_file specifies a configuration file\n"); fprintf( stderr, "-i instrument decodes data only for specified instrument\n"); fprintf( stderr, "-g prints data in fixed offset (in hours) from GMT time\n" ); fprintf( stderr, " (e.g. -g0 prints in GMT time)\n"); fprintf( stderr, "-b interprets data as binary file (default is uuencode)\n" ); fprintf( stderr, "-h interprets data as hex file (default is uuencode)\n" ); fprintf( stderr, "-l prints data in local time (default)\n"); fprintf( stderr, "-n prints record numbers\n"); fprintf( stderr, "-r outputs raw data\n"); } /* use_msg() */ /************************************************************************/ /* Function : process_command_line */ /* Purpose : Read the arguments from the command line */ /* Inputs : argc, argv from main() routine */ /* Outputs : TRUE if arguments OK, else FALSE */ /************************************************************************/ MBool process_command_line ( Int argc, char **argv ) { Int i; for ( i = 0; i < SENSORS; i++ ) decode_sensor[i] = FALSE; while ( (i = getopt(argc, argv, "bc:g:hi:lnr")) != EOF ) switch( i ) { case 'b': fileType = FT_BIN; break; case 'c': cfgp = optarg; break; case 'g': dolocaltime = FALSE; putenv( "TZ=GMT0" ); gmt_offset = atoi(optarg); break; case 'h': fileType = FT_HEX; break; case 'i': for ( i = 0; i < SENSORS; i++ ) if ( strcasecmp(optarg, sensor_names[i]) == 0 ) { decode_all = FALSE; decode_sensor[i] = TRUE; } break; case 'l': dolocaltime = TRUE; break; case 'n': donumber = TRUE; break; case 'r': outputRaw = TRUE; break; default: return( FALSE ); } return( TRUE ); } /* process_command_line() */ /************************************************************************/ /* Function : print_header */ /* Purpose : Print log header */ /* Inputs : Identification string */ /* Outputs : None */ /************************************************************************/ Void print_header( LogRecHdr *hdrp, char *ident ) { struct tm *tp; time_t logTime; logTime = (time_t)hdrp->log_time; if ( dolocaltime ) tp = localtime( &logTime ); else { logTime += (3600 * gmt_offset); tp = gmtime( &logTime ); } printf( "%-8s ", ident ); if ( donumber ) printf("%4d ", hdrp->log_nmbr); printf("%02d/%02d/%02d %02d:%02d:%02d ", tp->tm_year, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); } /* print_header() */ /************************************************************************/ /* Function : printbytes */ /* Purpose : Print data stream as a stream of bytes */ /* Inputs : Byte ptr, length */ /* Outputs : None */ /************************************************************************/ Void printbytes( Byte *s, Int len ) { Int i, curlen; for ( i = 0; i < len; ) { printf("\n "); curlen = len - i; if ( curlen > 32 ) curlen = 32; while ( curlen-- ) printf("%02x", s[i++]); } printf("\n"); } /* printbytes() */ /************************************************************************/ /* Function : printwords */ /* Purpose : Print data stream as a stream of words */ /* Inputs : Byte ptr, length */ /* Outputs : None */ /************************************************************************/ Void printwords( Byte *p, Int len ) { Int i; for ( i = 0; i < len; i += 2 ) printf( "%04x ", getIntelword(p + i) ); printf("\n"); } /* printwords() */ /************************************************************************/ /* Function : print_ascii */ /* Purpose : Print data stream as ascii stream */ /* Inputs : Length, MBool to strip CR & LF */ /* Outputs : None */ /************************************************************************/ Void print_ascii( Int len, MBool strip_nl, MBool convert_cr ) { char *p; buffer[len] = '\0'; if ( strip_nl ) { while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = ' '; while ( (p = strchr((char *)buffer, '\n')) != NULL ) *p = ' '; } if ( convert_cr ) { while ( (p = strchr((char *)buffer, '\r')) != NULL ) *p = '\n'; } printf("\n%s\n", buffer); } /* print_ascii() */ /************************************************************************/ /* Function : print_analog */ /* Purpose : Print data stream as analog channel data */ /* Inputs : First channel number, number of channels */ /* Outputs : None */ /************************************************************************/ Void print_analog( Int chan, Int nchans ) { Int i; Reg Analog *ap; for ( i = 0; i < nchans; i++ ) { ap = &analog[chan + i]; printf("%6.2f %s ", (((ap->a * (double)getIntelword(&buffer[2*i])) + ap->b) * ap->c) + ap->d, ap->units); } printf("\n"); } /* print_analog() */ /************************************************************************/ /* Function : print_gps */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : OK or SIZE_ERR */ /************************************************************************/ Status print_gps( Int len ) { Int32 lat, lon; Nat32 var; Nat16 samples, status; char lathem, lonhem; if ( len != 16 ) { printf("Bad GPS record size, was %d, should be 16\n",len); return( SIZE_ERR ); } lat = getIntellong(buffer); lon = getIntellong(&buffer[4]); var = getIntellong(&buffer[8]); samples = getIntelword(&buffer[12]); status = getIntelword(&buffer[14]); lathem = 'N'; lonhem = 'W'; if ( lat < 0 ) { lat = -lat; lathem = 'S'; } if ( lon < 0 ) { lon = -lon; lonhem = 'W'; } printf("%3d:%02d.%03d%c %3d:%02d.%03d%c StdDev %.2f Samp %d Stat %04x\n", (int)(lat/60000), (int)((lat/1000)%60), (int)(lat%1000), lathem, (int)(lon/60000), (int)((lon/1000)%60), (int)(lon%1000), lonhem, sqrt((double)var), samples, status); return( OK ); } /* print_gps() */ /************************************************************************/ /* Function : print_gps_type2 */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : OK or SIZE_ERR */ /************************************************************************/ Status print_gps_type2( Int len ) { Int32 lat, lon; Nat32 var; Nat16 samples, totTime, status; if ( len != 18 ) { printf("Bad GPS record size, was %d, should be 18\n",len); return( SIZE_ERR ); } lat = getIntellong(buffer); lon = getIntellong(&buffer[4]); var = getIntellong(&buffer[8]); samples = getIntelword(&buffer[12]); totTime = getIntelword(&buffer[14]); status = getIntelword(&buffer[16]); printf("%10.5f %10.5f StdDev %.2f Samp %d Time %d Stat %04x\n", lat/10000000., lon/10000000., sqrt((double)var), samples, totTime, status); return( OK ); } /* print_gps_type2() */ /************************************************************************/ /* Function : print_gps_type3 */ /* Purpose : Print buffer as GPS data */ /* Inputs : Length of buffer */ /* Outputs : OK or SIZE_ERR */ /************************************************************************/ Status print_gps_type3( Int len ) { Int32 lat, lon; Nat32 var; Nat16 fmt, samples, totTime, diffSamples, hdop, status; char lathem, lonhem; if ( (fmt = getIntelword(buffer)) != 1 ) { printf("Unknown GPS format %d\n", fmt); return( FMT_ERR ); } if ( len != 24 ) { printf("Bad GPS record size, was %d, should be 24\n",len); return( SIZE_ERR ); } samples = getIntelword(&buffer[2]); lat = getIntellong(&buffer[4]); lon = getIntellong(&buffer[8]); var = getIntellong(&buffer[12]); totTime = getIntelword(&buffer[16]); diffSamples = getIntelword(&buffer[18]); hdop = getIntelword(&buffer[20]); status = getIntelword(&buffer[22]); lathem = 'N'; lonhem = 'W'; if ( lat < 0 ) { lat = -lat; lathem = 'S'; } if ( lon < 0 ) { lon = -lon; lonhem = 'W'; } printf("%3d:%02d.%04d%c %3d:%02d.%03d%c StdDev %.2f Samp %d\n", (int)(lat/600000), (int)((lat/10000)%60), (int)(lat%10000), lathem, (int)(lon/600000), (int)((lon/10000)%60), (int)(lon%10000), lonhem, sqrt((double)var), samples); printf(" On Time %d Diff %d HDOP %.1f Temp %d Stat %04x\n", totTime, diffSamples, 0.1*hdop, (status>>8) & 0xff, status & 0xff); return( OK ); } /* print_gps_type3() */ /************************************************************************/ /* Function : print_ctd */ /* Purpose : Print buffer as CTD data */ /* Inputs : Length of buffer, CTD calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_ctd( Int len, CTDCal *ccp ) { CTDDecode ctd; /* Struct to hold decoded CTD data */ Status rtn; /* Return code */ if ( (rtn = decode_ctd(buffer, len, &ctd, ccp)) != OK ) { sensor_error( rtn ); return( rtn ); } printf("Num %d Press %6.3f Temp %6.3f Cond %6.3f\n", ctd.ctd_sample, ctd.ctd_press, ctd.ctd_temp, ctd.ctd_cond); printf(" Salinity %6.4f Transmiss %6.4f Fluor %6.4f\n", ctd.ctd_sal, ctd.ctd_trans, ctd.ctd_fluor); return( OK ); } /* print_ctd() */ /************************************************************************/ /* Function : print_spec */ /* Purpose : Print buffer as Spectroradiometer data */ /* Inputs : Length of buffer, Spectro calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_spec( Int len, SpecCal *scp ) { Int i, j, n; /* Scratch */ Status rtn; /* Return code */ if ( (rtn = decode_spectro(buffer, len, &spec, scp)) != OK ) { sensor_error( rtn ); return( rtn ); } printf("Time %9.5f", spec.spc_day + (double)(spec.spc_sec)/86400.0); for ( i = 0, n = 100; i < SPEC_BANKS; i++ ) for ( j = 0; j < scp->spc_nchans[i]; j++ ) { if ( n >= 60 ) { printf("\n "); n = 0; } if ( scp->spc_cal[i][j].type > 0 ) n += printf("%5s %9.6f ", scp->spc_cal[i][j].name, spec.spc_chan[i][j].spc_mean); } printf("\n"); return( OK ); } /* print_spec() */ /************************************************************************/ /* Function : print_nitrate_decoded */ /* Purpose : Decode and print decoded nitrate data */ /* Inputs : Length, calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_nitrate_decoded( Int len, No3Cal *no3cp ) { Reg Byte *p, *q; /* Scratch ptrs */ No3Decode no3; /* Struct to hold decoded NO3 data */ Status rtn; /* Return code */ buffer[len] = '\0'; for ( p = buffer; p - buffer < len; p = q ) { /* Loop to decode one line at a time*/ while ( (p - buffer < len) && ((*p == '\r') || (*p == '\n')) ) p++; if ( (q = (Byte *)strchr((char *)p, '\r')) == NULL ) q = (Byte *)strchr((char *)p, '\n'); if ( (q != NULL) && (q - buffer < len) ) *q++ = '\0'; else q = p + strlen((char *)p) + 1; if ( (rtn = decode_no3(p, len, &no3, no3cp)) == OK ) { if ( no3cp->nc_format == NO3_DRIFT1 ) printf("%-.14s no3 %6.4f Temp %6.3f Salinity %6.4f Cond %6.4f\n", no3.no3_time, no3.no3_conc, no3.no3_temp, no3.no3_salinity, no3.no3_conductivity); else printf("%-.14s no3 %6.4f Temp %6.3f\n", no3.no3_time, no3.no3_conc, no3.no3_temp); } } return( OK ); } /* print_nitrate_decoded() */ /************************************************************************/ /* Function : print_spec_prr */ /* Purpose : Print buffer as PRR-600 Spectroradiometer data */ /* Inputs : Length of buffer, Spectro calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_spec_prr( Int len, SpecCal *scp ) { Int bank, chan, cursor; /* Bank, chan nums, cursor position*/ Status rtn; /* Return code */ if ( (rtn = decode_prr(buffer, len, &specprr, scp)) != OK ) { sensor_error( rtn ); return( rtn ); } for ( bank = 0, cursor = 100; bank < specprr.prr_nbanks; bank++ ) for ( chan = 0; (chan < specprr.prr_bank[bank].prr_nchans); chan++ ) { if ( cursor >= 60 ) { printf("\n "); cursor = 0; } if ( scp->spc_cal[bank][chan].type > 0 ) cursor += printf("%-5.5s %9.5f ", scp->spc_cal[bank][chan].name, specprr.prr_bank[bank].prr_chan[chan]); } printf("\n"); return( OK ); } /* print_spec_prr() */ /************************************************************************/ /* Function : print_satlantic */ /* Purpose : Print buffer as Satlantic spectroradiometer data */ /* Inputs : Length of buffer, Satlantic calibration struct */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_satlantic( Int len, SatlanticCal *scp ) { Int chan, cursor; /* Channel number, cursor position */ Status rtn; /* Return code */ SatlanticDecode satlantic; /* Decoded Satlantic data */ if ( (rtn = decode_satlantic(buffer, len, satlantic, scp)) != OK ) { sensor_error( rtn ); return( rtn ); } for ( chan = 0, cursor = 80; chan < scp->sat_chans; chan++ ) { if ( cursor >= 64 ) { printf("\n "); cursor = 10; } cursor += printf("%s %9.6f ", scp->sat_cal[chan].sat_name, satlantic[chan]); } printf("\n"); return( OK ); } /* print_satlantic() */ /************************************************************************/ /* Function : print_adcpv1 */ /* Purpose : Print V1 voltage of ADCP */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ #define V1_OFS 45 #define V1_MULT 0.05 Status print_adcpv1( Void ) { printf( " V1 %5.2f", V1_MULT * (double)((unsigned char)buffer[V1_OFS])); return( OK ); } /* print_adcpv1() */ /************************************************************************/ /* Function : print_ac9 */ /* Purpose : Print buffer as AC-9 data */ /* Inputs : Length of buffer */ /* Outputs : OK or Error type */ /************************************************************************/ Status print_ac9( Int len ) { Status rtn; Int chan; Ac9Decode ac9; if ( (rtn = decode_ac9((Ac9Data *)buffer, len, &ac9)) != OK ) { sensor_error( rtn ); return( rtn ); } printf( "%d samples Temp %8.4f\n", (int)ac9.ac9_samples, ac9.ac9_temp ); for ( chan = 0; chan < AC9_CHANS; chan++ ) { printf("%s %6.4f ", ac9ChanNames[chan], ac9.ac9_value[chan]); if ( (chan % 6) == 5 ) printf("\n"); } return( OK ); } /* print_ac9() */ /************************************************************************/ /* Function : print_shutter */ /* Purpose : Print shutter log record */ /* Inputs : Sensor, length */ /* Outputs : None */ /************************************************************************/ Void print_shutter( Byte *p, Int len ) { Word status; if ( len < (Int)(2 * sizeof(Word)) ) { printf("Bad record size, was %d, should be 4\n",len); return; } status = getIntelword( buffer + sizeof(Word) ); printf( "Pos %4d Stat %04x Shutter %2d Try %2d Rtn %2d ", getIntelword(buffer), status, ((status >> 12) & 7), (status & 0xff), ((status >> 8) & 0x0f) ); if ( status & 0x8000 ) printf( "open\n"); else printf( "close\n"); } /* print_shutter() */ /************************************************************************/ /* Function : print_gndflt */ /* Purpose : Print Ground Fault data */ /* Inputs : Buffer, length, calibr struct */ /* Outputs : None */ /************************************************************************/ Void print_gndflt( Byte *p, Int len, GndFltCal *gfp ) { Reg int i; Reg GndFltCal *gfPtr; Reg Nat16 raw; double value; for ( i = 0, gfPtr = gfp; i < MAX_GF_CALS; i++, gfPtr++ ) if ( gfPtr->cal_valid && (len >= (Int)(gfPtr->raw_offset + sizeof(Nat16))) ) { raw = getMotword( p + gfPtr->raw_offset ); value = (double)(raw - gfPtr->cal_offset) / gfPtr->cal_divisor; printf( "%s %5.2f %s\n", gfPtr->ident, value, gfPtr->units ); } printf("\n"); } /* print_gndflt() */ /************************************************************************/ /* Function : read_tstring_cfg */ /* Purpose : Just here to satisfy linker (only needed for extract) */ /* Inputs : Ptr to tstring cfg file name ptr */ /* Outputs : OK or ERROR */ /************************************************************************/ Status read_tstring_cfg( char *fileName, TStringCfg *tCfgp ) { return( OK ); } /* read_tstring_cfg() */ /************************************************************************/ /* Function : print_tstring */ /* Purpose : Print data from Inductive Modem Temperature String */ /* Inputs : Buffer, Length */ /* Outputs : None */ /************************************************************************/ Void print_tstring( char *buffer, Int len ) { char *datap, *linep; Reg Int32 cnt; Int32 dummy1; Flt32 dummy2; buffer[len] = '\0'; printf("\n"); for ( datap = buffer, cnt = 0; *datap && (cnt < len); ) { linep = datap; for ( ; *datap && (cnt < len); datap++, cnt++ ) if ( (*datap == '\r') || (*datap == '\n') ) { *datap++ = '\0'; cnt++; break; } if ( sscanf(linep, " %d, %g", &dummy1, &dummy2) == 2 ) printf("%s\n", linep); } } /* print_tstring() */ /************************************************************************/ /* Function : sensor_error */ /* Purpose : Print error in decoding sensor data */ /* Inputs : Error type */ /* Outputs : None */ /************************************************************************/ Void sensor_error( Status err ) { switch( err ) { case ERROR: printf("Error\n"); break; case SIZE_ERR: printf("Wrong size\n"); break; case CHKSUM_ERR: printf("Checksum error\n"); break; case FMT_ERR: printf("Bad data format\n"); break; default: printf("Unknown error\n"); } } /* sensor_error() */