COMMENT *

This file is used to generate DSP code for the TIMII second generation 
    timing board. This is Rev. 3.00 software.     
Put rarely used and non-time critical routines in SRAM program memory 
	(P: > $200) since it carries a wait state penalty
The timing board controls the exposure and turns on the analog power
	(MASTER = TIMING option)
	*
	PAGE    132     ; Printronix page width - 132 columns

; Define a section name so it doesn't conflict with other application programs
	SECTION	TIM

; Include a header file that defines global parameters
	INCLUDE "/home/leach/DSPlib/timhdr.asm"

APL_NUM	EQU	0	; Application number from 0 to 3
CC	EQU	SHUTTER_CONTROL

; Include miscellaneous timing commands
        INCLUDE "/home/leach/DSPlib/timCCDmisc.asm"

;SXMIT	EQU     $00F060	; Series transmit A/D channels #0 to #3
;SXMIT	EQU     $00F020	; Series transmit A/D channels #0 to #1
;SXMIT	EQU     $00F000	; Series transmit A/D channel #0 only
;SXMIT  EQU     $00F021	; Series transmit A/D channel #1 only
;SXMIT  EQU     $00F042	; Series transmit A/D channel #2 only
;SXMIT  EQU     $00F063	; Series transmit A/D channel #3 only
;SXMIT  EQU     $00F062	; Series transmit A/D channels #2 to #3
;SXMIT	EQU     $00F0A0	; Series transmit A/D channels #0 to #5
;SXMIT	EQU     $00F0E4	; Series transmit A/D channels #4 to #7
;SXMIT	EQU     $00F0E0	; Series transmit A/D channels #0 to #7
;SXMIT	EQU     $00F0A2	; Series transmit A/D channels #2 to #5

SXMIT	EQU     $00F060

;**************************************************************************
;                   	                                                  *
;    Permanent address register assignments                               *
;	 R1 - Address of SSI receiver contents				  *
;	 R2 - Address of SCI receiver contents				  *
;        R3 - Pointer to current top of command buffer                    *
;        R4 - Pointer to processed contents of command buffer		  *
;        R5 - Temporary register for processing SSI and SCI contents      *
;        R6 - CCD clock driver address for CCD #0 = $FF80                 *
;                It is also the A/D address of analog board #0            *
;                                                                         *
;    Other registers                                                      *
;        R0, R7 - Temporary registers used all over the place.            *
;        R5 - Can be used as a temporary register but is circular,        *
;               modulo 32.       					  *
;**************************************************************************

;  Specify execution and load addresses
	IF	@SCP("DOWNLOAD","HOST")
	ORG	P:APL_ADR,P:APL_ADR		; Download address
	ELSE
	ORG     P:APL_ADR,P:APL_NUM*N_W_APL	; EEPROM address
	ENDIF

; Keep the CCD idling when not reading out
IDLE	DO      Y:<NSR,IDL1     ; Loop over number of pixels per line
	MOVE    #<SERIAL_IDLE,R0 ; Serial transfer on pixel
	JSR     <CLOCK  	; Go to it
	JSR	<GET_RCV	; Check for FO or SSI commands
	JCC	<NO_COM		; Continue IDLE if no commands received
	ENDDO   		; Cancel the DO loop system stack numbers
	JMP     <CHK_SSI	; Go process header and command
NO_COM  NOP
IDL1	
	MOVE    #<PARALLEL,R0	; Address of parallel clocking waveform
	JSR     <CLOCK  	; Go clock out the CCD charge
	JMP     <IDLE

; Fast clear of CCD, executed as a command
CLEAR	JSR	<CLR_CCD
	JMP     <FINISH

; Fast clear image before each exposure, executed as a subroutine
CLR_CCD	DO      Y:<NPCLR,LPCLR	; Loop over number of lines in image
	MOVE    #<PARALLEL,R0	; Address of parallel transfer waveform
	JSR     <CLOCK  	; Go clock out the CCD charge
	NOP			; Do loop restriction
LPCLR
	MOVE	#TST_RCV,X0	; Wait for commands during exposure
	MOVE	X0,X:<IDL_ADR	;  instead of idling
	RTS

;  ***********************   CCD  READOUT   ***********************
; Overall loop - transfer and read NPR lines
;
; Clear out the serial shift register
RDCCD	BSET	#ST_RDC,X:<STATUS 	; Set status to reading out
	BSET	#WW,X:PBD		; Set WW = 1 for 16-bit image data
	JSET	#TST_IMG,X:STATUS,SYNTHETIC_IMAGE
	MOVE	#(END_SERIAL-SERIAL-1),M1
	MOVE	#(END_SERIAL-SERIAL),X0
	MOVE	Y:<NSR,X1		; Compute number of waveform entries
	MPY	X0,X1,B
	ASR	B			; Correct for multiplication left shift
	ASR	B			; /2 for dual or quad readout
	MOVE	B0,A
	MOVE	X:<ONE,X1
	SUB	X1,A
	MOVE	A1,Y:<NCLKS		; Y:<NCLKS = (END_SERIAL-SERIAL)*NSR-1

	DO      Y:<NSCLR,LSCLR		; Loop over number of pixels to skip
        MOVE    #<SSKIP,R0      	; Address of serial skipping waveforms
        JSR     <CLOCK          	; Go clock out the CCD charge
        NOP                     	; Do loop restriction
