;+
; Project     : SOLAR-B - EIS
;
; Name        : EIS_CPT_PROCESS_SCIENCE_SEQUENCES
;
; Purpose     : Implements science study as OBSTBL sequence tables
;
; Explanation : A science study consists of a number of rasters. It may span a number of OBSTBL sequence
;               tables. These are daisy-chained together. This routine runs through the rasters forming the study,
;               adding them to the current sequence table.
;               When the sequence table is full a new sequence table.
;               The mandatory control sequence for the last sequence table forming the study is completed
;               outside of this routine, as are the links between daisy-chained sequences forming the study.
;
; Use         : < result = eis_cpt_process_science_sequences( engineering_parameters, study_detail, raster_details, $
;                                                             time_for_reuse, linelists, sequences ) >
;
; Inputs      : raster_details          : STRUCTURE ARRAY of type EIS_raster_detail.
;               engineering_parameters  : STRUCTURE of type EIS_engineering_parameters.
;               study_detail            : STRUCTURE of type EIS_study_detail.
;               time_for_reuse          : DOUBLE TAI time after which sequences may be overwritten.
;               linelists               : INTARR[nrasters] gives linelist table index for each raster.
;
; Opt. Inputs : None.
;
; Outputs     : result      : INT flag :
;                               1 : processed science plan OK.
;                               0 : processing failed.
;               sequences   : STRUCTURE ARRAY of type EIS_CPT_sequence.
;
; Opt. Outputs: None.
;
; Keywords    : RESPONSE_RASTER_ID  : ULONG raster identifier indicating response study response raster
;               ADJUST_Y         : INT Flag indicating YSTART adjust allowed
;
; Calls       : None.
;
; Common      : None.
;
; Restrictions: None.
;
; Side effects: May output ASCII files.
;
; Category    : EIS_CPT.
;
; Prev. Hist. : None.
;
; Written     : Martin Carter RAL 261/10/04
;
; Modified    : Version 0.1, 26/01/05, MKC
;                 Changed how sequences constructed
;               Version 0.2, 01/02/05, MKC
;                 Changed study_index argument to seq_start and seq_end.
;                 Added extra control for re-use of sequence tables.
;                 Moved checksum and following study calculations.
;                 Removed obstbl argument.
;                 Added eis_cpt_obstbl.
;               Version 0.3, 02/03/05, MKC
;                 Corrected bug in logic.
;                 Added sequence position to eis cpt hex raster.
;                 Corrected seq_start unset.
;               Version 0.4, 18/03/05, MKC
;                 Moved eis cpt check study.
;               Version 0.5, 03/04/05, MKC
;                 Added sequences argument.
;               Version 0.6, 10/05/05, MKC
;                 Renamed from eis cpt process sequences for study.
;                 Changed INDEX keyword to LINK keyword.
;                 Fixed bug with loop back position.
;               Version 0.7, 05/07/05, MKC
;                 Used eis cpt set raster id.
;                 Implement only set slit/slot once per study and when changes.
;               Version 0.8, 21/07/05, MKC
;                 Added sequence ID to obstbl map description.
;               Version 0.9, 12/09/05, MKC
;                 Changed raster number/number of rasters to raster identifier.
;                 Changed sense of LINK keyword so that refers to previous table rather than following table.
;                 Changed so that uses an intermediate structure array of sequences.
;               Version 1.0, 19/07/06, MKC
;                 Added first sequence in study flag.
;               Version 1.1, 10/01/07, MKC
;                 Added disallowed slit/slot movement.
;                 Added check of raster length calculation.
;                 Moved raster check into routine.
;                 Removed check on hex array.
;                 Moved slit/slot command into routine.
;                 Used eis cpt end sequence.
;               Version 1.2, 17/04/07, MKC
;                 Moved special window commands to separate routine.
;                 Added keyword RESPONSE RASTER.
;                 Changed so that only set special window values if necessary.
;               Version 1.3, 23/03/10, MKC
;                 Added keyword ADJUST_Y.
;                 Changed so that does not issues special window command for YSTART if YADJUST set until response raster performed.
;               Version 1.4, 08/05/13, MKC
;                 Changed keyword RESPONSE RASTER to RESPONSE RASTER ID.
;                 Changed order of argument list and removed eis multiple sequences check.
;
; Version     : 1.4, 08/05/13
;-
;**********************************************************

