Viewing contents of file '../idllib/contrib/groupk/hbrsync.pro'
;+
; NAME:
;        HBRSYNC
;
; PURPOSE:
;        This routine processes the HBRB data (High-Bit-Rate in Bit telemetry
;        mode) and extracts the 128 kbps and 6.4 kbps datastream for a
;        minor frame.
;
; CATEGORY:
;        HEAO HBR.
;
; CALLING SEQUENCE:
;
;        HBRSYNC, Buf [, HBR, NRZ, MJF, MNF, Flags]
;
; INPUTS:
;        Buf  :    A concatenation of two HBR records, the earlier one
;                  first.  Namely, a 2*4096 element 2-byte array, intarr(8192).
;
; INPUT KEYWORD PARAMETERS:
;
;        INIT :    Set this keyword to initialize various parameters used in
;                  subsequent calls to this routine.
;
; OPTIONAL OUTPUTS:
;
;        HBR  :    The 128 kbps datastream packed into 4096 words, intarr(4096)
;                  containing a minor frame (320ms) of data.
;
;        NRZ  :    The 6.4 kbps datastream packed into 128 words, intarr(128)
;                  containing a minor frame (320ms) of data.
;
;        MJF  :    The major frame number, long.
;
;        MNF  :    The minor frame number, integer [0-127].
;
;        Flags:    A 3-element integer array containing possible error flags:
;
;                  Flags(0)  : Error code
;                                 0,        Success.
;                                 2,        Failure to find 6.4 kb DCS lock.
;                                 3,        Bad or missing synch pattern.
;                                 4,        Alternate failure(s) in NRZ clock.
;                                 5,        Minor frame is not 4096 words long.
;                                 6,        DCS bit lock lost somewhere in frame
;                                 7,        Minor frame is out of Buf array boundary.
;
;                  Flags(1)  : if Flags(0) =
;                                 3,        Word offset to the start of the minor
;                                             frame with a bad or missing synch
;                                             pattern.  This offset is relative to
;                                             the next DCS synch bit transition to 0.
;                                 4,        Number of tick tock errors.
;                                 5,        Word offset to the next DCS synch bit
;                                             transition to 0.
;                                 6,        Word offset to the lost DCS bit lock.
;                                 7,        Word offset to the end of the minor frame.
;
;                              ** Unless stated otherwise, all word offsets are
;                                 relative to the start of the buffer.
;
;                  Flags(2)  : Word offset in Buf array to the "real" start of
;                              the minor frame for the NRZ data.
;
; COMMON BLOCKS:
;
;        HBRSYNC:  This common blocks holds various parameters and static
;             variables used in repeated calls to this routine.
;
; PROCEDURE:
;        You must call first this routine with the INIT keyword set to define
;        various parameters.
;
;
; MODIFICATION HISTORY:
;
; MODIFIED 3 31 83 TO CORRECT FOR OBSERVED TICKTOCK ERRORS ON SOME TAPES
; INIT ENTRY ADDED.
;  MODULE TO CONTAIN BIT SHOVING STUFF FOR HEAO HIGH BIT RATE DATA
;  D P MCNUTT  1 26 83    -    NO RIGHTS RESERVED
;
; THE FOLLOWING ASSEMBLY PARAMETER AFFECTS THE TIMING OF THE MINOR FRAME
; DATA RETURNED.  FAZEF=0 WILL USE THE EARLIER OF THE TWO AVAILABLE COPIES OF
; A MINOR FRAME, FAZEF=1 WILL USE THE LATER.
;
;   **** I will use the convention that BIT 0 is the LEAST significant bit.
;   **** All numbers will be in base 10, unless stated otherwise.
;
;   We will assume that the data is in BIG Endian convention since this
;   routine was written for the Data Generals which used this convention.
;
;   "Ported" to IDL from Data
;   General Eclipse assembly      : Han Wen, April 1995.
;        23-APR-1995              Bugfix: NRZ was returning as a long integer (4-byte)
;                                 instead of a (2-byte) integer.
;        08-JUL-1995              Changed word offset (Flags(1)) for BITSBAD error
;                                 relative to start of buffer instead of start of minor
;                                 frame.
;-
pro HBRSYNC, Buf, HBR, NRZ, MJF, MNF, Flags, INIT=Init

         common HBRSYNC, B_, E_, V_, C_
