; ; Copyright (C) 2023 Texas Instruments Incorporated ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; ; Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the ; distribution. ; ; Neither the name of Texas Instruments Incorporated nor the names of ; its contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;************************************************************************************ ;*   File:     bissc_main.asm                                            * ;*                                                                                  * ;*   Brief:    Firmware initialization, Storing position data, Control communication* ;************************************************************************************ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;/ ; Assembler Directives Section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;/ .sect ".text" .retain ; Required for building .out with assembly file .retainrefs ; Required for building .out with assembly file .global BISSC_INIT .include "bissc_icss_reg_defs.h" .include "bissc_params.h" .include "bissc_interface.h" .include "firmware_version.h" .include "bissc_macros.h" ;bissc main starts from here BISSC_INIT: JMP BISSC_MAIN .word ICSS_FIRMWARE_RELEASE_1, ICSS_FIRMWARE_RELEASE_2 BISSC_MAIN: .if $isdefed("PRU0") .asg PRU0_DMEM, PRUx_DMEM .asg ICSS_CFG_PRU0_ENDAT_CH0_CFG1, ICSS_CFG_PRUx_BISSC_CH0_CFG1 .asg ICSS_CFG_PRU0_ENDAT_CH1_CFG1, ICSS_CFG_PRUx_BISSC_CH1_CFG1 .asg ICSS_CFG_PRU0_ENDAT_CH2_CFG1, ICSS_CFG_PRUx_BISSC_CH2_CFG1 .asg ICSS_CFG_PRU0_ENDAT_CH0_CFG0, ICSS_CFG_PRUx_BISSC_CH0_CFG0 .asg ICSS_CFG_PRU0_ENDAT_CH1_CFG0, ICSS_CFG_PRUx_BISSC_CH1_CFG0 .asg ICSS_CFG_PRU0_ENDAT_CH2_CFG0, ICSS_CFG_PRUx_BISSC_CH2_CFG0 .asg ICSS_CFG_PRU0_ENDAT_TXCFG, ICSS_CFG_PRUx_BISSC_TXCFG .asg ICSS_CFG_PRU0_ENDAT_RXCFG, ICSS_CFG_PRUx_BISSC_RXCFG .endif .if $isdefed("PRU1") .asg PRU1_DMEM, PRUx_DMEM .asg ICSS_CFG_PRU1_ENDAT_CH0_CFG1, ICSS_CFG_PRUx_BISSC_CH0_CFG1 .asg ICSS_CFG_PRU1_ENDAT_CH1_CFG1, ICSS_CFG_PRUx_BISSC_CH1_CFG1 .asg ICSS_CFG_PRU1_ENDAT_CH2_CFG1, ICSS_CFG_PRUx_BISSC_CH2_CFG1 .asg ICSS_CFG_PRU1_ENDAT_CH0_CFG0, ICSS_CFG_PRUx_BISSC_CH0_CFG0 .asg ICSS_CFG_PRU1_ENDAT_CH1_CFG0, ICSS_CFG_PRUx_BISSC_CH1_CFG0 .asg ICSS_CFG_PRU1_ENDAT_CH2_CFG0, ICSS_CFG_PRUx_BISSC_CH2_CFG0 .asg ICSS_CFG_PRU1_ENDAT_TXCFG, ICSS_CFG_PRUx_BISSC_TXCFG .asg ICSS_CFG_PRU1_ENDAT_RXCFG, ICSS_CFG_PRUx_BISSC_RXCFG .endif .if $isdefed("ENABLE_MULTI_MAKE_RTU") M_BISSC_LS_WAIT_FOR_SYNC .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") M_BISSC_LS_WAIT_FOR_SYNC .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") M_BISSC_LS_WAIT_FOR_SYNC .endif ; clear all registers ZERO &R0, 120 SBCO &R0, PRUx_DMEM, BISSC_REG_BACKUP, 24 LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 ;bit_idx - 4 th bit(middle one) of 8x over clock or 2nd bit for 4x oversampling LDI VALID_BIT_IDX, BISSC_CH0_VALID_BIT_IDX ;Valid bit index base(24) LBCO &PRIMARY_CORE, PRUx_DMEM, BISSC_MASK_FOR_PRIMARY_CORE, 1 ;load the primary core mask .if $isdefed("ENABLE_MULTI_MAKE_RTU") ZERO &SCRATCH1, 1 SBCO &SCRATCH1, PRUx_DMEM, BISSC_LS_EXEC_RTU_STATE, 1 QBBC BISSC_SKIP_GLOBAL_REINIT0?, PRIMARY_CORE, 0 ;global reinit to be done only by primary core SET R31, BISSC_TX_GLOBAL_REINIT ; Set TX_EN low .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") ZERO &SCRATCH1, 1 SBCO &SCRATCH1, PRUx_DMEM, BISSC_LS_EXEC_PRU_STATE, 1 QBBC BISSC_SKIP_GLOBAL_REINIT0?, PRIMARY_CORE, 1 SET R31, BISSC_TX_GLOBAL_REINIT .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") ZERO &SCRATCH1, 1 SBCO &SCRATCH1, PRUx_DMEM, BISSC_LS_EXEC_TXPRU_STATE, 1 QBBC BISSC_SKIP_GLOBAL_REINIT0?, PRIMARY_CORE, 2 SET R31, BISSC_TX_GLOBAL_REINIT .else SET R31, BISSC_TX_GLOBAL_REINIT .endif BISSC_SKIP_GLOBAL_REINIT0?: LBCO &CH_MASK, PRUx_DMEM, BISSC_CHANNEL_CONFIG_OFFSET, 1 .if $isdefed("ENABLE_MULTI_MAKE_RTU") LDI CH_MASK, BISSC_CONFIG_CH0 ;change the channel mask it self, so individual PRU work as channel agnostic, single channel single PRU firmware. .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") LDI CH_MASK, BISSC_CONFIG_CH1 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") LDI CH_MASK, BISSC_CONFIG_CH2 .endif ;Measure the Processing delay upon initialization LDI SCRATCH1.b0, 0 ;clear the re measure flag for processing delay before proc measurement SBCO &SCRATCH1, PRUx_DMEM, BISSC_RE_MEASURE_PROC_DELAY, 1 M_MEASURE_MAX_PROC_TIME ;update the status to notify application LDI STATUS_REG1, 1 .if $isdefed("ENABLE_MULTI_MAKE_RTU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_STATUS_CH0_CONFIG_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_STATUS_CH1_CONFIG_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_STATUS_CH2_CONFIG_OFFSET, 1 .else ;ch0 status offset is the base status offset and only ch0 offset is going to be used in single ch or multi ch single pru SBCO &STATUS_REG1, PRUx_DMEM, BISSC_STATUS_CH0_CONFIG_OFFSET, 1 .endif BISSC_HANDLE_HOST_TRIGGER: ;If Host Trigger=1, request made by R5F to Firmware, now Firmware do processing and when done set trigger to 0 so that R5F application can act further. .if $isdefed("ENABLE_MULTI_MAKE_RTU") LBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH0_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") LBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH1_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") LBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH2_STATUS_OFFSET, 1 .else ;ch0 cycle trigger offset is the base cycle trigger offset and only ch0 offset is going to be used in single ch or multi ch single pru LBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH0_STATUS_OFFSET, 1 .endif LBCO &STATUS_REG2, PRUx_DMEM, BISSC_MEAS_PROC_DELAY_OFFSET, 1 LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 QBBC BISSC_SKIP_MEASURE_PROC_DELAY?, STATUS_REG2, 0 ;Measure the Processing delay upon host trigger LDI SCRATCH1.b0, 0 SBCO &SCRATCH1, PRUx_DMEM, BISSC_RE_MEASURE_PROC_DELAY, 1 M_MEASURE_MAX_PROC_TIME BISSC_SKIP_MEASURE_PROC_DELAY?: QBBS BISSC_CTRL_CMD_DONE, BISSC_FLAGS_REG, 0 .if $isdefed("ENABLE_MULTI_MAKE_RTU") LBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH0_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") LBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH1_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") LBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH2_CONFIG_OFFSET, 4 .else ;ch0 ctrl command offset is the base ctrl command offset and only ch0 ctrl command offset is going to be used in single ch or multi ch single pru LBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH0_CONFIG_OFFSET, 4 .endif QBEQ BISSC_CTRL_CMD_SKIP, SCRATCH, 0 MOV BISSC_CTRL_CMD, SCRATCH SET BISSC_FLAGS_REG, BISSC_FLAGS_REG, 0 ZERO &SCRATCH, 4 .if $isdefed("ENABLE_MULTI_MAKE_RTU") SBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH0_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") SBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH1_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") SBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH2_CONFIG_OFFSET, 4 .else SBCO &SCRATCH, PRUx_DMEM, BISSC_CTRL_CMD_CH0_CONFIG_OFFSET, 4 .endif ZERO &BISSC_CTRL_FF, 4 LDI BISSC_CTRL_CRC, 0 LDI BISSC_CTRL_CYCLE_CNTR, 0 LDI BISSC_CTRL_CMD_RES, 0 LDI BISSC_CTRL_OTF_CRC, 0 LDI BISSC_CMD_BIT_PTR, 31 ; CMD bit pointer will points to MSB always, decremented only when we transmit one bit from hex command QBA BISSC_CTRL_CMD_DONE BISSC_CTRL_CMD_SKIP: CLR BISSC_FLAGS_REG, BISSC_FLAGS_REG, 0 BISSC_CTRL_CMD_DONE: ;wait till host trigger is set to 1. QBEQ BISSC_HANDLE_HOST_TRIGGER, STATUS_REG1, 0 ;BiSS-C position data/control communication loop start here ;clock mode in freerunning/stop low/stop high and ch0 is selected QBBC BISSC_IS_CH1?, CH_MASK, 0 LDI R30.w2, (BISSC_TX_CLK_MODE_FREERUN_STOPHIGH | BISSC_TX_CH0_SEL) LBCO &SCRATCH2.w2, PRUx_DMEM, BISSC_CH0_PROC_DELAY_OFFSET, 2 LDI R30.b0, 0 BISSC_IS_CH1?: QBBC BISSC_IS_CH2?, CH_MASK, 1 LDI R30.w2, (BISSC_TX_CLK_MODE_FREERUN_STOPHIGH | BISSC_TX_CH1_SEL) LBCO &SCRATCH2.w2, PRUx_DMEM, BISSC_CH1_PROC_DELAY_OFFSET, 2 LDI R30.b0, 0 BISSC_IS_CH2?: QBBC BISSC_SKIP_CH_SEL1?, CH_MASK, 2 LDI R30.w2, (BISSC_TX_CLK_MODE_FREERUN_STOPHIGH | BISSC_TX_CH2_SEL) LBCO &SCRATCH2.w2, PRUx_DMEM, BISSC_CH2_PROC_DELAY_OFFSET, 2 LDI R30.b0, 0 BISSC_SKIP_CH_SEL1?: ; since ENABLE_RUNTIME_CH is kept enabled with all 3 channels selected for multi channel, last channel would have been selected by now .if $isdefed("ENABLE_MULTI_CHANNEL") LOOP BISSC_SEND_RECEIVE_BISSC_MULTI_CHANNEL, 3 SUB R30.b2, R30.b2, 1 BISSC_SEND_RECEIVE_BISSC_MULTI_CHANNEL: .endif ;clock mode in freerunning/stop low/stop high and ch0 is selected LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 LBCO &SCRATCH2.b1, PRUx_DMEM, BISSC_POS_CRC_LEN_CONFIG_OFFSET, 1 .if $isdefed("ENABLE_MULTI_MAKE_RTU") LBCO &DAISY_CHAIN, PRUx_DMEM, BISSC_NUM_ENCODER_CH0_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") LBCO &DAISY_CHAIN, PRUx_DMEM, BISSC_NUM_ENCODER_CH1_CONFIG_OFFSET, 4 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") LBCO &DAISY_CHAIN, PRUx_DMEM, BISSC_NUM_ENCODER_CH2_CONFIG_OFFSET, 4 .else ;ch0 number of encoders and encoder data lengths is the base daisychain offset and only ch0 offset is going to be used in single ch or multi ch single pru LBCO &DAISY_CHAIN, PRUx_DMEM, BISSC_NUM_ENCODER_CH0_CONFIG_OFFSET, 4 .endif ;compute RX frame size from input arguments. ACK length will be taken from processing delay. ADD SCRATCH2.w2, SCRATCH2.w2, DAISY_CHAIN.b1 ;data length of encoder 0 ADD SCRATCH2.w2, SCRATCH2.w2, SCRATCH2.b1 ;crc length ADD SCRATCH2.w2, SCRATCH2.w2, BISSC_EW_LEN ;E + W ADD SCRATCH2.w2, SCRATCH2.w2, BISSC_SB_CDS_LEN ;SB + CDS QBEQ BISSC_SKIP_DAISY_CHAIN, DAISY_CHAIN.b2, 0 ADD SCRATCH2.w2, SCRATCH2.w2, DAISY_CHAIN.b2 ;data length of encoder 1 ADD SCRATCH2.w2, SCRATCH2.w2, SCRATCH2.b1 ;crc length ADD SCRATCH2.w2, SCRATCH2.w2, BISSC_EW_LEN ;E + W QBEQ BISSC_SKIP_DAISY_CHAIN, DAISY_CHAIN.b3, 0 ADD SCRATCH2.w2, SCRATCH2.w2, DAISY_CHAIN.b3 ;data length of encoder 2 ADD SCRATCH2.w2, SCRATCH2.w2, SCRATCH2.b1 ;crc length ADD SCRATCH2.w2, SCRATCH2.w2, BISSC_EW_LEN ;E + W BISSC_SKIP_DAISY_CHAIN: LDI SCRATCH2.w0, 0 ; store Rx and Tx frame size to ICSS_CFG_PRUx_ED_CHx for all configured channels M_BISSC_CLK_CONFIG CH_MASK, SCRATCH2 LDI SCRATCH1, 0 ;clear the syn bits for load share. SBCO &SCRATCH1, PRUx_DMEM, BISSC_LS_EXEC_RTU_STATE, 4 LDI R30.b0, 0 .if $isdefed("ENABLE_MULTI_CHANNEL") SET R31, BISSC_TX_GLOBAL_GO .else SET R31, BISSC_TX_CHANNEL_GO .endif ;enable Rx for channel 0 QBBC BISSC_IS_CH1_EN?, CH_MASK, 0 SET R30, BISSC_CH0_RX_EN BISSC_IS_CH1_EN?: QBBC BISSC_IS_CH2_EN?, CH_MASK, 1 SET R30, BISSC_CH1_RX_EN BISSC_IS_CH2_EN?: QBBC BISSC_ACK_BIT1?, CH_MASK, 2 SET R30, BISSC_CH2_RX_EN ;ack bit BISSC_ACK_BIT1?: ; wait for valid bit AND SCRATCH1.b0, R31.b3, CH_MASK QBNE BISSC_ACK_BIT1?, SCRATCH1.b0, CH_MASK ; wait for valid MOV SCRATCH1, R31 ;Set the valid bit for clearing flag so that next bit can come. QBBC BISSC_IS_CH1_VALID_ACK?, CH_MASK, 0 SET R31, R31, BISSC_CH0_RX_VALID_BIT_OFFSET BISSC_IS_CH1_VALID_ACK?: QBBC BISSC_IS_CH2_VALID_ACK?, CH_MASK, 1 SET R31, R31, BISSC_CH1_RX_VALID_BIT_OFFSET BISSC_IS_CH2_VALID_ACK?: QBBC BISSC_SKIP_RX_VALID_ACK?, CH_MASK, 2 SET R31, R31, BISSC_CH2_RX_VALID_BIT_OFFSET BISSC_SKIP_RX_VALID_ACK?: ;must maintain 3 cycles before checking next valid bit NOP NOP QBBC BISSC_IS_CH1_FIFO_ACK?, CH_MASK, 0 QBBC BISSC_ACK_FOUND1?, SCRATCH1.b0, FIFO_BIT_IDX BISSC_IS_CH1_FIFO_ACK?: QBBC BISSC_IS_CH2_FIFO_ACK?, CH_MASK, 1 QBBC BISSC_ACK_FOUND1?, SCRATCH1.b1, FIFO_BIT_IDX BISSC_IS_CH2_FIFO_ACK?: QBBC BISSC_ACK_BIT1?, CH_MASK, 2 QBBS BISSC_ACK_BIT1?, SCRATCH1.b2, FIFO_BIT_IDX BISSC_ACK_FOUND1?: ;start bit BISSC_START_BIT1?: ; wait for valid bit AND SCRATCH1.b0, R31.b3, CH_MASK QBNE BISSC_START_BIT1?, SCRATCH1.b0, CH_MASK ; wait for valid MOV SCRATCH1, R31 QBBC BISSC_IS_CH1_VALID_SB?, CH_MASK, 0 SET R31, R31, BISSC_CH0_RX_VALID_BIT_OFFSET BISSC_IS_CH1_VALID_SB?: QBBC BISSC_IS_CH2_VALID_SB?, CH_MASK, 1 SET R31, R31, BISSC_CH1_RX_VALID_BIT_OFFSET BISSC_IS_CH2_VALID_SB?: QBBC BISSC_SKIP_RX_VALID_SB?, CH_MASK, 2 SET R31, R31, BISSC_CH2_RX_VALID_BIT_OFFSET BISSC_SKIP_RX_VALID_SB?: NOP NOP ;must maintain 3 cycles before checking next valid bit QBBC BISSC_IS_CH1_FIFO_SB?, CH_MASK, 0 QBBS BISSC_START_BIT_FOUND?, SCRATCH1.b0, FIFO_BIT_IDX BISSC_IS_CH1_FIFO_SB?: QBBC BISSC_IS_CH2_FIFO_SB?, CH_MASK, 1 QBBS BISSC_START_BIT_FOUND?, SCRATCH1.b1, FIFO_BIT_IDX BISSC_IS_CH2_FIFO_SB?: QBBC BISSC_START_BIT1?, CH_MASK, 2 QBBC BISSC_START_BIT1?, SCRATCH1.b2, FIFO_BIT_IDX BISSC_START_BIT_FOUND?: ; cds bit BISSC_CDS_BIT1?: ; wait for valid bit AND SCRATCH1.b0, R31.b3, CH_MASK QBNE BISSC_CDS_BIT1?, SCRATCH1.b0, CH_MASK MOV BISSC_CDS_BACKUP, R31 QBBC BISSC_IS_CH1_VALID_CDS?, CH_MASK, 0 SET R31, R31, BISSC_CH0_RX_VALID_BIT_OFFSET BISSC_IS_CH1_VALID_CDS?: QBBC BISSC_IS_CH2_VALID_CDS?, CH_MASK, 1 SET R31, R31, BISSC_CH1_RX_VALID_BIT_OFFSET BISSC_IS_CH2_VALID_CDS?: QBBC BISSC_CDS_BIT_DETECTED?, CH_MASK, 2 SET R31, R31, BISSC_CH2_RX_VALID_BIT_OFFSET BISSC_CDS_BIT_DETECTED?: .if $isdefed("ENABLE_MULTI_CHANNEL") ADD RAW_DATA_LEN, DAISY_CHAIN.b1, (BISSC_EW_LEN + BISSC_RX_CRCBITS) .else QBBC BISSC_RCV_CH1?, CH_MASK, 0 LDI SCRATCH2.b3, BISSC_POS_DATA_WORD_CH0_OFFSET LDI SCRATCH2.b1, BISSC_POS_CRC_ERR_COUNT_CH0_OFFSET LDI SCRATCH2.b2, BISSC_POS_OTF_CRC_CH0_OFFSET JMP BISSC_SKIP_RCV? BISSC_RCV_CH1?: QBBC BISSC_RCV_CH2?, CH_MASK, 1 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 8 LDI SCRATCH2.b3, BISSC_POS_DATA_WORD_CH1_OFFSET LDI SCRATCH2.b1, BISSC_POS_CRC_ERR_COUNT_CH1_OFFSET LDI SCRATCH2.b2, BISSC_POS_OTF_CRC_CH1_OFFSET JMP BISSC_SKIP_RCV? BISSC_RCV_CH2?: QBBC BISSC_SKIP_RCV?, CH_MASK, 2 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 16 LDI SCRATCH2.b3, BISSC_POS_DATA_WORD_CH2_OFFSET LDI SCRATCH2.b1, BISSC_POS_CRC_ERR_COUNT_CH2_OFFSET LDI SCRATCH2.b2, BISSC_POS_OTF_CRC_CH2_OFFSET BISSC_SKIP_RCV?: .endif BISSC_POSITION_DATA?: QBEQ BISSC_END_RECEIVE?, DAISY_CHAIN.b0,0 ZERO &RAW_DATA1_0, 24 QBEQ BISSC_ENCODER3_DATA?, DAISY_CHAIN.b0, 3 ;check if encoder 2 is connected QBEQ BISSC_ENCODER2_DATA?, DAISY_CHAIN.b0, 2 ;check if encoder 1 is connected .if !$isdefed("ENABLE_MULTI_CHANNEL") ADD RAW_DATA_LEN, DAISY_CHAIN.b1, (BISSC_EW_LEN + BISSC_RX_CRCBITS) .endif LDI SCRATCH2.b0, BISSC_POS_DATA_RES_ENCODER0_OFFSET QBA BISSC_START_RECEIVE? BISSC_ENCODER2_DATA?: .if !$isdefed("ENABLE_MULTI_CHANNEL") ADD RAW_DATA_LEN, DAISY_CHAIN.b2, (BISSC_EW_LEN + BISSC_RX_CRCBITS) .endif LDI SCRATCH2.b0, BISSC_POS_DATA_RES_ENCODER1_OFFSET QBA BISSC_START_RECEIVE? BISSC_ENCODER3_DATA?: .if !$isdefed("ENABLE_MULTI_CHANNEL") ADD RAW_DATA_LEN, DAISY_CHAIN.b3, (BISSC_EW_LEN + BISSC_RX_CRCBITS) .endif LDI SCRATCH2.b0, BISSC_POS_DATA_RES_ENCODER2_OFFSET BISSC_START_RECEIVE?: .if $isdefed("ENABLE_MULTI_CHANNEL") ;receive pos data for multiple channel at once M_OTF_RECEIVE_MC RAW_DATA1_0, RAW_DATA2_0, RAW_DATA1_1, RAW_DATA2_1, RAW_DATA1_2, RAW_DATA2_2, SCRATCH2.b0 .else ;receive pos data for single channel M_OTF_RECEIVE RAW_DATA1_0, RAW_DATA2_0, SCRATCH2.b0 .endif SUB DAISY_CHAIN.b0, DAISY_CHAIN.b0, 1 QBA BISSC_POSITION_DATA? BISSC_END_RECEIVE?: ; Control communication starts from here QBBC BISSC_CTRL_COMMUNICATION_SKIP?, BISSC_FLAGS_REG, 0 ADD BISSC_CTRL_CYCLE_CNTR, BISSC_CTRL_CYCLE_CNTR, 1 QBLE BISSC_CTRL_START_BIT?, BISSC_CTRL_CYCLE_CNTR, 16 QBA BISSC_CTRL_CMD_BIT_SEND_SKIP? BISSC_CTRL_START_BIT?: LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 QBNE BISSC_CTRL_CMD_NEXT_BIT?, BISSC_CTRL_CYCLE_CNTR, 16 ;enable clock override for setting clock to low during timeout ZERO &SCRATCH1, 4 SET SCRATCH1, SCRATCH1, 29 M_BISSC_CLK_CONFIG CH_MASK, SCRATCH1 QBA BISSC_CTRL_CMD_START_BIT_SENT? BISSC_CTRL_CMD_NEXT_BIT?: QBBC BISSC_SEND_HIGH?, BISSC_CTRL_CMD, BISSC_CMD_BIT_PTR BISSC_SEND_LOW?: ;enable clock override for setting clock to low during timeout ZERO &SCRATCH1, 4 SET SCRATCH1, SCRATCH1, 29 M_BISSC_CLK_CONFIG CH_MASK, SCRATCH1 BISSC_SEND_HIGH?: QBNE BISSC_CTRL_NO_WAIT_FOR_ENCODER_START_BIT?, BISSC_CMD_BIT_PTR, 13 QBBC BISSC_CTRL_SB_CH1?, CH_MASK, 0 QBBS BISSC_CTRL_NO_WAIT_FOR_ENCODER_START_BIT?, BISSC_CDS_BACKUP.b0, FIFO_BIT_IDX BISSC_CTRL_SB_CH1?: QBBC BISSC_CTRL_SB_CH2?, CH_MASK, 1 QBBS BISSC_CTRL_NO_WAIT_FOR_ENCODER_START_BIT?, BISSC_CDS_BACKUP.b1, FIFO_BIT_IDX BISSC_CTRL_SB_CH2?: QBBC BISSC_SKIP_CTRL_SB?, CH_MASK, 2 QBBS BISSC_CTRL_NO_WAIT_FOR_ENCODER_START_BIT?, BISSC_CDS_BACKUP.b2, FIFO_BIT_IDX BISSC_SKIP_CTRL_SB?: ZERO &SCRATCH1, 4 SET SCRATCH1, SCRATCH1, 29 M_BISSC_CLK_CONFIG CH_MASK, SCRATCH1 QBA BISSC_CTRL_CMD_BIT_SEND_SKIP? BISSC_CTRL_NO_WAIT_FOR_ENCODER_START_BIT?: SUB BISSC_CMD_BIT_PTR, BISSC_CMD_BIT_PTR, 1 QBLE BISSC_CTRL_CMD_DATA_RCV_SKIP? , BISSC_CMD_BIT_PTR, 12 QBGT BISSC_READ_CTRL_CRC_BITS? , BISSC_CMD_BIT_PTR, 4 LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 .if $isdefed("ENABLE_MULTI_CHANNEL") LDI SCRATCH.b0, BISSC_REG_BACKUP LOOP BISSC_READ_CDS_BITS_PER_CH?, 3 LBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 .else QBBS BISSC_SKIP_FIFO_CTRL_DATA?, CH_MASK, 0 QBBC BISSC_IS_CH2_FIFO_CTRL_DATA?, CH_MASK, 1 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 8 JMP BISSC_SKIP_FIFO_CTRL_DATA? BISSC_IS_CH2_FIFO_CTRL_DATA?: ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 16 BISSC_SKIP_FIFO_CTRL_DATA?: .endif LSL BISSC_CTRL_CMD_RES, BISSC_CTRL_CMD_RES, 1 QBBS BISSC_CDS_BIT_SET?, BISSC_CDS_BACKUP, FIFO_BIT_IDX XOR EX.b0, BISSC_CTRL_FF.b3, 0 QBA BISSC_CTRL_CMD_OTF_CRC? BISSC_CDS_BIT_SET?: XOR EX.b0, BISSC_CTRL_FF.b3, 1 SET BISSC_CTRL_CMD_RES, BISSC_CTRL_CMD_RES, 0 BISSC_CTRL_CMD_OTF_CRC?: MOV BISSC_CTRL_FF.b3, BISSC_CTRL_FF.b2 MOV BISSC_CTRL_FF.b2, BISSC_CTRL_FF.b1 XOR BISSC_CTRL_FF.b1, BISSC_CTRL_FF.b0, EX.b0 MOV BISSC_CTRL_FF.b0, EX.b0 .if $isdefed("ENABLE_MULTI_CHANNEL") SBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 ADD SCRATCH.b0, SCRATCH.b0, 8 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 8 BISSC_READ_CDS_BITS_PER_CH?: .endif QBA BISSC_CTRL_CMD_BIT_SEND_SKIP? BISSC_READ_CTRL_CRC_BITS?: LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 .if $isdefed("ENABLE_MULTI_CHANNEL") LDI SCRATCH.b0, BISSC_REG_BACKUP LOOP BISSC_READ_CTRL_CRC_BITS_PER_CH?, 3 LBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 .else QBBS BISSC_SKIP_FIFO_CTRL_CRC?, CH_MASK, 0 QBBC BISSC_IS_CH2_FIFO_CTRL_CRC?, CH_MASK, 1 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 8 JMP BISSC_SKIP_FIFO_CTRL_CRC? BISSC_IS_CH2_FIFO_CTRL_CRC?: QBBC BISSC_SKIP_FIFO_CTRL_CRC?, CH_MASK, 2 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 16 BISSC_SKIP_FIFO_CTRL_CRC?: .endif LSL BISSC_CTRL_CRC, BISSC_CTRL_CRC, 1 QBBC BISSC_CDS_BIT_CLEAR?, BISSC_CDS_BACKUP, FIFO_BIT_IDX SET BISSC_CTRL_CRC, BISSC_CTRL_CRC, 0 QBA BISSC_READ_CDS_CRC_OF_NEXT_CH? BISSC_CDS_BIT_CLEAR?: CLR BISSC_CTRL_CRC, BISSC_CTRL_CRC, 0 BISSC_READ_CDS_CRC_OF_NEXT_CH?: .if $isdefed("ENABLE_MULTI_CHANNEL") SBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 ADD SCRATCH.b0, SCRATCH.b0, 8 ADD FIFO_BIT_IDX, FIFO_BIT_IDX, 8 BISSC_READ_CTRL_CRC_BITS_PER_CH?: .endif BISSC_CTRL_CMD_BIT_SEND_SKIP?: BISSC_CTRL_CMD_DATA_RCV_SKIP?: BISSC_CTRL_CMD_START_BIT_SENT?: QBEQ BISSC_CTRL_CMD_COMPLETED?, BISSC_CMD_BIT_PTR, 0 QBA BISSC_CTRL_COMMUNICATION_SKIP? BISSC_CTRL_CMD_COMPLETED?: .if $isdefed("ENABLE_MULTI_CHANNEL") LDI BASE_OFFSET, BISSC_CH0_CTRL_BASE_OFFSET LDI SCRATCH.b0, BISSC_REG_BACKUP LOOP BISSC_STORE_CTRL_RES?, 3 LBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 .else QBBC BISSC_STORE_CH1_CTRL_RES?, CH_MASK, 0 LDI BASE_OFFSET, BISSC_CH0_CTRL_BASE_OFFSET JMP BISSC_SKIP_CH2_CTRL_RES? BISSC_STORE_CH1_CTRL_RES?: QBBC BISSC_STORE_CH2_CTRL_RES?, CH_MASK, 1 LDI BASE_OFFSET, BISSC_CH1_CTRL_BASE_OFFSET JMP BISSC_SKIP_CH2_CTRL_RES? BISSC_STORE_CH2_CTRL_RES?: QBBC BISSC_SKIP_CH2_CTRL_RES?, CH_MASK, 2 LDI BASE_OFFSET, BISSC_CH2_CTRL_BASE_OFFSET BISSC_SKIP_CH2_CTRL_RES?: .endif LDI BISSC_CTRL_OTF_CRC, 0 QBBS BISSC_CTRL_CRC_BIT?, BISSC_CTRL_FF.b0, 0 SET BISSC_CTRL_OTF_CRC, BISSC_CTRL_OTF_CRC, 0 BISSC_CTRL_CRC_BIT?: QBBS BISSC_CTRL_CRC_BIT1?, BISSC_CTRL_FF.b1, 0 SET BISSC_CTRL_OTF_CRC, BISSC_CTRL_OTF_CRC, 1 BISSC_CTRL_CRC_BIT1?: QBBS BISSC_CTRL_CRC_BIT2?, BISSC_CTRL_FF.b2, 0 SET BISSC_CTRL_OTF_CRC, BISSC_CTRL_OTF_CRC, 2 BISSC_CTRL_CRC_BIT2?: QBBS BISSC_CTRL_CRC_END?, BISSC_CTRL_FF.b3, 0 SET BISSC_CTRL_OTF_CRC, BISSC_CTRL_OTF_CRC, 3 BISSC_CTRL_CRC_END?: AND BISSC_CTRL_OTF_CRC, BISSC_CTRL_OTF_CRC, 0xF AND BISSC_CTRL_CRC, BISSC_CTRL_CRC, 0xF ADD SCRATCH3.b0, BASE_OFFSET, BISSC_CTRL_CMD_RESULT_OFFSET SBCO &BISSC_CTRL_CMD_RES, PRUx_DMEM, SCRATCH3.b0, 1 ADD SCRATCH3.b0, BASE_OFFSET, BISSC_CTRL_CMD_DATA_CRC_OFFSET SBCO &BISSC_CTRL_CRC, PRUx_DMEM, SCRATCH3.b0, 1 ADD SCRATCH3.b0, BASE_OFFSET, BISSC_CTRL_CMD_OTF_CRC_OFFSET SBCO &BISSC_CTRL_OTF_CRC, PRUx_DMEM, SCRATCH3.b0, 1 QBEQ BISSC_CTRL_CRC_SUCCESS?, BISSC_CTRL_OTF_CRC, BISSC_CTRL_CRC ADD SCRATCH3.b0, BASE_OFFSET, BISSC_CTRL_CMD_CRC_ERROR_COUNT_OFFSET LBCO &SCRATCH1, PRUx_DMEM, SCRATCH3.b0, 4 ADD SCRATCH1, SCRATCH1, 1 SBCO &SCRATCH1, PRUx_DMEM, SCRATCH3.b0, 4 BISSC_CTRL_CRC_SUCCESS?: LDI BISSC_CTRL_CRC, 0 LDI BISSC_CTRL_OTF_CRC, 0 .if $isdefed("ENABLE_MULTI_CHANNEL") ZERO &BISSC_CTRL_FF, 4 SBCO &BISSC_CTRL_FF, PRUx_DMEM, SCRATCH.b0, 8 ADD SCRATCH.b0, SCRATCH.b0, 8 ADD BASE_OFFSET, BASE_OFFSET, 8 BISSC_STORE_CTRL_RES?: .endif BISSC_HOST_CMD_END: CLR BISSC_FLAGS_REG, BISSC_FLAGS_REG, 0 ;clear the flag which indicate the control communication LDI STATUS_REG1, 0 ;Clear Host Trigger .if $isdefed("ENABLE_MULTI_MAKE_RTU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CTRL_CMD_CH0_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CTRL_CMD_CH1_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CTRL_CMD_CH2_STATUS_OFFSET, 1 .else ;ch0 ctrl command offset is the base offset and only ch0 offset is going to be used in single ch or multi ch single pru SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CTRL_CMD_CH0_STATUS_OFFSET, 1 .endif BISSC_CTRL_COMMUNICATION_SKIP?: LBCO &SCRATCH2, PRUx_DMEM, BISSC_CONFIG_DELAY_40US_OFFSET, 4 ;wait here for 40(biss_timeout)) useconds LSR SCRATCH2, SCRATCH2, 1 BISSC_DELAY_LOOP1?: SUB SCRATCH2, SCRATCH2, 1 QBNE BISSC_DELAY_LOOP1?, SCRATCH2, 0 LBCO &FIFO_BIT_IDX, PRUx_DMEM, BISSC_FIFO_BIT_IDX_OFFSET, 1 BISSC_RESET_BIT?: ; wait for valid bit AND SCRATCH1.b0, R31.b3, CH_MASK QBNE BISSC_RESET_BIT?, CH_MASK, SCRATCH1.b0 MOV SCRATCH1, R31 QBBC BISSC_IS_CH1_VALID_RB?, CH_MASK, 0 SET R31, R31, BISSC_CH0_RX_VALID_BIT_OFFSET BISSC_IS_CH1_VALID_RB?: QBBC BISSC_IS_CH2_VALID_RB?, CH_MASK, 1 SET R31, R31,BISSC_CH1_RX_VALID_BIT_OFFSET BISSC_IS_CH2_VALID_RB?: QBBC BISSC_SKIP_RX_VALID_RB?, CH_MASK, 2 SET R31, R31,BISSC_CH2_RX_VALID_BIT_OFFSET BISSC_SKIP_RX_VALID_RB?: ;must maintain 3 cycles before checking next valid bit NOP NOP QBBC BISSC_IS_CH1_FIFO_RB?, CH_MASK, 0 QBBS BISSC_SKIP_RESET_BIT?, SCRATCH1.b0, FIFO_BIT_IDX BISSC_IS_CH1_FIFO_RB?: QBBC BISSC_IS_CH2_FIFO_RB?, CH_MASK, 1 QBBS BISSC_SKIP_RESET_BIT?, SCRATCH1.b1, FIFO_BIT_IDX BISSC_IS_CH2_FIFO_RB?: QBBC BISSC_RESET_BIT?, CH_MASK, 2 QBBC BISSC_RESET_BIT?, SCRATCH1.b2, FIFO_BIT_IDX BISSC_SKIP_RESET_BIT?: ;disable clock override by default ZERO &SCRATCH1, 4 M_BISSC_CLK_CONFIG CH_MASK, SCRATCH1 .if $isdefed("ENABLE_MULTI_MAKE_RTU") M_BISSC_LS_WAIT_FOR_SYNC QBBC BISSC_SKIP_GLOBAL_REINIT?, PRIMARY_CORE, 0 NOP NOP SET R31, R31, 19 ;BISSC_TX_GLOBAL_REINIT ; Set TX_EN low ; rx_en = 0 : Disable RX mode LDI R30.b3, 0 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") M_BISSC_LS_WAIT_FOR_SYNC QBBC BISSC_SKIP_GLOBAL_REINIT?, PRIMARY_CORE, 1 NOP NOP SET R31, R31, 19 ;BISSC_TX_GLOBAL_REINIT ; Set TX_EN low ; rx_en = 0 : Disable RX mode LDI R30.b3, 0 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") M_BISSC_LS_WAIT_FOR_SYNC QBBC BISSC_SKIP_GLOBAL_REINIT?, PRIMARY_CORE, 2 NOP NOP SET R31, R31, 19 ;BISSC_TX_GLOBAL_REINIT ; Set TX_EN low ; rx_en = 0 : Disable RX mode LDI R30.b3, 0 .else SET R31, R31, 19 ;BISSC_TX_GLOBAL_REINIT ; Set TX_EN low ; rx_en = 0 : Disable RX mode LDI R30.b3, 0 .endif BISSC_SKIP_GLOBAL_REINIT?: LDI STATUS_REG1, 0 ;Clear Host Trigger .if $isdefed("ENABLE_MULTI_MAKE_RTU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH0_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_PRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH1_STATUS_OFFSET, 1 .elseif $isdefed("ENABLE_MULTI_MAKE_TXPRU") SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH2_STATUS_OFFSET, 1 .else ;ch0 cycle trigger offset is the base cycle trigger offset and only ch0 offset is going to be used in single ch or multi ch single pru SBCO &STATUS_REG1, PRUx_DMEM, BISSC_CYCLE_TRIGGER_CH0_STATUS_OFFSET, 1 .endif ;Handle next Position request by user. JMP BISSC_HANDLE_HOST_TRIGGER ;never reach here HALT