FUNCTION eis_cpt_process_science_sequences, raster_details, engineering_parameters, study_detail, $
                                            time_for_reuse, linelists, sequences, RESPONSE_RASTER_ID=response_raster_id, ADJUST_Y=adjust_y

  ; set up named variable
  ; NB raster ID = 0 is an invalid ID

  IF NOT KEYWORD_SET(response_raster_id) THEN response_raster_id = 0

  ; set up sequence data structure

  sequence = {EIS_CPT_sequence}

  ; get sequence ID in bytes

  seqid = eis_cpt_uinttobytes(study_detail.study_identifier)

  ; set up ID

  sequence.study_identifier = study_detail.study_identifier

  ; set up sequence link for study

  sequence.linked_study_identifier = study_detail.linked_study_identifier

  ; set up study repeat number

  sequence.study_repeat_number = study_detail.study_repeat_number

  ; set up slit/slot disallowed flag

  sequence.slit_slot.disallowed = study_detail.slit_slot.disallowed

  ; set up description used in obstbl_map

  sequence.description = eis_cpt_bytestohex(seqid,/OX) + ' : ' + study_detail.description

  ; set up time associated with tables

  sequence.time = time_for_reuse

  ; set up first in study flag

  sequence.first = 1

  ; set up sequence header (with dummy length)
  ; [sequence length, study id, sequence repeat]

  sequence_header = [0B, seqid, BYTE(study_detail.study_repeat_number)]

  ; initialize first sequence

  bytes = sequence_header

  ; initialize slit/slot position
  ; if slit/slot movement allowed ensure that the study sets the initial slit/slot position
  ; thereafter the slit/slot position is only set if it changes
  ; if slit/slot movement disallowed set slit/slot to initial position

  IF study_detail.slit_slot.disallowed THEN current_slit_slot = study_detail.slit_slot.initial ELSE current_slit_slot = -1

  ; set up initial special hardware window coords [xstart,ystart,xsize,ysize]
  ; -1 values ensure that the first special window in the study sets up all the values

  current_special_hardware_window = [-1,-1,-1,-1]

  ; loop through rasters

  FOR r = 0, N_ELEMENTS(raster_details)-1 DO BEGIN

    ; check raster parameters

    IF NOT eis_cpt_check_raster(engineering_parameters, raster_details[r]) THEN GOTO, error

    ; check if slit slot position changed for raster

    IF current_slit_slot NE raster_details[r].slit_slot THEN BEGIN

      ; check whether slit/slot command fits in current sequence, if not finish current sequence and start a new one
      ; NB sequence finishes with a 2 byte mandatory sequence control and a 1 byte checksum
      ;    slit/slot command is 9 bytes

      IF N_ELEMENTS(bytes)+9+3 GT !EIS_CPT_CONSTANTS.sql THEN eis_cpt_end_sequence, bytes, sequence, sequences, /LINK

      ; add slit slot command to sequence

      eis_cpt_add, bytes, eis_cpt_slit_slot_auto ( raster_details[r].slit_slot, engineering_parameters.mechanism_control.slit_direction )

    ENDIF

    ; check if special CAM hardware window required

    IF raster_details[r].special_hardware_window_flag THEN BEGIN

      ; check if adjust y allowed and response raster id set
      ; NB can have XRT filler response study where adjust_y is set but not response_raster_id

      IF KEYWORD_SET(adjust_y) AND KEYWORD_SET(response_raster_id) THEN BEGIN

        ; check if response raster performed yet

        IF NOT KEYWORD_SET(response_raster_performed) THEN BEGIN

          ; for a response study with adjust y set
          ; ystart will be poked into CAM CSG ID 4 by the onboard SW at the start of the study
          ; so must not overwrite the value set up by the onboard SW
          ; NB although yheight is also poked by th eonboard sw, it is the same value as used
          ; by the response raster so can be overwritten

          ; setting current special hardware window ystart value to that of the special hardware window ensures that
          ; value does not get set by CAM commands

          current_special_hardware_window[1] = raster_details[r].special_hardware_window[1]

        ENDIF

      ENDIF

      ; get special hardware window commands taking into account what has already been set up and whether the YSTART value
      ; is to be dynamically repointed

      special_commands = eis_cpt_c_set_window ( engineering_parameters.CAM_readout_parameters.addresses, $
                                                raster_details[r].special_hardware_window, current_special_hardware_window)

      ; check if any special commands produced

      IF KEYWORD_SET(special_commands) THEN BEGIN

        ; check whether special hardware window command fits in current sequence, if not finish current sequence and start a new one
        ; NB sequence finishes with a 2 byte mandatory sequence control and a 1 byte checksum
        ;    special hardware window command is 10 bytes per value

        IF N_ELEMENTS(bytes)+N_ELEMENTS(special_commands)+3 GT !EIS_CPT_CONSTANTS.sql THEN eis_cpt_end_sequence, bytes, sequence, sequences, /LINK

        ; set special hardware window

        eis_cpt_add, bytes, special_commands

      ENDIF

      ; set current special window

      current_special_hardware_window = raster_details[r].special_hardware_window

      ; check if response raster performed
      ; for a response raster with adjust y set
      ; ystart and yheight will be poked into CAM CSG ID 4 by the onboard SW
      ; so only need to check if xstart and xlength are changed
      ; (the ystart linelist value is also changed)
      ; subsequent studies using special windows will need to be aware that ystart is not then known
      ; NB only first raster with response raster ID responds

      IF NOT KEYWORD_SET(response_raster_performed) AND raster_details[r].raster_id EQ response_raster_id THEN BEGIN

        current_special_hardware_window[1] = -1

        response_raster_performed = 1

      ENDIF

    ENDIF

    ; process raster to hex

    hex = eis_cpt_hex_raster ( engineering_parameters, raster_details[r], linelists[r] )

    ; check raster length

    IF N_ELEMENTS(hex) NE eis_cpt_raster_length(raster_details[r]) THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; check whether raster fits in current sequence, if not finish current sequence and start a new one
    ; NB sequence finishes with a 2 byte mandatory sequence control and a 1 byte checksum

    IF N_ELEMENTS(bytes)+N_ELEMENTS(hex)+3 GT !EIS_CPT_CONSTANTS.sql THEN eis_cpt_end_sequence, bytes, sequence, sequences, /LINK

    ; offset loop back position

    hex[N_ELEMENTS(hex)-1] = hex[N_ELEMENTS(hex)-1] + N_ELEMENTS(bytes)

    ; add raster to current sequence

    eis_cpt_add, bytes, hex

    ; update current slit slot

    current_slit_slot = raster_details[r].slit_slot

  ENDFOR

  ; finish last sequence in the study

  eis_cpt_end_sequence, bytes, sequence, sequences, /LAST, LINK=study_detail.linked_study_identifier

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END





