#!/usr/local/bin/perl 

# **
# **    SCCS Identification Keyword
# **    @(#)lzpscan	1.8   11/04/97 16:25:35
# **

#****************************************************************************
#  FILE     : lzpscan

#  AUTHOR   : Keith Hogie
#
# ****************************************************************************
require "bigint.pl";
require "bigfloat.pl";


$VERSION = "1.0  9/24/97" ;
$BEGREC = 1 ;
$ENDREC = 20000000 ;

#########################################################################
#	Table of SRC/DST codes and various related text strings
#######################################################################

$SRCT = << "E_O_T" ;
0012=REN=REN=Renaissance Testbed=00012=Renaissance Testbed, GSFC, Bldg 23
0046=XCE=MOC=Cmd Echo, Mon Blks =00046=GGS POCC, SOHO MOC
0064=SOC=SOC=SOC Simulator      =00064=SOC Simulator, GSFC, Bldg 25 
0167=NOC=NOC=JPL Monitor Blocks =00167=JPL NOCC
0123=CTA=CTA=Compat. Tst Area 21=00123=SPC-04  9M
0125=CTA=CTA=Compat. Tst Area 21=00125=DSS-05  34M S
0133=CTA=CTA=Compat. Tst Area 21=00133=DSS-06  70M
0137=CTA=CTA=Compat. Tst Area 21=00137=DSS-07  34M H
0146=CTA=CTA=Compat. Tst Area 21=00146=DSS-08  26M
0175=CTA=CTA=Compat. Tst Area 21=00175=MIL-71  26M
0135=SHO=SMO=SOHO Telemetry     =00135=SOHO MOCC & IPD
0201=D12=GDS=Goldstone          =00201=DSS-12 34M
0204=D16=GDS=Goldstone          =00204=DSS-16 26M
0311=D24=GDS=Goldstone          =00311=DSS-24 34M BWG
0341=GEO=GEO=GEOTAIL GDCF       =00341=GEOTAIL GDCF
0346=D27=GDS=Goldstone          =00346=DSS-27 34M HSB
0222=D42=CAN=Canberra           =00222=DSS-42 34M
0225=D46=CAN=Canberra           =00225=DSS-46 26M
0302=WRT=WRT=WIND R/T Tlm       =00302=GGS POCC, SPOF, GDCF
0075=WPB=WPB=WIND P/B Tlm       =00075=GGS POCC, GDCF
0362=PRT=PRT=POLAR R/T Tlm      =00362=GGS POCC, GDCF
0120=PWI=PWI=POLAR R/T PWI      =00362=GDCF
0234=PPB=PPB=POLAR P/B Tlm      =00362=GGS POCC, GDCF
0363=D61=MAD=Madrid             =00363=DSS-61 34M
0366=D66=MAD=Madrid             =00366=DSS-66 26M
E_O_T

@SR = split( /\n/, $SRCT ) ;
$I = 0 ;
while( $SR[ $I ] ) {            # process each line of table information
        @LS = split( /=/, $SR[ $I ] ) ; # split line into fields with = separator
        $INDX     = oct( $LS[0] ) ;     # get numeric station code
        $SRC_IRTS[ $INDX ] = $LS[1] ;   # 3 char name for building IRTS tables
        $SRC_HASH{ $LS[1] }= $INDX  ;   # build array to associate name with number
        $SRC3[ $INDX ]     = $LS[2] ;   # 3 char name
        $SRC_DESC[ $INDX ] = $LS[3] ;   # descriptive site name
        $SRC5[ $INDX ]     = $LS[4] ;   # 5 char antenna name
        $SRC_ANT[ $INDX ]  = $LS[5] ;   # long antenna name
        $I++ ;
}


#########################################################################
#	Table of SCID codes and various related text strings
#######################################################################

$SCID[ 0010 ] = "WIND - Normal" ;
$SCID[ 0011 ] = "WIND - Simulation" ;
$SCID[ 0015 ] = "POLAR - Normal" ;
$SCID[ 0016 ] = "POLAR - Simulation" ;
$SCID[ 0001 ] = "GEOTAIL - Normal" ;
$SCID[ 0025 ] = "SOHO" ;


#########################################################################
#	Table of PDF (Proj Data Fmt) codes and various related text strings
#######################################################################

$PDFT = << "E_O_T" ;
0343=B=RT=WIND=  5.565 Kbps - Science, Maneuver, Contingency (R/T)
0344=A=RT=WIND=  1.113 Kbps - Engineering (R/T)
0345=C=RT=WIND= 11.130 Kbps - 2X-Science, Maneuver, Contingency (R/T)
0342=E=PB=WIND= 64.000 Kbps - Science, Maneuver, Contingency (P/B)
0320=D=PB=WIND= 32.000 Kbps - 1/2-Science, Maneuver, Contingency (P/B)
0321=F=PB=WIND=128.000 Kbps - 2X-Science, Maneuver, Contingency (P/B)
0322=B=RT=POLAR= 55.650 Kbps - Science, Maneuver, Contingency (R/T)
0323=A=RT=POLAR=  1.113 Kbps - Engineering (R/T)
0325=G=RT=POLAR= 256.000 Kbps - PWI Data (Real-time)
0326=D=PB=POLAR= 512.000 Kbps - Science, Maneuver, Contingency (P/B)
0330=C=PB=POLAR= 256.000 Kbps - 1/2-Science, Maneuver, Contingency (P/B)
0310=A=RT=GEOTAIL= 16.384 Kbps - Record and Contingency (R/T)
0311=B=RT=GEOTAIL= 65.536 Kbps - Record and Contingency (R/T)
0307=C=PB=GEOTAIL= 65.536 Kbps - Record and Contingency (P/B)
0313=D=PB=GEOTAIL= 131.072 Kbps - Record and Contingency (P/B)
0312= =RT=SOHO=SOHO Real-time TLM (VC0 and VC1)
0324= =PB=SOHO=SOHO TR Dump TLM (VC4)
0327= =PB=SOHO=SOHO MDI TLM (VC2 and VC3)
E_O_T

@PR = split( /\n/, $PDFT ) ;
$I = 0 ;
while( $PR[ $I ] ) {            # process each line of table information
        @LS = split( /=/, $PR[ $I ] ) ; # split line into fields with | separator
        $INDX     = oct( $LS[0] ) ;     # get numeric PDF code
        $PDF[ $INDX ]      = $LS[1] ;   # 1 char name
        $PDF_RTPB[ $INDX ] = $LS[2] ;   # Real-time or Playback (RT or PB)
        $PDF_SAT[ $INDX ]  = $LS[3] ;   # Satellite name
        $PDF_DESC[ $INDX ] = $LS[4] ;   # long description of PDF data
        $I++ ;
}

#########################################################
#       Table of Geotail subrecord length               #
# Satellite+Instr+TMI, subrecord size, description	#
#########################################################

$SRCT = <<"E_O_T";
GEOTAIL-PWI1= 11 = Science Mode =     Geotail - PWI
GEOTAIL-PWI3= 29 = Contingency Mode = Geotail - PWI
GEOTAIL-HEP1= 13 = Science Mode =     Geotail - HEP
GEOTAIL-HEP3= 12 = Contingency Mode = Geotail - HEP
GEOTAIL-MGF1=  8 = Science Mode =     Geotail - MGF
GEOTAIL-MGF3= 12 = Contingency Mode = Geotail - MGF
GEOTAIL-LEP1=  8 = Science Mode =     Geotail - LEP
GEOTAIL-LEP3= 12 = Contingency Mode = Geotail - LEP
GEOTAIL-EFD1=  8 = Science Mode =     Geotail - EFD
GEOTAIL-EFD3= 15 = Contingency Mode = Geotail - EFD
GEOTAIL-EPI1= 20 = Science Mode =     Geotail - EPI
GEOTAIL-EPI3=  5 = Contingency Mode = Geotail - EPI
GEOTAIL-CPI1= 36 = Science Mode =     Geotail - CPI
GEOTAIL-CPI3=  9 = Contingency Mode = Geotail - CPI
GEOTAIL-SCR1= 11 = Science Mode =     Geotail - SCR
GEOTAIL-SCR3= 11 = Contingency Mode = Geotail - SCR
E_O_T

@SR = split(/\n/, $SRCT);
for($I=0;$SR[ $I ]; $I++)
{
        @LS = split( /=/, $SR[$I] );
        $INDX = $LS[0];
        $GEO_SUB_BYTE{$INDX} = $LS[1];
        $GEO_SUB_DESC{$INDX} = $LS[2];
}


#########################################################
#       Table of Wind/Polar subrecord length            #
# Satellite+Instr+TMI, subrecord size, description	#
#########################################################

$SRCT = <<"E_O_T";
WIND-3DP1= 50 = Science Mode =     Wind/Polar - 3DP
WIND-3DP3= 36 = Maneuver Mode =    Wind/Polar - 3DP
WIND-3DP4= 50 = Contingency Mode = Wind/Polar - 3DP
WIND-3DP5= 50 = Science Mode =     Wind Only  - 3DP
WIND-3DP7= 36 = Maneuver Mode =    Wind Only  - 3DP
WIND-3DP8= 50 = Contingency Mode = Wind Only  - 3DP
WIND-EPA1= 24 = Science Mode =     Wind/Polar - EPA
WIND-EPA3= 23 = Maneuver Mode =    Wind/Polar - EPA
WIND-EPA4= 24 = Contingency Mode = Wind/Polar - EPA
WIND-EPA5= 24 = Science Mode =     Wind Only  - EPA
WIND-EPA7= 23 = Maneuver Mode =    Wind Only  - EPA
WIND-EPA8= 24 = Contingency Mode = Wind Only  - EPA
WIND-KON1=  6 = Science Mode =     Wind/Polar - KON
WIND-KON3=  6 = Maneuver Mode =    Wind/Polar - KON
WIND-KON4=  6 = Contingency Mode = Wind/Polar - KON
WIND-KON5=  6 = Science Mode =     Wind Only  - KON
WIND-KON7=  6 = Maneuver Mode =    Wind Only  - KON
WIND-KON8=  6 = Contingency Mode = Wind Only  - KON
WIND-MFI1= 25 = Science Mode =     Wind/Polar - MFI
WIND-MFI3= 23 = Maneuver Mode =    Wind/Polar - MFI
WIND-MFI4= 25 = Contingency Mode = Wind/Polar - MFI
WIND-MFI5= 25 = Science Mode =     Wind Only  - MFI
WIND-MFI7= 23 = Maneuver Mode =    Wind Only  - MFI
WIND-MFI8= 25 = Contingency Mode = Wind Only  - MFI
WIND-SMS1= 42 = Science Mode =     Wind/Polar - SMS
WIND-SMS3= 35 = Maneuver Mode =    Wind/Polar - SMS
WIND-SMS4= 42 = Contingency Mode = Wind/Polar - SMS
WIND-SMS5= 42 = Science Mode =     Wind Only  - SMS
WIND-SMS7= 35 = Maneuver Mode =    Wind Only  - SMS
WIND-SMS8= 42 = Contingency Mode = Wind Only  - SMS
WIND-SWE1= 45 = Science Mode =     Wind/Polar - SWE
WIND-SWE3=  2 = Maneuver Mode =    Wind/Polar - SWE
WIND-SWE4= 45 = Contingency Mode = Wind/Polar - SWE
WIND-SWE5= 45 = Science Mode =     Wind Only  - SWE
WIND-SWE7=  2 = Maneuver Mode =    Wind Only  - SWE
WIND-SWE8= 45 = Contingency Mode = Wind Only  - SWE
WIND-TGR1= 21 = Science Mode =     Wind/Polar - TGR
WIND-TGR3= 21 = Maneuver Mode =    Wind/Polar - TGR
WIND-TGR4= 21 = Contingency Mode = Wind/Polar - TGR
WIND-TGR5= 21 = Science Mode =     Wind Only  - TGR
WIND-TGR7= 21 = Maneuver Mode =    Wind Only  - TGR
WIND-TGR8= 21 = Contingency Mode = Wind Only  - TGR
WIND-WAV1= 45 = Science Mode =     Wind/Polar - WAV
WIND-WAV3= 61 = Maneuver Mode =    Wind/Polar - WAV
WIND-WAV4= 45 = Contingency Mode = Wind/Polar - WAV
WIND-WAV5= 45 = Science Mode =     Wind Only  - WAV
WIND-WAV7= 61 = Maneuver Mode =    Wind Only  - WAV
WIND-WAV8= 45 = Contingency Mode = Wind Only  - WAV
WIND-SCR1= 15 = Science Mode =     Wind/Polar - SCR
WIND-SCR3= 66 = Maneuver Mode =    Wind/Polar - SCR
WIND-SCR5= 15 = Science Mode =     Wind Only  - SCR
WIND-SCR7= 66 = Maneuver Mode =    Wind Only  - SCR
E_O_T

@SR = split(/\n/, $SRCT);
for($I=0;$SR[ $I ]; $I++)
{
        @LS = split( /=/, $SR[$I] );
        $INDX = $LS[0];
        $WIND_SUB_BYTE{$INDX} = $LS[1];
        $WIND_SUB_DESC{$INDX} = $LS[2];
}


#########################################################
#       Table of Wind/Polar subrecord length            #
# Satellite+Instr+TMI, subrecord size, description	#
#########################################################

$SRCT = <<"E_O_T";
POLAR-CAM1= 10 = Science Mode =     Polar - CAM
POLAR-CAM3= 10 = Maneuver Mode =    Polar - CAM
POLAR-CAM4= 17 = Contingency Mode = Polar - CAM
POLAR-CEP1= 18 = Science Mode =     Polar - CEP
POLAR-CEP3= 18 = Maneuver Mode =    Polar - CEP
POLAR-CEP4= 33 = Contingency Mode = Polar - CEP
POLAR-EFI1= 13 = Science Mode =     Polar - EFI
POLAR-EFI3= 13 = Maneuver Mode =    Polar - EFI
POLAR-EFI4= 25 = Contingency Mode = Polar - EFI
POLAR-HYD1= 24 = Science Mode =     Polar - HYD
POLAR-HYD3=  2 = Maneuver Mode =    Polar - HYD
POLAR-HYD4= 47 = Contingency Mode = Polar - HYD
POLAR-MFE1=  6 = Science Mode =     Polar - MFE
POLAR-MFE3=  6 = Maneuver Mode =    Polar - MFE
POLAR-MFE4= 10 = Contingency Mode = Polar - MFE
POLAR-PIX1= 24 = Science Mode =     Polar - PIX
POLAR-PIX3= 11 = Maneuver Mode =    Polar - PIX
POLAR-PIX4=  2 = Contingency Mode = Polar - PIX
POLAR-PWI1= 21 = Science Mode =     Polar - PWI
POLAR-PWI3= 21 = Maneuver Mode =    Polar - PWI
POLAR-PWI4= 42 = Contingency Mode = Polar - PWI
POLAR-SEP1= 24 = Science Mode =     Polar - SEP
POLAR-SEP3= 11 = Maneuver Mode =    Polar - SEP
POLAR-SEP4=  2 = Contingency Mode = Polar - SEP
POLAR-TID1= 22 = Science Mode =     Polar - TID
POLAR-TID3= 22 = Maneuver Mode =    Polar - TID
POLAR-TID4= 43 = Contingency Mode = Polar - TID
POLAR-TIM1= 21 = Science Mode =     Polar - TIM
POLAR-TIM3= 21 = Maneuver Mode =    Polar - TIM
POLAR-TIM4= 41 = Contingency Mode = Polar - TIM
POLAR-UVI1= 58 = Science Mode =     Polar - UVI
POLAR-UVI3= 49 = Maneuver Mode =    Polar - UVI
POLAR-UVI4=  1 = Contingency Mode = Polar - UVI
POLAR-VIS1= 54 = Science Mode =     Polar - VIS
POLAR-VIS3= 55 = Maneuver Mode =    Polar - VIS
POLAR-VIS4=  2 = Contingency Mode = Polar - VIS
POLAR-SCR1=  9 = Science Mode =     Polar - SCR
POLAR-SCR4=  9 = Contingency Mode = Polar - SCR
E_O_T

@SR = split(/\n/, $SRCT);
for($I=0;$SR[ $I ]; $I++)
{
        @LS = split( /=/, $SR[$I] );
        $INDX = $LS[0];
        $POLAR_SUB_BYTE{$INDX} = $LS[1];
        $POLAR_SUB_DESC{$INDX} = $LS[2];
}


#########################################################################
#	Table of Mission ID and Mission Name				#
#########################################################################
$SATID{"geotail"} = 24;
$SATID{"wind"}    = 25;
$SATID{"polar"}   = 26;
$SATNAME[24]      = "GEOTAIL";
$SATNAME[25]	  = "WIND";
$SATNAME[26]	  = "POLAR";


#########################################################################
#	Table of Instrument ID and Instrument Name			#
#########################################################################

$INSTR{"GEOTAIL-1"}  =  "PWI";
$INSTR{"GEOTAIL-2"}  =  "HEP";
$INSTR{"GEOTAIL-3"}  =  "MGF";
$INSTR{"GEOTAIL-4"}  =  "LEP";
$INSTR{"GEOTAIL-5"}  =  "EFD";
$INSTR{"GEOTAIL-6"}  =  "EPI";
$INSTR{"GEOTAIL-7"}  =  "CPI";
$INSTR{"GEOTAIL-8"}  =  "SCR";
$INSTR{"GEOTAIL-94"} =  "SIRIUS";
$INSTR{"GEOTAIL-99"} =  "QAF";
$INSTR{"WIND-1"}     =  "WAV";
$INSTR{"WIND-2"}     =  "EPA";
$INSTR{"WIND-3"}     =  "MFI";
$INSTR{"WIND-4"}     =  "SWE";
$INSTR{"WIND-5"}     =  "SMS";
$INSTR{"WIND-6"}     =  "3DP";
$INSTR{"WIND-7"}     =  "TGR";
$INSTR{"WIND-8"}     =  "KON";
$INSTR{"WIND-9"}     =  "SCR";
$INSTR{"WIND-99"}    =  "QAF";
$INSTR{"POLAR-1"}    =  "PWI";
$INSTR{"POLAR-2"}    =  "HYD";
$INSTR{"POLAR-3"}    =  "MFE";
$INSTR{"POLAR-4"}    =  "TIM";
$INSTR{"POLAR-5"}    =  "TID";
$INSTR{"POLAR-6"}    =  "UVI";
$INSTR{"POLAR-7"}    =  "VIS";
$INSTR{"POLAR-8"}    =  "PIX";
$INSTR{"POLAR-9"}    =  "CAM";
$INSTR{"POLAR-10"}   =  "CEP";
$INSTR{"POLAR-11"}   =  "EFI";
$INSTR{"POLAR-12"}   =  "SCR";
$INSTR{"POLAR-96"} =  "PWIW";
$INSTR{"POLAR-99"}   =  "QAF";

$FRM_IN_BLK{"GEOTAIL"} = 4;
$FRM_IN_BLK{"WIND/POLAR"} = 2;
$MAX_MAJ{"GEOTAIL"} = 8;
$MAX_MAJ{"WIND/POLAR"} = 256;

$C_OPEN = "[0m";
$C_ROWS = "[%dH";
$C_COLS = "[%dC";


        #--------------------------------------------------
        #   Parse input parameters
        #--------------------------------------------------
