;+
;
; dpcstr 
;
; PURPOSE
;	Decode an MDI Data Product Code into English according to the Rock 
;	Bush rules (an alternative to dpc_decode)
;
; CALLING SEQUENCE
; 	str = dpcstr(dpc,[keyword])
;
; INPUTS
; 	dpc is either a string containing a hexadecimal DPC, or an 
;	integer number.
;
; OPTIONAL INPUTS
; 	If defined, "stuff" tells what to display. If it's undefined, 
;	it defaults to "all".  Recognized key strings are:
;
;	all - Mention everything
;	obs - Describe the main observation type
;	pre - Generate a prefix for timestamp-filename generation
;	siz - Size information only 
;
; OPTIONAL OUTPUTS (by keyword)
;       size:  the size of the associated image, in pixels
;	bins:  The size of NxM bins, in pixels (currently we only 
;		support 2x2, 4x4, and 8x8)
; TO DO
;	Should understand DPCs better -- we just interpret the rules in a 
;	rudimentary fashion and don't keep track of historical or accidental
;	nuances within the rules.
;
;  BUGS 
;	Kludgey vectorization should be fixed -- it uses a for loop.
;
; HISTORY
;	8-May-97	At MDM's request, removed all non-documentation
;			references to the FUG() routine. (CED) 
;	28-April-97 	   Vectorized (in a kludgey way) (CED)
;	16-Jan-97	   Fixed problem with modding of negative numbers (CED)
;	Improved 15-Jan-97 (Regularized spacing, etc.) (CED)
; 	Written 10/14/96   (based on the description at
; 	http://www.lmsal.com/MDI/ops/dep_stuff/dpc_rules2.txt)
;	[Craig DeForest]
;	27-Feb-2006 (SEG) - Fix n2b array out of range error
;-
function dpcstr,dpc_in,stuff,size=sz,verbose=verbose,bins=bins
if not isvalid(verbose) then verbose=0
if(not isvalid(stuff)) then stuff = 'all'

allflag = (strpos(stuff,'all') ge 0)
obsflag = (strpos(stuff,'obs') ge 0)
preflag = (strpos(stuff,'pre') ge 0)
sizflag = (strpos(stuff,'siz') ge 0)


out = replicate("",n_elements(dpc_in))

for ii=0,n_elements(dpc_in)-1 do begin
	dpc = dpc_in(ii)	
	n0 = ''
	n1 = ''
	n2 = ''
	n3 = ''


	; 
	; Kludge to test the type of 'dpc':  if it's a string, adding '0' will change it;
	; if it's numeric, then it won't.
	;
	dpc2 = dpc + '0'
	
	if(dpc2 ne dpc) then begin          ; we got a string -- convert to numeric
		; Clean up the '0xF000' case -- get rid of leading '0x'.
		fmh = strpos(dpc,'0x')
		if(fmh eq -1) then fmh = strpos(dpc,'0X')
		if(fmh ge 0) then dpc = strmid(dpc,fmh+2,strlen(dpc)-fmh-2)

		dpc0 = long(0) ; Force type of dpc0 
	
		reads,dpc,dpc0,format='(z8.8)'
	end else $
		dpc0 = long(dpc)           ; we got a numeric type -- convert to long
	;print,'dpc = ',dpc,format='(a,z8.8)'
	
	;
	; Now we've got the dpc as a long int.  We convert it to hexadecimal, to make
	; sure we've got a standard format.
	;
	nybble = bytarr(8)
	snybble = strarr(8)
	
	for i=0,7 do begin
	; Extra mod is added to combat sign problem with braindead modding:
	; negative numbers yield negative mods.
		nybble(7-i) = ((ishft(dpc0,-(4*i))) mod 16 + 16) mod 16
		snybble(7-i) = (['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'])(nybble(7-i))
	end
	if verbose then print,'dpc0 = ',dpc0,format='(A,z)'
	if verbose then print,'nybbles = ',snybble
	
	;
	; OK, we've got the nybbles split out into individual characters -- we can act on each
	; one independently.
	;
	
	; Nybble 0 - Flight/Ground, low/high, general data type
	n0 = n0 + (['flt ','gnd ']) $
		(ishft(nybble(0),-3))
	n0 = n0 + (['5k   ','160k ']) $
		(ishft(nybble(0),-2) mod 2)
	n0 = n0 + (['std-sci ','lfig-sci','IP-engrg','misc.   ']) $
		(nybble(0) mod 4)
	
	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; Science & Limb Figure interpretation
	;
	if( (nybble(0) mod 4) le 1 ) then begin 
		; Nybble 2 - Nastiness!  The upper two bits give us info on the generation; the lower
		; two bits are part of the next thing.
		n1 = n1 + ([	'60S ', 	'30S ', 't-w ', '    '  ]) $
			(ishft(nybble(2),-2))
	
		; Nybble 1 - Relatively easy.
		n1 = n1 + ([	$
		'filtergram   ','FD filt (sum)','FD dop (raw) ','FD dop (BP 0)',$
		'HR line depth','FD ldpth w/FF','FD continuum ','FD cont  w/FF',$
		'FD magnetogm ','FD mag  (sum)','HR dopplergm ','HR magnetogm ',$
		'FD line depth','HR continuum ','UNKNOWN (E)  ','UNKNOWN (F)  '	$
		     ]) $
			(nybble(1))
	
		n1a = (['filt','filt','fddop','fddop',$
			'hrld',		'fdld',		'fdcont',	'fdcont',$
			'fdmag',	'fdmag',	'hrdop',	'hrmag', $
			'fdld',		'hrcont',	'',		''])(nybble(1))
	
		n2b = nybble(3) + 16 * (nybble(2) mod 4)

		if (n2b eq 21) then begin ;;--------SEG 27-Feb-2006 Fix n2b array out of range error --------
			n2b = n2b + 1
		endif
	
		if( (nybble(1) le 1) and (n2b le 21)) then $ ; Special filtergram case
				n1 = strtrim(n1,2) + ([	$
			 	'              ',' (smpl filtgm)',' (TAP burst)  ',' (TAP cont)   ',$
				' (Ice dk)     ',' (Ice FD CAL) ',' (ice HR CAL) ',' (comp. test) ',$
				' (HR cont)    ',' (Intmdt Sd)  ',' (Intmdt Si)  ',' (FD cont)    ',$
				' (hi cdnce HR)',' (FD CAL dtun)',' (FD OBS dtun)',' (focus)      ',$
				' (HR lgt xfer)',' (dark)       ',' (full dark)  ',' (phs dvsy HR)',$
				' (FD lgt xfer)'])(n2b) $
			else $
				n1 = n1 + string('(vers. 0x',n2b,')',format='(A,Z2,A)')
		
	end else if( (nybble(0) mod 4) eq 2 ) then begin
		; IP Engineering!
		n1 = n1 + '    ' + $ ; Extra space to skip the time specifier...
			([ $
	;	'             ','             ','             ','             '
		'IP Reg Dump  ','IP Table Dump','IP BinLst Dmp','IP Lmb Fg Dmp',$
		'IP Memory Dmp','1/5-p Mem Dmp','Unknown (6)  ','Unknown (7)  ',$
		'Unknown (8)  ','Unknown (9)  ','ISS HR smpld ','Unknown (B)  ',$
		'Unknown (C)  ','Unknown (D)  ','IP Err Dump  ','Unknown (F)  ' $
		])(nybble(1))
	
		case nybble(1) of
		0: if(nybble(3) eq 1) then $
			n1 = n1+'(Reg dump)   ' else n1=n1+'(Unknown)    '
		1: case nybble(4) of
			1: n1=n1+'(reciprocal) '
			2: n1=n1+'(velocity  ) '
			3: n1=n1+'(square-root)'
			else: n1=n1+string('(unk. vrs. ',n4,')',format='(a,z1,a)')
		   endcase
		2: case n4 of
			5: n1=n1+'(rwbin list) '
			6: n1=n1+'(vwbin list) '
			7: n1=n1+'(LOI list)   '
			14:n1=n1+'(Limb figure)'
			0: n1=n1+'(crop list)  '
			else: n1=n1+string('(unk. vrs. ',n4,')',format='(a,z1,a)')
		   endcase
		else: n1 = n1 + '             '
		endcase
	end else	n1 = n1 + '(Sim or Test Data)        '
	         
		; 
	;
	; Put memory dump decoding here if desired....
	;
	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; Data format
	
	if((nybble(0) mod 4) le 1) then begin  ; Science observable data formats...
		n3 = n3 + ([								$
			'cropped linear image ',	'cropped sqrt#1 image ',	$
			'extracted linear image ',	'extracted sqrt#1 image ',	$
			'NxM binned image ',		'RW binned image ',		$
			'VW binned image ',		'IW binned image ',		$
			'AW binned image ',		'circular buffer ',		$
			'Cropped sqrt#2 image ',	'full image 1040x1033 ',	$
			'extracted sqrt#2 image ',	'Unknown (D) ',			$
			'Unknown (E) ',			'Unknown (F) '			$
			])(nybble(4))
	
	;
	; Stick formatting information here (bits 0 - 14)
	;
	end
	
	;
	; Stick other kinds of data format info here...
	;
	
	;
	; We read the shape information from the last few nybbles and stick it into our height and width modifiers...
	word = snybble(4)+snybble(5)+snybble(6)+snybble(7)
	
	sbf = 'subfield'
	sz = -1
	
	n4 = ''
	if(verbose) then print,'word = '+word
	
	if word eq '0fc0' then begin & sz = [1024,1024] & n4 = 'cropped' 	& end
	
	if nybble(4) eq 2 then begin
		if word eq '2000' then begin & sz = [1024,1024] & n4 = 'full-field'    	& end
		if word eq '2201' then begin & sz = [1024,128]  & n4 = 'subfield'    	& end
		if word eq '2202' then begin & sz = [128,1024]  & n4 = 'subfield'    	& end
		if word eq '2400' then begin & sz = [256,256]   & n4 = 'subfield'    	& end
		if word eq '2100' then begin & sz = [300,300]   & n4 = 'subfield' 	& end
		if word eq '2300' then begin & sz = [350,350]   & n4 = 'subfield'	& end
		if word eq '2500' then begin & sz = [400,400]   & n4 = 'subfield'	& end
		if word eq '2700' then begin & sz = [450,450]   & n4 = 'subfield'	& end
		if word eq '2900' then begin & sz = [550,550]   & n4 = 'subfield'	& end
		if word eq '2a00' then begin & sz = [1024,600]  & n4 = 'subfield'	& end
		if word eq '2b00' then begin & sz = [1024,640]  & n4 = 'subfield'	& end
		if word eq '2b01' then begin & sz = [640,1024]  & n4 = 'subfield'	& end
		if word eq '2c00' then begin & sz = [128,128]   & n4 = 'subfield'	& end
		if word eq '2d00' then begin & sz = [1024,500]  & n4 = 'subfield'	& end
		if word eq '2d01' then begin & sz = [500,1024]  & n4 = 'subfield'	& end
		if word eq '2e00' then begin & sz = [1024,800]  & n4 = 'subfield'	& end
		if word eq '2f00' then begin & sz = [1024,850]  & n4 = 'subfield'	& end
		if word eq '2040' then begin & sz = [1024,750]  & n4 = 'subfield'	& end
		if word eq '2140' then begin & sz = [1024,700]  & n4 = 'subfield'	& end
	end else if snybble(4) eq '3' then begin
		if word eq '3000' then begin & sz = [1024,1024] & n4 = 'subfield'	
		end else n4 = 'Random sqrt subfield' 	
	end else begin
		if word eq '4400' then begin & sz = [256,256]   & n4 = '(4x4-binned) full-field' & bins=[4,4]  	& end
		if word eq '4800' then begin & sz = [512,512]   & n4 = '(2x2-binned) full-field' & bins=[2,2] 	& end
		if word eq '4c00' then begin & sz = [128,128]   & n4 = '(8x8-binned) full-field' & bins=[8,8]  	& end
		if word eq '5001' then begin & sz = 12453       & n4 = 'RWBIN/golf-proxy'           	& end
		if word eq '6001' then begin & sz = 180         & n4 = 'VWBIN/medium-l'             	& end
		if word eq '7001' then begin & sz = 180         & n4 = 'IRBIN/LOI'                  	& end
		if word eq '9001' then begin & sz = 220800      & n4 = 'circular-buffer'            	& end
		if word eq 'afc0' then begin & sz = [1024,1024] & n4 = 'cropped'                    	& end
		if word eq 'b000' then begin & sz = [1040,1033] & n4 = 'Full-unexpurgated-CCD-field'	& end
		if word eq 'c001' then begin & sz = 245760      & n4 = 'Extract-3-strips-1024x80'   	& end
		if word eq 'afb0' then begin & sz = 17878       & n4 = 'limb-figure'                	& end
		if word eq 'cf58' then begin & sz = 20624       & n4 = 'limb-figure'                	& end
	end
	
	if(sz(0) lt 0) then n4 = n4 + '(Unknown shape)'
	
	
	if ( (size(sz))(0) eq 1 ) and ( (size(sz))(1) gt 1 ) then $
		ssz = strtrim(sz(0),2)+'x'+strtrim(sz(1),2)+'-pixel' $
	else if (sz ge 0) then $
		ssz = strtrim(sz,2) + '-pixel' $
	else    ssz = ''
	
	n4 = ssz + ' ' + n4 + ' '                    
	if(strlen(n1) eq 0) then n1 = ' '
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;
	; Assemble and return the stuff...
	;

	if(allflag) then out(ii) = strtrim(n0+n4+n1+n2)
	if(obsflag) then out(ii) = strtrim(n1)
	if(preflag) then out(ii) = strtrim(n1a)
	if(sizflag) then out(ii) = strtrim(n4)
end

if(n_elements(out) eq 1) then return,out(0) else return,out
				
end
