;
;*++ mls28FEB98		analog subroutines for cmd monitor: Disti Cert 98
;
		; modified 3/21/98 -jea
		;
		;*********************************************************************
		; A/D interface functions
		;*********************************************************************
ReadAD	; This routine uses ReadADn to get the A/D value from channel n
		;*********************************************************************
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"ANn\r", CmdPC, "Read A/D channel n\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; The channel selection is passed in the WREG (it is necessary to 
		;  bring it in from the cmd monitor). It is necessary to pass in the 
		;  channel, then convert the results and wrap the appropriate
		;  text around the answer to be returned to the user.
		; Both the  selected Channel and value is returned.
		; 
		call	SetupAD				; init A/D
		movlw	cmdPrmBuff			; load parameter buffer address
		movwf	FSR1				;  into FSR1 
		movfp	INDF1, WREG			; put channel selection into WREG
		call	ReadADn				; read specified analog channel
		; generate output string
		CpyTbl2Out	AnD				; init beginning of output buffer
		movlb	5					; be sure bank 5 stil selected
		swapf	ADCON0, w			; move channel to w and swap ends
		andlw	0x00F				; mask extraneous bits
		call	Dec2Buf				; convert channel into output buffer
		CpyTbl2Out	EqtD			; add = text
		movfp	ADRESH, WREG		; get 0, 1, 2, or 3 from MSbyte
		andlw	0x03				; mask out upper bits
		call	Dec2Buf				; convert msb of value with no leading 0
		movfp	ADRESL, WREG		; get lsb of a/d value
		call	Hex2Buf				; convert lsb as a hex number
		CpyTbl2Out	FsD				; add trailing text
		return						; return from Cmd
		; This is the end of the functions executable code
		;
		; These data statements store constant ascii output strings in program 
		;  memory. They're accessed using the CpyTbl2Out macro.
AnD		; constant string for analog channel
	data	"\nAN",0
EqtD	; constant string for =
	data	" = ",0
FsD		; constant string for trailing text
	data	" hex, of 3FF Full Scale\n\r",0
		; 
		; 
		;*********************************************************************
ReadTmp	; This routine uses ReadADn to read the thermister on A/D channel 4
		;*********************************************************************
		;
		; install this command in the CmdMenu lookup table
	CmdPC = $						; save current inline assembly PC value
	org CurCmdMenuAdr				; set assembly PC to addr for new entry
	; CmdMenu table entry
	data	"T\r", CmdPC, "Read thermnister on A/D channel 4\r\n"
	CurCmdMenuAdr = $				; set current CmdMenu addr for next entry
	org CmdPC						; begin cmd code gen at inline address
		;
		; This routine uses ReadADn to get the raw ADC count. Channel 
		;  selection is passed in the WREG (4 for the Thermistor). The 
		;  following assumption may be used to convert from raw ADC to 
		;  degrees F: within a small range around room temperature, the ADC 
		;  count changes one count per degree F; the 10 bit count at 77 deg F 
		;  is dec 930. Hint: the two MSbs are always set at room temperature
		;  together they are worth 256 + 512 = 768. 
		;
		call	SetupAD				; init A/D
		movlw	4					; select channel 4
		call	ReadADn				; get raw adc count (ignore 2 MSBs)
		CpyTbl2Out	ThrmD
		movlb	5					; bank select
		movlw	0x055				; in addition to two msbs (being ignored)
		subwf	ADRESL, W			;  subtract 85 from lsb for temperature F
		call 	Dec2Buf				; convert into output buffer
		CpyTbl2Out	DegD			; add trailing text
		return						; return from Cmd
		; This is the end of the functions executable code
		;
		; These data statements store constant ascii output strings in program 
		;  memory. They're accessed using the CpyTbl2Buf and CpyTblCont macros 
		;  with the addresses given by the labels.
ThrmD	; constant string for thermister
	data	"\nThermistor temp = ", 0
DegD	; constant string for trailing text
	data	" deg Fahrenheit\n\r", 0
		;
		;*********************************************************************
ReadADn	; Read the A/D channel specified in W
		;*********************************************************************
		;
		; This subroutine selects the channel, waits for settling time, starts
		;  the conversion, waits for completion, then returns - leaving the 
		;  result in ADRESx. It is called while WREG contains channel (0 - 11)
		;  inclusive leaves right justified result in ADRESL and 'H and
		;  insures channel selected does not exceed 11.
		; 
		movlb	5					; AD work in Bank 5
		andlw	0x0F				; test and limit channel to valid range
		movwf	ADRESH				; temporary storage
		btfsc	ADRESH, 3 			; 12 or greater is invlalid: 
		bcf		ADRESH, 2 			;  if 8 set insure 4 is not
		swapf	ADRESH, W			; value belongs in upper nibble
		iorlw	0x01				; also turn on AD without starting conv
		movwf	ADCON0				; load into A/D control reg
		; delay settle time, ~50 uSec: ~200 instruction cycles at 16 MHz
		movlw	0x040				; 64 * 3 * .25 uSec = 48uSec
		movwf	ADRESH				; temporary storage
		decfsz	ADRESH				; decrement until 0
		goto	$-1					;  until then wait
		bsf	ADCON0, 2				; start conversion
		btfsc	ADCON0, 2			; loop til conversion complete
		goto	$-1
		return						; return with results in ADRESx
		;
		;*********************************************************************
SetupAD	; Init the A/D peripheral
		;*********************************************************************
		;
		; Instructions: (Don't forget to select Bank)
		; ADCON0
		;  Select AN0, Turn on AD, do not start AD
		; ADCON1
		;  The processor clock is 16MHz; select the AD conversion clock so 
		;   Tad is fast, but in spec.  Right justify for ease of processing.
		;  Enable all analog inputs. Use Vdd & Vss as Ref rails.
		;  Make sure the relevant data direction bits are set!
		; 
		movlb	5					; select bank 5
		movlw	b'00000001'			; Select AN0, turn on AD, do not start AD
		movwf	ADCON0				; in ADCON0
		movlw	b'01110000'			; Tad clk = Fosc/32 = 2 uSec Tad per.
									; Right justify, Enable all analog inputs
									; Use Vdd & Vss as Ref rails
		movwf	ADCON1				; in ADCON1
		movlw	0x0F				; mask to set digital input
		iorwf	DDRG				; in DDRG for AN0 - AN3
		movlw	0xFF				; mask to set digital input
		iorwf	DDRF				; on DDRF for AN4 - AN11
		return						; return with A/D initialized

; end of file a2dcmd.asm ********************************************************