RDI_PD0_IO.pl
changeset 40 6a46e9d31106
parent 39 3bddaa514ef5
child 42 80d039881d2c
equal deleted inserted replaced
39:3bddaa514ef5 40:6a46e9d31106
     1 #======================================================================
     1 #======================================================================
     2 #                    R D I _ B B _ R E A D . P L 
     2 #                    R D I _ P D 0 _ I O . P L 
     3 #                    doc: Sat Jan 18 14:54:43 2003
     3 #                    doc: Sat Jan 18 14:54:43 2003
     4 #                    dlm: Tue Aug  8 16:19:45 2017
     4 #                    dlm: Wed Nov 22 11:03:59 2017
     5 #                    (c) 2003 A.M. Thurnherr
     5 #                    (c) 2003 A.M. Thurnherr
     6 #					 uE-Info: 562 21 NIL 0 0 72 0 2 4 NIL ofnI
     6 #					 uE-Info: 156 40 NIL 0 0 72 0 2 4 NIL ofnI
     7 #======================================================================
     7 #======================================================================
     8 	
     8 	
     9 # Read RDI PD0 binary data files (*.[0-9][0-9][0-9])
     9 # Read RDI PD0 binary data files (*.[0-9][0-9][0-9])
    10 	
    10 	
    11 # HISTORY:
    11 # HISTORY:
    89 #	Aug  1, 2017: BUG: minor typo in ocean surveyor code (err check not done?)
    89 #	Aug  1, 2017: BUG: minor typo in ocean surveyor code (err check not done?)
    90 #	Aug  7, 2017: - added LAG_LENGTH
    90 #	Aug  7, 2017: - added LAG_LENGTH
    91 #				  - added SPEED_OF_SOUND to header
    91 #				  - added SPEED_OF_SOUND to header
    92 #	Aug  8, 2017: - replaced croak() by die()
    92 #	Aug  8, 2017: - replaced croak() by die()
    93 #				  - added actual transducer frequencies
    93 #				  - added actual transducer frequencies
       
    94 #	Nov 22, 2017: - BUG: dayNo() and monthLength() clashed with [libconv.pl]
    94 	
    95 	
    95 # FIRMWARE VERSIONS:
    96 # FIRMWARE VERSIONS:
    96 #	It appears that different firmware versions generate different file
    97 #	It appears that different firmware versions generate different file
    97 #	structures. Currently (Sep 2005) these routines have been tested
    98 #	structures. Currently (Sep 2005) these routines have been tested
    98 #	with the following firmware versions (as reported by [listHdr]):
    99 #	with the following firmware versions (as reported by [listHdr]):
   148 #		0x88000100	FSU instrument during A0304 (Firmware 16.12)
   149 #		0x88000100	FSU instrument during A0304 (Firmware 16.12)
   149 #		0x88008180	LDEO uplooker (slave) during NBP0402 (Firmware 16.21)
   150 #		0x88008180	LDEO uplooker (slave) during NBP0402 (Firmware 16.21)
   150 #		0x00008180	LDEO downlooker (master) during NBP0402 (Firmware 16.21)
   151 #		0x00008180	LDEO downlooker (master) during NBP0402 (Firmware 16.21)
   151 #	  According to the manual (January 2001 version) this would, for example,
   152 #	  According to the manual (January 2001 version) this would, for example,
   152 #	  indicate power failures on both FSU and LDEO slave instruments...
   153 #	  indicate power failures on both FSU and LDEO slave instruments...
       
   154 #	- defining the variable "$RDI_PD0_IO::IGNORE_Y2K_CLOCK" before calling &readData()
       
   155 #	  makes the code ignore the Y2K clock and use the old clock instead; this 
       
   156 #	  is used for Dan Torres' KVH system
   153 	
   157 	
   154 # &readData() returns perl obj (ref to anonymous hash) with the following
   158 # &readData() returns perl obj (ref to anonymous hash) with the following
   155 # structure:
   159 # structure:
   156 #
   160 #
   157 #	DATA_SOURCE_ID					scalar		0x7f (Workhorse, also DVL)
   161 #	DATA_SOURCE_ID					scalar		0x7f (Workhorse, also DVL)
   291 	use strict;
   295 	use strict;
   292 	use Time::Local;						# timegm()
   296 	use Time::Local;						# timegm()
   293 	
   297 	
   294 #----------------------------------------------------------------------
   298 #----------------------------------------------------------------------
   295 # Time Conversion Subroutines
   299 # Time Conversion Subroutines
       
   300 #	- prepended with _ to avoid conflicts with [libconv.pl]
   296 #----------------------------------------------------------------------
   301 #----------------------------------------------------------------------
   297 	
   302 	
   298 	sub monthLength($$) 									# of days in month
   303 	sub _monthLength($$) 									# of days in month
   299 	{
   304 	{
   300 		my($Y,$M) = @_;
   305 		my($Y,$M) = @_;
   301 	
   306 	
   302 		return 31 if ($M==1 || $M==3 || $M==5 || $M==7 ||
   307 		return 31 if ($M==1 || $M==3 || $M==5 || $M==7 ||
   303 					  $M==8 || $M==10 || $M==12);
   308 					  $M==8 || $M==10 || $M==12);
   308 		return 29;
   313 		return 29;
   309 	}
   314 	}
   310 	
   315 	
   311 	{ my($epoch,$lM,$lD,$lY,$ldn);							# static scope
   316 	{ my($epoch,$lM,$lD,$lY,$ldn);							# static scope
   312 	
   317 	
   313 	  sub dayNo($$$$$$)
   318 	  sub _dayNo($$$$$$)
   314 	  {
   319 	  {
   315 		  my($Y,$M,$D,$h,$m,$s) = @_;
   320 		  my($Y,$M,$D,$h,$m,$s) = @_;
   316 		  my($dn);
   321 		  my($dn);
   317 	  
   322 	  
   318 		  if ($Y==$lY && $M==$lM && $D==$lD) {				# same day as last samp
   323 		  if ($Y==$lY && $M==$lM && $D==$lD) {				# same day as last samp
   320 		  } else {											# new day
   325 		  } else {											# new day
   321 			  $epoch = $Y unless defined($epoch);			# 1st call
   326 			  $epoch = $Y unless defined($epoch);			# 1st call
   322 			  $lY = $Y; $lM = $M; $lD = $D; 				# store
   327 			  $lY = $Y; $lM = $M; $lD = $D; 				# store
   323 	  
   328 	  
   324 			  for ($dn=0,my($cY)=$epoch; $cY<$Y; $cY++) {	# multiple years
   329 			  for ($dn=0,my($cY)=$epoch; $cY<$Y; $cY++) {	# multiple years
   325 				  $dn += 337 + &monthLength($Y,$M);
   330 				  $dn += 337 + &_monthLength($Y,$M);
   326 			  }
   331 			  }
   327 	  
   332 	  
   328 			  $dn += $D;									# day in month
   333 			  $dn += $D;									# day in month
   329 			  while (--$M > 0) {							# preceding months
   334 			  while (--$M > 0) {							# preceding months
   330 				  $dn += &monthLength($Y,$M);
   335 				  $dn += &_monthLength($Y,$M);
   331 			  }
   336 			  }
   332 	
   337 	
   333 			  $ldn = $dn;									# store
   338 			  $ldn = $dn;									# store
   334 		  }
   339 		  }
   335 		  return $dn + $h/24 + $m/24/60 + $s/24/3600;
   340 		  return $dn + $h/24 + $m/24/60 + $s/24/3600;
   772         } else {
   777         } else {
   773 			$id == 0x0080 ||
   778 			$id == 0x0080 ||
   774 				die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF))));
   779 				die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF))));
   775         }
   780         }
   776 
   781 
   777 		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL
   782 #		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL
   778 			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");
   783 			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");
   779 			(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},
   784 			(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},
   780 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   785 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   781 			 ${$E}[$ens]->{SECONDS},$B4) = unpack('CCCCCCC',$buf);
   786 			 ${$E}[$ens]->{SECONDS},$B4) = unpack('CCCCCCC',$buf);
   782 			${$E}[$ens]->{SECONDS} += $B4/100;
   787 			${$E}[$ens]->{SECONDS} += $B4/100;
   783 			${$E}[$ens]->{YEAR} += (${$E}[$ens]->{YEAR} > 80) ? 1900 : 2000;
   788 			${$E}[$ens]->{YEAR} += (${$E}[$ens]->{YEAR} > 80) ? 1900 : 2000;
   784 		} else {
   789 #		} else {
   785 			sysseek(WBRF,7,1) || die("$WBRcfn: $!");							# use Y2K RTC instead
   790 #			sysseek(WBRF,7,1) || die("$WBRcfn: $!");							# use Y2K RTC instead
   786 		}
   791 #		}
   787 
   792 
   788 		sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!");
   793 		sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!");
   789 		$ensNo += unpack('C',$buf) << 16;
   794 		$ensNo += unpack('C',$buf) << 16;
   790 		${$E}[$ens]->{NUMBER} = $ensNo;
   795 		${$E}[$ens]->{NUMBER} = $ensNo;
   791 		
   796 		
   827 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60;
   832 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60;
   828 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100;
   833 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100;
   829 		${$E}[$ens]->{PITCH_STDDEV} /= 10;
   834 		${$E}[$ens]->{PITCH_STDDEV} /= 10;
   830 		${$E}[$ens]->{ROLL_STDDEV} /= 10;
   835 		${$E}[$ens]->{ROLL_STDDEV} /= 10;
   831 
   836 
   832 		if ($fixed_leader_bytes==53 || $fixed_leader_bytes==59) {			# Workhorse instruments
   837 		if (($fixed_leader_bytes==53 || $fixed_leader_bytes==59) && 		# Workhorse instruments
       
   838 			!defined($RDI_PD0_IO::IGNORE_Y2K_CLOCK)) {
   833 			sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!");
   839 			sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!");
   834 			(${$E}[$ens]->{ERROR_STATUS_WORD},
   840 			(${$E}[$ens]->{ERROR_STATUS_WORD},
   835 		 	 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV},
   841 		 	 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV},
   836 			 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH},
   842 			 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH},
   837 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   843 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   864 		${$E}[$ens]->{TIME}
   870 		${$E}[$ens]->{TIME}
   865 			= sprintf("%02d:%02d:%05.02f",${$E}[$ens]->{HOUR},
   871 			= sprintf("%02d:%02d:%05.02f",${$E}[$ens]->{HOUR},
   866 										  ${$E}[$ens]->{MINUTE},
   872 										  ${$E}[$ens]->{MINUTE},
   867 									 	  ${$E}[$ens]->{SECONDS});
   873 									 	  ${$E}[$ens]->{SECONDS});
   868 		${$E}[$ens]->{DAYNO}
   874 		${$E}[$ens]->{DAYNO}
   869 			= &dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY},
   875 			= &_dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY},
   870 					 ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECONDS});
   876 					  ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECONDS});
   871 
   877 
   872 		# when analyzing an STA file from an OS75 SADCP (Poseidion),
   878 		# when analyzing an STA file from an OS75 SADCP (Poseidion),
   873 		# I noticed that there is no time information. This causes
   879 		# I noticed that there is no time information. This causes
   874 		# timegm to bomb. 
   880 		# timegm to bomb. 
   875 		if (${$E}[$ens]->{MONTH} == 0) {					# no time info
   881 		if (${$E}[$ens]->{MONTH} == 0) {					# no time info