; subprogram to read the ADCs directly and to write them to the IMEM of unused CPUs ; ; $Id: adc2cpu.asm 1949 2008-02-18 20:13:19Z angelov $: ; input ; c10 contains one or two start addresses 0x100+i ; Start Address CPU ADCs ; 0x100..0x107 0 0.. 7 ; 0x100..0x107 1 5..12 ; 0x100..0x107 2 9..16 ; 0x100..0x107 3 13..20 ; c11 is the number of words-1 (bits 31..16) and the start address in GIO (bits 15..0). ; the start addresses of IMEM0,1,2,3 are 0x8000, 0x9000, 0xA000, 0xB000 ; after each increment, the address will be ANDed with 0xB000. So the address will wrap ; after 0xBFFF to 0xA000! This is useful when using cpu1,2. ; Note that c11 is optionally used for debugging as counter of the clear interrupts! ; So when using adc2cpu disable these counters! #def debug_adc2cpu = 1; write to DMEM some parameters ; ONE channel ; cpu start address max samples uses IMEM ; 0 0x9000 3*4096*2 1,2,3 ; or ; 1 0xA000 3*4096*2 2,3,0 ; or ; 2 0xB000 3*4096*2 3,0,1 ; or ; 3 0xA000 3*4096*2 0,1,2 ; TWO channels in TWO CPUs ; CPUs start addr max samples uses IMEM ; 0,1 0xA000,0xB000 2 x 4096*2 2,3 ; ... adc2cpu: mov c11, r0 iext 0xFFFF mov 0xFFFF, r1 and r0, r1, r10 ; start address in GIO jmp cc_zero, adc2cpu_off ; turn off if 0 swp r0, r0 ; now bits 15..0 and r0, r1, r11 ; number of words jmp cc_zero, adc2cpu_off ; turn off if 0 mov 0x3FF, r2 ; mask for the ADC shl 12, r2, r3 or r2, r3, r2 iext 0xBFFF mov 0xBFFF, r9 ; mask for the address in GIO mov c10, r0 mov 0x107, r1 and r0, r1, r12 ; r12 points to the address of the 1st ADC jmp cc_zero, adc2cpu_off ; turn off if 0 mov adc2cpu_1adc, r8 shlt 1, r0 jmp cc_ncarry, adc2cpu_2adc_tst swp r0, r0 mov 0xFFF, r3 and r3, r0, r3 ; the oversampling factor mov r3, r4 ; the oversampling counter mov 0, r1 ; the accumulator mov 0x200, r14 mov adc2cpu_1dec, r8 ; jmp cc_uncond, adc2cpu_sync_prep adc2cpu_2adc_tst: swp r0, r0 ; now take bits 15..0 and r0, r1, r13 ; r13 points to the address of the 2nd ADC (optional) jmpr cc_zero, +2 mov adc2cpu_2adc, r8 adc2cpu_sync_prep: ; now sync... cli mov adc2cpu_sync, r0 mov 0x20, r5 mul32 r5, c5, r5 mov 0xb07, r6 add r6, r5, r6 ; the IRQ7 address sgio r0, r6 mov 0xb0e, r6 add r6, r5, r6 ; the IRQHW address mov b10000101, r0 ; the mask nop ; enough nops nop ; to ensure that nop ; no CPU will wait nop ; after writing to GIO nop ; otherwise the CPUs nop ; will be not synchronized! jmpr cc_busy, 0 ; this should not happen! sgio r0, r6 sti ; enable interrupts jmpr cc_uncond, 0 ; and wait forever adc2cpu_sync: ; for debugging #ifdef debug_adc2cpu mov 0, r15 nop sra+ r9 nop sra+ r10 nop sra+ r11 nop sra+ r12 nop sra+ r13 #endif ; here the CPUs are synchronized with the EOC (end of conversion) of the ADC jmp cc_uncond, r8 ; jump to the proper routine adc2cpu_off: mov 0, r0 mov clk_onoff, r1 sub r1, c1, r1 ; turn off permanently sgio r0, r1 jmpr cc_uncond, 0 nop adc2cpu_2adc: ; Read 2 ADC channels ; here we have ; r10 is the start address in GIO ; ; r9 is mask for the address = 0xBFFF, ANDed after each increment ; ; r11 is the number of words, decremented after GIO write ; exit if carry is set! ; ; r2 mask for the data = 0x3FF3FF ; ; r12 is the address of the ADC ; ; r13 is the address of the 2nd ADC ; instruction CPU clock lpio r12, r0 ; 0 lpio r13, r0 ; 1 lpio r13, r1 ; 2 shl 12, r1, r1 ; 3 or r0, r1, r0 ; 4 and r0, r2, r0 ; 5 sgio r0, r10 ; 6 add r10, c1, r10 ; 7 write_address++ and r10, r9, r10 ; 8 write_address & 0xBFFF sub r11, c1, r11 ; 9 word_counter-- jmp cc_ncarry, r8 ; 10 & 11 jmp cc_uncond, adc2cpu_clear adc2cpu_1adc: ; Read 1 ADC channel ; here we have ; r10 is the start address in GIO ; ; r9 is mask for the address = 0xBFFF, ANDed after each increment ; ; r11 is the number of words, decremented after GIO write ; exit if carry is set! ; ; r2 mask for the data = 0x3FF3FF ; ; r12 is the address of the 1st ADC ; lpio r12, r0 ; 0 lpio r12, r0 ; 1 nop ; 2 nop ; 3 nop ; 4 nop ; 5 nop ; 6 nop ; 7 nop ; 8 nop ; 9 nop ; 10 nop ; 11 lpio r12, r1 ; 0 lpio r12, r1 ; 1 shl 12, r1, r1 ; 2 or r1, r0, r0 ; 3 and r0, r2, r0 ; 4 sgio r0, r10 ; 5 add r10, c1, r10 ; 6 write_address++ and r10, r9, r10 ; 7 write_address & 0xBFFF sub r11, c1, r11 ; 8 word_counter-- nop ; 9 jmp cc_ncarry, r8 ; 10 & 11 jmp cc_uncond, adc2cpu_clear adc2cpu_1dec: ; Read 1 ADC channel ; here we have ; r10 is the start address in GIO ; ; r9 is mask for the address = 0xBFFF, ANDed after each increment ; ; r11 is the number of words, decremented after GIO write ; exit if carry is set! ; ; r2 mask for the data = 0x3FF3FF ; r3 number of oversamples ; ; r12 is the address of the 1st ADC ; lpio r12, r0 ; 0 lpio r12, r0 ; 1 and r0, r2, r0 ; 2 mask xor r0, r14, r0 ; 3 invert the MSB add r0, r1, r1 ; 4 accumulate sub r4, c1, r4 ; 5 loop counter-- jmp cc_zero, adc2cpu_1dec_store ; 6 nop ; 7 nop ; 8 nop ; 9 jmp cc_uncond, r8 ; 10 & 11 adc2cpu_1dec_store: sgio r1, r10 ; 8 store add r10, c1, r10 ; 9 write_address++ and r10, r9, r10 ; 10 write_address & 0xBFFF sub r11, c1, r11 ; 11 word_counter-- jmp cc_carry, adc2cpu_clear ; 0 ; first sample in the loop lpio r12, r0 ; 1 lpio r12, r0 ; 2 and r0, r2, r0 ; 3 mask & accumulate xor r0, r14, r1 ; 4 invert the MSB mov r3, r4 ; 5 the oversampling counter sub r4, c1, r4 ; 6 loop counter-- jmp cc_zero, adc2cpu_1dec_store ; 7 nop ; 8 nop ; 9 jmp cc_uncond, r8 ; 10 & 11 adc2cpu_clear: ; for debugging #ifdef debug_adc2cpu sra+ r10 nop sra+ r11 #endif cli; mov b00000101, r1 ; restore the mask jmpr cc_busy, 0 sgio r1, r6 mov 0x412, r0 ; code for clear jmpr cc_busy, 0 sgio r0, SMCMD ; send clear jmp cc_uncond, clr_endloop nop