head 2.9; access ; symbols ; locks ; strict; comment @ * @; 2.9 date 98.08.24.13.45.55; author bobh; state Exp; branches ; next 2.8; 2.8 date 98.03.17.11.11.42; author bobh; state Exp; branches ; next 2.7; 2.7 date 97.09.09.09.52.47; author bobh; state Exp; branches ; next 2.6; 2.6 date 96.05.30.15.07.57; author bobh; state Exp; branches ; next 2.2; 2.2 date 94.01.17.11.09.59; author hebo; state Exp; branches ; next 2.1; 2.1 date 92.09.02.15.43.25; author hebo; state Exp; branches ; next 2.0; 2.0 date 92.08.31.15.35.57; author hebo; state Exp; branches ; next 1.0; 1.0 date 92.05.12.18.18.20; author hebo; state Exp; branches ; next ; desc @Routines to decode spectroradiometer data for decode, extract @ 2.9 log @Archiving sources after M2/M3 & Eqpac deployments of 1998 @ text @/****************************************************************************/ /* Copyright 1992 MBARI */ /****************************************************************************/ /* $Header: spec.c,v 2.8 98/03/17 11:11:42 bobh Exp $ */ /* Summary : Spectroradiometer decode routines for decode.c, extract.c */ /* Filename : spec.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 2.8 $ */ /* Created : 05/12/92 */ /****************************************************************************/ /* Modification History: */ /* 12may92 rah - created */ /* $Log: spec.c,v $ * Revision 2.8 98/03/17 11:11:42 11:11:42 bobh (Bob Herlien) * Archiving sources prior to porting to DOS/Windows * * Revision 2.7 97/09/09 09:52:47 09:52:47 bobh (Bob Herlien) * Archiving various changes * * Revision 2.6 96/05/30 15:07:57 15:07:57 bobh (Bob Herlien) * Update for version in use during 1995-6 deployment * * Revision 2.2 94/01/17 11:09:59 11:09:59 hebo (Bob Herlien) * Misc changes * * Revision 2.1 92/09/02 15:43:25 15:43:25 hebo (Bob Herlien) * Don't subtract offset from standard deviation * * Revision 2.0 92/08/31 15:35:57 15:35:57 hebo (Bob Herlien) * August 1992 Deployment. Changed to allow multiple sensors of same type. * * Revision 1.0 92/05/12 18:18:20 18:18:20 hebo (Bob Herlien) * Initial revision * */ /****************************************************************************/ #include /* Standard I/O */ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* Time */ #include /* for memcpy() */ #include /* for toupper() */ #include /* for strcmp */ #include #define PRR_FORMAT 1 /* Format word for PRR spectro */ #define SRE 9.539e-06 /* Gain constant for PRR spectro */ /********************************/ /* External Functions */ /********************************/ Extern Nat16 getIntelword( Byte *p ); /* Get word in Intel format */ Extern Nat32 getIntellong( Byte *p ); /* Get long word in Intel format */ /********************************/ /* Module Local Data */ /********************************/ MLocal double prr_gains[] = { 256.0, 16.0, 1.0, 0.0 }; MLocal char tmp_buff[256]; /************************************************************************/ /* Function : init_spec_cal */ /* Purpose : Initialize Spectroradiometer calibration */ /* Inputs : None */ /* Outputs : none */ /************************************************************************/ Void init_spec_cal( SpecCal *scp ) { Reg Int32 bank, chan; memset( (void *)scp, sizeof(SpecCal), 0 ); for ( bank = 0; bank < SPEC_BANKS; bank++ ) for ( chan = 0; chan < SPEC_CHANS; chan++ ) { scp->spc_cal[bank][chan].a = 0.0; scp->spc_cal[bank][chan].b = 1.0; scp->spc_cal[bank][chan].c = 0.0; strncpy( scp->spc_cal[bank][chan].name, "No calibration", CHAN_NAMELEN ); strncpy( scp->spc_cal[bank][chan].units, "volts", UNIT_NAMELEN ); } } /* init_spec_cal() */ /**************************************************************************/ /* Function : read_spec_file */ /* Purpose : Reentrant routine to read one file of spectro calibrations*/ /* Inputs : Name of file, Ptr to cal struct, Boolean for got channel nos*/ /* Outputs : OK or ERROR */ /* Comments : Discards lines until it finds record with number of chans*/ /* then assumes channel calibration records follow */ /* Assumes bank number is zero-relative (so leaves it alone)*/ /* but that channel number is one-relative, so subtracts 1 */ /**************************************************************************/ Status read_spec_file( char *fileName, SpecCal *scp, MBool gotChans ) { FILE *fp; Int bank, chan, cmin, cmax; Reg char *p; SpecChanCal cal; if ( (fp = fopen(fileName, "rb")) == (FILE *)NULL ) return( ERROR ); while( fgets(tmp_buff, sizeof(tmp_buff), fp) != NULL ) { if ( (p = strchr(tmp_buff, '\n')) != NULL ) *p = '\0'; if ( (tmp_buff[0] == '#') || (strlen(tmp_buff) == 0) ) ; /* Skip comments & blank lines */ else if ( !gotChans ) { if( sscanf(tmp_buff, " %d %d %d %d %d %d", &scp->spc_nchans[0], &scp->spc_nchans[1], &scp->spc_nchans[2], &scp->spc_nchans[3], &scp->spc_nchans[4], &scp->spc_nchans[5]) > 0 ) gotChans = TRUE; } else if ( sscanf(tmp_buff, " %d %d %d %8s %lg %lg %lg %d %d %20s", &bank, &chan, &cal.type, &cal.name, &cal.a, &cal.b, &cal.c, &cmin, &cmax, &cal.units) >= 7 ) memcpy( (void *)&scp->spc_cal[bank][chan-1], (void *)&cal, sizeof(cal) ); else read_spec_file( tmp_buff, scp, gotChans ); } fclose( fp ); return( OK ); } /* read_spec_file() */ /**************************************************************************/ /* Function : read_spec_cal */ /* Purpose : Read Spectroradiometer calibration file */ /* Inputs : Name of file, Ptr to calibration structure to fill in */ /* Outputs : OK or ERROR */ /**************************************************************************/ Status read_spec_cal( char *fileName, SpecCal *scp ) { Reg Int i; init_spec_cal( scp ); scp->spc_totchans = 0; if ( read_spec_file(fileName, scp, FALSE) != OK ) return( ERROR ); for( i = 0; i < SPEC_BANKS; i++ ) { if ( scp->spc_nchans[i] > SPEC_CHANS ) return( ERROR ); scp->spc_totchans += scp->spc_nchans[i]; } if ( scp->spc_totchans <= 0 ) return( ERROR ); return( OK ); } /* read_spec_cal() */ /************************************************************************/ /* Function : decode_value */ /* Purpose : Decode one spectro value */ /* Inputs : Pointer to Spectro data, channel calibration struct, Bool*/ /* Outputs : Value as double precision number */ /* Comment : Used only by decode_spectro(), currently unused */ /* a coefficient not used -- MER always uses linear calibr*/ /************************************************************************/ double decode_value( Byte *p, SpecChanCal *sccp, MBool apply_offset ) { Nat32 raw; Int32 mantissa; Int32 exponent; double voltage; raw = getIntellong( p ); /* Get hex value */ mantissa = raw & 0x7fffff; /* Get mantissa */ if ( raw & 0x800000 ) /* Get mantissa's sign */ mantissa = -mantissa; exponent = ((raw >> 24) & 0xff) - 23; /* Get exponent */ voltage = (double)mantissa * pow(2.0, (double)exponent); if ( apply_offset ) voltage -= sccp->c; if ( sccp->type == 6 ) return( sccp->a * voltage / sccp->b ); return( voltage / sccp->b ); } /* decode_value() */ /************************************************************************/ /* Function : decode_spectro */ /* Purpose : Decode Spectroradiometer information */ /* Inputs : Pointer to Spectro data, length, ptr to return struct */ /* Outputs : OK, SIZE_ERR, FMT_ERR, or CHKSUM_ERR */ /* Comments : MER Spectro decode routine, currently unused */ /************************************************************************/ Status decode_spectro( Byte *spdata, Int splen, SpecDecode *sdp, SpecCal *scp ) { Nat32 val; Int32 i, j, n; Byte chksum; SpecChanCal *sccp; SpecChanDecode *scdp; memset( (void *)sdp, sizeof(SpecDecode), 0 ); if ( splen < (Int)((4 * scp->spc_totchans * sizeof(Nat32)) + 9) ) return( SIZE_ERR ); /* Check size, rtn if bad */ if ( *spdata != 'S' ) /* Look for leading 'S', */ return( FMT_ERR ); /* return if bad */ if ( getIntelword(spdata+1) != splen ) /* Look for length field, */ return( FMT_ERR ); /* return if bad */ chksum = 0; /* Init checksum */ for ( i = 0; i < splen - 1; i++ ) /* Compute checksum */ chksum += spdata[i]; if ( chksum != spdata[splen-1] ) /* Return error if bad chksum*/ return( CHKSUM_ERR ); val = getIntellong( spdata + 3 ); /* Get time/date field */ sdp->spc_year = ((val >> 9) & 0x3f) + 1980; /* Decode year */ sdp->spc_day = (val & 0xff); /* Decode julian day */ if ( val & 0x8000 ) sdp->spc_day += 0x100; sdp->spc_sec = (val >> 16) & 0xffff; /* Decode seconds since 00:00*/ if ( val & 0x100 ) sdp->spc_sec += 0x10000L; for ( i = 0, n = 8; i < SPEC_BANKS; i++ ) for ( j = 0; j < scp->spc_nchans[i]; j++ ) { sccp = &scp->spc_cal[i][j]; scdp = &sdp->spc_chan[i][j]; scdp->spc_mean = decode_value( spdata + n, sccp, TRUE ); n += sizeof(Nat32); scdp->spc_std = decode_value( spdata + n, sccp, FALSE ); n += sizeof(Nat32); scdp->spc_min = decode_value( spdata + n, sccp, TRUE ); n += sizeof(Nat32); scdp->spc_max = decode_value( spdata + n, sccp, TRUE ); n += sizeof(Nat32); } return( OK ); } /* decode_spectro() */ /************************************************************************/ /* Function : decode_prr_chan */ /* Purpose : Decode one channel of PRR-600 Spectroradiometer data */ /* Inputs : Raw data, ptr to channel calibration */ /* Outputs : Channel value */ /************************************************************************/ double decode_prr_chan( Int16 ival, SpecChanCal *sccp ) { double volts; Nat16 gainbits; gainbits = (ival & 0xc000) >> 14; if ( ival & 0x2000 ) /* Bit 12 is sign bit */ ival |= 0xc000; else ival &= ~0xc000; if ( gainbits >= 3 ) volts = 1e99; else volts = prr_gains[gainbits] * (double)ival * SRE; if ( sccp == (SpecChanCal *)NULL ) return( volts ); switch ( sccp->type ) { case 1: case 2: case 3: case 4: return( (volts - sccp->c) / sccp->b ); case 5: return( sccp->c + (sccp->b * volts) + (sccp->a * volts * volts) ); case 6: return( (sccp->a * (volts - sccp->c)) / sccp->b); case 7: return( sccp->a * sccp->b * (volts - sccp->c) ); case 0: default: return( 0.0 ); } } /* decode_prr_chan() */ /************************************************************************/ /* Function : decode_prr */ /* Purpose : Decode PRR-600 Spectroradiometer data */ /* Inputs : Pointer to Spectro data, length, ptr to return struct */ /* Outputs : OK, SIZE_ERR, or FMT_ERR */ /************************************************************************/ Status decode_prr( Byte *spdata, Int splen, PrrDecode *sdp, SpecCal *scp ) { Nat32 bank, chan, chansForThisBank; Int32 bytesUsed; Int16 ival; sdp->prr_nbanks = 0; for ( bank = 0; bank < SPEC_BANKS; bank++ ) { sdp->prr_bank[bank].prr_nchans = 0; for ( chan = 0; chan < SPEC_CHANS; chan++ ) sdp->prr_bank[bank].prr_chan[chan] = 0.0; } if ( getIntelword(spdata) != PRR_FORMAT ) return( FMT_ERR ); bytesUsed = sizeof( Nat16 ); for ( bank = 0; (bank < SPEC_BANKS) && (bytesUsed < splen); bank++ ) { sdp->prr_nbanks = bank + 1; chansForThisBank = getIntelword( spdata + bytesUsed ); bytesUsed += sizeof( Nat16 ); for ( chan = 0; (chan < chansForThisBank) && (bytesUsed < splen); chan++, bytesUsed += sizeof(Int16) ) { sdp->prr_bank[bank].prr_nchans = chan + 1; ival = (Int16)getIntelword( spdata + bytesUsed ); if ( scp == (SpecCal *)NULL ) sdp->prr_bank[bank].prr_chan[chan] = decode_prr_chan( ival, (SpecChanCal *)NULL ); else sdp->prr_bank[bank].prr_chan[chan] = decode_prr_chan( ival, &scp->spc_cal[bank][chan] ); } } return( OK ); } /* decode_prr() */ /************************************************************************/ /* Function : read_satlantic_cal */ /* Purpose : Read Satlantic Spectro calibration file */ /* Inputs : Name of file, Ptr to calibration structure to fill in */ /* Outputs : OK or ERROR */ /* Comments : Discards lines until it finds record with number of chans*/ /* then assumes channel calibration records follow */ /************************************************************************/ Status read_satlantic_cal( char *name, SatlanticCal *scp ) { FILE *fp; MBool got_chans; Int chan; memset( (void *)scp, sizeof(SatlanticCal), 0 ); for ( chan = 0; chan < MAX_SAT_CHANS; chan++ ) { scp->sat_cal[chan].sat_factor = 1.0; scp->sat_cal[chan].sat_immers = 1.0; scp->sat_cal[chan].sat_offset = 0.0; strncpy( scp->sat_cal[chan].sat_name, "No calibration", CHAN_NAMELEN ); } got_chans = FALSE; chan = 0; if ( (fp = fopen(name, "rb")) == (FILE *)NULL ) return( ERROR ); while( fgets(tmp_buff, sizeof(tmp_buff), fp) != NULL ) { if ( tmp_buff[0] == '#' ) ; /* Skip comments */ else if ( !got_chans ) { if( sscanf(tmp_buff, " %d %d", &scp->sat_unused_chans, &scp->sat_chans) > 1 ) got_chans = TRUE; } else if ( sscanf(tmp_buff, " %6s %lg %lg %lg", &scp->sat_cal[chan].sat_name, &scp->sat_cal[chan].sat_factor, &scp->sat_cal[chan].sat_immers, &scp->sat_cal[chan].sat_offset) >= 4 ) { chan++; } } if ( scp->sat_chans <= 0 ) return( ERROR ); fclose( fp ); return( OK ); } /* read_satlantic_cal() */ /************************************************************************/ /* Function : decode_satlantic */ /* Purpose : Decode Satlantic Spectro data */ /* Inputs : Pointer to Spectro data, length, ptr to return struct */ /* Outputs : OK or SIZE_ERR */ /************************************************************************/ Status decode_satlantic( Byte *satdata, Int len, SatlanticDecode sdp, SatlanticCal *scp ) { Int chan; double raw; Byte *datp; SatlantChanCal *sccp; if ( len < (Int)((scp->sat_unused_chans + scp->sat_chans) * sizeof(Nat16)) ) return( SIZE_ERR ); datp = satdata + (scp->sat_unused_chans * sizeof(Nat16)); for ( chan = 0; chan < scp->sat_chans; chan++, datp += sizeof(Nat16) ) { sccp = &scp->sat_cal[chan]; raw = (double)getIntelword(datp) - sccp->sat_offset; /* if ( raw < 0.0 ) raw = 0.0; */ sdp[chan] = raw * sccp->sat_factor * sccp->sat_immers; } return( OK ); } /* decode_satlantic */ @ 2.8 log @Archiving sources prior to porting to DOS/Windows @ text @d4 1 a4 1 /* $Header: spec.c,v 2.7 97/09/09 09:52:47 bobh Exp $ */ d9 1 a9 1 /* $Revision: 2.7 $ */ d15 3 d40 2 a41 2 #include /* MBARI type definitions */ #include /* MBARI constants */ d46 1 a68 1 d191 1 a191 1 signed char exponent; @ 2.7 log @Archiving various changes @ text @d4 1 a4 1 /* $Header: spec.c,v 2.6 96/05/30 15:07:57 bobh Exp $ */ d9 1 a9 1 /* $Revision: 2.6 $ */ d15 3 d221 1 a221 1 Nat32 i, j, n; d228 1 a228 1 if ( splen < ((4 * scp->spc_totchans * sizeof(Nat32)) + 9) ) d335 2 a336 1 Nat32 bank, chan, bytesUsed, chansForThisBank; d400 1 a400 1 scp->sat_cal[chan].sat_offset = 0; d420 1 a420 1 else if ( sscanf(tmp_buff, " %6s %lg %lg %d", d450 2 a451 1 Int chan, i; d455 1 a455 1 if ( len < ((scp->sat_unused_chans + scp->sat_chans) * sizeof(Nat16)) ) d463 6 a468 6 i = getIntelword(datp) - sccp->sat_offset; if ( i < 0 ) i = 0; sdp[chan] = i * sccp->sat_factor * sccp->sat_immers; @ 2.6 log @Update for version in use during 1995-6 deployment @ text @d4 1 a4 1 /* $Header: spec.c,v 2.2 94/01/17 11:09:59 hebo Exp $ */ d9 1 a9 1 /* $Revision: 2.2 $ */ d15 3 d91 3 a93 3 /* Function : read_spec_cal */ /* Purpose : Read Spectroradiometer calibration file */ /* Inputs : Name of file, Ptr to calibration structure to fill in */ d98 1 a98 1 /* but that channel number is one-relative, so subtracts 1 */ d101 1 a101 1 read_spec_cal( char *name, SpecCal *scp ) d104 2 a105 1 Int i, bank, chan, n, cmin, cmax; a106 1 Boolean got_chans; d108 1 a108 5 init_spec_cal( scp ); got_chans = FALSE; n = 0; if ( (fp = fopen(name, "rb")) == (FILE *)NULL ) d113 5 a117 3 if ( tmp_buff[0] == '#' ) ; /* Skip comments */ else if ( !got_chans ) d123 1 a123 1 got_chans = TRUE; a127 1 { d130 2 a131 2 n++; } d135 23 a157 2 for( i = scp->spc_totchans = 0; i < SPEC_BANKS; i++ ) d181 1 a181 1 decode_value( Byte *p, SpecChanCal *sccp, Boolean apply_offset ) d272 52 d330 1 a330 1 decode_prr( Byte *spdata, Int splen, SpecPRRDecode sd, SpecCal *scp ) a333 3 Nat16 gainbits; double volts; SpecChanCal *sccp; d335 2 d338 2 d341 2 a342 1 sd[bank][chan] = 0.0; d351 1 d358 1 a359 2 gainbits = (ival & 0xc000) >> 14; sccp = &scp->spc_cal[bank][chan]; d361 3 a363 2 if ( ival & 0x2000 ) /* Bit 12 is sign bit */ ival |= 0xc000; d365 2 a366 27 ival &= ~0xc000; if ( gainbits >= 3 ) volts = 1e99; else volts = prr_gains[gainbits] * (double)ival * SRE; switch ( sccp->type ) { case 0: break; case 1: case 2: case 3: case 4: sd[bank][chan] = (volts - sccp->c) / sccp->b; break; case 5: sd[bank][chan] = sccp->a + (sccp->b * volts) + (sccp->c * volts * volts); break; case 6: sd[bank][chan] = (sccp->a * (volts - sccp->c)) / sccp->b; } d387 1 a387 1 Boolean got_chans; @ 2.2 log @Misc changes @ text @d4 1 a4 1 /* $Header: spec.c,v 2.1 92/09/02 15:43:25 hebo Exp $ */ d9 1 a9 1 /* $Revision: 2.1 $ */ d15 3 d39 4 d55 1 a55 1 MLocal SpecChanCal cal; /* Temp calibration struct */ d59 1 d69 2 d73 11 d87 5 a91 5 /************************************************************************/ /* Function : read_spec_cal */ /* Purpose : Read Spectroradiometer calibration file */ /* Inputs : Name of file, Ptr to calibration structure to fill in */ /* Outputs : OK or ERROR */ d93 4 a96 2 /* then assumes channel calibration records follow */ /************************************************************************/ d102 1 d114 3 a116 1 if ( !got_chans ) d128 1 a128 1 memcpy( (void *)&scp->spc_cal[bank-1][chan-1], d143 1 a143 1 if ( (scp->spc_totchans <= 0) || (n < scp->spc_totchans) ) d156 2 a157 1 /* Comment : a coefficient not used -- MER always uses linear calibr*/ d191 1 d254 1 a254 1 /* Outputs : Number of channels decoded, SIZE_ERR, or FMT_ERR */ d256 1 a256 4 #define SRE 9.539e-06 MLocal double prr_gains[] = { 256.0, 16.0, 1.0, 0.0 }; Int d259 1 a259 2 Nat32 i, j; Int len; d265 16 a280 3 for ( i = len = 0; i < SPEC_BANKS; i++ ) for ( j = 0; (j < scp->spc_nchans[i]) && (len < splen); j++, len += sizeof(Int16) ) d282 1 a282 1 ival = (Int16)getIntelword( spdata + len ); d284 1 a284 1 sccp = &scp->spc_cal[i][j]; d292 1 a292 1 sd[i][j] = 1e99; d294 3 d298 17 a314 5 volts = prr_gains[gainbits] * (double)ival * SRE; if ( sccp->type == 5 ) sd[i][j] = sccp->a*volts*volts + sccp->b*volts + sccp->c; else sd[i][j] = (volts - sccp->c) / sccp->b; d317 1 d319 1 a319 1 return( len / sizeof(Int16) ); d322 96 @ 2.1 log @Don't subtract offset from standard deviation @ text @d4 1 a4 1 /* $Header: spec.c,v 2.1 92/09/02 15:41:24 hebo Exp $ */ d15 3 d78 1 a78 1 Int i, j, n, bank, chan, cmin, cmax; d92 4 a95 3 if( sscanf(tmp_buff, " %d %d %d %d", &scp->spc_nchans[0], &scp->spc_nchans[1], &scp->spc_nchans[2], &scp->spc_nchans[3]) == 4 ) d98 3 a100 3 else if ( sscanf(tmp_buff, " %d %d %8s %lg %lg %d %d %20s", &bank, &chan, &cal.name, &cal.factor, &cal.offset, &cmin, &cmax, &cal.units) >= 7 ) a101 1 cal.present = strcmp(cal.name, "Unused") ? -1 : 0; d110 1 a110 1 for( i = j = 0; i < SPEC_BANKS; i++ ) d114 1 a114 1 j+= scp->spc_nchans[i]; d117 1 a117 1 if ( (j <= 0) || (n < j) ) d130 1 d149 1 a149 1 voltage -= sccp->offset; d151 2 a152 1 return( voltage / sccp->factor ); d154 2 d169 1 a169 1 Nat16 i, j, n; d176 2 a177 2 n = scp->spc_nchans[0] + scp->spc_nchans[1] + scp->spc_nchans[2] + scp->spc_nchans[3]; a178 3 if ( splen < ((4 * n * sizeof(Nat32)) + 9) ) /* Check size, rtn if bad */ return( SIZE_ERR ); d220 49 @ 2.0 log @Auguest 1992 Deployment. Changed to allow multiple sensors of same type. @ text @d4 1 a4 1 /* $Header: spec.c,v 1.0 92/05/12 18:18:20 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.0 $ */ d15 3 d125 1 a125 1 /* Inputs : Pointer to Spectro data, channel calibration struct */ d129 1 a129 1 decode_value( Byte *p, SpecChanCal *sccp ) d144 2 a145 1 return( (voltage - sccp->offset) / sccp->factor ); d147 2 d165 1 d202 2 a203 1 sdp->spc_chan[i][j].spc_mean = decode_value( spdata + n, sccp ); d205 1 a205 1 sdp->spc_chan[i][j].spc_std = decode_value( spdata + n, sccp ); d207 1 a207 1 sdp->spc_chan[i][j].spc_min = decode_value( spdata + n, sccp ); d209 1 a209 1 sdp->spc_chan[i][j].spc_max = decode_value( spdata + n, sccp ); @ 1.0 log @Initial revision @ text @d4 1 a4 1 /* $Header$ */ d14 4 a17 1 /* $Log$ a29 15 #define CHAN_NAMELEN 8 /* Length of channel name */ #define UNIT_NAMELEN 20 /* Length of units name */ #define CAL_FILE "spectro.cal" typedef struct /************************************/ { /* Calibration structure type */ Int type; /* Channel type field (major num) */ Int chan; /* Channel number (minor number) */ char name[CHAN_NAMELEN]; /* Name of channel */ double factor; /* mulitplicative factor */ double offset; /* subtractive offset */ char units[UNIT_NAMELEN]; /* Units of measure */ } SpecCal; /************************************/ d42 2 a43 2 MLocal Int chans = SPEC_CHANS; /* Number of channels */ MLocal SpecCal cal[SPEC_CHANS]; /* Calibration values */ d53 1 a53 1 init_spec_cal( Void ) d55 1 a55 1 memset( (void *)&cal, sizeof(cal), 0 ); d63 1 a63 1 /* Inputs : Name of file */ d65 2 a66 2 /* Comments : Discards lines until it finds valid calibration record,*/ /* then assumes channels are in order */ d69 1 a69 1 read_spec_cal( char *name ) d72 2 a73 3 Int i, cmin, cmax; SpecCal fc; char buff[256]; d75 3 a77 1 init_spec_cal(); d79 1 a79 6 if ( name == NULL ) fp = fopen( CAL_FILE, "rb" ); else fp = fopen( name, "rb" ); if ( fp == (FILE *)NULL ) d82 1 a82 1 for ( i = 0; (i < SPEC_CHANS) && (fgets(buff, sizeof(buff), fp) != NULL); ) d84 16 a99 4 if ( sscanf(buff, "%d %d %8s %lg %lg %d %d %20s", &cal[i].type, &cal[i].chan, &cal[i].name, &cal[i].factor, &cal[i].offset, &cmin, &cmax, &cal[i].units) >= 7 ) i++; d103 7 a109 1 return( (i > 0) ? OK : ERROR ); d111 5 d122 1 a122 1 /* Inputs : Pointer to Spectro data, channel number */ d126 1 a126 1 decode_value( Byte *p, Int chan ) d141 1 a141 1 return( (voltage - cal[chan].offset) / cal[chan].factor ); d153 1 a153 1 decode_spectro( Byte *spdata, Int splen, SpecDecode *sdp ) d156 1 a156 1 Nat16 i, j; d158 1 d160 1 a160 2 if ( splen < ((SPEC_CHANS * sizeof(Nat32)) + 9) ) return( SIZE_ERR ); /* Check size, rtn if bad */ d162 6 d191 15 a205 11 for ( i = 0; i < SPEC_CHANS; i++ ) { sdp->spc_chan[i].spc_mean = decode_value( spdata + (((4 * i) + 2) * sizeof(Nat32)), i ); sdp->spc_chan[i].spc_std = decode_value( spdata + (((4 * i) + 3) * sizeof(Nat32)), i ); sdp->spc_chan[i].spc_min = decode_value( spdata + (((4 * i) + 4) * sizeof(Nat32)), i ); sdp->spc_chan[i].spc_max = decode_value( spdata + (((4 * i) + 5) * sizeof(Nat32)), i ); } @