LSCLR  

; Start the loop for parallel shifting desired number of lines
	MOVE	Y:<NPR,A
	LSR	A			; For quad readout
	DO      A,LPR 		     	; Loop over each line readout
	MOVE	A,P:RSTWDT 		; Reset watchdog timer

; Once per line check for a command. Only the ABORT command is allowed
	JSR	<GET_RCV		; Was a command received?
	JCC	<CONT_RD		; If no, continue reading out
	JMP	<CHK_SSI		; If yes, go process it

; Abort the readout currently underway
ABR_RDC	JCLR	#ST_RDC,X:<STATUS,START	; Do nothing - we're not reading out
	ENDDO				; Properly terminate LPR readout loop
	JMP	<RDC_END

; High efficiency serial shift code
CONT_RD	MOVE	#<SERIAL,R1
	MOVE    #<PARALLEL,R0		; Address of parallel clocking waveform
	JSR     <CLOCK          	; Go clock out the CCD charge
        MOVE    Y:(R1)+,A       	; Start the pipeline
	DO	Y:<NCLKS,LSR		; Number of waveform entries per line
        MOVE    A,X:(R6) Y:(R1)+,A      ; Send out the waveform
LSR
        MOVE    A,X:(R6)        	; Flush out the pipeline
LPR					; End parallel clocking

; Restore the controller to non-image data transfer and idling if necessary
RDC_END	BCLR	#WW,X:PBD		; Clear WW to 0 for 32-bit commands
	BCLR	#ST_RDC,X:<STATUS 	; Set status to reading out
	JCLR	#IDLMODE,X:<STATUS,START ; Don't idle after readout
	MOVE	#IDLE,X0
	MOVE	X0,X:<IDL_ADR
        JMP     <START			; Wait for a new command

;  *************************    SUBROUTINES    ***********************
; Core subroutine for clocking out CCD charge
CLOCK   MOVE    Y:(R0)+,X0      	; # of waveform entries 
        MOVE    Y:(R0)+,A       	; Start the pipeline
        DO      X0,CLK1                 ; Repeat X0 times
        MOVE    A,X:(R6) Y:(R0)+,A      ; Send out the waveform
CLK1
        MOVE    A,X:(R6)        	; Flush out the pipeline
        RTS                     	; Return from subroutine

; Check for program overflow
        IF	@CVS(N,*)>=$200
        WARN    'Application P: program is too large!'	; Make sure program
	ENDIF						;  will not overflow

; ***********  DATA AREAS - READOUT PARAMETERS AND WAVEFORMS  ************

; Command table - make sure there are exactly 32 entries in it
	IF	@SCP("DOWNLOAD","HOST")
	ORG	X:COM_TBL,X:COM_TBL				; Download address
	ELSE			
        ORG     P:COM_TBL,P:APL_NUM*N_W_APL+APL_LEN+$200 	; EEPROM address
	ENDIF
	DC	'IDL',IDL  	; Put CCD in IDLE mode    
	DC	'STP',STP  	; Exit IDLE mode
	DC	'SBV',SETBIAS 	; Set DC bias supply voltages  
	DC	'RDC',RDCCD 	; Begin CCD readout    
	DC	'CLR',CLEAR  	; Fast clear the CCD   
	DC	'SGN',ST_GAIN  	; Set video processor gain     
	DC	'WRC',WR_CNTRL	; Write control word over SSI link
	DC	'SDC',SET_DC	; Set DC coupled diagnostic mode
	DC	'SBN',SET_BIAS_NUMBER	; Set bias number
	DC	'SMX',SET_MUX	; Set clock driver MUX output
	DC	'ABR',ABR_RDC	; Abort exposure readout
	DC	'CRD',CONT_RD	; Continue reading out
	DC	'DON',START	; Nothing special
	DC	'CSW',CLR_SWS	; Clear analog switches to reduce power drain
	DC	'RCC',READ_CONTROLLER_CONFIGURATION 

	DC	'OSH',OPEN_SHUTTER
	DC	'CSH',CLOSE_SHUTTER
	DC      'PON',PWR_ON		; Turn on all camera biases and clocks
	DC      'POF',PWR_OFF		; Turn +/- 15V power supplies off

	DC	'SET',SET_EXP_TIME 	; Set exposure time
	DC	'RET',RD_EXP_TIME 	; Read elapsed exposure time
	DC	'SEX',START_EXPOSURE
	DC	'PEX',PAUSE_EXPOSURE
	DC	'REX',RESUME_EXPOSURE
	DC	'AEX',ABORT_EXPOSURE
	DC	0,START,0,START,0,START,0,START
	DC	0,START,0,START,0,START

	IF	@SCP("DOWNLOAD","HOST")
	ORG	Y:0,Y:0		; Download address
	ELSE
	ORG     Y:0,P:		; EEPROM address continues from P: above
	ENDIF