@PROGN    = split( /\// , $0 ) ;	# split program name to get last piece
$PROGNAME = $PROGN[ -1 ] ;	# get last field

						# check program invocation name to determine
if    ( $PROGNAME eq "lzpedit" ) { $LZPEDIT++ }	# if we are scanning or editing or comparison
elsif ( $PROGNAME eq "lzpscan" ) { $LZPSCAN++ }
elsif ( $PROGNAME eq "lzpdiff" ) { $LZPDIFF++; $SHORT_NAME = "FILE A : "; }
elsif ( $PROGNAME eq "lzpprod" ) { $PRODSHOW++ }
elsif ( $PROGNAME eq "lzpappend" ) { $LZPAPPEND++ }
elsif ( $PROGNAME eq "lzpSTR_FP" ) { $LZPSTR_FP++ }

if($LZPSTR_FP) { 
	&time_usage();
	print "Enter time: ";
	$TIME_IN = <STDIN>;
	@tmp = split(/\./, $TIME_IN);
	$NUM_DOT = $#tmp;

	chop( $TIME_IN ) ;		# remove last char (NL)

	if($NUM_DOT == 1) { $FP2STR++ }
	elsif ($NUM_DOT == 0) { if(length($TIME_IN) >= 12 ) { $PB52STR++; } else { $FP2STR++; } }
	elsif($NUM_DOT == 2) { $STR2FP++ }
	else { die "Invalid time\n"; }
	
	if($STR2FP)
	{
    		$STR_IN = $TIME_IN;
	
    		$FP = &str2FP($STR_IN);
    		printf("FP time: %.6f\n", $FP);
	}
	elsif($FP2STR)
	{
    		$FP_IN = sprintf("%.6f", $TIME_IN);
		
    		$STR = &FP2str($FP_IN);
    		printf("STR time: %s\n", $STR);
	}
	elsif($PB52STR)
	{
		@TEST = unpack("A2 A2 A2 A2 A2 A2", $TIME_IN);
		for($i=0; $i< $#TEST; $i++)
		{
			$TEST[$i] =~ y/A-Z/a-z/;
			$hi = unpack("C", $TEST[$i]);
			$lo = unpack("xC", $TEST[$i]);
			if($lo >= unpack("C", "a")) {
				$lo = 10 + $lo - unpack("C", "a");
			}
			else {  
				$lo -= unpack("C", "0"); 
			}
			if($hi >= unpack("C", "a")) {
				$hi = 10 + $hi - unpack("C", "a");
			}
			else { 
				$hi -= unpack("C", "0"); 
			}
			$TEST[$i] = ($hi * 16) + $lo;
		}	
		$TIME++;
		$STR = &PB5_STR(@TEST);
    		printf("STR time: %s\n", $STR);
	}

	die "\n";
}


if( not defined $ARGV[0] ) {			# no parameters specified at all
	if( $LZPSCAN ) { scan_usage() ; die "\n";}
	if( $LZPEDIT ) { edit_usage() ; die "\n";}
	if( $LZPDIFF ) { diff_usage() ; die "\n";}
}


while ($_ = $ARGV[0], /^-/ ) {
        shift;
        last if (/^--$/ ) ;
        if (/^-a/)      { $OLINE++; }    #enable one line dump of all records
        if (/^-b/)      { $BEGREC = $ARGV[0] ; # get begining frame number to process
				shift;
                                }
        if (/^-c/)      { $CODES++; scan_usage(); die "\n";}    #set flag to display conversion code tables
        if (/^-d/)      { $DELTA++; }    	#enable delta time printing
        if (/^-e/)      { $ENDREC = $ARGV[0] ; # get end frame number to process
				shift;
                                }
        if (/^-f/)      { $FIELD = $ARGV[0] ; # get byte field number to extract
				shift;
                                }
        if (/^-g/)	{ $GARBAGE++; }		# skip printing filled blocks
        if (/^-h/)      { $HELP++; scan_usage(); edit_usage(); display_usage(); die "\n";}
        if (/^-i/)      { $IDFILE++;} 	#enable file ID mode only
        if (/^-l/)      { $LONG++;  }    #enable long dump
        if (/^-t/)      { $TIME++ }    #enable HH:MM:SS time format dump
        if (/^-x/)      { $HEX++;   }    #enable hex dump
        if (/^-z/)      { $OLINE++ ; $HEX++ ; $ZYNC++;   }    #enable zync location in hex dump
	if (/^-v/)	{ $VERBOSE++ }  # turn on verbose
        if (/^-V/)      { print( "$0 - Version $VERSION\n" ); exit; }    # show program version
}


$NUMFILES = 0 ;
while ( $ARGV[0] ) {
	$FILENAME[ $NUMFILES ] = $ARGV[0] ;
	shift;
	$NUMFILES++ ;
}
$CURRFILE = 0 ;


if($PRODSHOW) 
{
   
    if($NUMFILES != 2) { &display_usage(); die "\n";}

    ($SAT_NAME = $FILENAME[ 1 ]) =~ tr/A-Z /a-z/;
    $DATE_TIME = $FILENAME[ 0 ];

    if( ($SAT_NAME ne "wind") && ($SAT_NAME ne "polar") && ($SAT_NAME ne "geotail") )
    {
         &display_usage(); die "\n";
    }

    $DEV_OPS = &Get_dev_or_ops();

    $PATH_PROD = "/" . $SAT_NAME . "/" . $DEV_OPS . "/data3/" . $SATID{$SAT_NAME} ;

    $NUMFILES = 0;
    @PROD_DIR = `ls -1 $PATH_PROD`;
    
    $I = 0;
    foreach $PRODUCT (@PROD_DIR)
    {
       	$PRODUCT =~ s/\n//g;

       	$FILE_DIR = $PATH_PROD . "/". $PRODUCT;
	if(-d $FILE_DIR) { 
	    chdir($FILE_DIR);
       	    @TMP = `ls -1`;
    
       	    foreach $PROD_FILE (@TMP)
       	    {
           	    ($_ = $PROD_FILE) =~ s/\n//g;
            	    if(/$DATE_TIME/) { 
			if(/NUL/)     { if(/SFD/) {} else {$SIRIUS_FILE[$K] = $FILE_DIR . "/" . $_; $K++}}
			elsif(/PWIW/) { $PWIW_FILE[$L] = $FILE_DIR . "/" . $_; $L++}
			elsif(/DAT/)  { $TDM_FILE[$J] = $FILE_DIR . "/" . $_; $J++}
		    }
            	    next;
       	    }
	}
       	next;
    }
    $NUMFILES += $J + $K + $L;
    if($NUMFILES == 0) { die "No products created on $DATE_TIME for $SAT_NAME\n"; }
    splice(@TDM_FILE, $#TDM_FILE+1, 0, @SIRIUS_FILE);
    splice(@TDM_FILE, $#TDM_FILE+1, 0, @PWIW_FILE);
    @FILENAME = @TDM_FILE;
    print "\n";
}


#########################################################################
#		 This is the major program loop to go through all files requested
#
#######################################################################

FILELOOP:


if($LZPDIFF && $NUMFILES != 2) { &diff_usage(); die "\n";}

if($LZPAPPEND)
{
    if($NUMFILES < 2) { &diff_usage(); die "\n";}

    if($CURRFILE == 0) { 
	$F_IN = '>>' . $FILENAME[$CURRFILE];
	$XX = open(TOFILE, $F_IN);
    }
    else
    {
	$YY = open(FRFILE, $FILENAME[$CURRFILE]);
	@STAT = stat(FRFILE);
	$RB = $RW = 1;
	while($RB && $RB == $RW)
	{
	     $RB = sysread(FRFILE, $REC, 600);
	     $RW = syswrite(TOFILE, $REC, $RB);
	}
    }
    goto NEXTFILE ;
}
   

&Get_Window_Size ();
$STARTTIME = time() ;
@STGMT     = localtime( $STARTTIME ) ;
$STGMT[4]++ ; 	# increment month to 1-12 range
$START_TIME_STR = $STGMT[4] . '/' . $STGMT[3] . '/' . $STGMT[5] . '  ' . $STGMT[2] . ':' . $STGMT[1];
$RECNUM = 0 ;
$CONSEC_GOOD = 0 ;
$REC = "" ;
$PRTMSG = "" ;
@PB5 = 0 ;
@ANF_TOT = 0 ;

@SRC_TOT = 0 ;
@DST_TOT = 0 ;
@BFC_TOT = 0 ;
@SCID_TOT = 0 ;
@DSID_TOT = 0 ;
@TYPE_TOT = 0 ;

$CDHF_FILL = 0 ;

$X_HDROK = $X_SRC = $X_DST = $X_BFC = $X_SCID = $X_DSID = $X_TYPE = 0 ;

$MAJ_SYNC = $MAJ_MIF = $DELMAJ = $DELMIN = $DELOK = 0 ;
$MODE = $MAJNUM = 0 ;
$LEN_FULL = $LEN_PARTIAL = $LEN_ZERO = 0 ;

$TOT_PERFSYNC  = $TOT_IMPRSYNC = 0 ;
$TOT_PERFFLGS  = $TOT_IMPRFLGS = 0 ;

$FLG = $DOY = $MSOD = $USOMS = 0 ;

$PREV_MSOD = $PREV_UOMS = 0 ;

$FN = '<'.$FILENAME[ $CURRFILE ] ;
$FNOUT = '>'.$FILENAME[ $CURRFILE ].'.ed' ;	#create edit output file name in case needed
$XX = open( IN, $FN ) || die "Can't open file $FILENAME[ $CURRFILE ]\n" ;

$SAT     = "" ;
$RTPB    = "" ;
$PDF     = "" ;
$SRC     = "" ;
$DEST    = "" ;
$GRT1DOY   = "" ;
$GRT1MSOD  = "" ;
$GRT1USOMS = "" ;

$FILE_FMT = "" ; 
$REC_FMT = "" ; 
$BLK_TYPE = "" ;
$FRM_TYPE = "" ;
$DATA_TYPE = "" ;
$SYNCPAT = 0x0 ;

$F_HDR_LEN = 0 ;
$R_HDR_LEN = 0 ;
$R_DAT_LEN = 0 ;
$R_RS_LEN  = 0 ;
$R_ANN_LEN = 0 ;
$R_TRL_LEN = 0 ;

if($LZPDISPLAY) { &PROD_DISPLAY(); goto FILELOOP; }

$RB = sysread( IN, $REC, 1024) ;
if( $RB != 1024 ) {
        printf( "****** Short file -                       %70.70s\n", $FILENAME[ $CURRFILE ] ) ;
	goto NEXTFILE ;
}

$IDRFHDR = substr( $REC, 0, 96 ) ;	# grab first 96 bytes in case IDR format

if( Pattern_Loc( $REC, 0x627627, 0 ) ) {	# found Nascom block sync

	$SYNCPAT = 0x627627 ;
	
	$FILE_FMT = "GBRS" ;	
	$REC_FMT = "BLOCK" ;
	$BLK_TYPE = "DGIB" ;
	$DATA_TYPE = "TLM" ;	# set for basic telemetry for now
	$F_HDR_LEN = 0 ;
	$R_HDR_LEN = 0 ;
	$R_DAT_LEN = 600 ;
	
	if( Pattern_Loc( $REC, 0x627627, 600 ) ) { 	# back to back, no annotation
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 0 ;
		$R_TRL_LEN = 0 ;
	}
	
	if( Pattern_Loc( $REC, 0x627627, 608 ) ) { 	# back to back, annotation
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 8 ;
		$R_TRL_LEN = 0 ;
	}
}


if( Pattern_Loc( $REC, 0x627627, 12 ) ) {	# found Nascom sync after RTP 

	$SYNCPAT = 0x627627 ;
	
	$FILE_FMT = "GBRS" ;	
	$REC_FMT = "BLOCK" ;
	$BLK_TYPE = "DGIB" ;
	$DATA_TYPE = "" ;	# set for basic telemetry for now
	$F_HDR_LEN = 0 ;
	$R_HDR_LEN = 12 ;
	$R_DAT_LEN = 600 ;
	$R_RS_LEN  = 0 ;
	$R_ANN_LEN = 0 ;
	$R_TRL_LEN = 0 ;

}
	
if( Pattern_Loc( $REC, 0x627627, 116 ) ) { 	# IDR format

	$SYNCPAT = 0x627627 ;
	
	$FILE_FMT = "IDR" ;	
	$REC_FMT = "BLOCK" ;
	$BLK_TYPE = "DGIB" ;
	$DATA_TYPE = "TLM" ;	# set for basic telemetry for now
	$F_HDR_LEN = 96 ;
	$R_HDR_LEN = 20 ;
	$R_DAT_LEN = 600 ;
	$R_RS_LEN  = 0 ;
	$R_ANN_LEN = 0 ;
	$R_TRL_LEN = 4 ;
}

	
if( Pattern_Loc( $REC, 0x494c5a50, 0 ) ) { 	# CDHF format

	$SYNCPAT = 0xfaf320 ;
	
	$FILE_FMT = "CDHF" ;	
	$REC_FMT = "CDHFREC" ;
	$BLK_TYPE = "DGIB" ;
	$DATA_TYPE = "TLM" ;	# set for basic telemetry for now
	$F_HDR_LEN = 15844 ;
	$R_HDR_LEN = 4 ;
	$R_DAT_LEN = 15840 ;
	$R_RS_LEN  = 0 ;
	$R_ANN_LEN = 0 ;
	$R_TRL_LEN = 0 ;
}

#
# now figure out Satellite and RTPB
#

if( $REC_FMT eq "BLOCK" ) {
	seek(IN, 0, 0);
	$RB = sysread(IN, $REC, 4096);
	$REC_START = $F_HDR_LEN + $R_HDR_LEN ;

	for( $I=0; $I<=3; $I++ ) {
		$B[$I] = substr( $REC, $REC_START, $R_DAT_LEN ) ;
		( $XSRC[$I], $XDST[$I], $XBFC[$I], $XSCID[$I], $XDSID[$I], $XTYPE[$I] ) = 
			unpack( "x3 C1 C1 C1 C1 C1 C1 x3", $B[$I] ) ;
		$REC_START = $REC_START + $R_DAT_LEN + $R_RS_LEN + $R_ANN_LEN + $R_TRL_LEN + $R_HDR_LEN ;
	}

	$RTPB = $PDF_RTPB[ $XDSID[ 0 ] ] ;
	$PDF  = $PDF[ $XDSID[ 0 ] ] ;
	$SRC  = $SRC_DESC [ $XSRC [ 0 ] ] ;
	$DEST = $SRC_ANT [ $XDST [ 0 ] ] ;
	
	if( $BLK_TYPE eq "DGIB" ) {
		@T1 = unpack( "x12 C6", $B[0] ) ;
		$GRT1DOY = (( $T1[0] & 0x3f) << 3 ) | (( $T1[1] >> 5 ) & 0x7 )  ;
		$GRT1MSOD = (($T1[1] & 0x1f ) << 22) | ( $T1[2] << 14) | ( $T1[3] << 6 ) | (( $T1[4] >> 2 ) & 0x3f) ;
		$GRT1USOMS = ($T1[4] & 0x03 ) << 8 | $T1[5]  ;
	}

	if( $BLK_TYPE eq "DDPS" ) {
		$GRT1DOY = 0 ;
		$GRT1MSOD = 0 ;
		$GRT1USOMS = 0 ;
	}


#
#		To check for blocks with TIPIT LZP data don't look in first block
#		because that always contains C9 fill
#
	if( Pattern_Loc( $B[2], 0xfaf320, 12+125 ) ) { 	# check TIPIT LZP format
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "TLZP" ;	# TIPIT LZP format, sync at end - GEO-RT
		$RTPB = "RT" ;
		$SAT = "GEOTAIL" ;

		if($LZPDIFF || $LZPSCAN) {
			$F_HDR_LEN = 0 ;
			$R_HDR_LEN = 0 ;
			$R_DAT_LEN = 128 ;	
			$R_ANN_LEN = 8 ;
			$R_RS_LEN  = 0 ;
			$R_TRL_LEN = 0 ;
			$FILE_FMT = "TIPIT" ;	
			$REC_FMT = "FRAME" ;
			$SYNCPAT = 0xfaf320 ;
		}
	}

	if( Pattern_Loc( $B[2], 0x04cf5f, 12+125 ) ) { 	# check TIPIT LZP format
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "TLZP" ;	# TIPIT LZP format, sync at end - GEO-PB
		$RTPB = "PB" ;
		$SAT = "GEOTAIL" ;

		if($LZPDIFF || $LZPSCAN) {
			$F_HDR_LEN = 0 ;
			$R_HDR_LEN = 0 ;
			$R_DAT_LEN = 128 ;	
			$R_ANN_LEN = 8 ;
			$R_RS_LEN  = 0 ;
			$R_TRL_LEN = 0 ;
			$FILE_FMT = "TIPIT" ;	
			$REC_FMT = "FRAME" ;
			$SYNCPAT = 0xfaf320 ;
		}
	}

	if( Pattern_Loc( $B[2], 0xfaf320, 12+253 ) ) { 	# check TIPIT LZP format
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "TLZP" ;	# TIPIT LZP format, sync at end - WP-RT
		$RTPB = "RT" ;
		$SAT = "WIND/POLAR" ;

		if($LZPDIFF || $LZPSCAN) {
			$F_HDR_LEN = 0 ;
			$R_HDR_LEN = 0 ;
			$R_DAT_LEN = 256 ;	
			$R_ANN_LEN = 8 ;
			$R_RS_LEN  = 0 ;
			$R_TRL_LEN = 0 ;
			$FILE_FMT = "TIPIT" ;	
			$REC_FMT = "FRAME" ;
			$SYNCPAT = 0xfaf320 ;
		}
	}

	if( Pattern_Loc( $B[2], 0x04cf5f, 12+253 ) ) { 	# check TIPIT LZP format
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "TLZP" ;	# TIPIT LZP format, sync at end - WP-PB
		$RTPB = "PB" ;
		$SAT = "WIND/POLAR" ;

		if($LZPDIFF || $LZPSCAN) {
			$F_HDR_LEN = 0 ;
			$R_HDR_LEN = 0 ;
			$R_DAT_LEN = 256 ;	
			$R_ANN_LEN = 8 ;
			$R_RS_LEN  = 0 ;
			$R_TRL_LEN = 0 ;
			$FILE_FMT = "TIPIT" ;	
			$REC_FMT = "FRAME" ;
			$SYNCPAT = 0xfaf320 ;
		}
	}

	if( Pattern_Loc( $B[0], 0x1acffc1d, 19 ) ) { 	# check SOHO VCDU format
		$BLK_TYPE = "DGIB" ;
		$DATA_TYPE = "SVCDU" ;	# SOHO VCDU format
		$SAT = "SOHO" ;
	}

	if( not $SAT ) {	# try block header
		$SAT = $SCID[ $XSCID[0] ] ;
	}
	
	$PDF  = $PDF[ $XDSID[ 0 ] ] ;
	$SRC  = $SRC_DESC [ $XSRC [ 0 ] ] ;
	$DEST = $SRC_ANT [ $XDST [ 0 ] ] ;

	if(($DATA_TYPE ne "TLZP") and ($SCID[$XSCID[0]] eq "")) { $FILE_FMT = ""; }
}

if( not $FILE_FMT ) {		# no idea yet, try TDM frames

	if( Pattern_Loc( $REC, 0xfaf320, 0 ) ) { 	# starts with frame
	
		$SYNCPAT = 0xfaf320 ;
	
		$FILE_FMT = "LZP" ;	
		$REC_FMT = "FRAME" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 0 ;
		$R_DAT_LEN = 256 ;	# try 256 for starters
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 0 ;
		$R_TRL_LEN = 0 ;
		
		if( Pattern_Loc( $REC, 0xfaf320, 256 ) ) {	# W/P, no Ann.
			$R_DAT_LEN = 256 ;	# WIND or POLAR
			$SAT = "WIND/POLAR" ;
		}

		if( Pattern_Loc( $REC, 0xfaf320, 264 ) ) {	# W/P, no Ann.
			$R_DAT_LEN = 256 ;	# WIND or POLAR
			$R_ANN_LEN = 8 ;
			$SAT = "WIND/POLAR" ;
		}

		if( Pattern_Loc( $REC, 0xfaf320, 128 ) ) {	# GEO, no Ann.
			$R_DAT_LEN = 128 ;	# GEOTAIL
			$SAT = "GEOTAIL" ;
		}

		if( Pattern_Loc( $REC, 0xfaf320, 136 ) ) {	# GEO, no Ann.
			$R_DAT_LEN = 128 ;	# GEOTAIL
			$R_ANN_LEN = 8 ;
			$SAT = "GEOTAIL" ;
		}
	}

	if( Pattern_Loc( $REC, 0xfaf320, 253 ) || Pattern_Loc( $REC, 0x04cf5f, 253 ) ) { 	# TIPIT, WIND/POLAR
	
		$SYNCPAT = 0xfaf320 ;
	
		$FILE_FMT = "TIPIT" ;	
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "LZP" ;	
		$REC_FMT = "FRAME" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 0 ;
		$R_DAT_LEN = 256 ;
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 8 ;
		$R_TRL_LEN = 0 ;
		
		$SAT = "WIND/POLAR" ;
	}	

	if( Pattern_Loc( $REC, 0xfaf320, 125 ) || Pattern_Loc( $REC, 0x04cf5f, 125 ) ) {	# TIPIT, GEOTAIL
	
		$SYNCPAT = 0xfaf320 ;
	
		$FILE_FMT = "TIPIT" ;	
		$BLK_TYPE = "DDPS" ;
		$DATA_TYPE = "LZP" ;	
		$REC_FMT = "FRAME" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 0 ;
		$R_DAT_LEN = 128 ;
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 8 ;
		$R_TRL_LEN = 0 ;
		
		$SAT = "GEOTAIL" ;
	}

}

if( $REC_FMT eq "FRAME" ) {	# determine frame data characteristics

    if ( $DATA_TYPE eq "TLZP")
    {
	if( Pattern_Loc( $REC, 0x04cf5f, 253 ) || Pattern_Loc( $REC, 0x04cf5f, 125 ) ) { $RTPB = "PB"; }
	if( Pattern_Loc( $REC, 0xfaf320, 253 ) || Pattern_Loc( $REC, 0xfaf320, 125 ) ) { $RTPB = "RT"; }
   }
   else
   {
	$SEQ_DIR = 0;
			# read frames to determine RT/PB
	$HS = $F_HDR_LEN + $R_HDR_LEN ;		# header skip and overall record length
	$RL = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN +  $R_ANN_LEN + $R_TRL_LEN -1 ;	
	
	if( $R_ANN_LEN  ) {	# annotation exists if ANN_LEN nonzero
		@T1      = unpack( "x$HS x$R_DAT_LEN x$R_RS_LEN S4", $REC ) ;

		$T1F = ($T1[0] >> 4 ) & 0x0fff ;
		$GRT1USOMS = $T1[3] ;
		$GRT1DOY = ( ( ($T1[0] & 0xf ) << 5) | ( ($T1[1] & 0xf800) >> 11 ) ) ;
		$GRT1MSOD = ( $T1[1] & 0x07ff ) * 65536 + $T1[2] ;
	}
	else {
		$GRT1DOY = 0 ;
		$GRT1MSOD = 0 ;
		$GRT1USOMS = 0 ;
	}

		# pick minor frame sequence count (first byte after sync) from
		# some frames to determine the order of the frames
	
	#@SEQ_CHK = unpack( "x$HS x3 C1 x$RL C1 x$RL C1 x$RL C1 x$RL C1 x$RL C1", $REC );

	#for ( $I=0 ; $I < 5 ; $I++ ) {
	#	$SEQ_DEL = $SEQ_CHK[ $I + 1 ] - $SEQ_CHK[ $I ] ;
	#	if($SEQ_DEL > 100 || $SEQ_DEL < -100) { $SEQ_DEL = 0; }
	#	$SEQ_DIR += $SEQ_DEL ;
	#}

	#if( $SEQ_DIR > 3 ) { $RTPB = "RT" }
	#if( $SEQ_DIR < 3 ) { $RTPB = "PB" } 

         
	$ReadLen = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN +  $R_ANN_LEN + $R_TRL_LEN;	

	 seek(IN, $F_HDR_LEN, 0);
	 $RB = sysread(IN, $REC, $ReadLen);
	 for ($I=0; ($RB > 0) && $I < 200; $I++)
	 {
		$SEQ = unpack("x3 C1", $REC);
		if(not defined $PREV_SEQ) { $PREV_SEQ = $SEQ; }
		if( ($PREV_SEQ - $SEQ) > 0 ) { $DECREASE ++ }
		if( ($PREV_SEQ - $SEQ) < 0 ) { $INCREASE ++ }
		$PREV_SEQ = $SEQ;
	       	$RB = sysread(IN, $REC, $ReadLen);
	 }
	
	 if( $DECREASE > $INCREASE ) { $RTPB = "PB" }
	 if( $INCREASE > $DECREASE ) { $RTPB = "RT" }
	 seek(IN, 0, 0);
	 $RB = sysread( IN, $REC, 1024) ;
	
   }

   if( not defined $RTPB ) { print " Not able to determine RT or PB\n" }
}


if( not $FILE_FMT ) {		# no idea yet, try RS, CCSDS frames

	if( Pattern_Loc( $REC, 0x1acffc1d, 0 ) ) { 	# starts with frame
	
		$SYNCPAT = 0x1acffc1d ;
	
		$FILE_FMT = "RAW/CCSDS" ;	
		$REC_FMT = "CCSDS" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 0 ;
		
		if( Pattern_Loc( $REC, 0x1acffc1d, 1020 ) ) {	# W/P, Raw frames
			$R_DAT_LEN = 892 ;	
			$R_RS_LEN  = 128 ;
			$R_ANN_LEN = 0 ;
			$R_TRL_LEN = 0 ;
			$SAT = "WIND/POLAR" ;
		}
		
		if( Pattern_Loc( $REC, 0x1acffc1d, 1028 ) ) {	# W/P, Raw frames + ANN
			$R_DAT_LEN = 892 ;	
			$R_RS_LEN  = 128 ;
			$R_ANN_LEN = 8 ;
			$R_TRL_LEN = 0 ;
			$SAT = "WIND/POLAR" ;
		}
		
		if( Pattern_Loc( $REC, 0x1acffc1d, 1279 ) ) {	# SOHO, Raw frames
			$R_DAT_LEN = 1119 ;	
			$R_RS_LEN  = 160 ;
			$R_ANN_LEN = 0 ;
			$R_TRL_LEN = 0 ;
			$SAT = "SOHO" ;
		}
		
		if( Pattern_Loc( $REC, 0x1acffc1d, 1287 ) ) {	# SOHO, Raw frames + ANN
			$R_DAT_LEN = 1119 ;	
			$R_RS_LEN  = 160 ;
			$R_ANN_LEN = 8 ;
			$R_TRL_LEN = 0 ;
			$SAT = "SOHO" ;
		}
	}
}


if( not $FILE_FMT ) {		# no idea yet, try MBEG, PACOR format

	if( substr( $REC, 0, 4 ) eq "MBEG" ) { 	# starts with MBEG
	
		$SYNCPAT = 0x00 ;
	
		$FILE_FMT = "PACOR-MBEG" ;	
		$REC_FMT = "PACOR" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 64 ;
		
		$R_DAT_LEN = 1119 ;	
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 0 ;
		$R_TRL_LEN = 1 ;
		$SAT = "SOHO" ;
	}


	if( substr( $REC, 0, 4 ) eq "DBEG" ) { 	# starts with DBEG
	
		$SYNCPAT = 0x00 ;
	
		$FILE_FMT = "PACOR-DBEG" ;	
		$REC_FMT = "PACOR" ;
		$F_HDR_LEN = 0 ;
		$R_HDR_LEN = 64 ;
		
		$R_DAT_LEN = 1119 ;	
		$R_RS_LEN  = 0 ;
		$R_ANN_LEN = 0 ;
		$R_TRL_LEN = 1 ;
		$SAT = "SOHO" ;
	}
}

if( not $FILE_FMT ) {		# no idea yet, try ISTP product format

	if( Pattern_Loc( $REC, 0x505749, 0 ) )  {	# PWIW Product
	
		$FILE_FMT  = "ISTP"; 
		$REC_FMT   = "RECORD";
		$DATA_TYPE = "PWIW";
		$F_HDR_LEN = 23232;
		$R_HDR_LEN = 264;
		$R_DAT_LEN = 264*87;
		$SAT = "POLAR"; 
	}
	
	if ( Pattern_Loc( $REC, 0xFFFFF0, 0 ) ) {	# SIRIUS product

        	$FILE_FMT  = "ISTP";
        	$REC_FMT   = "RECORD";
		$DATA_TYPE = "SIRIUS";
        	$F_HDR_LEN = 2880;
        	$F_TRL_LEN = 23040;
        	$R_HDR_LEN = 0;
		$R_DAT_LEN = 144;
		$SAT = "GEOTAIL"; 
	}
	
	if( Pattern_Loc( $REC, 0x180000, 0 ) || 
	    Pattern_Loc( $REC, 0x190000, 0 ) || 
	    Pattern_Loc( $REC, 0x1A0000, 0 ) ) {  	# TDM product

        	$FILE_FMT  = "ISTP";
        	$REC_FMT   = "RECORD";
		$DATA_TYPE = "TDM";
		if ( Pattern_Loc( $REC, 0x180000, 0 ) ) { 	# Geotail products
			$F_HDR_LEN = &Swap_Number( unpack("x176 L1", $REC), 4 );
			$R_HDR_LEN = 560;
			$R_DAT_LEN = $F_HDR_LEN-$R_HDR_LEN;
			$SAT = "GEOTAIL"; 
			$NUM_MNF = 512;
		}

                if ( Pattern_Loc( $REC, 0x190000, 0 ) ) {		# Wind TDM product
			$F_HDR_LEN = &Swap_Number( unpack("x176 L1", $REC), 4 );
			$R_HDR_LEN = 300;
			$R_DAT_LEN = $F_HDR_LEN-$R_HDR_LEN;
			$SAT = "WIND"; 
			$NUM_MNF = 250;
		}

                if ( Pattern_Loc( $REC, 0x1A0000, 0 ) ) {		# Polar TDM product
			$F_HDR_LEN = &Swap_Number( unpack("x176 L1", $REC), 4 );
			$R_HDR_LEN = 300;
			$R_DAT_LEN = $F_HDR_LEN-$R_HDR_LEN;
			$SAT = "POLAR"; 
			$NUM_MNF = 250;
		}

		if ( Pattern_Loc( $REC, 0x512F41, 4 ) ) {       # QAF for TDM product
			$DATA_TYPE = "QAF";
               		$F_HDR_LEN = 8040;
               		$R_HDR_LEN = 40;
			$R_DAT_LEN = 40*200;
		}
	}

}

if( not $FILE_FMT) {		# no idea yet, try decom file format

	close(IN);

	&Parse_Product_FileName($FILENAME[$CURRFILE]);
	&get_SESSION_PATH($FILENAME[$CURRFILE]);

	($FTYPE, $APP) = split(/_/, $FileName);

	if($FTYPE eq "du") 
	{
		open(DU, $CURRPATH . $FileName); 
		$DU_FNAME = $FileName;
		open(DUS, $CURRPATH . "dus_" . $APP);
		$DUS_FNAME = "dus_" . $APP;
	}	
	if($FTYPE eq "dus") 
	{
		open(DU, $CURRPATH . "du_" . $APP); 
		$DU_FNAME = "du_" . $APP;
		open(DUS, $CURRPATH . $FileName);
		$DUS_FNAME = $FileName;
	}	

	$RB_DUS = sysread(DUS, $DUS_REC, 60);
	if($RB_DUS == 60) { $CHK_VAL = unpack("L1", $DUS_REC); }

	if( $CHK_VAL == $SESSION )
	{
                $TFS = unpack("x50 S1", $DUS_REC);

		$FILE_FMT  = "ISTP"; 
		$REC_FMT   = "DECOM";
		$DATA_TYPE = "DUS";
		$TFS_LEN = $TFS * 8;
               	$R_DAT_LEN = 52+$TFS_LEN;
		$DU_OFF_LEN = 4;

		seek(DU, 0, 0);
		seek(DUS, 0, 0);

		&DECOM_SCAN(); 
	}
		
}

if( not $FILE_FMT ) {		# if file type still not known, give up
	$FILE_FMT = "UNK" ;
	printf( "****** %4.4s file type              %70.70s - skipping\n", $FILE_FMT, $FILENAME[ $CURRFILE ] ) ;
	if( $HEX) { HEXPRT( $REC, 2048 ) } ;
	goto NEXTFILE ;
}

if($SAT eq "GEOTAIL") { $TIME_TITLE = "TTCD-Time"; }
else			{ $TIME_TITLE = "SC---Time"; }


@STAT = stat( IN ) ;
$RTOT_LEN = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN + $R_ANN_LEN + $R_TRL_LEN ;

if( $RTOT_LEN == 0 ) { $R_TOT = $STAT[7] ; $RUNITS = "bytes" ; }
else { 
	$R_TOT = ( $STAT[7] - $F_HDR_LEN ) / $RTOT_LEN ; $RUNITS = "records" ;
	if($DATA_TYPE eq "TLZP")
	{
	   $R_TOT = $STAT[7] / 600;
	   if($LZPSCAN && $LZPDIFF) {$R_TOT = $R_TOT * $FRM_IN_BLK{$SAT}; }
	}
}

if( $IDFILE ) {		# print just one line file identifier
	printf( "%10s %4s %5s %2s %1s %6.1d %7s %3.1d-%8.1d %-50s\n",
		 $SAT, $FILE_FMT, $REC_FMT, $RTPB, $PDF, $R_TOT, $RUNITS, $GRT1DOY, $GRT1MSOD,  $FILENAME[ $CURRFILE ] ) ;
	goto NEXTFILE ;
}


if( $FILE_FMT eq "UNK" ) { goto NEXTFILE } ;

if($PRODSHOW)
{
    $RS = seek( IN, $RSEEK, 0 ) ;

    if($TDM_HEADER == 0 || $SIRIUS_HEADER == 0)
    {
        if($DATA_TYPE eq "SIRIUS" && $SIRIUS_HEADER == 0) 
	{
	    print "\n\nSIRIUS PRODUCTS:\n";
	    print "                                             +------------------FIRST------------------+";
	    print "   +------------------LAST-------------------+    \n";
	    print "PROD#        FILE NAME              #MIFs     DATE      TIME        FI cnt      TI cnt  ";
	    print "    DATE      TIME        FI cnt      TI cnt      \n";
	    print "====== =========================== ======== ======== ============= ========== ==========";
	    print "= ======== ============ ========== ===========\n";
	    $SIRIUS_HEADER++;
	}
	elsif( ($DATA_TYPE eq "TDM" || $DATA_TYPE eq "QAF") && $TDM_HEADER == 0 )
	{
	    print "\n\nTDM PRODUCTS:\n";
	    print "                                              +-----------------FIRST-------------------+";
	    print "   +------------------LAST-------------------+\n";
	    print "PROD#        FILE NAME              #MAFs     MAFC     SC time              ATC          ";
	    print "   MAFC     SC time              ATC        \n";
	    print "====== ===========================  ======   ====== ============== =======================";
	    print " ====== ============== =======================\n";
	    $TDM_HEADER++;
	}
    }

    if( $REC_FMT eq "RECORD" ) { &SHOW_PROD( ) }	# go do PRODUCT showing

    goto NEXTFILE;
}
	
#########################################################################
#	Print information on file format identified
########################################################################


printf("================== %s $FILENAME[ $CURRFILE ]  ============ $START_TIME_STR == \n\n", $SHORT_NAME ) ;

print( "Data from Satellite - $SAT\n" ) ;

$CTIME = localtime( $STAT[10] ) ;
$SIZE_STR = sprintf( "%9.1d", $STAT[7] ) ;
$SIZE_COMMAS = commas( $SIZE_STR ) ;
print ( "\n" ) ;
printf("     Size = %11s bytes    Created %s\n", $SIZE_COMMAS, $CTIME ) ;

print ( "\n" ) ;
print( "     File format       = $FILE_FMT \n" );
print( "     Record format     = $REC_FMT\n" );

if( $REC_FMT eq "BLOCK" ) { 
	print( "     Block type        = $BLK_TYPE\n" ); }

if( $REC_FMT eq "FRAME" ) { 
	print( "     Frame type        = $FRM_TYPE\n" ); }

if( $REC_FMT eq "CCSDS" ) { 
	print( "     Frame type        = $FRM_TYPE\n" ); }

print(  "     Data Type         = $DATA_TYPE\n" );

print(  "     Realtime/Playback = $RTPB\n" ) ;

print(  "     Satellite         = $SAT\n");

print ( "\n" ) ;
printf( "     SYNC pattern      =  %8.2x\n", $SYNCPAT );

#########################################################################
#	If sync search option turned on, determine shifted sync values
########################################################################

if( $ZYNC ) {
	if( $REC_FMT eq "BLOCK" ) { 
		if( $RTPB eq "RT" ) { $XZYNC_PAT = 0xfaf320 ; }
			else { $XZYNC_PAT = 0x04cf5f ; }
	}
		
	printf( "     SYNC search patterns inside record based on %8.8x\n", $XZYNC_PAT ) ;
	printf( "          ", ) ;
	
	for( $I=0; $I<8 ; $I++ ) {
		$XZ[$I] = $XZYNC_PAT >> $I & 0xffff ;
		printf( "  %4.4x", $XZ[$I] ) ;
		$XZ1[$I] = $XZ[$I] >> 8 & 0xff ;
		$XZ2[$I] = $XZ[$I]      & 0xff ;
	}
	print( "\n" ) ;
	
}


#########################################################################
#	Now print out what we know about the file so far, then scan it
########################################################################


print( "\n" ) ;
print( "\n" ) ;
print(  "File record structure\n\n" ) ;
printf( "     File   HEADER  length = %4.0d bytes\n", $F_HDR_LEN ) ;
printf( "     Record HEADER  length = %4.0d bytes\n", $R_HDR_LEN ) ;
printf( "     Record DATA    length = %4.0d bytes\n", $R_DAT_LEN ) ;
printf( "     Record R/S     length = %4.0d bytes\n", $R_RS_LEN ) ;
printf( "     Record ANNOT.  length = %4.0d bytes\n", $R_ANN_LEN ) ;
printf( "     Record TRAILER length = %4.0d bytes\n", $R_TRL_LEN ) ;

print( "\n" ) ;
if($DATA_TYPE eq "TLZP") { $REC_TOT = $R_TOT * $FRM_IN_BLK{$SAT} }
else { $REC_TOT = $R_TOT; }
printf( " %4.1d %sS in file %s\n", $REC_TOT, $REC_FMT, $FILENAME[ $CURRFILE ] ) ;
print( "\n" ) ;

if( $FILE_FMT eq "IDR" )	{

	@IDRH = unpack( "S48", $IDRFHDR ) ;	# break header into 2=byte chunks
	$IDRBLKS = $IDRH[0] << 16 | $IDRH[1] ;
	$IDRSCID = $IDRH[12] ;
	$IDRSTART = ( $IDRH[26] * 65536 ) + $IDRH[27] ;
	$IDREND   = ( $IDRH[28] * 65536 ) + $IDRH[29] ;
	$IDRDELTA = $IDREND - $IDRSTART ;
	$IDR_HR   = int( $IDRDELTA / 3600000 ) ;
	$IDR_SHR  = $IDRDELTA - ( $IDR_HR * 3600000 ) ;
	$IDR_SEC  = $IDR_SHR % 60000 ;
	$IDR_MN  = ( $IDRDELTA - ($IDR_HR * 3600000 ) - ($IDR_SEC )) / 60000 ;
	$IDRGAPS = $IDRH[43] ;
	$IDRMISS = $IDRH[44] ;

	printf( "\n" ) ;
	printf( "IDR File Header Information\n\n" ) ;

	HEXPRT( $IDRFHDR , 96 ) ;

	printf( "     # blocks in IDR file = %7.1d     Gaps = %6.1d    Missing = %6.1d\n",
		 $IDRBLKS, $IDRGAPS, $IDRMISS ) ;
	printf( "     Start seconds = %10.1u  (since 1970)\n", $IDRSTART ) ;
	printf( "     End   seconds = %10.1u  (since 1970)\n", $IDREND ) ;
	printf( "     Elapsed time  = %10.1u  (%2.1d:%2.2d:%2.2d)\n",
		 $IDRDELTA, $IDR_HR, $IDR_MN, $IDR_SEC ) ;


}

if( $REC_FMT eq "BLOCK" ) {
	printf( "\n" ) ;
	printf( "\n" ) ;
	printf( "Header fields from first block\n\n" ) ;
	printf( "                   Oct Dec Hex\n" ) ;
	printf( "     Source      = %3.1o %3.1d %3.1x %s %s\n", $XSRC[0], $XSRC[0], $XSRC[0], 
		$SRC_DESC[ $XSRC[0] ], $SRC_ANT[ $XSRC[0] ] ) ;
	printf( "     Destination = %3.1o %3.1d %3.1x %s %s\n", $XDST[0], $XDST[0], $XDST[0], 
		$SRC_DESC[ $XDST[0] ], $SRC_ANT[ $XDST[0] ] ) ;
	printf( "     Blk Fmt Code= %3.1o %3.1d %3.1x \n", $XBFC[0], $XBFC[0], $XBFC[0], 
		 ) ;
	printf( "     S/C ID      = %3.1o %3.1d %3.1x %s\n", $XSCID[0], $XSCID[0], $XSCID[0], 
		$SCID[ $XSCID[0] ] ) ;
	printf( "     Data Str ID = %3.1o %3.1d %3.1x PDF=%s    %s\n", $XDSID[0], $XDSID[0], $XDSID[0], 
		$PDF[ $XDSID[0] ], $PDF_DESC[ $XDSID[0] ] ) ;
	printf( "     Message Type= %3.1o %3.1d %3.1x \n", $XTYPE[0], $XTYPE[0], $XTYPE[0], 
		 ) ;
	print ( "\n" ) ;
}

$ReadLen = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN +  $R_ANN_LEN + $R_TRL_LEN;	

#########################################################################
#       Do either FRM or PROD file comparison
#
#       At this point the following are set
#
#       $RECA = first record from file A
#       $RECB = first record from file B
#       $RBA  = status from read into $RECA (number of bytes read)
#       $RBB  = status from read into $RECB (number of bytes read)
#       $RECLEN = length of records to read (should be the same for both A & B)
#       $RTPB = "RT" or "PB" depending on data sequence (should be the same for both A & B)
#
#       Position input file and read first record
#       Then call FRAME or BLOCK diff
#
#######################################################################
if( $LZPDIFF ) {

        # Keep all info we've known so far
	# Goto beginning to read info for second file
	# if 2 sets of info are not match, exit

	if( $CURRFILE == 0 ) 
	{
		$FILE_INFO_A = $SAT.'_'.$RTPB.'_'.$SYNCPAT.'_'.$R_DAT_LEN.'_'.$R_ANN_LEN;
		$FILE_FMT_A = $FILE_FMT;
		$DATA_TYPE_A = $DATA_TYPE;
		$XX = open( A_IN, $FN ) || die "Can't open file $FILENAME[ $CURRFILE ]\n" ;
		@STAT = stat(A_IN);
		$FILE_SIZE_A = @STAT[7];
		$CURRFILE++;
		$NUMREC = $R_TOT;
		$R_TOT_A = $R_TOT;
		$SHORT_NAME = "FILE B: ";
		goto FILELOOP ;
	}
	else
	{
		$XX = open( B_IN, $FN ) || die "Can't open file $FILENAME[ $CURRFILE ]\n" ;
		@STAT = stat(A_IN);
		$FILE_SIZE_B = @STAT[7];
		$FILE_INFO_B = $SAT.'_'.$RTPB.'_'.$SYNCPAT.'_'.$R_DAT_LEN.'_'.$R_ANN_LEN;
		$FILE_FMT_B = $FILE_FMT;
		$DATA_TYPE_B = $DATA_TYPE;
		$NUMREC += $R_TOT;
		$R_TOT_B = $R_TOT;
	}

	($SAT_A,$RTPB_A,$SYNCPAT_A,$R_DAT_LEN_A,$R_ANN_LEN_A) = split(/_/, $FILE_INFO_A);
	($SAT_B,$RTPB_B,$SYNCPAT_B,$R_DAT_LEN_B,$R_ANN_LEN_B) = split(/_/, $FILE_INFO_B);

	#print "$DATA_TYPE_A,$SAT_A,$RTPB_A,$SYNCPAT_A,$R_DAT_LEN_A,$R_ANN_LEN_A\n";
        #print "$DATA_TYPE_B,$SAT_B,$RTPB_B,$SYNCPAT_B,$R_DAT_LEN_B,$R_ANN_LEN_B\n";

	if ($FILE_INFO_A ne $FILE_INFO_B)
        {
		if($REC_FMT_A eq "RECORD") { $SYNC_A = "N/A"; }
		else			 { $SYNC_A = sprintf("%8.8x", $SYNCPAT_A); }
		if($REC_FMT_B eq "RECORD") { $SYNC_B = "N/A"; }
		else			 { $SYNC_B = sprintf("%8.8x", $SYNCPAT_B); }
		
		print "*****************************************************************\n";
		print "\t\tDIFFERENT FILE TYPE. CAN'T COMPARE\n";
		print "\n\t FORMAT     SATTELITE    FRM_SYNC    DATA_LEN    ANNO_LEN\n\n";

		printf("FILE A:\t%7.7s    %10.10s    %8.8s    %8d    %8d\n", 
					$RTPB_A,$SAT_A,$SYNC_A,$R_DAT_LEN_A,$R_ANN_LEN_A);
		printf("FILE B:\t%7.7s    %10.10s    %8.8s    %8d    %8d\n", 
					$RTPB_B,$SAT_B,$SYNC_B,$R_DAT_LEN_B,$R_ANN_LEN_B);
		die "\n";
	}

        $HS = $F_HDR_LEN + $R_HDR_LEN ;         # header skip and overall record length

        $RSEEK = $HS ;  # location of first data record


        if( $REC_FMT eq "FRAME" )  	# go do FRAME comparison
	{
		if($SAT eq "WIND/POLAR") { isPOLAR($FILENAME[$CURRFILE]); }
		&FRM_PRE_SCAN(A_IN, B_IN);
		$MAJNUM_A = $MJFC_A;
		$MAJNUM_B = $MJFC_B;
		print "\nEND PRESCAN\n\n";


		$RS = seek( A_IN, $RSEEK, 0 ) ;
		$RS = seek( B_IN, $RSEEK, 0 ) ;

		$RB_A += sysread( A_IN, $REC_A, 600);
		$RB_B += sysread( B_IN, $REC_B, 600); 

		if( $DATA_TYPE_A eq "TLZP" && &Garbage_Loc($REC_A,  64) )  
		{
		  	$RS = seek( A_IN, 600,0);
		}
		else { $RS = seek( A_IN, 0, 0 ) ; }

		if( $DATA_TYPE_B eq "TLZP" && &Garbage_Loc($REC_B,  64) )
		{
		  	$RS = seek( B_IN, 600,0);
		}
		else { $RS = seek( B_IN, 0, 0 ) ; }

		if($DATA_TYPE_A eq "TLZP") { $RB_A = sysread(A_IN, $REC_A, 12); }
        	$RB_A = sysread( A_IN, $REC_A, $ReadLen) ;
		if($DATA_TYPE_B eq "TLZP") { $RB_B = sysread(B_IN, $REC_B, 12); }
        	$RB_B = sysread( B_IN, $REC_B, $ReadLen) ;

		$PHYS_FRM_A = 0;
		$PHYS_FRM_B = 0;
		$A_SAME_B=$A_DIFF_B=$A_NOT_IN_B=$B_NOT_IN_A=0;

		&FRM_DIFF( ); 
		print "\n------------------------ PDIFF SUMMARY ---------------------------\n";
		print "\nNumber of MIFs in A same as in B:\t\t\t$A_SAME_B\n";
		print "Number of MIFs in A diff from B:\t\t\t$A_DIFF_B\n";
		print "Number of MIFs in A not in B:\t\t\t\t$A_NOT_IN_B\n";
		print "Number of MIFs in B not in A:\t\t\t\t$B_NOT_IN_A\n\n";
	}
        if( $REC_FMT eq "RECORD" )  	# go do PRODUCT comparison
	{
        	$RB_A = sysread( A_IN, $REC_A, $ReadLen) ;
        	$RB_B = sysread( B_IN, $REC_B, $ReadLen) ;

		$PHYS_FRM_A = 0;
		$PHYS_FRM_B = 0;
		$A_SAME_B=$A_DIFF_B=$A_NOT_IN_B=$B_NOT_IN_A=0;

		&PROD_DIFF( ); 
		print "\n------------------------ PDIFF SUMMARY ---------------------------\n";
		print "\nNumber of MIFs in A same as in B:\t\t\t$A_SAME_B\n";
		print "Number of MIFs in A diff from B:\t\t\t$A_DIFF_B\n";
		print "Number of MIFs in A not in B:\t\t\t\t$A_NOT_IN_B\n";
		print "Number of MIFs in B not in A:\t\t\t\t$B_NOT_IN_A\n\n";
	}
}

#########################################################################
#	Do either BLK or FRM editing until end of file
#
#	At this point the following are set
#
#	$REC = first record from file
#	$RB  = status from read into $REC (number of bytes read)
#	$RECLEN = length of records to read
#	$RTPB = "RT" or "PB" depending on data sequence
#
#	Get list of blocks/frames to delete
#	Then call editor to do deletions
#
#######################################################################
if( $LZPEDIT ) { 

$DNUM = 0 ;

EINP:	E_INP() ;		# if EDIT, get deletion list

	E_PRT( 25 ) ;
	
	$EASK = "" ;
	while( ($EASK ne "R" and $EASK ne "r") and 
	       ($EASK ne "A" and $EASK ne "a") and 
	       ($EASK ne "O" and $EASK ne "o") ) {
		print( "Reset, Add to list, or OK (R,A,O)\n" ) ;
		$EASK = <STDIN> ;
		chop( $EASK ) ;		# remove last char (NL)
	}
	
	if( $EASK eq "A" || $EASK eq "a") { goto EINP }
	
	if( $EASK eq "R" || $EASK eq "r") {
		undef %DELETE ;
		undef @DL ;
		undef @DR ;
		$DNUM = 0 ;
		goto EINP ;
		} 
	
	
	$EASK = "" ;
	while( $EASK ne "Y" and $EASK ne "y" and $EASK ne "N" and $EASK ne "n" ) {
		print( "Edit file $FILENAME[ $CURRFILE ], output to $FNOUT (Y,N)\n" ) ;
		$EASK = <STDIN> ;
		chop( $EASK ) ;		# remove last char (NL)
	}

	if( $EASK eq "N" or $EASK eq "n" ) { exit }
	
	REC_EDIT( ) ; 		# do actual edit processing
}



#########################################################################
#	Do either BLK, FRM or CCSDS scanning until end of file
#
#	At this point the following are set
#
#	$REC = first record from file
#	$RB  = status from read into $REC (number of bytes read)
#	$RECLEN = length of records to read
#	$RTPB = "RT" or "PB" depending on data sequence
#
#	Position input file and read first record
#	Then call FRAME or BLOCK scanner
#
#######################################################################
if( $LZPSCAN ) { 

	$HS = $F_HDR_LEN + $R_HDR_LEN ;		# header skip and overall record length

	$RSEEK = $HS ; 	# location of first data record

	if( $BEGREC != 0 ) {
		$RSEEK = $HS + ( $BEGREC * $ReadLen ) ;
		#$RECNUM = $BEGREC -1 ;
	}

	$RS = seek( IN, $RSEEK, 0 ) ;

	$RB = sysread( IN, $REC, $ReadLen) ;

	if( $REC_FMT eq "BLOCK" ) {
		@R = unpack( "C24", $REC ) ;
		$EXPSEQ = $R[9] ;	 # set expected seq to start clean
	}

	if( $REC_FMT eq "FRAME" ) {
		@F = unpack( "C8", $REC ) ;
		$MFN_EXPECT = $F[3]  ;	# set expected minor frame number to start clean
	}

	if( $REC_FMT eq "FRAME" ) { FRM_SCAN( ) } 	# go do FRAME scanning

	if( $REC_FMT eq "BLOCK" ) { BLK_SCAN( ) } 	# go do block scanning

	if( $REC_FMT eq "CCSDS" ) { CCSDS_SCAN( ) } 	# go do CCSDS scanning

	if( $REC_FMT eq "PACOR" ) { PACOR_SCAN( ) } 	# go do PACOR scanning

	if( $REC_FMT eq "CDHFREC" ) { CDHF_SCAN( ) } 	# go do CDHF log scanning
	
	if( $REC_FMT eq "RECORD" ) { PROD_SCAN( ) }	# go do PRODUCT scanning
}

#########################################################################
#	When done processing one file
#	
#	Compute processing time and rate
#	Then advance to next file in list or exit if no more files
#
#######################################################################

SUMMARY:

$STOPTIME = time() ;
$TOTTIME = $STOPTIME - $STARTTIME ;
if( $TOTTIME eq 0 ) { $TOTTIME = 1 }

if($LZPDIFF) { 
   $AVGRATE = $NUMREC / $TOTTIME; 
   $AVGBITS = $AVGRATE * $ReadLen * 8;
}
else {
   $AVGRATE = $RECNUM  / $TOTTIME ;	# processing rate in frames/second
   $AVGBITS = $AVGRATE * $ReadLen * 8 ;	# processing rate in bits/second
}
$AVGKBPS = $AVGBITS / 1000    ;


printf( " Elapsed time = %5.1d sec.   Rate = %6.1d frms/sec.   %6.1d Kbps\n",
 	$TOTTIME, $AVGRATE, $AVGKBPS ) ;
print( "\n" ) ;
print( "\n" ) ;

NEXTFILE:

$CURRFILE++ ;

if( $CURRFILE < $NUMFILES ) { goto FILELOOP }

		#######################
exit ;		# end of main program #
		#######################
##################################################################################
##################################################################################
##################################################################################


#########################################################################
#		Prompt operator for list of record numbers to be deleted
#	
#		clean up list and return on arrays $DL[] and $DR[] as
#		left (DL) and right (DR) record deleteion number pairs
#
#######################################################################


sub E_INP {

$GET_INPUT++ ;

while( $GET_INPUT ) {

	print( "Enter $REC_FMT numbers to delete (e.g. 5, 9-12, 3, 123-999999, CR=done)\n" ) ;
	$EINP = <STDIN> ;
	if( length($EINP) == 1 ) { $GET_INPUT = "" ; next ; }

	$EINP =~ s/ - /-/g ;			# turn sss-sss into -
	$EINP =~ s/,/ /g ;			# turn commas into space

	print "$EINP\n";

	@EINPARMS = split( /[ \t\n]+/ , $EINP ) ;	# split on whitespace
	foreach $P (@EINPARMS) {
		( $P1,$P2 ) = split( /-/, $P ) ;

		if( $P eq $P1 ) { 		# only one parm
			if( not defined $DELETE{ $P1 } ) {
				$DELETE{ $P1 } = $P1 ;	# set single num delete
				}
			else {
				printf( "%s number %6.1d already defined\n", $REC_FMT, $P1 ) ;
			}
		}
		else {	# range of numbers identified

			if( $P2 < $P1 ) {	# invalid range
				printf( "Range %6.1d-%6.1d invalid, ignored\n", $P1, $P2) ;
				next;
			}

			if( defined $DELETE{ $P1 } ) {	#check for collision

				if( $P2 <= $DELETE{ $P1 } ) {
					printf( "%6.1d LE %6.1d-%6.1d\n",$P2,$P1,$DELETE{$P1});
				}

				if( $P2 > $DELETE{ $P1 } ) {
					printf( "%6.1d GT %6.1d-%6.1d\n",$P2,$P1,$DELETE{$P1});
					$DELETE{ $P1 } = $P2 ;
				}

			}
			else {	# no collision, enter range
				$DELETE{ $P1 } = $P2 ;
				}
		}
	}

		# Clean up overlap 

	$DNUM = 0 ;
	$DLP = $DRP = 0 ; 	# previous values for cleanup pass
	foreach( sort numerically keys %DELETE ) {

			# start = previous start + 1, end <= previous end, clear entry
#		printf( "%6.1d-%6.1d  test consec  %6.1d-%6.1d\n",$_,$DELETE{$_},$DLP,$DRP);
		if( $_ == $DRP+1  ) {
#			printf( "%6.1d-%6.1d CONSEC %6.1d-%6.1d, stretched\n",$_,$DELETE{$_},$DLP,$DRP);
			$DELETE{ $DLP } = $DELETE{ $_ } ;
			$DRP = $DELETE{ $DLP } ;
			delete( $DELETE{$_} ) ;
			next ;
		}

			# start = previous start, end <= previous end, clear entry
#		printf( "%6.1d-%6.1d  test inside  %6.1d-%6.1d\n",$_,$DELETE{$_},$DLP,$DRP);
		if( ($_ < $DRP) and ($DELETE{ $_ } <= $DRP) ) {
#			printf( "%6.1d-%6.1d INSIDE %6.1d-%6.1d, ignored\n",$_,$DELETE{$_},$DLP,$DRP);
			delete( $DELETE{$_} ) ;
			next ;
		}

			# start = previous start, end >  previous end, move end, clear this
#		printf( "%6.1d-%6.1d  test end  %6.1d-%6.1d\n",$_,$DELETE{$_},$DLP,$DRP);
		if( ($_ < $DRP) and ($DELETE{ $_ } > $DRP) ) {
#			printf( "%6.1d-%6.1d GT END %6.1d-%6.1d, move end\n",$_,$DELETE{$_},$DLP,$DRP);
			$DELETE{ $DLP } = $DELETE{ $_ } ;
			$DRP = $DELETE{ $DLP } ;	# move previous right reference
			delete( $DELETE{$_} ) ;
			next ;
		}
	
			# if neither case above matched, just move to new range	
		$DLP = $_ ;	# move previous pointer to the current range
		$DRP = $DELETE{ $_ } ;
	}

		# Unload associative array DELETE into DL and DR arrays

	$DNUM = 0 ;
	foreach( sort numerically keys %DELETE ) {
		$DL[ $DNUM ] = $_ ;
		$DR[ $DNUM++ ] = $DELETE{ $_ } ;
	}

	if( $DL[ 0 ] == 0 ) { $DL[ 0 ] = 1; } 	# don't like zero base here
	
}

}		# return

sub numerically { $a <=> $b }
#########################################################################
#		Print out entire left-right pairs formatted on screen
#	
#		E_PRT( #rows )
#
#		Assumes pairs in $DL and $DR arrays and number of rows
#		  to display before pausing is passed in
#
#######################################################################


sub E_PRT {

$EROWS = $_[0] ;
$E = 0 ;

printf( " Record Deletetion Table ( %3.1d entries)\n", $DNUM ) ;

while( $E < $DNUM ) {

	printf( "%3.1d. %7.1d", $E, $DL[ $E ] ) ;
	if( $DL[ $E ] == $DR[ $E ] ) { 
		printf( "          " ) ; }	# single value
		else {
		printf( "-%-7.1d  ", $DR[ $E ] ) ; # end of range
	}

	print( "\n" ) ;
	
	$E++ ;
}

print( "\n" ) ;
}		# return

#########################################################################
#		Do record editing until end of file
#
#
#######################################################################

sub REC_EDIT{

$MAJNUM=0; $MODE=0; $PB5PRT=0; $PRTMSG="";	

$YY = open( OUT, $FNOUT ) || die "Can't open file $FNOUT\n" ;

$RS = seek( IN, 0, 0 ) ;	# rewind file

if( $F_HDR_LEN ) { 		# if file header, copy it to output
	$RB = sysread(   IN, $REC, $F_HDR_LEN ) ;
	$WB = syswrite( OUT, $REC, $F_HDR_LEN ) ;
}

$RB = sysread( IN, $REC, $ReadLen ) ;	# then get first record 
$RECNUM = 1 ;				# record numbers start at 1

$D = 0 ;

while( $RB == $ReadLen ) {

	if( $RECNUM == $DL[ $D ] ) {		#skip this record
		while( $RECNUM <= $DR[$D] ) {
			$DWINDOW++ ; 		# count consecutive deletions
			$PRTMSG = "DELETED" ;
			$REC_DELETED ++ ;
			if( $DWINDOW < 10  or $RECNUM == $DR[$D] or $LONG ) {	# print first 10 and last

				if( $DWINDOW >= 10 and $RECNUM == $DR[$D] and not $LONG ) {
					print( "   ...\n" ) ;
					print("  Deleted all $REC_FMT" . "s through\n") ;
				}

				if( $REC_FMT eq 'BLOCK' ) {
					$P_REC = substr( $REC, $R_HDR_LEN, $R_DAT_LEN ) ;
					BLK_PRT( $P_REC, $RECNUM, $PRTMSG);
				}

	 			if( $REC_FMT eq 'FRAME' ) {
					($SYNC, $MFN, @DATA) = unpack( "L1 X C1 C8 ", $REC ) ;
					if($SAT eq "WIND/POLAR") {
						if( ($MFN)%5 == 0 ) { $MODE = $DATA[0] ;}
						if( $MNF%25 == 0 ) { $MAJNUM = $DATA[0] ;}
                                         } 
					elsif ($SAT eq "GEOTAIL") {
						$PB5[$MFN %4] = $DATA[0];
						if( $MFN%256 == 0 ) {
                                			$MAJNUM = $DATA[ 1 ];
							$PB5PRT = unpack("L1", pack("C4", @PB5));
						}
					}
					FRM_PRT( $REC, $RECNUM, $MAJNUM, $MODE, $PB5PRT, $PRTMSG);
				}
			}

			$RB = sysread( IN, $REC, $ReadLen ) ;
			if( $RB != $ReadLen ) { last ; }
			
			$RECNUM ++ ;
			}
		print( "\n" ) ;
		$D++ ; 		#advance to next deletetion spec
		}
	else {
		$WB = syswrite( OUT, $REC, $ReadLen ) ;
		$DWINDOW = 0 ;
		$REC_COPIED ++ ;

		$RB = sysread(   IN, $REC, $ReadLen ) ;
		if( $RB != $ReadLen ) { last ; }
		$RECNUM++ ;
	}
}

print( "\n" ) ;
print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ] EDIT   ( output in $FNOUT)\n" ) ;
print( "\n" ) ;
printf( " Total records READ %7.1d\n", $RECNUM ) ;
printf( "     records OUTPUT %7.1d     DELETED %7.1d\n", $REC_COPIED, $REC_DELETED ) ;
print( "\n" ) ;

}		# return

#########################################################################
#		Do PACOR scanning until end of file
#
#######################################################################

sub PACOR_SCAN{

	$RS = seek( IN, 0, 0 ) ;

	$RB = sysread( IN, $REC, 4 ) ;
	if( $REC eq "MBEG" ) { 		# skip MBEG if necessary
		$RB = sysread( IN, $REC, 4 ) ; 
		$RB = sysread( IN, $REC, 4 ) ; 	# read in DBEG string
	}

	if( $REC eq "DBEG" ) { $RB = sysread( IN, $DUS, 60 ) } #read DBEG( DUS header)
		else{ print( "DBEG format error at $RECNUM - exiting\n" ) ; exit(0) ; }

	$DBNUM = 0 ;

	while( $RB ) {

		if( ++$RECNUM > $ENDREC ) { last }

		@DS = unpack( "S30", $DUS ) ;	# convert to 16 bit integers

		$DULEN = $DS[ 16 ] ;	# get Data Unit length field

		if( $DULEN == 0 ) { last }	# see if last DUS

		$DUPAD = $DULEN % 4 ;	# pad to 4 byte boundary
		if( $DUPAD ) { $DUPAD = 4 - $DUPAD }
		$DULEN = $DULEN + $DUPAD ;

		$RB = sysread( IN, $DU, $DULEN ) ;	# read Data Unit

		$ANFLGS = 0 ;		# check for normal flags
		if( $DS[26] != 0x0400 ) { $ANFLGS++ }
		if( $DS[27] != 0x0400 ) { $ANFLGS++ }
		if( $DS[28] != 0x0100 ) { $ANFLGS++ }
		if( ( $DS[29] & 0xdf00 )  != 0x0000 ) { $ANFLGS++ }

		$SYNC = unpack( "L1", $DU ) ;

		if( $SYNC == 0x1acffc1d  ) {
			$TOT_PERFSYNC ++ ;	# count perfect sync patterns
			if( $ANFLGS == 0 ) { $CONSEC_GOOD ++ ;	} #  indicate consec. good rec
			}
		else {
			$PRTMSG = "Bad Sync" ;
			$TOT_IMPRSYNC ++ ;	# count imperfect sync patterns
			$WINDOW_ON ++ ;		# turn on print of bad frames window
		}
		
		if( $ANFLGS == 0 ) {
			$TOT_PERFFLGS ++ ;	# count perfect annotation flags
			}
		else {
			$PRTMSG = $PRTMSG . "FLAGS   " ;
			$TOT_IMPRFLGS ++ ;	# count imperfect annotation flags
			$WINDOW_ON ++ ;		# turn on print of bad frames window
		
			#	$MASK = 0x001 ;
			#	for ( $I=12 ; $I > 0 ; $I-- ) {
			#		if( $ANFLGS & $MASK ) { $ANF_TOT[ $I ]++ ; }
			#		$MASK = $MASK << 1 ;
			#	}
		}

		if( $PRTMSG eq "" ) { $PRTMSG = "        " ; }
				
		##################################################################
		# See if Error window ON and we need to print last good frame
		##################################################################

		if( $WINDOW_ON && $LONG && not $WINDOW_LAST ) {		
			$CONSEC_GOOD = 0 ;	# reset consecutive good counter
			if( $WINDOW_REC != $RECNUM_LAST ) {	#don't repeat previous
				print( "\n" ) ;
				$FGOOD = "GOOD    " ;
				if( $RECNUM != 1 ) { 
					DBEG_PRT( $DUS_LAST, $DU_LAST, $RECNUM_LAST, $FGOOD);
				}
			}
			$WINDOW_LAST ++ ; 	# indicate old frame printed
		}
			# now print this frame if Error window ON or if One line print mode

		if( ($WINDOW_ON && $LONG) || $OLINE) 	{
		
			DBEG_PRT( $DUS, $DU, $RECNUM, $PRTMSG);
			$WINDOW_REC = $RECNUM ; 	# remember last recnum printed
		}	
	
		# Clear PRTMSG and see if we are back in good data and turn off window

		$PRTMSG = "" ;	
		if( $CONSEC_GOOD >= 1 ) { $WINDOW_ON = 0 ; $WINDOW_LAST = 0}

		$DU_LAST = $DU;		#save last frame for dumping if we detect problems
		$DUS_LAST = $DUS ;
		$RECNUM_LAST  = $RECNUM ;

		$RB = sysread( IN, $REC, 4 ) ;
		if( $RB == 0 ) { last } 	# see if end of file

		if( $REC eq "MBEG" ) { 		# skip MBEG if necessary
			$RB = sysread( IN, $REC, 4 ) ;
			$RB = sysread( IN, $REC, 4 ) ; 	# read in DBEG string
		}

		if( $REC eq "DBEG" ) { $RB = sysread( IN, $DUS, 60 ) } #read DBEG( DUS header)
			else{ print( "DBEG format error at $RECNUM - exiting\n" ) ; exit(0) ; }
	}

print( "\n" ) ;
$PRTMSG = "FINAL PACOR DUS-DU\n" ;
DBEG_PRT( $DUS, $DU, $RECNUM, $PRTMSG);

print( "\n" ) ;
print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ]\n" ) ;
print( "\n" ) ;
print( "  Total DUS_DU       = $RECNUM\n" ) ;
#print( "  Total Perfect Sync = $TOT_PERFSYNC     Bad Sync  = $TOT_IMPRSYNC\n" ) ;
#print( "  Total NO Flags Set = $TOT_PERFFLGS     Flags Set = $TOT_IMPRFLGS\n" ) ;

#if( $R_ANN_LEN ) {
#	for ( $I=1 ; $I < 13 ; $I++ ) {
#		$IPLUS4 = $I + 4 ;
#		printf( " Total F%2.1d = %6.0d \n", $IPLUS4, $ANF_TOT[ $I ] ) ;
#	}
#}

print( "\n" ) ;
}

#########################################################################
#       Subroutine to print a DUS-DU formatted, one line header
#       $_[0] -	$DUS    - data unit summary
#       $_[1] -	$DU     - data unit 
#       $_[2] - $RECNUM - sequential record count to identify frame
#       $_[3] - $PRTMSG - text string to print at end of line
#
#       DBEG_PRT   ( DUS, DU, RECNUM, PRTMSG  ) ;
#
#       Returns  nothing special 
#
#######################################################################

sub DBEG_PRT  {
	if( not $TITLE_DONE ) {
		print "  Seq.   SYNC     SC VC Mas/VC         FLG           Ground Time\n" ; 
		$TITLE_DONE ++ ;
	}

	@DS = unpack( "S30", $_[0] ) ;

	$DULEN = $DS[ 16 ] ;
	$DOY = ( $DS[18] >> 5 ) & 0x7ff ;
	$MSOD = ( ( $DS[18] & 0x1f ) << 22 ) | ( $DS[19] << 6 ) | 
			( ( $DS[20] >> 10 ) & 0x3f) ;
	$USOMS = ( $DS[20] & 0x3ff ) ;

	@R = unpack( "C12" , $_[1] ) ;

	$CCSDS_VERS = ( $R[4] >> 14 ) & 0x3 ;

	if( $CCSDS_VERS == 0 ) {
		$CCSDS_SCID = ( ( $R[4] & 0x3f ) <<4 ) | ( ( $R[5] >>4 ) & 0xf ) ;
		$CCSDS_VCID = ( $R[5] >> 1 ) & 0x7  ;
		$CCSDS_MASTER = $R[6] ;
		$CCSDS_VC     = $R[7] ;
		}
	else	{
		$CCSDS_SCID = ( ( $R[4] & 0x3f ) <<2 ) | ( ( $R[5] >>6 ) & 0x3 ) ;
		$CCSDS_VCID = ( $R[5] & 0x3f )  ;
		$CCSDS_VCCNT = ( $R[6] << 16 ) | ( $R[7] << 8 ) | $R[8] ;
	}

	if( not $FIELD ) {
	printf( "#%6.1d  %2.2x%2.2x%2.2x%2.2x %2.1d %2.1d %3.1d/%3.1d %4.4x%4.4x %4.4x%4.4x %s ", 
		$_[2],  $R[0], $R[1], $R[2], $R[3] ,  
		$CCSDS_SCID, $CCSDS_VCID, $CCSDS_MASTER, $CCSDS_VC, 
		$DS[26], $DS[27], $DS[28], $DS[29] , $_[3] ) ; 

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);
	}
	
	else {
	$FLD0 = $FIELD - 1 ;
	$FLD_EXT = unpack( "x$FLD0 C1", $_[1] ) ;
	printf( "#%6.1d  %3.1d/%3.1d %2.2x %2.2x%2.2x%2.2x %2.2x [%2.2x] %s", 
		$_[2], $_[2], $HM, $_[3], $R[0], $R[1], $R[2], $R[3], $FLD_EXT, $_[3] ) ; 
	printf( " %3.1x  ", $FLG ) ;

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);
	}
	
	if( $DELTA ) {
		$DL_MSOD = $MSOD - $PREV_MSOD ;
		$DL_USOMS = $USOMS - $PREV_USOMS ;
		if( $DL_USOMS < 0 ) { $DL_USOMS += 1000 ; $DL_MSOD -= 1 ; }
		if( $PREV_MSOD ) { printf( " del=%8.1d %3.3d", $DL_MSOD, $DL_USOMS ) ; }
		$PREV_MSOD = $MSOD ;
		$PREV_USOMS = $USOMS ;
	}

	printf( " %s\n", $_[5] ) ;

	if( $HEX ) { 
		printf( "\n" ) ;
		HEXPRT( $_[0], 60 ) ; 
		printf( "\n" ) ;
		HEXPRT( $_[1], $DULEN ) ; 
		printf( "\n" ) ;
	}
}		# return


