RDI_PD0_IO.pl
changeset 42 80d039881d2c
parent 40 6a46e9d31106
child 43 b63fa355644c
child 44 b7654ea68af6
--- a/RDI_PD0_IO.pl
+++ b/RDI_PD0_IO.pl
@@ -1,9 +1,9 @@
 #======================================================================
 #                    R D I _ P D 0 _ I O . P L 
 #                    doc: Sat Jan 18 14:54:43 2003
-#                    dlm: Wed Nov 22 11:03:59 2017
+#                    dlm: Sat Dec 23 16:03:46 2017
 #                    (c) 2003 A.M. Thurnherr
-#					 uE-Info: 156 40 NIL 0 0 72 0 2 4 NIL ofnI
+#					 uE-Info: 1184 24 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 	
 # Read RDI PD0 binary data files (*.[0-9][0-9][0-9])
@@ -92,6 +92,11 @@
 #	Aug  8, 2017: - replaced croak() by die()
 #				  - added actual transducer frequencies
 #	Nov 22, 2017: - BUG: dayNo() and monthLength() clashed with [libconv.pl]
+#				  - added support for RDI_PD0_IO::IGNORE_Y2K_CLOCK
+#	Dec  7, 2017: - added suppress_error to readHeader()
+#	Dec 23, 2017: - BUG: could no longer read Anslope II raw files
+#				  - added support for patching ADCP time data
+#				  - added support for RDI_PD0_IO::OVERRIDE_Y2K_CLOCK
 	
 # FIRMWARE VERSIONS:
 #	It appears that different firmware versions generate different file
@@ -391,10 +396,16 @@
 	
 sub readHeader(@)
 {
-	my($fn,$dta) = @_;
+	my($fn,$dta,$suppress_error) = @_;
 	$WBRcfn = $fn;
 	open(WBRF,$WBRcfn) || die("$WBRcfn: $!");
-	WBRhdr($dta) || die("$WBRcfn: Insufficient data\n");
+	if (WBRhdr($dta)) {
+		return 1;
+    } elsif ($suppress_error) {
+		return undef;
+    } else {
+		die("$WBRcfn: Insufficient data\n");
+    }
 }
 
 sub WBRhdr(@)
@@ -779,8 +790,8 @@
 				die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF))));
         }
 
-#		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL
-			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");
+#		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL (if DISABLED!)
+			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");					# always read pre-Y2K clock
 			(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},
 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
 			 ${$E}[$ens]->{SECONDS},$B4) = unpack('CCCCCCC',$buf);
@@ -852,7 +863,9 @@
 
 # 		THE FOLLOWING LINE OF CODE WAS REMOVED 7/30/2016 WHEN I ADDED A POP
 #		TO THE last STATEMENT ABOVE (INCOMPLETE ENSEMBLE)
