; ********************** START OF COADDER PROGRAM *********************** ; Define a section name so it doesn't conflict with other application programs SECTION COADD ; Define some useful DSP register locations RST_ISR EQU $0 ; Hardware reset interrupt BUF_STR EQU $80 ; Starting address of buffers in X: BUF_LEN EQU $20 ; Length of buffers COM_BUF EQU BUF_STR ; Starting address of command buffer in X: COM_TBL EQU COM_BUF+BUF_LEN ; Starting address of command table in X: ADR_TBL EQU COM_TBL+BUF_LEN ; Table with SRAM addresses for pixels APL_ADR EQU $10 ; Start of application code, $10 for now APL_LEN EQU $2F0-APL_ADR ; Length of application code area ROM_OFF EQU $4AAB ; Offset address into timing board ROM ; so it gets placed at $6001 = 24k into ; 32k ROM SRAM_AD EQU $5F0 ; Address in timing board SRAM where coadder code is X_TABLE EQU 0 ; Starting address of X: memory table ; DSP specific addresses BCR EQU $FFFE ; Bus (=Port A) Control Register -> Wait States PCC EQU $FFE1 ; Port C Control Register PCDDR EQU $FFE3 ; Port C Data Direction Register PCD EQU $FFE5 ; Port C Data Register CRA EQU $FFEC ; SSI Control Register A CRB EQU $FFED ; SSI Control Register B SSISR EQU $FFEE ; SSI Status Register SSIRX EQU $FFEF ; SSI Receiver SSITX EQU $FFEF ; SSI Transmitter PBC EQU $FFE0 ; Port B Control Register PBDDR EQU $FFE2 ; Port B Data Direction Register PBD EQU $FFE4 ; Port B Data Register PCTL EQU $FFFD ; PLL control register IPR EQU $FFFF ; Interrupt Priority Register SCR EQU $FFF0 SSR EQU $FFF1 SCCR EQU $FFF2 STXL EQU $FFF4 SRXL EQU $FFF4 SSI_TDE EQU 6 ; SSI Transmitter data register empty SSI_RDF EQU 7 ; SSI Receiver data register full RCV_ERR EQU 2 ; Place in X: memory for SSI errors ; Board addresses RDFIFO EQU $C000 ; Read A/D FIFO into DSP WRCAFIFO EQU $C001 ; Write from DSP to coadder FIFO RSTFIFO EQU $C002 ; Reset both A/D and coadder FIFOs RSTSRAM EQU $8000 ; Start 32-bit mode pointer with D0-D23 (X: memory) ; Parallel port bit numbers, Port B SRAMADDR16 EQU 4 ; SRAM address line 16 SRAMADDR17 EQU 5 ; SRAM address line 17 SRAMADDR18 EQU 6 ; SRAM address line 18 SRAMADDR19 EQU 7 ; SRAM address line 19 GAIN EQU 8 ; A/D gain EF EQU 9 ; Bit number of incomimng FIFO empty flag HF EQU 10 ; Bit number of incoming FIFO half full flag ; Define a little table for X: memory entries NCOADDS EQU X_TABLE NUTR EQU NCOADDS+1 CDS EQU NUTR+1 NFS EQU CDS+1 NCOLS EQU NFS+1 NROWS EQU NCOLS+1 NREADS EQU NROWS+1 ; More flags, Port C M24_32 EQU 2 ; 24- or 32-bit coaddition, Port C CAHF EQU 5 ; Cadder FIFO half full flag, on Port C MEM_ERR EQU 3 ; Set if memory testing error ;************************************************************************** ; * ; Permanent address register assignments * ; R1 - Pointer to commands received pending processing * ; R2 - Pointer to processed commands * ; R3 - Pixel address of frame being coadded * ; R4 - Pixel address of frame being transmitted * ; R5 - RDFIFO address = $C000 * ; R6 - WRCAFIFO address = $C001 * ; * ;************************************************************************** ;****************************************************************************** ;**** COADDER CODE IN SRAM PROGRAM SPACE **** ;****************************************************************************** ; Specify the load address for the coadder code IF @SCP("DOWNLOAD","HOST") ORG P:RST_ISR,P:$5F0 ; Download address ELSE ORG P:RST_ISR,P:RST_ISR+ROM_OFF ; ROM address ENDIF ; Special address for two words for downloading over coadder SCI port DC END_ADR ; Number of boot code words DC $0 ; Starting address of boot code ; After RESET jump to initialization code IF @SCP("DOWNLOAD","HOST") ORG P:RST_ISR,P:$5F0+2 ; Download address ELSE ORG P:RST_ISR,P:RST_ISR+ROM_OFF+2 ; ROM address ENDIF JMP <INIT ; This is the interrupt service for RESET NOP DC 0,0,0,0 ; Put the ID words for this version of the ROM code. It is placed at ; the address of the SWI = software interrupt, which we never use. DC $000000 ; Institution ; Location ; Instrument DC $030004 ; Version 3.00, board #4 = coadder ; Space for ISRA and ISRB. P:$ISRA = $8 DC 0,0,0,0 ; This SSI interrupt service routine receives timing board data MOVEP X:SSIRX,X:(R1)+ ; Put the word in the SSI receiver buffer NOP ; The SSI interrupts to here when there is an error. JSR CLR_SSI ; Initialization of the DSP - system register, serial link, interrupts ; Starting address = P:$10 INIT MOVEC #$08,OMR ; Operating Mode Register - Single chip mode ; suitable for use with the OnCE port, with ; internal Y: memory disabled MOVEP #$7F0002,X:PCTL ; MFO to 11=2, DFO to 3=0, XTLD=1, PSTP=1, ; PEN=1, COD0 to 1=0, CSRC=1 and CKOS=1 ; CKOUT enabled to 3 x BUS-CLK = 75 MHz ; Port B MOVEP #$0,X:PBC ; Port B Control Register enabling port B ; pins as general purpose I/O. MOVEP #$01F0,X:PBDDR ; SRAMADDR16-19, GAIN are outputs MOVEP #$0000,X:PBD ; SRAMADDR16-19 = 0 BSET #GAIN,X:PBD ; Gain = 1 for 0 to -10V A/D (BSET, low gain) ; BCLR #GAIN,X:PBD ; Gain = 0 for 0 to -5V A/D (BCLR, high gain) ; Port C MOVEP #$6002,X:CRA ; SSI programming MOVEP #$BD20,X:CRB ; SSI programming MOVEP #$01C8,X:PCC ; Enable SSI, not SCI MOVEP #$0004,X:PCDDR ; PC2 = M24/32 is an output ; Set external bus access speeds MOVEP #$2281,X:BCR ; Wait states for external memory accesses ; Ext. X:, Ext. Y, Ext. P:, Ext. I/O MOVEP #$2000,X:IPR ; Service SSI interrups only, level 1 BCLR #M24_32,X:PCD ; 24-bit (CLR) or 32-bit (SET) coaddition ; Clear the high address lines to the SRAM to zero BCLR #SRAMADDR16,X:PBD ; SRAM address line = 0 BCLR #SRAMADDR17,X:PBD ; SRAM address line = 0 BCLR #SRAMADDR18,X:PBD ; SRAM address line = 0 BCLR #SRAMADDR19,X:PBD ; SRAM address line = 0 ; Set up software tables and registers MOVE #<COM_BUF,R1 ; Starting address of command buffer CLR A R1,R2 MOVE #31,M1 ; Input buffers are circular, modulo 32 MOVE M1,M2 DO #32,ZERO_X ; Zero receiver buffer MOVE A,X:(R1)+ ZERO_X MOVE #RDFIFO,R5 ; Its in a register for faster execution MOVE #WRCAFIFO,R6 ; Its in a register for faster execution ; Write the command table to X: memory MOVE #TABLE,R0 MOVE #COM_TBL,R7 DO #(END_TABLE-TABLE),L_COM MOVE P:(R0)+,X0 MOVE X0,X:(R7)+ L_COM ANDI #$FC,MR ; Enable interrupt processing ; Start processing commands here START MOVE R1,X0 ; Pointer to received commands MOVE R2,A ; Pointer to processed commands CMP X0,A JEQ <START ; Keep waiting if there are no new commands ; Check the header (S,D,N) for self-consistency CHK_HDR MOVE X:(R2),Y0 MOVE #$FCF0F8,A1 ; Test for S.LE.3 and D.LE.$F and N.LE.7 AND Y0,A JNE <BAD_HDR ; Test failed, discard candidate header MOVE #$030300,A1 AND Y0,A ; Test for S.NE.0 or D.NE.0 JEQ <BAD_HDR ; Test failed, discard candidate header MOVE #7,A1 AND Y0,A ; Test for N.GE.1 JNE RD_COM BAD_HDR MOVE (R2)+ ; Increment past bad header JMP <START ; Test failed, discard candidate header ; Read all the words of the command before processing them RD_COM MOVE A,Y0 ; Y0 = NWORDS RD_WORD MOVE R1,A ; R1 = pointer to received commands MOVE R2,X0 ; R2 = pointer to processed commands SUB X0,A JGE <L_C32 MOVE #>32,X1 ; Correct for the circular buffer ADD X1,A L_C32 CMP Y0,A ; Has it been incremented to RCV_BUF + NWORDS? JLT <RD_WORD ; No, keep looking for more ; Process the receiver entry - is it in the command table ? COMMAND MOVE X:(R2)+,A ; Save the header MOVE A,X:<HDR MOVE X:(R2)+,A ; Get the command buffer entry MOVE #<COM_TBL,R0 ; Get command table starting address DO #NUM_COM,END_COM ; Loop over command table MOVE X:(R0)+,X1 ; Get the command table entry CMP X1,A X:(R0),R7 ; Does receiver = table entries address? JNE <NOT_COM ; No, keep looping ENDDO ; Restore the DO loop system registers JMP (R7) ; Jump execution to the command NOT_COM MOVE (R0)+ ; Increment the register past the table address END_COM ;******************************************************************************* ; It's not in the command table - send an error message ERROR MOVE #'ERR',X0 ; Send the message - there was an error JMP <FINISH1 ; This protects against unknown commands ; Send a reply packet - header and reply FINISH MOVE #'DON',X0 ; Send a DONE message as a reply FINISH1 MOVE #$040202,A ; Only reply to the timing board JSR <XMT_TIM MOVE X0,A JSR <XMT_TIM JMP <START ; Go get the next command ;******************************************************************************* ; Test Data Link - simply return value received after 'TDL' TDL MOVE X:(R2)+,X0 ; Get data value MOVE #$040002,A ; Reply to the host JSR <XMT_TIM MOVE X0,A JSR <XMT_TIM JMP <START ; Go get the next command ; Get the four arguments from the timing board GET_ARGUMENTS MOVE X:(R2)+,X0 MOVE X0,X:<NCOADDS ; Number of coadds MOVE X:(R2)+,X0 MOVE X0,X:<NUTR ; Number of up-the-ramp exposures MOVE X:(R2)+,X0 MOVE X0,X:<CDS ; Correlated double sampling or not MOVE X:(R2)+,X0 MOVE X0,X:<NFS ; Number of Fowler samples MOVE X:(R2)+,X0 MOVE X0,X:<NCOLS ; Number of Cols MOVE X:(R2)+,X0 MOVE X0,X:<NROWS ; Number of Rows MOVE X:(R2)+,X0 MOVE X0,X:<NREADS ; Number of Reads RTS ;******************************************************************************* ; This is "Initialize coadder board". Zero out 512 x 512 pixel of SRAM ICA MOVE A,X:RSTFIFO ; Reset A/D and coadder FIFOs MOVE X0,X:RSTSRAM ; Initialize the Ping-Pong data pointer BSET #M24_32,X:PCD ; Always 32-bit (SET) coaddition BCLR #SRAMADDR17,X:PBD JSR <INIT_FRAME ; This is the reset frame BSET #SRAMADDR17,X:PBD JSR <INIT_FRAME ; This is the expose frame JMP <START INIT_FRAME BCLR #SRAMADDR16,X:PBD ; A16 = 0 JSR <CLR_MEM BSET #SRAMADDR16,X:PBD ; A16 = 1 JSR <CLR_MEM RTS ; Zero out one 64k = 256 x 256 pixel page of SRAM = 64 k words CLR_MEM MOVE #$10000,X0 ; 64K words of SRAM memory at a time CLR A MOVE A1,R3 DO X0,ZERO_SRAM MOVE A,Y:(R3) MOVE A,Y:(R3)+ ; Initialize D31-D00 of coadder memory ZERO_SRAM RTS ; Always store the reset frame in SRAMADDR17 = 0 ; always store the expose frame in SRAMADDR17 = 1 ;******************************************************************************* ; This is the coadder routine. Up-the-ramp is not supported. RDC MOVE A,X:RSTFIFO ; Reset A/D and coadder FIFOs MOVE X0,X:RSTSRAM ; Initialize the Ping-Pong data pointer MOVE #$00FFFF,X1 ; Set D23-D16 = 0 MOVEP #$1181,X:BCR ; Wait states for ext. memory accesses ; Ext. X:, Ext. Y, Ext. P:, Ext. I/O JSR <GET_ARGUMENTS ; Get all the arguments for this call DO X:<NCOADDS,L_COADDS JCLR #0,X:<CDS,FS_RESET ; Don't coadd reset frame if CDS = 0 BCLR #SRAMADDR17,X:PBD DO X:<NFS,FS_RESET ; Number of Fowler samples per frame JSR <COADD_FRAME ; This is the reset frame NOP FS_RESET BSET #SRAMADDR17,X:PBD DO X:<NFS,FS_EXPOSE JSR <COADD_FRAME ; This is the expose frame NOP FS_EXPOSE NOP L_COADDS MOVEP #$2281,X:BCR ; Wait states for ext. memory accesses JMP <START ; Coadd one 256 x 512 pixel frame COADD_FRAME BCLR #SRAMADDR16,X:PBD ; A16 = 0 JSR <COADD ; one 256x256 pix frame BSET #SRAMADDR16,X:PBD ; A16 = 1 JSR <COADD ; another 256x256 frame NOP RTS ; Define a macro so in-line code can be simplified COADD_ONE_PIXEL MACRO AND X1,A Y:(R0),B1 MOVE Y:(R0),B2 ; Get coadded D31-D24 from SRAM ADD A,B X:(R5),A1 MOVE B1,Y:(R0) ; Write D23-D00 to SRAM MOVE B2,Y:(R0)+ ; Write D31-D24 to SRAM, increment pixel pointer ENDM ; Coadd 1/2 a frame = 128k pixels (32-bit coaddition) COADD CLR A MOVE A,R0 ; R0 = SRAM address MOVE X0,X:RSTSRAM ; Initialize the Ping-Pong data pointer MOVE #16384,X0 DO X0,COADD_4 ; Read all the image minus four pixels JCLR #EF,X:PBD,* ; Wait for the FIFO to be not empty MOVE X:(R5),A1 ; Read from the A/D FIFO COADD_ONE_PIXEL ; Macro defined immediately above COADD_ONE_PIXEL COADD_ONE_PIXEL AND X1,A Y:(R0),B1 MOVE Y:(R0),B2 ADD A,B ; Don't read FIFO, because its not ready yet MOVE B1,Y:(R0) MOVE B2,Y:(R0)+ COADD_4 RTS ; This sends 512x512x2 16-bit samples (512x512 32-bit pixels) to the FIFO ****** ;******************************************************************************* ; Transmit the coadded image to the CAFIFO for reading by the timing board. ; Data is always transmitted in 32-bits per pixel format. TCA MOVE A1,X:RSTFIFO ; Reset A/D and coadder FIFOs MOVE A1,X:RSTSRAM ; Initialize the Ping-Pong data pointer JSET #0,X:<CDS,L_3 BSET #SRAMADDR17,X:PBD ; CDS = 0 JSR <XMIT_FRAME JMP <START L_3 BCLR #SRAMADDR17,X:PBD ; CDS = 1 => Yes correlated double JSR <XMIT_FRAME ; sampling BSET #SRAMADDR17,X:PBD JSR <XMIT_FRAME JMP <START XMIT_FRAME BCLR #SRAMADDR16,X:PBD ; A16 = 0 JSR <WR_CAFIFO ; dump one 256x256 (32-bit) pix page per board BSET #SRAMADDR16,X:PBD ; A16 = 1 JSR <WR_CAFIFO ; dump another 256x256 (32-bit) pix page per board RTS WR_CAFIFO ; Transmit a 64k (256x256 32-bit) pixel image CLR A MOVE A1,R0 DO #1024,L_TCA2 JCLR #CAHF,X:PCD,* ; Wait if the FIFO is half full DO #64,L_TCA3 MOVE Y:(R0),A0 ; Get bits D23-D00 of coadded image MOVE A0,B0 ; Write bits D15-D00 to B0 MOVE Y:(R0)+,A1 ; Get bits D31-D24 of coadded image REP #16 ; Shift bits D31-D16 into position ASR A MOVE A0,X:(R6) ; Write bits D31-D16 to CAFIFO (first 16 bits into FIFO) MOVE B0,X:(R6) ; Write bits D15-D00 to CAFIFO (second 16 bits into FIFO) L_TCA3 NOP L_TCA2 RTS ; Transmit a word to the timing board over the SSI XMT_TIM JCLR #SSI_TDE,X:SSISR,* ; Continue if SSI XMT register is empty MOVEP A,X:SSITX ; Write to SSI buffer RTS ; Clear error condition and interrupt on SSI receiver CLR_SSI MOVEP X:SSISR,X:RCV_ERR ; Read SSI status register MOVEP X:SSIRX,X:RCV_ERR ; Read receiver register to clear error RTI ; This sends 512x512 16-bit samples (512x512 16-bit pixels) to the FIFO ******** ;******************************************************************************* ; This is the pass through (PT) readout code READ_PT JSR <GET_ARGUMENTS ; Get all the arguments for this call MOVE A,X:RSTFIFO ; Reset the A/D and coadder FIFOs ; DO X:<NCOADDS,L_NCOADDS ; JCLR #0,X:<CDS,L1_NFS ; One frame per coadd if CDS = 0 ; DO X:<NFS,L1_NFS ; Loop over number of Fowler samples ; MOVE A,X:RSTFIFO ; Reset the A/D and coadder FIFOs ; JSR <READ_PT_FRAME ; This is the first frame ; NOP ;L1_NFS ; DO X:<NUTR,L_NUTR ; DO X:<NFS,L2_NFS ; Loop over number of Fowler samples DO X:<NREADS,L2_NFS ; Loop over NREADS ; MOVE A,X:RSTFIFO ; Reset the A/D and coadder FIFOs JSR <READ_PT_FRAME ; This is the second frame NOP L2_NFS NOP ;L_NUTR ; NOP ;L_NCOADDS JMP <START READ_PT_FRAME ; 512 rows by 512 cols for HAWAII 4-quad (4 amp) MOVE X:<NROWS,A1 LSR A1 DO A1,L_ROWS ; NROWS/2 MOVE X:<NCOLS,A1 LSR A1 DO A1,L_COLS ; NCOLS/2 JCLR #EF,X:PBD,* ; Wait for the pixel data MOVE X:(R5),X0 ; Read one 16-bit pix from the A/D FIFO (per board) PIX (amp) 0 MOVE X0,X:(R6) ; Write one 16-bit pix to output FIFO (per board) MOVE X:(R5),X0 ; PIX (amp) 1 MOVE X0,X:(R6) MOVE X:(R5),X0 ; PIX (amp) 2 MOVE X0,X:(R6) MOVE X:(R5),X0 ; PIX (amp) 3 MOVE X0,X:(R6) L_COLS NOP L_ROWS NOP RTS ;****************************************************************************** ;*** Command table. This is different from the TIM/TIMBOOT command table *** ;****************************************************************************** ; Command table is in P: memory so it downloads from the timing board NUM_COM EQU 6 ; Number of commands TABLE DC 'ICA',ICA ; Initialize coadder board DC 'RDC',RDC ; Read image, after exposure DC 'TCA',TCA ; Transmit coadder image to timing board DC 'TDL',TDL ; Test Data Link DC 'RPT',READ_PT ; Read pass through DC 'ERR',ERROR END_TABLE ;****************************************************************************** ;*** End of Command table. *** ;****************************************************************************** ; Last address of program so number of program words can be calculated END_ADR ;****************************************************************************** ;**** END OF COADDER CODE ************* ;****************************************************************************** ; Check for overflow IF @CVS(N,*)>$6FF WARN 'Internal P: memory overflow!' ENDIF ENDSEC ; End of section COADD