;
         if keyword_set(INIT) then begin

         ;  Define various bit parameters

              B_ = { $
                   LOSS:15,$  ; Analog lost data bit
                   HLOK:14,$  ; High bit rate lock
                   TIKT:13,$  ; Tick tock FAZEF bit for copies of NRZ data
                   LNRZ:12,$  ; 6.4kb NRZ data
                   FSYN:7 ,$  ; Frame synch flag from the DCS ground station
                   LLOK:6 ,$  ; 6.4kb bit synch lock flag
                   HBR1:11,$
                   HBR2:8 ,$  ; Bit locations in source words of HBR data bytes
                   HBR3:5 ,$
                   HBR4:0  }

         ;  Define error codes for the Flags array

              E_ = { $
                   NOSYNCH :2,$   ; Failure to find 6.4 kb DCS lock
                   BADSYNCH:3,$   ; Bad or missing synch pattern
                                  ;   second word is SLIP value
                   TIKTOK  :4,$   ; Alternate failure(s) in NRZ clock
                                  ;   second word is count thereof
                   BUMSIZ  :5,$   ; Minor frame is not 4096 words long
                                  ;   second word is ordinal of next synch
                                  ;   bit transition if it occurred early.
                   BITSBAD :6,$   ; DCS bit lock lost somewhere in the frame
                   OBOUNDS :7 }   ; Minor frame is out of Buf bounds
                                  ;   second word is end of minor frame offset

         ;  Define other miscellaneous constants

              SLIPR     = 100
              LBUF      =8192          ; Length of double buffer in 16 bit words
              LIMBF     =-LBUF/2-SLIPR

              C_ = { $
                   SLIPR: SLIPR,$      ; +/- range allowed for slip checking
                   LIMBF: LIMBF,$      ; = -4196, limiting address in search for
                                       ;    DCS synch
                   LIMB2: -4095+16,$   ; = -4079, Length of scan to find second
                                       ;    sync flag.
                   LOKC9: -4096,$
                   TTMSK: 8192,$       ; Mask for tick tock bit (6.4kb clock)
                                       ; 0010 0000 0000 0000

                   TTERR: -16384, $    ; Fill word in case of ticktock failure
                                       ; 1100 0000 0000 0000

                   ; BARKER CODE 24: 111 110 101 111 001 100 100 000
                   PTRNH:  -1293,$     ; 1 111 101 011 110 011
                   PTRNL:  8192  }     ; 0 010 000 000 000 000

         ;  Define various STATIC variables

              V_ = { $
                   SLIP :-64,$    ; Offset required to give earlier minor frame
                                  ; this value requires that TTSAV be initialized
                                  ; to 0
                   TTSAV:0,$      ; Storage for 'last' ticktock value
                   TTCNT:0,$      ; Counter for ticktock failures
                   INITF:0,$      ; Init/reinit flag, zero means init
                   TTTRY:0,$      ; Try counter for ticktock phasing
                   TTINI:0 }

              return
         endif

;   Leftover stuff from HBRSYNC.SR
;
;        FAZEF=0
;        BANANA=0 ; Set so that slip will not be reset on synch fail ; on 3/31


;   Initialize/define output arguments

         if N_ELEMENTS( MJF ) eq 0 then MJF = 0L

         HBR       = intarr(4096)
         NRZ       = intarr(128)
         Flags     = intarr(3)

         V_.TTTRY  = 0            ; Set try count for ticktock phasing
         SLIPS     = V_.SLIP      ; Save beginning value for loop test

;
;   Search for the first word in the buffer in which the frame synch word is
;   set.  this means that the DCS ground station is locked on and has found
;   the minor frame synch word.
;
         bitsets   = (BUF(C_.SLIPR:8191) and 2^B_.FSYN)    ; Bump C_.SLIPR words
                                                           ; ahead to avoid
                                                           ; early synch pattern

         here0     = WHERE( bitsets eq 0, nzero )     ; The first word where
                                                      ; the B_.FSYN bit is NOT
                                                      ; set points to the first
                                                      ; DCS frame synch

         if (nzero eq 0) then begin
              Flags(0) = E_.NOSYNCH         ; DCS never found frame synch
              return                        ; Exit with error flag
         endif