#########################################################################
#		Do CDHF scanning until end of file
#
#######################################################################

sub CDHF_SCAN{

$FRMLEN = 256  ;
$FRMNUM = $RECNUM * 60 ;	# adjust frame count in case beginning skip

$RTOT_LEN = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN + $R_ANN_LEN + $R_TRL_LEN ;

$MFN_EXPECT = unpack( "C1", $REC ) ;	# initialize expect minor frame count 

printf( "\n" ) ;
printf( "CDHF Log File Start Record\n\n" ) ;

HEXPRT( $IDRFHDR, 24 ) ;	# hex dump first 24 bytes of start record

while( $RB ) {

	if( ++$RECNUM > $ENDREC ) { last }

	$RINBUF = int( $RB / 264) ;	# adjust for short records

	if( $RB < $RTOT_LEN ) { 
		printf( " Short record encountered\n" ) ;
		printf( "    Record # %7.1d only %2.1d frames\n", $RECNUM, $RINBUF ) ;
		printf( "    only %6.1d of %6.1d read\n", $RB, $RTOT_LEN ) ;
	}
	
	for( $RF=0 ; $RF < $RINBUF ; $RF++ ) {	# walk through 60 frames in record

		$FRM_OFFSET =  $RF * 264 ;
		$CREC = substr( $REC, $FRM_OFFSET, 264 ) ; 	# get one frame
	
		# unpack CREC into Sync word, Minor Frame Num, and Data bytes
			
		($MFN, $SYNC, $ANFLGS) = unpack( "C1 x252 L1 X S1 ", $CREC ) ;

		$SYNC   = ( $SYNC   >> 8 ) & 0xffffff ;
		$ANFLGS = ( $ANFLGS >> 4 ) & 0xfff ;

			# do a quick check for zero fields and skip since
			# they should be fil frames in the last record

		if( $MFN==0 and $SYNC==0 ) { $CDHF_FILL++; next ; }

		$FRMNUM++ ;

		##################################################################
		#		Check for perfect frame sync pattern 0xfaf320
		##################################################################

		if( $SYNC == $SYNCPAT ) {
			$TOT_PERFSYNC ++ ;	# count perfect sync patterns
			$CONSEC_GOOD ++ ;	#  indicate consec. good rec
			}
		else {
			$PRTMSG = "Bad Sync Pattern " ;
			$TOT_IMPRSYNC ++ ;	# count imperfect sync patterns
			$WINDOW_ON ++ ;		# turn on print of bad frames window
		}

		if( $MFN == $MFN_EXPECT ) {
			$TOT_PERFMFN ++ ;	# count perfect sequence numbers
			}
		else {
			$PRTMSG = "Bad MFN " ;
			$TOT_IMPRMFN ++ ;	# count imperfect sequence numbers
			$WINDOW_ON ++ ;		# turn on print of bad frames window
		}

		if( $ANFLGS == 0 ) {
			$TOT_PERFFLGS ++ ;	# count perfect annotation flags
			}
		else {
			$PRTMSG = $PRTMSG . "FLAGS " ;
			$TOT_IMPRFLGS ++ ;	# count imperfect annotation flags
			$WINDOW_ON ++ ;		# turn on print of bad frames window

			$MASK = 0x001 ;
			for ( $I=12 ; $I > 0 ; $I-- ) {
				if( $ANFLGS & $MASK ) { $ANF_TOT[ $I ]++ ; }
				$MASK = $MASK << 1 ;
			}
		}
		
		##################################################################
		# See if Error window ON and we need to print last good frame
		##################################################################

		if( $WINDOW_ON && $LONG && not $WINDOW_LAST ) {		
			$CONSEC_GOOD = 0 ;	# reset consecutive good counter
			if( $WINDOW_REC != $FRMNUM_LAST ) {	#don't repeat previous
				print( "\n" ) ;
				$FGOOD = "GOOD" ;
				if( $FRMNUM != 1 ) { 
					CDHF_PRT($CREC_LAST, $RECNUM_LAST, $FRMNUM_LAST, $FGOOD ) ;
				}
			}
			$WINDOW_LAST ++ ; 	# indicate old frame printed
		}

		# now print this frame if Error window ON or if One line print mode

		if( ($WINDOW_ON && $LONG) || $OLINE) 	{
		
			CDHF_PRT( $CREC, $RECNUM, $FRMNUM, $PRTMSG);
			$WINDOW_REC = $FRMNUM ; 	# remember last recnum printed
		}	
		
		# Clear PRTMSG and see if we are back in good data and turn off window

		$PRTMSG = "" ;	
		if( $CONSEC_GOOD >= 1 ) { $WINDOW_ON = 0 ; $WINDOW_LAST = 0}

		$CREC_LAST = $CREC;		#save last frame for dumping if we detect problems
		$RECNUM_LAST  = $RECNUM ;
		$FRMNUM_LAST  = $FRMNUM ;
		$MFN_EXPECT   = $MFN + 1 ;	# set next expected MFN

		if( $MFN_EXPECT >= 250 ) { $MFN_EXPECT = 0 } ;
	
	}	# loop through all 60 frames in a record before reading next
	
	if( $OLINE ) { $TRLR = substr( $REC, 15840, 4 ) ; HEXPRT( $TRLR, 4 ) ; }

	$LOCSTRT = $LOC ;

	$LOC += $R_TOT_LEN ;	   #keep running byte count

	$RB = sysread( IN, $REC, $RTOT_LEN ) ;
	
	if( Pattern_Loc( $REC, 0x494c5a50, 0 ) ){
	
		print( "\n" ) ;
		print( "Session End Record\n\n" ) ;
		
		HEXPRT( $REC, 24 ) ;
		
		last ;
	}
}

print( "\n" ) ;
print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ]\n" ) ;
print( "\n" ) ;
printf( "  Total Data frames  = %8.1d     Fill frms = %8.1d\n", $FRMNUM, $CDHF_FILL ) ;
printf( "  Total Perfect Sync = %8.1d     Bad Sync  = %8.1d\n", $TOT_PERFSYNC, $TOT_IMPRSYNC ) ;
printf( "  Total Perfect  MFN = %8.1d     Bad  MFN  = %8.1d\n", $TOT_PERFMFN, $TOT_IMPRMFN ) ;
printf( "  Total NO Flags Set = %8.1d     Flags Set = %8.1d\n", $TOT_PERFFLGS, $TOT_IMPRFLGS ) ;

print( "\n" ) ;
print( "\n" ) ;
for ( $I=1 ; $I < 13 ; $I++ ) {
	$IPLUS4 = $I + 4 ;
	printf( " Total F%2.1d = %6.0d \n", $IPLUS4, $ANF_TOT[ $I ] ) ;
}

print( "\n" ) ;

}		# end of CDHF processing routine,  return


#########################################################################
#       Subroutine to print a CDHF frame formatted, one line header
#       $_[0] -	$REC    - frame string
#       $_[1] - $RECNUM - sequential record count to identify record
#	$_[2] - $FRMNUM - Frame number that goes with frame 
#       $_[3] - $PRTMSG - text string to print at end of line
#
#       CDHF_PRT   ( REC, RECNUM, FRMNUM,  PRTMSG  ) ;
#
#       Returns  nothing special 
#
#######################################################################

sub CDHF_PRT  {
	if( not $TITLE_DONE ) {
		print "  Recnum. Frmnum.  MFN  DATA  ... SYNC    FLG  Ground Time\n" ; 
		$TITLE_DONE ++ ;
	}

	@R  = unpack( "C12 " , $_[0] ) ;
	$FS = unpack( "x253 L1" , $_[0] ) ;
	$FS = ( $FS   >> 8 ) & 0xffffff ;

	 	# extract annotation field
	$ANN = substr( $_[0] , 256, 8 ) ;
	ANN_SPLIT( $ANN ) ;

	printf( "# %6.1d  %6.1d   %2.2x  %2.2x%2.2x%2.2x%2.2x  %6.6x ", 
		$_[1], $_[2], $R[0], $R[1], $R[2], $R[3], $R[4],  $FS  ) ;

	printf( " %3.1x ", $FLG ) ;

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);

#	if( $TIME ) {	# see if time desired in HH:MM:SS format
#
#		$HR = int( $MSOD/3600000 ) ;
#		$MN = int( ( $MSOD - $HR * 3600000 ) / 60000 ) ;
#		$SC = int( ( $MSOD - $HR * 3600000 - $MN * 60000 ) / 1000 ) ;
#		$MS = $MSOD - ($HR * 3600000) - ($MN * 60000) - ($SC * 1000) ;
#
#        	printf( " %3.1x %3.3d-%2.2d:%2.2d:%2.2d.%3.3d%3.3d",
#                	$FLG, $DOY, $HR, $MN, $SC, $MS, $USOMS ) ;
#	}
#
#	else {
#		
#		printf( " %3.1x %3.3d-%8.1d.%3.3d",
#			$FLG, $DOY, $MSOD, $USOMS ) ;
#	}

	
	if( $DELTA ) {
		$DL_MSOD = $MSOD - $PREV_MSOD ;
		$DL_USOMS = $USOMS - $PREV_USOMS ;
		if( $DL_USOMS < 0 ) { $DL_USOMS += 1000 ; $DL_MSOD -= 1 ; }
		if( $PREV_MSOD ) { printf( " del=%8.1d %3.3d", $DL_MSOD, $DL_USOMS ) ; }
		$PREV_MSOD = $MSOD ;
		$PREV_USOMS = $USOMS ;
	}

	printf( " %s\n", $_[3] ) ;

	if( $HEX ) { 
		printf( "\n" ) ;
		HEXPRT( $_[0], 256 ) ; 
		
		HEXPRT( $ANN,  8 ) ; 
		printf( "\n" ) ;
	}
}		# return



#########################################################################
#		Do CCSDS scanning until end of file
#
#######################################################################