-#		pop(@{$E}),last if (${$E}[$ens]->{MONTH}>12);						# 10/15/2014; IWISE#145 UL ???
+#		THE LINE WAS RE-ENABLED ON 12/23/2017 BECAUSE OTHERWISE THE
+#		ANSLOPE II PROFILES IN THE HOWTO CANNOT BE READ.
+		pop(@{$E}),last if (${$E}[$ens]->{MONTH}>12);						# 10/15/2014; IWISE#145 UL ???
 
 		if ($fixed_leader_bytes == 58) {									# Explorer DVL
 			sysread(WBRF,$buf,14) == 14 || die("$WBRcfn: $!");
@@ -882,6 +895,7 @@
 			${$E}[$ens]->{UNIX_TIME} = 0;
 			${$E}[$ens]->{SECNO} = 0;
         } else {
+#			print(STDERR "\n[$ens]->${$E}[$ens]->{MINUTE}:${$E}[$ens]->{HOUR},${$E}[$ens]->{DAY},${$E}[$ens]->{MONTH},${$E}[$ens]->{YEAR}-<\n");
 			${$E}[$ens]->{UNIX_TIME}
 				= timegm(0,${$E}[$ens]->{MINUTE},
 						   ${$E}[$ens]->{HOUR},
@@ -1157,30 +1171,56 @@
 		sysseek(WBPF,$start_ens+$WBPofs[0]+25,0) || die("$WBPcfn: $!");
 		syswrite(WBPF,$buf,1) == 1 || die("$WBPcfn: $!");
 
-		#------------------------------
-		# Variable Leader
-		#------------------------------
+		#----------------------------------------------------------------------
+		# Variable Leader #1
+		#	- if $RDI_PD0_IO::OVERRIDE_Y2K_CLOCK is set, the data from the pre-Y2K
+		#	  clock are used to override the ADCP clock values; this allows
+		#	  a better time to be recorded by the data acquisition system
+		#	  without overwriting the main instrument clock data
+		#----------------------------------------------------------------------
 
-		sysseek(WBPF,$start_ens+$WBPofs[1]+14,0) || die("$WBPcfn: $!");		# jump to SPEED_OF_SOUND
+		if ($RDI_PD0_IO::OVERRIDE_Y2K_CLOCK) {
+			sysseek(WBPF,$start_ens+$WBPofs[1]+4,0) || die("$WBPcfn: $!");		# jump to RTC_YEAR
+			sysread(WBPF,$buf,7) == 7 || die("$WBRcfn: $!");					# read pre-Y2K clock
+			($dta->{ENSEMBLE}[$ens]->{YEAR},
+			 $dta->{ENSEMBLE}[$ens]->{MONTH},
+			 $dta->{ENSEMBLE}[$ens]->{DAY},
+			 $dta->{ENSEMBLE}[$ens]->{HOUR},
+			 $dta->{ENSEMBLE}[$ens]->{MINUTE},
+			 $dta->{ENSEMBLE}[$ens]->{SECONDS},$B4) =
+				unpack('CCCCCCC',$buf);
+			$dta->{ENSEMBLE}[$ens]->{SECONDS} += $B4/100;
+			$dta->{ENSEMBLE}[$ens]->{YEAR} += ($dta->{ENSEMBLE}[$ens]->{YEAR} > 80) ? 1900 : 2000;
+		}
+		
+		#----------------------------------------------------------------------
+		# Variable Leader #2
+		#	- patch everything from SPEED_OF_SOUND to TEMPERATURE
+		# 	- at one stage, IMP allowed for missing values in pitch/roll and heading;
+		#	  on 12/23/2017 the corresponding code was disabled (replaced by assertion)
+		#----------------------------------------------------------------------
+
+		sysseek(WBPF,$start_ens+$WBPofs[1]+14,0) || die("$WBPcfn: $!");			# jump to SPEED_OF_SOUND
 		
 		$dta->{ENSEMBLE}[$ens]->{XDUCER_DEPTH} = _round($dta->{ENSEMBLE}[$ens]->{XDUCER_DEPTH}*10);
 
-		#---------------------------------
-		# NB: IMP allows for missing value
-		#---------------------------------
+#		$dta->{ENSEMBLE}[$ens]->{HEADING} = defined($dta->{ENSEMBLE}[$ens]->{HEADING})
+#							   ? _round($dta->{ENSEMBLE}[$ens]->{HEADING}*100)
+#							   : 0xF000;
+#		$dta->{ENSEMBLE}[$ens]->{PITCH} = defined($dta->{ENSEMBLE}[$ens]->{PITCH})
+#							 ? unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{PITCH}*100)))
+#							 : 0x8000;
+#		$dta->{ENSEMBLE}[$ens]->{ROLL} = defined($dta->{ENSEMBLE}[$ens]->{ROLL})
+#						    ? unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{ROLL}*100)))
+#						    : 0x8000;
 
-		$dta->{ENSEMBLE}[$ens]->{HEADING} = defined($dta->{ENSEMBLE}[$ens]->{HEADING})
-							   ? _round($dta->{ENSEMBLE}[$ens]->{HEADING}*100)
-							   : 0xF000;
-		$dta->{ENSEMBLE}[$ens]->{PITCH} = defined($dta->{ENSEMBLE}[$ens]->{PITCH})
-							 ? unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{PITCH}*100)))
-							 : 0x8000;
-		$dta->{ENSEMBLE}[$ens]->{ROLL} = defined($dta->{ENSEMBLE}[$ens]->{ROLL})
-						    ? unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{ROLL}*100)))
-						    : 0x8000;
-
-		$dta->{ENSEMBLE}[$ens]->{TEMPERATURE} =
-			unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{TEMPERATURE}*100)));
+		croak("$0: assertion failed") unless defined($dta->{ENSEMBLE}[$ens]->{HEADING}) &&
+											 defined($dta->{ENSEMBLE}[$ens]->{PITCH}) &&
+											 defined($dta->{ENSEMBLE}[$ens]->{ROLL});
+		$dta->{ENSEMBLE}[$ens]->{HEADING} 	  = _round($dta->{ENSEMBLE}[$ens]->{HEADING}*100);
+		$dta->{ENSEMBLE}[$ens]->{PITCH}   	  = unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{PITCH}*100)));
+		$dta->{ENSEMBLE}[$ens]->{ROLL} 	  	  = unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{ROLL}*100)));
+		$dta->{ENSEMBLE}[$ens]->{TEMPERATURE} = unpack('S',pack('s',_round($dta->{ENSEMBLE}[$ens]->{TEMPERATURE}*100)));
 
 		$buf = pack('vvvvvvv',
 			 $dta->{ENSEMBLE}[$ens]->{SPEED_OF_SOUND},
@@ -1192,6 +1232,23 @@
 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
 
 
+		#----------------------------------------------------------------------
+		# Variable Leader #3
+		#	- patch Y2K RTC
+		#----------------------------------------------------------------------
+
+		sysseek(WBPF,$start_ens+$WBPofs[1]+57,0) || die("$WBPcfn: $!");			# jump to RTC_CENTURY
+
+		my($century) 	= int($dta->{ENSEMBLE}[$ens]->{YEAR} / 100);
+		my($year)	 	=     $dta->{ENSEMBLE}[$ens]->{YEAR} % 100;
+		my($seconds) 	= int($dta->{ENSEMBLE}[$ens]->{SECONDS});
+		my($hundredths) = 100 * ($dta->{ENSEMBLE}[$ens]->{SECONDS} - $seconds);
+		$buf = pack('CCCCCCCC',$century,$year,$dta->{ENSEMBLE}[$ens]->{MONTH},
+							   $dta->{ENSEMBLE}[$ens]->{DAY},$dta->{ENSEMBLE}[$ens]->{HOUR},
+							   $dta->{ENSEMBLE}[$ens]->{MINUTE},$seconds,$hundredths);
+		my($nw) = syswrite(WBPF,$buf,8);
+		$nw == 8 || die("$WBPcfn: $nw bytes written ($!)");
+		
 		#--------------------
 		# Velocity Data
 		#--------------------