.origin 0 // start of program in PRU memory .entrypoint START // program entry point for the debugger //Copyright Doug Lewis Sept 2017 #include <./pruadc.h> START: // Clear clock outputs to the ADS 1278 CLR SPI_CLK_A_C_PIN // Clear all registers we are going to use, since we know that they can come up // with garbage in them MOV r0, 0 MOV r1, 0 MOV CLOCK_COUNT, 0 // R2 MOV RUN_STATE, 0 // R3 MOV ADC_CNTRL_STR, 0 // R4 MOV ADC_CHNG_FLG, 0 // R5 MOV SMPL_BIT_CNTR, 0 // R6 MOV CHAN_BITMASK, 0 // R7 MOV SHR_MEM_PTR, 0 // R8 MOV SHR_MEM_SZ, 0 // R9 MOV COUNT, 0 // R10 MOV HEAD, 0 // R11 MOV TAIL, 0 // R12 MOV PRU_DATA_STRT, 0 // R13 MOV CURRENT_SAMPLE, 0 // R14 MOV CURRENT_BUF, 0 // R15 MOV CUR_BUF_ADRS, 0 // R16 MOV CUR_BUF_LEFT, 0 // R17 MOV SHR_MEM_START, 0 // R18 MOV NUM_BLOCKS, 0 // R19 MOV BUFF_COUNT, 0 // R20 MOV SAMPLE1 , 0 // R21 MOV SAMPLE2 , 0 // R22 MOV SAMPLE3 , 0 // R23 MOV SAMPLE4 , 0 // R24 MOV SAMPLE5 , 0 // R25 MOV SAMPLE6 , 0 // R26 MOV SAMPLE7 , 0 // R27 MOV SAMPLE8 , 0 // R28 MOV WRAP_COUNT, 0 // R29 // Enable the OCP master port -- allows transfer of data to Linux userspace LBCO r0, C4, 4, 4 // load PRU-ICSS CFG reg into r0 CLR r0, r0, 4 // clear bit 4 (STANDBY_INIT) SBCO r0, C4, 4, 4 // store the modified r0 back at the load addr START_LOOP: // This is an easy place to halt the debugger MOV r1,ADC_STATE_ADDR LBBO RUN_STATE, r1, 0, 4 // the daq state is now loaded into r3. QBEQ START_LOOP, RUN_STATE, 0 // We hang out in a loop until told to read the adc MOV r1,ADC_ADDR // LBBO SHR_MEM_PTR, r1, 0, 4 // load the Linux address that is passed into r8 -- to store sample values MOV R1, PRU0_START_OFFSET ADD PRU_DATA_STRT, SHR_MEM_START, R1 MOV SHR_MEM_PTR, PRU_DATA_STRT MOV r1,ADC_SIZE // LBBO SHR_MEM_SZ, r1, 0, 4 // load the size that is passed into r9 -- the number of samples to take MOV r1,PRU0_NUM_BLOCKS // LBBO NUM_BLOCKS, r1, 0, 4 // load the count of how many 128K blocks we are going to record MEM_BUF_ALLOCATED: MOV CUR_BUF_LEFT, BUFSIZE MOV r1,ADC_CNTRL_CHANGE // load the base address into r1 LBBO ADC_CHNG_FLG, r1, 0, 4 // the ADC_CNTL_CHANGE is now loaded into R5 QBBS CONFIG_CHANGE, ADC_CHNG_FLG.t0 // If bit 1 of ADC_CTRL_CHANGE is set, there is a config //change QBA CONFIG_DONE // Else no changes, goto CONFIG_DONE CONFIG_CHANGE: MOV r1, CLOCK_CNTR_ADDR LBBO CLOCK_COUNT, r1, 0, 4 // the clock delay is now loaded into r2. MOV r1,ADC_CNTRL_STR_ADDR LBBO ADC_CNTRL_STR, r1, 0, 4 // the ADC_CNTL_STR is now loaded into R4 CLR ADC_CHNG_FLG.t1 // Clear the change flag so we dont do the config every loop CONFIG_DONE: //We want to look at the first bit in the config bitmask. READ_NEXT_SAMPLE: MOV r1,ADC_STATE_ADDR //Check to see if we are still need to be running LBBO RUN_STATE, r1, 0, 4 QBEQ CONTINUE_DAQ, RUN_STATE, 1 HALT // We've been told to stop. CONTINUE_DAQ: MOV SAMPLE1, 0 MOV SAMPLE2, 0 MOV SAMPLE3, 0 MOV SAMPLE4, 0 MOV SAMPLE5, 0 MOV SAMPLE6, 0 MOV SAMPLE7, 0 MOV SAMPLE8, 0 // We check data ready to make sure the ADC has had a chance to initialize and set dready high before sampling. DATA_READY_HIGH: QBBS DATA_READY_WAIT, SPI_DSR_A_C_PIN QBA DATA_READY_HIGH DATA_READY_WAIT: QBBC DATA_READY, SPI_DSR_A_C_PIN // If Data Ready line clear, read a sample QBA DATA_READY_WAIT // Else hang out in a tight loop ... DATA_READY: MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL1: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock line to be high DELAYON1: SUB r0, r0, 1 QBNE DELAYON1, r0, 0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT1, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE1, SAMPLE1, 0x00000001 ZERO_BIT1: LSL SAMPLE1, SAMPLE1, 1 // Shift current sample contents left by one MOV r0, CLOCK_COUNT DELAYOFF1: SUB r0, r0, 1 QBNE DELAYOFF1, r0, 0 // loop until the delay has expired (equals 0) SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample QBNE READ_CHANNEL1, SMPL_BIT_CNTR, 0 ////////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL2: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON2: SUB r0, r0, 1 QBNE DELAYON2, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT2, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE2, SAMPLE2, 0x00000001 ZERO_BIT2: LSL SAMPLE2, SAMPLE2, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF2: SUB r0, r0, 1 QBNE DELAYOFF2, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL2, SMPL_BIT_CNTR, 0 ////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL3: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON3: SUB r0, r0, 1 QBNE DELAYON3, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT3, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE3, SAMPLE3, 0x00000001 ZERO_BIT3: LSL SAMPLE3, SAMPLE3, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF3: SUB r0, r0, 1 QBNE DELAYOFF3, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL3, SMPL_BIT_CNTR, 0 ///////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL4: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON4: SUB r0, r0, 1 QBNE DELAYON4, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT4, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE4, SAMPLE4, 0x00000001 ZERO_BIT4: LSL SAMPLE4, SAMPLE4, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF4: SUB r0, r0, 1 QBNE DELAYOFF4, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL4, SMPL_BIT_CNTR, 0 ///////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL5: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON5: SUB r0, r0, 1 QBNE DELAYON5, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT5, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE5, SAMPLE5, 0x00000001 ZERO_BIT5: LSL SAMPLE5, SAMPLE5, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF5: SUB r0, r0, 1 QBNE DELAYOFF5, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL5, SMPL_BIT_CNTR, 0 ///////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL6: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON6: SUB r0, r0, 1 QBNE DELAYON6, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT6, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE6, SAMPLE6, 0x00000001 ZERO_BIT6: LSL SAMPLE6, SAMPLE6, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF6: SUB r0, r0, 1 QBNE DELAYOFF6, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL6, SMPL_BIT_CNTR, 0 ///////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL7: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON7: SUB r0, r0, 1 QBNE DELAYON7, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT7, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE7, SAMPLE7, 0x00000001 ZERO_BIT7: LSL SAMPLE7, SAMPLE7, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF7: SUB r0, r0, 1 QBNE DELAYOFF7, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL7, SMPL_BIT_CNTR, 0 ///////////////////////// MOV SMPL_BIT_CNTR, SAMPLE_SIZE // We're going to read 24 bits READ_CHANNEL8: MOV r0, CLOCK_COUNT // Reload the clock delay val into R0 SET SPI_CLK_A_C_PIN // set the clock to be high DELAYON8: SUB r0, r0, 1 QBNE DELAYON8, r0, 0 // Reload the clock delay val into R0 CLR SPI_CLK_A_C_PIN // set the clock to be low // Read Data In QBBC ZERO_BIT8, SPI_DATA_IN_A_C_PIN // Check to see whether Data In is a 0 or 1 OR SAMPLE8, SAMPLE8, 0x00000001 ZERO_BIT8: LSL SAMPLE8, SAMPLE8, 1 // Shift current sample contents left by one SUB SMPL_BIT_CNTR, SMPL_BIT_CNTR, 1 // See if we have read all 24 bits of the sample MOV r0, CLOCK_COUNT DELAYOFF8: SUB r0, r0, 1 QBNE DELAYOFF8, r0, 0 // loop until the delay has expired (equals 0) QBNE READ_CHANNEL8, SMPL_BIT_CNTR, 0 ///////////////////////// STORE_SAMPLE: LSR SAMPLE1, SAMPLE1, 1 // Need to shift the sample word back to the right by one LSR SAMPLE2, SAMPLE2, 1 LSR SAMPLE3, SAMPLE3, 1 LSR SAMPLE4, SAMPLE4, 1 LSR SAMPLE5, SAMPLE5, 1 LSR SAMPLE6, SAMPLE6, 1 LSR SAMPLE7, SAMPLE7, 1 LSR SAMPLE8, SAMPLE8, 1 MOV SAMPLE1.b3, 0x01 // Stash the channel bitmask in the upper byte used to store the sample MOV SAMPLE2.b3, 0x02 MOV SAMPLE3.b3, 0x04 MOV SAMPLE4.b3, 0x08 MOV SAMPLE5.b3, 0x10 MOV SAMPLE6.b3, 0x20 MOV SAMPLE7.b3, 0x40 MOV SAMPLE8.b3, 0x80 SBBO SAMPLE1, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE2, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE3, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE4, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE5, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE6, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE7, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SBBO SAMPLE8, SHR_MEM_PTR, 0, 4 // store the sample value into shared memory space ADD SHR_MEM_PTR, SHR_MEM_PTR, 4 // Add 4 bytes per sample to the address pointer SUB CUR_BUF_LEFT, CUR_BUF_LEFT, 32 // reducing the number of samples - 4 bytes per sample, 8 channels QBEQ BUFFER_DONE, CUR_BUF_LEFT, 0 // See if we have taken 128kb of samples QBA READ_NEXT_SAMPLE // If we've looped thru all channels in the sample. wait for the next sample BUFFER_DONE: MOV CUR_BUF_LEFT, BUFSIZE // If we have recorded all of the buffers that we need to, then halt. SUB NUM_BLOCKS, NUM_BLOCKS, 1 QBEQ END, NUM_BLOCKS, 0 MOV R1, BUFSIZE ADD CUR_BUF_ADRS, CUR_BUF_ADRS, R1 MOV r1, SHARED_MEM_SIZE QBEQ WRAP_TIME, CUR_BUF_ADRS, r1 QBA READ_NEXT_SAMPLE WRAP_TIME: // Always wanted to be a rapper ;-0) // We have used all the shared memory to write samples, wrap back to the beginning. MOV CUR_BUF_ADRS, 0 MOV r31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0 HALT //DEBUG QBA READ_NEXT_SAMPLE // halt the pru program -- we reach here when the file is full. END: HALT