sub CCSDS_SCAN{

$FRMLEN = $R_DAT_LEN + $R_RS_LEN ;

$RTOT_LEN = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN + $R_ANN_LEN + $R_TRL_LEN ;

while( $RB ) {

	if( ++$RECNUM > $ENDREC ) { last }
	
		# unpack REC into Sync word, Minor Frame Num, and Data bytes
			
	($SYNC, $MFN, @DATA) = unpack( "L1 X C1 C8 ", $REC ) ;

	if( $R_ANN_LEN ) {
		$ANFLGS = unpack("x$FRMLEN S1", $REC ) ;     #  grab 12 bit annotation field
		$ANFLGS = ( $ANFLGS >> 4 ) & 0xfff ;
	}
	else { $ANFLGS = 0 ; }

		##################################################################
		#		Check for perfect frame sync pattern 0x1acffc1d
		##################################################################

	if( $SYNC == 0x1acffc1d ) {
		$TOT_PERFSYNC ++ ;	# count perfect sync patterns
		if( $ANFLGS == 0 ) { $CONSEC_GOOD ++ ;	} #  indicate consec. good rec
		}
	else {
		$PRTMSG = "Bad Sync Pattern " ;
		$TOT_IMPRSYNC ++ ;	# count imperfect sync patterns
		$WINDOW_ON ++ ;		# turn on print of bad frames window
	}

	if( $ANFLGS == 0 ) {
		$TOT_PERFFLGS ++ ;	# count perfect annotation flags
		}
	else {
		$PRTMSG = $PRTMSG . "FLAGS " ;
		$TOT_IMPRFLGS ++ ;	# count imperfect annotation flags
		$WINDOW_ON ++ ;		# turn on print of bad frames window

		$MASK = 0x001 ;
		for ( $I=12 ; $I > 0 ; $I-- ) {
			if( $ANFLGS & $MASK ) { $ANF_TOT[ $I ]++ ; }
			$MASK = $MASK << 1 ;
		}
	}
		
		##################################################################
		# See if Error window ON and we need to print last good frame
		##################################################################

	if( $WINDOW_ON && $LONG && not $WINDOW_LAST ) {		
		$REJECT_MIN++ ;		# turn on minor frame reject
		$CONSEC_GOOD = 0 ;	# reset consecutive good counter
		if( $WINDOW_REC != $RECNUM_LAST ) {	#don't repeat previous
			print( "\n" ) ;
			$FGOOD = "GOOD" ;
			if( $RECNUM != 1 ) { 
				CCSDS_PRT($REC_LAST, $RECNUM_LAST, $FGOOD ) ;
			}
		}
		$WINDOW_LAST ++ ; 	# indicate old frame printed
	}

		# now print this frame if Error window ON or if One line print mode

	if( ($WINDOW_ON && $LONG) || $OLINE) 	{
		
		CCSDS_PRT( $REC, $RECNUM, $PRTMSG);
		$WINDOW_REC = $RECNUM ; 	# remember last recnum printed
	}	
		
		# Clear PRTMSG and see if we are back in good data and turn off window

	$PRTMSG = "" ;	
	if( $CONSEC_GOOD >= 1 ) { $WINDOW_ON = 0 ; $WINDOW_LAST = 0}

	$REC_LAST = $REC;		#save last frame for dumping if we detect problems
	$RECNUM_LAST  = $RECNUM ;
	$REJECT_MIN = 0 ;	# clear minor frame reject flag

	$LOCSTRT = $LOC ;

	$LOC += $ReadLen ;	   #keep running byte count

	$RB = sysread( IN, $REC, $ReadLen ) ;
}

print( "\n" ) ;
$PRTMSG = "FINAL CCSDS frame\n" ;
CCSDS_PRT( $REC, $RECNUM, $PRTMSG);

$PB5END = PB5_STR(@PB5 ) ;

print( "\n" ) ;
print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ]\n" ) ;
print( "\n" ) ;
print( " Start PB5TIME = $PB5START     End PB5TIME = $PB5END\n" ) ;
print( "\n" ) ;
print( "  Total frames       = $RECNUM\n" ) ;
print( "  Total Perfect Sync = $TOT_PERFSYNC     Bad Sync  = $TOT_IMPRSYNC\n" ) ;
print( "  Total NO Flags Set = $TOT_PERFFLGS     Flags Set = $TOT_IMPRFLGS\n" ) ;

if( $R_ANN_LEN ) {
	for ( $I=1 ; $I < 13 ; $I++ ) {
		$IPLUS4 = $I + 4 ;
		printf( " Total F%2.1d = %6.0d \n", $IPLUS4, $ANF_TOT[ $I ] ) ;
	}
}
print( "\n" ) ;

}		# end of CCSDS processing routine,  return


#########################################################################
#       Subroutine to print a CCSDS frame formatted, one line header
#       $_[0] -	$REC    - frame string
#       $_[1] - $RECNUM - sequential record count to identify frame
#	$_[2] - $MAJNUM - MAJOR frame number that goes with frame
#	$_[3] - $MODE   - MODE that goes with frame
#       $_[4] - $PRTMSG - text string to print at end of line
#
#       CCSDS_PRT   ( REC, RECNUM, MAJNUM, MODE, PRTMSG  ) ;
#
#       Returns  nothing special 
#
#######################################################################

sub CCSDS_PRT  {
	if( not $TITLE_DONE ) {
		print "  Seq.   SYNC     SC VC Mas/VC Data     FLG  Ground Time\n" ; 
		$TITLE_DONE ++ ;
	}

	@R = unpack( "C12" , $_[0] ) ;
	$CCSDS_VERS = ( $R[4] >> 14 ) & 0x3 ;

	if( $CCSDS_VERS == 0 ) {
		$CCSDS_SCID = ( $R[4] >> 3 ) & 0x7 ;
		$CCSDS_VCID = ( $R[5] >> 1 ) & 0x7  ;
		$CCSDS_MASTER = $R[6] ;
		$CCSDS_VC     = $R[7] ;
		}
	else	{
		$CCSDS_SCID = ( $R[4] >> 3 ) & 0x7 ;
		$CCSDS_VCID = ( ( $R[4] << 5 ) & 0xe0 ) | ( ( $R[5] >> 3 ) & 0x1f ) ;
	}

	if( $R_ANN_LEN ) { 	# if annotation field, extract it
		$UFRMLEN = $R_DAT_LEN + $R_RS_LEN ;
		$ANN = substr( $_[0] , $UFRMLEN, 8 ) ;
		ANN_SPLIT( $ANN ) ;
	}

	if( not $FIELD ) {
	printf( "#%6.1d  %2.2x%2.2x%2.2x%2.2x %2.1d %2.1d %3.1d/%3.1d %2.2x%2.2x %2.2x%2.2x %s", 
		$_[1], $R[0], $R[1], $R[2], $R[3],  
		$CCSDS_SCID, $CCSDS_VCID, $CCSDS_MASTER, $CCSDS_VC, 
		$R[8], $R[9], $R[10], $R[11], $_[4] ) ; 
	printf( " %3.1x  ", $FLG ) ;

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);
	}
	
	else {
	$FLD0 = $FIELD - 1 ;
	$FLD_EXT = unpack( "x$FLD0 C1", $_[0] ) ;
	printf( "#%6.1d  %3.1d/%3.1d %2.2x %2.2x%2.2x%2.2x %2.2x [%2.2x] %s", 
		$_[1], $_[2], $HM, $_[3], $R[0], $R[1], $R[2], $R[3], $FLD_EXT, $_[4] ) ; 
	printf( " %3.1x  ", $FLG ) ;

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);
	}
	
	if( $DELTA ) {
		$DL_MSOD = $MSOD - $PREV_MSOD ;
		$DL_USOMS = $USOMS - $PREV_USOMS ;
		if( $DL_USOMS < 0 ) { $DL_USOMS += 1000 ; $DL_MSOD -= 1 ; }
		if( $PREV_MSOD ) { printf( " del=%8.1d %3.3d", $DL_MSOD, $DL_USOMS ) ; }
		$PREV_MSOD = $MSOD ;
		$PREV_USOMS = $USOMS ;
	}

	printf( " %s\n", $_[5] ) ;

	if( $HEX ) { 
		printf( "\n" ) ;
		HEXPRT( $_[0], $R_DAT_LEN ) ; 
		
		if( $R_RS_LEN ) { 
			$CRS = substr( $_[0], $R_DAT_LEN, $R_RS_LEN ) ; 
			HEXPRT( $CRS, $R_RS_LEN ) ; 
		}
		HEXPRT( $ANN,  $R_ANN_LEN ) ; 
		printf( "\n" ) ;
	}
}		# return


#########################################################################
#		Do FRM scanning until end of file
#
#######################################################################

sub FRM_SCAN{
    local ($NUM_FRM_READ, $MFN_BIT1, $MAJNUM);

$NUM_FRM_READ = 1;
$RECNUM = $MODE = 0 ;  $MFN_BIT1 = 0x000; $MAJNUM = -999; 
$FRMLEN = $R_DAT_LEN + $R_RS_LEN;
$RTOT_LEN = $R_HDR_LEN + $R_DAT_LEN + $R_RS_LEN + $R_ANN_LEN + $R_TRL_LEN ;
if($SAT eq "WIND/POLAR") { isPOLAR($FILENAME[$CURRFILE]); } 

seek(IN, 0, 0);
$RB = sysread( IN, $REC, 600 ) ;
if( $DATA_TYPE eq "TLZP" && Garbage_Loc($REC,  64) )  
{
	seek(IN, 600, 0);
}
else { $RS = seek( IN, 0, 0 ) ; }

if($DATA_TYPE eq "TLZP") {  # Read off block header if TLZP
    $RB = sysread( IN, $REC, 12 ); 
}
$RB = sysread( IN, $REC, $ReadLen ) ;

while( $RB ) {

	$RECNUM++;

	if( $RECNUM < ($BEGREC-200) ) { goto SKIPAFRM; }
	
	if($RECNUM > $ENDREC) { $LONG=$OLINE=$HEX=0; };
#	{ 
#		if( ($VERBOSE == 1) && ($RECNUM < $R_TOT - 200) ) { goto SKIPAFRM;} 
#		else {last} 
#	}

#        if((not $LONG) and (not $OLINE) and (not $HEX)) 
#	{
#	    if($PB5START)
#	    {
#	        if(not defined $REC_SKIP)
#	        {
#		    $REC_SKIP = $RECNUM = $R_TOT - 200;
#		    if($DATA_TYPE eq "TLZP")
#		    {
#			    $RECNUM = $RECNUM*2;
#			    seek(IN, $REC_SKIP*600, 0);
#			    $RB = sysread( IN, $REC, 12 );
#		    }
#		    else
#		    {
#			    seek(IN, $REC_SKIP*$ReadLen, 0);
#		    }
#		    $RB = sysread(IN, $REC, $ReadLen);
#		    $RECNUM++;
#	        }
#	    }
#	}

	if($DATA_TYPE eq "TLZP") { $REC = &TIPITtoLZP($REC); }
	
			# unpack REC in to Sync word, Minor Frame Num, and Data bytes
			
	($SYNC, $MFN, @DATA) = unpack( "L1 X C1 C10 ", $REC ) ;


	$MFN = $MFN_BIT1 | $MFN; 

	if(not $FIRST_MFN) { $FIRST_MFN = $MFN; }

	$SYNC = ($SYNC >> 8 ) & 0xffffff ;

	if( $R_ANN_LEN ) {
		$ANFLGS = unpack("x$FRMLEN S1", $REC ) ;     #  grab 12 bit annotation field
		$ANFLGS = ( $ANFLGS >> 4 ) & 0xfff ;
	}
	else { $ANFLGS = 0 ; }

		##################################################################
		#		Check for perfect frame sync pattern 0xfaf320
		##################################################################

	if( $SYNC == 0xfaf320 ) {
		$TOT_PERFSYNC ++ ;	# count perfect sync patterns
		}
		
	else {
		$PRTMSG = "Bad Sync Pattern " ;
		$TOT_IMPRSYNC ++ ;	# count imperfect sync patterns
		$WINDOW_ON ++ ;		# turn on print of bad frames window
		$MAJ_SYNC++ ;		# indicate a SYNC error in this major frame
	}

	if( $ANFLGS == 0 ) {
		$TOT_PERFFLGS ++ ;	# count perfect annotation flags
		}
		
	else {
		$PRTMSG = $PRTMSG . "FLAGS " ;
		$TOT_IMPRFLGS ++ ;	# count imperfect annotation flags
		$WINDOW_ON ++ ;		# turn on print of bad frames window
		$MAJ_FLGS++ ;		# indicate a Flags error in this major frame

		$MASK = 0x001 ;
		for ( $I=12 ; $I > 0 ; $I-- ) {
			if( $ANFLGS & $MASK ) { $ANF_TOT[ $I ]++ ; }
			$MASK = $MASK << 1 ;
		}
	}

		##################################################################
		#			Process perfect frames
		##################################################################


	if( $MFN == $MFN_EXPECT  || $MFN == 0) {	# do good frame processing
	
		$TOT_GOODM ++ ;		# count good min frm seq cases
		$TOT_DELOK  ++ ;
		$DELOK  ++ ;
		$CONSEC_GOOD ++ ;	# count consecutive good recs to turn off window




		##################################################################
		#			Extract more detailed fields only if necessary
		##################################################################

		#if($MFN == 0 || ($RTPB eq "PB" && $FIRST_MFN < ($MFN+100)) || ($RTPB eq "RT" && $FIRST_MFN > ($MFN+100)) )
		#if($MFN == 0 || $MFN % 17 == 0 || $MFN % 25 == 0 || $MFN % 32 == 0)
		#	{ $START=1; }

		if($SAT eq "WIND/POLAR") {

		    if( isPOLAR($FILENAME[$CURRFILE]) )					# POLAR
		    {
		        #if($MFN%17 == 1) { $START = 1; }

			# collect pieces of PB5 time from proper frames
			if( ( $MFN-6 ) %125 == 0 ) { $PB5[0] = $DATA[0];}
			if( ( $MFN-7 ) %125 == 0 ) { $PB5[1] = $DATA[0];}
			if( ( $MFN-11 ) %125 == 0 ) { $PB5[2] = $DATA[0];}
			if( ( $MFN-12 ) %125 == 0 ) { $PB5[3] = $DATA[0];}
			if( ( $MFN-16 ) %125 == 0 ) { $PB5[4] = $DATA[0];}
			if( ( $MFN-17 ) %125 == 0 ) { $PB5[5] = $DATA[0];}

			# Report start time
			if( (not $PB5START) && $RECNUM > 25 && $MFN%125 == 0 ) { $PB5START = PB5_STR(@PB5); }

			# Report major frame count
			if( ($MFN)%25 == 1 ) { $MAJNUM = $DATA[ 0 ];}
			
			# Report major frame time
			if( $RECNUM > 25 && $MFN%125 == 0  &&  $TIME )      { $PB5PRT = PB5_STR( @PB5 ) }

		    }
		    else								# WIND
		    {

		        if($MFN == 0) { $START = 1; }
			#get mode for WIND
		 	if( $START  && $MFN%5 == 0 ) { $MODE = $DATA[0] ; }
		
			# collect pieces of PB5 time from proper frames
		 	if( ( $MFN-4 ) %25 == 0 ) { $PB5[0] = $DATA[0];  $PB5[1] = $DATA[1]; }
		 	if( ( $MFN-9 ) %25 == 0 ) { $PB5[2] = $DATA[0];  $PB5[3] = $DATA[1]; }
		 	if( ( $MFN-14) %25 == 0 ) { $PB5[4] = $DATA[0];  $PB5[5] = $DATA[1]; }

			# get start time
			if( (not $PB5START) && $RECNUM>25 && $MFN%25 > 14) { $PB5START = PB5_STR(@PB5);}
			
			# Report major frame count	
			if( $MFN%25 == 0 ) { $MAJNUM = $DATA[ 1 ] ; }
 	
			# Report major frame time
			if( $TIME && $RECNUM>25 && $MFN%25 >=0)	 { 	
			 	$PB5PRT = PB5_STR( @PB5 ) ; 
			#	printf( "**#%6.1d  %3.1d/%3.1d %2.2x         %s \n", 
			#		 	$RECNUM, $MAJNUM, $MFN, $MODE, $PB5PRT ) ; 
			}
		    }
		}

		elsif( $SAT eq "GEOTAIL") {
			if($MFN == 0) { $START = 1; }

			$PB5[3-($MFN %4)] = $DATA[0];
			if( (not $PB5START) && $RECNUM >= 4 && $MFN%4 == 0) { $PB5START = unpack("L1", pack("C4", @PB5)); }

			if ( ($MFN%4 == 3) && $TIME )	{
				$PB5PRT = unpack("L1", pack("C4", @PB5));
				#printf( "#%6.1d  %3.1d/%3.1d %2.2x        %x\n",
				#	$RECNUM, $MAJNUM, $MFN, $MODE, $PB5PRT );
			}
			if($MFN%32==0) { 
				$MAJNUM = ($DATA[ 6 ] & 0x0f) >> 1;
				$MFN_BIT1 = ($DATA[ 6 ] & 0x01) << 8 ;
				$MFN |= $MFN_BIT1;
				#$MODE = unpack("S1", pack("C2", $DATA[8] , $DATA[9]));
				$MODE = $DATA[5];

				
			}
		}
				
	}		# end of good frame processing
		
		##################################################################
		#			Process questionable frames
		##################################################################

	else {	
	
		if( ($MFN > 249 && $SAT eq "WIND/POLAR") || ($MFN > 511 && $SAT eq "GEOTAIL"))  {

			$PRTMSG = $PRTMSG . "Bad MIF number " ;
			$TOT_BADM ++ ;		# count bad min frm seq cases
			$MAJ_M++ ;		# indicate a frame count error in this major frame
		}

		$DELTAMF = $MFN_EXPECT - $MFN ;

		if( $DELTAMF <= 0 ) {		# wrap into next major frame
			$TOT_DELMAJ ++ ;
			$DELMAJ ++ ;
			$PRTMSG = $PRTMSG . "Frame SKIP - " ;
			}
		
		if( $DELTAMF >  1 ) {		# skip farther down this major frame, maybe
			$TOT_DELMIN ++ ;
			$DELMIN ++ ;
			$PRTMSG = $PRTMSG . "Frame SKIP + " ;
			}

		$WINDOW_ON ++ ;	# turn on print of bad frames window
		
	}		# end of questionable frame processing
	



		##################################################################
		# See if Error window ON and we need to print last good frame
		##################################################################

	if( $WINDOW_ON && $LONG && not $WINDOW_LAST ) {		
		$REJECT_MIN++ ;		# turn on minor frame reject
		$CONSEC_GOOD = 0 ;	# reset consecutive good counter
		if( $WINDOW_REC != $RECNUM_LAST ) {	#don't repeat previous
			print( "\n" ) ;
			if($SAT eq "WIND/POLAR") { $PB5PRT = PB5_STR( @PB5 ) ;}
			else { $PB5PRT = unpack("L1", pack("C4", @PB5)); }
			$FGOOD = "GOOD" ;
			if( $RECNUM != 1 ) { 
				FRM_PRT($REC_LAST, $RECNUM_LAST, $MAJNUM_LAST,
					 $MODE_LAST, $PB5PRT, $FGOOD);
			}
		}
		$WINDOW_LAST ++ ; 	# indicate old frame printed
	}

        if((not $LONG) and (not $OLINE) and (not $HEX)) { goto SKIPAFRM; }

		# now print this frame if Error window ON or if One line print mode

	if( ($WINDOW_ON && $LONG) || $OLINE) 	{
		
		if($SAT eq "WIND/POLAR") { $PB5PRT = PB5_STR( @PB5 ); }
		else { $PB5PRT = unpack("L1", pack("C4", @PB5)); }

    		if( ($RECNUM >= $BEGREC) && ($RECNUM <= $ENDREC) ) 
		{
			FRM_PRT( $REC, $RECNUM, $MAJNUM, $MODE, $PB5PRT, $PRTMSG);
		}
		else
		{
SKIPAFRM:
			if($VERBOSE) {
				$ROW_FORMAT = sprintf($C_ROWS, $ROWS);
				if($DISPLAY eq "") { print "...\n" }
				$DISPLAY = sprintf("%s%s#%6d ", $C_OPEN, $ROW_FORMAT, $RECNUM);
				syswrite(STDERR, $DISPLAY, length($DISPLAY));
			}
		}

		$WINDOW_REC = $RECNUM ; 	# remember last recnum printed
		if( $MFN == 0 ) { print( "" ) }
	}	
		
		##################################################################
		#		Set next expected frame num, and check for end major frame
		##################################################################

	if( $RTPB eq "PB" ) { 
		$MFN_EXPECT = $MFN - 1; 
		if( $MFN_EXPECT == -1 ) {
			if( $SAT eq "WIND/POLAR" ) { $MFN_EXPECT = 249; $END_MAJOR++; }
			else			   { $MFN_EXPECT = 511; $END_MAJOR++; $MFN_BIT1 = 0;}
			if( isPWIW($FILENAME[$CURRFILE]) ) { $MFN_EXPECT = 255; }
		}
	}
	else 	{ 
		$MFN_EXPECT = $MFN + 1; 
		if( $MFN_EXPECT == 256 && isPWIW($FILENAME[$CURRFILE]) ) {  $MFN_EXPECT = 0; $END_MAJOR++;}
		if( $MFN_EXPECT == 250 && $SAT eq "WIND/POLAR" && (not isPWIW($FILENAME[$CURRFILE]))) { $MFN_EXPECT = 0; $END_MAJOR++; }
		if( $MFN_EXPECT == 512 && $SAT eq "GEOTAIL" )    { $MFN_EXPECT = 0; $END_MAJOR++; $MFN_BIT1 = 0;}
	}
	
	if( $END_MAJOR ) {

		if($SAT eq "WIND/POLAR") { $MAX_MNF = 250; }
		else			 { $MAX_MNF = 512; }

		if( $MAJ_SYNC == 0 and $MAJ_MIF == 0 and $DELMAJ == 0 
		 and $DELMIN == 0 and $DELOK == $MAX_MNF ) {	#MAJOR frame OK

			$TOT_MAJOK ++ ;
			$PRTMSG = "MAJOR frame OK" ;
			if($SAT eq "WIND/POLAR") { $PB5PRT = PB5_STR( @PB5TIME_LAST ); }
			else { $PB5PRT = unpack("L1", pack("C4", @PB5TIME_LAST)); }
		}
		else {		# MAJOR frame has some BAD spots

			$TOT_MAJBAD ++ ;
			$PRTMSG = "MAJOR frame ERRORS - Sync $MAJ_SYNC" ;
			$PRTMSG = $PRTMSG . "  Delta <$DELMAJ >$DELMIN, OK=$DELOK\n"  ;
			if($SAT eq "WIND/POLAR") { $PB5PRT = PB5_STR( @PB5TIME_LAST ); }
			else { $PB5PRT = unpack("L1", pack("C4", @PB5TIME_LAST)); }
		}


		$MAJ_SYNC = $MAJ_MIF = $DELMAJ = $DELMIN = $DELOK = 0 ;
		if($RTPB eq "PB" && $MAJNUM != -999)    { $MAJNUM -- ; }
		elsif($RTPB eq "RT" && $MAJNUM != -999) { $MAJNUM ++; }

		if( $MAJNUM < 0 && $MAJNUM > -999) { 
			$MAJNUM = 255 ; 
			if($SAT eq "GEOTAIL") {$MAJNUM = 7; $MFN_BIT1 = 0x100;}
		}
	
		$END_MAJOR = 0 ;	# clear end of major frame flag	
	}	

		# Clear PRTMSG and see if we are back in good data and turn off window

	$PRTMSG = "" ;	
	if( $CONSEC_GOOD >= 1 ) { $WINDOW_ON = 0 ; $WINDOW_LAST = 0}

	$REC_LAST = $REC;		#save last frame for dumping if we detect problems
	$RECNUM_LAST  = $RECNUM ;
	$MAJNUM_LAST = $MAJNUM ;
	$MODE_LAST    = $MODE    ;
	@PB5TIME_LAST =  @PB5 ; 

NEXT_FRM:
	$REJECT_MIN = 0 ;	# clear minor frame reject flag
	$LOCSTRT = $LOC ;

	$LOC += $ReadLen ;	   #keep running byte count

	if($DATA_TYPE eq "TLZP") {
		if($NUM_FRM_READ % $FRM_IN_BLK{$SAT} == 0) 
			{ $RB = sysread(IN, $REC, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); }
	}

	$RB = sysread( IN, $REC, $ReadLen ) ;

	$NUM_FRM_READ++;
	
}

print( "\n" ) ;
$PRTMSG = "LAST minor frame\n" ;
if($SAT eq "GEOTAIL") { 
	$PB5PRT = unpack("L1", pack("C4", @PB5)); 
	$PB5END = unpack("L1", pack("C4", @PB5TIME_LAST)); 
}
else {
	$PB5PRT = PB5_STR( @PB5 ) ;
	$PB5END = PB5_STR(@PB5 ) ;
}
FRM_PRT( $REC_LAST, $RECNUM_LAST, $MAJNUM_LAST, $MODE_LAST, $PB5PRT, $PRTMSG ) ;


print( "\n" ) ;
print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ]\n" ) ;
print( "\n" ) ;
if($SAT eq "GEOTAIL") { 
	printf( " Start TTCD TIME = %X    End TTCD TIME = %X\n", $PB5START, $PB5END ) ; 
}
else { print( " Start PB5TIME = $PB5START     End PB5TIME = $PB5END\n" ) ; }
print( "\n" ) ;
print( "  Total frames       = $RECNUM\n" ) ;
print( "  Total Perfect Sync = $TOT_PERFSYNC     Bad Sync  = $TOT_IMPRSYNC\n" ) ;
print( "  Total NO Flags Set = $TOT_PERFFLGS     Flags Set = $TOT_IMPRFLGS\n" ) ;
$TOT_DEL = $TOT_DELMAJ + $TOT_DELMIN ;
print( "  Total Seq skips OK = $TOT_DELOK     SKIP > 1  = $TOT_DEL\n" ) ;
print( "\n" ) ;
print( "  Total PERFECT MAJOR frames = $TOT_MAJOK\n" ) ;
print( "  Total ERRORED MAJOR frames = $TOT_MAJBAD\n" ) ;
print( "\n" ) ;
if( $R_ANN_LEN ) {
	for ( $I=1 ; $I < 13 ; $I++ ) {
		$IPLUS4 = $I + 4 ;
		printf( " Total F%2.1d = %6.0d \n", $IPLUS4, $ANF_TOT[ $I ] ) ;
	}
}
print( "\n" ) ;

}		# end of frame processing routine,  return


#########################################################################
#       Subroutine to print a frame formatted, one line header
#       $_[0] -	$REC    - frame string
#       $_[1] - $RECNUM - sequential record count to identify frame
#	$_[2] - $MAJNUM - MAJOR frame number that goes with frame
#	$_[3] - $MODE   - MODE that goes with frame
#	$_[4] - $PB5TIME- string containg PB5 time for this major frame
#       $_[5] - $PRTMSG - text string to print at end of line
#
#       FRM_PRT   ( REC, RECNUM, MAJNUM, MODE, PB5TIME, PRTMSG  ) ;
#
#       Returns  nothing special 
#
#######################################################################

sub FRM_PRT  {
	$PB5TIME_CPY = $_[4];
	$MAJNUM_CPY = $_[2];
	
	if( $TITLE_DONE % 80 == 0 ) {
	    if( not $FIELD ) { print "\n  Seq.   Maj/Min Mode SYNC    --------$TIME_TITLE-------- FLG  Ground Time\n" ; }
	    else             { print "\n  Seq.   Maj/Min Mode SYNC   Field ---$TIME_TITLE-------- FLG  Ground Time\n" ; }
	}
	$TITLE_DONE ++ ;

	@R = unpack( "C8" , $_[0] ) ;

	if($LZPSCAN || $SAT eq "WIND/POLAR") { $HM = $R[3]; }		# get minor frame count from raw data   
	else		         { $HM = $MFN; }		# get minor frame count from calculation 
	#$HM = $MFN;

	if( $R_ANN_LEN ) { 	# if annotation field, extract it
		$UFRMLEN = $R_DAT_LEN + $R_RS_LEN ;
		$ANN = substr( $_[0] , $UFRMLEN, 8 ) ;
		ANN_SPLIT ( $ANN ) ;
	}

	if($LZPSCAN)
	{
	        if ($SAT eq "WIND/POLAR")
	        {
		    if( isPOLAR($FILENAME[$CURRFILE]) )					# POLAR
		    {
			# last pieces of PB5 time was collected ?
			if( not (($HM-17) % 125 == 0) ) { $PB5TIME_CPY = ""; }
			if( isPWIW($FILENAME[$CURRFILE]) ) 
			{ 
				$PB5TIME_CPY = ""; 
				if( not ($_[1] % 2048 == 1) ) { $MAJNUM_CPY = ""; }
			}
			else {
		        	if( not ($HM % 25 == 0) ) { $MAJNUM_CPY = ""; }
			}
                    }
		    else								# WIND
		    {
			# last pieces of PB5 time was collected ?
			if( not (($HM-14) % 25 == 0) ) { $PB5TIME_CPY = ""; }
		        if( not ($HM % 25 == 0) ) { $MAJNUM_CPY = ""; }
		    }
		}
		else
		{
		    if( not ($HM % 4 == 3) ) { $PB5TIME_CPY = ""; }
		    else { $PB5TIME_CPY = sprintf("%u", $_[4]); }
		    if( not ($HM % 32 == 0) ) { $MAJNUM_CPY = ""; }
		}
	}

	if( not $FIELD ) { 
	    if( ($SAT eq "GEOTAIL") or (($SAT eq "WIND/POLAR") and (not isPOLAR($FILENAME[$CURRFILE]))) ) {
		printf( "#%6.1u  %3.3s/%3.1u %2.2x %2.2x%2.2x%2.2x %2.2x %2.2x   %20.20s", 
			$_[1], $MAJNUM_CPY, $HM, $_[3], $R[0], $R[1], $R[2], $R[3], $R[4],  $PB5TIME_CPY ) ; 
	    }
	    else {
		printf( "#%6.1u  %3.3s/%3.1u %2.2x %2.2x%2.2x%2.2x %2.2x %2.2x%2.2x %20.20s", 
			$_[1], $MAJNUM_CPY, $HM, $_[3], $R[0], $R[1], $R[2], $R[3], $R[4], $R[5], $PB5TIME_CPY ) ; 
	    }
	}
	
	else {
	    $FLD0 = $FIELD - 1 ;
	    $FLD_EXT = unpack( "x$FLD0 C1", $_[0] ) ;
	    printf( "#%6.1d  %3.1d/%3.1d %2.2x %2.2x%2.2x%2.2x %2.2x [%2.2x] %20.20s", 
			$_[1], $_[2], $HM, $_[3], $R[0], $R[1], $R[2], $R[3], $FLD_EXT, $PB5TIME_CPY ) ; 
	}

	printf( " %3.1x  ", $FLG ) ;
	#if($DATA_TYPE eq "TLZP") { printf( "%3.1d %5.1u %4.1d " , $DOY, $MSOD, $USOMS ) ; }
	#else {TIME_PRT( $DOY, $MSOD, $USOMS, $TIME); }

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME); 

#	if( $TIME ) {		# convert time field to HH:MM:SS.ms format
#
#		$HR = int( $MSOD/3600000 ) ;
#		$MN = int( ( $MSOD - $HR * 3600000 ) / 60000 ) ;
#		$SC = int( ( $MSOD - $HR * 3600000 - $MN * 60000 ) / 1000 ) ;
#		$MS = $MSOD - ($HR * 3600000) - ($MN * 60000) - ($SC * 1000) ;
#
#		printf( " %3.1x  %3.3d-%2.2d:%2.2d:%2.2d.%3.3d %3.3d", $FLG, $DOY, $HR, $MN, $SC, $MS, $USOMS ) ;
#		}
#		else {
#		printf( " %3.1x  %3.3d-%8.8d %3.3d", $FLG, $DOY, $MSOD, $USOMS ) ;
#	}
	
	if( $DELTA ) {
		$DL_MSOD = $MSOD - $PREV_MSOD ;
		$DL_USOMS = $USOMS - $PREV_USOMS ;
		if( $DL_USOMS < 0 ) { $DL_USOMS += 1000 ; $DL_MSOD -= 1 ; }
		if( $PREV_MSOD ) { printf( " del=%8.1d %3.3d", $DL_MSOD, $DL_USOMS ) ; }
		$PREV_MSOD = $MSOD ;
		$PREV_USOMS = $USOMS ;
	}

	printf( " %s\n", $_[5] ) ;

	if( $HEX ) { 
		printf( "\n" ) ;
		HEXPRT( $_[0], $R_DAT_LEN ) ; 
		HEXPRT( $ANN,  $R_ANN_LEN ) ; 
		printf( "\n" ) ;
	}
}		# return


#########################################################################
#       Subroutine to break down a PB5 time field
#		$_[0]  - first byte of 6 byte PB5 time field 
#		$_[1]  - second byte of 6 byte PB5 time field 
# 		...
#		$_[5]  - sixth byte of 6 byte PB5 time field 
#
#       PB5_STR   (  ) ;
#
#       Returns  string of time field in ASCII
#
#######################################################################

