; This file is used to generate DSP code for the second generation 
;    timing board for the SITe 424A imager (2048 x 2049 pixels, 24 microns)

	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	SUBARRAY+SPLIT_SERIAL+SPLIT_PARALLEL+MPP_CAPABLE+SHUTTER_CONTROL+BINNING

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

	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

;**************************************************************************
;                   	                                                  *
;    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
	JMP     <CHK_SSI		; Go process header and command
NO_COM  NOP
IDL1
	MOVE    #PARALLEL_CLEAR,R0	; Address of parallel clocking waveform
	JSR     <SLOW_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_CLEAR,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 to read one image
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

; Skip over NP_SKIP rows for subimage readout
	CLR	A
	MOVE	Y:<NP_SKIP,A		; Number of rows to skip
	TST	A
	JEQ	<L_SCLR
	DO      A,LPR_SKIP
	MOVE    Y:PARALLEL,R0
	JSR     <SLOW_CLOCK
	NOP
LPR_SKIP	

; Clear out accumulated charge from the serial shift register 
	DO      Y:<NSCLR,L_SCLR
	MOVE	Y:SERIAL_SKIP,R0 
	JSR     <CLOCK
	NOP
L_SCLR

; Parallel shift the image into the serial shift register
	MOVE	Y:<NPR,A		; Number of rows in ccdtool image
	JCLR	#SPLIT_P,X:STATUS,*+3
	ASR	A			; Split parallel requires NPR / 2
	DO      A,LPR			; Number of rows to read out

; Check for a command once per line. 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 readout loop
	JMP	<RDC_END

CONT_RD	DO	Y:<NPBIN,LPR_I  	; Transfer # of rows, with binning
	MOVE    Y:PARALLEL,R0
	JSR     <SLOW_CLOCK		; Slow, long parallel clocking
	NOP
LPR_I

; Skip over NS_SKP1 columns for subimage readout
	CLR	A
	MOVE	Y:<NS_SKP1,A		; Number of columns to skip
	TST	A
	JEQ	<LS_SKIP1
	DO      A,LS_SKIP1
	MOVE    Y:SERIAL_SKIP,R0
	JSR     <CLOCK
	NOP
LS_SKIP1	

; Finally read some real pixels
	MOVE	Y:<NR_BIAS,X0		; NR_BIAS = number of bias columns
	MOVE	Y:<NSR,A		; NSR = number of columns in image
	SUB	X0,A			; Read NSR - NR_BIAS pixels
	JCLR	#SPLIT_S,X:STATUS,*+3
	ASR	A			; Split serials require NSR / 2

; This is the serial binning routine
	CLR	B
	MOVE	Y:<NSBIN,B		; Serial binning parameter
	MOVE	X:<ONE,X0
	CMP	X0,B
	JEQ	<NO_BIN			; Skip over serial binning software

	DO      A,LSR_BIN		; Number of pixels to read out
	MOVE	#CCD_RESET,R0		; Reset the output nodes
	JSR	<CLOCK
	DO      B,LSR_I  		; Bin serially NSBIN times
	MOVE	Y:SERIAL_CLOCK,R0 	; Serially clock the charge
	JSR     <CLOCK
	NOP
LSR_I
	MOVE	#VIDEO_PROCESS,R0 	; Video process the binned pixel
	JSR     <CLOCK
	NOP
LSR_BIN
	JMP	<OVER_RD		; All done binning

; This is the NO serial binning routine
NO_BIN	DO      A,LSR			; Number of rows to read out
	MOVE	Y:SERIAL_READ,R0 
	JSR     <CLOCK
	NOP
LSR					; End of serial loop

; Now skip over NS_SKP2 columns for subimage readout
OVER_RD	CLR	A
	MOVE	Y:<NS_SKP2,A		; Number of columns to skip
	TST	A
	JEQ	<LS_SKIP2
	DO      A,LS_SKIP2
	MOVE    Y:SERIAL_SKIP,R0
	JSR     <CLOCK
	NOP
LS_SKIP2

; And read the bias pixels if in subimage readout mode
	CLR	A
	MOVE	Y:<NR_BIAS,A		; Number of bias columns to read
	TST	A
	JEQ	<LR_BIAS
	JCLR	#SPLIT_S,X:STATUS,*+3
	ASR	A			; Split serials require NR_BIAS / 2
	DO      A,LR_BIAS
	MOVE	Y:SERIAL_READ,R0 
	JSR     <CLOCK
	NOP
LR_BIAS
	NOP
LPR					; End of parallel loop

; 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

; Clocking subroutine for very long parallel clocks
SLOW_CLOCK
	MOVE	Y:(R0)+,X0	; Number of waveform entries
	DO	X0,L_SLOW_CLOCK	
	MOVE	Y:(R0)+,A	; Get the waveform
	DO	Y:<N_PAR,*+3	; Loop over it N_PAR times
	MOVE	A,X:(R6)	; Write it to the hardware
	NOP
L_SLOW_CLOCK
	RTS

; 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  ************

; 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 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	'SOS',SEL_OS	; Select Output Source
	DC	'MPP',SEL_MPP	; Select MPP mode
	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

	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      2090   	 	; Number of pixels read per row
NPR     DC      2049	     	; Number of lines read
NSCLR   DC      2200 		; Clear serial register, twice
NPCLR   DC      1100	    	; Clear parallel register once, in split mode

; Binning parameters
NSBIN   DC      1       	; Serial binning parameter
NPBIN   DC      1       	; Parallel binning parameter

; Miscellaneous definitions
TST_DAT	DC	0		; Temporary definition for test images
SH_DEL	DC	10		; Delay in milliseconds between shutter closing 
				;   and image readout

; Subimage readout parameters - set to not have any effect
NP_SKIP	DC	0		; Number of rows to skip
NS_SKP1	DC	0		; Number of serials to skip before read
NS_SKP2	DC	0		; Number of serials to skip after read
NR_BIAS	DC	0		; Number of bias pixels to read

; Subimage readout parameters
;NP_SKIP	DC	200		; Number of rows to skip
;NS_SKP1	DC	1000		; Number of serials to skip before read
;NS_SKP2	DC	800		; Number of serials to skip after read
;NR_BIAS	DC	100		; Number of bias pixels to read

; Readout peculiarity parameters
N_PAR		DC	10 		; 30 Delay parameter for parallel clocks
SERIAL_SKIP 	DC	SERIAL_SKIP_A	; Address of serial skipping waveforms
SERIAL_READ	DC	SERIAL_READ_A	; Address of serial waveform table
SERIAL_CLOCK 	DC	SERIAL_CLOCK_A	; Address of serial clocking waveforms
PARALLEL 	DC	PARALLEL_UPPER	; Address of parallel waveform table
OS		DC	'__A'		; The name of the Output Source(s)

; Include the waveform table
        INCLUDE "SITe424.waveforms"	; SITe424AB readout waveforms

	ENDSEC				; End of section TIM

;  End of program
	END