RDI_PD0_IO.pl
changeset 18 bb7bb9f83db9
parent 14 8c79b38a7086
child 21 0b5bbe60131c
equal deleted inserted replaced
17:591779f6df30 18:bb7bb9f83db9
     1 #======================================================================
     1 #======================================================================
     2 #                    R D I _ P D 0 _ I O . 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 Nov 26 01:29:26 2013
     4 #                    dlm: Wed May  7 10:41:18 2014
     5 #                    (c) 2003 A.M. Thurnherr
     5 #                    (c) 2003 A.M. Thurnherr
     6 #                    uE-Info: 873 10 NIL 0 0 72 74 2 4 NIL ofnI
     6 #                    uE-Info: 827 0 NIL 0 0 72 74 2 4 NIL ofnI
     7 #======================================================================
     7 #======================================================================
     8 
     8 
     9 # Read RDI BroadBand Binary Data Files (*.[0-9][0-9][0-9])
     9 # Read RDI BroadBand Binary Data Files (*.[0-9][0-9][0-9])
    10 
    10 
    11 # HISTORY:
    11 # HISTORY:
    52 #	Apr 29, 2013: - changed semantics to assume EOF when unexpected number of data types
    52 #	Apr 29, 2013: - changed semantics to assume EOF when unexpected number of data types
    53 #					are present in an ensemble
    53 #					are present in an ensemble
    54 #	Nov 25, 2013: - renamed from [RDI_BB_Read.pl]
    54 #	Nov 25, 2013: - renamed from [RDI_BB_Read.pl]
    55 #				  - begin implementing WBWens()
    55 #				  - begin implementing WBWens()
    56 #				  - checkEnsemble() expunged
    56 #				  - checkEnsemble() expunged
       
    57 #	Mar  3, 2014: - BUG: WBPens() did not handle incomple ensembles at EOF correctly
       
    58 #	Mar  4, 2014: - added support for DATA_SOURCE_ID
       
    59 #	Apr 24, 2014: - added debug statements to log %-GOOD values
       
    60 #	May  6, 2014: - loosened input format checks
       
    61 #	May  7, 2014: - removed BT_present flag
    57 
    62 
    58 # FIRMWARE VERSIONS:
    63 # FIRMWARE VERSIONS:
    59 #	It appears that different firmware versions generate different file
    64 #	It appears that different firmware versions generate different file
    60 #	structures. Currently (Sep 2005) these routines have been tested
    65 #	structures. Currently (Sep 2005) these routines have been tested
    61 #	with the following firmware versions (as reported by [listHdr]):
    66 #	with the following firmware versions (as reported by [listHdr]):
    64 #------------------------------------------------------------
    69 #------------------------------------------------------------
    65 #	05.52	BB150 (1)				UH 		CLIVAR/P16S 42
    70 #	05.52	BB150 (1)				UH 		CLIVAR/P16S 42
    66 #	16.12	WH300 (1)				FSU 	A0304		53
    71 #	16.12	WH300 (1)				FSU 	A0304		53
    67 #	16.21	WH300 (1)				LDEO 	NBP0402		53
    72 #	16.21	WH300 (1)				LDEO 	NBP0402		53
    68 #	16.27	WH300 (2)				Nash 	?			59
    73 #	16.27	WH300 (2)				Nash 	?			59
       
    74 
       
    75 # PD0 IMP FILE FORMAT EXTENSIONS:
       
    76 #	- DATA_SOURCE_ID = 0xA0 | PATCHED_MASK (vs. 0x7F for TRDI PD0 files)
       
    77 #		PATCHED_MASK & 0x04:	pitch value has been patched
       
    78 #		PATCHED_MASK & 0x02:	roll value has been patched
       
    79 #		PATCHED_MASK & 0x01:	heading value has been patched
       
    80 #	- PITCH & ROLL can be missing (0x8000 badval as in velocities)
       
    81 #	- HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading)
    69 
    82 
    70 # NOTES:
    83 # NOTES:
    71 #	- RDI stores data in VAX/Intel byte order (little endian)
    84 #	- RDI stores data in VAX/Intel byte order (little endian)
    72 #	- the output data structure does not exactly mirror the file data
    85 #	- the output data structure does not exactly mirror the file data
    73 #	  structure; the header is not stored at all and the fixed leader
    86 #	  structure; the header is not stored at all and the fixed leader
    97 #	  indicate power failures on both FSU and LDEO slave instruments...
   110 #	  indicate power failures on both FSU and LDEO slave instruments...
    98 
   111 
    99 # &readData() returns perl obj (ref to anonymous hash) with the following
   112 # &readData() returns perl obj (ref to anonymous hash) with the following
   100 # structure:
   113 # structure:
   101 #
   114 #
       
   115 #	DATA_SOURCE_ID					scalar		0x7f (Workhorse, also DVL)
   102 #	NUMBER_OF_DATA_TYPES			scalar		6 (no BT) or 7
   116 #	NUMBER_OF_DATA_TYPES			scalar		6 (no BT) or 7
   103 #	ENSEMBLE_BYTES					scalar		?, number of bytes w/o checksum
   117 #	ENSEMBLE_BYTES					scalar		?, number of bytes w/o checksum
   104 #	HEADER_BYTES					scalar		?
   118 #	HEADER_BYTES					scalar		?
   105 #	FIXED_LEADER_BYTES				scalar		42 for BB150; 53 for WH300, 58 for WH600, 59 for WH300(Nash)
   119 #	FIXED_LEADER_BYTES				scalar		42 for BB150; 53 for WH300, 58 for WH600, 59 for WH300(Nash)
   106 #	VARIABLE_LEADER_BYTES			scalar		?
   120 #	VARIABLE_LEADER_BYTES			scalar		?
   181 #		N_BEAMS_USED				scalar		3,4,5(?)
   195 #		N_BEAMS_USED				scalar		3,4,5(?)
   182 #		NUMBER						scalar		1--16777215
   196 #		NUMBER						scalar		1--16777215
   183 #		BUILT_IN_TEST_ERROR			scalar		?,undefined=none
   197 #		BUILT_IN_TEST_ERROR			scalar		?,undefined=none
   184 #		SPEED_OF_SOUND				scalar		1400--1600 [m/s]
   198 #		SPEED_OF_SOUND				scalar		1400--1600 [m/s]
   185 #		XDUCER_DEPTH				scalar		0.1--999.9 [m]
   199 #		XDUCER_DEPTH				scalar		0.1--999.9 [m]
   186 #		HEADING						scalar		0--359.99 [deg]
   200 #		HEADING						scalar		0--359.99 [deg]    --- IMP EXTENSION: undef
   187 #		PITCH						scalar		-20.00-20.00 [deg]
   201 #		PITCH						scalar		-20.00-20.00 [deg] --- IMP EXTENSION: undef
   188 #		ROLL						scalar		-20.00-20.00 [deg]
   202 #		ROLL						scalar		-20.00-20.00 [deg] --- IMP EXTENSION: undef
   189 #		SALINITY					scalar		0-40 [psu]
   203 #		SALINITY					scalar		0-40 [psu]
   190 #		TEMPERATURE					scalar		-5.00--40.00 [deg]
   204 #		TEMPERATURE					scalar		-5.00--40.00 [deg]
   191 #		MIN_PRE_PING_WAIT_TIME		scalar		? [s]
   205 #		MIN_PRE_PING_WAIT_TIME		scalar		? [s]
   192 #		HEADING_STDDEV				scalar		0-180 [deg]
   206 #		HEADING_STDDEV				scalar		0-180 [deg]
   193 #		PITCH_STDDEV				scalar		0.0-20.0 [deg]
   207 #		PITCH_STDDEV				scalar		0.0-20.0 [deg]
   315 
   329 
   316 	sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!");
   330 	sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!");
   317 	($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES})
   331 	($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES})
   318 		= unpack('CCvCC',$buf);
   332 		= unpack('CCvCC',$buf);
   319 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   333 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   320 	$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
   334 ##	$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
   321 	printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d)\n",
   335 	printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d)\n",
   322 		$dta->{NUMBER_OF_DATA_TYPES})
   336 		$dta->{NUMBER_OF_DATA_TYPES})
   323 			unless ($dta->{NUMBER_OF_DATA_TYPES} == 6 ||
   337 			unless ($dta->{NUMBER_OF_DATA_TYPES} == 6 ||
   324 					$dta->{NUMBER_OF_DATA_TYPES} == 7);
   338 					$dta->{NUMBER_OF_DATA_TYPES} == 7);
   325 	$dta->{BT_PRESENT} = ($dta->{NUMBER_OF_DATA_TYPES} == 7);
   339 	$dta->{BT_PRESENT} = ($dta->{NUMBER_OF_DATA_TYPES} == 7);
   551 
   565 
   552 sub WBRens($$$)
   566 sub WBRens($$$)
   553 {
   567 {
   554 	my($nbins,$fixed_leader_bytes,$E) = @_;
   568 	my($nbins,$fixed_leader_bytes,$E) = @_;
   555 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBRofs);
   569 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBRofs);
   556 	my($ens,$ensNo,$dayStart,$ens_length,$BT_present,$hid,$did,$ndt);
   570 	my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$ndt);
   557 
   571 
   558 	for ($ens=$start_ens=0; 1; $ens++,$start_ens+=$ens_length+2) {
   572 	for ($ens=$start_ens=0; 1; $ens++,$start_ens+=$ens_length+2) {
   559 #		print(STDERR "ens = $ens\n");
   573 #		print(STDERR "ens = $ens\n");
   560 #		print(STDERR "start_ens = $start_ens\n");
   574 #		print(STDERR "start_ens = $start_ens\n");
   561 
   575 
   565 
   579 
   566 		sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!");
   580 		sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!");
   567 		sysread(WBRF,$buf,6) == 6 || last;
   581 		sysread(WBRF,$buf,6) == 6 || last;
   568 		($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf);
   582 		($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf);
   569 		$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   583 		$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   570 		$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
   584 ##		$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
   571 		printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   585 ##		printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   572 				unless ($ndt == 6 || $ndt == 7);
   586 ##				unless ($ndt == 6 || $ndt == 7);
   573 		$BT_present = ($ndt == 7);
       
   574 		sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!");
   587 		sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!");
   575 		@WBRofs = unpack("v$ndt",$buf);
   588 		@WBRofs = unpack("v$ndt",$buf);
   576 		$fixed_leader_bytes = $WBRofs[1] - $WBRofs[0];
   589 		$fixed_leader_bytes = $WBRofs[1] - $WBRofs[0];
   577 #		print(STDERR "@WBRofs\n");
   590 #		print(STDERR "@WBRofs\n");
   578 	
   591 	
   592 
   605 
   593 		#------------------------------
   606 		#------------------------------
   594 		# Variable Leader
   607 		# Variable Leader
   595 		#------------------------------
   608 		#------------------------------
   596 	
   609 	
       
   610 		${$E}[$ens]->{DATA_SOURCE_ID} = $did;								# IMP extension
       
   611 
   597 		sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!");
   612 		sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!");
   598 		sysread(WBRF,$buf,4) == 4 || die("$WBRcfn: $!");
   613 		sysread(WBRF,$buf,4) == 4 || die("$WBRcfn: $!");
   599 		($id,$ensNo) = unpack("vv",$buf);
   614 		($id,$ensNo) = unpack("vv",$buf);
   600 
   615 
   601 		$id == 0x0080 ||
   616 		$id == 0x0080 ||
   633 		${$E}[$ens]->{BUILT_IN_TEST_ERROR} = undef
   648 		${$E}[$ens]->{BUILT_IN_TEST_ERROR} = undef
   634 			unless (${$E}[$ens]->{BUILT_IN_TEST_ERROR});
   649 			unless (${$E}[$ens]->{BUILT_IN_TEST_ERROR});
   635 		$BIT_errors++ if (${$E}[$ens]->{BUILT_IN_TEST_ERROR});
   650 		$BIT_errors++ if (${$E}[$ens]->{BUILT_IN_TEST_ERROR});
   636 
   651 
   637 		${$E}[$ens]->{XDUCER_DEPTH} /= 10;
   652 		${$E}[$ens]->{XDUCER_DEPTH} /= 10;
   638 		${$E}[$ens]->{HEADING} /= 100;
   653 
   639 		${$E}[$ens]->{PITCH} = unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100;
   654 		#-------------------------------------------------
   640 		${$E}[$ens]->{ROLL}  = unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100;
   655 		# IMP EXTENSION: PITCH/ROLL/HEADING CAN BE MISSING
   641 		${$E}[$ens]->{TEMPERATURE} =
   656 		#-------------------------------------------------
   642 			unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100;
   657 		
       
   658 		${$E}[$ens]->{HEADING} = (${$E}[$ens]->{HEADING} == 0xF000)
       
   659 							   ? undef
       
   660 							   : ${$E}[$ens]->{HEADING} / 100;
       
   661 		${$E}[$ens]->{PITCH} = (${$E}[$ens]->{PITCH} == 0x8000)
       
   662 							 ? undef
       
   663 							 : unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100;
       
   664 		${$E}[$ens]->{ROLL}  = (${$E}[$ens]->{ROLL} == 0x8000)
       
   665                              ? undef
       
   666                              : unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100;
       
   667                              
       
   668 		${$E}[$ens]->{TEMPERATURE} = unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100;
   643 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60;
   669 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60;
   644 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100;
   670 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100;
   645 		${$E}[$ens]->{PITCH_STDDEV} /= 10;
   671 		${$E}[$ens]->{PITCH_STDDEV} /= 10;
   646 		${$E}[$ens]->{ROLL_STDDEV} /= 10;
   672 		${$E}[$ens]->{ROLL_STDDEV} /= 10;
   647 
   673 
   778 
   804 
   779 		$id == 0x0400 ||
   805 		$id == 0x0400 ||
   780 			die(sprintf($FmtErr,$WBRcfn,"Percent-Good Data",$id,$ens));
   806 			die(sprintf($FmtErr,$WBRcfn,"Percent-Good Data",$id,$ens));
   781 
   807 
   782 		for ($i=0,$bin=0; $bin<$nbins; $bin++) {
   808 		for ($i=0,$bin=0; $bin<$nbins; $bin++) {
       
   809 #			printf(STDERR "%-GOOD($bin): ");
   783 			for ($beam=0; $beam<4; $beam++,$i++) {
   810 			for ($beam=0; $beam<4; $beam++,$i++) {
       
   811 #				printf(STDERR "$dta[$i] ");
   784 				${$E}[$ens]->{PERCENT_GOOD}[$bin][$beam] = $dta[$i];
   812 				${$E}[$ens]->{PERCENT_GOOD}[$bin][$beam] = $dta[$i];
   785 			}
   813 			}
   786 		}
   814 #			printf(STDERR "\n");
   787 
   815 		}
   788 		#--------------------
   816 
       
   817 		#-----------------------------------------
   789 		# Bottom-Track Data
   818 		# Bottom-Track Data
   790 		#--------------------
   819 		#	- scan through remaining data types
   791 
   820 		#-----------------------------------------
   792 		if ($BT_present) {
   821 
   793 			sysseek(WBRF,$start_ens+$WBRofs[6],0) || die("$WBRcfn: $!");
   822 		my($nxt);
       
   823 		for ($nxt=6; $nxt<$ndt; $nxt++) {										# scan until BT found
       
   824 			sysseek(WBRF,$start_ens+$WBRofs[$nxt],0) || die("$WBRcfn: $!");
   794 			sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!");
   825 			sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!");
   795 			$id = unpack('v',$buf);
   826 			$id = unpack('v',$buf);
   796 	
   827 			last if ($id == 0x0600);
   797 			$id == 0x0600 ||
   828 		}
   798 				die(sprintf($FmtErr,$WBRcfn,"Bottom Track",$id,$ens));
   829 
   799 	
   830 		next if ($nxt == $ndt);													# no BT found => next ens
   800 			sysseek(WBRF,14,1) || die("$WBRcfn: $!");		# BT config
   831 
   801 	
   832 
   802 			sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!");
   833 		sysseek(WBRF,14,1) || die("$WBRcfn: $!");								# BT config
   803 			@dta = unpack('v4v4C4C4C4',$buf);
   834 
   804 		    
   835 		sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!");
   805 			for ($beam=0; $beam<4; $beam++) {
   836 		@dta = unpack('v4v4C4C4C4',$buf);
   806 				${$E}[$ens]->{BT_RANGE}[$beam] = $dta[$beam] / 100
   837 	    
   807 						if ($dta[$beam]);
   838 		for ($beam=0; $beam<4; $beam++) {
   808 			}
   839 			${$E}[$ens]->{BT_RANGE}[$beam] = $dta[$beam] / 100
   809 			for ($beam=0; $beam<4; $beam++) {
   840 					if ($dta[$beam]);
   810 				${$E}[$ens]->{BT_VELOCITY}[$beam] =
   841 		}
   811 					unpack('s',pack('S',$dta[4+$beam])) / 1000
   842 		for ($beam=0; $beam<4; $beam++) {
   812 						if ($dta[4+$beam] != 0x8000);
   843 			${$E}[$ens]->{BT_VELOCITY}[$beam] =
   813 			}
   844 				unpack('s',pack('S',$dta[4+$beam])) / 1000
   814 			for ($beam=0; $beam<4; $beam++) {
   845 					if ($dta[4+$beam] != 0x8000);
   815 				${$E}[$ens]->{BT_CORRELATION}[$beam] = $dta[8+$beam]
   846 		}
   816 					if ($dta[8+$beam]);
   847 		for ($beam=0; $beam<4; $beam++) {
   817 			}
   848 			${$E}[$ens]->{BT_CORRELATION}[$beam] = $dta[8+$beam]
   818 			for ($beam=0; $beam<4; $beam++) {
   849 				if ($dta[8+$beam]);
   819 				${$E}[$ens]->{BT_EVAL_AMPLITUDE}[$beam] = $dta[12+$beam];
   850 		}
   820 			}
   851 		for ($beam=0; $beam<4; $beam++) {
   821 			for ($beam=0; $beam<4; $beam++) {
   852 			${$E}[$ens]->{BT_EVAL_AMPLITUDE}[$beam] = $dta[12+$beam];
   822 				${$E}[$ens]->{BT_PERCENT_GOOD}[$beam] = $dta[16+$beam];
   853 		}
   823 			}
   854 		for ($beam=0; $beam<4; $beam++) {
   824 	
   855 			${$E}[$ens]->{BT_PERCENT_GOOD}[$beam] = $dta[16+$beam];
   825 			sysseek(WBRF,6,1) || die("$WBRcfn: $!");		# BT config
   856 		}
   826 	
   857 
   827 			sysread(WBRF,$buf,20) == 20 || die("$WBRcfn: $!");
   858 		sysseek(WBRF,6,1) || die("$WBRcfn: $!");		# BT config
   828 			@dta = unpack('v4C4C4C4',$buf);
   859 
   829 	
   860 		sysread(WBRF,$buf,20) == 20 || die("$WBRcfn: $!");
   830 			for ($beam=0; $beam<4; $beam++) {
   861 		@dta = unpack('v4C4C4C4',$buf);
   831 				${$E}[$ens]->{BT_RL_VELOCITY}[$beam] =
   862 
   832 					unpack('s',pack('S',$dta[$beam])) / 1000
   863 		for ($beam=0; $beam<4; $beam++) {
   833 						if ($dta[$beam] != 0x8000);
   864 			${$E}[$ens]->{BT_RL_VELOCITY}[$beam] =
   834 			}
   865 				unpack('s',pack('S',$dta[$beam])) / 1000
   835 			for ($beam=0; $beam<4; $beam++) {
   866 					if ($dta[$beam] != 0x8000);
   836 				${$E}[$ens]->{BT_RL_CORRELATION}[$beam] = $dta[4+$beam]
   867 		}
   837 					if ($dta[4+$beam]);
   868 		for ($beam=0; $beam<4; $beam++) {
   838 			}
   869 			${$E}[$ens]->{BT_RL_CORRELATION}[$beam] = $dta[4+$beam]
   839 			for ($beam=0; $beam<4; $beam++) {
   870 				if ($dta[4+$beam]);
   840 				${$E}[$ens]->{BT_RL_ECHO_AMPLITUDE}[$beam] = $dta[8+$beam];
   871 		}
   841 			}
   872 		for ($beam=0; $beam<4; $beam++) {
   842 			for ($beam=0; $beam<4; $beam++) {
   873 			${$E}[$ens]->{BT_RL_ECHO_AMPLITUDE}[$beam] = $dta[8+$beam];
   843 				${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam];
   874 		}
   844 			}
   875 		for ($beam=0; $beam<4; $beam++) {
   845 	
   876 			${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam];
   846 			sysseek(WBRF,2,1) || die("$WBRcfn: $!");		# BT config
   877 		}
   847 	
   878 
   848 			sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!");
   879 		sysseek(WBRF,2,1) || die("$WBRcfn: $!");		# BT config
   849 			@dta = unpack('C4CC4',$buf);
   880 
   850 	
   881 		sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!");
   851 			for ($beam=0; $beam<4; $beam++) {
   882 		@dta = unpack('C4CC4',$buf);
   852 				${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam];
   883 
   853 			}
   884 		for ($beam=0; $beam<4; $beam++) {
   854 			${$E}[$ens]->{HIGH_GAIN} if	   ($dta[4]);
   885 			${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam];
   855 			${$E}[$ens]->{LOW_GAIN}	unless ($dta[4]);
   886 		}
   856 			for ($beam=0; $beam<4; $beam++) {
   887 		${$E}[$ens]->{HIGH_GAIN} if    ($dta[4]);
   857 				${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36
   888 		${$E}[$ens]->{LOW_GAIN} unless ($dta[4]);
   858 					if ($dta[5+$beam]);
   889 		for ($beam=0; $beam<4; $beam++) {
   859 	        }
   890 			${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36
   860 	    } # BT present
   891 				if ($dta[5+$beam]);
       
   892 		}
   861 	} # ens loop
   893 	} # ens loop
   862 }
   894 }
   863 
   895 
   864 #----------------------------------------------------------------------
   896 #----------------------------------------------------------------------
   865 # WBPens(nbins,fixed_leader_bytes,^data)
   897 # WBPens(nbins,fixed_leader_bytes,^data)
   884 
   916 
   885 sub WBPens($$$)
   917 sub WBPens($$$)
   886 {
   918 {
   887 	my($nbins,$fixed_leader_bytes,$E) = @_;
   919 	my($nbins,$fixed_leader_bytes,$E) = @_;
   888 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs);
   920 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs);
   889 	my($ens,$ensNo,$dayStart,$ens_length,$BT_present,$hid,$did,$ndt);
   921 	my($ens,$ensNo,$dayStart,$ens_length,$hid,$ndt);
   890 
   922 
   891 	for ($ens=$start_ens=0; 1; $ens++,$start_ens+=$ens_length+2) {
   923 	for ($ens=$start_ens=0; $ens<=$#{$E}; $ens++,$start_ens+=$ens_length+2) {
   892 
   924 
   893 		#----------------------------------------
   925 		#------------------------------
   894 		# Get ensemble length and # of data types 
   926 		# Patch Header (Data Source Id)
   895 		#----------------------------------------
   927 		#------------------------------
   896 
   928 
   897 		sysseek(WBPF,$start_ens,0) || die("$WBPcfn: $!");
   929 		sysseek(WBPF,$start_ens,0) || die("$WBPcfn: $!");
   898 		sysread(WBPF,$buf,6) == 6 || last;
   930 		sysread(WBPF,$buf,1) || die("$WBPcfn: unexpected EOF");
   899 		($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf);
   931 		($hid) = unpack('C',$buf);
   900 		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,0));
   932 		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,$ens));
   901 		$did == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Data Source",$did,0));
   933 
       
   934 		$buf = pack('C',${$E}[$ens]->{DATA_SOURCE_ID});
       
   935 		my($nw) = syswrite(WBPF,$buf,1);
       
   936 		$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
       
   937 
       
   938 		sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF");
       
   939 		($ens_length,$dummy,$ndt) = unpack('vCC',$buf);
   902 		printf(STDERR "\n$WBPcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   940 		printf(STDERR "\n$WBPcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   903 				unless ($ndt == 6 || $ndt == 7);
   941 				unless ($ndt == 6 || $ndt == 7);
   904 		$BT_present = ($ndt == 7);
   942 
   905 		sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!");
   943 		sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!");
   906 		@WBPofs = unpack("v$ndt",$buf);
   944 		@WBPofs = unpack("v$ndt",$buf);
   907 		$fixed_leader_bytes = $WBPofs[1] - $WBPofs[0];
   945 		$fixed_leader_bytes = $WBPofs[1] - $WBPofs[0];
   908 	
   946 	
   909 		#------------------------------
   947 		#------------------------------
   911 		#------------------------------
   949 		#------------------------------
   912 	
   950 	
   913 		sysseek(WBPF,$start_ens+$WBPofs[1]+12,0) || die("$WBPcfn: $!");
   951 		sysseek(WBPF,$start_ens+$WBPofs[1]+12,0) || die("$WBPcfn: $!");
   914 		
   952 		
   915 		${$E}[$ens]->{XDUCER_DEPTH} *= 10;
   953 		${$E}[$ens]->{XDUCER_DEPTH} *= 10;
   916 		${$E}[$ens]->{HEADING} *= 100;
   954 
   917 		
   955 		# IMP EXTENSIONS
   918 		${$E}[$ens]->{PITCH} = unpack('S',pack('s',${$E}[$ens]->{PITCH}*100));
   956 		#---------------
   919 		${$E}[$ens]->{ROLL}  = unpack('S',pack('s',${$E}[$ens]->{ROLL} *100));
   957 		${$E}[$ens]->{HEADING} = defined(${$E}[$ens]->{HEADING})
       
   958 							   ? ${$E}[$ens]->{HEADING} * 100
       
   959 							   : 0xF000;
       
   960 		${$E}[$ens]->{PITCH} = defined(${$E}[$ens]->{PITCH})
       
   961 							 ? unpack('S',pack('s',${$E}[$ens]->{PITCH}*100))
       
   962 							 : 0x8000;
       
   963 		${$E}[$ens]->{ROLL} = defined(${$E}[$ens]->{ROLL})
       
   964 						    ? unpack('S',pack('s',${$E}[$ens]->{ROLL}*100))
       
   965 						    : 0x8000;
       
   966 
   920 		${$E}[$ens]->{TEMPERATURE} =
   967 		${$E}[$ens]->{TEMPERATURE} =
   921 			unpack('S',pack('s',${$E}[$ens]->{TEMPERATURE}*100));
   968 			unpack('S',pack('s',${$E}[$ens]->{TEMPERATURE}*100));
   922 
   969 
   923 		sysseek(WBPF,2,1);			# skip built-in test which reads as 0 but is usually undef		
   970 		sysseek(WBPF,2,1);			# skip built-in test which reads as 0 but is usually undef		
   924 									# this was found not to matter, but there is no reason to edit
   971 									# this was found not to matter, but there is no reason to edit
   931 			 ${$E}[$ens]->{SPEED_OF_SOUND},
   978 			 ${$E}[$ens]->{SPEED_OF_SOUND},
   932 			 ${$E}[$ens]->{XDUCER_DEPTH},${$E}[$ens]->{HEADING},
   979 			 ${$E}[$ens]->{XDUCER_DEPTH},${$E}[$ens]->{HEADING},
   933 			 ${$E}[$ens]->{PITCH},${$E}[$ens]->{ROLL},
   980 			 ${$E}[$ens]->{PITCH},${$E}[$ens]->{ROLL},
   934 			 ${$E}[$ens]->{SALINITY},${$E}[$ens]->{TEMPERATURE});
   981 			 ${$E}[$ens]->{SALINITY},${$E}[$ens]->{TEMPERATURE});
   935 
   982 
   936 #		unless ($b1 eq $buf) {
       
   937 #			printf(STDERR "ens = $ens\n");
       
   938 #			printf(STDERR "hdg: $hdg, ${$E}[$ens]->{HEADING}\n");
       
   939 #			printf(STDERR "xd: $xd, ${$E}[$ens]->{XDUCER_DEPTH}\n");
       
   940 #			printf(STDERR "pit: $pit, ${$E}[$ens]->{PITCH}\n");
       
   941 #			printf(STDERR "rol: $rol, ${$E}[$ens]->{ROLL}\n");
       
   942 #			printf(STDERR "sal: $sal, ${$E}[$ens]->{SALINITY}\n");
       
   943 #			printf(STDERR "tem: $tem, ${$E}[$ens]->{TEMPERATURE}\n");
       
   944 #
       
   945 #			printf(STDERR "read: %04X %04X %04X %04X %04X %04X %04X written: %04X %04X %04X %04X %04X %04X %04X\n",unpack('v7',$b1),unpack('v7',$buf));
       
   946 #
       
   947 #			die;
       
   948 #		}
       
   949 
       
   950 		my($nw) = syswrite(WBPF,$buf,14);
   983 		my($nw) = syswrite(WBPF,$buf,14);
   951 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
   984 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
   952 
   985 
   953 		#----------------
   986 		#----------------
   954 		# Update Checksum
   987 		# Update Checksum