GAIN	DC	0		; Video processor gain and integrator speed
NSR     DC      44   	 	; Number Serial Read, prescan + image + bias
NPR     DC      80	     	; Number Parallel Read of each readout only
NSCLR   DC      300    		; To clear serial register
NPCLR   DC      400	    	; To clear parallel register
NSBIN   DC      1       	; Serial binning parameter (not used)
NPBIN   DC      1       	; Parallel binning parameter (not used)
NCLKS	DC	0		; Number of clocks per CCD line
SH_DEL	DC	10		; Delay from shutter closing to readout 
				;   in milliseconds

;  Miscellaneous definitions for CCD operation
TST_DAT	DC	0		; Temporary definition for test images

; CCD clock voltage definitions
VIDEO	EQU	$000000	; Video processor board select = 0
CLK	EQU	$002000	; Clock driver board select = all boards for clocks 
CLK2	EQU	$002000	; Clock driver board select = 2 for DAC setting
P_DELAY	EQU	$020000	; Parallel clock delay
R_HI	EQU	3000	; Reset and Serial clocks High +4.0 volts
R_LO	EQU	770	; Reset and Serial clocks Low  -6.0 volts
SI_HI	EQU	2710	; Storage and Image High +3.0 volts
SI_LO	EQU	620	; Storage and Image Low  -7.0 volts

; Define switch state bits for the CCD clocks of the EEV CCD
RL	EQU	0	; Reset output node
RH	EQU	1
SI1L	EQU	0	; Storage and image register, phase #1
SI1H	EQU	2
SI2L	EQU	0	; Storage and image register, phase #2
SI2H	EQU	4
SI3L	EQU	0	; Storage and image register, phase #3
SI3H	EQU	8
R1L	EQU	0	; Serial shift register, phase #1
R1H	EQU	$10
R3L	EQU	0	; Serial shift register, phase #2
R3H	EQU	$20
R2L	EQU	0	; Serial shift register, phase #3
R2H	EQU	$40

;  ***  Definitions for Y: memory waveform tables  *****
PARALLEL DC	SERIAL_IDLE-PARALLEL-2  
	DC	CLK+P_DELAY+SI1L+SI2H+SI3H+RH+R1H+R2L+R3L
	DC	CLK+P_DELAY+SI1L+SI2L+SI3H+RH+R1H+R2L+R3L
	DC	CLK+P_DELAY+SI1H+SI2L+SI3H+RH+R1H+R2L+R3L
	DC	CLK+P_DELAY+SI1H+SI2L+SI3L+RH+R1H+R2L+R3L
	DC	CLK+P_DELAY+SI1H+SI2H+SI3L+RH+R1H+R2L+R3L
	DC	CLK+P_DELAY+SI1L+SI2H+SI3L+RH+R1H+R2L+R3L
	DC	CLK+$000000+SI1L+SI2H+SI3L+RL+R1H+R2L+R3L

; Video processor bit definition
;	     xfer, A/D, integ, Pol+, Pol-, DCrestore, rst   (1 => switch open)
SERIAL_IDLE
	DC	SSKIP-SERIAL_IDLE-2
	DC	CLK+SI1L+SI2H+SI3L+RH+R1H+R2H+R3L
	DC	VIDEO+$000000+%1110100	; Change nearly everything
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2L+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3H
	DC	VIDEO+$000000+%1110111	; Stop resetting integrator
	DC	VIDEO+$2e0000+%0000111	; Integrate for 1 microsec
	DC	VIDEO+$000000+%0011011	; Stop Integrate
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3L
	DC	VIDEO+$000000+%0011011	; Delay for signal to settle
	DC	VIDEO+$000000+%0011011	; Delay for signal to settle
	DC	VIDEO+$2c0000+%0001011	; Integrate for another microsec
	DC	VIDEO+$000000+%0001011	; Continue integrating
	DC	VIDEO+$000000+%0011000	; Stop integrate, A/D is sampling

; Serial clocking waveform for skipping
SSKIP   DC	DACS-SSKIP-2
	DC	CLK+SI1L+SI2H+SI3L+RH+R1H+R2L+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2H+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2L+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3L

