SUBROUTINE EA_DCOD  ( cldt, bufrtn, nhours, iret )
C************************************************************************
C* EA_DCOD								*
C*									*
C* This routine decodes bulletins containing EARS (EUMETSAT ATOVS	*
C* Retransmission Service) BUFR messages into NCEP BUFR format.		*
C*									*
C* EA_DCOD ( CLDT, BUFRTN, NHOURS, IRET )				*
C*									*
C* Input parameters:							*
C*	CLDT		CHAR*		Date-time from command line	*
C*	BUFRTN		CHAR*		NCEP EARS BUFR tables file	*
C*	NHOURS		INTEGER		Max # of hours before run time	*
C*					for creating BUFR output	*
C*									*
C* Output parameters:							*
C*	IRET		INTEGER		Return code:			*
C*					  0 = normal return		*
C*									*
C**									*
C* Log:									*
C* J. Ator/NCEP         03/05						*
C* J. Ator/NCEP         11/09	Add capability for MHS			*
C* J. Ator/NCEP         09/15	Restructured to use IO='SEC3' and add	*
C*				capability for CrIS and ATMS		*
C* J. Ator/NCEP         02/16	Add capability for IASI                 *
C* M. Weiss/IMSG        03/17   1. Modified the order in which the      *
C*                              contents of Section 3 messages/bulletin *
C*                              headers via data type are checked.      *
C*                              2. Inserted DO WHILE to prevent         *
C*                              declaring bullok = false when the       * 
C*                              number of descriptors (ndesc) is > 1    *
C*                              3. As a result of (2), added the        *
C*                              following log file message:             *  
C*                              "message contains extra descriptors"    *
C*                              which is not flagged by Big Brother.    *
C* J. Ator/NCEP		09/17	Store GSES for CrIS and IASI subtypes.	*
C* J. Ator/NCEP		08/18	Remove GSES from CRIS and IASI subtypes,*
C*				and add dynamic allocation with MXMSGL.	*
C* M. Weiss/IMSG        09/18   Changed MXDSC (Max # of descriptors)    * 
C*                              from 10 to 200                          *
C* M. Weiss/IMSG        10/18   Added Direct Broadcast (DB) CrIS, ATMS, *
C*                              and IASI subtypes.                      *
C* M. Weiss/IMSG        06/19   Added NOAA-20 full spectral CrIS        *
C* M. Weiss/IMSG        08/19   CrIS NPP DB NSR uses CRCHN and          *
C*                              CrIS NOAA-20 DB FSR uses CRCHNM.        *
C* M. Weiss/IMSG        09/19   For RARS IASI data add INQX GTS header  *
C* M. Weiss/IMSG        12/19   For RARS IASI data add INQI and bypass  * 
C*                              INQX AMMC GTS headers                   *
C* M. Weiss/IMSG        01/20   Optimized case statements to be able to *
C*                              process future IASI and CrIS headers.   *
C* M. Weiss/IMSG        04/20   Updates related to NPP CrIS FSR feeds   *
C* J. Ator/NCEP		08/20	Store NEDTQW values when available for  *
C*                              AMSU-A/B, HIRS and MHS data             *
C* J. Ator/NCEP         08/20	Add capability for AIRS data		*
C* J. Ator/NCEP         06/23   Call ISETPRM as function                *
C* J. Ator/NCEP         06/23   Use new decod_ut library routines,      *
C*                              clean up and simplify logic             *
C* J. Ator/NCEP         03/25   Process CrIS from INS                   *
C************************************************************************
	INCLUDE		'GEMPRM.PRM'
	INCLUDE		'BRIDGE.PRM'
        INCLUDE         'eacmn.cmn'

	CHARACTER*(*)	cldt, bufrtn

	CHARACTER	bull*(DCMXBF), cbull*(DCMXBF),
     +			seqnum*8, buhd*8, cborg*8, bulldt*8, bbb*8,
     +			bfstin*8, bfstot*8,
     +			ctag*8, ctagp*8, ctagpr*10, drptag*10,
     +			cdesc(MXDSC)*6, meastyp*3, cval*8,
     +                  bufrdn*(DCMXLN), bufrbn*(DCMXLN)

	INTEGER		irundt (5), irptdt (5), ibull ( DCMXBF / 4 ),
     +			ndrp2 (3), idxtmbr ( MXBMSE )

	LOGICAL		bullok, msgok, crisn20

	REAL*8		r8ary ( MXVAL ), GETBMISS

	EQUIVALENCE	( cbull (1:4), ibull (1) )
C*-----------------------------------------------------------------------
	iret = 0

C*      Get the BUFR tables directory from the tables file.  This
C*      directory will be passed to subroutine MTINFO as the location
C*      in which to search for any needed master table files.

        CALL FL_PATH ( bufrtn, bufrdn, bufrbn, ierpth )

C*	Set any configurable BUFRLIB parameters to optimize them for
C*	the needs of this program.  This includes setting any
C*	parameters associated with BUFRLIB features that we won't be
C*	using in this program to artificially low values, which in turn
C*	will prevent the unnecessary allocation of a lot of memory that
C*	will never be used.

        IF ( ( ISETPRM ( 'NFILES', 4 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MXMSGL', 2000000 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MAXMEM', 100000 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MAXMSG', 100 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MXDXTS', 5 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MXLCC', 8 ) .ne. 0 ) .or.
     +       ( ISETPRM ( 'MXCDV', 6000 ) .ne. 0 ) ) RETURN

C*	Open the tables file for the output stream.

	CALL FL_SOPN ( bufrtn, iubftn, ierspn )
	IF ( ierspn .ne. 0 ) THEN
	  CALL DC_WLOG ( 0, 'FL', ierspn, bufrtn, ierwlg )
	  RETURN
	END IF

C*	Open the messages file for the input stream.

	CALL FL_GLUN ( iubfme, iergln )
	IF  ( iergln .ne. 0 )  THEN
	  CALL DC_WLOG  ( 0, 'FL', iergln, ' ', ierwlg )
	  RETURN
	END IF
	OPEN ( UNIT = iubfme, FILE = '.dummy/dcears',
     +		FORM = 'UNFORMATTED' )
	CALL OPENBF ( iubfme, 'SEC3', iubftn )

        CALL MTINFO ( bufrdn, 98, 99 )

C*	Open the messages file for the output stream.

	CALL FL_GLUN ( iubfmn, iergln )
	IF ( iergln .ne. 0 ) THEN
	  CALL DC_WLOG ( 0, 'FL', iergln, ' ', ierwlg )
	  RETURN
	END IF

C*	Connect the tables and messages files for the output stream.

	CALL OPENBF ( iubfmn, 'NUL', iubftn )
        r8bfms = GETBMISS()

C*	Specify that output messages are to be compressed, edition 4
C*      and up to 199.9K bytes in size.

	CALL CMPMSG ('Y') 
	CALL PKVS01 ( 'BEN', 4 )
	CALL MAXOUT ( 199900 )

C*	Close the tables file for the output stream.

        CALL FL_CLOS ( iubftn, iercls )
        IF ( iercls .ne. 0 ) THEN
          CALL DC_WLOG ( 0, 'FL', iercls, ' ', ierwlg )
        END IF

	DO WHILE ( .true. )

C*	  Get a new bulletin from the input pipe.

	  CALL DC_GBUL ( bull, lenb, ifdtyp, iergbl )
	  IF ( iergbl .ne. 0 ) THEN

C*	    A time-out occurred while waiting for a new bulletin
C*	    on the input pipe.  Shut down the decoder and exit.

	    CALL DC_WLOG ( 0, 'DC', iergbl, ' ', ierwlg )
	    CALL CLOSBF ( iubfme )
	    CALL CLOSBF ( iubfmn )
	    CALL FL_CLAL ( iercal )
	    RETURN
	  END IF

C*        Do not decode AFOS products.

          IF ( ifdtyp .ne. 0 ) CYCLE

C*	  Decode the header information from this bulletin.

	  CALL DC_GHDR ( bull, lenb, seqnum, buhd, cborg,
     +			 bulldt, bbb, ibptr, ierghd )
	  IF ( ierghd .ne. 0 ) THEN
	    CALL DC_WLOG ( 2, 'DC', ierghd, ' ', ierwlg )
            CYCLE
          END IF

C*	  Start an entry for this bulletin in the decoder log.

	  logmsg = '########################################'
	  CALL DC_WLOG  ( 2, 'DC', 2, logmsg, ierwlg )
	  logmsg = seqnum // buhd // cborg // bulldt // bbb
	  CALL DC_WLOG  ( 2, 'DC', 2, logmsg, ierwlg )

C*        Get the run date-time.

          CALL UT_GET_RUNDT ( cldt, irundt, iergrd )
          IF ( iergrd .ne. 0 ) CYCLE

	  nrept = 0

	  bullok = .true.

          DO WHILE ( bullok )

C*          Locate the next BUFR message within the bulletin, and store
C*          it within an equivalenced integer array.

            CALL UT_GET_BUFRMG ( bull, lenb, ibptr, istart, msglen,
     +              mtyp, msbti, MXDSC, cdesc, ndesc, ierbmg )
            IF ( ierbmg .ne. 0 ) THEN

C*	      Print the type and number of reports processed.

              WRITE ( UNIT = logmsg, FMT = '( 2A, I4, A )' )
     +                  bfstot, ': ', nrept,' reports'
	      CALL DC_WLOG  ( 2, 'DC', 2, logmsg, ierwlg )

C*            Make sure that all BUFR output for this bulletin
C*            has been written to the BUFR output stream before
C*            going back to DC_GBUL and waiting for a new bulletin
C*            on the input pipe.

              CALL UT_WBFR ( iubfmn, 'ears', 1, ierwbf )
              bullok = .false.
              CYCLE
            END IF

            cbull = bull ( istart : ibptr )

C*	    Open the BUFR message for reading.

	    CALL READERME ( ibull, iubfme, bfstin, ibfdt, ierrme )
	    IF ( ierrme .ne. 0 ) CYCLE

C*          Check the contents of Section 3 of the message along
C*          with the bulletin header to verify the data type.

            ii = 1
            bfstot = '????????'
            crisn20 = .false.
            DO WHILE ( ( bfstot(6:8) .eq. '???' ) .and.
     +                    ( ii .le. ndesc ) )
              SELECT CASE ( cdesc(ii)(1:6) )
                CASE ( "310009" )
                  SELECT CASE ( buhd (1:3) )
                    CASE ( "INA" )   ! AMSU-A
                      bfstot = 'NC021033'
                      idxyear = 16
                      ntmbr = 15
                      nr8in = 127
                  END SELECT
                CASE ( "310010" )
                  SELECT CASE ( buhd (1:3) )
		    CASE ( "INB" )   ! AMSU-B
                      bfstot = 'NC021034'
		      idxyear = 16
                      ntmbr = 5
		      nr8in = 67
                    CASE ( "INM" )   ! MHS
                      bfstot = 'NC021036'
                      idxyear = 16
                      ntmbr = 5
                      nr8in = 67
                  END SELECT
                CASE ( "310008" )
		  SELECT CASE ( buhd (1:3) )
                    CASE ( "INH" )   ! HIRS
		      bfstot = 'NC021035'
		      idxyear = 16
                      ntmbr = 19
		      nr8in = 156
                  END SELECT
		CASE ( "310060" )   ! CrIS
                  SELECT CASE ( buhd (1:4) )
		    CASE ( "INCX" ) ! RARS CrIS
                      bfstot = 'NC021037'
		      idxyear = 5
		      drptag = '(CRCHN)'
		      ctag = 'SRAD'
		    CASE ( "INCT" ) ! DB CrIS NSR
                      bfstot = 'NC021212'
		      idxyear = 5
		      drptag = '(CRCHN)'
		      ctag = 'SRAD'
                  END SELECT
                CASE ( "001007" )  ! NOTE: No Table D descriptor
                  IF ( ndesc .ge. 73 ) THEN
                    SELECT CASE ( buhd (1:3) )
                      CASE ( "INC", "INS" )  ! DB CrIS FSR
                        bfstot = 'NC021212'
                        idxyear = 5
                        drptag = '(CRCHNM)'
                        ctag = 'SRAD'
                        crisn20 = .true.
                    END SELECT
                  END IF
		CASE ( "310061" )  ! ATMS
                  SELECT CASE ( buhd (1:4) )
		    CASE ( "INSX", "INSI" ) ! RARS ATMS
                      bfstot = 'NC021038'
		      idxyear = 6
		      drptag = '(ATMSCH)'
		      ctag = 'TMBR'
                    CASE ( "INST" ) ! DB ATMS
		      bfstot = 'NC021213'
		      idxyear = 6
		      drptag = '(ATMSCH)'
		      ctag = 'TMBR'
                  END SELECT
                CASE ( "340008" )  ! IASI
                  SELECT CASE ( buhd (1:3) )
                    CASE ( "IEQ", "INQ" )
                      IF ( buhd (1:4) .eq. 'INQT' ) THEN
                        bfstot = 'NC021239'  ! DB IASI
                      ELSE
                        bfstot = 'NC021039'  ! RARS IASI
                      END IF
		      idxyear = 5
		      drptag = '(IASICHN)'
		      ctag = 'SCRA'
                  END SELECT
		CASE ( "310050" )  ! AIRS
                  SELECT CASE ( buhd (1:4) )
                    CASE ( "INRT" )
		      bfstot = 'NC021249'
		      idxyear = 27
		      drptag = '(SCBTSEQN)'
		      ctag = 'TMBR'
                  END SELECT
              END SELECT
              ii = ii + 1
            END DO

C*          Print any unknown or extra descriptors to the decoder log.

            CALL EA_PUED ( cdesc, ndesc, bfstot, crisn20, ierued )

            IF ( bfstot(6:8) .eq. '???' ) CYCLE

            msgok = .true.

	    DO WHILE ( msgok )

C*	      Get the next report from this BUFR message.

	      IF ( IREADSB ( iubfme ) .ne. 0 ) THEN

C*		There are no more reports in this message.

		msgok = .false.
                CYCLE
              ENDIF

	      nrept = nrept + 1

              IF ( nrept .eq. 1 ) THEN

C*              Finish up some final checks and other calculations
C*              that couldn't be done earlier, because we needed
C*              some data values from within the first report of
C*              the BUFR message, and we hadn't yet called IREADSB
C*              to read in that first report.

                SELECT CASE ( buhd (1:3) )
                  CASE ( "INC" )

C*                  For CrIS, do an additional sanity check for
C*                  FSR content, to ensure that such reports are
C*                  processed correctly even if they start using
C*                  a Table D descriptor at some future point,
C*                  and in which case the previous logic would
C*                  have mistakenly labeled them as NSR.

                    CALL UT_BFRI ( iubfme, 'SAID', rval, iret )
                    isaid = NINT ( rval )
                    CALL UT_BFCI  ( iubfme, 'MTYP', cval, iret )
                    meastyp = cval(1:3)
                    IF ( meastyp .eq. "FSR" ) THEN
                      IF ( ( isaid .ge. 224 ) .or.
     +                     ( isaid .le. 226 ) ) THEN
                         bfstot = 'NC021212'
		         idxyear = 5
		         drptag = '(CRCHNM)'
		         ctag = 'SRAD'
                         crisn20 = .true.
                      END IF
                    END IF
                END SELECT

                SELECT CASE ( bfstot(6:8) )
                  CASE ( "037", "038", "039",
     +                   "212", "213", "239", "249" )

C*		    Get the number of delayed replication levels
C*		    for each subset in the message.  The message
C*		    is compressed, so the number of replications
C*		    will be identical for each subset.

		    CALL GETTAGPR ( iubfme, ctag, 1, ctagp, ierptg )
		    CALL ST_LSTR ( ctagp, lctagp, ier )
		    ctagpr = '(' // ctagp(1:lctagp) // ')'
		    CALL UFBINT ( iubfme, r8ary, MXVAL, 1,
     +			          ierusg, ctagpr )
		    ndrp = IDINT ( r8ary (1) )
                    ndrp1 = ndrp + 1
                  CASE ( "033", "034", "035", "036" )

C*                  Compute the expected indices of all of the
C*                  TMBRST values within each input subset.

                    idxtmbrf = 43  ! expected index of first one
                    DO ii = 1, ntmbr
                      idxtmbr (ii) = idxtmbrf + (ii-1)*6
                    END DO
                END SELECT

C*              Calculate the total number of data values in
C*              the subset, based on all of the delayed
C*              replication counts.

                SELECT CASE ( bfstot(6:8) )
                  CASE ( "037", "212" ) ! CrIS
                    IF ( .NOT. crisn20 ) THEN
                      nr8in = ( ndrp * 2 ) + 56
                    ELSE
		      CALL GETTAGPR ( iubfme, ctag, ndrp1, ctagp,
     +                                ierptg )
		      CALL ST_LSTR ( ctagp, lctagp, ier )
		      ctagpr = '{' // ctagp(1:lctagp) // '}'
		      CALL UFBINT ( iubfme, r8ary, MXVAL, 1,
     +				    ierusg, ctagpr )
                      ndrp12 = IDINT ( r8ary (1) )
		      nr8in = ( ndrp * 2 ) + ( ndrp12 * 2 ) + 641
                    END IF
                  CASE ( "038", "213" ) ! ATMS
		    nr8in = ( ndrp * 9 ) + 25
                  CASE ( "039", "239" ) ! IASI
		    CALL GETTAGPR ( iubfme, 'NNPCS', 1, ctagp, ierptg )
		    CALL ST_LSTR ( ctagp, lctagp, ier )
		    ctagpr = '(' // ctagp(1:lctagp) // ')'
		    CALL UFBREP ( iubfme, r8ary, 1, MXVAL,
     +			          ierusg, ctagpr )
		    ndrp2(1) = IDINT ( r8ary (1) )
		    ndrp2(2) = IDINT ( r8ary (2) )
		    ndrp2(3) = IDINT ( r8ary (3) )
		    nr8in = ( ndrp * 2 ) + 322 +
     +			  ndrp2(1) + ndrp2(2) + ndrp2(3)
                  CASE ( "249" ) ! AIRS
		    nr8in = ( ndrp * 4 ) + 174
                END SELECT

	      END IF

C*	      Read all of the main data values from this report.

	      CALL UFBSEQ ( iubfme, r8ary, MXVAL, 1, ierusq, bfstin )

C*            Read any supplemental values from this report.

              CALL EA_SUPP ( iubfme, bfstot, ntmbr, idxtmbr,
     +                       r8ary, nr8in, nr8ot, ieresp )

C*	      Append the bulletin ID and receipt time data to
C*	      the end of the data values array.

	      CALL UT_C2R8 ( seqnum, 8, r8ary(nr8ot+1), nr8, ier )
	      CALL UT_C2R8 ( buhd,   8, r8ary(nr8ot+2), nr8, ier )
	      CALL UT_C2R8 ( cborg,  8, r8ary(nr8ot+3), nr8, ier )
	      CALL UT_C2R8 ( bulldt, 8, r8ary(nr8ot+4), nr8, ier )
	      CALL UT_C2R8 ( bbb,    8, r8ary(nr8ot+5), nr8, ier )
	      r8ary ( nr8ot +  6 ) = FLOAT ( 0 )
	      r8ary ( nr8ot +  7 ) = FLOAT ( irundt (1) )
	      r8ary ( nr8ot +  8 ) = FLOAT ( irundt (2) )
	      r8ary ( nr8ot +  9 ) = FLOAT ( irundt (3) )
	      r8ary ( nr8ot + 10 ) = FLOAT ( irundt (4) )
	      r8ary ( nr8ot + 11 ) = FLOAT ( irundt (5) )
	      nr8ot = nr8ot + 11

C*	      Do not create BUFR output for reports that are more than
C*	      NHOURS before or more than 3 hours after the run time.

              CALL UT_CHECK_BUFRRPTDT ( 2, irundt, r8ary(idxyear),
     +            r8ary(idxyear+1), r8ary(idxyear+2), r8ary(idxyear+3),
     +            r8ary(idxyear+4), nhours, 180, irptdt, iercrt )
              IF ( iercrt .ne. 0 ) CYCLE

C*	      Open a BUFR message for output.

              ibfdt = ( irptdt (1) * 1000000 )  + ( irptdt (2) * 10000 )
     +                   + ( irptdt (3) * 100 )  +  irptdt (4)
	      CALL OPENMB ( iubfmn, bfstot, ibfdt )

C*	      Write all of the data values for this report.

              SELECT CASE ( bfstot(6:8) )
                CASE( "037", "038", "039",
     +                "212", "213", "239", "249" )
                  CALL DRFINI ( iubfmn, ndrp, 1, drptag )
              END SELECT

              IF ( crisn20 ) THEN
                SELECT CASE( bfstot(6:8) )
                  CASE( "037", "212" )
                    CALL DRFINI ( iubfmn, 1,  1, '<CRISN20>' )
                    CALL DRFINI ( iubfmn, ndrp12, 1, '{GCRCHN}' )
                END SELECT
              END IF

              SELECT CASE ( bfstot(6:8) )
                CASE( "039", "239" ) ! IASI only
                  CALL DRFINI ( iubfmn, ndrp2, 3, '(IASIPCS)' )
              END SELECT

	      CALL UFBSEQ ( iubfmn, r8ary, nr8ot, 1, ierusq, bfstot )

              CALL UT_WBFR ( iubfmn, 'ears', 0, ierwbf )

	    END DO

          END DO

	END DO

	RETURN
	END