1 #====================================================================== |
1 #====================================================================== |
2 # / D A T A / S R C / O C E A N O G R A P H Y / A D C P _ T O O L S / 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: Thu Feb 27 10:28:29 2020 |
4 # dlm: Sun Apr 12 20:02:30 2020 |
5 # (c) 2003 A.M. Thurnherr |
5 # (c) 2003 A.M. Thurnherr |
6 # uE-Info: 716 1 NIL 0 0 72 0 2 4 NIL ofnI |
6 # uE-Info: 123 72 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: |
12 # Jan 18, 2003: - incepted aboard the Aurora Australis (KAOS) |
12 # Jan 18, 2003: - incepted aboard the Aurora Australis (KAOS) |
13 # Jan 19, 2003: - continued |
13 # Jan 19, 2003: - continued |
14 # Jan 20, 2003: - replaced INTENSITY by AMPLITUDE |
14 # Jan 20, 2003: - replaced INTENSITY by AMPLITUDE |
15 # Jan 21, 2003: - changed heading-correction field names |
15 # Jan 21, 2003: - changed heading-correction field names |
115 # Jun 12, 2018: - BUG: IMPed files did not pass the garbage detection |
115 # Jun 12, 2018: - BUG: IMPed files did not pass the garbage detection |
116 # Jun 13, 2019: - adapted reading routines to RTI files (free order of data types) |
116 # Jun 13, 2019: - adapted reading routines to RTI files (free order of data types) |
117 # - removed old BT_PRESENT code |
117 # - removed old BT_PRESENT code |
118 # Jun 28, 2019: - renamed SECONDS to SECOND for consistency |
118 # Jun 28, 2019: - renamed SECONDS to SECOND for consistency |
119 # Jun 30, 2019: - added dirty flag to prevent bad PD0 patching |
119 # Jun 30, 2019: - added dirty flag to prevent bad PD0 patching |
120 # Feb 13, 2020: - added support for $readDataProgress |
120 # - added $show_progress |
|
121 # Feb 13, 2020: - added support for $readDataProgress (to Jun 13 version) |
|
122 # Apr 12, 2020: - merged laptop and whoosher versions which both implemented |
|
123 # progreass; not sure whether this merge is successful |
121 |
124 |
|
125 |
122 # FIRMWARE VERSIONS: |
126 # FIRMWARE VERSIONS: |
123 # It appears that different firmware versions generate different file |
127 # It appears that different firmware versions generate different file |
124 # structures. Currently (Sep 2005) these routines have been tested |
128 # structures. Currently (Sep 2005) these routines have been tested |
125 # with the following firmware versions (as reported by [listHdr]): |
129 # with the following firmware versions (as reported by [listHdr]): |
126 # |
130 # |
313 # BT_RL_ECHO_AMPLITUDE[beam] scalars see ECHO_AMPLITUDE |
317 # BT_RL_ECHO_AMPLITUDE[beam] scalars see ECHO_AMPLITUDE |
314 # BT_RL_PERCENT_GOOD[beam] scalars see PERCENT_GOOD |
318 # BT_RL_PERCENT_GOOD[beam] scalars see PERCENT_GOOD |
315 # BT_SIGNAL_STRENGTH[beam] scalars 0--255 |
319 # BT_SIGNAL_STRENGTH[beam] scalars 0--255 |
316 # HIGH_GAIN bool 1, undefined |
320 # HIGH_GAIN bool 1, undefined |
317 # LOW_GAIN bool 1, undefined |
321 # LOW_GAIN bool 1, undefined |
318 |
322 |
319 use strict; |
323 use strict; |
320 use Time::Local; # timegm() |
324 use Time::Local; # timegm() |
321 |
325 |
|
326 $RDI_PD0_IO::show_progress = 0; # when set, print . every 1000 ens read |
|
327 |
322 #---------------------------------------------------------------------- |
328 #---------------------------------------------------------------------- |
323 # Time Conversion Subroutines |
329 # Time Conversion Subroutines |
324 # - prepended with _ to avoid conflicts with [libconv.pl] |
330 # - prepended with _ to avoid conflicts with [libconv.pl] |
325 #---------------------------------------------------------------------- |
331 #---------------------------------------------------------------------- |
326 |
332 |
327 sub _monthLength($$) # of days in month |
333 sub _monthLength($$) # of days in month |
328 { |
334 { |
329 my($Y,$M) = @_; |
335 my($Y,$M) = @_; |
330 |
336 |
331 return 31 if ($M==1 || $M==3 || $M==5 || $M==7 || |
337 return 31 if ($M==1 || $M==3 || $M==5 || $M==7 || |
332 $M==8 || $M==10 || $M==12); |
338 $M==8 || $M==10 || $M==12); |
333 return 30 if ($M==4 || $M==6 || $M==9 || $M==11); |
339 return 30 if ($M==4 || $M==6 || $M==9 || $M==11); |
334 return 28 if ($Y%4 != 0); |
340 return 28 if ($Y%4 != 0); |
335 return 29 if ($Y%100 != 0); |
341 return 29 if ($Y%100 != 0); |
336 return 28 if ($Y%400 > 0); |
342 return 28 if ($Y%400 > 0); |
337 return 29; |
343 return 29; |
338 } |
344 } |
339 |
345 |
340 { my($epoch,$lM,$lD,$lY,$ldn); # static scope |
346 { my($epoch,$lM,$lD,$lY,$ldn); # static scope |
341 |
347 |
342 sub _dayNo($$$$$$) |
348 sub _dayNo($$$$$$) |
343 { |
349 { |
344 my($Y,$M,$D,$h,$m,$s) = @_; |
350 my($Y,$M,$D,$h,$m,$s) = @_; |
345 my($dn); |
351 my($dn); |
346 |
352 |
347 if ($Y==$lY && $M==$lM && $D==$lD) { # same day as last samp |
353 if ($Y==$lY && $M==$lM && $D==$lD) { # same day as last samp |
348 $dn = $ldn; |
354 $dn = $ldn; |
349 } else { # new day |
355 } else { # new day |
350 $epoch = $Y unless defined($epoch); # 1st call |
356 $epoch = $Y unless defined($epoch); # 1st call |
351 $lY = $Y; $lM = $M; $lD = $D; # store |
357 $lY = $Y; $lM = $M; $lD = $D; # store |
352 |
358 |
353 for ($dn=0,my($cY)=$epoch; $cY<$Y; $cY++) { # multiple years |
359 for ($dn=0,my($cY)=$epoch; $cY<$Y; $cY++) { # multiple years |
354 $dn += 337 + &_monthLength($Y,$M); |
360 $dn += 337 + &_monthLength($Y,$M); |
355 } |
|
356 |
|
357 $dn += $D; # day in month |
|
358 while (--$M > 0) { # preceding months |
|
359 $dn += &_monthLength($Y,$M); |
|
360 } |
|
361 |
|
362 $ldn = $dn; # store |
|
363 } |
361 } |
364 return $dn + $h/24 + $m/24/60 + $s/24/3600; |
362 |
|
363 $dn += $D; # day in month |
|
364 while (--$M > 0) { # preceding months |
|
365 $dn += &_monthLength($Y,$M); |
|
366 } |
|
367 |
|
368 $ldn = $dn; # store |
365 } |
369 } |
366 |
370 return $dn + $h/24 + $m/24/60 + $s/24/3600; |
367 } # static scope |
371 } |
368 |
372 |
|
373 } # static scope |
|
374 |
369 #---------------------------------------------------------------------- |
375 #---------------------------------------------------------------------- |
370 # Read Data |
376 # Read Data |
371 #---------------------------------------------------------------------- |
377 #---------------------------------------------------------------------- |
372 |
378 |
373 my($WBRcfn,$WBPcfn); # current file names for reading/patching |
379 my($WBRcfn,$WBPcfn); # current file names for reading/patching |
374 my($BIT_errors) = 0; # built-in-test errors |
380 my($BIT_errors) = 0; # built-in-test errors |
375 |
381 |
376 my($FmtErr) = "%s: illegal %s Id 0x%04x at ensemble %d"; |
382 my($FmtErr) = "%s: illegal %s Id 0x%04x at ensemble %d"; |
377 |
383 |
378 #---------------------------------------------------------------------- |
384 #---------------------------------------------------------------------- |
379 # skip to next valid start of ensemble (skip over garbage) |
385 # skip to next valid start of ensemble (skip over garbage) |
380 #---------------------------------------------------------------------- |
386 #---------------------------------------------------------------------- |
381 |
387 |
382 sub goto_next_ens(@) |
388 sub goto_next_ens(@) |
383 { |
389 { |
384 my($fh,$return_skipped) = @_; # if return_skipped not set, return file pos |
390 my($fh,$return_skipped) = @_; # if return_skipped not set, return file pos |
385 my($buf,$dta); |
391 my($buf,$dta); |
386 |
392 |
417 print(STDERR "WARNING (RDI_PD0_IO): PD0 file starts with $skipped garbage bytes\n"); |
423 print(STDERR "WARNING (RDI_PD0_IO): PD0 file starts with $skipped garbage bytes\n"); |
418 } else { |
424 } else { |
419 print(STDERR "WARNING (RDI_PD0_IO): $skipped garbage bytes in PD0 file beginning at byte $garbage_start\n"); |
425 print(STDERR "WARNING (RDI_PD0_IO): $skipped garbage bytes in PD0 file beginning at byte $garbage_start\n"); |
420 } |
426 } |
421 } |
427 } |
422 |
428 |
423 return $fpos; |
429 return $fpos; |
424 } |
430 } |
425 |
431 |
426 #---------------------------------------------------------------------- |
432 #---------------------------------------------------------------------- |
427 # readHeader(file_name,^dta) WBRhdr(^data) |
433 # readHeader(file_name,^dta) WBRhdr(^data) |
428 # - read header data |
434 # - read header data |
429 # - also includes some data from 1st ens |
435 # - also includes some data from 1st ens |
430 #---------------------------------------------------------------------- |
436 #---------------------------------------------------------------------- |
431 |
437 |
432 sub readHeader(@) |
438 sub readHeader(@) |
433 { |
439 { |
434 my($fn,$dta,$suppress_error) = @_; |
440 my($fn,$dta,$suppress_error) = @_; |
435 $WBRcfn = $fn; |
441 $WBRcfn = $fn; |
436 open(WBRF,$WBRcfn) || die("$WBRcfn: $!"); |
442 open(WBRF,$WBRcfn) || die("$WBRcfn: $!"); |
437 if (WBRhdr($dta)) { |
443 if (WBRhdr($dta)) { |
438 return 1; |
444 return 1; |
439 } elsif ($suppress_error) { |
445 } elsif ($suppress_error) { |
440 return undef; |
446 return undef; |
441 } else { |
447 } else { |
442 die("$WBRcfn: Insufficient data\n"); |
448 die("$WBRcfn: Insufficient data\n"); |
443 } |
449 } |
444 } |
450 } |
445 |
451 |
446 sub WBRhdr($) |
452 sub WBRhdr($) |
447 { |
453 { |
448 my($dta) = @_; |
454 my($dta) = @_; |
503 $dta->{INSTRUMENT_TYPE} = 'Workhorse'; |
509 $dta->{INSTRUMENT_TYPE} = 'Workhorse'; |
504 } elsif ($dta->{FIXED_LEADER_BYTES} == 58) { # DVL |
510 } elsif ($dta->{FIXED_LEADER_BYTES} == 58) { # DVL |
505 $dta->{INSTRUMENT_TYPE} = 'Explorer'; |
511 $dta->{INSTRUMENT_TYPE} = 'Explorer'; |
506 } elsif ($dta->{FIXED_LEADER_BYTES} == 60) { # OS75 |
512 } elsif ($dta->{FIXED_LEADER_BYTES} == 60) { # OS75 |
507 $dta->{INSTRUMENT_TYPE} = 'Ocean Surveyor'; |
513 $dta->{INSTRUMENT_TYPE} = 'Ocean Surveyor'; |
508 } else { |
514 } else { |
509 $dta->{INSTRUMENT_TYPE} = 'unknown'; |
515 $dta->{INSTRUMENT_TYPE} = 'unknown'; |
510 } |
516 } |
511 |
517 |
512 #-------------------------------- |
518 #-------------------------------- |
513 # Variable Leader: SPEED_OF_SOUND |
519 # Variable Leader: SPEED_OF_SOUND |
514 #-------------------------------- |
520 #-------------------------------- |
515 |
521 |
516 sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!"); |
522 sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!"); |
517 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
523 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
518 $id = unpack('v',$buf); |
524 $id = unpack('v',$buf); |
519 if ($dta->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
525 if ($dta->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
520 $id == 0x0081 || printf(STDERR $FmtErr."\n",$WBRcfn,"Variable Leader",$id,1); |
526 $id == 0x0081 || printf(STDERR $FmtErr."\n",$WBRcfn,"Variable Leader",$id,1); |
521 } else { |
527 } else { |
522 $id == 0x0080 || printf(STDERR $FmtErr."\n",$WBRcfn,"Variable Leader",$id,1); |
528 $id == 0x0080 || printf(STDERR $FmtErr."\n",$WBRcfn,"Variable Leader",$id,1); |
523 } |
529 } |
524 sysseek(WBRF,12,1) || die("$WBRcfn: $!"); # skip up to speed of sound |
530 sysseek(WBRF,12,1) || die("$WBRcfn: $!"); # skip up to speed of sound |
525 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
531 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
526 $dta->{SPEED_OF_SOUND} = unpack('v',$buf); |
532 $dta->{SPEED_OF_SOUND} = unpack('v',$buf); |
527 |
533 |
528 #-------------------- |
534 #-------------------- |
529 # FIXED LEADER |
535 # FIXED LEADER |
530 #-------------------- |
536 #-------------------- |
531 |
537 |
532 sysseek(WBRF,$start_ens+$WBRofs[0],0) || die("$WBRcfn: $!"); |
538 sysseek(WBRF,$start_ens+$WBRofs[0],0) || die("$WBRcfn: $!"); |
544 $dta->{TRANSMIT_LAG_DISTANCE}) = |
550 $dta->{TRANSMIT_LAG_DISTANCE}) = |
545 unpack('vCCCCC3CvvvCCCCvCCCCvvCCvvCCCCv',$buf); |
551 unpack('vCCCCC3CvvvCCCCvCCCCvvCCvvCCCCv',$buf); |
546 |
552 |
547 if ($dta->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
553 if ($dta->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
548 $id == 0x0001 || printf(STDERR $FmtErr."\n",$WBRcfn,"Fixed Leader",$id,0); |
554 $id == 0x0001 || printf(STDERR $FmtErr."\n",$WBRcfn,"Fixed Leader",$id,0); |
549 } else { |
555 } else { |
550 $id == 0x0000 || printf(STDERR $FmtErr."\n",$WBRcfn,"Fixed Leader",$id,0); |
556 $id == 0x0000 || printf(STDERR $FmtErr."\n",$WBRcfn,"Fixed Leader",$id,0); |
551 } |
557 } |
552 |
558 |
553 # $dta->{BEAM_FREQUENCY} = 2**($B1 & 0x07) * 75; # nominal |
559 # $dta->{BEAM_FREQUENCY} = 2**($B1 & 0x07) * 75; # nominal |
554 if (($B1&0x07) == 0b000) { $dta->{BEAM_FREQUENCY} = 76.8; } # actual |
560 if (($B1&0x07) == 0b000) { $dta->{BEAM_FREQUENCY} = 76.8; } # actual |
555 elsif (($B1&0x07) == 0b001) { $dta->{BEAM_FREQUENCY} = 153.6; } |
561 elsif (($B1&0x07) == 0b001) { $dta->{BEAM_FREQUENCY} = 153.6; } |
556 elsif (($B1&0x07) == 0b010) { $dta->{BEAM_FREQUENCY} = 307.2; } |
562 elsif (($B1&0x07) == 0b010) { $dta->{BEAM_FREQUENCY} = 307.2; } |
557 elsif (($B1&0x07) == 0b011) { $dta->{BEAM_FREQUENCY} = 614.4; } |
563 elsif (($B1&0x07) == 0b011) { $dta->{BEAM_FREQUENCY} = 614.4; } |
558 elsif (($B1&0x07) == 0b100) { $dta->{BEAM_FREQUENCY} = 1228.8; } |
564 elsif (($B1&0x07) == 0b100) { $dta->{BEAM_FREQUENCY} = 1228.8; } |
559 elsif (($B1&0x07) == 0b101) { $dta->{BEAM_FREQUENCY} = 2457.6; } |
565 elsif (($B1&0x07) == 0b101) { $dta->{BEAM_FREQUENCY} = 2457.6; } |
560 else { die(sprintf("$WBRcfn: cannot decode BEAM_FREQUENCY (%03b)\n",$B1&0x07)); } |
566 else { die(sprintf("$WBRcfn: cannot decode BEAM_FREQUENCY (%03b)\n",$B1&0x07)); } |
561 |
567 |
562 $dta->{CONVEX_BEAM_PATTERN} = 1 if ($B1 & 0x08); |
568 $dta->{CONVEX_BEAM_PATTERN} = 1 if ($B1 & 0x08); |
563 $dta->{CONCAVE_BEAM_PATTERN} = 1 if (!($B1 & 0x08)); |
569 $dta->{CONCAVE_BEAM_PATTERN} = 1 if (!($B1 & 0x08)); |
564 $dta->{SENSOR_CONFIG} = ($B1 & 0x30) >> 4; |
570 $dta->{SENSOR_CONFIG} = ($B1 & 0x30) >> 4; |
565 $dta->{XDUCER_HEAD_ATTACHED} = 1 if ($B1 & 0x40); |
571 $dta->{XDUCER_HEAD_ATTACHED} = 1 if ($B1 & 0x40); |
566 |
572 |
567 if (($B2 & 0x03) == 0x00) { $dta->{BEAM_ANGLE} = 15; } |
573 if (($B2 & 0x03) == 0x00) { $dta->{BEAM_ANGLE} = 15; } |
568 elsif (($B2 & 0x03) == 0x01) { $dta->{BEAM_ANGLE} = 20; } |
574 elsif (($B2 & 0x03) == 0x01) { $dta->{BEAM_ANGLE} = 20; } |
569 elsif (($B2 & 0x03) == 0x02) { $dta->{BEAM_ANGLE} = 30; } |
575 elsif (($B2 & 0x03) == 0x02) { $dta->{BEAM_ANGLE} = 30; } |
570 if (($B2 & 0xF0) == 0x40) { $dta->{N_BEAMS} = 4; } |
576 if (($B2 & 0xF0) == 0x40) { $dta->{N_BEAMS} = 4; } |
571 elsif (($B2 & 0xF0) == 0x50) { $dta->{N_BEAMS} = 5; $dta->{N_DEMODS} = 3; } |
577 elsif (($B2 & 0xF0) == 0x50) { $dta->{N_BEAMS} = 5; $dta->{N_DEMODS} = 3; } |
572 elsif (($B2 & 0xF0) == 0xF0) { $dta->{N_BEAMS} = 5; $dta->{N_DEMODS} = 2; } |
578 elsif (($B2 & 0xF0) == 0xF0) { $dta->{N_BEAMS} = 5; $dta->{N_DEMODS} = 2; } |
573 |
579 |
574 $dta->{BIN_LENGTH} /= 100; |
580 $dta->{BIN_LENGTH} /= 100; |
575 $dta->{BLANKING_DISTANCE} /= 100; |
581 $dta->{BLANKING_DISTANCE} /= 100; |
576 |
582 |
577 $dta->{MAX_ERROR_VELOCITY} /= 1000; |
583 $dta->{MAX_ERROR_VELOCITY} /= 1000; |
578 $dta->{TIME_BETWEEN_PINGS} *= 60; |
584 $dta->{TIME_BETWEEN_PINGS} *= 60; |
579 $dta->{TIME_BETWEEN_PINGS} += $B3 + $B4/100; |
585 $dta->{TIME_BETWEEN_PINGS} += $B3 + $B4/100; |
580 |
586 |
581 $dta->{BEAM_COORDINATES} = 1 if (($B5 & 0x18) == 0x00); |
587 $dta->{BEAM_COORDINATES} = 1 if (($B5 & 0x18) == 0x00); |
582 $dta->{INSTRUMENT_COORDINATES} = 1 if (($B5 & 0x18) == 0x08); |
588 $dta->{INSTRUMENT_COORDINATES} = 1 if (($B5 & 0x18) == 0x08); |
583 $dta->{SHIP_COORDINATES} = 1 if (($B5 & 0x18) == 0x10); |
589 $dta->{SHIP_COORDINATES} = 1 if (($B5 & 0x18) == 0x10); |
584 $dta->{EARTH_COORDINATES} = 1 if (($B5 & 0x18) == 0x18); |
590 $dta->{EARTH_COORDINATES} = 1 if (($B5 & 0x18) == 0x18); |
585 $dta->{PITCH_AND_ROLL_USED} = 1 if ($B5 & 0x04); |
591 $dta->{PITCH_AND_ROLL_USED} = 1 if ($B5 & 0x04); |
586 $dta->{USE_3_BEAM_ON_LOW_CORR} = 1 if ($B5 & 0x02); |
592 $dta->{USE_3_BEAM_ON_LOW_CORR} = 1 if ($B5 & 0x02); |
587 $dta->{BIN_MAPPING_ALLOWED} = 1 if ($B5 & 0x01); |
593 $dta->{BIN_MAPPING_ALLOWED} = 1 if ($B5 & 0x01); |
588 |
594 |
589 $dta->{HEADING_ALIGNMENT} = |
595 $dta->{HEADING_ALIGNMENT} = |
590 ($dta->{EARTH_COORDINATES} || $dta->{SHIP_COORDINATES}) ? |
596 ($dta->{EARTH_COORDINATES} || $dta->{SHIP_COORDINATES}) ? |
591 $dta->{HEADING_ALIGNMENT} / 100 : undef; |
597 $dta->{HEADING_ALIGNMENT} / 100 : undef; |
592 $dta->{HEADING_BIAS} = |
598 $dta->{HEADING_BIAS} = |
593 ($dta->{EARTH_COORDINATES} || $dta->{SHIP_COORDINATES}) ? |
599 ($dta->{EARTH_COORDINATES} || $dta->{SHIP_COORDINATES}) ? |
597 $dta->{USE_PRESSURE_SENSOR} = 1 if ($B6 & 0x20); |
603 $dta->{USE_PRESSURE_SENSOR} = 1 if ($B6 & 0x20); |
598 $dta->{USE_COMPASS} = 1 if ($B6 & 0x10); |
604 $dta->{USE_COMPASS} = 1 if ($B6 & 0x10); |
599 $dta->{USE_PITCH_SENSOR} = 1 if ($B6 & 0x08); |
605 $dta->{USE_PITCH_SENSOR} = 1 if ($B6 & 0x08); |
600 $dta->{USE_ROLL_SENSOR} = 1 if ($B6 & 0x04); |
606 $dta->{USE_ROLL_SENSOR} = 1 if ($B6 & 0x04); |
601 $dta->{USE_CONDUCTIVITY_SENSOR} = 1 if ($B6 & 0x02); |
607 $dta->{USE_CONDUCTIVITY_SENSOR} = 1 if ($B6 & 0x02); |
602 $dta->{USE_TEMPERATURE_SENSOR} = 1 if ($B6 & 0x01); |
608 $dta->{USE_TEMPERATURE_SENSOR} = 1 if ($B6 & 0x01); |
603 |
609 |
604 $dta->{SPEED_OF_SOUND_CALCULATED} = 1 if ($B7 & 0x40); |
610 $dta->{SPEED_OF_SOUND_CALCULATED} = 1 if ($B7 & 0x40); |
605 $dta->{PRESSURE_SENSOR_AVAILABLE} = 1 if ($B7 & 0x20); |
611 $dta->{PRESSURE_SENSOR_AVAILABLE} = 1 if ($B7 & 0x20); |
606 $dta->{COMPASS_AVAILABLE} = 1 if ($B7 & 0x10); |
612 $dta->{COMPASS_AVAILABLE} = 1 if ($B7 & 0x10); |
607 $dta->{PITCH_SENSOR_AVAILABLE} = 1 if ($B7 & 0x08); |
613 $dta->{PITCH_SENSOR_AVAILABLE} = 1 if ($B7 & 0x08); |
608 $dta->{ROLL_SENSOR_AVAILABLE} = 1 if ($B7 & 0x04); |
614 $dta->{ROLL_SENSOR_AVAILABLE} = 1 if ($B7 & 0x04); |
609 $dta->{CONDUCTIVITY_SENSOR_AVAILABLE} = 1 if ($B7 & 0x02); |
615 $dta->{CONDUCTIVITY_SENSOR_AVAILABLE} = 1 if ($B7 & 0x02); |
610 $dta->{TEMPERATURE_SENSOR_AVAILABLE} = 1 if ($B7 & 0x01); |
616 $dta->{TEMPERATURE_SENSOR_AVAILABLE} = 1 if ($B7 & 0x01); |
611 |
617 |
612 $dta->{DISTANCE_TO_BIN1_CENTER} /= 100; |
618 $dta->{DISTANCE_TO_BIN1_CENTER} /= 100; |
613 $dta->{TRANSMITTED_PULSE_LENGTH} /= 100; |
619 $dta->{TRANSMITTED_PULSE_LENGTH} /= 100; |
614 |
620 |
615 $dta->{FALSE_TARGET_THRESHOLD} = undef |
621 $dta->{FALSE_TARGET_THRESHOLD} = undef |
616 if ($dta->{FALSE_TARGET_THRESHOLD} == 255); |
622 if ($dta->{FALSE_TARGET_THRESHOLD} == 255); |
617 $dta->{TRANSMIT_LAG_DISTANCE} /= 100; |
623 $dta->{TRANSMIT_LAG_DISTANCE} /= 100; |
618 |
624 |
619 if ($dta->{INSTRUMENT_TYPE} eq 'Workhorse') { |
625 if ($dta->{INSTRUMENT_TYPE} eq 'Workhorse') { |
620 sysread(WBRF,$buf,11) == 11 || die("$WBRcfn: $!"); |
626 sysread(WBRF,$buf,11) == 11 || die("$WBRcfn: $!"); |
621 ($W1,$W2,$W3,$W4,$W5,$dta->{TRANSMIT_POWER}) = |
627 ($W1,$W2,$W3,$W4,$W5,$dta->{TRANSMIT_POWER}) = |
622 unpack('vvvvvC',$buf); |
628 unpack('vvvvvC',$buf); |
623 |
629 |
624 $dta->{CPU_SERIAL_NUMBER} = sprintf("%04X%04X%04X%04X",$W1,$W2,$W3,$W4); |
630 $dta->{CPU_SERIAL_NUMBER} = sprintf("%04X%04X%04X%04X",$W1,$W2,$W3,$W4); |
625 |
631 |
626 $dta->{NARROW_BANDWIDTH} = ($W5 == 1); |
632 $dta->{NARROW_BANDWIDTH} = ($W5 == 1); |
627 $dta->{WIDE_BANDWIDTH} = ($W5 == 0); |
633 $dta->{WIDE_BANDWIDTH} = ($W5 == 0); |
628 $dta->{TRANSMIT_POWER_HIGH} = ($dta->{TRANSMIT_POWER} == 255); |
634 $dta->{TRANSMIT_POWER_HIGH} = ($dta->{TRANSMIT_POWER} == 255); |
629 |
635 |
630 if ($dta->{FIXED_LEADER_BYTES} == 59) { # new style with serial number |
636 if ($dta->{FIXED_LEADER_BYTES} == 59) { # new style with serial number |
631 sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!"); |
637 sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!"); |
632 ($dummy,$dta->{SERIAL_NUMBER},$dummy) = # last bytes is beam angle, but that info has |
638 ($dummy,$dta->{SERIAL_NUMBER},$dummy) = # last bytes is beam angle, but that info has |
633 unpack('CVC',$buf); # already been provided above |
639 unpack('CVC',$buf); # already been provided above |
634 } |
640 } |
635 } |
641 } |
636 |
642 |
637 if ($dta->{INSTRUMENT_TYPE} eq 'Explorer') { |
643 if ($dta->{INSTRUMENT_TYPE} eq 'Explorer') { |
638 sysread(WBRF,$buf,16) == 16 || die("$WBRcfn: $!"); |
644 sysread(WBRF,$buf,16) == 16 || die("$WBRcfn: $!"); |
639 ($dummy,$dummy,$W5,$dummy,$dta->{SERIAL_NUMBER}) = |
645 ($dummy,$dummy,$W5,$dummy,$dta->{SERIAL_NUMBER}) = |
640 unpack('VVvvV',$buf); |
646 unpack('VVvvV',$buf); |
641 $dta->{NARROW_BANDWIDTH} = ($W5 == 1); |
647 $dta->{NARROW_BANDWIDTH} = ($W5 == 1); |
642 $dta->{WIDE_BANDWIDTH} = ($W5 == 0); |
648 $dta->{WIDE_BANDWIDTH} = ($W5 == 0); |
643 } |
649 } |
644 |
650 |
645 #----------------------- |
651 #----------------------- |
646 # 1st ENSEMBLE, BT Setup |
652 # 1st ENSEMBLE, BT Setup |
647 #----------------------- |
653 #----------------------- |
648 |
654 |
649 # CODE DISABLED BECAUSE BT_PRESENT FLAG WAS REMOVED. WITHOUT THIS CODE, |
655 # CODE DISABLED BECAUSE BT_PRESENT FLAG WAS REMOVED. WITHOUT THIS CODE, |
650 # [listHdr] DOES NOT LIST ANY BT INFO |
656 # [listHdr] DOES NOT LIST ANY BT INFO |
651 # |
657 # |
652 # if ($dta->{BT_PRESENT}) { |
658 # if ($dta->{BT_PRESENT}) { |
653 # sysseek(WBRF,$start_ens+$WBRofs[$BT_dt],0) || die("$WBRcfn: $!"); |
659 # sysseek(WBRF,$start_ens+$WBRofs[$BT_dt],0) || die("$WBRcfn: $!"); |
654 # sysread(WBRF,$buf,12) == 12 || die("$WBRcfn: $!"); |
660 # sysread(WBRF,$buf,12) == 12 || die("$WBRcfn: $!"); |
657 # $dta->{BT_MIN_PERCENT_GOOD},$dta->{BT_MODE}, |
663 # $dta->{BT_MIN_PERCENT_GOOD},$dta->{BT_MODE}, |
658 # $dta->{BT_MAX_ERROR_VELOCITY}) = unpack('vvvCCCCv',$buf); |
664 # $dta->{BT_MAX_ERROR_VELOCITY}) = unpack('vvvCCCCv',$buf); |
659 # |
665 # |
660 # $id == 0x0600 || |
666 # $id == 0x0600 || |
661 # printf(STDERR $FmtErr."\n",$WBRcfn,"Bottom Track",$id,0,tell(WBRF)); |
667 # printf(STDERR $FmtErr."\n",$WBRcfn,"Bottom Track",$id,0,tell(WBRF)); |
662 # |
668 # |
663 # $dta->{BT_MAX_ERROR_VELOCITY} = |
669 # $dta->{BT_MAX_ERROR_VELOCITY} = |
664 # $dta->{BT_MAX_ERROR_VELOCITY} ? $dta->{BT_MAX_ERROR_VELOCITY} / 1000 |
670 # $dta->{BT_MAX_ERROR_VELOCITY} ? $dta->{BT_MAX_ERROR_VELOCITY} / 1000 |
665 # : undef; |
671 # : undef; |
666 # |
672 # |
667 # sysseek(WBRF,28,1) || die("$WBRcfn: $!"); |
673 # sysseek(WBRF,28,1) || die("$WBRcfn: $!"); |
668 # sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!"); |
674 # sysread(WBRF,$buf,6) == 6 || die("$WBRcfn: $!"); |
669 # ($dta->{BT_RL_MIN_SIZE},$dta->{BT_RL_NEAR},$dta->{BT_RL_FAR}) |
675 # ($dta->{BT_RL_MIN_SIZE},$dta->{BT_RL_NEAR},$dta->{BT_RL_FAR}) |
670 # = unpack('vvv',$buf); |
676 # = unpack('vvv',$buf); |
671 # |
677 # |
672 # $dta->{BT_RL_MIN_SIZE} /= 10; |
678 # $dta->{BT_RL_MIN_SIZE} /= 10; |
673 # $dta->{BT_RL_NEAR} /= 10; |
679 # $dta->{BT_RL_NEAR} /= 10; |
674 # $dta->{BT_RL_FAR} /= 10; |
680 # $dta->{BT_RL_FAR} /= 10; |
675 # |
681 # |
676 # sysseek(WBRF,20,1) || die("$WBRcfn: $!"); # skip data |
682 # sysseek(WBRF,20,1) || die("$WBRcfn: $!"); # skip data |
677 # sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
683 # sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
678 # $dta->{BT_MAX_TRACKING_DEPTH} = unpack('v',$buf) / 10; |
684 # $dta->{BT_MAX_TRACKING_DEPTH} = unpack('v',$buf) / 10; |
679 # } |
685 # } |
680 |
686 |
681 return $dta; |
687 return $dta; |
682 } |
688 } |
683 |
689 |
684 #---------------------------------------------------------------------- |
690 #---------------------------------------------------------------------- |
685 # readData(file_name,^data[,first_ens,last_ens[,last_bin]]) |
691 # readData(file_name,^data[,first_ens,last_ens[,last_bin]]) |
686 # - read ensembles |
692 # - read ensembles |
687 # - read all ensembles unless first_ens and last_ens are given |
693 # - read all ensembles unless first_ens and last_ens are given |
688 # - read all bins unless last_bin is given |
694 # - read all bins unless last_bin is given |
689 # - if global var $readDataProgress > 0, a . is printed |
695 # - NB: CODE GETS PROGRESSIVELY SLOWER => HUGE PAIN FOR LARGE FILES |
690 # every $readaDataProgress ensembles |
|
691 #---------------------------------------------------------------------- |
696 #---------------------------------------------------------------------- |
692 |
697 |
693 sub readData(@) |
698 sub readData(@) |
694 { |
699 { |
695 my($fn,$dta,$fe,$le,$lb) = @_; |
700 my($fn,$dta,$fe,$le,$lb) = @_; |
696 $WBRcfn = $fn; |
701 $WBRcfn = $fn; |
697 open(WBRF,$WBRcfn) || die("$WBRcfn: $!\n"); |
702 open(WBRF,$WBRcfn) || die("$WBRcfn: $!\n"); |
698 WBRhdr($dta) || die("$WBRcfn: Insufficient Data\n"); |
703 WBRhdr($dta) || die("$WBRcfn: Insufficient Data\n"); |
699 $lb = $dta->{N_BINS} |
704 $lb = $dta->{N_BINS} |
700 unless (numberp($lb) && $lb>=1 && $lb<=$dta->{N_BINS}); |
705 unless (numberp($lb) && $lb>=1 && $lb<=$dta->{N_BINS}); |
701 WBRens($lb,$dta->{FIXED_LEADER_BYTES},\@{$dta->{ENSEMBLE}},$fe,$le); |
706 WBRens($lb,$dta->{FIXED_LEADER_BYTES},\@{$dta->{ENSEMBLE}},$fe,$le); |
702 print(STDERR "$WBRcfn: $BIT_errors built-in-test errors\n") |
707 print(STDERR "$WBRcfn: $BIT_errors built-in-test errors\n") |
703 if ($BIT_errors); |
708 if ($BIT_errors); |
704 } |
709 } |
708 my($nbins,$fixed_leader_bytes,$E,$fe,$le) = @_; |
713 my($nbins,$fixed_leader_bytes,$E,$fe,$le) = @_; |
709 my($B1,$B2,$B3,$B4,$I,$bin,$beam,$dummy,@dta,$i,$cs); |
714 my($B1,$B2,$B3,$B4,$I,$bin,$beam,$dummy,@dta,$i,$cs); |
710 my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$el); |
715 my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$el); |
711 local our($ndt,$buf,$id,$start_ens,@WBRofs); |
716 local our($ndt,$buf,$id,$start_ens,@WBRofs); |
712 |
717 |
713 sysseek(WBRF,0,0) || die("$WBRcfn: $!"); |
718 sysseek(WBRF,0,0) || die("$WBRcfn: $!"); |
714 ENSEMBLE: |
719 ENSEMBLE: |
715 for ($ens=0; 1; $ens++) { |
720 for ($ens=0; 1; $ens++) { |
716 # die unless defined($global::readDataProgress); |
721 print(STDERR '.') if ($RDI_PD0_IO::show_progress && $ens % 1000 == 0); |
717 print(STDERR '.') if ($global::readDataProgress>0 && ($ens%$global::readDataProgress)==0); |
|
718 $start_ens = goto_next_ens(\*WBRF); |
722 $start_ens = goto_next_ens(\*WBRF); |
719 last unless defined($start_ens); |
723 last unless defined($start_ens); |
720 |
724 |
721 #---------------------------------------- |
725 #---------------------------------------- |
722 # Handle first_ens and last_ens |
726 # Handle first_ens and last_ens |
746 ${$E}[$ens]->{PRODUCER} = 'IMP+LADCP (Thurnherr software)'; |
750 ${$E}[$ens]->{PRODUCER} = 'IMP+LADCP (Thurnherr software)'; |
747 } elsif ($did&0xF0 == 0xE0) { |
751 } elsif ($did&0xF0 == 0xE0) { |
748 ${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)'; |
752 ${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)'; |
749 } else { |
753 } else { |
750 ${$E}[$ens]->{PRODUCER} = 'unknown'; |
754 ${$E}[$ens]->{PRODUCER} = 'unknown'; |
751 } |
755 } |
752 |
756 |
753 if (defined($ens_length) && ($el != $ens_length)) { |
757 if (defined($ens_length) && ($el != $ens_length)) { |
754 $RDI_PD0_IO::File_Dirty = 1; |
758 $RDI_PD0_IO::File_Dirty = 1; |
755 print(STDERR "WARNING (RDI_PD0_IO): ensemble ${$E}[$#{$E}]->{NUMBER} skipped (unexpected length)\n"); |
759 print(STDERR "WARNING (RDI_PD0_IO): ensemble ${$E}[$#{$E}]->{NUMBER} skipped (unexpected length)\n"); |
756 pop(@{$E}); |
760 pop(@{$E}); |
757 $ens--; |
761 $ens--; |
758 next; |
762 next; |
759 } |
763 } |
760 |
764 |
761 $ens_length = $el; |
765 $ens_length = $el; |
762 |
766 |
763 ## printf(STDERR "$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
767 ## printf(STDERR "$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
764 ## unless ($ndt == 6 || $ndt == 7); |
768 ## unless ($ndt == 6 || $ndt == 7); |
765 my($nread) = sysread(WBRF,$buf,2*$ndt); # 2019 EPR test |
769 my($nread) = sysread(WBRF,$buf,2*$ndt); # 2019 EPR test |
792 |
796 |
793 unless (unpack('%16C*',$buf) == unpack('v',$cs)) { # bad checksum |
797 unless (unpack('%16C*',$buf) == unpack('v',$cs)) { # bad checksum |
794 # print(STDERR "BAD CHECKSUM\n"); |
798 # print(STDERR "BAD CHECKSUM\n"); |
795 pop(@{$E}); $ens--; |
799 pop(@{$E}); $ens--; |
796 next; |
800 next; |
797 } |
801 } |
798 |
802 |
799 #------------------------------ |
803 #------------------------------ |
800 # Variable Leader |
804 # Variable Leader |
801 #------------------------------ |
805 #------------------------------ |
802 |
806 |
803 my($lastEns) = $ensNo; |
807 my($lastEns) = $ensNo; |
804 sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!"); |
808 sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!"); |
805 sysread(WBRF,$buf,4) == 4 || die("$WBRcfn: $!"); |
809 sysread(WBRF,$buf,4) == 4 || die("$WBRcfn: $!"); |
806 ($id,$ensNo) = unpack("vv",$buf); # only lower two bytes!!! |
810 ($id,$ensNo) = unpack("vv",$buf); # only lower two bytes!!! |
807 |
811 |
808 if (${$E}[$ens]->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
812 if (${$E}[$ens]->{INSTRUMENT_TYPE} eq 'Ocean Surveyor') { |
809 $id == 0x0081 || |
813 $id == 0x0081 || |
810 die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF)))); |
814 die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF)))); |
811 } else { |
815 } else { |
812 $id == 0x0080 || |
816 $id == 0x0080 || |
813 die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF)))); |
817 die(sprintf($FmtErr,$WBRcfn,"Variable Leader",$id,$ensNo + ($lastEns - ($lastEns & 0xFFFF)))); |
814 } |
818 } |
815 |
819 |
816 # if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) { # BB150 & Explorer DVL (if DISABLED!) |
820 # if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) { # BB150 & Explorer DVL (if DISABLED!) |
817 sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!"); # always read pre-Y2K clock |
821 sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!"); # always read pre-Y2K clock |
818 (${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH}, |
822 (${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH}, |
819 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE}, |
823 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE}, |
860 ${$E}[$ens]->{XDUCER_DEPTH} /= 10; |
864 ${$E}[$ens]->{XDUCER_DEPTH} /= 10; |
861 |
865 |
862 #------------------------------------------------- |
866 #------------------------------------------------- |
863 # IMP EXTENSION: PITCH/ROLL/HEADING CAN BE MISSING |
867 # IMP EXTENSION: PITCH/ROLL/HEADING CAN BE MISSING |
864 #------------------------------------------------- |
868 #------------------------------------------------- |
865 |
869 |
866 ${$E}[$ens]->{HEADING} = (${$E}[$ens]->{HEADING} == 0xF000) |
870 ${$E}[$ens]->{HEADING} = (${$E}[$ens]->{HEADING} == 0xF000) |
867 ? undef |
871 ? undef |
868 : ${$E}[$ens]->{HEADING} / 100; |
872 : ${$E}[$ens]->{HEADING} / 100; |
869 ${$E}[$ens]->{PITCH} = (${$E}[$ens]->{PITCH} == 0x8000) |
873 ${$E}[$ens]->{PITCH} = (${$E}[$ens]->{PITCH} == 0x8000) |
870 ? undef |
874 ? undef |
871 : unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100; |
875 : unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100; |
872 ${$E}[$ens]->{ROLL} = (${$E}[$ens]->{ROLL} == 0x8000) |
876 ${$E}[$ens]->{ROLL} = (${$E}[$ens]->{ROLL} == 0x8000) |
873 ? undef |
877 ? undef |
874 : unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100; |
878 : unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100; |
875 |
879 |
876 ${$E}[$ens]->{TEMPERATURE} = unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100; |
880 ${$E}[$ens]->{TEMPERATURE} = unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100; |
877 ${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60; |
881 ${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60; |
878 ${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100; |
882 ${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100; |
879 ${$E}[$ens]->{PITCH_STDDEV} /= 10; |
883 ${$E}[$ens]->{PITCH_STDDEV} /= 10; |
880 ${$E}[$ens]->{ROLL_STDDEV} /= 10; |
884 ${$E}[$ens]->{ROLL_STDDEV} /= 10; |
881 |
885 |
882 if (($fixed_leader_bytes==53 || $fixed_leader_bytes==59) && # Workhorse instruments |
886 if (($fixed_leader_bytes==53 || $fixed_leader_bytes==59) && # Workhorse instruments |
883 !defined($RDI_PD0_IO::IGNORE_Y2K_CLOCK)) { |
887 !defined($RDI_PD0_IO::IGNORE_Y2K_CLOCK)) { |
884 sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!"); |
888 sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!"); |
885 (${$E}[$ens]->{ERROR_STATUS_WORD}, |
889 (${$E}[$ens]->{ERROR_STATUS_WORD}, |
886 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV}, |
890 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV}, |
887 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH}, |
891 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH}, |
888 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE}, |
892 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE}, |
889 ${$E}[$ens]->{SECOND},$B4) |
893 ${$E}[$ens]->{SECOND},$B4) |
890 = unpack('VvVVCCCCCCCCC',$buf); |
894 = unpack('VvVVCCCCCCCCC',$buf); |
891 |
895 |
893 ${$E}[$ens]->{PRESSURE_STDDEV} /= 1000; |
897 ${$E}[$ens]->{PRESSURE_STDDEV} /= 1000; |
894 ${$E}[$ens]->{YEAR} *= 100; ${$E}[$ens]->{YEAR} += $B3; |
898 ${$E}[$ens]->{YEAR} *= 100; ${$E}[$ens]->{YEAR} += $B3; |
895 ${$E}[$ens]->{SECOND} += $B4/100; |
899 ${$E}[$ens]->{SECOND} += $B4/100; |
896 } |
900 } |
897 |
901 |
898 # THE FOLLOWING LINE OF CODE WAS REMOVED 7/30/2016 WHEN I ADDED A POP |
902 # THE FOLLOWING LINE OF CODE WAS REMOVED 7/30/2016 WHEN I ADDED A POP |
899 # TO THE last STATEMENT ABOVE (INCOMPLETE ENSEMBLE) |
903 # TO THE last STATEMENT ABOVE (INCOMPLETE ENSEMBLE) |
900 # THE LINE WAS RE-ENABLED ON 12/23/2017 BECAUSE OTHERWISE THE |
904 # THE LINE WAS RE-ENABLED ON 12/23/2017 BECAUSE OTHERWISE THE |
901 # ANSLOPE II PROFILES IN THE HOWTO CANNOT BE READ. |
905 # ANSLOPE II PROFILES IN THE HOWTO CANNOT BE READ. |
902 pop(@{$E}),last if (${$E}[$ens]->{MONTH}>12); # 10/15/2014; IWISE#145 UL ??? |
906 pop(@{$E}),last if (${$E}[$ens]->{MONTH}>12); # 10/15/2014; IWISE#145 UL ??? |
903 |
907 |
904 if ($fixed_leader_bytes == 58) { # Explorer DVL |
908 if ($fixed_leader_bytes == 58) { # Explorer DVL |
905 sysread(WBRF,$buf,14) == 14 || die("$WBRcfn: $!"); |
909 sysread(WBRF,$buf,14) == 14 || die("$WBRcfn: $!"); |
906 (${$E}[$ens]->{ERROR_STATUS_WORD}, |
910 (${$E}[$ens]->{ERROR_STATUS_WORD}, |
907 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV}) |
911 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV}) |
908 = unpack('VvVV',$buf); |
912 = unpack('VvVV',$buf); |
909 ${$E}[$ens]->{PRESSURE} /= 1000; |
913 ${$E}[$ens]->{PRESSURE} /= 1000; |
910 ${$E}[$ens]->{PRESSURE_STDDEV} /= 1000; |
914 ${$E}[$ens]->{PRESSURE_STDDEV} /= 1000; |
911 } |
915 } |
912 |
916 |
913 ${$E}[$ens]->{DATE} |
917 ${$E}[$ens]->{DATE} |
914 = sprintf("%02d/%02d/%d",${$E}[$ens]->{MONTH}, |
918 = sprintf("%02d/%02d/%d",${$E}[$ens]->{MONTH}, |
915 ${$E}[$ens]->{DAY}, |
919 ${$E}[$ens]->{DAY}, |
916 ${$E}[$ens]->{YEAR}); |
920 ${$E}[$ens]->{YEAR}); |
917 ${$E}[$ens]->{TIME} |
921 ${$E}[$ens]->{TIME} |
940 |
944 |
941 $dayStart = timegm(0,0,0,${$E}[$ens]->{DAY}, |
945 $dayStart = timegm(0,0,0,${$E}[$ens]->{DAY}, |
942 ${$E}[$ens]->{MONTH}-1, |
946 ${$E}[$ens]->{MONTH}-1, |
943 ${$E}[$ens]->{YEAR}) |
947 ${$E}[$ens]->{YEAR}) |
944 unless defined($dayStart); |
948 unless defined($dayStart); |
945 ${$E}[$ens]->{SECNO} = ${$E}[$ens]->{UNIX_TIME} - $dayStart; |
949 ${$E}[$ens]->{SECNO} = ${$E}[$ens]->{UNIX_TIME} - $dayStart; |
946 } |
950 } |
947 |
951 |
948 sysseek(WBRF,$start_ens+$WBRofs[0]+4,0) # System Config / Fixed Leader |
952 sysseek(WBRF,$start_ens+$WBRofs[0]+4,0) # System Config / Fixed Leader |
949 || die("$WBRcfn: $!"); |
953 || die("$WBRcfn: $!"); |
950 |
954 |
951 sysread(WBRF,$buf,5) == 5 || die("$WBRcfn: $!"); |
955 sysread(WBRF,$buf,5) == 5 || die("$WBRcfn: $!"); |
952 ($B1,$dummy,$dummy,$dummy,${$E}[$ens]->{N_BEAMS_USED}) |
956 ($B1,$dummy,$dummy,$dummy,${$E}[$ens]->{N_BEAMS_USED}) |
953 = unpack('CCCCC',$buf); |
957 = unpack('CCCCC',$buf); |
954 ${$E}[$ens]->{XDUCER_FACING_UP} = 1 if ($B1 & 0x80); |
958 ${$E}[$ens]->{XDUCER_FACING_UP} = 1 if ($B1 & 0x80); |
955 ${$E}[$ens]->{XDUCER_FACING_DOWN} = 1 unless ($B1 & 0x80); |
959 ${$E}[$ens]->{XDUCER_FACING_DOWN} = 1 unless ($B1 & 0x80); |
956 |
960 |
957 #-------------------- |
961 #-------------------- |
958 # Velocity Data |
962 # Velocity Data |
959 #-------------------- |
963 #-------------------- |