sub PB5_STR  {

   local ($JDOY5, $ADJUST, $YEAR5, $CURR_YEAR); 

   $DOY5 = $SOD5 = $MSOD5 = $FMSOD5 = 0;

#   $CURR_YEAR = 1900+$STGMT[5];

#printf( "\n%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x \n", @_ ) ;

	$DOY5 = (( $_[0] << 7 )  |  ( $_[1] >> 1 )  ) & 0x3fff ;
	$SOD5 = (( $_[1] & 0x01) << 16 )  |  ( $_[2] << 8 ) | ( $_[3] )  ;
	$MSOD5= (( $_[4] << 8 ) | $_[5] ) >> 6 ;
	$FMSOD5= ( $_[5] ) & 0x3f ;

#printf( "\n%2.2x %2.2x %2.2x %2.2x \n", $DOY5,$SOD5,$MSOD5,$FMSOD5 ) ;

# JD since 1904
	$JDOY5 = &YMDtoJD(19951010) + $DOY5;
	$YEAR5 = int( &JDtoYMD($JDOY5) / 10000 );
	
	#if($YEAR5 <= $CURR_YEAR) { $ADJUST = 1; }
	#else 			 { $ADJUST = 0; }

	$ADJUST = 1;

# Days of year since Jan 1st $YEAR5
	if($DOY5 >= 0) {
		$DOY5 = $JDOY5 - &YMDtoJD( $YEAR5*10000+101 ) + $ADJUST;
		if($DOY5 < 0) {$DOY5 = 0; }
	}
	else { $DOY5 = 0; }

	if($TIME) {
		$tempUTC = &FP2str(&ydmu2UTC($YEAR5, $DOY5, $SOD5*1000+$MSOD5, $FMSOD5));
		$STR = sprintf("%03u %02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 4, 3)),
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));

		if($PB52STR) { $STR = sprintf("%d ", substr($tempUTC, 0, 4)) . $STR; }

		#$HR = int( $SOD5/3600 ) ;
		#$MN = int( ( $SOD5 - $HR * 3600 ) / 60 ) ;
		#$SC = ( $SOD5 - $HR * 3600 - $MN * 60 ) ;
		#$STR = sprintf( "%3.3u %2.2u:%2.2u:%2.2u:%3.3u.%3.3u" , $DOY5, $HR, $MN, $SC, $MSOD5, $FMSOD5 ) ;
	} else {
		$STR = sprintf( "%3.3u %8.8u %3.3u.%2.2u" , $DOY5, $SOD5, $MSOD5, $FMSOD5 ) ;
	}

	return $STR ;
}		# return


###############################################################################
#
#
#	Format and print the time value (DOY, MSOD,     USOMS) passed in                  #
#	if $HHFLG is     set,    do it in HH:MM:SS format instead of     MSOD format       #
#
#
###############################################################################

sub TIME_PRT {

        my ($DOY, $MSOD, $USOMS, $HHFLG ) = @_;
        my( $HR, $MN, $SC, $MS ) ;

        if( $HHFLG ) {           # convert time field to DOY-HH:MM:SS.mmm uuu format

                $HR = int( $MSOD/3600000 ) ;
                $MN = int( ( $MSOD - $HR * 3600000 ) / 60000 ) ;
                $SC = int( ( $MSOD - $HR * 3600000 - $MN * 60000 ) / 1000 ) ;
#                $MS = $MSOD - ($HR * 3600000) - ($MN * 60000) - ($SC * 1000) ;
		$MS = $MSOD % 1000 ;

                printf( "%3.3u-%2.2u:%2.2u:%2.2u-%3.3u %3.3u", $DOY, $HR, $MN, $SC, $MS, $USOMS ) ;
                }
        else {
		$SC = int( $MSOD / 1000 ) ;
		$MS = $MSOD % 1000 ;
		$SC_COMMAS = commas( $SC ) ;
                # printf( "%3.3u %6.6s.%3.3u %3.3u", $DOY, $SC_COMMAS, $MS, $USOMS ) ;
                printf( "%3.3u %8.8u %3.3u.%2.2u", $DOY, $SC, $MS, $USOMS ) ;
        }
}



#########################################################################
#		Do BLK processing until end of file
#
#######################################################################

sub BLK_SCAN{

$SEQ_SKIP = $SEQ_OK = 0 ;
$SYNC_BAD = $SYNC_OK = 0 ;
$RECNUM_LAST = 0 ;
$WINDOW_REC = 1 ;

print "\n" ;

while( $RB ) {
	
	$RECNUM++;

	@R = unpack( "C24", $REC ) ;	# unpack first 24 bytes of block

	$PRTMSG = "" ;

	if( $RECNUM == 1 ) {	# initialize header check bytes
		$RECSRC_LAST  = $R[3] ;
		$RECDST_LAST  = $R[4] ;
		$RECBFC_LAST  = $R[5] ;
		$RECSCID_LAST  = $R[6] ;
		$RECDSID_LAST  = $R[7] ;
		$RECTYPE_LAST  = $R[8] ;

	}

	$SRC_TOT[ $R[3] ]++ ;	# count occurrences of each source code
	$DST_TOT[ $R[4] ]++ ;	# count occurrences of each dest code
	$BFC_TOT[ $R[5] ]++ ;	# count occurrences of each BFC code
	$SCID_TOT[ $R[6] ]++ ;	# count occurrences of each SCID code
	$DSID_TOT[ $R[7] ]++ ;	# count occurrences of each DSID code
	$TYPE_TOT[ $R[8] ]++ ;	# count occurrences of each TYPE code

	if( $BLK_TYPE eq "DDPS" ) {
		$SEQ = ( $R[9] & 0xf ) * 65536 + $R[10] * 256 + $R[11] ;
	}
	else { $SEQ = $R[9] ; }

	if( $SEQ != $EXPSEQ ) {
		$SEQ_SKIP ++ ;
		$WINDOW_ON++ ;
		$PRTMSG = $PRTMSG . "Blk_Seq_Skip " ;
		}
	else { $SEQ_OK ++ ; $CONSEC_GOOD++ }	# bump flag toossibly turn off window

	if( $R[3] != $RECSRC_LAST ) { $X_SRC++; $PRTMSG=$PRTMSG . "SRC-Diff " }
	if( $R[4] != $RECDST_LAST ) { $X_DST++; $PRTMSG=$PRTMSG . "DST-Diff " }
	if( $R[5] != $RECBFC_LAST ) { $X_BFC++; $PRTMSG=$PRTMSG . "BFC-Diff " }
	if( $R[6] != $RECSCID_LAST ) { $X_SCID++; $PRTMSG=$PRTMSG . "SCID-Diff " }
	if( $R[7] != $RECDSID_LAST ) { $X_DSID++; $PRTMSG=$PRTMSG . "DSID-Diff " }
	if( $R[8] != $RECTYPE_LAST ) { $X_TYPE++; $PRTMSG=$PRTMSG . "TYPE-Diff " }

	if( $PRTMSG ) { $WINDOW_ON++ }
		else { $X_HDROK++ ; }

	$DLEN = $R[10] * 256 + $R[11] ;	# data length in bits
		
	if( $DLEN == 0) {
		$LEN_ZERO ++ ;
		$WINDOW_ON++ ;
		$PRTMSG = $PRTMSG . "ZERO data len " ;
	}
		
	if( $DLEN > 4592) {
		$LEN_OVER ++ ;
		$WINDOW_ON++ ;
		$PRTMSG = $PRTMSG . "HUGE data len " ;
	}
		
	if( $DLEN >= 1  && $DLEN < 4592 ) { $LEN_PARTIAL ++ ; }
		
	if( $DLEN == 4592 ) { $LEN_FULL ++ ; }

		# now check for TIPIT LZP format and do special handling

	if( $DATA_TYPE eq "TLZP" ) {
		$FPB = 2 ;	# 2 frames per block for WIND/POLAR
		$FLEN = 256 ;
		$TLZP_PRT = "" ;
		if( $SAT eq "GEOTAIL" ) { $FPB = 4 ; $FLEN = 128 ; }
		$FSLOC = 9 + $FLEN ;
		for( $F=0; $F<$FPB ; $F++ ) {
			if( $RTPB eq "RT" ) {
				$FSNUM  = substr( $REC, $FSLOC - $FLEN + 3 , 1 ) ;
				$FNUM = unpack( "C1", $FSNUM ) ;
			}
			else {	# reverse frame number if needed
				$FSRNUM  = substr( $REC, $FSLOC - 1 , 1 ) ;
				$FRBNUM = unpack( "B8", $FSRNUM ) ;
				$FBNUM = reverse(  $FRBNUM ) ;
				$FSNUM = pack( "B8", $FBNUM ) ;
				$FNUM = unpack( "C1", $FSNUM ) ;
			}

			$FSSYNC = substr( $REC, $FSLOC, 4 )  ;
			$FSYNC = unpack( "L1", $FSSYNC ) >> 8 & 0xffffff ;
			$FANN  = substr( $REC, $FSLOC+3, 8 ) ;
			ANN_SPLIT( $FANN ) ;	# split up annotation field
		
			if( $FLG != 0) {
				$TOT_IMPRFLGS ++ ;
				$WINDOW_ON++ ;
				$PRTMSG = $PRTMSG . "FLAGS " ;
				}
			else { $TOT_PERFFLGS++ ; }


			# now print this block if Error window ON or if One line print mode

			if( ($WINDOW_ON && $LONG) || $OLINE) 	{
				$TLZP_PRT = $TLZP_PRT . 
			sprintf( "   \t0x%2.2x (%3.1d)  \t%6.6x  \t%3.1x \t%3.1d-%5.1d %4.1d\n" , 
					$FNUM, $FNUM, $FSYNC, $FLG, $DOY, $MSOD, $USOMS ) ;
			}
			$FSLOC += $FLEN + 8 ;
		}
	}

	if( ($RECNUM > $ENDREC) || ((not $LONG) and (not $OLINE) and (not $HEX))) { goto SKIPABLK; }

		##################################################################
		# See if Error window ON and we need to print last good frame
		##################################################################

	if( $WINDOW_ON && $LONG && not $WINDOW_LAST ) {		
		$CONSEC_GOOD = 0 ;	# reset consecutive good counter
		if( $WINDOW_REC != $RECNUM_LAST ) {	#don't repeat previous
			print( "\n" ) ;
			$FGOOD = "GOOD" ;
			if( $RECNUM != 1 ) { BLK_PRT($REC_LAST, $RECNUM_LAST, $FGOOD);}
		}
		$WINDOW_LAST ++ ; 	# indicate old block printed
	}

		# now print this block if Error window ON or if One line print mode

	if( ($WINDOW_ON && $LONG) || $OLINE) 	{
		$GARBAGE_FOUND = 0;
		if($GARBAGE) {
			$GARBAGE_FOUND = Garbage_Loc($REC,  70) && Garbage_Loc($REC, 170) &&
    			    		 Garbage_Loc($REC, 270) && Garbage_Loc($REC, 370) &&
    			    		 Garbage_Loc($REC, 470) && Garbage_Loc($REC, 570);
		}
		if(! $GARBAGE_FOUND) {
    			if( ($RECNUM >= $BEGREC) && ($RECNUM <= $ENDREC) ) 
			{
				BLK_PRT( $REC, $RECNUM, $PRTMSG);
			}
			else
			{
SKIPABLK:
				if($VERBOSE) {
					$ROW_FORMAT = sprintf($C_ROWS, $ROWS);
					if($DISPLAY eq "") { print "...\n" }
					$DISPLAY = sprintf("%s%s#%6d ", $C_OPEN, $ROW_FORMAT, $RECNUM);
					syswrite(STDERR, $DISPLAY, length($DISPLAY));
				}
			}

			#BLK_PRT( $REC, $RECNUM, $PRTMSG);
			if( $TLZP_PRT ) { print( "$TLZP_PRT\n" ) }
		}
		$WINDOW_REC = $RECNUM ;		# remember last rec printed
	}	
		


	if( $BLK_TYPE eq "DDPS" ) {
		$EXPSEQ = ( $SEQ + 1 ) % 1048576  ;	# expected seq = current + 1 mod 256
	}
	else {
		$EXPSEQ = ( $SEQ + 1 ) % 256  ;	# expected seq = current + 1 mod 256
	}

		# Clear PRTMSG and see if we are back in good data and turn off window

	$PRTMSG = "" ;	
	if( $CONSEC_GOOD >= 1 ) { $WINDOW_ON = 0 ; $WINDOW_LAST = 0}

	$REC_LAST = $REC;		#save last block for dumping if we detect problems
	$RECNUM_LAST  = $RECNUM ;

	$RECSRC_LAST = $R[3] ;
	$RECDST_LAST = $R[4] ;
	$RECBFC_LAST = $R[5] ;
	$RECSCID_LAST = $R[6] ;
	$RECDSID_LAST = $R[7] ;
	$RECTYPE_LAST = $R[8] ;
	
	$RB = sysread( IN, $REC, $ReadLen) ;

}



print( "\n" ) ;
print( "Summary of file $FILENAME[ $CURRFILE ]\n" ) ;
print( "\n" ) ;

BLK_PRT( $B[0], 1, "First Block");
BLK_PRT( $REC_LAST, $RECNUM_LAST, "Last Block");

print( "\n" ) ;
printf( " Total blocks       %7.1d\n", $RECNUM ) ;
printf( " Block sequence OK  %7.1d     seq SKIP %7.1d\n", $SEQ_OK, $SEQ_SKIP ) ;
printf( " Block header   OK  %7.1d     Src  DIFF%7.1d  Dest.-DIFF%7.1d  BFC__DIFF%7.1d\n", $X_HDROK, $X_SRC, $X_DST, $X_BFC ) ;
printf( "                                SCID DIFF%7.1d  DSID -DIFF%7.1d  Type_DIFF%7.1d\n", $X_SCID, $X_DSID, $X_TYPE ) ;
printf( " Block datalen FULL %7.1d     PARTIAL  %7.1d  ZERO      %7.1d\n",
	 $LEN_FULL, $LEN_PARTIAL, $LEN_ZERO ) ;
print( "\n" ) ;

if( $X_SRC ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  Source Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $SRC_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x  %s %s\n", $SRC_TOT[$I],
			$I, $I, $I, $SRC_DESC[$I], $SRC_ANT[$I] ) ;
	}
}
}

if( $X_DST ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  Destination Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $DST_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x  %s %s\n", $DST_TOT[$I],
			$I, $I, $I, $SRC_DESC[$I], $SRC_ANT[$I] ) ;
	}
}
}

if( $X_BFC ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  BFC    Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $BFC_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x \n", $BFC_TOT[$I],
			$I, $I, $I ) ;
	}
}
}

if( $X_SCID ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  Spacecraft ID Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $SCID_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x  %s\n", $SCID_TOT[$I],
			$I, $I, $I, $SCID[$I] ) ;
	}
}
}

if( $X_DSID ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  Data Stream ID Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $DSID_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x  %8s %2s %1s %s\n", $DSID_TOT[$I],
			$I, $I, $I, $PDF_SAT[$I], $PDF_RTPB[$I], $PDF[$I], $PDF_DESC[$I] ) ;
	}
}
}

if( $X_TYPE ) {	# if any code changes occurred, then print list

printf( "\n     #  Oct  Dec  Hex  Type      Code Occurrences\n" ) ;
for( $I=0; $I<256 ; $I++ ) {
	if( $TYPE_TOT[ $I ] > 0 ) {
		printf( "%6.1d  %3.1o  %3.1d  %3.1x \n", $TYPE_TOT[$I],
			$I, $I, $I ) ;
	}
}
}

print( "\n" ) ;
print( "\n" ) ;

}



#########################################################################
#       Subroutine to print a block formatted, one line header
#       $_[0] -	$REC    - block string
#       $_[1] - $RECNUM - sequential record count to identify frame
#       $_[2] - $PRTMSG - text string to print at end of line
#
#       BLK_PRT   ( REC, RECNUM, PRTMSG  ) ;
#
#       Returns  nothing special 
#
#      +--------+--------+ 
#    1 | Nascom 4800 BB  | 0 , 1	Nascom Sync ( first 16 bits)
#      +--------+--------+ 
#    2 | Sync   | Source | 2 , 3	Sync ( 8 )  ,  Source code
#      +--------+---+----+
#    3 | Dest   |Seq| BFC| 4 , 5	Destination ,  Seq(3)  BFC(5)
#      +--------+---+----+
#    4 | SCID   |  DSID  | 6 , 7	Spacecraft ID, Data Stream ID
#      +--------+--------+
#    5 | Type   | Blk Cnt| 8 , 9	Data Type   ,  Block count
#      +--------+--------+
#    6 |xyz  Blk Length  |10 ,11	Flgs(3)   Block len. bits (13)
#      +--------+--------+
#    7 |ab DOY(9) MSOD(5)|12 ,13	Flags(2)  DOY(9) First milliseconds of day (5)
#      +--------+--------+
#    8 |   MSOD ( 16 )   |14 ,15	  more milliseconds of day (16)
#      +--------+--------+
#    9 |MSOD(6) USOMS(10)|16 ,17	last MSOD(6)  Microseconds of millisecond (10)
#      +--------+--------+
#      |        |        |
#
#######################################################################

sub BLK_PRT  {
	if( not $TITLE_DONE ) {
		if( $TIME ) {
		print "\n Recnum  Seq   Sync SrcDstBFC SC DSTyp Len. DOY-HH:MM:SS.ms  us\n" ; 
			}
			else {
		print "\n Recnum  Seq   Sync SrcDstBFC SC DSTyp Len. DOY-Second.ms  us\n" ; 
		}

		$TITLE_DONE ++ ;
	}

	@R = unpack( "C24", $_[0] ) ;	# unpack first 24 bytes of block

	if( $BLK_TYPE eq "DGIB" ) {
		$BSEQ = $R[9] ;			# get block sequence count
		$BLEN = $R[10] * 256 + $R[11] ;	# data length in bits
		$BBLEN = $BLEN / 8 ;		# data length in bytes

		$DOY = (( $R[12] & 0x3f) << 3 ) | (( $R[13] >> 5 ) & 0x7 )  ;
		$MSOD = (($R[13] & 0x1f ) << 22) | ( $R[14] << 14) | ( $R[15] << 6 ) | (( $R[16] >> 2 ) & 0x3f) ;
		$USOMS = ($R[16] & 0x03 ) << 8 | $R[17]  ;
	}

	if( $BLK_TYPE eq "DDPS" ) {
		$BSEQ = $R[10] * 256 + $R[11] ;
		$BBLEN = 585 ;
		$DOY = 0 ;
		$MSOD = 0 ;
		$USOMS = 0 ;
	}

	printf( "#%6.1u  %3.1u  %2.2x%2.2x%2.2x %2.2x %2.2x %2.2x",
		$_[1], $BSEQ, $R[0],$R[1],$R[2], $R[3], $R[4], $R[5] ) ;

       	printf( " %2.2x %2.2x %2.2x %4.3d ",
               	$R[6],$R[7],$R[8], $BBLEN ) ;

	TIME_PRT( $DOY, $MSOD, $USOMS, $TIME);

#	if( $TIME ) {	# see if time desired in HH:MM:SS format
#
#		$HR = int( $MSOD/3600000 ) ;
#		$MN = int( ( $MSOD - $HR * 3600000 ) / 60000 ) ;
#		$SC = int( ( $MSOD - $HR * 3600000 - $MN * 60000 ) / 1000 ) ;
#		$MS = $MSOD - ($HR * 3600000) - ($MN * 60000) - ($SC * 1000) ;
#
#        	printf( " %2.2x %2.2x %2.2x %4.3d %3.3d-%2.2d:%2.2d:%2.2d.%3.3d%3.3d",
#                	$R[6],$R[7],$R[8], $BBLEN, $DOY, $HR, $MN, $SC, $MS, $USOMS ) ;
#	}
#
#	else {
#		
#		printf( " %2.2x %2.2x %2.2x %4.3u %3.3u-%8.1u.%3.3u",
#			$R[6],$R[7],$R[8], $BBLEN, $DOY, $MSOD, $USOMS ) ;
#	}

	if( $DELTA ) {
		$DL_MSOD = $MSOD - $PREV_MSOD ;
		$DL_USOMS = $USOMS - $PREV_USOMS ;
		if( $DL_USOMS < 0 ) { $DL_USOMS += 1000 ; $DL_MSOD -= 1 ; }
		if( $PREV_MSOD ) { printf( " del=%8.1d %3.3d", $DL_MSOD, $DL_USOMS ) ; }
		$PREV_MSOD = $MSOD ;
		$PREV_USOMS = $USOMS ;
	}

	printf( " %s\n", $_[2] ) ;

		# if they asked for hex dump (-x), do it now

	if( $HEX ) {
		printf( "\n" ) ;
		printf( "Source      = %2.2x %3.3o %3.3d %s %s\n", $R[3], $R[3], $R[3], 
			$SRC_DESC[ $R[3] ], $SRC_ANT[ $R[3] ] ) ;
		printf( "Destination = %2.2x %3.3o %3.3d %s %s\n", $R[4], $R[4], $R[4], 
			$SRC_DESC[ $R[4] ], $SRC_ANT[ $R[4] ] ) ;
		printf( "S/C ID      = %2.2x %3.3o %3.3d %s\n", $R[6], $R[6], $R[6], 
			$SCID[ $R[6] ] ) ;
		printf( "Data Str ID = %2.2x %3.3o %3.3d PDF=%s %s\n", $R[7], $R[7], $R[7], 
			$PDF[ $R[7] ], $PDF_DESC[ $R[7] ] ) ;
	}

	if( $HEX ) { 
		printf( "\n" ) ;
		HEXPRT(  $_[0], $R_DAT_LEN ) ; 
		printf( "\n" ) ;
	}
}
#########################################################################
#       Subroutine to split annotation field passed to it
#               $_[0]  - 8 byte annotation field
#
#       ANN_SPLIT   ( $REC  ) ;
#
#	Returns : $FLG - 12 bit flag string
#		  $DOY - day of year
#		  $MSOD - milliseconds of day
#		  $USOMS - micro-seconds of millisecond
#
#########################################################################

sub ANN_SPLIT {
	$FLG = $DOY = $MSOD = $USOMS = 0;
	@T = unpack( "S4" , $_[0] ) ;
	$FLG = ($T[0] >> 4 ) & 0x0fff ;
	$DOY = ( ( ($T[0] & 0xf ) << 5) | ( ($T[1] & 0xf800) >> 11 ) ) ;
	$MSOD = ( $T[1] & 0x07ff ) * 65536 + $T[2] ;
	$USOMS = $T[3] ;
}

#########################################################################
#       Subroutine to do hex dump of record passed to it
#		$_[0]  - string of $_[1] bytes to dump
#
#       HEXPRT   ( $REC, $RECLEN ) ;
#
#       Returns  nothing special
#
#######################################################################

sub HEXPRT  {
	local($I);

	$LEN = $_[1] ;
	$LONGS = int( $LEN / 4 );		# see how many long words in record
	$ODDS  = $LEN % 4 ;		# see how many bytes left over

	$FULLLONG = int( $LONGS / 8 ) * 8 ;	# see how many full lines to print
	$ODDLONGS = $LONGS - $FULLLONG ;	# see num. long words on last line
	
	if( $ZYNC ) {
		$ZYNC_STR = "" ;
		$ZYNC_PSTR = "" ;
		@ZY = unpack( "C$LEN", $_[0] ) ;
		for( $ZZ = 0; $ZZ < $LEN; $ZZ++ ) {
			for( $ZI = 0; $ZI<8 ; $ZI++ ) {
				if( $ZY[$ZZ] == $XZ1[$ZI] ) { 	# see if first byte match
					if( $ZY[$ZZ+1] == $XZ2[$ZI] ) {	# check second byte
					$ZYNC_STR = $ZYNC_STR . sprintf( "%4.1d ", $ZZ ) ;
					$ZYNC_PSTR = $ZYNC_PSTR . sprintf( "%4.4x ", $XZ[$ZI] ) ;
					}
				}
			}
		}
		if( length( $ZYNC_STR) ) {
			print( "Sync pattern $ZYNC_PSTR\n" ) ;
			print( "at locations $ZYNC_STR\n\n" ) ;
		}
	}
	
	if( $ODDS ) { $ULONGS = $LONGS + 1 ; }	# unpack extra word if odd bytes on end
		else { $ULONGS = $LONGS ; }

	@L   = unpack( "N$ULONGS", $_[0] ) ;		# unpack all longs	
	
	if( $ODDS ) { 
		$OD[0] = ( $L[ $LONGS ] >> 24 ) & 0xff ; 
		$OD[1] = ( $L[ $LONGS ] >> 16 ) & 0xff ; 
		$OD[2] = ( $L[ $LONGS ] >>  8 ) & 0xff ; 
	}

	for ( $R=0 ; $R<$FULLLONG ; $R+=8 ) {	# print full lines (8 words each)
	
		printf( "  %4.1d  %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x\n" ,
			$R*4, $L[$R+0], $L[$R+1], $L[$R+2], $L[$R+3],  
			      $L[$R+4], $L[$R+5], $L[$R+6], $L[$R+7] ) ;
	}
	
	if( $ODDLONGS == 0 and $ODDS ) {	# do very short line of last bytes
		printf( "  %4.1d  ", $R*4 ) ;	# print location
		
		for ( $I=0 ; $I<$ODDS ; $I+=1 ) {
			printf( "%2.2x" , $OD[$I]  ) ;
		}
	}		

	if( $ODDLONGS) { 	# print last partial line
		printf( "  %4.1d  ", $R*4 ) ;	# print location

		for ( $I=0 ; $I<$ODDLONGS ; $I++ ) {
			printf( "%8.8x " , $L[$R+$I]  ) ;
		}

		if( $ODDS ) {	# print final bytes on line
			for ( $I=0 ; $I<$ODDS ; $I+=1 ) {
				printf( "%2.2x" , $OD[$I]  ) ;
			}
		}

	}
printf( "\n" ) ;

}

sub scan_usage{ 
	if( not $CODES ) {

        print "USAGE:\n  lzpscan  [options] filename  \n";
	print "      \n" ;
	print "              - no options, scan file, produce summary report\n" ;
        print "         -a   - print all blks/frms (one line format, MJF and MNF level for product)\n" ;
        print "         -b # - begining record number to process\n" ;
        print "         -c   - print out table of src/dst, DSID codes\n" ;
        print "         -d   - print delta time for each block/frame printed\n" ;
        print "         -e # - ending frame record to process\n" ;
        print "         -f # - field byte number to extract (frames)\n" ;
	print "         -g   - skip printing of garbage blocks\n";
        print "         -h   - help\n" ;
        print "         -i   - print one line of file identity info\n" ;
        print "         -l   - long format scan (print bad spots, MJF level for product)\n" ;
        print "         -t   - print SC time in HH:MM:SS.ms format \n" ;
	print "         -v   - turn verbose on \n";
        print "         -V   - version info\n" ;
        print "         -x   - add hex format dump of any record that prints\n" ;
        print "         -z   - scan for frame sync patterns in data, (-a,-x)\n" ;
	}

	if( $CODES ) {

		printf( "\n\nOct  Dec  Hex  Source/Dest. Descriptions\n\n" ) ;

		for( $I=0; $I<256 ; $I++ ) {
			if( defined $SRC_DESC[ $I ] ) {
				printf( "%3.1o  %3.1d  %3.1x  %s %s\n", $I, $I, $I,
					$SRC_DESC[$I], $SRC_ANT[$I] ) ;
			}
		}

		printf( "\n\nOct  Dec  Hex  DSID/PDF Descriptions\n\n" ) ;

		for( $I=0; $I<256 ; $I++ ) {
			if( defined $PDF[ $I ] ) {
				printf( "%3.1o  %3.1d  %3.1x  %8s %2s %1s %s\n", $I, $I, $I,
					$PDF_SAT[$I], $PDF_RTPB[$I], $PDF[$I], $PDF_DESC[$I] ) ;
			}
		}

		printf( "\n\nOct  Dec  Hex  Spacecraft ID Codes\n\n" ) ;

		for( $I=0; $I<256 ; $I++ ) {
			if( defined $SCID[ $I ] ) {
				printf( "%3.1o  %3.1d  %3.1x  %s \n", $I, $I, $I,
					$SCID[$I] ) ;
			}
		}
	}

        print "\n" ;
}

sub edit_usage{ 
        print "USAGE:\n   lzpedit  [options] filename  \n";
	print "      \n" ;
        print "         -h   - help\n" ;
        print "         -l   - long format, print each record deleted\n" ;
        print "         -v   - turn verbose on\n" ;
        print "         -V   - version info\n" ;
        print "         -x   - add hex format dump of any record deleted\n" ;

        print "\n" ;
}

sub diff_usage{ 
        print "USAGE:\n   lzpdiff  [options] filenameA filenameB  \n";
	print "      \n" ;
        print "         -a   - print MNF level and MJF level for any difference\n" ;
        print "         -h   - help\n" ;
        print "         -t   - print time in HH:MM:SS.ms format \n" ;
        print "         -v   - turn verbose on\n" ;
        print "         -V   - version info\n" ;

	print "\n";
}


sub display_usage {
	print "USAGE:\n   lzpprod date/time sattelite\n\n";
	print "\t where date/time in YYYYMMDD format for product files\n";
	print "\t       sattelite is either Wind, Polar, or Geotail\n";
	print "\n";
}


sub scandecom_usage {
	print "USAGE:\n   ";
	print "\t e.g.: lzpscandecom /wind/ops/data1/25/1/app0001\n";
	print "\t if no directory, assume current directory\n";

	print "\n";
}


sub time_usage {
    print "USAGE:  $PROGNAME\n";
    print "\tEnter time when prompt\n";
    print "\tThe valid time is either\n";
    print "\t\tFP time (ssssssssss.ssssss) or \n";
    print "\t\tPB5 time (12 or 14 hex digits) or\n";
    print "\t\tstring time(YYYYDDD.HHMMSS.UUUUUU)\n";
    print "\n";
}

#
#	Pattern_Loc( $Record, $Pattern, $Loc )
#
#	Returns 0 = not found, 1 = found

sub Pattern_Loc{ 

local( $REC, $PAT, $LOC ) = @_ ;

$CHK_VAL = unpack( "x$LOC L1", $REC ) ;	# extract 4-byte string at offset

if( $PAT <= 0xffffff ) { $CHK_VAL = ( $CHK_VAL >> 8 ) & 0xffffff ; }	# shift for 3-byte string

if( $CHK_VAL == $PAT ) { return 1 }
	else { return 0 }
	
}

sub commas {
	local($_) = @_ ;
	1 while s/(.*\d)(\d\d\d)/$1,$2/;
	$_;
}



sub Garbage_Loc {

local($REC, $LOC) = @_;

$CHK_VAL = unpack( "x$LOC L1", $REC ) ; # extract 4-byte string at offset

return ( ( $CHK_VAL == 0x00000000 ) || ($CHK_VAL == 0xFFFFFFFF ) || 
	 ( $CHK_VAL == 0x55555555 ) || ($CHK_VAL == 0xAAAAAAAA ) ||
	 ( $CHK_VAL == 0x9C9C9C9C ) || ($CHK_VAL == 0xC9C9C9C9 ) );
}



sub Swap_String {
   local ($STR) = @_;

   $LEN = length($STR);
   if($LEN <= 8)
   {
        @BYTE = reverse unpack("C$LEN", $STR);
        $STR = pack("C$LEN", @BYTE);
   }
   elsif($LEN == 12)                            # QAF ATCTime
   {
        @TEMP = unpack("C$LEN", $STR);
        $BYTE[ 0] = $TEMP[ 0+1];
        $BYTE[ 1] = $TEMP[ 0+0];
        $BYTE[ 2] = $TEMP[ 2+1];
        $BYTE[ 3] = $TEMP[ 2+0];
        $BYTE[ 4] = $TEMP[ 4+3];
        $BYTE[ 5] = $TEMP[ 4+2];
        $BYTE[ 6] = $TEMP[ 4+1];
        $BYTE[ 7] = $TEMP[ 4+0];
        $BYTE[ 8] = $TEMP[ 8+3];
        $BYTE[ 9] = $TEMP[ 8+2];
        $BYTE[10] = $TEMP[ 8+1];
        $BYTE[11] = $TEMP[ 8+0];

        $STR = pack("C$LEN", @BYTE);
   }
   elsif($LEN == 16)                            # TDM ATCTime
   {
        @TEMP = unpack("C$LEN", $STR);
        $BYTE[ 0] = $TEMP[ 0+3];
        $BYTE[ 1] = $TEMP[ 0+2];
        $BYTE[ 2] = $TEMP[ 0+1];
        $BYTE[ 3] = $TEMP[ 0+0];
        $BYTE[ 4] = $TEMP[ 4+3];
        $BYTE[ 5] = $TEMP[ 4+2];
        $BYTE[ 6] = $TEMP[ 4+1];
        $BYTE[ 7] = $TEMP[ 4+0];
        $BYTE[ 8] = $TEMP[ 8+3];
        $BYTE[ 9] = $TEMP[ 8+2];
        $BYTE[10] = $TEMP[ 8+1];
        $BYTE[11] = $TEMP[ 8+0];
        $BYTE[12] = $TEMP[12+3];
        $BYTE[13] = $TEMP[12+2];
        $BYTE[14] = $TEMP[12+1];
        $BYTE[15] = $TEMP[12+0];

        $STR = pack("C$LEN", @BYTE);
   }
   else
   {
        $STR = reverse $STR;
   }
   return $STR;
}

sub Swap_Number {
  local ($WORD, $SIZE) = @_;

   if($SIZE == 4) {
        return unpack("L1", pack("C4", reverse unpack("C4", pack("L1", $WORD))));
   }
   else {
        return unpack("S1", pack("C2", reverse unpack("C2", pack("S1", $WORD))));
   }
}


