function sag_ext_mnem, data, mnem, data_sou, $
		string=string, raw_value=raw_value, nostring=nostring, $
		qdebug=qdebug, qstop=qstop, ss_cond=ss_cond, init=init
;+
; $Id: sag_ext_mnem.pro 12405 2013-01-26 02:11:04Z sabolish $
; 
; $Name:  $
;
;NAME:
;	sag_ext_mnem
;PURPOSE:
;	LM/SAG routine to extract mnemonic information from data
;SAMPLE CALLING SEQUENCE:
;	out = sag_ext_,nem(data, mnem, data_sou)
;	out = sag_ext_mnem(be, 'iuispzta')
;INPUTS:
;	data	- Raw data.  Form is 2-D where first D is the
;		  packet (or image header) and the second D is for 
;		  time (or image #).  It must be BYTE type
;	mnem	- Single mnemonic to extract
;OPTIONAL INPUT:
;	data_sou- Source of data.  It is a string of value
;			'HK': - input data is raw HK packets
;			'DP': - input data is raw data product header
;		  Default is "HK".
;HISTORY:
;	Written 23-Sep-99 by M.Morrison using TRACE GTT_MNEM.PRO as start
;	28-Sep-99 (MDM) - Put in protection for out of range extract
;	 5-Oct-99 (MDM) - Fixed discrete (string) type outputs
;	14-Oct-99 (MDM) - Added "IS1" (signed 16 bit number)
;	 9-May-02 (MDM) - Added conditionals option
;	18-Jan-07 (GAL)	- Added "R1 and R2" unsigned types
;	31-Aug-07 (GAL) - Using cvs to doc changes, and correct non-byte-aligned data
;	21-Nov-07 (GAL) - Add ylog conversions 
;	 4-May-09 (GAL) - Changed dtyp "UL4" (Unsigned-Long) result from float to uLong and for 
;				dtyp "U" added a conv to uLong (was long, which has sign bit). 
;	 5-May-09 (GAL) - Changed what was dtyp "ULI" (not sure what this was) to "UL1" and 
;				added a conv to uLong (was also long).  
;   	13-Oct-09 (GAL) - Updated byte-swap code to work for Solaris-Intel platform.  See "swapping"
;   	    	    	    below for details. Old code commented-out and not removed.
;   	    	    	    This change is for SUVI.
;	21-Feb-10 (GAL) - Updated byte-swap code to work for Mac OS, Intel platform. Added logic to 
;			catch Mac OS on intel.
;	26-Jun-12 (GAL) - For IRIS, added 64-bit containers for the SC tlm. Adding U61,U68 for unsigned
;			no swap and 64-bit swapped words. Also, added R61 and R62 for Double-type, no swap
;			and 64-bit swapped words.
;
; $Log: sag_ext_mnem.pro,v $
; Revision 1.9  2009/05/06 17:22:33  linford
; Changed dtyp ULx return from long to ULong and added print statements for qdebug
;
; Revision 1.8  2008/07/30 17:42:24  linford
; fixed roundoff error in polynom. calculation, raw and out are now doubles in conversions for A-type
;
; Revision 1.7  2007/12/04 16:58:32  linford
; Add YSI or ylog conversions
;
; Revision 1.6  2007/09/05 16:24:33  linford
; fix typo on qdebug line
;
; Revision 1.5  2007/09/04 21:31:11  linford
; completed the new use of signed byte by adding logic for SB type
;
; Revision 1.4  2007/09/04 18:38:50  linford
; finish fix for making a two's complement 8-bit conversion for IS1 types
;
; Revision 1.3  2007/08/31 23:19:29  linford
;  correct non-byte aligned data IS1
;
; Revision 1.2  2007/08/31 23:01:58  linford
; add cvs logging, correct non-byte aligned data IS1
;
;-
;
common sag_hk_dbase_blk1, tlm, alg, ylg, dsc, cmd, cond
;
if (n_elements(tlm) eq 0) then stat = execute(getenv('SAG_EGSE_DB_RD_PRO'))
if (n_elements(tlm) eq 0) then begin
    print, 'Read problem with HK database.  Cannot continue.  Stopping...
    stop
end
;
if (n_elements(data_sou) eq 0) then data_sou = 'HK'
;
if (data_type(mnem) ne 7) then begin	;non string type
    print, 'SAG_EXT_MNEM: Input mnemonic list must be string
    return, -1
end
;
if (n_elements(mnem) ne 1) then begin	;array of mnemonics
    print, 'SAG_EXT_MNEM: Only one mnemonic at a time'
    print, 'MNEM=', mnem
    return, -1
end
if (n_elements(data) eq 0) then begin
    print, 'SAG_EXT_MNEM: No input data passed in'
    return, -1
end
;
n = data_chk(data, /ny) > 1
len = data_chk(data, /nx)
if (data_type(data) ne 1) then begin
    data = byte(data, 0, len*2, n)
end
;
ss = where(tlm.name eq strlowcase(mnem), nss)
if (nss eq 0) then begin
    print, 'SAG_EXT_MNEM: Mnemonic not found in database....................' + mnem
    return, -1
end
;
tlm0 = tlm(ss)
if (keyword_set(qdebug)) then help, /st, tlm0
;
;---- Conditional check

ssout = lindgen(n)
nout = n
if (tlm0.cond ne '') then begin
    ss2 = where(cond.name eq tlm0.cond, nss2)
    if (nss2 ne 1) then stop, tlm0.cond + ' conditional not found in database'
    cond0 = cond(ss2(0))
    ;
    mnem_cond = cond0.mnem
    v = sag_ext_mnem(data, mnem_cond, 'HK')

    v_ok = fix(str2arr(cond0.list, delim=':'))

    qok = is_member(v, v_ok)	;trim down to ok items
    ssout0 = where(qok, nout0)
    if (nout0 eq 0) and (not keyword_set(init)) then return, -1
    if (not keyword_set(init)) then begin
	ssout = ssout0
	ss_cond = ssout0
	nout = nout0
    end
end
;--------

;
ii = 0
if (strupcase(data_sou) eq 'DP') then ii = (where(tlm0.apid eq 'DPH'))(0)
if (ii eq -1) then begin
    print, 'SAG_EXT_MNEM: Mnemonic ' + mnem + ' is not in the Dataproduct header'
    return, -1
end
;
stbyte = tlm0.stbyte(ii)
if (stbyte ge len) then begin
    print, 'SAG_EXT_MNEM: Mnemonic ' + mnem + 'is outside the packet length
    return, -1
end

;-- get the container type CODE for the data:
dtyp = tlm0.type		; container type CODE
stbit = tlm0.stbit		; start bit, for byte aligned is =0
nbit = tlm0.nbit		; bit length

if (keyword_set(qdebug) ) then begin
	print, 'SAG_EXT_MNEM: Mnemonic = ' + mnem
	print, 'SAG_EXT_MNEM: container type CODE: '+ dtyp
	print, 'SAG_EXT_MNEM: start bit = ', stbit
	print, 'SAG_EXT_MNEM: bit length =', nbit
	print, 'SAG_EXT_MNEM: start byte =', stbyte
end 

; Step 1, extract the cantainer per the "dtyp" 
case dtyp of
	'UL1':	out = long( data(stbyte:stbyte+3, ssout), 0, nout)			;32 bits 01020304 no swap
	'SL1':	out = long( data(stbyte:stbyte+3, ssout),0, nout)			;32 bits signed
	'UI1':	out = fix(  data(stbyte:stbyte+1, ssout), 0, nout)			;16 bits 0102 no swap
	'SI1':	out = fix(  data(stbyte:stbyte+1, ssout), 0, nout)			;16 bits signed
	'SSCHW':out = long(  data(stbyte:stbyte+3, ssout), 0, nout)			;32 bits 02010403 byte-swap shorts
	'USCHW':out = long(  data(stbyte:stbyte+3, ssout), 0, nout)			;32 bits signed
	'UI2':	out = fix(  data(stbyte:stbyte+1, ssout), 0, nout)			;16 bits 0201 byte-swap shorts
	'SI2':	out = fix(  data(stbyte:stbyte+1, ssout), 0, nout)			;16 bits signed
	'U64':	out = long64( data(stbyte:stbyte+7, ssout), 0, nout)			;64 bits
	'S64':	out = long64( data(stbyte:stbyte+7, ssout), 0, nout)			;64 bits
	'DBL':	out = double( data(stbyte:stbyte+7, ssout), 0, nout)			;64 bits
	'SCF':	out = float( data(stbyte:stbyte+3, ssout), 0, nout)			;32 bits
	'UB':	out = fix(reform(data(stbyte, ssout)))					;8 bits
	'SB':	out = fix(reform(data(stbyte, ssout)))					;8 bits (note, needs fix below)
	;
	else:  begin
		out = long( data(stbyte:stbyte+3, ssout), 0, nout)			;32 bits, default
		print, 'SAG_EXT_MNEM: Unknown type, '+dtyp+' assuming 32-bit unsigned'
	end 
endcase

if (keyword_set(qdebug)) then print,'SAG_EXT_MNEM: [mnem, dtyp] = ',mnem,' ,',dtyp
if (keyword_set(qdebug)) then help,out
if (keyword_set(qdebug)) then print,'SAG_EXT_MNEM: extracted container: out =',out

;
;---- Do byte swapping for non-SGI machines...
;

; Following line was commented-out 13-Oct-09 for SUVI, Solaris-Intel platform
;qswap = is_member(/swap_os)

; New byte-swap code (perhaps is Sun centric but works for now):
machos = !version
qswap = is_member(/swap_os)
if ((qswap eq 0) and (machos.arch eq 'x86_64') and (machos.os eq 'sunos')) then begin
    qswap = 1
end
; New byte-swap code for Mac OS:
if ((qswap eq 0) and (machos.arch eq 'x86_64') and (machos.os eq 'darwin')) then begin
	qswap = 1
end
if (qswap) then dec2sun, out

if (keyword_set(qdebug)) then print,'SAG_EXT_MNEM: byte swap flag qswap: =',qswap
if (keyword_set(qdebug)) then print,'SAG_EXT_MNEM: extracted container BYTE-SWAPPED: out =',out
;
;---- Adjust the datatype as necessary (byte swapping, unsigning, masking) per EGSE rules
;	for field type processing.
;
case dtyp of
	'UL1':	out = ulong(out)				
	'SL1':	out = long(out)					
	'UI1':	out = uint(out)					;might need to do out=unsign(out) instead, though output format would be 32 bits
	'SI1':	out = fix(out)
	'SSCHW':begin						;0123 becomes 1032
			byteorder, out, /sswap			;swap bytes in shortword
			out=long(out)
		end
	'USCHW':begin						;0123 becomes 1032
			byteorder, out, /sswap			;swap bytes in shortword
			out = ulong(out) 	
		end
	'UI2':	begin						;0123 becomes 1032
			byteorder, out, /sswap			;swap bytes in shortword
			out = uint(out)				;might need to do out=unsign(out) instead, though output format would be 32 bits	
		end
	'SI2':	begin						;0123 becomes 1032
			byteorder, out, /sswap			;swap bytes in shortword
			out = fix(out)					
		end
	'U64':	begin						;01234567 becomes 76543210
			byteorder, out, /L64swap		;swap bytes in 8-byte word
			out = ulong64(out)
		end
	'S64':	begin						;01234567 becomes 76543210
			byteorder, out, /L64swap		;swap bytes in 8-byte word
			out = long64(out)			
		end
	'DBL':	out = double(out)			
	'SCF':	out = float(out)
;;	'UB':	out = out			
	'SB':	begin
			for i=0L,n_elements(out)-1 do begin			; convert into 8-bit two's comp. signed val.
				if ( out[i] ge 128 ) then out[i] = out[i] - 256	
			endfor
		end
	else:	print, 'SAG_EXT_MNEM: Unknown type, '+dtyp+' no byte swapping performed'
endcase

;
if (keyword_set(qdebug)) then print, n, nout, ss, stbyte, dtyp, tlm0.stbit, tlm0.nbit
if (keyword_set(qdebug)) then help,out
;
case dtyp of
	'UL1':	nbit4type = 32
	'SL1':	nbit4type = 32
	'UI1':	nbit4type = 16
	'SI1':	nbit4type = 16
	'SSCHW':nbit4type = 32
	'USCHW':nbit4type = 32
	'UI2':	nbit4type = 16
	'SI2':	nbit4type = 16
	'U64':	nbit4type = 64
	'S64':	nbit4type = 64
	'DBL':	nbit4type = 64
	'SCF':	nbit4type = 32
	'UB':	nbit4type = 16
	'SB':	begin
			twoComplement=1
			nbit4type=16
		end
	else:	begin
			nbit4type = 32
			print, 'SAX_EXT_MNEM: Unknowon type, '+dtyp+' no masking performed'
		end
endcase

if (nbit4type ne tlm0.nbit) then begin
    stbit = nbit4type - tlm0.stbit - tlm0.nbit	;database terminology has bit0=MSB
    if (keyword_set(qdebug)) then print, 'Masking... stbit=', stbit
    out = mask(out, stbit, tlm0.nbit)
    if (keyword_set(qdebug)) then print,'Masked out value= ', out
    if ( n_elements(twoComplement) ne 0 ) then begin
	    for i=0L,n_elements(out)-1 do begin			; convert into 8-bit two's comp. signed val.
		    if ( out[i] ge 128 ) then out[i] = out[i] - 256	
	    end
	    if (keyword_set(qdebug)) then print,'Converted to Twos Comp. Signed out value= ', out
    end 
end
if (keyword_set(qdebug)) then help,out
;
;--------------------------- Conversions
;
if (not keyword_set(raw_value)) then begin
    case tlm0.conv_code of
	'A': begin
		ss = where(alg.name eq tlm0.conv, nss)
		raw = double(out)
		out = 0d
		coeff = alg(ss(0)).coeff
		for i=0L,n_elements(coeff)-1 do out = out + coeff(i)*raw^i
	     end
	'Y': begin
		;print, 'Convert to YLOG units using either 5k or 10k'
		ss = where(ylg.name eq tlm0.conv, nss)	; compare "YSI_5/10K_THERMISTOR" names
		ylg0 = ylg(ss)
		;print, 'Using YSI type conversion: ', ylg0.name
		;print, ylg0.descr
		;print, ylg0.acoeff
		;print, ylg0.ccoeff
		raw = float(out)
		res = (1.0+raw*ylg0.dcoeff/ylg0.ecoeff)/(ylg0.fcoeff-(raw/ylg0.ecoeff))
		out = 1.0/(ylg0.acoeff+ylg0.bcoeff*alog(res)+ylg0.ccoeff*alog(res)*alog(res)*alog(res))-ylg0.gcoeff
	     end
	else:
    endcase
end
if (not keyword_set(raw_value)) and (not keyword_set(nostring)) then begin
    case tlm0.conv_code of
	'D': begin
		ss = where(dsc.name eq tlm0.conv, nss)
		dsc0 = dsc(ss)
		ntabmax = max([dsc0.low, dsc0.hi])
		table = strarr(ntabmax+2) + '???'
		for i=0L,nss-1 do begin		;build the lookup table
		    ist = dsc0(i).low > 0 < ntabmax
		    ien = dsc0(i).hi  > 0 < ntabmax
		    table(ist:ien) = dsc0(i).str
		end
		nnn = n_elements(table)-1
		out = table(out >0<nnn )
	     end
	else:
    endcase
end
;
if (n_elements(out) eq 1) then out = out(0)	;make it scalar
if (keyword_set(qstop)) then stop
return, out
end
