; $Id$: #REP Compiling Zero Suppression Mode Raw Data Readout ; ZERO SUPPRESSION case ; check if some events should be send without ZS #ifdef cpu3 SEM b0111_0000 ; cpu3 waits that cpu0..2 write their masks #else SEM b1000_0000 ; cpu0..2 wait that cpu3 writes the final mask #endif ; cpu3 #ifneq ZS_FULL_MOD, ZS_FULL_NO ; the 3 constants ZS_FULL_N1..3 are 2**N-1 and are defined in run_parameters.tcs #ifeq ZS_FULL_MOD, ZS_FULL_1 mova ZS_FULL_N1, r9 ; in case of 01 #endif #ifeq ZS_FULL_MOD, ZS_FULL_2 mova ZS_FULL_N2, r9 ; in case of 10 #endif #ifeq ZS_FULL_MOD, ZS_FULL_3 mova ZS_FULL_N3, r9 ; in case of 11 #endif mov EBR_CH_MSK, r6 ; set which channels to send, here all ; the mask is local for each CPU and starts from bit 0 ; the predefined masks are 5 bit long for CPU0..2 and 6 bit long for CPU3 and r9, EventCounter, r9 ; take the lower n-bits in Event Counter cmp r9, ZS_FULL_EVENT ; and compare with 1 => if 1, full readout in ZS! ; r9 is not used any more, so we can check later again this condition! ; from here we have a full readout in zero suppressed mode jmp cc_eq, raw_ebiscan_done ; skip the reading of the indicators and continue with the full mask loaded before #endif ; now read the indicators and mark the ADC channels with non-zero indicators ; we can not transfer more than 180 samples/CPU => 60 32-bit words/CPU ; this means 30 samples/ADC channel in black event mov 0, r6 ; r6 is used as local channel mask, now init with 0 mov ZS_SMSK_DM, r15 ; prepare the DMEM read pointer ; load a sample mask in r2 (and r3 when >32 samples) ; ZS_MASK is stored in DMEM and is consistent with the number of samples already! mov EBI0, rio ; address of the first indicator in the local IO space, same for all CPUs lra rr_dword, r2 ; read the sample mask, bits 0..31 lra+ rr_dword, r2 mov 1, r8 ; travelling 1, will be shifted left in each loop and used to set bits in r6 #ifgt NSAMPLES, 30 lra rr_dword, r3 ; read the sample mask, bits 32..63 lra+ rr_dword, r3 nop ; not sure if necessary? mov ZSL_SMSK_C, r15 ; prepare to write the AND-ed masks #endif raw_ebiscan_next: lpio+ r0 ; read twice because of the latency in LIO lpio+ r0 #ifgt NSAMPLES, 30 lpio rio, r1 ; read the upper 32 bits of the mask #endif ; now r0 (+r1 when Nsamples>30) contain the indicator mask, r2 (+r3 when Nsamples>30) the global mask stored in DMEM, and r2, r0, r0 ; AND with the sample mask #ifgt NSAMPLES, 30 sra+ r0 ; store the AND-ed mask, bits 0..31 and r3, r1, r1 ; AND with the sample mask (Nsamples>30) sra+ r1 ; store the AND-ed mask, bits 32..63 or r0, r1, r0 ; if 0, both are 0! #endif jmpr cc_zero, +2 ; skip setting the bit for this channel in the mask when 0 or r6, r8, r6 ; set the bit corresponding to this channel sll 1, r8, r8 ; shift the mask left cmp r8, EBR_CH_MSK ; check for last channel, CPU3 has one ADC channel more jmp cc_ltu, raw_ebiscan_next ; for CPU0..2: exit when r8 is b0100000 and EBR_CH_MSK is b0011111 ; for CPU3 : exit when r8 is b1000000 and EBR_CH_MSK is b0111111 ; the adc mask in r6 is not absolute, now shift properly to the left (by 0, 5, 10, 15 for CPU0..3) raw_ebiscan_done: sll EBR_CH_INI, r6, r6 ; EBR_CH_INI is defined as 0, 5, 10, 15 for cpu0..3 ; in run_parameters.tcs there were defined the following constants, so that we don't need to read h_0: ; ZS_TRACKL has 3 possible values: ; ZS_TRACKL_DIS_CONTR do not add the channels contributing to tracklets/candidates ; ZS_TRACKL_ENA_CONTR add the channels contributing to tracklets ; ZS_TRACKL_CAN_CONTR add the channels contributing to candidates ; ZS_ADCMSK_AND 0 or 1 ; - enable AND of the selected by ZS logic ADC channels with the value of the ADCMASK register #ifndef cpu3 ; only cpu0..2 have tracklets #ifneq ZS_TRACKL, ZS_TRACKL_DIS_CONTR ; check eventually contribution of tracklets or tracklet candidates ; calculate the ADC mask for the zero suppression in case of tracklets cmp f8, 0 ; ch+1 is 0 if no tracklet present jmp cc_zero, raw_notrack ; no contribution - no candidate => no tracklet, nothing to check any more ; here we have at least a tracklet candidate! #ifeq ZS_TRACKL, ZS_TRACKL_ENA_CONTR ; have to check for tracklet really sent? mov TrcklDMEMz, r15 ; was sent by the next CPU! nop lra4 r0 lra4 r0 ; read the tracklet cmpa r0, NSIG_TR_VAL ; if equal to the end marker, no tracklet was sent jmp cc_eq, raw_notrack #endif ; here we must add the channels contributing to the tracklet candidate! mov 0xF0, r0 ; 1111b << 4, take the 4 ADC channels cmp f9, 0 ; number of hits in ch+1 jmpr cc_neq, +2 mov 0x70, r0 ; 0111b << 4, take the 3 ADC channels only ; f0 numerates the channel pairs and can be from 0 to 17, f8=f0+1 (1 to 18) ; to a tracklet contribute channels f0, f0+1, f0+2, and in most cases f0+3 (when f9 > 0) sub f0, 4, r1 ; ch-4 is from -4 to 13: within the range of the shl operation ; => this was the reason to load b1111_0000 to r0 and to change the shift distance shl r1, r0, r0 ; x111_0000 << (ch-4) or r0, r6, r6 ; or the ADC channel mask ; in case of NSAMPLES>30, if the ZS_SMASK of channel f0 is 0, we have to copy there the mask of f0+1 ; ...of channel f0+2 is 0, we have to copy there the mask of f0+1 ; ...of channel f0+3 is 0, we have to copy there the mask of f0+2 #endif ; contribution mode #endif ; cpu0..2 raw_notrack: ; cpu3 is here earlier #ifdef cpu3 #ifeq ZS_ADCMSK_AND, 1 lgio 0, ADCMSK_DB jmpr cc_busy, 0 lpio GBUSR0, r1 #else iext 0x1FFFFF ; 21 bits with 1 mov 0x1FFFFF, r1 ; load the full ADC mask #endif #ifeq ZS_ADCMSK_OR, 1 mov ZS_ADC_ORM_DM, r15 ; prepare reading the adc OR mask nop lra rr_dword, r2 lra rr_dword, r2 #else mov 0, r2 #endif syn ; waits until cpu0..2 write something to g4..6 ; r6 is the own mask or r6, adc_ch_msk_0, r6 ; add CPU0 channels or r6, adc_ch_msk_1, r6 ; add CPU1 ... or r6, adc_ch_msk_2, r6 ; add CPU2 ... and store the intermediate result and r1, r6, r6 ; and with the ADC channels mask to avoid reading masked channels or r6, r2, adc_ch_msk ; apply the OR mask, if any and store the result in GRF => release CPU0..2 #else ; cpu0..2 mov r6, adc_ch_msk ; store the own contribution to the ADC mask to the global register SYN ; and wait until CPU3 writes the final result to g7 #endif ; the complete channel mask is in g7, all CPUs come simultaneously here ; SEM b1111_0000 ; sync mask for the CPUs, all must write to g4..g7 ; here all CPUs start simultaneously ; shift back to the right to get the mask relative to the CPU's start channel slr EBR_CH_INI, adc_ch_msk_3, r6 ; the result for cpu0..2 contains extra non-zero bits on positions > 4, relevant are only bits 4..0 ; the result for cpu3 contains no extra non-zero bits! ; count the number of 1 in the lower 5 (6 for CPU3) bits in r6 mov 0, r7 ; clear the counter slr 1, r6 ; copy bit 0 to carry adc r7, 0, r7 ; add the carry to r7 slr 2, r6 ; copy bit 1 to carry adc r7, 0, r7 ; add the carry to r7 slr 3, r6 ; copy bit 2 to carry adc r7, 0, r7 ; add the carry to r7 slr 4, r6 ; copy bit 3 to carry adc r7, 0, r7 ; add the carry to r7 slr 5, r6, r0 ; copy bit 4 to carry and the r6 >> 5 to r0 (unknown for cpu0..2, 0 or 1 for cpu3) #ifdef cpu0 adc r7, 0, r7 ; add the carry to r7 #endif #ifdef cpu1 adc r7, 0, g1 ; add the carry to g1 #endif #ifdef cpu2 adc r7, 0, g2 ; add the carry to g2 #endif #ifdef cpu3 adc r7, r0, g3 ; add the old value to the carry & the LSBit and store in g3 #endif #ifdef cpu0 add r7, g1, r7 ; accumulate all number of channels add r7, g2, r7 ; accumulate all number of channels add r7, g3, r7 ; accumulate all number of channels #endif #ifdef cpu3 mov r6, adc_ch_msk ; the own mask only #else mov EBR_CH_MSK, r0 ; bits 4..0 (cpu0..2) or 5..0 (cpu3) set, the rest cleared and r0, r6, adc_ch_msk ; copy back the adc channel mask to the grf register and clear the unused bits ; r6 of CPU0 still contains the full ADC mask! #endif ; prepare the pointer to DMEM, lower 16 bits - ADC data, upper 16 bits - ZS sample mask in DMEM #ifneq RAW_SCSN, RAW_SCSN_DIS mov AddrDMdata, r15 ; we have to init r15 even in case of no transfer of ADC data to the DMEM ; because the other half could be used as another pointer and ORed to this pointer ; => so at least the upper 16 bits (exactly 16..27) here should be 0!!! #else #ifgt NSAMPLES, 30 mov 0, r15 ; init it somehow to be sure that after the OR below the pointer in the upper bits is not changed #endif #endif #ifgt NSAMPLES, 30 mov ZSL_SMSK_C, r2 swp r2, r2 ; pointer to the 64-bit ZS sample masks or r15, r2, r15 #endif #ifdef cpu0 ; cpu0 must send the MCM header, the others skip this part ; r7 contains the number of ADC channels to be sent #ifgt DONT_SEND_EMPTY_HDR_ZS, 0 cmp r7, 0 jmp cc_eq, raw_transf_ch ; skip sending of MCM header and empty ADC mask ; start eventuelly storing the ADC values to DMEM #endif spio r11, NODP ; NI transfer chip header #ifneq RAW_SCSN, RAW_SCSN_DIS sra+ r11 ; r11 contains the MCM Header #endif ; combine the full header word with the ADC mask not r7, r7 ; the number of ADC channels, inverted ; the bits 31..5 are all 1 here, bits 4..0 is the inverted number sll 13, r7, r7 sll 13, r7, r7 ; << 26, the inverted number is in 30..26, bit 31 is 1 slr 1, r7, r7 ; >> 1, the inverted number is in 29..25, bit 30 is 1, bit 31 is 0 sll 4, r6, r6 ; adc mask << 4, in bits 24..4 or r6, r7, r6 ; 01 & not(ADC count) & adc_msk[3] & adc_msk[2] & adc_msk[1] & adc_msk[0] & "0000" mov b1100, r7 or r6, r7, r6 ; 01 & not(ADC count) & adc_msk[3] & adc_msk[2] & adc_msk[1] & adc_msk[0] & "1100" spio r6, NODP ; send the ADC mask #ifneq RAW_SCSN, RAW_SCSN_DIS sra+ r6 #endif #endif ; cpu0 raw_transf_ch: ; refresh EBPP - when wrong, the ADC data contain a parity bit #ifdef cpu1 mov EBPP_VAL, r7 iext EBPP sgio r7, EBPP #endif #ifneq RAW_SCSN, RAW_SCSN_ALL ; not possible that the channel is not selected, but stored to DMEM mov NODP, r6 ; store always to the NI output port when the ADC channel is selected #endif ; once for all 5 or 6 transmitted channels mov RAW_END_BITS, r7 ; RAW_SCSN is one of: RAW_SCSN_ALL, RAW_SCSN_ZS (only in ZS mode), RAW_SCSN_DIS ;############################################## ;# NI&SCSN transfer 1st channel ;############################################## #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR0, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! #else jmp cc_ncarry, raw_2nd_skip ; skip this channel when not marked and not full SCSN transfer #endif mov raw_2nd, rstack jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples raw_2nd_skip: #ifgt NSAMPLES, 30 swp r15, r15 add r15, 4, r15 add r15, 4, r15 swp r15, r15 #else nop #endif raw_2nd: xor r7, 1, r7 ; toggle the LSB, prepare for the next channel ;############################################## ;# NI&SCSN transfer 2nd channel ;############################################## #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR1, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! #else jmp cc_ncarry, raw_3rd_skip ; skip this channel when not marked and not full SCSN transfer #endif mov raw_3rd, rstack jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples raw_3rd_skip: #ifgt NSAMPLES, 30 swp r15, r15 add r15, 4, r15 add r15, 4, r15 swp r15, r15 #else nop #endif raw_3rd: xor r7, 1, r7 ; toggle the LSB, prepare for the next channel ;############################################## ;# NI&SCSN transfer 3rd channel ;############################################## #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR2, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! #else jmp cc_ncarry, raw_4th_skip ; skip this channel when not marked and not full SCSN transfer #endif mov raw_4th, rstack jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples raw_4th_skip: #ifgt NSAMPLES, 30 swp r15, r15 add r15, 4, r15 add r15, 4, r15 swp r15, r15 #else nop #endif raw_4th: xor r7, 1, r7 ; toggle the LSB, prepare for the next channel ;############################################## ;# NI&SCSN transfer 4th channel ;############################################## #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR3, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! #else jmp cc_ncarry, raw_5th_skip ; skip this channel when not marked and not full SCSN transfer #endif mov raw_5th, rstack jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples raw_5th_skip: #ifgt NSAMPLES, 30 swp r15, r15 add r15, 4, r15 add r15, 4, r15 swp r15, r15 #else nop #endif raw_5th: xor r7, 1, r7 ; toggle the LSB, prepare for the next channel ;############################################## ;# NI&SCSN transfer 5th channel ;############################################## #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR4, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! #else jmp cc_ncarry, raw_6th_skip ; skip this channel when not marked and not full SCSN transfer #endif mov raw_6th, rstack jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples raw_6th_skip: #ifgt NSAMPLES, 30 swp r15, r15 add r15, 4, r15 add r15, 4, r15 swp r15, r15 #else nop #endif raw_6th: xor r7, 1, r7 ; toggle the LSB, prepare for the last channel ;############################################## ;# NI&SCSN transfer 6th channel (CPU3 only) ;############################################## #ifndef cpu3 jmp cc_uncond, raw_end_ni_tmsn ; cpu0..2 exit here #else #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels mov NODP, r6 ; the NI output port #endif mov EBR5, rio slr 1, adc_ch_msk, adc_ch_msk ; check the flag #ifeq RAW_SCSN, RAW_SCSN_ALL ; store to DMEM always, even the not marked for transmission ADC channels ; when the channel is not marked, but RAW_SCSN is RAW_SCSN_ALL we have still to write to DMEM for SCSN readout! ; when RAW_SCSN is not RAW_SCSN_ALL we have to skip this channel jmpr cc_carry, +2 mov GBUSR0, r6 ; dummy output port, GBUSR0 is readonly! ZS channel, but stored in DMEM #else jmp cc_ncarry, raw_end_ni_tmsn ; skip this channel when not marked and not full SCSN transfer and EXIT! #endif mov raw_end_ni_tmsn, rstack ; return address = continue with end marker transmitting ; jmp cc_uncond, raw_ChTML ; with/without DMEM store, with ZS, up to 30 or more samples ; don't need to jump here, as this part follows directly! #endif ; cpu3 #ifgt NSAMPLES, 30 ;############################################################################## ;# ;# NI transmission of one channel if nsamples > 30 ;# - here only some preparation, then use the normal ZS subroutine ;# ;############################################################################## ;# ;# Interface: ;# ;# Input: r14 start address of event buffer in LIO ;# r7 OR mask for the 32 bit word ;# r6 address in LIO of the output port, either 0 (NI) or dummy (zero suppressed channel) ;# r8 rstack, return address ;# r15 bits 31..16: the address of the indicators, AND-ed with the ZS_SMSK ;# ;# Output: sends data to the NI output port ;# Modifies: r1, 2, 3, 4, 5 ;# ;############################################################################## ; use r1, 2, 3, 4, 5 ; find the first sample to send raw_ChTML: #ifneq ZS_FULL_MOD, ZS_FULL_NO mov 0, r2 ; r2 is the first sample to be transferred cmp r9, ZS_FULL_EVENT ; compare with 1 => if 1, full readout in ZS! jmp cc_eq, _raw_time_cmpr_start ; skip searching in the sample mask - it was not calculated! #endif swp r15, r15 ; now point to the ZS SMASKS nop lra4 r1 lra4+ r1 ; the lower 32 bits of the mask nop lra4 r3 ; the upper 32 bits of the mask lra4+ r3 ; the upper 32 bits of the mask nop swp r15, r15 ; restore the DMEM pointer mvpcr +2, rstack2 jmp cc_uncond, fit_search_lsb ; search for the lowest non-zero bit in r1, returns the position in r2, destroys r5 cmp r2, 32 ; the result is 32 when the input was 0 jmp cc_ltu, _raw_time_cmpr_found mov r3, r1 ; now will search in the upper bits 32..63 of the mask mvpcr +2, rstack2 jmp cc_uncond, fit_search_lsb ; search for the lowest non-zero bit in r1, returns the position in r2, destroys r5 mov 32, r5 ; we have to add 32 to the found position ; we don't check if the result was 32, as whis would mean, that the complete 64-bit mask was 0 - impossible! add r2, r5, r2 ; as it is in the upper bits 32..63 mov 0x3F, r5 ; 11 1111 and r2, r5, r2 ; so, if the result was 64 = 100 0000 (both masks=0) we will start from 0! ; here we have in r2 the position of the first non-zero bit in the mask _raw_time_cmpr_found: ; now we need to know the highest bit set in the mask ; we can send min 5 and max 3*NWORDS-1 samples ; we want to send 2 samples before the first marked cmp r2, NBEG_PRE jmpr cc_gtu, +2 mov NBEG_PRE, r2 ; if the left margin <= 2, set it to 2 #ifgt NBEG_PRE, 4 ; for 0..4 we don't need the additional instruction to load NBEG_PRE to a register mov NBEG_PRE, r3 sub r2, r3, r2 ; but start two samples before, now is r2 >= 0 #else sub r2, NBEG_PRE, r2 ; but start two samples before, now is r2 >= 0 #endif ; now the beginning is ok, has up to 2 presamples cmp r2, NBEG_MAX ; compare the beginning with the max value = NSAMPLES+1-3*NWORDS jmpr cc_leu, +2 ; skip the correction when <= max mov NBEG_MAX, r2 ; correct to the max value, so the complete window is within 0..NSAMPLES-1 _raw_time_cmpr_start: ; here we are ready, r2 is the start sample ; as first sample we have to send the offset | nwords << 6 mov NWORDS, r3 mul32 r3, 3, r1 ; r1 must containt 3*nwords, as it is expacted to contain the normal of samples in the normal ADC readout sll 6, r3, r3 or r3, r2, r3 ; this is the first "sample" add rio, r2, rio ; add the start bin to the address of the event buffer for time=0 ; read 2 samples from the event buffer lpio+ r4 ; memory delay (synchronous read) lpio+ r4 lpio rio, r5 ; here we have 3 "samples", the first has a special meaning, the other two are normal ADC samples ; and so we can jump in the middle of the loop jmp cc_uncond, raw_ChTML_shift ; jump in the loop of the normal ZS readout procedure ; input : r1 - search here for the lowest non-zero bit, will be destroyed ; rstack - return address ; output: r2 - the found position from 0 to 31, if more - r1 was 0 ; modifies internally: r5 #inc "fit_search_lsb.asm" ;############################################################################## ;# ;# NI transmission of one channel, up to 30 samples ;# ;############################################################################## ;# ;# Interface: ;# ;# Input: r14 (rio) start address of event buffer in LIO ;# r7 OR mask for the 32 bit word (the two LSBits) ;# r6 address in LIO of the output port, either NODP (NI) or dummy (zero suppressed channel) ;# r8 rstack, return address ;# ;# Output: sends data to the NI output port, writes data to DMEM ;# Modifies: r1, r2 (>30), r3, r4, r5, r14 (rio), r15 (>30, SCSN readout) ;# ;############################################################################## #else ; NSAMPLES <= 30 raw_ChTML: mov NSAMPLES, r1 ; init the loop counter #endif raw_ChTML_loop: ; now only one jump entry point for all kinds of readout & test patterns! ; now read 3 ADC values in a burst, the readout is pipelined, the first value must be read twice! ; lpio rio, r3 ; initial read has to be done twice due to ; lpio+ r3 ; memory delay (synchronous read), get the first values and request the second ; lpio rio, r4 ; initial read has to be done twice due to ; lpio+ r4 ; get the second value and request the third ; lpio rio, r5 ; initial read has to be done twice due to ; lpio+ r5 ; get the third lpio+ r3 ; request the first value and increment the address lpio+ r3 ; get the first value increment the address again lpio+ r4 ; get the second value and increment the address for the last time lpio rio, r5 ; get the last value, don't increment the address! raw_ChTML_shift: ; here the 3 samples are in r3 (earlier), r4, r5 (latest) ; the format is, from bit 31 to 0: r5 - r4 - r3 - r7 (2 LSBits) sll 10, r5, r5 ; combine three 10 bit data words or r5, r4, r5 ; to one (32=10+10+10+2) bit data word slr 4, r5 ; shift by 4 so we are looking at the upper 16 bit only jmp cc_zero, raw_ADCzero ; correct data if the upper 16 bit of the two ADC samples are 0 ; => OR r5 with 0x400, effectively set the LSBit if the last ADC sample raw_ADCcor: ; returns here after the optional correction (s. above) sll 10, r5, r5 ; r5 already contains two samples, (latest << 10 | middle) << 10 or r5, r3, r5 ; append the first (earliest) ADC sample sll 2, r5, r5 ; prepare space for two additional bits on the right side or r5, r7, r5 ; set the two LSBs, r7 is preloaded and toggled properly after each channel spio r5, r6 ; write to NI or dummy #ifneq RAW_SCSN, RAW_SCSN_DIS sra+ r5 ; store the ADC data to DMEM, note that the pointer is initialized before! #endif sub r1, 3, r1 ; decrease the remaining number of samples to read by 3, as we send 3 samples at once jmp cc_gtu, raw_ChTML_loop ; close the loop ; no more data in this ADC channel jmp cc_uncond, rstack ; return from subroutine raw_ADCzero: mov 0x400, r4 ; set the LSB of the latest ADC sample or r5, r4, r5 ; to prevent sending the end-marker 0x0000 in the upper 16 bits jmp cc_uncond, raw_ADCcor