sub PROD_SCAN {
   local ($RB, $I, $J);

   seek(IN,0,0);
   
   if( $DATA_TYPE eq "TDM" ) {
        $TOT_FILL = 0;
    	$TOT_FSE  = 0;
    	$TOT_MNCE = 0;
	$ZERO_FLAG = 0;
	$NON_ZERO_FLAG = 0;

   	$RB = sysread(IN, $REC, 2792);

	PROD_FHPRT($REC);

   	seek(IN, $PHYS_LEN, 0);

	if($LONG || $OLINE || $HEX) {
   		printf("\nDATA PORTION\n");
	}

	while($PHYS_NUM < $RECNUM)
   	{
        	$RB = sysread(IN, $REC, $PHYS_LEN);
		PROD_PRT($REC);
   	}

	$ZERO_FLAG = $RECNUM - 1 - $NON_ZERO_FLAG;
	printf("\n------------------ RECORDS SUMMARY ---------------------\n");

#	printf(" len of PHYS REC = %d\n", $PHYS_LEN);
#	printf(" len of REC HDR = %d\n", $R_HDR_LEN);
#	printf(" len of INST DATA = %d\n", $PHYS_LEN - $R_HDR_LEN);
#	printf(" Telemetry Mode Indicator = %d - %s\n", $TMI, $MISSION_SUB_DESC{$SAT."-".$APNAME.$TMI});
#	printf(" Size of subrecord = %d bytes\n", $MISSION_SUB_BYTE{$SAT."-".$APNAME.$TMI});
#	printf(" Number of MNF per MJF = %d\n", $NUM_MNF);

	printf("\nTotal Records       Zero Flags       Non-Zero Flags");
	printf("\n%5d                %5d           %5d\n\n", $RECNUM-1, $ZERO_FLAG, $NON_ZERO_FLAG);
	printf("\t  MNF with Fill Flag set:      %4d\n", $TOT_FILL);
	printf("\t  MNF with Frame Synch Error:  %4d\n", $TOT_FSE);
	printf("\t  MNF with Counter Error Flag: %4d\n", $TOT_MNCE);
        printf("\n$TMI_CHANGE\n");
   }

   if( $DATA_TYPE eq "QAF" ) 
   {
	$RB = sysread(IN, $REC, $F_HDR_LEN);

	QAF_FHPRT($REC);

   	$PHYS_NUM = 0;
	while( $PHYS_NUM <= $RECNUM ) 
	{
		$RB = sysread(IN, $REC, $F_HDR_LEN);
		QAF_PRT($REC);
	}
   }

   if ($DATA_TYPE eq "PWIW") {

	$RB = sysread(IN, $REC, $F_HDR_LEN);
	
	PWIW_FHPRT($REC);

	if( $LONG ) {
        	printf("\nRECORD HEADER\n");
		printf("\tPHYS#  MNFC  HRPC  YYYY  DDD  MSECOD     RAWTIME     #WBR  #HRP  #PFCT  ");
		printf("#FILL  #MODE_CHG  #MODE_ERR  #CNT_ERR  #HRP_CNT_ERR  #FSE\n");
	}

	$PHYS_NUM = 0;
	while( $PHYS_NUM < $RECNUM )
	{
		$RB = sysread(IN, $REC, $F_HDR_LEN);
		PWIW_PRT($REC);
	}

   }

   if($DATA_TYPE eq "SIRIUS") {
	$RB = sysread(IN, $REC, $F_HDR_LEN);

	SIRIUS_FHPRT($REC);

	if( $LONG || $OLINE || $HEX)
	{
	     printf("\nTELEMETRY DATA\n");
	}

	$MNF = 1;
	while($MNF <= $NUM_MNF)
        {
             $RB = sysread(IN, $REC, 144);
             SIRIUS_PRT($REC);
	     $MNF++;
        }

	@STAT = stat(IN);
	printf("\nBLOCK INFORMATION:");
	seek(IN, $STAT[7] - 23040, 0);
	$RB = sysread(IN, $REC, 4);
	$NUM_BLKS = unpack("x2 S1", $REC);
	printf("\t$NUM_BLKS Blocks\n");
#
#	for($J=0; $J<$NUM_BLKS; $J++)
#	{
#		$RB = sysread(IN, $REC, 8);
#		
#		( $SC_TIME, $PHYS_BLK ) = unpack("L1 L1", $REC);
#		
#		printf("\t\t%3d", $PHYS_BLK);
#		printf("\t\t\t%8.8x\n", $SC_TIME);
#	}


	$ZERO_FLAG = $NUM_MNF - $NON_ZERO_FLAG;
	printf("\n------------------ RECORDS SUMMARY ---------------------\n");
	printf("\nTotal MNF       Zero Flags       Non-Zero Flags");
	printf("\n%5d             %5d              %5d\n\n", $NUM_MNF, $ZERO_FLAG, $NON_ZERO_FLAG);
	printf("\t  MNF with Frame Synch Error:  %4d\n", $TOT_FSE);
	printf("\t  MNF with Counter Error Flag: %4d\n\n", $TOT_MNCE);
	printf("\n%s\n", $BITRATE_CHANGE);
	printf("\n%s\n", $DATAID_CHANGE);
   }

   printf("\n");

}

sub PROD_FHPRT {

    local ($REC) = @_;

    $SCID = 0;
    ($SCID, $APID, $APNAME, $PHYS_NUM, $REC_PER_MJF, $RECNUM, $BEGIN_MJFC,
     $LAST_MJFC, $BEGIN_SCTIME, $LAST_SCTIME, $BEGIN_ATCTIME, $LAST_ATCTIME,
     $EXPCT_MJF, $NUM_MJF, $NUM_GAP,$DTYPE,$DECOM_RERUN,$DECOM_PROG_VER,
     $DECOM_DB_VER, $DECOM_DATE, $DECOM_FILE, $PHYS_LEN, $MERGE_RERUN,
     $MERGE_PROG_VER, $MERGE_DATE, $EDIT_NUM, $EDIT_FILE)
                = unpack("L1 L1 a3 x L1 L1 L1 L1 L1 a8 a8 a16 a16 L1 L1 L1 a4 L1 \
                          a8 a8 a16 a44 L1 x20 L1 a8 a16 L1 a20", $REC);

     $PHYS_NUM = &Swap_Number($PHYS_NUM, 4);
     $RECNUM = &Swap_Number($RECNUM, 4);
     $PHYS_LEN = &Swap_Number($PHYS_LEN, 4);
     $SCID = &Swap_Number($SCID, 4);
     $APID = &Swap_Number($APID, 4) % 100;
     $NUM_MJF =  &Swap_Number($NUM_MJF, 4);
     $BEGIN_MJFC = &Swap_Number($BEGIN_MJFC, 4);
     $LAST_MJFC =  &Swap_Number($LAST_MJFC, 4);
     $BEGIN_SCTIME = unpack("H12",Swap_String($BEGIN_SCTIME));
     $LAST_SCTIME = unpack("H12",Swap_String($LAST_SCTIME));
     @BEGIN_ATCTIME = unpack("L4",Swap_String($BEGIN_ATCTIME));
     @LAST_ATCTIME = unpack("L4",Swap_String($LAST_ATCTIME));
     ($byyyy, $bddd, $bmmm, $buuu) = unpack("L4", &Swap_String($BEGIN_ATCTIME));
     ($lyyyy, $lddd, $lmmm, $luuu) = unpack("L4", &Swap_String($LAST_ATCTIME));

     if($SAT eq "GEOTAIL")    { %MISSION_SUB_BYTE = %GEO_SUB_BYTE; %MISSION_SUB_DESC = %GEO_SUB_DESC;}
     elsif($SAT eq "WIND")    { %MISSION_SUB_BYTE = %WIND_SUB_BYTE; %MISSION_SUB_DESC = %WIND_SUB_DESC;}
     elsif($SAT eq "POLAR")   { %MISSION_SUB_BYTE = %POLAR_SUB_BYTE; %MISSION_SUB_DESC = %POLAR_SUB_DESC;}

     if( $LZPSCAN ) {
        printf("FILE LABEL RECORD\n");
        printf("\tTotal Number Records \t\t\t\t%d\n", $RECNUM);
        printf("\tPhysical Record length \t\t\t\t%d\n", $PHYS_LEN);
        printf("\tSCID \t\t\t\t\t\t%d\n", $SCID);
        printf("\tAPID \t\t\t\t\t\t%d\n", $APID);
        printf("\tAPID name \t\t\t\t\t%s\n", $APNAME);
        printf("\tNumber of  Records per Major frame \t\t%d\n", &Swap_Number($REC_PER_MJF, 4));
        printf("\t# Expected MJF \t\t\t\t\t%d\n", &Swap_Number($EXPCT_MJF, 4));
        printf("\t# MJF in file \t\t\t\t\t%d\n", $NUM_MJF);
        printf("\t# Data Gaps in file \t\t\t\t%d\n", &Swap_Number($NUM_GAP, 4));
        printf("\tFirst MJFC \t\t\t\t\t%d\n", $BEGIN_MJFC);
        printf("\tLast MJFC \t\t\t\t\t%d\n", $LAST_MJFC);
        printf("\tFirst SC time \t\t\t\t\t%s\n", $BEGIN_SCTIME);
        printf("\tLast SC time \t\t\t\t\t%s\n", $LAST_SCTIME);
	if($TIME)
	{
		$tempUTC = &FP2str(&ydmu2UTC($byyyy, $bddd, $bmmm, $buuu));
		$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));
		printf("\tFirst ATC time \t\t\t\t\t%4d %03d %s\n", $byyyy, $bddd, $PB5UTC);
		$tempUTC = &FP2str(&ydmu2UTC($lyyyy, $lddd, $lmmm, $luuu));
		$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));
		printf("\tLast ATC time \t\t\t\t\t%4d %03d %s\n", $lyyyy, $lddd, $PB5UTC);
	}
	else
	{
        	printf("\tFirst ATC time \t\t\t\t\t%d %d %d %d\n", @BEGIN_ATCTIME);
        	printf("\tLast ATC time \t\t\t\t\t%d %d %d %d\n", @LAST_ATCTIME);
	}
        printf("\tData Type \t\t\t\t\t%s\n", $DTYPE);
        printf("\tDecom Rerun number \t\t\t\t%d\n", &Swap_Number($DECOM_RERUN, 4));
        printf("\tDecom Program Version \t\t\t\t%s\n", $DECOM_PROG_VER);
        printf("\tDecom Database Version \t\t\t\t%s\n", $DECOM_DB_VER);
        printf("\tDecom Date \t\t\t\t\t%s\n", $DECOM_DATE);
        printf("\tDecom File Name \t\t\t\t%s\n", $DECOM_FILE);
        printf("\tMerge Rerun Number \t\t\t\t%d\n", &Swap_Number($MERGE_RERUN, 4));
        printf("\tMerge Program Version \t\t\t\t%s\n", $MERGE_PROG_VER);
        printf("\tMerge Date \t\t\t\t\t%s\n", $MERGE_DATE);
        printf("\tEdit Number \t\t\t\t\t%d\n", &Swap_Number($EDIT_NUM, 4));
        printf("\tEdit File Name \t\t\t\t\t%s\n", $EDIT_FILE);
     }

}

sub PROD_PRT {
    local ($REC) = @_;
    local ($I);

    $RHDR = substr($REC, 0, 48);

#    $THE_REST = substr($REC, 48, 252);
#    HEXPRT($RHDR, 48); print "\n\n";
#    HEXPRT($THE_REST, length($THE_REST)); print "\n\n";

    ($INST_NUM, $PHYS_NUM, $MJFC, $SC_TIME, $ATC_TIME, $FILL, $FSE, $TMI) =
                        unpack("L1 L1 L1 a8 a16 L1 L1 L1", $RHDR);

    $TMI = &Swap_Number($TMI, 4);
    $FILL = &Swap_Number($FILL, 4);
    $FSE = &Swap_Number($FSE, 4);
    $PHYS_NUM = &Swap_Number($PHYS_NUM, 4);
    $MNQB = substr($REC, 48, int(($NUM_MNF/4)+0.5)*4);
    @QTYB = unpack("C$NUM_MNF", $MNQB);
    $MNCE = 0;
    $NUM_PERFCT = $NUM_MNF;

    for($J=0; $J<$NUM_MNF; $J++) {
            $MNCE += $QTYB[$J] & 0x02;
	    if($QTYB[$J] != 0) { $NUM_PERFCT --; }
    }


    if( ($LONG || $OLINE || $HEX) && ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) 
    {
             if( ($OLINE || $HEX) || ($LONG && $LINES % 61 == 0) ) {
		   if($TIME) { printf("\n   PHYS#  MJFC  YYYY  DOY   HH:MM:SS:mmm.uuu   "); }
		   else { printf("\n   PHYS#  MJFC  YYYY  DOY   MSECOD    USEC    "); }
                   printf("  (SC CLOCK)       #FILL  #FSE   #MNCE   #PFCT   TMI\n");
             }
             printf("   %04d   ", $PHYS_NUM );
             printf("%3d   ", &Swap_Number($MJFC, 4) );
	     ($yyyy, $ddd, $mmm, $uuu) = unpack("L4",Swap_String($ATC_TIME));
	     if($TIME)
	     {
		$tempUTC = &FP2str(&ydmu2UTC($yyyy, $ddd, $mmm, $uuu));
		$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));
		printf("%4d  %03d   %s ", $yyyy, $ddd, $PB5UTC);
	     }
	     else { printf("%d  %03d  %08d   %04d  ", $yyyy, $ddd, $mmm, $uuu); }
	     printf("  %s    ", unpack("H14",Swap_String($SC_TIME)) ); 
             printf("%4d    ", $FILL );
             printf("%3d    ", FSE );
             printf("%3d    ", $MNCE);
	     printf("%5d   ", $NUM_PERFCT);
             printf("%3d   ", $TMI);
    	     if( $FILL || $FSE || $MNCE) { printf("  FLAGGED"); }
	     printf("\n");
    	     if( $OLINE  || $HEX ) {
		  printf("\t\t\t\tData Record Header: \n");
		  HEXPRT($RHDR, 48);
             	  printf("\t\t\t\tMinor Frames Quality Bytes:\n");
                  HEXPRT($MNQB, $NUM_MNF);
		  print "\n";
    	     }
	     $LINES++;
    }
    else 
    {
	if($VERBOSE) {
	        if(not defined $DISPLAY ) { syswrite(STDERR,  "...\n", 56); }
		$ROW_FORMAT = sprintf($C_ROWS, $ROWS);
		$COL_FORMAT = sprintf($C_COLS, 1);
		$DISPLAY = sprintf("%s%sScanning Phys Rec %s%d  ", $C_OPEN, $ROW_FORMAT, $COL_FORMAT, $PHYS_NUM);
		syswrite(STDERR, $DISPLAY, length($DISPLAY));
	}
    }


    if( $HEX && ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) {
    	     $SUBREC_BYTE = $MISSION_SUB_BYTE{$SAT."-".$APNAME.$TMI};
	     $TOTAL_BYTES = $NUM_MNF * $SUBREC_BYTE;
	     $SUBREC  = substr($REC, $R_HDR_LEN, $TOTAL_BYTES);
	     for ($I = 0; $I < $NUM_MNF; $I++) {
             	 printf("\t\t\t\tData Subrecord:  %d\n", $I+1);
             	 HEXPRT(substr($SUBREC, $I*$SUBREC_BYTE, $SUBREC_BYTE), $SUBREC_BYTE);
	     }
    }

    $TOT_FILL += $FILL;
    $TOT_FSE  += $FSE;
    $TOT_MNCE += $MNCE;
    if( $FILL || $FSE || $MNCE) { $NON_ZERO_FLAG++; }

    if( defined $PREV_TMI ) {
	if( $PREV_TMI != $TMI ) {
	   $TMI_CHANGE = $TMI_CHANGE . sprintf("  Mode changes from $PREV_TMI (%s) to $TMI (%s) at Phys Rec %d\n", 
						     $MISSION_SUB_DESC{$SAT."-".$APNAME.$PREV_TMI},
						     $MISSION_SUB_DESC{$SAT."-".$APNAME.$TMI}, $PHYS_NUM);
	}
    }
}

sub QAF_FHPRT {

    local ($REC) = @_;

    ($SCID, $APNAME, $RECNUM, $PROC_TIME, $BEGIN_TIME, $LAST_TIME, $PROD_TYPE, $DECOM_SEQ,
     $NUM_MJF, $NUM_GAP, $NUM_PERFECT, $NUM_ERR_FREE, $NUM_ERR, $EXP_FLAG) =
                unpack("L1 a4 L1 a16 a12 a12 a4 L1 L1 L1 L1 L1 L1 L1", $REC);

    $NUM_MJF = &Swap_Number($NUM_MJF, 4);
    $RECNUM = &Swap_Number($RECNUM, 4);
    ($byyyy, $bddd, $bmmm, $buuu) = unpack("S1 S1 L1 L1", &Swap_String($BEGIN_TIME));
    @BEGIN_ATCTIME = unpack("S1 S1 L1 L1", &Swap_String($BEGIN_TIME));
    ($lyyyy, $lddd, $lmmm, $luuu) = unpack("S1 S1 L1 L1", &Swap_String($LAST_TIME));
    @LAST_ATCTIME = unpack("S1 S1 L1 L1", &Swap_String($LAST_TIME));

    if($LZPSCAN)
    {
         printf("FILE LABEL RECORD\n");
         printf("\tSpacecraft ID:\t\t\t\t\t%d\n", &Swap_Number($SCID,4));
         printf("\tFile ID:\t\t\t\t\t%s\n", $APNAME);
         printf("\tNumber of QA Records:\t\t\t\t%d\n", $RECNUM);
         printf("\tFile Process Time:\t\t\t\t%s %s %s:%s:%s.%s\n",
                                	     unpack("a4 a3 a2 a2 a2 a3", $PROC_TIME) );
	 if($TIME)
	 {
		$tempUTC = &FP2str(&ydmu2UTC($byyyy, $bddd, $bmmm, $buuu));
		$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));
		printf("\tTime of First MJF:\t\t\t\t%4d %03d %s\n", $byyyy, $bddd, $PB5UTC);
		$tempUTC = &FP2str(&ydmu2UTC($lyyyy, $lddd, $lmmm, $luuu));
		$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    				sprintf("%d", substr($tempUTC, 8, 2)),
    				sprintf("%d", substr($tempUTC, 10, 2)),
    				sprintf("%d", substr($tempUTC, 12, 2)),
    				sprintf("%d", substr($tempUTC, 15, 3)),
    				sprintf("%d", substr($tempUTC, 18, 3)));
		printf("\tTime of Last MJF:\t\t\t\t%4d %03d %s\n", $lyyyy, $lddd, $PB5UTC);
	 }
	 else
	 {
         	printf("\tTime of First MJF:\t\t\t\t%d %d %d %d\n", @BEGIN_ATCTIME);
	 	printf("\tTime of Last MJF:\t\t\t\t%d %d %d %d\n", @LAST_ATCTIME);
	 }
         printf("\tProduction Indicator:\t\t\t\t%s\n", $PROD_TYPE);
         printf("\tDecom Sequence Number:\t\t\t\t%d\n", &Swap_Number($DECOM_SEQ, 4));
         printf("\tTotal Number of MJF:\t\t\t\t%d\n", $NUM_MJF);
         printf("\tTotal Number of Data Gap:\t\t\t%d\n", &Swap_Number($NUM_GAP, 4));
         printf("\tTotal Number of Perfect MJF:\t\t\t%d\n", &Swap_Number($NUM_PERFECT, 4));
         printf("\tTotal Number of error-free MJF:\t\t\t%d\n", &Swap_Number($NUM_ERR_FREE, 4));
         printf("\tTotal Number of MJF with errors:\t\t%d\n", &Swap_Number($NUM_ERR, 4));
         printf("\tExperiment File Flag:\t\t\t\t%8.8x\n", &Swap_Number($EXP_FLAG, 4));
    }
}

sub QAF_PRT {

    local ($REC) = @_;

    $REC_HDR = substr($REC, 0, $R_HDR_LEN);
    ($PHYS_NUM, $MJF_ENT, $MJF_GAP, $MJF_PFCT) = unpack("L1 L1 L1 L1", $REC_HDR);

    $PHYS_NUM = &Swap_Number($PHYS_NUM, 4);
    $MJF_ENT = &Swap_Number($MJF_ENT, 4);
    $MJF_GAP = &Swap_Number($MJF_GAP, 4);
    $MJF_PFCT = &Swap_Number($MJF_PFCT, 4);

    if( ($LONG || $OLINE) && ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) 
    {
	 if($LZPSCAN)
	 {
	 	if($OLINE || $FIRST_REC == 0) {
         		printf("\nRECORD HEADER\n");
              		printf("\tPHYS#    #MJF_ENTRES    #MJF_GAPS    #MJF_PFCT  \n");
	 	}

         	printf("\t%5d    %5d          %5d        %5d\n", $PHYS_NUM, $MJF_ENT, $MJF_GAP, $MJF_PFCT);
	 }

	 $FIRST_REC++;
    }

    for($J=0; $J<$MJF_ENT; $J++)
    {
        $QAF_ENTRIES = substr($REC, ($J*40)+$R_HDR_LEN, 40);
	($BEGIN_TIME, $ATC_FLAG, $GAP_FLAG, $TMI, $MJFC, $MNF_FILL, $MNFC_ERR, $MNF_FSE, $MNFC_JUMP) = 
			unpack("a12 S1 S1 x2 S1 L1 L1 L1 L1 L1", $QAF_ENTRIES);

	if( ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) 
	{
	     if( ($OLINE || $HEX) && $LZPSCAN ) 
	     {
		  if($LINES % 40 == 0 || $HEX) {
         		printf("\n\tMAJOR FRAME Q/A ENTRIES:\n");
			if($TIME) {
				printf("\tENTRY  YYYY  DDD  HH:MM:SS:mmm.uuu  ATC_FLAG  GAP_FLAG  TMI  MJFC  ");
			}
			else {
         			printf("\tENTRY  YYYY  DDD   MSECOD   USECS  ATC_FLAG  GAP_FLAG  TMI  MJFC  ");
			}
         		printf("MNF_FILL  MNF_ERR  MNF_FSE  MNF_JUMP\n");
		  }
             	  printf("\t%3d    ", $J+1);
		  ($yyyy, $ddd, $mmm, $uuu) = unpack("S S L1 L1", &Swap_String($BEGIN_TIME));
		  if($TIME)
		  {
			$tempUTC = &FP2str(&ydmu2UTC($yyyy, $ddd, $mmm, $uuu));
			$PB5UTC = sprintf("%02u:%02u:%02u:%03u.%03u", 
    					sprintf("%d", substr($tempUTC, 8, 2)),
    					sprintf("%d", substr($tempUTC, 10, 2)),
    					sprintf("%d", substr($tempUTC, 12, 2)),
    					sprintf("%d", substr($tempUTC, 15, 3)),
    					sprintf("%d", substr($tempUTC, 18, 3)));
			printf("%4d  %3d  %s ", $yyyy, $ddd, $PB5UTC);
		  }
		  else
		  {
             	  	printf("%4d  %3d  %08d  %04d ", $yyyy, $ddd, $mmm, $uuu);
		  }
             	  printf("    %d     ", &Swap_Number($ATC_FLAG, 2));
             	  printf("    %d     ", &Swap_Number($GAP_FLAG, 2));
             	  printf("  %d    ", &Swap_Number($TMI, 2));
             	  printf("%3d     ", &Swap_Number($MJFC, 4));
             	  printf("%3d     ", &Swap_Number($MNF_FILL, 4));
             	  printf("%3d      ", &Swap_Number($MNFC_ERR, 4));
             	  printf("%3d      ", &Swap_Number($MNF_FSE, 4));
             	  printf("%3d\n", &Swap_Number($MNFC_JUMP, 4));
	     	  if($HEX) 
	     	  {
			  print "\n\tHEX DUMPED\n";
             	  	  HEXPRT($REC, 80);
			  print "\n";
	     	  }
	     }
	     if($J==0) { $BEGIN_MJFC = &Swap_Number($MJFC, 4); }
	     if($J == $MJF_ENT) { $LAST_MJFC = &Swap_Number($MJFC, 4); }
	     $LINES++;
        }
    	else 
    	{
	     if($VERBOSE) 
	     {
	             if(not defined $DISPLAY) { print "...\nScan Phys Rec#\n"; }
		     $ROW_FORMAT = sprintf($C_ROWS, $ROWS-1);
		     $COL_FORMAT = sprintf($C_COLS, 23);
		     $DISPLAY = sprintf("%s%s%s%d ", $C_OPEN, $ROW_FORMAT, $COL_FORMAT, $PHYS_NUM);
		     syswrite(STDERR, $DISPLAY, length($DISPLAY));
	    }
    	}
    }

}


sub SIRIUS_FHPRT {

    local ($REC) = @_;

    $REC = &toASCII($REC);
    ($SCID, $PATH_NUM, $NUM_MNF, $STAT_ID, $DAT_ID, $DAT_NAME,
    $FIRST_DATE, $FIRST_TIME, $FIRST_FI_CNT, $FIRST_TI_CNT,
    $LAST_DATE, $LAST_TIME, $LAST_FI_CNT, $LAST_TI_CNT,
    $CORR_DATE, $CORR_TIME, $CORR_FI_CNT, $CORR_TI_CNT,
    $TI_INTVL, $COMMENT, $MSG_DATA) = unpack("x2 a4 a10 x4 a6 a2 a2 a20 \
                                              a6 a9 x a3 a10 x  \
                                              a6 a9 x a3 a10 x  \
                                              a6 a9 x a3 a10 x5 \
                                              a8 x136 A144 x144 A144", $REC);

    $RECNUM = $NUM_MNF;

    if($LZPSCAN)
    {
         printf("FILE LABEL RECORD\n");
         printf("\tSpacecraft ID:\t\t\t\t\t\t\t%d\n", $SCID);
         printf("\tPath Number:\t\t\t\t\t\t\t%s\n", $PATH_NUM);
         printf("\tNumber of MNF:\t\t\t\t\t\t\t%d\n", $NUM_MNF);
         printf("\tStation ID:\t\t\t\t\t\t\t%d\n", $STAT_ID);
         printf("\tData ID:\t\t\t\t\t\t\t%d\n", $DAT_ID);
         printf("\tData Name:\t\t\t\t\t\t\t%s\n", $DAT_NAME);
         printf("\tFirst Frame Date:\t\t\t\t\t\t%s\n", $FIRST_DATE);
         printf("\tFirst Frame Time:\t\t\t\t\t\t%s\n", $FIRST_TIME);
         printf("\tFirst Frame FI Counter:\t\t\t\t\t\t%d\n", $FIRST_FI_CNT);
         printf("\tFirst Frame TI Counter:\t\t\t\t\t\t%s\n", $FIRST_TI_CNT);
         printf("\tLast Frame Date:\t\t\t\t\t\t%s\n", $LAST_DATE);
         printf("\tLast Frame Time:\t\t\t\t\t\t%s\n", $LAST_TIME);
         printf("\tLast Frame FI Counter:\t\t\t\t\t\t%d\n", $LAST_FI_CNT);
         printf("\tLast Frame TI Counter:\t\t\t\t\t\t%s\n", $LAST_TI_CNT);
         printf("\tTime Correlation Data Date:\t\t\t\t\t%s\n", $CORR_DATE);
         printf("\tTime Correlation Data Time:\t\t\t\t\t%s\n", $CORR_TIME);
         printf("\tTime Correlation Data FI Counter:\t\t\t\t%d\n", $CORR_FI_CNT);
         printf("\tTime Correlation Data TI Counter:\t\t\t\t%s\n", $CORR_TI_CNT);
         printf("\tT1 Interval (msecs):\t\t\t\t\t\t%5.3f\n", $TI_INTVL);
         printf("\tComment:\t\t\t\t\t%s\n", $COMMENT);
         printf("\tMessage Data:\t\t\t\t\t%s\n\n", $MSG_DATA);
    }

}

sub SIRIUS_PRT {
   
    local ($REC) = @_;

    ($LEAP_DAY, $HOUR, $MIN, $SEC, $MSEC, $RATE_ID, $MNF_CNTR, $TIME_CNTR, $QLTY, $RAW_CNT) = 
		unpack("S1 C1 C1 C1 S1 C1 C1 L1 C1 x5 x7 C1", $REC);
   
    if ($MNF_CNTR%256 ==0) { $RAW_CNT = $RAW_CNT & 0x0f; $BIT1 = $RAW_CNT & 0x01; $BIT2to4 = $RAW_CNT >> 1; 
	 		#	printf("****** %d\t%d\t %d\t %d --- %d\n", $MNF, $MNF_CNTR, $RAW_CNT, $BIT1, $BIT2to4); 
			   }
    $LEAP = ($LEAP_DAY & 0xf000) >> 8;
    $DAY = $LEAP_DAY & 0x0fff;
    $BIT_RATE = ($RATE_ID & 0xf0) >> 4;
    $DATA_ID = $RATE_ID & 0x0f;
    $MSEC = $MSEC >> 4;

    if( $BIT1 == 1) { $MJF_BOUND = 1; } else { $MJF_BOUND = 0; }

    $PREV_BIT1 = $BIT1;

    if( $LONG && ($MNF >= $BEGREC) )
    {
	if( ($MNF_CNTR == 0 && $BIT1 == 1) || (not defined $FIRST_REC) || ($MNF == $NUM_MNF) ) 
		{ $DUMP_MJFR++; $NUM_FLAG = $MNF_FLAGED; $MNF_FLAGED=0;}
	else { $DUMP_MJFR = 0; $NUM_FLAG = 0; }
	if($MNF > $ENDREC) {$DUMP_MJFR = 0;}
	if(not defined $FIRST_REC) { $FIRST_REC++; }
 	if($MNF == $BEGREC) { $PFCT_MNF = 0; $FILL_MNF = 0; $FSE_MNF = 0; }
    }

    if($QLTY != 0 && $LONG) { $MNF_FLAGED++;}
    if( $QLTY == 0 ) { $PFCT_MNF++;}
    else { $NON_ZERO_FLAG++;}

    if(($QLTY >> 5) == 1) { $TOT_MNCE++; $FILL_MNF++;}
    if(($QLTY >> 3) == 1) { $TOT_FSE++; $FSE_MNF++;}
    $TOTAL_MNF ++;

    if($MNF < $BEGREC && $VERBOSE) { if(not defined $SHOW_BEG) {print "\n...\nScan Phys Rec#\n"; $SHOW_BEG++} }
    elsif($MNF < $ENDREC) { $SHOW_BEG=0; }
    if($MNF > $ENDREC && $VERBOSE) { if(not defined $SHOW_END) {print "\n...\nScan Phys Rec#\n"; $SHOW_END++} }

    if( (($OLINE || $HEX) && ($MNF >= $BEGREC) && ($MNF <= $ENDREC)) || $DUMP_MJFR)
    {
	if( $HEX || $LINES % 64 == 0 ) {
	    printf("\n SEQ\tLEAP?  DDD HH:MM:SS.UUU   (TIME  CNTR)  BIT RATE   DATA/ID   MNFC");
	    if($LONG) { print "  TOTAL MIFs  FILL MIFs  FSE MIFs  PFCT MNFs\n"; }
	    else { print "   QLTY\n"; }
	} 
	$LINES++;

	$TO_PRT = sprintf("%4d\t%3d %6.3x %02x:%02x:%02x:%03.3x   ( %8.8X ) %6x\t %5x\t %7d  ",
		$MNF,$LEAP,$DAY,$HOUR,$MIN,$SEC,$MSEC,$TIME_CNTR,$BIT_RATE,$DATA_ID,$MNF_CNTR);
	if($LONG) 
        {
	    $SAVE_SEQ = $MNF;
	    if($SAVE_PRT eq "" ) { $SAVE_PRT = $TO_PRT; $SAVE_SEQ = $MNF; }
	    else { 
		$SAVE_PRT = $SAVE_PRT . sprintf("%7d %10d %9d %11d\n", $TOTAL_MNF, $FILL_MNF, $FSE_MNF, $PFCT_MNF);
		print $SAVE_PRT; 
		$SAVE_PRT = $TO_PRT; 
    		$PFCT_MNF = 0;
    		$FILL_MNF = 0;
		$FSE_MNF = 0;
		$TOTAL_MNF = 0;
    		if(($QLTY >> 5) == 1) { $FILL_MNF++;}
    		if(($QLTY >> 3) == 1) { $FSE_MNF++;}
	    }
	    
	}
	else { printf("%s %4.2X\n", $TO_PRT, $QLTY); }

        if( $HEX  && ($MNF >= $BEGREC) && ($MNF <= $ENDREC) )
        {
            HEXPRT($REC, 144);
	    print "\n"
        }
    }


    if($VERBOSE && ($SHOW_END || $SHOW_BEG)) 
    {
	$ROW_FORMAT = sprintf($C_ROWS, $ROWS-1);
	$COL_FORMAT = sprintf($C_COLS, 23);
	$DISPLAY = sprintf("%s%s%s%d\n", $C_OPEN, $ROW_FORMAT, $COL_FORMAT, $MNF);
	syswrite(STDERR, $DISPLAY, length($DISPLAY));
    }

    if (defined $PREV_BITRATE) 
    {
	if($BIT_RATE != $PREV_BITRATE){ 
		$BITRATE_CHANGE = $BITRATE_CHANGE . "Bit rate changes from $PREV_BITRATE to $BIT_RATE at MNF Seq. $MNF\n"; 
	}
    }

    if (defined $PREV_DATAID) 
    {
	if($DATA_ID != $PREV_DATAID) {  
		$DATAID_CHANGE = $DATAID_CHANGE . "Data ID chages from $PREV_DATAID to $DATA_ID at MNF Seq. $MNF\n"; 
	}
    }
    $PREV_BITRATE = $BIT_RATE; 
    $PREV_DATAID = $DATA_ID; 
}

