head 2.9; access ; symbols ; locks ; strict; comment @ * @; 2.9 date 98.08.24.13.45.53; author bobh; state Exp; branches ; next 2.8; 2.8 date 98.03.17.11.11.39; author bobh; state Exp; branches ; next 2.7; 2.7 date 97.09.09.09.52.45; author bobh; state Exp; branches ; next 2.4; 2.4 date 94.01.21.14.36.17; author hebo; state Exp; branches ; next 1.3; 1.3 date 94.01.17.11.07.26; author hebo; state Exp; branches ; next 1.2; 1.2 date 92.09.24.10.20.30; author hebo; state Exp; branches ; next 1.1; 1.1 date 92.09.12.10.10.14; author hebo; state Exp; branches ; next 1.0; 1.0 date 92.02.25.10.46.57; author hebo; state Rel; branches ; next ; desc @Routines to decode ATLAS data for decode.c and extract.c @ 2.9 log @Archiving sources after M2/M3 & Eqpac deployments of 1998 @ text @/****************************************************************************/ /* Copyright 1991 MBARI */ /****************************************************************************/ /* $Header: atlas.c,v 2.8 98/03/17 11:11:39 bobh Exp $ */ /* Summary : ATLAS decode routines for decode.c, extract.c */ /* Filename : atlas.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 2.8 $ */ /* Created : 01/24/92 */ /****************************************************************************/ /* Modification History: */ /* 24jan91 rah - created */ /* $Log: atlas.c,v $ * Revision 2.8 98/03/17 11:11:39 11:11:39 bobh (Bob Herlien) * Archiving sources prior to porting to DOS/Windows * * Revision 2.7 97/09/09 09:52:45 09:52:45 bobh (Bob Herlien) * Archiving various changes * * Revision 2.4 94/01/21 14:36:17 14:36:17 hebo (Bob Herlien) * Added support for date ranges in cfg file * * Revision 1.3 94/01/17 11:07:26 11:07:26 hebo (Bob Herlien) * Misc changes * * Revision 1.2 92/09/24 10:20:30 10:20:30 hebo (Bob Herlien) * Added check for broken sensors, write 0.0 result. This due to M2 broken 500m * * Revision 1.1 92/09/12 10:10:14 10:10:14 hebo (Bob Herlien) * Corrected problem with wind direction due to checking bounds before atan2() * * Revision 1.0 92/02/25 10:46:57 10:46:57 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 #define CAL_FILE "cable01a.coef" /* ATLAS calibration file */ #define RAWSPEED_CNT 0.192 /* .192 m/s for each count of raw spd*/ /********************************/ /* External Functions */ /********************************/ Extern Nat16 getIntelword( Byte *p ); /* Get word in Intel format */ /************************************************************************/ /* Function : init_pod_cal */ /* Purpose : Initialize one ATLAS pod calibration */ /* Inputs : Ptr to pod to init */ /* Outputs : None */ /************************************************************************/ Void init_pod_cal( ACal *p ) { p->a = (double)0.0; p->b = (double)1.0; p->c = (double)0.0; p->d = (double)0.0; p->e = (double)1.0; } /* init_pod_cal() */ /************************************************************************/ /* Function : init_atlas_cal */ /* Purpose : Initialize ATLAS calibration */ /* Inputs : Cal struct ptr */ /* Outputs : none */ /************************************************************************/ Void init_atlas_cal( AtlasCal *cp ) { Int32 i; init_pod_cal( &cp->ac_air ); init_pod_cal( &cp->ac_sst ); for ( i = 0; i < 10; i++ ) init_pod_cal( &cp->ac_temp[i] ); init_pod_cal( &cp->ac_rh ); init_pod_cal( &cp->ac_wind ); cp->ac_wind.a = (double)1.0; cp->ac_wind.b = (double)0.0; cp->ac_wind.c = (double)1.0; } /* init_atlas_cal() */ /************************************************************************/ /* Function : read_atlas_cal */ /* Purpose : Read ATLAS calibration file */ /* Inputs : Name of file, ptr to calibr struct */ /* Outputs : OK or ERROR */ /* Comments : From ATLAS documention, sensor type field is: */ /* 1 Original temperature sensor (old cable, RP/LP air and SST)*/ /* 2 Pressure */ /* 3 Wind */ /* 4 Conductivity */ /* 5 New-style temperature sensor calibration */ /* 6 Air (for HP and Standard ATLAS) */ /* 7 SST (for HP tube) */ /* 8 Relative humidity sensor */ /************************************************************************/ Status read_atlas_cal( char *name, AtlasCal *cp ) { FILE *fp; Int32 t, p; ACal fc; char buff[256]; char id[16]; init_atlas_cal( cp ); if ( name == NULL ) fp = fopen( CAL_FILE, "rb" ); else fp = fopen( name, "rb" ); if ( fp == (FILE *)NULL ) return( ERROR ); t = p = 0; while ( fgets(buff, sizeof(buff), fp) != NULL ) { init_pod_cal( &fc ); if ( sscanf(buff, "%1d %d %4c %lg %lg %lg %lg %lg", &fc.pod_type, &fc.ident, id, &fc.a, &fc.b, &fc.c, &fc.d, &fc.e) >= 6 ) { switch( fc.pod_type ) { case 1: case 5: if ( t < TEMPS ) memcpy( (void *)&(cp->ac_temp[t++]), (void *)&fc, sizeof(fc) ); break; case 2: if ( p < PRESS ) memcpy( (void *)&(cp->ac_press[p++]), (void *)&fc, sizeof(fc) ); break; case 3: memcpy( (void *)&(cp->ac_wind), (void *)&fc, sizeof(fc) ); break; case 6: memcpy( (void *)&(cp->ac_air), (void *)&fc, sizeof(fc) ); break; case 7: memcpy( (void *)&(cp->ac_sst), (void *)&fc, sizeof(fc) ); break; } } } fclose( fp ); return( OK ); } /* read_atlas_cal() */ /************************************************************************/ /* Function : decode_temp */ /* Purpose : Decode ATLAS temperature */ /* Inputs : Count from temp pod, ptr to ACal struct */ /* Outputs : Double-precision temperature, or 0.0 if error */ /************************************************************************/ double decode_temp( Nat16 count, ACal *cp ) { double r, logr, temp; if ( count < 0x1000 ) /* Check for broken sensor*/ return( (double)0.0 ); switch( cp->pod_type ) { case 1: /* Original pod, incl. orig SST */ r = 7.68e08 / ((2.525 * (double)count) - 7680.0); break; case 5: /* Self-calibrating temp pod */ r = 3.072e08 / (double)count; break; case 7: /* HP SST */ r = ((4.0e08/(double)count) * cp->e) + cp->d; break; default: return( (double)0.0 ); } logr = log10(r); temp = 1.0 / (cp->a + (cp->b * logr) + (cp->c * logr * logr * logr)) - 273.15; if ( temp < 0.0 ) /* More error checking */ return( (double)0.0 ); return( temp ); } /* decode_temp() */ /************************************************************************/ /* Function : decode_atlas */ /* Purpose : Decode ATLAS information */ /* Inputs : Pointer to ATLAS data, length, ptr to return struct */ /* Outputs : OK, SIZE_ERR or CHKSUM_ERR */ /************************************************************************/ Status decode_atlas( Byte *atdata, Int32 atlen, AtlasDecode *adp, AtlasCal *acp ) { double r, u, v; Int32 i; Int32 at_words; Nat16 chksum; signed char cu, cv; union { Atlas ata; AtlasLong atl; Nat16 atn[ATLAS_LONG]; } atlas; at_words = atlen / sizeof(Nat16); if ( (at_words != ATLAS_WORDS) && (at_words != ATLAS_LONG) ) return( SIZE_ERR ); /* Check # words, rtn if bad */ chksum = 0; /* Init checksum */ for ( i = 0; i < at_words - 1; i++ ) { /* Translate Intel word type */ atlas.atn[i] = getIntelword(atdata + i * sizeof(Nat16)); chksum += atlas.atn[i]; /* Compute checksum */ } if ( chksum != getIntelword(atdata + i * sizeof(Nat16)) ) return( CHKSUM_ERR ); /* Return error if bad chksum*/ /* Get time of ATLAS data, convert to ddd.fff */ adp->atd_time = (double)atlas.ata.at_time / 128.0; adp->atd_time += fmod(adp->atd_time, 1.0) / 3.0; r = (5.0 * (double)atlas.ata.at_air / 1024.0 * acp->ac_air.e) + acp->ac_air.d; /* Calc voltage of air temp */ adp->atd_air = (r * acp->ac_air.b) + acp->ac_air.a; /* Calc air temp from voltage*/ adp->atd_sst = decode_temp( atlas.ata.at_sst, &acp->ac_sst ); for ( i = 0; i < TEMPS; i++ ) /* Calculate temp of each temp pod */ adp->atd_temp[i] = decode_temp(atlas.ata.at_temp[i], &acp->ac_temp[i]); for ( i = 0; i < PRESS; i++ ) /* Calculate pressure of each pod */ { if ( atlas.ata.at_press[i] == 0 ) /* Check for broken sensor*/ adp->atd_press[i] = 0.0; else adp->atd_press[i] = 0.6897 * (((76800.0 / atlas.ata.at_press[i]) * acp->ac_press[i].b) + acp->ac_press[i].a); } /* Calculate relative humidity */ adp->atd_rh = (((double)atlas.ata.at_rh / 2.56) * acp->ac_rh.b) + acp->ac_rh.a; /* Calculate wind speed and direction */ cu = (signed char)(atlas.ata.at_wind >> 8); cv = (signed char)(atlas.ata.at_wind & 0xff); u = acp->ac_wind.a * (double)cu; v = acp->ac_wind.a * (double)cv; adp->atd_windspd = (sqrt(u*u + v*v) * acp->ac_wind.e) + acp->ac_wind.d; if ( u == 0 ) adp->atd_winddir = 0.0; else adp->atd_winddir = 180.0/PI * atan2(u,v); adp->atd_winddir += acp->ac_wind.b; while ( adp->atd_winddir < 0.0 ) adp->atd_winddir += 360.0; adp->atd_windu = adp->atd_windspd * sin(adp->atd_winddir * PI / 180.0); adp->atd_windv = adp->atd_windspd * cos(adp->atd_winddir * PI / 180.0); adp->atd_compass = (double)(atlas.atl.at_covane >> 8) * 360./256.; adp->atd_vane = (double)(atlas.atl.at_covane & 0xff) * 360./256.; adp->atd_rawdir = adp->atd_compass + adp->atd_vane + acp->ac_wind.b + 180.; while ( adp->atd_rawdir >= 360.0 ) adp->atd_rawdir -= 360.0; adp->atd_rawspeed = (double)(atlas.atl.at_windspeed >> 8) * RAWSPEED_CNT; return( OK ); } /* decode_atlas() */ @ 2.8 log @Archiving sources prior to porting to DOS/Windows @ text @d4 1 a4 1 /* $Header: atlas.c,v 2.7 97/09/09 09:52:45 bobh Exp $ */ d9 1 a9 1 /* $Revision: 2.7 $ */ d15 3 d40 2 a41 2 #include /* MBARI type definitions */ #include /* MBARI constants */ d293 4 a296 1 adp->atd_winddir = 180.0/PI * atan2(u,v); @ 2.7 log @Archiving various changes @ text @d4 1 a4 1 /* $Header: atlas.c,v 2.4 94/01/21 14:36:17 hebo Exp $ */ d9 1 a9 1 /* $Revision: 2.4 $ */ d15 3 @ 2.4 log @Added support for date ranges in cfg file @ text @d4 1 a4 1 /* $Header: atlas.c,v 1.3 94/01/17 11:07:26 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.3 $ */ d15 3 d281 2 a282 2 cu = atlas.ata.at_wind >> 8; cv = atlas.ata.at_wind & 0xff; @ 1.3 log @Misc changes @ text @d4 1 a4 1 /* $Header: atlas.c,v 1.2 92/09/24 10:20:30 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.2 $ */ d15 3 a41 10 typedef struct /************************************/ { /* Calibration structure type */ Int32 pod_type; /* Pod type */ Int32 ident; /* Pod ID number */ double a; /* A calibration coefficient */ double b; /* B calibration coefficient */ double c; /* C calibration coefficient */ double d; /* D calibration coefficient */ double e; /* E calibration coefficient */ } Cal; /************************************/ a42 11 typedef struct /************************************/ { /* Struct for ATLAS calibration */ Cal ac_air; /* Air temp calibration */ Cal ac_sst; /* Sea surface temp calibration */ Cal ac_temp[TEMPS]; /* Temperature pod calibrations */ Cal ac_press[PRESS]; /* Pressure pod calibrations */ Cal ac_rh; /* Relative humidity calibration */ Cal ac_wind; /* Wind calibration */ } AtlasCal; /************************************/ a49 7 /********************************/ /* Module Local Data */ /********************************/ MLocal AtlasCal cal; /* ATLAS calibration */ d57 1 a57 1 init_pod_cal( Cal *p ) d71 1 a71 1 /* Inputs : None */ d75 1 a75 1 init_atlas_cal( Void ) d79 2 a80 2 init_pod_cal( &cal.ac_air ); init_pod_cal( &cal.ac_sst ); d82 6 a87 6 init_pod_cal( &cal.ac_temp[i] ); init_pod_cal( &cal.ac_rh ); init_pod_cal( &cal.ac_wind ); cal.ac_wind.a = (double)1.0; cal.ac_wind.b = (double)0.0; cal.ac_wind.c = (double)1.0; d95 1 a95 1 /* Inputs : Name of file */ d108 1 a108 1 read_atlas_cal( char *name ) d112 1 a112 1 Cal fc; d116 1 a116 1 init_atlas_cal(); d139 1 a139 1 memcpy( (void *)&(cal.ac_temp[t++]), d145 1 a145 1 memcpy( (void *)&(cal.ac_press[p++]), d150 1 a150 1 memcpy( (void *)&(cal.ac_wind), (void *)&fc, sizeof(fc) ); d154 1 a154 1 memcpy( (void *)&(cal.ac_air), (void *)&fc, sizeof(fc) ); d158 1 a158 1 memcpy( (void *)&(cal.ac_sst), (void *)&fc, sizeof(fc) ); d173 1 a173 1 /* Inputs : Count from temp pod, ptr to Cal struct */ d177 1 a177 1 decode_temp( Nat16 count, Cal *cp ) d222 1 a222 1 decode_atlas( Byte *atdata, Int32 atlen, AtlasDecode *adp ) d254 3 a256 3 r = (5.0 * (double)atlas.ata.at_air / 1024.0 * cal.ac_air.e) + cal.ac_air.d; /* Calc voltage of air temp */ adp->atd_air = (r * cal.ac_air.b) + cal.ac_air.a; d259 1 a259 1 adp->atd_sst = decode_temp( atlas.ata.at_sst, &cal.ac_sst ); d262 1 a262 1 adp->atd_temp[i] = decode_temp( atlas.ata.at_temp[i], &cal.ac_temp[i] ); d271 1 a271 1 * cal.ac_press[i].b) + cal.ac_press[i].a); d274 2 a275 2 adp->atd_rh = (((double)atlas.ata.at_rh / 2.56) * cal.ac_rh.b) + cal.ac_rh.a; d280 3 a282 3 u = cal.ac_wind.a * (double)cu; v = cal.ac_wind.a * (double)cv; adp->atd_windspd = (sqrt(u*u + v*v) * cal.ac_wind.e) + cal.ac_wind.d; d285 1 a285 1 adp->atd_winddir += cal.ac_wind.b; d294 1 a294 1 adp->atd_rawdir = adp->atd_compass + adp->atd_vane + cal.ac_wind.b + 180.; @ 1.2 log @Added check for broken sensors, write 0.0 result. This due to M2 broken 500m @ text @d4 1 a4 1 /* $Header: atlas.c,v 1.1 92/09/12 10:10:14 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.1 $ */ d15 3 d37 1 d41 2 d102 1 a102 1 Int i; d127 1 a127 1 /* 5 New-style temperature sensor calibration) */ d129 1 a129 1 /* 7 SST (for HP and Standard ATLAS) */ d136 1 a136 1 Int type, ident, t, p; d139 1 a139 1 char id1[16], id2[4]; d156 2 a157 2 if ( sscanf(buff, "%1d %d %4c %lg %lg %lg %lg %lg", &type, &ident, id1, &fc.a, &fc.b, &fc.c, &fc.d, &fc.e) >= 6 ) d159 1 a159 3 id1[4] = '\0'; sscanf( id1, "%1s", id2 ); switch( toupper(id2[0]) ) d161 5 a165 2 case 'A': memcpy( (void *)&(cal.ac_air), (void *)&fc, sizeof(fc) ); d168 1 a168 5 case 'S': memcpy( (void *)&(cal.ac_sst), (void *)&fc, sizeof(fc) ); break; case 'P': d174 2 a175 4 case 'T': if ( t < TEMPS ) memcpy( (void *)&(cal.ac_temp[t++]), (void *)&fc, sizeof(fc) ); d178 2 a179 2 case 'W': memcpy( (void *)&(cal.ac_wind), (void *)&fc, sizeof(fc) ); d181 4 d196 45 d247 1 a247 1 decode_atlas( Byte *atdata, Int atlen, AtlasDecode *adp ) d249 3 a251 2 double r, logr, u, v; Int i; d256 3 a258 2 Atlas ata; Nat16 atn[ATLAS_WORDS]; d261 2 a262 1 if ( atlen < (ATLAS_WORDS * sizeof(Nat16)) ) d266 1 a266 1 for ( i = 0; i < ATLAS_WORDS-1; i++ ) d284 1 a284 16 /* Non-HP style sea-surface temp (SST) cable */ /* r = (7.68e08 / (2.525 * (double)(atlas.ata.at_sst) - 7680.0) * cal.ac_sst.e) + cal.ac_sst.d; */ /* Calculate sea-surface temp (SST) */ if ( atlas.ata.at_sst < 0x1000 ) /* Check for broken sensor*/ adp->atd_sst = 0.0; else { r = ((4.0e08 / (double)atlas.ata.at_sst) * cal.ac_sst.e) + cal.ac_sst.d; logr = log10(r); adp->atd_sst = 1.0 / (cal.ac_sst.a + (cal.ac_sst.b * logr) + (cal.ac_sst.c * logr * logr * logr)) - 273.15; } d286 5 a290 1 for ( i = 0; i < 10; i++ ) /* Calculate temp of each of 10 temp pods */ d292 2 a293 2 if ( atlas.ata.at_temp[i] < 0x1000 ) /* Check for broken sensor*/ adp->atd_temp[i] = 0.0; d295 2 a296 9 { r = 7.68e08 / ((2.525 * (double)atlas.ata.at_temp[i]) - 7680.0); logr = log10(r); adp->atd_temp[i] = 1.0 / (cal.ac_temp[i].a + (cal.ac_temp[i].b * logr) + (cal.ac_temp[i].c * logr * logr * logr)) - 273.15; } if ( adp->atd_temp[i] < 0.0 ) /* More error checking */ adp->atd_temp[i] = 0.0; a297 6 for ( i = 0; i < 2; i++ ) /* Calculate pressure of each of 2 pods */ { adp->atd_press[i] = 0.6897 * (((76800.0 / atlas.ata.at_press[i]) * cal.ac_press[i].b) + cal.ac_press[i].a); } d316 8 @ 1.1 log @Corrected problem with wind direction due to checking bounds before atan2() @ text @d4 1 a4 1 /* $Header: atlas.c,v 1.0 92/02/25 10:46:57 hebo Rel $ */ d9 1 a9 1 /* $Revision: 1.0 $ */ d15 3 d237 8 a244 3 r = ((4.0e08 / (double)atlas.ata.at_sst) * cal.ac_sst.e) + cal.ac_sst.d; logr = log10(r); adp->atd_sst = 1.0 / (cal.ac_sst.a + (cal.ac_sst.b * logr) d246 1 d250 7 a256 3 r = 7.68e08 / ((2.525 * (double)atlas.ata.at_temp[i]) - 7680.0); logr = log10(r); adp->atd_temp[i] = 1.0 / (cal.ac_temp[i].a d259 3 @ 1.0 log @Initial revision @ text @d4 1 a4 1 /* $Header: atlas.c,v 1.1 92/02/25 10:45:31 hebo Exp $ */ d9 1 a9 1 /* $Revision: 1.1 $ */ d15 1 a15 1 * Revision 1.1 92/02/25 10:45:31 10:45:31 hebo (Bob Herlien) d263 2 a264 4 if ( fabs(v) < 0.0001 ) adp->atd_winddir = (u > 0.0) ? 0 : 180; else adp->atd_winddir = 180.0/PI * atan2(u,v); @