; Initialization of clock driver and video processor DACs and switches
DACS	DC	END_DACS-DACS-1
	DC	(CLK2<<8)+R_HI		; R High
	DC	(CLK2<<8)+(1<<14)+R_LO	; R Low
	DC	(CLK2<<8)+(2<<14)+SI_HI	; SI1 High
	DC	(CLK2<<8)+(3<<14)+SI_LO	; SI1 Low
	DC	(CLK2<<8)+(4<<14)+SI_HI	; SI2 High
	DC	(CLK2<<8)+(5<<14)+SI_LO	; SI2 Low
	DC	(CLK2<<8)+(6<<14)+SI_HI	; SI3 High
	DC	(CLK2<<8)+(7<<14)+SI_LO	; SI3 Low
	DC	(CLK2<<8)+(8<<14)+R_HI	; R1 High
	DC	(CLK2<<8)+(9<<14)+R_LO	; R1 Low
	DC	(CLK2<<8)+(10<<14)+R_HI	; R3 High
	DC	(CLK2<<8)+(11<<14)+R_LO	; R3 Low
	DC	(CLK2<<8)+(12<<14)+R_HI	; R2 High
	DC	(CLK2<<8)+(13<<14)+R_LO	; R2 Low

; Set gain and integrator speed. x 9.5 gain, fast integrate
	DC	$0c3fee			; Gain, integrate speed, board #0
	DC	$1c3fee			; Gain, integrate speed, board #1

; Input offset voltages for DC coupling. Target is U4#6 = 24 volts
	DC	$0c0800			; Input offset, ch. A, board #0
	DC	$0c8800			; Input offset, ch. B, board #0
	DC	$1c0800			; Input offset, ch. A, board #1
	DC	$1c8800			; Input offset, ch. B, board #1

; Output offset voltages to get around 1000 DN A/D units on a dark frame
	DC	$0c46c0			; Output video offset, ch. A, bd. #0
	DC	$0cc6c0			; Output video offset, ch. B, bd. #0
	DC	$1c46c0			; Output video offset, ch. A, bd. #1
	DC	$1cc6c0			; Output video offset, ch. B, bd. #1

; DC bias voltages for the EEV39 wavefront sensor CCD chip
	DC	$0d0c8a			; Vod = 24.00 V, pin #1, board #0
	DC	$0d4c8a			; Vod = 24.00 V, pin #2, board #0
	DC	$0d8719			; Vrd = 11.00 V, pin #3, board #0
	DC	$0f8540			; Vog = -3.4V pin #11, board #0
	DC	$1d0c8a			; Vod = 24.00 V, pin #1, board #1
	DC	$1f8540			; Vog = -3.4V pin #11 best CTE, bd. #1
END_DACS

; Check for Y: data memory overflow
        IF	@CVS(N,*)>$80
        WARN    'Application Y: data memory is too large!' ; Make sure Y:
	ENDIF						   ;  will not overflow

; The fast serial code with the circulating address register must start on
;    a boundary that is a multiple of the address register modulus.
; Offset $2C0 leaves APL_LEN+$200 words for P: code, $20 words for commands, 
;    and $80 words for Y: waveforms above.

	IF	@SCP("DOWNLOAD","HOST")
	ORG	Y:$80,Y:$80		; Download address
	ELSE
	ORG     Y:$80,P:APL_NUM*N_W_APL+APL_LEN+$2C0 ; EEPROM address
	ENDIF

;	     xfer, A/D, integ, Pol+, Pol-, DCrestore, rst   (1 => switch open)
SERIAL	DC	CLK+SI1L+SI2H+SI3L+RH+R1H+R2H+R3L
	DC	VIDEO+$000000+%1110100	; Change nearly everything
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3L
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2H+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1L+R2L+R3H
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3H
	DC	SXMIT			; Transmit A/D data to host
	DC	VIDEO+$000000+%1110111	; Stop resetting integrator
	DC	VIDEO+$000000+%1110111	; Delay for signal to settle
	DC	VIDEO+$2e0000+%0000111	; Integrate for 1 microsec
	DC	VIDEO+$000000+%0011011	; Stop Integrate
	DC	CLK+SI1L+SI2H+SI3L+RL+R1H+R2L+R3L
	DC	VIDEO+$000000+%0011011	; Delay for signal to settle
	DC	VIDEO+$000000+%0011011	; Delay for signal to settle
	DC	VIDEO+$2e0000+%0001011	; Integrate for another microsec
	DC	VIDEO+$000000+%0011011	; Stop integrate, A/D is sampling
END_SERIAL

; Check for overflow in the EEPROM case
	IF	@SCP("DOWNLOAD","EEPROM")
		IF	@CVS(N,@LCV(L))>(APL_NUM+1)*N_W_APL
	WARN    'EEPROM overflow!'	; Make sure next application
		ENDIF			;  will not be overwritten
	ENDIF

	ENDSEC		; End of section TIM

;  End of program
	END