sub PWIW_FHPRT {

    local ($REC) = @_;

    $HDR = substr($REC, 0, 252);
    $TIME_TYPE[0] = "GT Time";
    $TIME_TYPE[1] = "PB5 Time";

    ($SCID, $APNAME, $PHYS_NUM, $RECNUM, $BEGIN_SCTIME, $LAST_SCTIME, $BEGIN_TIME, $LAST_TIME,
    $FIRST_MNFC, $LAST_MNFC, $FIRST_HRPC, $LAST_HRPC, $MNF_EXPCT, $MNF, $MNF_WBR, $MNF_HRP,
    $MNF_PFCT, $MNF_FILL, $MNFM, $MNFM_ERR, $MNFC_ERR, $HRP_ERR, $MNFC_ERR, $MNF_FSE, $IPASS_VER,
    $IPASS_TIME, $IPASS_RERUN, $EXP_NAME, $SFD_NAME, $TIME_FLAG, $IPASS_TYPE, $FILE_SEQ ) =
                unpack("L1 a4 L1 L1 a8 a8 a12 a12 L1 L1 L1 L1 L1 L1 L1 L1 L1 x8 \
                        L1 L1 L1 L1 L1 L1 a8 a16 L1 a44 a44 L1 a4 L1", $HDR);

    $RECNUM = &Swap_Number($RECNUM, 4);
    $MNF =  &Swap_Number($MNF, 4) ;
    $MNF_WBR = &Swap_Number($MNF_WBR, 4) ;
    $MNF_HRP = &Swap_Number($MNF_HRP, 4) ;
    $BEGIN_SCTIME = unpack("H64", $BEGIN_SCTIME) ;
    $LAST_SCTIME = unpack("H64", $LAST_SCTIME) ;
    @BEGIN_ATCTIME = unpack("L4", &Swap_String($BEGIN_TIME) );
    @LAST_ATCTIME = unpack("L4", &Swap_String($LAST_TIME) );
    $FIRST_MNFC =  &Swap_Number($FIRST_MNFC, 4) ;
    $LAST_MNFC = &Swap_Number($LAST_MNFC, 4) ;
    $FIRST_HRPC = &Swap_Number($FIRST_HRPC, 4) ;
    $LAST_HRPC = &Swap_Number($LAST_HRPC, 4);

    if($LZPSCAN)
    {
         printf("FILE LABEL RECORD\n");
         printf("\tSpacecraft ID:\t\t\t\t%d\n", &Swap_Number($SCID, 4) );
         printf("\tInstrument Name:\t\t\t\t%s\n", $APNAME);
         printf("\tNumber of Physical Records:\t\t\t%d\n", &Swap_Number($RECNUM, 4) );
         printf("\tRaw Data Time - First Frame:\t\t\t%s\n", $BEGIN_SCTIME );
         printf("\tRaw Data Time - Last Frame:\t\t\t%s\n",  $LAST_SCTIME );
         printf("\tCorrected Time - First Frame:\t\t\t%d %d %d\n", @BEGIN_ATCTIME );
         printf("\tCorrected Time - Last Frame:\t\t\t%d %d %d\n", @LAST_ATCTIME );
         printf("\tFrame Counter - First Frame:\t\t\t%d\n", $FIRST_MNFC );
         printf("\tFrame Counter - Last Frame:\t\t\t%d\n", $LAST_MNFC );
         printf("\tHRP Sequence Counter - First Frame:\t\t%d\n", $FIRST_HRPC );
         printf("\tHRP Sequence Counter - Last Frame:\t\t%d\n", $LAST_HRPC );
         printf("\tNumber of Frame Expected:\t\t\t%d\n", &Swap_Number($MNF_EXPCT, 4) );
         printf("\tNumber of Frames in File:\t\t\t%d\n", $MNF );
         printf("\tNumber of WBR Frames in File:\t\t\t%d\n", $MNF_WBR );
         printf("\tNumber of HRP Frames in File:\t\t\t%d\n", $MNF_HRP );
         printf("\tNumber of Perfect Frames in File:\t\t%d\n", &Swap_Number($MNF_PFCT, 4) );
         printf("\tNumber of Fill Frames in File:\t\t\t%d\n", &Swap_Number($MNF_FILL, 4) );
         printf("\tNumber of Frames Containing Mode Change:\t%d\n", &Swap_Number($MNFM, 4) );
         printf("\tNumber of Frames Containing Mode Bit Errors:\t%d\n", &Swap_Number($MNFM_ERR, 4) );
         printf("\tNumber of Frames Counter Errors:\t\t%d\n", &Swap_Number($MNFC_ERR, 4) );
         printf("\tNumber of Frames Containing HRP Counter Errors:\t%d\n", &Swap_Number($HRP_ERR, 4) );
         printf("\tNumber of Frames Containing FSW Error:\t\t%d\n", &Swap_Number($MNF_FSE, 4) );
         printf("\tIPASS Program Version Number:\t\t\t%s\n", $IPASS_VER);
         printf("\tIPASS Program Run Date/Time:\t\t\t%s\n", $IPASS_TIME);
         printf("\tIPASS Rerun Number:\t\t\t\t%d\n", &Swap_Number($IPASS_RERUN, 4) );
         printf("\tExperiment File Name:\t\t\t\t%s\n", $EXP_NAME);
         printf("\tSFDU File Name:\t\t\t\t\t%s\n", $SFD_NAME);
         printf("\tTime Processing Flag:\t\t\t\t\t%s\n", $TIME_TYPE[&Swap_Number($TIME_FLAG, 4)]);
         printf("\tIPASS Run Type:\t\t\t\t\t%s\n", $IPASS_TYPE);
         printf("\tExperiment File Version Number:\t\t\t%d\n", &Swap_Number($FILE_SEQ, 4) );
    }
}

sub PWIW_PRT {

     local ($REC) = @_;

     ($PHYS_NUM, $MNFC, $HRPC, $TIME, $RAW_TIME, $NUM_WBR, $NUM_HRP, $NUM_MNF, $NUM_PFCT,
      $NUM_FILL, $NUM_MODE, $NUM_MODE_ERR, $NUM_MNFC_ERR, $NUM_HRPC_ERR, $NUM_FSWE) =
                        unpack("L1 L1 L1 a8 a8 L1 L1 L1 L1 x8 L1 L1 L1 L1 L1 L1", $REC);

     $PHYS_NUM = &Swap_Number($PHYS_NUM, 4);
     $NUM_MNF = &Swap_Number($NUM_MNF, 4);
     $NUM_FILL = &Swap_Number($NUM_FILL, 4);
     $NUM_MODE = &Swap_Number($NUM_MODE, 4);
     $NUM_MODE_ERR = &Swap_Number($NUM_MODE_ERR, 4);
     $NUM_MNFC_ERR = &Swap_Number($NUM_MNFC_ERR, 4);
     $NUM_HRPC_ERR = &Swap_Number($NUM_HRPC_ERR, 4);
     $NUM_FSWE = &Swap_Number($NUM_FSWE, 4);

     if( $LONG && ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) {
     		printf("\t%5d  ", &Swap_Number($PHYS_NUM, 4));
     		printf("%4d  ", &Swap_Number($MNFC, 4));
     		printf("%4d  ", &Swap_Number($$HRPC, 4));
     		printf("%4d  %3d  %7d  ", unpack("S1 S1 L1", &Swap_Time($TIME)) );
     		printf("%s  ", unpack("H64", $RAW_TIME));
     		printf("%4d  ", &Swap_Number($NUM_WBR, 4));
     		printf("%4d  ", &Swap_Number($NUM_HRP, 4));
     		printf("%4d  ", $NUM_MNF);
     		printf("%5d  ", &Swap_Number($NUM_PFCT, 4));
     		printf("%5d  ", $NUM_FILL);
     		printf("%9d  ", $NUM_MODE);
     		printf("%9d  ", $NUM_MODE_ERR);
     		printf("%8d  ", $NUM_MNFC_ERR, 4);
     		printf("%12d  ", $NUM_HRPC_ERR);
     		printf("%4d\n", $NUM_FSWE);
     }

     if( ($HEX || $OLINE) && ($PHYS_NUM >= $BEGREC) && ($PHYS_NUM <= $ENDREC) ) 
     {
     		for($J=1; $J<$NUM_MNF; $J++)
                {
                        $RB += sysread(IN, $REC, 264);
                        printf("\n\t\t\tPHYSICAL MINOR %d in RECORD\n", $J);
                        HEXPRT($REC, 264);
                }
      }

}