;   Check next synch transition to see if it is 4096 words away.
;   For each minor frame (i.e. 320ms time interval), there are 16 sequential
;   words where bit B_.FSYN is 0.  So the 17th word where bit B_.FSYN is 0
;   should contain the next synch transition.

         if (nzero gt 16) then begin        ; If nzero eq 16, then next
                                            ; synch transition is out of buffer.
                                            ; Assume it's okay.

              if ((here0(16) - here0(0)) ne 4096) then begin
                   Flags(0) = E_.BUMSIZ               ;Error code
                   Flags(1) = C_.SLIPR + here0(16)    ;Word offset of
                                                      ;offending bit
                   return
              endif
         endif

RENTR:                            ; Possible reentry if SLIP value is bad

         START     = C_.SLIPR+ here0(0)     ; Offset of the first DCS sync bit
         START     = START   + V_.SLIP      ; Position to "real" start of minor
                                            ; frame
         Flags(2)  = START        ; Send start offset to caller  *-*
                                  ; In third word of flags       *-* 3-8-83
;
;   Check to see if minor frame is within buffer
;
         if START gt 4096 then begin
              Flags(0)  = E_.OBOUNDS
              Flags(1)  = START + 4095      ; Return out of bound offset
              return
         endif

;
;   Now pack up the minor frame into caller's buffer.
;
         BNRZ = BUF(START + 2*indgen(128*16))    ; Get every other word
         BNRZ = (BNRZ and 2^B_.LNRZ) ne 0        ; Pick out 6.4kb NRZ bits
         BNRZ = REFORM( BNRZ,16,128,/OVERWRITE ) ; Each 16 element array represents
                                                 ; the bit pattern of one minor frame,
                                                 ; where the 0th element corresponds
                                                 ; to the MSB, 2^15.
         bbase= REVERSE(indgen(16))
         bbase= 2^bbase                          ; i.e. [2^15, 2^14, ... 2^0]

         NRZ  = FIX(TRANSPOSE( bbase#BNRZ ))
;
;   Now see if we got a synch pattern at the right place
;
         SYBAD = 0

         if (NRZ(0) eq C_.PTRNH) then begin      ; Synch pattern HI
              AC0  = C_.PTRNL
              AC1  = NRZ(1) and -256             ; Only keep upper 8 bits

              if AC0 ne AC1 then SYBAD = 1
         endif else SYBAD = 1                    ; No match


         SYBA1 = 0                               ; Date: 3/31
         if SYBAD then begin                     ; If at beginning allow slip to
              if V_.INITF eq 0 then begin        ; adjust, otherwise fail on no
                   AC0  = V_.SLIP - 1            ; synch
                   AC1  = AC0  + C_.SLIPR        ; Limiting value
                                                 ; See if there, and if so,
                   if AC1 eq 0 then AC0 = 0      ; replace w/ other limit.
                   V_.SLIP = AC0
                   if (SLIPS ne V_.SLIP) then $  ; See if we have gone full
                        goto, RENTR              ; circle
                   SYBA1 = 1
              endif else SYBA1 = 1
         endif

         if SYBA1 then begin
              Flags(0) = E_.BADSYNCH
              Flags(1) = V_.SLIP
              return
         endif

;
;   Check DCS bit lock bit - if zero anywhere we will fail
;

         bitsets   = (BUF(START:START+4095) and 2^B_.LLOK)      ; Pick out DCS
                                                                ; bit lock


         here_bad  = WHERE( bitsets ne 0, nbad )

         if (nbad gt 0) then begin
              Flags(0)  = E_.BITSBAD   ; Set error flags for caller
              Flags(1)  = START + here_bad(0)
              return
         endif

;
;   CELL = 1 byte = 8 bits
;
;   Pick up the subframe ID and pass to caller
;      20 bits of the spacecraft clock are contained in cells 128,129,130
;   of each minor frame, the upper 4 bits of 128 being garbage.  eight more
;   bits of clock are transmitted in cell 81 of  minor frame 118.
;

         AC1  = NRZ(65)                ; CELLS  130 AND 131
         AC0  = NRZ(64)                ; CELLS  128 AND 129
         AC0  = AC0  and 4095          ; Clear out bits 12 thru 15
         CARRY= (AC1 and -32768) ne 0  ; Shift bit 15 into the CARRY
         if CARRY then $
         AC1  = (AC1 xor -32768 )
         AC1  = ISHFT(AC1,-8)          ; Get rid of garbage CELL 131.
         AC0  = ISHFT(AC0,1)           ; Shift and put CARRY into
         AC0  = AC0 + CARRY            ; bit 0.
         MNF  = AC1
         if (MNF ne 118) then begin    ; Get callers MJF bits
              ACL = ISHFT(MJF,3)
              AC1 = ISHFT(ACL,-16)     ; Get upper 16 bits of ACL
         endif else AC1 = NRZ(40)     ; Cell 81 plus garbage in high bits

         DUM  = AC0
         AC0  = AC1
         AC1  = long( DUM )
         AC0  = long( AC0 and 255 )    ; Lower 8 bits, 255=0000 0000 1111 1111
         AC1  = ISHFT( AC1,  3 )       ; Left justify low order bits
         MJF  = ISHFT( AC0, 16 ) + AC1
         MJF  = ISHFT( MJF, -3 )       ; and merge with the hi

;
;
;   Now we need to pack the high bit rate bits into the caller's output buffer
;   we will pick up one word at a time and shift the bits around.  In the output
;   the sign bit will be set if the HBR lock bit was set or if we had a tick-tock
;   sequence error.
;
;   There are 10 bits of HBR data for each BUF word, namely there are
;   ten 7.8125 microsecond time intervals where one or more photons may have
;   been detected.  Each bit that is set represents a detection of one or
;   more photons.  (We are assuming that the data is in the HBRB or High Bit
;   Rate BIT format.)
;
         HBRwrds   = (BUF and 63)                     or $  ; Bits 0 - 5
                     (ISHFT(BUF,-2) and 960)          or $  ; Bits 8 - 11
                     (ISHFT(BUF and 2^B_.HLOK,15-B_.HLOK))

HBM_0:
         V_.TTSAV= V_.TTINI       ; Value varies with assembly parameter "FAZEF"
         INC1 = 0 - 1             ; Set auto incrementer for destination buffer
         INC0 = START - 1         ; Set auto incrementer for source buffer
         COUNT= 4096              ; Set number of words to move

;
;   The bit picked up by TTMSK should be "tick-tock"ing between values
;   0 and 1 for sequential BUF words.
;
         for i=1,COUNT do begin

              INC0 = INC0 + 1
              AC1  = BUF(INC0)         ; Load up next source word
              AC2  = AC1 and C_.TTMSK  ; Pick up NRZ clock bit only
              AC0  = V_.TTSAV
              V_.TTSAV= AC2

              HBRfill   = HBRwrds(INC0)

              if (AC2 eq AC0) then begin    ; If next "tick" is a "tock"-> error
                   V_.TTSAV= C_.TTMSK xor AC2
                   AC0  = C_.TTERR
                   INC0 = INC0 - 1                 ; Move back in the source
                   if INC0 ne 0 then HBRfill = AC0 ; and go store the fill data
              endif

              INC1      = INC1 + 1
              HBR(INC1) = HBRfill

         endfor
;
;   Now calculate the number of words actually loaded from the buffer.  should
;   be 4096 - if not we had a ticktock error.
;

         AC0  = START + 4095
         AC0  = AC0 - INC0
         if AC0 ne 0 then begin   ; Will be zero if no tick tock errors

              if (V_.TTTRY ne 0) or $       ; Have tried both phases - just fail
                 (V_.INITF ne 0) then $     ; See if we ever had a good one
                 begin                      ;    yes so fail now
                   Flags(0) = E_.TIKTOK     ; Return with error
                   Flags(1) = AC0
                   return
              endif

              V_.TTINI = C_.TTMSK xor V_.TTINI   ; Otherwise invert the
              V_.TTTRY = V_.TTTRY + 1            ; initializer and try again.
              goto, HBM_0

         endif

         Flags(0) = AC0
         Flags(1) = V_.TTINI           ; Pass the initial value to DJY if he wants it
         V_.INITF = 1                  ; Adjust the innitializer flag
                                       ;  to show a successful pass
         return                        ; Return with no errors
;
;
;  A known problem with this code can occur when and if the synch pattern
; occurs before the beginning of the buffer and the DCS frame synch bit
; comes true right at the beginning of the buffer.  If this happens a simple
; fix is to save some data in storage space before the beginning of the
; buffer.  It happened: MURPHY'S RULE IS PROVEN; it's been fixed.
;
end