95 # - added support for RDI_PD0_IO::IGNORE_Y2K_CLOCK |
95 # - added support for RDI_PD0_IO::IGNORE_Y2K_CLOCK |
96 # Dec 7, 2017: - added suppress_error to readHeader() |
96 # Dec 7, 2017: - added suppress_error to readHeader() |
97 # Dec 23, 2017: - BUG: could no longer read Anslope II raw files |
97 # Dec 23, 2017: - BUG: could no longer read Anslope II raw files |
98 # - added support for patching ADCP time data |
98 # - added support for patching ADCP time data |
99 # - added support for RDI_PD0_IO::OVERRIDE_Y2K_CLOCK |
99 # - added support for RDI_PD0_IO::OVERRIDE_Y2K_CLOCK |
|
100 # Feb 6, 2018: - added supprort for first_ens, last_ens in readData() |
|
101 # Feb 7, 2018: - BUG: new params were not optional |
|
102 # - made read routines more permissive by allowing |
|
103 # garbage between ensembles |
|
104 # Mar 15, 2018: - BUG: WBPens() did not work for files with garbage |
|
105 # Mar 16, 2018: - added skipped garbage warning |
|
106 # - BUG: garbage skipping did not work correctly for files w/o BT |
|
107 # Mar 20, 2018: - BUG: garbage skipping STILL did not work correctly for files w/o BT |
|
108 # Apr 9, 2018: - added last_bin argument to readData() |
|
109 # Apr 10, 2018: - slight improvement (parameter range check) |
|
110 # Apr 23, 2018: - make WBRens() work (again?) with BB150 data froim 1996 |
|
111 # Apr 24, 2018: - BUG: undefined lat_bin argument to readData() did not work |
|
112 # Apr 30, 2018: - added support for repeated ensembles |
|
113 # - added warning on wrong ensemble length |
|
114 # Jun 9, 2018: - removed double \n from warnings |
|
115 # Jun 12, 2018: - BUG: IMPed files did not pass the garbage detection |
100 |
116 |
101 # FIRMWARE VERSIONS: |
117 # FIRMWARE VERSIONS: |
102 # It appears that different firmware versions generate different file |
118 # It appears that different firmware versions generate different file |
103 # structures. Currently (Sep 2005) these routines have been tested |
119 # structures. Currently (Sep 2005) these routines have been tested |
104 # with the following firmware versions (as reported by [listHdr]): |
120 # with the following firmware versions (as reported by [listHdr]): |
117 # - first ensemble uses default RDI DATA_SOURCE_ID because the LDEO_IX |
133 # - first ensemble uses default RDI DATA_SOURCE_ID because the LDEO_IX |
118 # software assumes this |
134 # software assumes this |
119 # |
135 # |
120 # - DATA_SOURCE_ID = 0x7F original TRDI PD0 file |
136 # - DATA_SOURCE_ID = 0x7F original TRDI PD0 file |
121 # |
137 # |
122 # - DATA_SOURCE_ID = 0xA0 | PATCHED_MASK produced by IMP+LADP |
138 # - DATA_SOURCE_ID = 0xA0 | PATCHED_MASK produced by IMP+LADCP, KVH+LADCP |
123 # PATCHED_MASK & 0x04: pitch value has been patched |
139 # PATCHED_MASK & 0x04: pitch value has been patched |
124 # PATCHED_MASK & 0x02: roll value has been patched |
140 # PATCHED_MASK & 0x02: roll value has been patched |
125 # PATCHED_MASK & 0x01: heading value has been patched |
141 # PATCHED_MASK & 0x01: heading value has been patched |
126 # - PITCH & ROLL can be missing (0x8000 badval as in velocities) |
142 # - PITCH & ROLL can be missing (0x8000 badval as in velocities) |
127 # - HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading) |
143 # - HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading) |
355 my($BIT_errors) = 0; # built-in-test errors |
371 my($BIT_errors) = 0; # built-in-test errors |
356 |
372 |
357 my($FmtErr) = "%s: illegal %s Id 0x%04x at ensemble %d"; |
373 my($FmtErr) = "%s: illegal %s Id 0x%04x at ensemble %d"; |
358 |
374 |
359 #---------------------------------------------------------------------- |
375 #---------------------------------------------------------------------- |
360 # skip to first valid ensemble (skip over initial garbage) |
376 # skip to next valid start of ensemble (skip over garbage) |
361 #---------------------------------------------------------------------- |
377 #---------------------------------------------------------------------- |
362 |
378 |
363 sub skip_initial_trash(@) |
379 sub goto_next_ens(@) |
364 { |
380 { |
365 my($quiet) = @_; |
381 my($fh,$return_skipped) = @_; # if return_skipped not set, return file pos |
366 my($buf,$dta); |
382 my($buf,$dta); |
367 |
383 |
368 my($found) = 0; # zero consecutive 0x7f found |
384 my($found) = 0; # zero consecutive 0x7f found |
369 my($skipped) = 0; |
385 my($skipped) = 0; my($garbage_start); |
370 while ($found < 2) { |
386 while ($found < 2) { |
371 sysread(WBRF,$buf,1) == 1 || last; |
387 sysread($fh,$buf,1) == 1 || last; |
372 ($dta) = unpack('C',$buf); |
388 ($dta) = unpack('C',$buf); |
373 if ($dta == 0x7f) { |
389 if ($dta == 0x7f) { |
374 $found++; |
390 $found++; |
375 } elsif ($found==1 && ($dta==0xE0 || ($dta&0xF0==0xA0 && $dta&0x0F<8))) { |
391 } elsif ($found==1 && |
376 $found++; |
392 ($dta==0xE0 || # from editPD0 |
377 } elsif ($found == 0) { |
393 (($dta&0xF0)==0xA0 && ($dta&0x0F)<8))) { # from IMP+LADCP or KVH+LADCP |
378 $skipped++; |
394 $found++; |
379 } else { |
395 } elsif ($found == 0) { |
380 $skipped += $found; |
396 $garbage_start = sysseek($fh,0,1)-1 unless defined($garbage_start); |
381 $found = 0; |
397 $skipped++; |
382 } |
398 } else { # here, found == 1 but 2nd byte was not found |
383 } |
399 $garbage_start = sysseek($fh,0,1)-$found unless defined($garbage_start); |
384 die("$WBRcfn: no valid ensemble header found [$!]\n") |
400 $skipped += $found; |
385 if ($found < 2); |
401 $found = 0; |
386 printf(STDERR "WARNING: %d bytes of initial garbage\n",$skipped) |
402 } |
387 if ($skipped > 0 && !$quiet); |
|
388 return sysseek(WBRF,-2,1); |
|
389 } |
403 } |
|
404 my($fpos) = ($found < 2) ? undef : sysseek($fh,-2,1); |
|
405 return $skipped if ($return_skipped); |
|
406 |
|
407 if ($skipped) { |
|
408 if (eof($fh)) { |
|
409 # 04/18/18: disabled the following line of code because it is very common at |
|
410 # least with the older RDI instruments I am looking at in the context |
|
411 # of the SR1b repeat section analysis |
|
412 # print(STDERR "WARNING (RDI_PD0_IO): PD0 file ends with $skipped garbage bytes\n"); |
|
413 } elsif ($garbage_start == 0) { |
|
414 print(STDERR "WARNING (RDI_PD0_IO): PD0 file starts with $skipped garbage bytes\n"); |
|
415 } else { |
|
416 print(STDERR "WARNING (RDI_PD0_IO): $skipped garbage bytes in PD0 file beginning at byte $garbage_start\n"); |
|
417 } |
|
418 } |
|
419 |
|
420 return $fpos; |
|
421 } |
390 |
422 |
391 #---------------------------------------------------------------------- |
423 #---------------------------------------------------------------------- |
392 # readHeader(file_name,^dta) WBRhdr(^data) |
424 # readHeader(file_name,^dta) WBRhdr(^data) |
393 # - read header data |
425 # - read header data |
394 # - also includes some data from 1st ens |
426 # - also includes some data from 1st ens |
417 |
449 |
418 #-------------------- |
450 #-------------------- |
419 # HEADER |
451 # HEADER |
420 #-------------------- |
452 #-------------------- |
421 |
453 |
422 skip_initial_trash(); |
454 my($skipped) = goto_next_ens(\*WBRF,1); |
|
455 printf(STDERR "WARNING: %d bytes of initial garbage\n",$skipped) |
|
456 if ($skipped > 0); |
|
457 |
423 sysread(WBRF,$buf,6) == 6 || return undef; |
458 sysread(WBRF,$buf,6) == 6 || return undef; |
424 ($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES}) |
459 ($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES}) |
425 = unpack('CCvCC',$buf); |
460 = unpack('CCvCC',$buf); |
426 $hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (hid)",$hid,0)); |
461 $hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (hid)",$hid,0)); |
427 $did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (did)",$did,0)); |
462 $did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (did)",$did,0)); |
696 |
731 |
697 return $dta; |
732 return $dta; |
698 } |
733 } |
699 |
734 |
700 #---------------------------------------------------------------------- |
735 #---------------------------------------------------------------------- |
701 # readData(file_name,^data) WBRens(nbins,fixed_leader_bytes,^data) |
736 # readData(file_name,^data[,first_ens,last_ens[,last_bin]]) |
702 # - read all ensembles |
737 # - read ensembles |
|
738 # - read all ensembles unless first_ens and last_ens are given |
|
739 # - read all bins unless last_bin is given |
703 #---------------------------------------------------------------------- |
740 #---------------------------------------------------------------------- |
704 |
741 |
705 sub readData(@) |
742 sub readData(@) |
706 { |
743 { |
707 my($fn,$dta) = @_; |
744 my($fn,$dta,$fe,$le,$lb) = @_; |
708 $WBRcfn = $fn; |
745 $WBRcfn = $fn; |
709 open(WBRF,$WBRcfn) || die("$WBRcfn: $!\n"); |
746 open(WBRF,$WBRcfn) || die("$WBRcfn: $!\n"); |
710 WBRhdr($dta,1) || die("$WBRcfn: Insufficient Data\n"); |
747 WBRhdr($dta,1) || die("$WBRcfn: Insufficient Data\n"); |
711 WBRens($dta->{N_BINS},$dta->{FIXED_LEADER_BYTES}, |
748 $lb = $dta->{N_BINS} |
712 \@{$dta->{ENSEMBLE}}); |
749 unless (numberp($lb) && $lb>=1 && $lb<=$dta->{N_BINS}); |
|
750 WBRens($lb,$dta->{FIXED_LEADER_BYTES},\@{$dta->{ENSEMBLE}},$fe,$le); |
713 print(STDERR "$WBRcfn: $BIT_errors built-in-test errors\n") |
751 print(STDERR "$WBRcfn: $BIT_errors built-in-test errors\n") |
714 if ($BIT_errors); |
752 if ($BIT_errors); |
715 } |
753 } |
716 |
754 |
717 sub WBRens($$$) |
755 sub WBRens(@) |
718 { |
756 { |
719 my($nbins,$fixed_leader_bytes,$E) = @_; |
757 my($nbins,$fixed_leader_bytes,$E,$fe,$le) = @_; |
720 my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBRofs); |
758 my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBRofs); |
721 my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$ndt); |
759 my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$ndt,$el); |
722 |
760 |
723 sysseek(WBRF,0,0) || die("$WBRcfn: $!"); |
761 sysseek(WBRF,0,0) || die("$WBRcfn: $!"); |
724 $start_ens = skip_initial_trash(1); |
762 ENSEMBLE: |
725 for ($ens=0; 1; $ens++,$start_ens+=$ens_length+2) { |
763 for ($ens=0; 1; $ens++) { |
726 # print(STDERR "ens = $ens\n"); |
764 $start_ens = goto_next_ens(\*WBRF); |
727 # print(STDERR "start_ens = $start_ens\n"); |
765 last unless defined($start_ens); |
|
766 |
|
767 #---------------------------------------- |
|
768 # Handle first_ens and last_ens |
|
769 #---------------------------------------- |
|
770 |
|
771 if (defined($fe) && $ens>0 && ${$E}[$ens-1]->{NUMBER}<$fe) { # delete previous ensemble |
|
772 pop(@{$E}); $ens--; |
|
773 } |
|
774 |
|
775 if (defined($le) && $ens>0 && ${$E}[$ens-1]->{NUMBER}>$le) { # delete previous ensemble and finish |
|
776 pop(@{$E}); $ens--; |
|
777 last; |
|
778 } |
728 |
779 |
729 #---------------------------------------- |
780 #---------------------------------------- |
730 # Get ensemble length and # of data types |
781 # Get ensemble length and # of data types |
731 #---------------------------------------- |
782 #---------------------------------------- |
732 |
783 |
733 sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!"); |
784 sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!"); |
734 sysread(WBRF,$buf,6) == 6 || last; |
785 sysread(WBRF,$buf,6) == 6 || last; |
735 ($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf); |
786 ($hid,$did,$el,$dummy,$ndt) = unpack('CCvCC',$buf); |
736 $hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,defined($ensNo)?$ensNo+1:0)); |
787 $hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,defined($ensNo)?$ensNo+1:0)); |
737 ${$E}[$ens]->{DATA_SOURCE_ID} = $did; |
788 ${$E}[$ens]->{DATA_SOURCE_ID} = $did; |
738 if ($did == 0x7f) { |
789 if ($did == 0x7f) { |
739 ${$E}[$ens]->{PRODUCER} = 'TRDI ADCP'; |
790 ${$E}[$ens]->{PRODUCER} = 'TRDI ADCP'; |
740 } elsif ($did&0xF0 == 0xA0) { |
791 } elsif ($did&0xF0 == 0xA0) { |
743 ${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)'; |
794 ${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)'; |
744 } else { |
795 } else { |
745 ${$E}[$ens]->{PRODUCER} = 'unknown'; |
796 ${$E}[$ens]->{PRODUCER} = 'unknown'; |
746 } |
797 } |
747 |
798 |
748 ## printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
799 if (defined($ens_length) && ($el != $ens_length)) { |
|
800 print(STDERR "WARNING (RDI_PD0_IO): ensemble ${$E}[$#{$E}]->{NUMBER} skipped (unexpected length)\n"); |
|
801 pop(@{$E}); |
|
802 $ens--; |
|
803 next; |
|
804 } |
|
805 |
|
806 $ens_length = $el; |
|
807 |
|
808 ## printf(STDERR "$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
749 ## unless ($ndt == 6 || $ndt == 7); |
809 ## unless ($ndt == 6 || $ndt == 7); |
750 sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!"); |
810 sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!"); |
751 @WBRofs = unpack("v$ndt",$buf); |
811 @WBRofs = unpack("v$ndt",$buf); |
752 $fixed_leader_bytes = $WBRofs[1] - $WBRofs[0]; |
812 $fixed_leader_bytes = $WBRofs[1] - $WBRofs[0]; |
753 # print(STDERR "@WBRofs\n"); |
813 # print(STDERR "@WBRofs\n"); |
761 # final ensemble. |
821 # final ensemble. |
762 |
822 |
763 sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!"); |
823 sysseek(WBRF,$start_ens,0) || die("$WBRcfn: $!"); |
764 unless ((sysread(WBRF,$buf,$ens_length) == $ens_length) && # incomplete ensemble |
824 unless ((sysread(WBRF,$buf,$ens_length) == $ens_length) && # incomplete ensemble |
765 (sysread(WBRF,$cs,2) == 2)) { |
825 (sysread(WBRF,$cs,2) == 2)) { |
|
826 # print(STDERR "INCOMPLETE ENSEMBLE\n"); |
766 pop(@{$E}); |
827 pop(@{$E}); |
767 last; |
828 last; |
768 } |
829 } |
769 |
830 |
770 unless (unpack('%16C*',$buf) == unpack('v',$cs)) { # bad checksum |
831 unless (unpack('%16C*',$buf) == unpack('v',$cs)) { # bad checksum |
771 pop(@{$E}); |
832 # print(STDERR "BAD CHECKSUM\n"); |
772 last; |
833 pop(@{$E}); $ens--; |
773 # next; # using this might make the code work |
834 next; |
774 } # for files with isolated bad ensembles |
835 } |
775 |
836 |
776 #------------------------------ |
837 #------------------------------ |
777 # Variable Leader |
838 # Variable Leader |
778 #------------------------------ |
839 #------------------------------ |
779 |
840 |
801 # sysseek(WBRF,7,1) || die("$WBRcfn: $!"); # use Y2K RTC instead |
862 # sysseek(WBRF,7,1) || die("$WBRcfn: $!"); # use Y2K RTC instead |
802 # } |
863 # } |
803 |
864 |
804 sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!"); |
865 sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!"); |
805 $ensNo += unpack('C',$buf) << 16; |
866 $ensNo += unpack('C',$buf) << 16; |
|
867 |
|
868 for (my($i)=$ens; $i>0; $i--) { # check for duplicate ens; e.g. 2018 S4P 24UL |
|
869 if (${$E}[$i]->{NUMBER} == $ensNo) { |
|
870 print(STDERR "WARNING (RDI_PD0_IO): duplicate ensemble $ensNo skipped\n"); |
|
871 pop(@{$E}); |
|
872 $ens--; |
|
873 next ENSEMBLE; |
|
874 } |
|
875 } |
|
876 |
806 ${$E}[$ens]->{NUMBER} = $ensNo; |
877 ${$E}[$ens]->{NUMBER} = $ensNo; |
807 |
878 |
808 sysread(WBRF,$buf,30) == 30 || die("$WBRcfn: $!"); |
879 sysread(WBRF,$buf,30) == 30 || die("$WBRcfn: $!"); |
809 (${$E}[$ens]->{BUILT_IN_TEST_ERROR},${$E}[$ens]->{SPEED_OF_SOUND}, |
880 (${$E}[$ens]->{BUILT_IN_TEST_ERROR},${$E}[$ens]->{SPEED_OF_SOUND}, |
810 ${$E}[$ens]->{XDUCER_DEPTH},${$E}[$ens]->{HEADING}, |
881 ${$E}[$ens]->{XDUCER_DEPTH},${$E}[$ens]->{HEADING}, |
886 ${$E}[$ens]->{SECONDS}); |
957 ${$E}[$ens]->{SECONDS}); |
887 ${$E}[$ens]->{DAYNO} |
958 ${$E}[$ens]->{DAYNO} |
888 = &_dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY}, |
959 = &_dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY}, |
889 ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECONDS}); |
960 ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECONDS}); |
890 |
961 |
891 # when analyzing an STA file from an OS75 SADCP (Poseidion), |
962 # when analyzing an STA file from an OS75 SADCP (Poseidon), |
892 # I noticed that there is no time information. This causes |
963 # I noticed that there is no time information. This causes |
893 # timegm to bomb. |
964 # timegm to bomb. |
894 if (${$E}[$ens]->{MONTH} == 0) { # no time info |
965 if (${$E}[$ens]->{MONTH} == 0) { # no time info |
895 ${$E}[$ens]->{UNIX_TIME} = 0; |
966 ${$E}[$ens]->{UNIX_TIME} = 0; |
896 ${$E}[$ens]->{SECNO} = 0; |
967 ${$E}[$ens]->{SECNO} = 0; |
897 } else { |
968 } else { |
898 # print(STDERR "\n[$ens]->${$E}[$ens]->{MINUTE}:${$E}[$ens]->{HOUR},${$E}[$ens]->{DAY},${$E}[$ens]->{MONTH},${$E}[$ens]->{YEAR}-<\n"); |
969 # print(STDERR "[$ens]->${$E}[$ens]->{MINUTE}:${$E}[$ens]->{HOUR},${$E}[$ens]->{DAY},${$E}[$ens]->{MONTH},${$E}[$ens]->{YEAR}-<\n"); |
899 ${$E}[$ens]->{UNIX_TIME} |
970 ${$E}[$ens]->{UNIX_TIME} |
900 = timegm(0,${$E}[$ens]->{MINUTE}, |
971 = timegm(0,${$E}[$ens]->{MINUTE}, |
901 ${$E}[$ens]->{HOUR}, |
972 ${$E}[$ens]->{HOUR}, |
902 ${$E}[$ens]->{DAY}, |
973 ${$E}[$ens]->{DAY}, |
903 ${$E}[$ens]->{MONTH}-1, # timegm jan==0!!! |
974 ${$E}[$ens]->{MONTH}-1, # timegm jan==0!!! |
1007 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
1075 sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!"); |
1008 $id = unpack('v',$buf); |
1076 $id = unpack('v',$buf); |
1009 last if ($id == 0x0600); |
1077 last if ($id == 0x0600); |
1010 } |
1078 } |
1011 |
1079 |
1012 next if ($nxt == $ndt); # no BT found => next ens |
1080 if ($nxt == $ndt) { # no BT found => next ens |
|
1081 # sysseek(WBRF,4,1) || die("$WBRcfn: $!"); # skip over remainder of ensemble |
|
1082 sysseek(WBRF,$start_ens+$ens_length+2,0) || die("$WBRcfn: $!"); |
|
1083 next; |
|
1084 } |
1013 |
1085 |
1014 sysseek(WBRF,14,1) || die("$WBRcfn: $!"); # BT range, velocity, corr, %-good, ... |
1086 sysseek(WBRF,14,1) || die("$WBRcfn: $!"); # BT range, velocity, corr, %-good, ... |
1015 sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!"); |
1087 sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!"); |
1016 @dta = unpack('v4v4C4C4C4',$buf); |
1088 @dta = unpack('v4v4C4C4C4',$buf); |
1017 for ($beam=0; $beam<4; $beam++) { |
1089 for ($beam=0; $beam<4; $beam++) { |
1052 for ($beam=0; $beam<4; $beam++) { |
1124 for ($beam=0; $beam<4; $beam++) { |
1053 ${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam]; |
1125 ${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam]; |
1054 } |
1126 } |
1055 |
1127 |
1056 sysseek(WBRF,2,1) || die("$WBRcfn: $!"); # BT signal strength & BT range high bytes |
1128 sysseek(WBRF,2,1) || die("$WBRcfn: $!"); # BT signal strength & BT range high bytes |
1057 sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!"); |
1129 # sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!"); |
1058 @dta = unpack('C4CC4',$buf); |
1130 if (sysread(WBRF,$buf,9) == 9) { # SR1b JR16 BB150 data files require this |
1059 for ($beam=0; $beam<4; $beam++) { |
1131 @dta = unpack('C4CC4',$buf); |
1060 ${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam]; |
1132 for ($beam=0; $beam<4; $beam++) { |
1061 } |
1133 ${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam]; |
1062 ${$E}[$ens]->{HIGH_GAIN} if ($dta[4]); |
1134 } |
1063 ${$E}[$ens]->{LOW_GAIN} unless ($dta[4]); |
1135 ${$E}[$ens]->{HIGH_GAIN} if ($dta[4]); |
1064 for ($beam=0; $beam<4; $beam++) { # high bytes (1 byte per beam) |
1136 ${$E}[$ens]->{LOW_GAIN} unless ($dta[4]); |
1065 ${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36 |
1137 for ($beam=0; $beam<4; $beam++) { # high bytes (1 byte per beam) |
1066 if ($dta[5+$beam]); |
1138 ${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36 |
1067 } |
1139 if ($dta[5+$beam]); |
|
1140 } |
|
1141 # sysseek(WBRF,8,1) || die("$WBRcfn: $!"); # remainder of ensemble |
|
1142 } |
|
1143 sysseek(WBRF,$start_ens+$ens_length+2,0) || die("$WBRcfn: $!"); |
1068 } # ens loop |
1144 } # ens loop |
1069 } |
1145 } |
1070 |
1146 |
1071 #---------------------------------------------------------------------- |
1147 #---------------------------------------------------------------------- |
1072 # writeData(output_file_name,^data) WBPens(nbins,fixed_leader_bytes,^data) |
1148 # writeData(output_file_name,^data) WBPens(nbins,fixed_leader_bytes,^data) |
1114 |
1190 |
1115 sub WBPens($$$) |
1191 sub WBPens($$$) |
1116 { |
1192 { |
1117 my($nbins,$fixed_leader_bytes,$dta) = @_; |
1193 my($nbins,$fixed_leader_bytes,$dta) = @_; |
1118 my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs); |
1194 my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs); |
1119 my($ens,$dayStart,$ens_length,$hid,$ndt); |
1195 my($ens,$dayStart,$ens_length,$hid,$ndt,$el); |
1120 |
1196 |
1121 for ($ens=$start_ens=0; $ens<=$#{$dta->{ENSEMBLE}}; $ens++,$start_ens+=$ens_length+2) { |
1197 # for ($ens=$start_ens=0; $ens<=$#{$dta->{ENSEMBLE}}; $ens++,$start_ens+=$ens_length+2) { |
|
1198 for ($ens=0; $ens<=$#{$dta->{ENSEMBLE}}; $ens++) { |
|
1199 $start_ens = goto_next_ens(\*WBPF); |
|
1200 die("ens = $ens\n") unless defined($start_ens); |
1122 |
1201 |
1123 #------------------------------ |
1202 #------------------------------ |
1124 # Patch Header (Data Source Id) |
1203 # Patch Header (Data Source Id) |
1125 #------------------------------ |
1204 #------------------------------ |
1126 |
1205 |
1132 $buf = pack('C',$dta->{ENSEMBLE}[$ens]->{DATA_SOURCE_ID}); |
1211 $buf = pack('C',$dta->{ENSEMBLE}[$ens]->{DATA_SOURCE_ID}); |
1133 my($nw) = syswrite(WBPF,$buf,1); |
1212 my($nw) = syswrite(WBPF,$buf,1); |
1134 $nw == 1 || die("$WBPcfn: $nw bytes written ($!)"); |
1213 $nw == 1 || die("$WBPcfn: $nw bytes written ($!)"); |
1135 |
1214 |
1136 sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF"); |
1215 sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF"); |
1137 ($ens_length,$dummy,$ndt) = unpack('vCC',$buf); |
1216 ($el,$dummy,$ndt) = unpack('vCC',$buf); |
1138 printf(STDERR "\n$WBPcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
1217 $ens--,next if (defined($ens_length) && ($el != $ens_length)); |
|
1218 $ens_length = $el; |
|
1219 |
|
1220 printf(STDERR "$WBPcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last |
1139 unless ($ndt == 6 || $ndt == 7); |
1221 unless ($ndt == 6 || $ndt == 7); |
1140 |
1222 |
1141 sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!"); |
1223 sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!"); |
1142 @WBPofs = unpack("v$ndt",$buf); |
1224 @WBPofs = unpack("v$ndt",$buf); |
1143 $fixed_leader_bytes = $WBPofs[1] - $WBPofs[0]; |
1225 $fixed_leader_bytes = $WBPofs[1] - $WBPofs[0]; |
1170 $buf = pack('C',$EX); |
1252 $buf = pack('C',$EX); |
1171 sysseek(WBPF,$start_ens+$WBPofs[0]+25,0) || die("$WBPcfn: $!"); |
1253 sysseek(WBPF,$start_ens+$WBPofs[0]+25,0) || die("$WBPcfn: $!"); |
1172 syswrite(WBPF,$buf,1) == 1 || die("$WBPcfn: $!"); |
1254 syswrite(WBPF,$buf,1) == 1 || die("$WBPcfn: $!"); |
1173 |
1255 |
1174 #---------------------------------------------------------------------- |
1256 #---------------------------------------------------------------------- |
|
1257 # Variable Leader #0 |
|
1258 # - read ensNo for debugging purposes |
|
1259 #---------------------------------------------------------------------- |
|
1260 |
|
1261 sysseek(WBPF,$start_ens+$WBPofs[1]+2,0) || die("$WBPcfn: $!"); |
|
1262 sysread(WBPF,$buf,2) == 2 || die("$WBPcfn: $!"); |
|
1263 my($ensNo) = unpack("v",$buf); # only lower two bytes!!! |
|
1264 sysseek(WBPF,$start_ens+$WBPofs[1]+13,0) || die("$WBPcfn: $!"); # jump to high byte |
|
1265 sysread(WBPF,$buf,1) == 1 || die("$WBPcfn: $!"); |
|
1266 $ensNo += unpack('C',$buf) << 16; |
|
1267 die("ensNo = $ensNo (should be $dta->{ENSEMBLE}[$ens]->{NUMBER})\n") |
|
1268 unless ($ensNo == $dta->{ENSEMBLE}[$ens]->{NUMBER}); |
|
1269 |
|
1270 #---------------------------------------------------------------------- |
1175 # Variable Leader #1 |
1271 # Variable Leader #1 |
1176 # - if $RDI_PD0_IO::OVERRIDE_Y2K_CLOCK is set, the data from the pre-Y2K |
1272 # - if $RDI_PD0_IO::OVERRIDE_Y2K_CLOCK is set, the data from the pre-Y2K |
1177 # clock are used to override the ADCP clock values; this allows |
1273 # clock are used to override the ADCP clock values; this allows |
1178 # a better time to be recorded by the data acquisition system |
1274 # a better time to be recorded by the data acquisition system |
1179 # without overwriting the main instrument clock data |
1275 # without overwriting the main instrument clock data |
1180 #---------------------------------------------------------------------- |
1276 #---------------------------------------------------------------------- |
1181 |
1277 |
1182 if ($RDI_PD0_IO::OVERRIDE_Y2K_CLOCK) { |
1278 if ($RDI_PD0_IO::OVERRIDE_Y2K_CLOCK) { |
1183 sysseek(WBPF,$start_ens+$WBPofs[1]+4,0) || die("$WBPcfn: $!"); # jump to RTC_YEAR |
1279 sysseek(WBPF,$start_ens+$WBPofs[1]+4,0) || die("$WBPcfn: $!"); # jump to RTC_YEAR |
1184 sysread(WBPF,$buf,7) == 7 || die("$WBRcfn: $!"); # read pre-Y2K clock |
1280 sysread(WBPF,$buf,7) == 7 || die("$WBPcfn: $!"); # read pre-Y2K clock |
1185 ($dta->{ENSEMBLE}[$ens]->{YEAR}, |
1281 ($dta->{ENSEMBLE}[$ens]->{YEAR}, |
1186 $dta->{ENSEMBLE}[$ens]->{MONTH}, |
1282 $dta->{ENSEMBLE}[$ens]->{MONTH}, |
1187 $dta->{ENSEMBLE}[$ens]->{DAY}, |
1283 $dta->{ENSEMBLE}[$ens]->{DAY}, |
1188 $dta->{ENSEMBLE}[$ens]->{HOUR}, |
1284 $dta->{ENSEMBLE}[$ens]->{HOUR}, |
1189 $dta->{ENSEMBLE}[$ens]->{MINUTE}, |
1285 $dta->{ENSEMBLE}[$ens]->{MINUTE}, |