sub isPOLAR {
   local ($FNAME) = @_;

   if($MY_SAT eq "")
   {
       ($FNAME, $REMAINDER) = split(/\//, reverse $FNAME);
       ($MY_SAT, $REMAINDER) = split(/_/, reverse $FNAME);
       if($MY_SAT ne "POLAR" && $MY_SAT ne "WIND")
       {
	    while( ($MY_SAT ne "P" and $MY_SAT ne "p") and ($MY_SAT ne "W" and $MY_SAT ne "w"))
	    {
	    	print "\t\tCan't distinguish POLAR or WIND\n";
	    	print "\t\tEnter satellite name (P or W): ";
	    	$MY_SAT = <STDIN> ;
	    	chop($MY_SAT);
	    }
	    if( $MY_SAT eq "P" || $MY_SAT eq "p") { $MY_SAT = "POLAR"; }
	    else {$MY_SAT = "WIND"; }
       }
   }
   return ($MY_SAT eq "POLAR");
}

sub isPWIW {
   local ($FNAME, $MISSION, $PDF) = @_;

   ($FNAME, $REMAINDER) = split(/\//, reverse $FNAME);
   ($MISSION, $PDF, $REMAINDER) = split(/_/, reverse $FNAME);
 
   if($PDF eq "GG" || $PDF eq "GI") { return 1; }
   else { return 0; }
}

sub get_SESSION_PATH {
   local ($FNAME) = @_;
   my ($tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $REMAINDER);

   ($CURRPATH, $REMAINDER) = split(/du/, $FNAME);

   if($CURRPATH eq "") { $CURRPATH = "./"; $FNAME = `pwd`;}

   ($tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $SESSION) = split(/\//, $FNAME);

   $SESSION = sprintf("%d", $SESSION);

}

sub toASCII {
   local ( $REC ) = @_;

   #	      0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f 
   @ASCII = ( 00,  00,  00,  00,  00,  00,  00, 128,  00,  00,  00,  00,  00,  00,  00,  00,	# 0
	      00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,	# 1
	      00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,	# 2
	      00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,	# 3
	      32,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  46,  60,  40,  43,  00,	# 4
	      38,  00,  00,  00,  00,  00,  00,  00,  00,  00,  33,  36,  42,  41,  59,  00,	# 5
	      45,  47,  00,  00,  00,  00,  00,  00,  00,  00,  00,  44,  37,  95,  62,  63,	# 6
	      00,  00,  00,  00,  00,  00,  00,  00,  00,  96,  58,  35,  64,  39,  61,  34,	# 7
	      00,  97,  98,  99, 100, 101, 102, 103, 104, 105,  00,  00,  00,  00,  00,  00,	# 8
	      00, 106, 107, 108, 109, 110, 111, 112, 113, 114,  00,  00,  00,  00,  00,  00,	# 9
	      00, 115, 116, 117, 118, 119, 120, 121, 122, 123,  00,  00,  00,  91,  00,  00,	# a
	      00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  00,  93,  00,  00,	# b
	     124,  65,  66,  67,  68,  69,  70,  71,  72,  73,  00,  00,  00,  00,  00,  00,	# c
	     126,  74,  75,  76,  77,  78,  79,  80,  81,  82,  00,  00,  00,  00,  00,  00,	# d
	      92,  00,  83,  84,  85,  86,  87,  88,  89,  90,  00,  00,  00,  00,  00,  00,	# e
	      48,  49,  50,  51,  52,  53,  54,  55,  56,  57, 125,  00,  00,  00,  00,  00);	# f

   $LEN = length($REC);

   @CHARS = unpack("C$LEN", $REC);

   foreach $CHAR (@CHARS) {
	$CHAR = $ASCII[$CHAR];
   }

   $REC = pack("C$LEN", @CHARS);

   return $REC;
}

sub YMDtoJD {
    local ($YMD) = @_;
    local ($a, $b, $c, $i, $j, $k, $l, $jd);

    $a = int($YMD/10000);
    $b = int($YMD / 100);
    $c = int($YMD);
    $i = $a;
    $j = $b-100*$a;
    $k = $c-100*$j-10000*$a;
    $l = int(($j-14)/12);
    $jd = $k-32075+int(1461*($i+4800+$l)/4);
    $jd = $jd+int(367*($j-2-$l*12)/12);
    $jd = $jd-int(3*int(($i+4900+$l)/100)/4);

    return $jd;
}

sub JDtoYMD {
    local ($JD) = @_;
    local ($l, $n, $m, $i, $o, $j, $k, $l, $j, $i, $cd);
 
    $l = $JD+68569;
    $n = int(4*$l/146097);
    $m = $l-int((146097*$n+3)/4);
    $i = int(4000*($m+1)/1461001);
    $o = $m-int(1461*$i/4)+31;
    $j = int(80*$o/2447);
    $k = $o-int(2447*$j/80);
    $l = int($j/11);
    $j = $j+2-12*$l;
    $i = 100*($n-49)+$i+$l;
    $cd = 10000*$i+100*$j+$k;
 
    return $cd;
}

sub JDtoDOY {
    local ($JAN1, $YMD) = @_;

    return (&YMDtoJD($YMD) - &YMDtoJD($JAN1) + 1);
}

sub ydmu2UTC {
    local ($yr, $doy, $moday, $uomsec) = @_;
    my ($uoday, $secoday, $nsecoday, $hr, $mn, $seco, $uosec, $subsecs, $jan1);
    my ($jan1JD, $jan1904JD, $days1904, $sec1904, $FPsec);
    #printf("Received: %d %3d %6d %3d\n", $yr, $doy, $moday, $uomsec);

    $uoday=$moday*1000+$uomsec;
    $secoday=int(&bdiv($uoday, 1000000));
    $nsecoday=$secoday;
    $hr=int($secoday/3600);
    $mn=int(($secoday-$hr*3600)/60);
    $seco=int($secoday-$hr*3600-$mn*6);

    $uosec=int(&bmod($uoday,1000000));
    $subsecs=$uosec/1000000;
    $jan1=$yr*10000+101;

    $jan1JD = &YMDtoJD($jan1);
    $jan1904 = &YMDtoJD(19040101.00);
    $days1904 = $jan1JD-$jan1904+$doy-1;
    $sec1904=$days1904*86400+$nsecoday;
    $FPsec=$sec1904+$subsecs;

    #printf("FP = %f\n", $FPsec);
    return $FPsec;
}

sub str2FP {
    local ($STR_IN) = @_;
    my($YR, $DY, $HR, $MM, $SEC, $USEC, $MILLI, $UOMSEC, $MSECODAY, $FP);

    $YR = sprintf("%d", substr($STR_IN, 0, 4));
    $DY = sprintf("%d", substr($STR_IN, 4, 3));
    $HR = sprintf("%d", substr($STR_IN, 8, 2));
    $MM = sprintf("%d", substr($STR_IN, 10, 2));
    $SEC = sprintf("%d", substr($STR_IN, 12, 2));
    $USEC = sprintf("%d", substr($STR_IN, 15, 6));

    if( ($YR >= 1970 && $YR < 2038) && ($DY >= 1 && $DY < 367) &&
        ($HR >= 0 && $HR < 24) && ($MM >=0 && $MM < 60) &&
        ($SEC >= 0 && $SEC < 60) && ($USEC >= 0 && $USEC < 1000000) )
    {

        $MILLI = int($USEC/1000);
        $UOMSEC = $USEC%1000;
        $MSECODAY = $MILLI+$SEC*1000+$MM*60000+$HR*3600000;

        $FP = &ydmu2UTC($YR, $DY, $MSECODAY, $UOMSEC);
    }
    else { printf("Invalid date/time string\n"); $FP = -1;}

    return $FP;
}

sub FP2str {
    local ($FP_IN) = @_;
    my ($STR, $JD, $ND, $JDMJF, $SD, $MSOD, $NS, $hr, $mn, $SS, $FS);
    my ($jan1, $YD, $HMS, $SEC, $DOY, $USEC);


    $JD = &YMDtoJD(19040101.00);
    $ND = int($FP_IN/86400);
    $JDMJF = $JD + $ND;
    $SD = $FP_IN - $ND*86400;
    $MSOD = int(&bmul($SD*1000));
    $NS = int($SD);
    $hr = int($NS/3600);
    $mn = int(($NS-$hr*3600)/60);
    $SS = $NS-$hr*3600-$mn*60;
    $FS= fround($SD-$NS, 6);

    $YMD = &JDtoYMD($JDMJF);
    $YR = sprintf("%d", substr($YMD, 0, 4));
    $MO = sprintf("%d", substr($YMD, 4, 2));
    $DY = sprintf("%d", substr($YMD, 6, 2));
    $jan1 = ($YR*10000)+101;

    $DOY = &JDtoDOY($jan1, $YMD);
    $YD = $YR*1000+$DOY;
    $HMS = $hr*10000+$mn*100+$SS;
    $SEC = int($FS*1000000);

    $STR = sprintf("%07u.%06u.%06u", $YD, $HMS, $SEC);

    return $STR;
}


#########################################################################
#		Do PRODUCT comparison until end of file
#
#######################################################################

sub PROD_DIFF{
    print "************* PDIFF FOR PRODUCT IS NOT SUPPORTED FOR NOW. ****************\n";
}

#########################################################################
#		Do FRM comparison until end of file
#
#######################################################################


sub FRM_DIFF{
   local($MFN_A, $MFN_B) ;

   $RECNUM_A = $RECNUM_B = $PRT_RECNUM_A = $PRT_RECNUM_B = 1;
   $MFN_BIT1_A = $MFN_BIT1_B = 0;
   $NUM_FRM_READ_A = $NUM_FRM_READ_B = 1;
   $NOT_CONVERTED_A = $NOT_CONVERTED_B = 1;
   $CURR_MFN_A = $CURR_MFN_B = 0;
   print "\n";

   while( ($RECNUM_B <= $R_TOT_B) || ($RECNUM_A <= $R_TOT_A) )
   {
	# Reverse bits and arrange FSW location to make it looks same as LZP format
	if($DATA_TYPE_A eq "TLZP" && $NOT_CONVERTED_A) { $REC_A = &TIPITtoLZP($REC_A); $NOT_CONVERTED_A = 0;}
	if($DATA_TYPE_B eq "TLZP" && $NOT_CONVERTED_B) { $REC_B = &TIPITtoLZP($REC_B); $NOT_CONVERTED_B = 0;}

	if($REC_A) {($SYNC_A, $MFN_A, @DATA_A) = unpack( "L1 X C1 C10 ", $REC_A) } ;
        if($REC_B) {($SYNC_B, $MFN_B, @DATA_B) = unpack( "L1 X C1 C10 ", $REC_B) } ;
	$CURR_MFN_A = $MFN_A; $CURR_MFN_B = $MFN_B;

	if($SAT eq "GEOTAIL") { $MFN_A |= $MFN_BIT1_A; $MFN_B |= $MFN_BIT1_B; }

	if($SAT eq "WIND/POLAR")
        {
            if( isPOLAR($FILENAME[$CURRFILE]) )                                 # POLAR
            {
                # Report major frame count
                if( $MFN_A%25 == 1 ) { $PREV_MAJNUM_A = $MAJNUM_A; $MAJNUM_A = $DATA_A[ 0 ] ;}
  
                if( $MFN_B%25 == 1 ) { $PREV_MAJNUM_B = $MAJNUM_B; $MAJNUM_B = $DATA_B[ 0 ] ; }

		# collect pieces of PB5 time from proper frames
                if( ( $MFN_A- 6 ) %125 == 0 ) { $PB5_A[0] = $DATA_A[0];}
                if( ( $MFN_A- 7 ) %125 == 0 ) { $PB5_A[1] = $DATA_A[0];}
                if( ( $MFN_A-11 ) %125 == 0 ) { $PB5_A[2] = $DATA_A[0];}
                if( ( $MFN_A-12 ) %125 == 0 ) { $PB5_A[3] = $DATA_A[0];}
                if( ( $MFN_A-16 ) %125 == 0 ) { $PB5_A[4] = $DATA_A[0];}
                if( ( $MFN_A-17 ) %125 == 0 ) { $PB5_A[5] = $DATA_A[0];}
                if( $MFN_A >= 17 && $MFN_A%125 == 0) 
		{ 
			$MNF_TIME_A = PB5_STR(@PB5_A); 
			$TIME_NUM_A = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5;
			#$TIME_NUM_A = int($TIME_NUM);
		}

                if( ( $MFN_B- 6 ) %125 == 0 ) { $PB5_B[0] = $DATA_B[0];}
                if( ( $MFN_B- 7 ) %125 == 0 ) { $PB5_B[1] = $DATA_B[0];}
                if( ( $MFN_B-11 ) %125 == 0 ) { $PB5_B[2] = $DATA_B[0];}
                if( ( $MFN_B-12 ) %125 == 0 ) { $PB5_B[3] = $DATA_B[0];}
                if( ( $MFN_B-16 ) %125 == 0 ) { $PB5_B[4] = $DATA_B[0];}
                if( ( $MFN_B-17 ) %125 == 0 ) { $PB5_B[5] = $DATA_B[0];}
                if( $MFN_B >= 17 && $MFN_B % 125 == 0) 
		{ 
			$MNF_TIME_B = PB5_STR(@PB5_B); 
			$TIME_NUM_B = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5;
			#$TIME_NUM_B = int($TIME_NUM);
		}
            }
            else                                                                # WIND
            {
                # Report major frame count
                if( $MFN_A%25 == 0 ) { $PREV_MAJNUM_A = $MAJNUM_A; $MAJNUM_A = $DATA_A[ 1 ] ; }
  
                if( $MFN_B%25 == 0 ) { $PREV_MAJNUM_B = $MAJNUM_B; $MAJNUM_B = $DATA_B[ 1 ] ; }

		# collect pieces of PB5 time from proper frames
                if( ( $MFN_A-4 ) %25 == 0 ) { $PB5_A[0] = $DATA_A[0];  $PB5_A[1] = $DATA_A[1]; }
                if( ( $MFN_A-9 ) %25 == 0 ) { $PB5_A[2] = $DATA_A[0];  $PB5_A[3] = $DATA_A[1]; }
                if( ( $MFN_A-14) %25 == 0 ) { $PB5_A[4] = $DATA_A[0];  $PB5_A[5] = $DATA_A[1]; }
                if( $MFN_A >= 14 && ($MFN_A-14) %25 == 0 ) 
		{ 
			$MNF_TIME_A = PB5_STR(@PB5_A); 
			$TIME_NUM_A = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5;
		}

                if( ( $MFN_B-4 ) %25 == 0 ) { $PB5_B[0] = $DATA_B[0];  $PB5_B[1] = $DATA_B[1]; }
                if( ( $MFN_B-9 ) %25 == 0 ) { $PB5_B[2] = $DATA_B[0];  $PB5_B[3] = $DATA_B[1]; }
                if( ( $MFN_B-14) %25 == 0 ) { $PB5_B[4] = $DATA_B[0];  $PB5_B[5] = $DATA_B[1]; }
                if( $MFN_B >= 14 && ($MFN_B-14)%25 == 0) 
		{ 
			$MNF_TIME_B = PB5_STR(@PB5_B); 
			$TIME_NUM_B = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5;
		}
            }
        }
        elsif( $SAT eq "GEOTAIL")
        {
		# Report major frame count
                if( $MFN_A%32==0 ) { 
				     $PREV_MAJNUM_A = $MAJNUM_A;
				     $MAJNUM_A = ($DATA_A[ 6 ] & 0x0f) >> 1; 
				     $MFN_BIT1_A = ($DATA_A[ 6 ] & 0x01) << 8 ;
				     $MFN_A |= $MFN_BIT1_A; 
				   }
  
                if( $MFN_B%32==0 ) { 
				     $PREV_MAJNUM_B = $MAJNUM_B;
				     $MAJNUM_B = ($DATA_B[ 6 ] & 0x0f) >> 1; 
				     $MFN_BIT1_B = ($DATA_B[ 6 ] & 0x01) << 8 ;
				     $MFN_B |= $MFN_BIT1_B; 
				   }

		# collect pieces of PB5 time from proper frames
		$PB5_A[$MAJNUM_A %4] = $DATA_A[0];
                if( $MFN_A %4 == 0) {$TIME_NUM_A = $MNF_TIME_A = unpack("L1", pack("C4", @PB5_A)); }

                $PB5_B[$MAJNUM_B %4] = $DATA_B[0];
                if( $MFN_B %4 == 0) {$TIME_NUM_B = $MNF_TIME_B = unpack("L1", pack("C4", @PB5_B)); }
        }

	# File B has more frame than file A
	if($RECNUM_A > $R_TOT_A) {
		if($RTPB eq "RT") { $TIME_NUM_A = "99999999999999"; }
		else		  { $TIME_NUM_A = "0"; }
	}
	# File A has more frame than file B
	if($RECNUM_B > $R_TOT_B) {
		if($RTPB eq "RT") { $TIME_NUM_B = "99999999999999"; }
		else		  { $TIME_NUM_B = "0"; }
	}

	if( ($RECNUM_A <= $R_TOT_A) && (($RTPB eq "RT" && $TIME_NUM_A < $TIME_NUM_B) || 
					($RTPB eq "PB" && $TIME_NUM_A > $TIME_NUM_B)) )
	{
	    if($OLINE || $LONG) {
		$TITLE_DONE = 1;
		$MFN = $MFN_A;
		print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ; 
		print "A   <";
		&FRM_PRT($REC_A, $RECNUM_A, $MAJNUM_A, $MODE_A, $MNF_TIME_A, "FRM in A not in B");
	    }
	    if($DATA_TYPE_A eq "TLZP") {
		if($NUM_FRM_READ_A % $FRM_IN_BLK{$SAT} == 0) 
			{ $RB_A += sysread(A_IN, $REC_A, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_A = 1;}
	    }
	    $RB_A += sysread( A_IN, $REC_A, $ReadLen); 
	    $RECNUM_A++; 
	    $NOT_CONVERTED_A = 1;
	    $MSG = "FRM IN A NOT IN B \n\n";
	    $A_NOT_IN_B++;
	    $NUM_FRM_READ_A++;
	}

	if( ($RECNUM_B <= $R_TOT_B) && (($RTPB eq "RT" && $TIME_NUM_A > $TIME_NUM_B) || 
					($RTPB eq "PB" && $TIME_NUM_A < $TIME_NUM_B)) )
	{
	    if($OLINE || $LONG) {
		$TITLE_DONE = 1;
		$MFN = $MFN_B;
		print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ; 
		print "B   >";
		&FRM_PRT($REC_B, $RECNUM_B, $MAJNUM_B, $MODE_B, $MNF_TIME_B, "FRM in B not in A");
	    }
	    if($DATA_TYPE_B eq "TLZP") {
                if($NUM_FRM_READ_B % $FRM_IN_BLK{$SAT} == 0)
                        { $RB_B += sysread(B_IN, $REC_B, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_B = 1;}
            }
	    $RB_B += sysread( B_IN, $REC_B, $ReadLen); 
	    $RECNUM_B++;
	    $NOT_CONVERTED_B = 1;
	    $MSG = sprintf("FRM IN B NOT IN A \n\n");
	    $B_NOT_IN_A++;
	    $NUM_FRM_READ_B++;
	}

	if( $TIME_NUM_A == $TIME_NUM_B )
	{
		$UFRMLEN = $R_DAT_LEN + $R_RS_LEN ;
    		if( $DATA_TYPE_A eq "TLZP" ) { 		
			$ANN = substr( $REC_A , $UFRMLEN, 8 ) ;
	 		&ANN_SPLIT($ANN);
			if($FLG >= 0x0700) { 
			    if($RTPB eq "PB") {$MFN_A = 999;}
			    else 	      {$MFN_A = -999;}
			    $MAJNUM_A = $MAJNUM_B; }
    		}
    		if( $DATA_TYPE_B eq "TLZP" ) { 		
			$ANN = substr( $REC_B , $UFRMLEN, 8 ) ;
	 		&ANN_SPLIT($ANN);
			if($FLG >= 0x0700) { 
			   if($RTPB eq "PB") { $MFN_B = 999; }
			   else		     { $MFN_B = -999; }
			   $MAJNUM_B = $MAJNUM_A; }
    		}

		if( ($RECNUM_A <= $R_TOT_A) && (($RTPB eq "RT" && $MAJNUM_A < $MAJNUM_B) || 
						($RTPB eq "PB" && $MAJNUM_A > $MAJNUM_B)) )
        	{
            	    if($OLINE || $LONG) {
                	$TITLE_DONE = 1;
                	$MFN = $MFN_A;
                	print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ;
                	print "A   <";
                	&FRM_PRT($REC_A, $RECNUM_A, $MAJNUM_A, $MODE_A, $MNF_TIME_A, "FRM in A not in B");
            	    }
		    if($DATA_TYPE_A eq "TLZP") {
                	if($NUM_FRM_READ_A % $FRM_IN_BLK{$SAT} == 0)
                        	{ $RB_A += sysread(A_IN, $REC_A, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_A = 1;}
            	    }
            	    $RB_A += sysread( A_IN, $REC_A, $ReadLen); 
		    $RECNUM_A++;
		    $NOT_CONVERTED_A = 1;
		    $MSG = "FRM IN A NOT IN B \n\n";
            	    $A_NOT_IN_B++;
		    $NUM_FRM_READ_A++;
        	}
		elsif( ($RECNUM_B <= $R_TOT_B) && (($RTPB eq "RT" && $MAJNUM_A > $MAJNUM_B) || 
						   ($RTPB eq "PB" && $MAJNUM_A < $MAJNUM_B)) )
        	{
            	    if($OLINE || $LONG) {
                	$TITLE_DONE = 1;
                	$MFN = $MFN_B;
                	print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ;
                	print "B   >";
                	&FRM_PRT($REC_B, $RECNUM_B, $MAJNUM_B, $MODE_B, $MNF_TIME_B, "FRM in B not in A");
            	    }
		    if($DATA_TYPE_B eq "TLZP") {
                    	if($NUM_FRM_READ_B % $FRM_IN_BLK{$SAT} == 0)
                            	{ $RB_B += sysread(B_IN, $REC_B, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_B = 1;}
                    }
            	    $RB_B += sysread( B_IN, $REC_B, $ReadLen); 
		    $RECNUM_B++;
		    $NOT_CONVERTED_B = 1;
		    $MSG = "FRM IN B NOT IN A \n\n";
            	    $B_NOT_IN_A++;
		    $NUM_FRM_READ_B++;
        	}
		else 	# MAJNUM_A == $MAJNUM_B
		{
		    if ( ($RECNUM_A <= $R_TOT_A) && (($RTPB eq "RT" && $MFN_A < $MFN_B) || 
						     ($RTPB eq "PB" && $MFN_B < $MFN_A)) )
                    {
                    	if($OLINE || $LONG) {
                        	print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ;
                        	print "A   <";
                        	$TITLE_DONE = 1;
                        	$MFN = $MFN_A;
                        	&FRM_PRT($REC_A, $RECNUM_A, $MAJNUM_A, $MODE_A, $MNF_TIME_A, "FRM in A not in B");
                    	}
                    	$A_NOT_IN_B++;
			$MSG = "FRM IN A NOT IN B \n\n";
			if($DATA_TYPE_A eq "TLZP") {
                        	if($NUM_FRM_READ_A % $FRM_IN_BLK{$SAT} == 0)
                                	{ $RB_A += sysread(A_IN, $REC_A, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_A= 1;}
                        }
                    	$RB_A += sysread( A_IN, $REC_A, $ReadLen); 
			$RECNUM_A++;
			$NOT_CONVERTED_A = 1;
			$NUM_FRM_READ_A++;
                    }
		    elsif( ($RECNUM_B <= $R_TOT_B) && (($RTPB eq "RT" && $MFN_A > $MFN_B) || 
						       ($RTPB eq "PB" && $MFN_B > $MFN_A)) )
                    {
                   	if($OLINE || $LONG) {
                        	print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ;
                        	print "B   >";
                        	$TITLE_DONE = 1;
                        	$MFN = $MFN_B;
                        	&FRM_PRT($REC_B, $RECNUM_B, $MAJNUM_B, $MODE_B, $MNF_TIME_B, "FRM in B not in A");
                   	}
			$MSG = "FRM IN B NOT IN A \n\n";
                   	$B_NOT_IN_A++;
			if($DATA_TYPE_B eq "TLZP") {
                        	if($NUM_FRM_READ_B % $FRM_IN_BLK{$SAT} == 0)
                                	{ $RB_B += sysread(B_IN, $REC_B, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_B = 1;}
                    	}
                   	$RB_B += sysread( B_IN, $REC_B, $ReadLen); 
			$RECNUM_B++;
			$NOT_CONVERTED_B = 1;
			$NUM_FRM_READ_B++;
                    }
		    else  # $MFN_A == $MFN_B
		    {
			$PAYLOAD_A = substr($REC_A, 0, $R_DAT_LEN);
			$PAYLOAD_B = substr($REC_B, 0, $R_DAT_LEN);
			if($PAYLOAD_A ne $PAYLOAD_B)
			{
			    if($OLINE || $LONG || $HEX) {
				print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ; 
				print "A   <";
                		$TITLE_DONE = 1;
				$MFN = $MFN_A;
				&FRM_PRT($REC_A, $RECNUM_A, $MAJNUM_A, $MODE_A, $MNF_TIME_A, "FRM in A not same as in B");
				if($HEX) { &HEXPRT($REC_A, length($REC_A)); }
				print "B   >";
				$MFN = $MFN_B;
				&FRM_PRT($REC_B, $RECNUM_B, $MAJNUM_B, $MODE_B, $MNF_TIME_B, "FRM in B not same as in A");
				if($HEX) { &HEXPRT($REC_B, length($REC_B)); }
			    }
			    $MSG = "PAYLOAD DIFFERENT \n\n";
			    $A_DIFF_B++;
			}
			else 
			{ 
			    if(0) {
                                print "\n       Seq.   Maj/Min Mode SYNC    Data ---$TIME_TITLE-------- FLG  Ground Time\n" ;
                                print "A   <";
                                $TITLE_DONE = 1;
                                $MFN = $MFN_A;
                                &FRM_PRT($REC_A, $RECNUM_A, $MAJNUM_A, $MODE_A, $MNF_TIME_A, "FRM in A same as in B");
				if($HEX) { &HEXPRT($REC_A, length($REC_A)); }
                                print "B   >";
                                $MFN = $MFN_B;
                                &FRM_PRT($REC_B, $RECNUM_B, $MAJNUM_B, $MODE_B, $MNF_TIME_B, "FRM in B same as in A");
				if($HEX) { &HEXPRT($REC_B, length($REC_B)); }
			    }
			    $MSG = "SAME CONTENT ";
			    $SHOWRUN = 1;
			    $A_SAME_B++; 
			}

			if($DATA_TYPE_A eq "TLZP") {
                                if($NUM_FRM_READ_A % $FRM_IN_BLK{$SAT} == 0)
                                        { $RB_A += sysread(A_IN, $REC_A, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_A = 1;}
                        }
			$RB_A += sysread( A_IN, $REC_A, $ReadLen); 
			$RECNUM_A++; $NUM_FRM_READ_A++;
			$NOT_CONVERTED_A = 1;

			if($DATA_TYPE_B eq "TLZP") {
                                if($NUM_FRM_READ_B % $FRM_IN_BLK{$SAT} == 0)
                                        { $RB_B += sysread(B_IN, $REC_B, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); $NOT_CONVERTED_A = 1;}
                        }
			$RB_B += sysread( B_IN, $REC_B, $ReadLen); 
			$RECNUM_B++; $NUM_FRM_READ_B++;
			$NOT_CONVERTED_B = 1;
		    } # minc a = minc b
		} # majc a = maj b
	 } # time_a = time_b
	 if( (not defined $LONG) && (not defined $OLINE) && (not defined $HEX) || $SHOWRUN)
	 {
		if($VERBOSE) { 
			$ROW_FORMAT = sprintf($C_ROWS, $ROWS-1); $G_CODE = $C_OPEN; 

			$DISPLAY = sprintf("%s%sCompare:  FILE A Seq# %6d (%3d/%3d)      |      FILE B Seq# %6d (%3d/%3d) : %20s ", 
				$G_CODE, $ROW_FORMAT, $PRT_RECNUM_A, $MAJNUM_A, $CURR_MFN_A, 
				$PRT_RECNUM_B, $MAJNUM_B, $CURR_MFN_B, $MSG);
			syswrite(STDERR, $DISPLAY, length($DISPLAY));
		}
		
		$PRT_RECNUM_A = $RECNUM_A;
		$PRT_RECNUM_B = $RECNUM_B;
		$SHOWRUN = 0;
		$MSG = "";
	 }
   } # while

}


sub FRM_PRE_SCAN 
{
   undef @PB5_B; undef @PB5_A;
  
   $START_TIME_A = $START_TIME_B = 0;
   $MJFC_A =  $MJFC_B = -9999;
   $FOUND_A = $FOUND_B = 0;
   $PRE_SKIP = 0;
   $NUM_FRM_READ_A = $NUM_FRM_READ_B = 1;

   print "\nSTART PRESCAN\n";
   print "     Prescan record  # \n";

   $RS = seek( A_IN, 0, 0 ) ;
   $RS = seek( B_IN, 0, 0 ) ;

   $RB_A += sysread( A_IN, $PRE_REC_A, 600);
   $RB_B += sysread( B_IN, $PRE_REC_B, 600); 
   
   if( $DATA_TYPE_A eq "TLZP" && &Garbage_Loc($PRE_REC_A,  64) )  
   {
	$RS = seek(A_IN, 600, 0);
   }
   else { $RS = seek( A_IN, 0, 0 ) ; }
   
   if( $DATA_TYPE_B eq "TLZP" && &Garbage_Loc($PRE_REC_B,  64) )
   {
	$RS = seek(B_IN, 600, 0);
   }
   else { $RS = seek( B_IN, 0, 0 ) ; }

   if($DATA_TYPE_A eq "TLZP") {  # Read off block header if TLZP
       $RB_A = sysread( A_IN, $PRE_REC_A, 12 ); 
   }
   $RB_A = sysread( A_IN, $PRE_REC_A, $ReadLen) ;

   if($DATA_TYPE_B eq "TLZP") {  # Read off block header if TLZP
       $RB_B = sysread( B_IN, $PRE_REC_B, 12 ); 
   }
   $RB_B = sysread( B_IN, $PRE_REC_B, $ReadLen) ;
   $RECNUM = 0;

   $MFN_SKIP_A = 0;
   $MFN_SKIP_B = 0;
   while( ($PRE_REC_A && $PRE_REC_B)  && ((not $FOUND_A) || (not $FOUND_B) || (not $START_TIME_A) || (not $START_TIME_B)) )
   {
	$RECNUM++;
	if($VERBOSE) {
		$ROW_FORMAT = sprintf($C_ROWS, $ROWS-1);
		$COL_FORMAT = sprintf($C_COLS, 23);
		$DISPLAY = sprintf("%s%s%s%d ", $C_OPEN, $ROW_FORMAT, $COL_FORMAT, $RECNUM);
		syswrite(STDERR, $DISPLAY, length($DISPLAY));
	}

	# Reverse bits and arrange FSW location to make it looks same as LZP format
        if($DATA_TYPE_A eq "TLZP") { $PRE_REC_A = &TIPITtoLZP($PRE_REC_A); }
        if($DATA_TYPE_B eq "TLZP") { $PRE_REC_B = &TIPITtoLZP($PRE_REC_B); }

	($SYNC_A, $MFN_A, @DATA_A) = unpack( "L1 X C1 C10 ", $PRE_REC_A) ;
	if(not $PREV_MFN_A) { $PREV_MFN_A = $MFN_A };
	($SYNC_B, $MFN_B, @DATA_B) = unpack( "L1 X C1 C10 ", $PRE_REC_B) ;
	if(not $PREV_MFN_B) { $PREV_MFN_B = $MFN_B };

	# Check RollOver
	if($RTPB eq "RT") 
	{
	       if( $PREV_MFN_A-$MFN_A > 200 || $PREV_MFN_A-$MFN_A < -200 || $MFN_A == 0) { $Roll_Over_A ++; }
	       if( $PREV_MFN_B-$MFN_B > 200 || $PREV_MFN_B-$MFN_B < -200 || $MFN_B == 0) { $Roll_Over_B ++; }
	} 
	if($RTPB eq "PB") 
	{
	       if( $MFN_A-$PREV_MFN_A > 200 || $MFN_A-$PREV_MFN_A < -200 || $MFN_A == 0) { $Roll_Over_A ++; }
	       if( $MFN_B-$PREV_MFN_B > 200 || $MFN_B-$PREV_MFN_B < -200 || $MFN_B == 0) { $Roll_Over_B ++; } 
	}
	$PREV_MFN_A = $MFN_A; 
	$PREV_MFN_B = $MFN_B; 
	
	# Report MJFC
	if($RECNUM >= $PRE_SKIP)
	{
	   if($MFN_A ) { $PRE_START_A = 1; }
	   if(not $FOUND_A) { $MFN_SKIP_A++; }
	   if($MFN_B ) { $PRE_START_B = 1; }
	   if(not $FOUND_B) { $MFN_SKIP_B++; }

           if($SAT eq "WIND/POLAR")
           {
                if( isPOLAR($FILENAME[$CURRFILE]) )                                 # POLAR
                {
                      # Report major frame count
                      if( (not $FOUND_A) && $MFN_A%25 == 1 ) { $MJFC_A = $DATA_A[ 0 ] ; $FOUND_A++; }
   
                      if( (not $FOUND_B) && $MFN_B%25 == 1 ) { $MJFC_B = $DATA_B[ 0 ] ; $FOUND_B++; }

		      # collect pieces of PB5 time from proper frames
                      if( ( $MFN_A-6 ) %125 == 0 ) { $PB5_A[0] = $DATA_A[0];}
                      if( ( $MFN_A-7 ) %125 == 0 ) { $PB5_A[1] = $DATA_A[0];}
                      if( ( $MFN_A-11 ) %125 == 0 ) { $PB5_A[2] = $DATA_A[0];}
                      if( ( $MFN_A-12 ) %125 == 0 ) { $PB5_A[3] = $DATA_A[0];}
                      if( ( $MFN_A-16 ) %125 == 0 ) { $PB5_A[4] = $DATA_A[0];}
                      if( ( $MFN_A-17 ) %125 == 0 ) { $PB5_A[5] = $DATA_A[0];}
		      if( $RECNUM > 25 && $MFN_A%17 == 0 && $START_TIME_A == 0) { 
			 	$MNF_TIME_A = PB5_STR(@PB5_A); 
				if($DOY5<=366 && $DOY5 > 0 && $SOD5 > 0) {$START_TIME_A++; }
				$TIME_NUM_A = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5; }

                      if( ( $MFN_B-6 ) %125 == 0 ) { $PB5_B[0] = $DATA_B[0];}
                      if( ( $MFN_B-7 ) %125 == 0 ) { $PB5_B[1] = $DATA_B[0];}
                      if( ( $MFN_B-11 ) %125 == 0 ) { $PB5_B[2] = $DATA_B[0];}
                      if( ( $MFN_B-12 ) %125 == 0 ) { $PB5_B[3] = $DATA_B[0];}
                      if( ( $MFN_B-16 ) %125 == 0 ) { $PB5_B[4] = $DATA_B[0];}
                      if( ( $MFN_B-17 ) %125 == 0 ) { $PB5_B[5] = $DATA_B[0];}
		      if( $RECNUM > 25 && $MFN_B % 17 == 0 && $START_TIME_B == 0) { 
				$MNF_TIME_B = PB5_STR(@PB5_B); 
				if($DOY5<=366 && $DOY5 > 0 && $SOD5 > 0) {$START_TIME_B++; }
				$TIME_NUM_B = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5; }
                 }
                 else                                                                # WIND
                 {
                      # Report major frame count
                      if( (not $FOUND_A) && $MFN_A%25 == 0 ) { $MJFC_A = $DATA_A[ 1 ] ; $FOUND_A++;}
   
                      if( (not $FOUND_B) && $MFN_B%25 == 0 ) { $MJFC_B = $DATA_B[ 1 ] ; $FOUND_B++;}

		      # collect pieces of PB5 time from proper frames
                      if( ( $MFN_A-4 ) %25 == 0 ) { $PB5_A[0] = $DATA_A[0];  $PB5_A[1] = $DATA_A[1]; }
                      if( ( $MFN_A-9 ) %25 == 0 ) { $PB5_A[2] = $DATA_A[0];  $PB5_A[3] = $DATA_A[1]; }
                      if( ( $MFN_A-14) %25 == 0 ) { $PB5_A[4] = $DATA_A[0];  $PB5_A[5] = $DATA_A[1]; }
		      if( $MFN_A %14 == 0 && $RECNUM>25 && $START_TIME_A == 0) {
				#printf("A call PB5_STR: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x \n", @PB5_A );
				$MNF_TIME_A = PB5_STR(@PB5_A); $START_TIME_A++;
				if($DOY5 > 0 && $SOD5 > 0) {$START_TIME_A++; }
				$TIME_NUM_A = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5; }
      
                      if( ( $MFN_B-4 ) %25 == 0 ) { $PB5_B[0] = $DATA_B[0];  $PB5_B[1] = $DATA_B[1]; }
                      if( ( $MFN_B-9 ) %25 == 0 ) { $PB5_B[2] = $DATA_B[0];  $PB5_B[3] = $DATA_B[1]; }
                      if( ( $MFN_B-14) %25 == 0 ) { $PB5_B[4] = $DATA_B[0];  $PB5_B[5] = $DATA_B[1]; }
		      if( $MFN_B%14 == 0 && $RECNUM > 25 && $START_TIME_B == 0) { 
				#printf("B call PB5_STR: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x \n", @PB5_B );
				$MNF_TIME_B = PB5_STR(@PB5_B); $START_TIME_B++;
				if($DOY5 > 0 && $SOD5 > 0) {$START_TIME_B++; }
				$TIME_NUM_B = $DOY5 . $SOD5 . $MSOD5 . $FMSOD5; }
                  }
           }
           elsif( $SAT eq "GEOTAIL")
           {
                   if( (not $FOUND_A) && $MFN_A%32==0 ) { $MJFC_A = ($DATA_A[ 6 ] & 0x0f) >> 1; $FOUND_A++;}
   
                   if( (not $FOUND_B) && $MFN_B%32==0 ) { $MJFC_B = ($DATA_B[ 6 ] & 0x0f) >> 1; $FOUND_B++;}

		   $PB5_A[$MFN_A %4] = $DATA_A[0];
		   if( $RECNUM >= 4 && $MFN_A %4 == 0 && $START_TIME_A == 0) {
				$TIME_NUM_A = $MNF_TIME_A = unpack("L1", pack("C4", @PB5_A)); }
   
		   $PB5_B[$MFN_B %4] = $DATA_B[0];
		   if( $RECNUM >= 14 && $MFN_B %4 == 0 && $START_TIME_B == 0) {
				$TIME_NUM_B = $MNF_TIME_B = unpack("L1", pack("C4", @PB5_B)); }
           }

	   #if($FOUND_A == 1) { print "\tFound A at $MFN_A\n"; $FOUND_A++;}
	   #if($FOUND_B == 1) { print "\tFound B at $MFN_B\n"; $FOUND_B++;}
	}
	else { $MFN_SKIP_A++; $MFN_SKIP_B++; }

   	if($DATA_TYPE_A eq "TLZP") {  
		if($NUM_FRM_READ_A % $FRM_IN_BLK{$SAT} == 0)
       			{ $RB_A = sysread(A_IN, $PRE_REC_A, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); }
   	}
   	$RB_A = sysread( A_IN, $PRE_REC_A, $ReadLen) ;
	$NUM_FRM_READ_A++;

   	if($DATA_TYPE_B eq "TLZP") {  
		if($NUM_FRM_READ_B % $FRM_IN_BLK{$SAT} == 0)
       			{ $RB_B = sysread(B_IN, $PRE_REC_B, 600 - ($FRM_IN_BLK{$SAT}*$ReadLen)); }
   	}
   	$RB_B = sysread( B_IN, $PRE_REC_B, $ReadLen) ;
	$NUM_FRM_READ_B++;
   }

#  print "file A $MJFC_A/$MFN_A skip $MFN_SKIP_A at $Roll_Over_A rollovers\n";
#  print "file B $MJFC_B/$MFN_B skip $MFN_SKIP_B at $Roll_Over_B rollovers\n";

   if($RTPB eq "PB") 
   { 
	$MJFC_A = ($MJFC_A + $Roll_Over_A) % $MAX_MAJ{$SAT};
	$MJFC_B = ($MJFC_B + $Roll_Over_B) % $MAX_MAJ{$SAT};
   }
   if($RTPB eq "RT") 
   { 
	$MJFC_A = ($MJFC_A - $Roll_Over_A) % $MAX_MAJ{$SAT};
	$MJFC_B = ($MJFC_B - $Roll_Over_B) % $MAX_MAJ{$SAT};
   }

#print "\nfile A: $MJFC_A/$MFN_A, $MNF_TIME_A, $TIME_NUM_A\n";
#print "file B: $MJFC_B/$MFN_B, $MNF_TIME_B, $TIME_NUM_B\n Total records search: $RECNUM\n";

}


sub TIPITtoLZP {
    local ($REC) = @_;
    local ($M, $SIZE, $REC_REVERSE);

    $REC_REVERSE = "";

    if( $R_ANN_LEN ) { 		# if annotation field, reverse it
         $EXT_MIF = substr($REC, 0, $R_DAT_LEN);
	 $ANN_DAT = substr($REC, $R_DAT_LEN, $R_ANN_LEN);
    }
    else { $EXT_MIF = $REC; $ANN_DAT = ""; }

    for($M=length($EXT_MIF)-4; $M >=0; $M = $M-4)
    {
	if($M > 0) { $SIZE = $M-1; }
	else { $SIZE = 0; }
	$REC_REVERSE = $REC_REVERSE . &REV_BITS(reverse(substr($EXT_MIF, $M, 4)), 4);
    }

    return ($REC_REVERSE . $ANN_DAT);
    # $REC_reverse = &REV_BITS(reverse($EXT_MIF), length($EXT_MIF)) . $ANN_DAT;
}

sub REV_BITS {
    local ($REC, $LEN) = @_;
    my (@CHAR, $I);

    $REVERSE[0x00] = 0x00;  $REVERSE[0x01] = 0x08;
    $REVERSE[0x02] = 0x04;  $REVERSE[0x03] = 0x0c;
    $REVERSE[0x04] = 0x02;  $REVERSE[0x05] = 0x0a;
    $REVERSE[0x06] = 0x06;  $REVERSE[0x07] = 0x0e;
    $REVERSE[0x08] = 0x01;  $REVERSE[0x09] = 0x09;
    $REVERSE[0x0a] = 0x05;  $REVERSE[0x0b] = 0x0d;
    $REVERSE[0x0c] = 0x03;  $REVERSE[0x0d] = 0x0b;
    $REVERSE[0x0e] = 0x07;  $REVERSE[0x0f] = 0x0f;

    @CHAR = unpack("C$LEN", reverse($REC));
    for($I=0; $I<$LEN; $I++)
    {
	$CHAR[$I] = ($REVERSE[$CHAR[$I] & 0x0f] << 4) |
		    ($REVERSE[($CHAR[$I] & 0xf0) >> 4 ]);
    }

    return (pack("C$LEN", @CHAR));
}


sub DECOM_SCAN {
    my ($ROW_PRT, $ROWS_PRT, $DUS_REC);

    $DU_SEQ = 0;
    $LINES = 0;
    $R_TOT = 0;
    $MAFC_JUMP_NUM = 0; 
    $MIFC_JUMP_NUM = 0; 
    $FSE_NUM = 0;
    $FRM_ERR_NUM = 0;
    $FLY_MODE_NUM = 0;
    $FRM_VER_ERR_NUM = 0;
    $NON_ZERO_FLAG = 0;
    $ROWS_PRT = "";
    $RB_DUS = sysread(DUS, $DUS_REC, 52);

 
    while($RB_DUS)
    {
	$SCID_ERR = 0;
	$FRM_VER_ERR = 0;
	$MAFC_JUMP = 0; 
	$MIFC_JUMP = 0;
	$FSW_ERR = 0;
	$FRM_ERR = 0;
	$R_TOT++;

	####################################################################################################
	# $DU_REASSEMBLY_FLAG = DU reassembly flag;
	#      	0: invalid header len (unused for dps)
	#	1: invalid telemetry data 
	#	2: invalid MAF mode (for dps)
	#	3: packet fragment
	#	4: invalid APID
	#	5: invalid DU len
	#	6: frame cnt jump
	#	7: Frame level errors (frame CRC, RS error, fs bit slip, fs pattern error, 
	#				SCID error, frame version error)
	#
	####################################################################################################
	# @FEPP_STAT = Array of front-end packetprimary (FEPP) status (at least 8 elements)
	#    NASCOM Block Processor/Frame Synchronizer Card Status: 3 bytes
	#	byte 0: 
	#		0: flywheel mode
	#		1: sync lock = 0, search = 1
	#		2: out of sync lock (drop lock)
	#		3: data buffer overflow
	#		4: data reverse
	#		5: frame CRC error
	#		6: frame CRC error
	#		7: data inverted
	#	byte 1:
	#		0: last frame for session
	#		1: sync word incl in CRC
	#		2,3: num of sync word bits in error
	#		4: sync word err detected
	#		5,6: bit slip count (0 to 3)
	#		7: bit slip detected
	#	byte 2:
	#		0: spare
	#		1: down conversion performed
	#		2: NASCOM port sequence err
	#		3: NASCOM block CRC error
	#		4: preamble mode indicator
	#		5,6: NASCOM block type (0 = TDRSS, 1 = DSN, 2 = GN, 3 = JSC)
	#		7: trouble frame
	#
	#    Spare bytes: 1 byte (byte 3)
	#
	#    Reed-Solomon (RS) Status: 2 bytes
	#	byte 4:
	#		0,4: spare
	#		5: uncorrectable RS error
	#		6: RS error detected & correct
	#		7: RS encoded
	#	byte 5: sum total of corrected syms
	#
	#    Packet Processor (PK) Status: 2 bytes
	#	byte 6:
	#		0: invalid spacecraft ID
	#		1: invalid frame version (for CCSDS and AOS only)
	#		2: major frame cnt jump
	#		3: minor frame cnt jump (MAF with fill)
	#		4: sequence reverse pkt (unused for dps)
	#		5: end of session token	
	#		6,7: spare
	#	byte 7: (VCID for dps)
	#		6,7: spare
	#		0,1,2,3,4,5: virtual channel ID (for CCSDS and AOS only)
	#
	####################################################################################################
	

  	($SESSION, $DU_VER, $DTYPE, $PACKET_VER, $FRM_VER, $DU_CNT, $SCID, $VCID,
   	$FEHID, $APID, $APID_PARITY, $PB_FLAG, $DU_REASSEMBLY_FLAG, $DU_NUM, $SC1, $SC2, $DU_LEN,
   	$DU_FILL, $BLOK1, $BLOK2, $LEN_CODE, $FRM_CNT, $SUB_FRM_CNT, $TFS) = 
   		unpack("L1 C1 C1 C1 C1 L1 S1 C1 C1 S1 S1 C1 C1 S1 L1 L1 S1 S1 S1 L1 S1 L1 S1 S1", $DUS_REC);

	if($APID > 100) { $APID -= 100; }
	
        $SC_TIME = sprintf("%8.8X%8.8X", $SC1, $SC2);
	$BLOCK_TIME = sprintf("%4.4X%8.8X", $BLOK1, $BLOK2);

	$TFS_LEN = $TFS * 8;
	$KEEP_DUS = $DUS_REC;
	$RB_DUS = sysread(DUS, $DUS_REC, $TFS_LEN);
	$KEEP_DUS = $KEEP_DUS . $DUS_REC;

	for($I=0; $I<$TFS_LEN; $I++) { $FORMAT = $FORMAT . "C1 ";}
	@FEPP_STAT = unpack($FORMAT, $DUS_REC);

	if($DEBUG) {
		@TFSB = unpack("L1 L1", @FEPP_STAT);
		printf("DEBUG PRINT: FEPP_STAT = %4.4x %4.4x\n", @TFSB);
	}

	if($FEPP_STAT[0] & 0x01) { $FLY_MODE = 1; $FLY_MODE_NUM++ }
        if($FEPP_STAT[1] & 0x10) { $FSW_ERR = 1;   $FSE_NUM++; }
	if($FEPP_STAT[2] & 0x80) { $FRM_ERR = 1;   $FRM_ERR_NUM++ }
	if($FEPP_STAT[6] & 0x02) { $FRM_VER_ERR = 1; $FRM_VER_ERR_NUM++ }
	if($FEPP_STAT[6] & 0x04) { $MAFC_JUMP = 1; $MAFC_JUMP_NUM++; }
	if($FEPP_STAT[6] & 0x08) { $MIFC_JUMP = 1;  $MIFC_JUMP_NUM++; }

	if($FLY_MODE || $FSW_ERR || $FRM_ERR || $FRM_VER_ERR || $MAFC_JUMP || $MIFC_JUMP) { $NON_ZERO_FLAG ++ }

        if($DU_REASSEMBLY_FLAG & 0x02) { $TMI_ERR = 1; $TMI_ERR_NUM++; }
	if($DU_REASSEMBLY_FLAG & 0x04) { $MODE_ERR = 1; $MODE_ERR_NUM++; }
	
   	$RB_DUS = sysread(DUS, $DUS_REC, 4);
	$KEEP_DUS = $KEEP_DUS . $DUS_REC;

   	$DU_OFF = unpack("L1", $DUS_REC);
	undef($DUS_REC);

	#if((not $LONG) and (not $OLINE) and (not $HEX)) { if($DU_SEQ%200==0) {sleep (2);} }

	if($PB_FLAG >> 4) { $RTPB = "PB"}
	else 		  { $RTPB = "RT"}

	if(not defined $DUS_SIZE) { $DUS_SIZE = 52 + $TFS_LEN + 4; }

	$DU_SEQ++;

	if((defined $DUS_SIZE) and ($DU_SEQ < $BEGREC)) { seek(DUS, ($BEGREC)*$DUS_SIZE, 0); $DU_SEQ = $BEGREC; }
	if($DU_SEQ > $ENDREC) { last }

	if((not $LONG) && (not $OLINE) && (not $HEX)) { goto SKIPAREC; }

	if(($LONG || $OLINE || $HEX) && ($DU_SEQ >= $BEGREC) && ($DU_SEQ <= $ENDREC))
	{
	    if($HEX || ($LINES%50) ==0 )
	    {
		if($ROWS_PRT ne "" && ($LONG || $OLINE))
		{
			if($TIME) { print `echo "$ROWS_PRT"| lzptime 7 8`; }
			else	  { print "$ROWS_PRT\n"; }
			$ROWS_PRT = "";
		}
    	    	$ROW_HDR1 =  "\nSEQ#   DU Size  Mission  Session  Instrument  Data Type         SC time";
		$ROW_HDR1 = $ROW_HDR1 . "           Nascom Ground Time     ";
		$ROW_HDR1 = $ROW_HDR1 . "Flywheel  MAFC Jump  MIFC Jump  FSW ERR  BAD MJF MODE\n";
    	    	$ROW_HDR2 =  "-----  -------  -------  -------  ----------  ---------  ---------------------";
		$ROW_HDR2 = $ROW_HDR2 . "   ---------------------   ";
		$ROW_HDR2 = $ROW_HDR2 . "--------  ---------  ---------  -------  -----------";
	        syswrite(STDERR, $ROW_HDR1, length($ROW_HDR1));
	        syswrite(STDERR, $ROW_HDR2, length($ROW_HDR2));
	    }

	    if($TIME)
	    {
	    	$ROW_PRT = sprintf("%5d%9d%9s%9d%12s%7s%22s%15s%8.1d%10.1d%10.1d%10.1d%10.1d", 
					$DU_SEQ, $DU_LEN, $SATNAME[$SCID], $SESSION, 
					$INSTR{$SATNAME[$SCID]."-".$APID}, $RTPB, $SC_TIME, $BLOCK_TIME, 
					$FLY_MODE, $MAFC_JUMP, $MIFC_JUMP, $FSW_ERR, $MODE_ERR);
	    }
	    else
	    {
		$ROW_PRT = sprintf("%5d%9d%9s%9d%8s%11s%27.27s%24.24s%8.1d%10.1d%10.1d%10.1d%10.1d",
					$DU_SEQ, $DU_LEN, $SATNAME[$SCID], $SESSION, 
					$INSTR{$SATNAME[$SCID]."-".$APID}, $RTPB, $SC_TIME, $BLOCK_TIME, 
					$FLY_MODE, $MAFC_JUMP, $MIFC_JUMP, $FSW_ERR, $MODE_ERR);
	    }

	    $ROWS_PRT = $ROWS_PRT . "\n" . $ROW_PRT;
	    undef($ROW_PRT);
		
	    if($HEX && ($DU_SEQ >= $BEGREC) && ($DU_SEQ <= $ENDREC))
	    {
		if($TIME) { print `echo "$ROWS_PRT" | lzptime 7 8 `; }
		else      { print $ROWS_PRT; }

		print "\n\nDUS DATA:\n";
		&HEXPRT($KEEP_DUS, length($KEEP_DUS));
		undef($KEEP_DUS);
		print "DU DATA:\n";
		seek(DU, $DU_OFF, 0);
		$RB_DU = sysread(DU, $DU_REC, $DU_LEN);
		if($RB_DU == 0) { die "Error on reading du file\n"; }
		&HEXPRT($DU_REC, $DU_LEN);
		print "\n";
		
		undef $ROWS_PRT;
	    }
	}
	else
	{
SKIPAREC:
	    if($VERBOSE) {
	        if(not defined $DISPLAY) { print "...\n"; }
	    	$ROW_FORMAT = sprintf($C_ROWS, $ROWS);
	        $DISPLAY = sprintf("%s%s%4d ", $C_OPEN, $ROW_FORMAT, $DU_SEQ);
	        syswrite(STDERR, $DISPLAY, length($DISPLAY));
	    }
	}

	$RB_DUS = sysread(DUS, $DUS_REC, 52);

	if(($DU_SEQ >= $BEGREC) && ($DU_SEQ <= $ENDREC)) { $LINES++; }
    }
    if($LONG || $OLINE )
    {
	if($TIME) { print `echo "$ROWS_PRT"| lzptime 7 8`; }
	else	  { print "$ROWS_PRT\n"; }
    }    

    print "\n\n------- DUS/DU Summary ------\n\n";
    @STAT = stat(DUS);
    $CTIME = localtime( $STAT[10] );

    print "DUS file name              $DUS_FNAME\n";
    print "             Created:      $CTIME\n";
    print "               Size :      $STAT[7]\n";
    print "           Data Type:      $RTPB\n";
    printf("        Record size:       %d bytes\n", $R_DAT_LEN+$DU_OFF_LEN);
    print "           # records:      $R_TOT\n";
    print " # records with Flag:      $NON_ZERO_FLAG\n";
    if($NON_ZERO_FLAG != 0) { 
	print " 			      	  # MAF jumps: $MAFC_JUMP_NUM\n"; 
	print " 				  # MIF jumps: $MIFC_JUMP_NUM\n";
	print "					  # FSW errors: $FSE_NUM\n";
	print "					  # Trouble frames: $FRM_ERR_NUM\n";
        print "                                   # Flywheel frames: $FLY_MODE_NUM\n";
        print "                                   # Frame version err: $FRM_VER_ERR_NUM\n";
   }

    undef(@STAT);
    @STAT = stat(DU);
    $CTIME = localtime( $STAT[10] );
    print "\nDU  file name              $DU_FNAME\n";
    print "        Created:           $CTIME\n";
    print "          Size :           $STAT[7]\n";

    die "\n";

}

sub SHOW_PROD {
   if( $DATA_TYPE eq "TDM" ) 
   {
   	$RB = sysread(IN, $REC, 2792);

	&PROD_FHPRT($REC);
	
	&Parse_Product_FileName($FILENAME[$CURRFILE]);
	printf("%5.5s%28.28s%8.5d%9.4d%15.15s%7.4d %3d %8d %3d%7.4d%15.15s%7.4d %3d %8d %3d\n", 
			$Product, $FileName, $NUM_MJF, $BEGIN_MJFC, $BEGIN_SCTIME, 
			@BEGIN_ATCTIME, $LAST_MJFC, $LAST_SCTIME, @LAST_ATCTIME);
   }

   if( $DATA_TYPE eq "QAF" ) 
   {
	$RB = sysread(IN, $REC, $F_HDR_LEN);

	&QAF_FHPRT($REC);

   	$PHYS_NUM = 0;
	while( $PHYS_NUM <= $RECNUM ) 
	{
		$RB = sysread(IN, $REC, $F_HDR_LEN);
		QAF_PRT($REC);
	}

	&Parse_Product_FileName($FILENAME[$CURRFILE]);
	printf("%5.5s%28.28s%8.5d%9.4d%15.15s%7.4d %3d %8d %3d%7.4d%15.15s%7.4d %3d %8d %3d\n", 
			$Product, $FileName, $NUM_MJF, $BEGIN_MJFC, "N/A", 
			@BEGIN_ATCTIME, $LAST_MJFC, "N/A", @LAST_ATCTIME);
   }

   if ($DATA_TYPE eq "PWIW") 
   {
	$RB = sysread(IN, $REC, $F_HDR_LEN);
	
	&PWIW_FHPRT($REC);

	&Parse_Product_FileName($FILENAME[$CURRFILE]);
	printf("%5.5s%28.28s%8.5d%9.4d%15.15s%7.4d %3d %3d %3d%7.4d%15.15s%7.4d %3d %8d %3d\n", 
			$Product, $FileName, $NUM_MJF, $BEGIN_MJFC, "", 
			@BEGIN_ATCTIME, $LAST_MJFC, "", @LAST_ATCTIME);
   }

   if($DATA_TYPE eq "SIRIUS") 
   {
	$RB = sysread(IN, $REC, $F_HDR_LEN);

	&SIRIUS_FHPRT($REC);

	&Parse_Product_FileName($FILENAME[$CURRFILE]);
	printf("%5.5s%28.28s%8.5d%10.6d%11.11s%11.5s%15.12s%9.6d%11.11s%11.5s%15.12s\n", 
			$Product, $FileName, $NUM_MNF, $FIRST_DATE, $FIRST_TIME, $FIRST_FI_CNT, 
			$FIRST_TI_CNT, $LAST_DATE, $LAST_TIME, $LAST_FI_CNT, $LAST_TI_CNT);
   }
}

sub Parse_Product_FileName {
   local ($FNAME) = @_;

   ($FileName, $Product, $REMAINDER) = split(/\//, reverse $FNAME);
   $FileName = reverse $FileName;
   $Product = reverse $Product;
   $Product =~ s/product//g; 
}

sub Get_dev_or_ops {
    my ($Sat, $tmp);
    local ($WHOAMI);

    ($tmp, $Sat, $WHOAMI) = split(/\//, `pwd`);

    $WHOAMI =~ s/\n//g;
    
    return $WHOAMI;
}

sub Get_Window_Size {
    my (@tmp);

    @tmp = split(/'/, `resize`);
    $COLUMNS = sprintf("%d", $tmp[1]);
    $ROWS = sprintf("%d", $tmp[3]);
}
