summaryrefslogblamecommitdiffstats
blob: 353f38f17eda360caa206ab2a38035bd264af338 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                         







                                                                     
                                                                    



















                                                                        
                            
  

                                                                                                  
  

                                                                             

                 









                                                                 
                                                                


                                    
                                                                                 




                                                                           

                 














                                                                

          
               
          
           


                  
                     

                                                     




                                                                                                           

                            

                                                                

                                                                                   

                                                                    







                                                   





                                                         
 







                                                                                        
 



                                                                                   

                                               



                                                                    

                           
                                                                   
                           
                                                                             
                                                            
                                                                 
 


                                                                    














                                                                                 

                                           
 


                                                                    

                        

                   
 
                              

                                                                                   
                          

                                         
                                           

                                          
                             
 
                                                                         

                           

                                                                        



                                                         


                                          
 

                                         
 

                                          
 




                                   


                               









                                                                                                     

                        





                                    

                 























                                                                                  
                        
                               


                





                                                                 
                             
                               



                              
                               



                                                                            




                                 

                                                                                                        
                              








                                                                                    

                                                  
                                                                            
                                         
                                     
                                                        
                                                         
                                               
 
                                
 

                                           



                

                                                


                
                         

                                                           
                                                







                                                                                    







                                                        



                  

        












                                                                                          







                                                                             











                                                                                 

                    

                     
                                          

                           
                              


                                  



                                    
                                              
                                    
                  












                                                               

                                            
                                                                            



                                                         
                                     









                                      
                           




                    







                                    

                        





                                    



                                     

                                       

                   



                                    




                                                                     

                           

                                           
                               
                                   
                                           
                                               
 

    
                                      


                          
                             

                                                         


                                                       



                                            


                                                 

                           
                                

                    
                                             


                                        


                                                     
 
                                                   













                                                                                 
                                          

                  

                                                                       
 

                                                                 


                                                                         
 

                                                                       

                                     


                                                 



                                            
                                                                            




                                                         
                                  









                                      
                           


                               
                     


                 







                                    

                        





                                    

                 









                                                                                     
                  


                                           





                                                                     

                                              


                                                                                    



                                                               

                      

                                                             


                                                
                                                           



                  


                                                     


                          

                                              

                                                
                                               
                                 
                                                   

                                                               
                                               













                                                                                              
                                         


                                                             
                    

                                               

                                                                      

                      

                                                                        

                  
                          
                                                                 



                                                                       

                                     
                                   

                                          

                                                              

                                                    
                                                                



                                                                

                                                                       


                                              

                                                                      


                                                        
                    

                                            
                                                                            


                        





                                    

                 










                                                                                     

                 


                                           

                                                                                



                                                              
 


                                           
 


                                           
 


                                           




                                                                     

                                                  
                 

                                                                 

                    



                                                              

                      

                                                                       
 

                                                  














                                                                                 
                          

                     
                                            
 

                                
                                                                                     



                                                                 
                                                      
                                                                 


                                                                          


                                                                    


                                               

                                                                       

                                      

                                                                       

                                   


                                                                                   

                                       

                                                              

                
                             

                                      


                                                           

                                            
                                                                         

                                                                    


                                                       

                        



                                    


                                                              






                                   

                  

                             

               


                                   


                        
                                           



                                                                                 

                                                    

            


                                           

                                      
                                                                






                                        




                                                       





                                                              

                             






                                                              

                              






                                                              
                              






                                                              


           
                                                        
                                          

                                                                   
                                                               
 
                               






                                                           



                                               

                                                                       

                                   

                                                                       








                                                                                  
 
                                   
                                  
 

                                                                                     

                                            

                   

                                               

                         


                                                       
 
                               

                  







                                    
; Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
;
; 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:   firm_main.asm
;
;     brief:  SORTE master protocol: contains the initialization routine and SORTE state machine.
;                                   
;
;    Version        Description                                Author
;     0.1         Created                                      Thomas Leyrer

;include section
    .include "../include/macros/macros.inc"
    .include "../include/macros/utils.inc"
    .include "../include/macros/sorte_macros.inc"
    .include "../include/macros/MACdef.inc"
    .include "../include/icss/icss_defines.inc"
    .include "../include/icss/icss_regs.inc"
    .include "../include/icss/icss_miirt_macros.inc"
    .include "../include/protocol/sorte_pru_master_register.inc"
    .include "../include/protocol/sorte_master_cfg.inc"
    .include "../include/protocol/sorte_packet_definition.inc"
	.include "../include/protocol/sorte_host_interface.inc"
    .include "firmware_version.inc"

; defines, set and asg section
; use PRU0 as SORTE master serving Port 0 receive and transmit. PRU1 is not used


; in order to ONLY send a 4 byte preamable, comment out the following line
; otherwise 8 byte preamble will be sent with every frame.
FULL_PREAMBLE     .set     1

; trace settings
trace_cmp0_left        .set 1

; Enable LED pattern generation
application_io          .set 1

;CCS/makefile specific settings
    .retain     ; Required for building .out with assembly file
    .retainrefs ; Required for building .out with assembly file

    .global    firm_main
    .global FN_STATE_MACHINE
    .global FN_EVENT_HANDLER
    .global FN_DISC_RCV
    .global IDLE_WAIT_FOR_LINK_ACTIVE
    .sect    ".text:firm_main"

;********
;* FIRM MAIN *
;********
firm_main:
; PRU init
; clear R0 to R30

    zero    &R0, 124

; configure defaults in SORTE configuration register
; options list: enable(bit 0); offline engineering;no trace; retrain on single crc error and timing error;
; no extra diag packet; no error test
;   ldi        TEMP_REG_1, 0x51
    ldi   TEMP_REG_1, 0x01
    sbco  &TEMP_REG_1, PRU0_DMEM_CONST, CTRL_REG_OFFSET , 1

; init status register to 0
    zero    &TEMP_REG_1,4
    sbco    &TEMP_REG_1, PRU0_DMEM_CONST, CTRL_REG_OFFSET+4 , 4

; init control parmaeter: set error counts for retrain to 3, no extra diags packet
      ldi32    TEMP_REG_1, 0x00000303
        sbco    &TEMP_REG_1, PRU0_DMEM_CONST, CTRL_REG_OFFSET+8 , 4

; set MII_RT mode for R30/R31 interface
;bit 1-0 PRU0_GPI_MODE R/W 0h PRU GPI (R31) modes:
;0h = Direct input mode. (default)
;1h = 16bit parallel capture mode.
;2h = 28bit shift in mode.
;3h = MII_RT mode

        ldi    TEMP_REG_1, 0x03
    .if $defined(PRU0)
    sbco    &TEMP_REG_1,ICSS_CFG_CONST,ICSS_CFG_GPCFG0,1
    .else
    sbco    &TEMP_REG_1,ICSS_CFG_CONST,ICSS_CFG_GPCFG1,1
    .endif

; set min frame count to 6 bytes (2 PREAMBLE(PE) + 4 payload bytes) in RXFRMS0 register
; memcpy(MII_RT_CFG_CONST+ 0x40, &TEMP_REG_1, 1);
    ldi    TEMP_REG_1, 0x06
    sbco     &TEMP_REG_1, MII_RT_CFG_CONST, ICSS_MIIRT_RXFRMS0, 1
    
; disable Port 1
    ldi    TEMP_REG_1, 0
    sbco     &TEMP_REG_1, MII_RT_CFG_CONST, ICSS_MIIRT_TXCFG1, 1

; set MII_RT into host send (HS) and host receive (HR) on same PRU; e.g. EMAC mode
; macro is PRU specific, i.e. each PRU can use this macro indepenently
    M_SET_MIIRT_HR
    M_SET_MIIRT_HS

; init the IEP timer, disable CMP0 wrap-around
    zero    &TEMP_REG_1, 4
    sbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 4
    lbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 4
    sbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 4

; starting with idle state
; test if there is an active link on the port using mdio interface
IDLE_WAIT_FOR_LINK_ACTIVE:
    lbco    &TEMP_REG_2.b0, ICSS_SHARED_RAM_CONST, MDIO_PHY_CONFIG_OFFSET, 1
    lbco    &TEMP_REG_1, ICSS_MDIO_CONST, ICSS_MDIO_LINK, 4
    qbbc    IDLE_WAIT_FOR_LINK_ACTIVE, TEMP_REG_1, TEMP_REG_2.b0

; check if enabled, enabling done at startup of pru firmware.
       lbco    &TEMP_REG_1.b0, PRU0_DMEM_CONST, CTRL_REG_OFFSET , 1
        qbbc    IDLE_WAIT_FOR_LINK_ACTIVE,TEMP_REG_1.b0, 0

; ------------------------------------------------------------------------------
; state: DISCOVERY
; Regsiter defines:
; n = TEMP_REG_4.b0 (iterations)
; m = TEMP_REG_4.b1 (counter for 32 bytes blocks in payload field)
; previous cycle counter = TEMP_REG_3
; tx_fifo_bytes_inserted = TEMP_REG_4.w2
; rx_bytes_received = TEMP_REG_6.w0
; rx_packet_cnt = TEMP_REG_6.b2
; rx_blocks_rcvd = TEMP_REG_6.b3
; ------------------------------------------------------------------------------
STATE_DISCOVERY:

; set state register
; init status register to DISCOVERY state
       M_SET_STATE S_DISCOV, TEMP_REG_1.b1

; Reset mode back to host send mode
; could occur if jumping back to DISCOVERY state from another state
    M_SET_MIIRT_HS

; reset rx and tx fifos
    M_RESET_RXFIFO
    M_RESET_TXFIFO

; R30.w2 is the mask register
; set R30 mask to take data from R30.w0 (TX path - PRU)
; all FFFF in mask takes the data from PRU, all 0000 take the data from RX_L1 fifo
    ldi    R30.w2, 0xFFFF

; set const to control PRU cycle counter
        ldi32     r27, ICSS_PRU0_CNTL_BASE

; set iteration count for DISCOVERY state
    ldi     TEMP_REG_4.b0, 0

; Entry point where master starts sending out DISCOVERY frame every 1 ms
STATE_DISCOVERY_ITERATION:

; reset RX- and TX-FIFO and clear TX errors via the command interface
    ldi    R31.w2, (D_RESET_RXFIFO | D_RX_ERROR_CLEAR | D_RESET_TXFIFO)

; start 1 ms timer using PRU cycle counter
; disable cycle counter to clear it
; bit 3 is cycle counter enable, need to keep PRU enable
        ldi    TEMP_REG_1.w0, 0x0b03
        sbbo    &TEMP_REG_1.b0, r27, 0, 1
        zero    &TEMP_REG_2, 4

; clear PRU cycle counter
        sbbo    &TEMP_REG_2, r27, 0x0c,4

; enable PRU cycle counter
        sbbo    &TEMP_REG_1.b1, r27, 0, 1

; clear previous PRU cycle counter
    zero    &TEMP_REG_3, 4
; clear bytes received register
    zero    &TEMP_REG_6, 2
    zero    &TEMP_REG_6.b3, 1

; send DISCOVERY packet header

; send 8 byte PA for wireshark capture
; in order to not send 8 byte PA, please comment out line which defines FULL_PREAMBLE at top of file
    .if $defined(FULL_PREAMBLE)
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    .endif

; send 4 byte pre-amble
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0xd555
    NOP
    M_PUSH_WORD

; 4 bytes header
    ldi32     TEMP_REG_1,DISC_HEADER
    ;ldi32    TX_DATA_WORD, DISC_HEADER
    ;M_PUSH_WORD
    mov        TX_DATA_BYTE, TEMP_REG_1.b0
    NOP
    M_PUSH_BYTE
    mov        TX_DATA_BYTE, TEMP_REG_1.b1
    NOP
    M_PUSH_BYTE
    ; jump to STATE_DISCOV_NOT_LAST is the discovery frame count is not 9;
    ; if it is 9, then set bit 3 of status register prior to sending
    ; out the next discovery frame which will transition the slave device
    ; to the next state. 
    qbne    STATE_DISCOV_NOT_LAST, TEMP_REG_4.b0, 9
    
    ldi    TEMP_REG_1.b3, 0x08
STATE_DISCOV_NOT_LAST:
    mov        TX_DATA_WORD, TEMP_REG_1.w2
    NOP
    M_PUSH_WORD
; start sending the payload
; initialize  2 byte count to zero, this will get incremented by each slave upon 
; receiving discovery frame; in general need 2 cycles between pushed to TX_FIFO.
; 
; 2 bytes: cnt (16 bit)
    ldi        TX_DATA_WORD, 0
    NOP
    M_PUSH_WORD

; need to check is slave is expecting to update READ_BYTE_OFFSET
; 2 bytes: READ_BYTE_OFFSET
;  ldi        TX_DATA_WORD, 0
;  NOP
;  M_PUSH_WORD

; 2 bytes: INPUT_BYTES_COUNT
    ldi        TX_DATA_WORD, 0
    NOP
    M_PUSH_WORD

; 2 bytes: OUTPUT_BYTES_COUNT
    ldi        TX_DATA_WORD, 0
    NOP
    M_PUSH_WORD

;   set number bytes inserted to TX_FIFO (8 PA + 4 H + 4 DISC H = 16 bytes)
    .if $defined(FULL_PREAMBLE)
    ldi        TEMP_REG_4.w2, 16
    .else
    ldi        TEMP_REG_4.w2, 14
    .endif

; set counter for DISCOVERY payload blocks (254 slaves * 4 bytes = 1016 bytes = 31 *32 bytes + 24 bytes
    ldi     TEMP_REG_4.b1, 31

; send 254 * 4 bytes = 1016 bytes = 31 *32 bytes + 24 bytes
; for i =0; i<254*4; i+=32 // send to TX fifo in blocks of 32 bytes

DISC_BLOCK_REPEAT:

; check TX_FIFO_LEVEL; start of frame time ~0
; TX_FIFO_LEVEL = bytes inserted - bytes sent on wire (delta t in 5 ns cycles / 16)
; if TX_FIFO_LEVEL <32  (32 bytes = 2.56 us = 512 PRU cycles
    lbbo     &PRU_CC_REG, r27, 0x0c , 4
    sub        TEMP_REG_1, PRU_CC_REG, TEMP_REG_3
; convert time difference which is in 5 ns into # of bytes 5ns * 16 = 80 ns
    lsr     TEMP_REG_1.w0, TEMP_REG_1, 4
; subtract sent bytes - time elapsed
    sub     TEMP_REG_1.w0, TEMP_REG_4.w2, TEMP_REG_1.w0
; if more than 32 bytes are available send next 32 bytes
    qblt     DISC_SKIP_SEND, TEMP_REG_1.w0, 32

    loop     DISC_PL_REPEAT, 16

;    ldi        TX_DATA_WORD, 0x0000
    mov        TX_DATA_WORD, TEMP_REG_4.w2
    NOP
    M_PUSH_WORD
DISC_PL_REPEAT:

    add        TEMP_REG_4.w2, TEMP_REG_4.w2, 32
    sub        TEMP_REG_4.b1, TEMP_REG_4.b1, 1

DISC_SKIP_SEND:

    CALL     FN_DISC_RCV

; check if more than 32 byte blocks need to be transfered.
    qblt    DISC_BLOCK_REPEAT, TEMP_REG_4.b1, 0

; insert last  24 bytes

; check TX_FIFO_LEVEL; start of frame time ~0
; TX_FIFO_LEVEL = bytes inserted - bytes sent on wire (delta t in 5 ns cycles / 16)
; if TX_FIFO_LEVEL <32  (32 bytes = 2.56 us = 512 PRU cycles

DISC_WAIT_LAST_BLOCK:
    lbbo     &PRU_CC_REG, r27, 0x0c , 4
    sub        TEMP_REG_1, PRU_CC_REG, TEMP_REG_3
    lsr     TEMP_REG_1.w0, TEMP_REG_1, 4
    sub     TEMP_REG_1.w0, TEMP_REG_4.w2, TEMP_REG_1.w0
    qblt     DISC_WAIT_LAST_BLOCK, TEMP_REG_1.w0, 24

    loop     DISC_LAST_REPEAT, 12
    ldi        TX_DATA_WORD, 0xbeef
    NOP
    M_PUSH_WORD
DISC_LAST_REPEAT:

    NOP
    NOP
; end packet with crc generated by PRU
    M_CMD16 D_PUSH_CRC_MSWORD_CMD | D_PUSH_CRC_LSWORD_CMD | D_TX_EOF
    nop


; check on receive
; on receive store packet in ICCS memory

; was this last interation? If not send another DISC after 1 ms (0x30d40) / 10ms (0x4E20)
DISC_WAIT_ITERATION:
    qbgt    DISC_WAIT_SKIP_RX, TEMP_REG_4.b0, TEMP_REG_6.b2
    CALL    FN_DISC_RCV
DISC_WAIT_SKIP_RX:
    ldi32    TEMP_REG_1, 0x0030d40
    lbbo     &PRU_CC_REG, r27, 0x0c , 4
    qblt    DISC_WAIT_ITERATION, TEMP_REG_1, PRU_CC_REG
    ; increment discovery frame send count by 1
    add    TEMP_REG_4.b0, TEMP_REG_4.b0, 1
    ; check to see if 10 discovery frames sent, if not, then
    ; continue to send  discovery frame. otherwise transition to PARAM state
    qbne    STATE_DISCOVERY_ITERATION, TEMP_REG_4.b0, 10

; ------------------------------------------------------------------------------
; state: PARAM
; Regsiter defines:
; n = TEMP_REG_4.b0 (iterations)
; m = TEMP_REG_4.b1 (counter for 32 bytes blocks in payload field)
; previous cycle counter = TEMP_REG_3
; ------------------------------------------------------------------------------

STATE_PARAM:

; stay in same host send mode as DISCOVERY state
;    M_SET_MIIRT_HS
;    M_SET_MIIRT_HR

; set protocol state
       M_SET_STATE S_PARAM, TEMP_REG_1.b1

; set number of iterations
    ldi     TEMP_REG_4.b0, 10

STATE_PARAM_ITERATION:
; setup PARAM packet using struct
    ldi       PARAM_P.da, 0xff
    ldi        PARAM_P.sa, 0
    ldi        PARAM_P.type, 0x02
    ldi        PARAM_P.status, 0x10
    qbne    STATE_PARAM_CONT,TEMP_REG_4.b0, 1
    ldi        PARAM_P.status, 0x18
STATE_PARAM_CONT:
    ldi32    PARAM_P.cycle_time,     CYCLE_TIME_10us
    ldi32    PARAM_P.sync_cycle,     SYNC_CYCLE_NONE
    ldi        PARAM_P.delay_period,     DELAY_PERIOD_1s
    ldi     PARAM_P.delay_burst,     DELAY_BURST_CNT_16
    ldi     PARAM_P.delay_gap,         DELAY_GAP_TIME_1ms
    ldi        PARAM_P.delay_fwd_time,    DELAY_FWD_TIME_320ns
    ldi        PARAM_P.ipg,            IPG_260ns
    ldi        PARAM_P.t_in,            T_IN_0
    ldi        PARAM_P.t_out,            T_OUT_0
    ldi        PARAM_P.topology,        TOPOLOGY_NORMAL
    ldi        PARAM_P.diagnostics,    DIAGS_MODE_PAYLOAD
    ldi        PARAM_P.alarm,            ALARM_MODE_NO
    ldi        PARAM_P.crc_mode,        CRC8 | (CRC8<<4)

; reset RX- and TX-FIFO and clear TX errors
    ldi        R31.w2, (D_RESET_RXFIFO | D_RX_ERROR_CLEAR | D_RESET_TXFIFO)

; start 1 ms timer using PRU cycle counter
; disable cycle counter to clear it
; bit 3 is cycle counter enable, need to keep PRU enable
    ldi        TEMP_REG_1.w0, 0x0b03
    sbbo    &TEMP_REG_1.b0, r27, 0, 1
    zero    &TEMP_REG_2, 4

; clear cycle counter
    sbbo    &TEMP_REG_2, r27, 0x0c,4

; enable cycle counter
    sbbo    &TEMP_REG_1.b1, r27, 0, 1

; clear previous cycle counter
    zero    &TEMP_REG_3, 4

; send PARAM packet

; pre-amble
; send 8 byte PA
    .if FULL_PREAMBLE
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    .endif

; send 4 byte pre-amble
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0xd555
    NOP
    M_PUSH_WORD

; set parameter for send loop
; R1.b0 points to start of structure
; R1.b1 used as loop counter
    ldi        R1.b1, $sizeof(PARAM_P)
    ldi        R1.b0, &R2.b0

;send PARAM packet
    loop    STATE_PARAM_SEND, R1.b1
    mvib    TX_DATA_BYTE, *R1.b0++
    M_PUSH_BYTE
    nop
STATE_PARAM_SEND:

; end packet with crc generated by PRU
    M_CMD16 D_PUSH_CRC_MSWORD_CMD | D_PUSH_CRC_LSWORD_CMD | D_TX_EOF

    ldi        R2.w0, 0
    ldi        R2.w2, 1000
; receive packet and check if all accepted
STATE_PARAM_WAIT_BANK0:
    add        R2.w0, R2.w0, 1
    xin        RXL2_BANK0, &R18, 1
    qbeq    STATE_PARAM_WAIT, R2.w0, R2.w2
    qbgt    STATE_PARAM_WAIT_BANK0, r18.b0, 32

   

    xin        RXL2_BANK0, &r2, 32+16

; received packet has PA?
; find start offset
    ldi        R1.b0, &R2.b0
STATE_PARAM_PA_SEARCH:
; check on error: r1.b0 >8 (R2 offset) + 8 (max PA size)
    qblt    STATE_PARAM_PA_CONT, r1.b0, 16
    mvib    TEMP_REG_1.b1, *R1.b0++
    qbne    STATE_PARAM_PA_SEARCH, TEMP_REG_1.b1, 0xD5
STATE_PARAM_PA_CONT:

; check on status byte ok
; add 3 bytes offset to get to status field
    add        R1.b0, R1.b0, 3
    mvib    TEMP_REG_1.b1, *R1.b0
    qbbs    STATE_PARAM_RCV_OK, TEMP_REG_1.b1, 0

;   not all slave accepted
;    qba        STATE_DISCOVERY
STATE_PARAM_RCV_OK:

    sub        TEMP_REG_4.b0,TEMP_REG_4.b0,1
;  todo: read and verify rest of packet
;  wait for end of 1 ms period
STATE_PARAM_WAIT:
    ldi32    TEMP_REG_1, 0x0030d40 - 18
    lbbo     &PRU_CC_REG, r27, 0x0c , 4
    qblt    STATE_PARAM_WAIT, TEMP_REG_1, PRU_CC_REG

    qbne    STATE_PARAM_ITERATION,TEMP_REG_4.b0, 0


; ------------------------------------------------------------------------------
; state: DELAY_MASTER
; Regsiter defines:
; n = TEMP_REG_4.w0 (iterations)
;
; min delay = TEMP_REG_6.w0
; max delay = TEMP_REG_6.w2
; avg delay = TEMP_REG_5.w2
;
; ------------------------------------------------------------------------------

; set protocol state
       M_SET_STATE S_LINED, TEMP_REG_1.b1

; reset iep timer
    ldi     TEMP_REG_1.b0, CNT_DISABLE
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_GLOBAL_CFG_REG, 1

    ldi32   TEMP_REG_1, 0
    sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG, 4
    .if $isdefed("ICSS_REV2")
        sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG + 4, 4
    .endif

    ldi     TEMP_REG_1.b0, 0x51
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_GLOBAL_CFG_REG, 1

; init min, max and avg delay values
    ldi32    TEMP_REG_6,0x00007fff
    ldi        TEMP_REG_5.w2, 0
    ldi        TEMP_REG_4.w0, DELAY_BURST_CNT_16

STATE_DELAYM:

; reset RX- and TX-FIFO and clear RX errors
    ldi        R31.w2, (D_RESET_RXFIFO | D_RX_ERROR_CLEAR | D_RESET_TXFIFO)

; reset cycle counter
; start 1 ms timer using PRU cycle counter
; disable cycle counter to clear it
; bit 3 is cycle counter enable, need to keep PRU enable
    ldi     TEMP_REG_1.w0, 0x0b03
    sbbo    &TEMP_REG_1.b0, r27, 0, 1
    zero    &TEMP_REG_2, 4

; clear cycle counter
    sbbo    &TEMP_REG_2, r27, 0x0c,4

; enable cycle counter
    sbbo    &TEMP_REG_1.b1, r27, 0, 1

; clear previous cycle counter
    zero    &TEMP_REG_3, 4

; send DELAY_REQ packet
; start with delay master mode
    M_SET_DELAY_M_P0

; pre-amble
; send 8 byte PA
    .if FULL_PREAMBLE
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    .endif

; send 4 byte pre-amble
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0xd555
    NOP
    M_PUSH_WORD

; 4 bytes header
    ldi32     TEMP_REG_1,DELAY_REQ_P
    mov        TX_DATA_BYTE, TEMP_REG_1.b0
    NOP
    M_PUSH_BYTE
    mov        TX_DATA_BYTE, TEMP_REG_1.b1
    NOP
    M_PUSH_BYTE
    ;qbne    STATE_DELAY_LAST, TEMP_REG_4.b0, (DELAY_BURST_CNT_16-1)
    qbne    STATE_DELAY_LAST, TEMP_REG_4.b0, 1    ; the frame counter runs down to 0
    ldi        TEMP_REG_1.b3, 0x08
STATE_DELAY_LAST:
    mov        TX_DATA_WORD, TEMP_REG_1.w2
    NOP
    M_PUSH_WORD

; send packet with crc generated by PRU
    M_CMD16 D_PUSH_CRC_MSWORD_CMD | D_PUSH_CRC_LSWORD_CMD | D_TX_EOF

; receive DELAY_RESP packet
STATE_DELAY_WAIT_BANK0:
    xin        RXL2_BANK0, &R18, 1
    qbgt    STATE_DELAY_WAIT_BANK0, r18.b0, 4

; read rx and tx time stamp - sof based
; read all time stamp register in one step r2 maps to cap0 (RX_SOF), r6 maps to cap
    lbco    &r2,ICSS_IEP_CONST, ICSS_IEP_CAPR0_REG, 6*4
    sub        TEMP_REG_1,r2,r6
    qbgt    STATE_DELAY_SKIP_MIN, TEMP_REG_6.w0, TEMP_REG_1.w0
    mov        TEMP_REG_6.w0, TEMP_REG_1.w0

STATE_DELAY_SKIP_MIN:
    qblt    STATE_DELAY_SKIP_MAX,TEMP_REG_6.w2,TEMP_REG_1.w0
    mov        TEMP_REG_6.w2, TEMP_REG_1.w0

STATE_DELAY_SKIP_MAX:
; calculate average, divide by count at the end
    add        TEMP_REG_5.w2, TEMP_REG_5.w2, TEMP_REG_1.w0

; wait gap (1ms)

STATE_DELAY_WAIT:
    ldi32    TEMP_REG_1, 0x0030d40
    lbbo     &PRU_CC_REG, r27, 0x0c , 4
    qblt    STATE_DELAY_WAIT, TEMP_REG_1, PRU_CC_REG

; repeat burst (16 times)

    sub        TEMP_REG_4.w0,TEMP_REG_4.w0, 1
    qbne    STATE_DELAYM,TEMP_REG_4.w0, 0

; shift right by 4 works for DELAY_BURST_CNT_16
    lsr        TEMP_REG_5.w2, TEMP_REG_5.w2, 4
; subtract bridge delay = 320 ns
    ldi        TEMP_REG_1.w0, DELAY_FWD_TIME_320ns
    sub     TEMP_REG_5.w2, TEMP_REG_5.w2, TEMP_REG_1.w0
; shift right by one to divide by 2 for line delay measurement
    lsr        TEMP_REG_5.w2, TEMP_REG_5.w2, 1

; ------------------------------------------------------------------------------
; state: SYNC
;
; Regsiter defines:
; n = TEMP_REG_4.w0 (iterations)
; period = TEMP_REG_3 (continous sync compare value used in cmp3)
; previous cycle counter = TEMP_REG_3
; ------------------------------------------------------------------------------

; send 1024 sync packets every 10 us using iep timer and cmp3 time of 500 ns for first packet
; sub-sequent packets have 10.0 us period

; set protocol state
       M_SET_STATE S_SYNC, TEMP_REG_1.b1


; set time triggered send mode where PRU0 uses cmp3 register
    M_SET_MIIRT_TTS

; disable IEP counter, keep cnt increment to 5
    ldi       TEMP_REG_1, 0x50
    sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_GLOBAL_CFG_REG, 1

; clear global status
    ldi       TEMP_REG_1, 0x1
    sbco      &TEMP_REG_1, ICSS_IEP_CONST,ICSS_IEP_GLOBAL_STATUS_REG, 1

; reset IEP timer
    ldi32   TEMP_REG_1, 0
    sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG, 4
    
    .if $isdefed("ICSS_REV2")
        sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG+4, 4
    .endif

; set iteration to 1024 sync packets
    ldi        TEMP_REG_4.w0, 1024

; set 500 ns offset for first sync packet
    ldi32    TEMP_REG_3, 500
    sbco    &TEMP_REG_3, ICSS_IEP_CONST, ICSS_IEP_CMP3_REG, 4

; load the IEP CMP CFG register and enable the cmp3
    lbco   &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 4
    set    TEMP_REG_1, TEMP_REG_1, 4
    sbco   &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 4

; clear cmp3 register
    ldi        TEMP_REG_1.b0, 0x08
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1


; enable IEP counter, keep cnt increment to 5
    ldi       TEMP_REG_1, 0x51
    sbco      &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_GLOBAL_CFG_REG, 1

STATE_SYNC_ITERATION:
; need to enable tx fifo for every packet in TX_EN_MODE
    M_SET_MIIRT_TTS

; reset RX- and TX-FIFO and clear RX errors
    ldi        R31.w2, (D_RESET_RXFIFO | D_RX_ERROR_CLEAR | D_RESET_TXFIFO)


; send 4 byte pre-amble
    ldi        TX_DATA_WORD, 0x5555
    NOP
    M_PUSH_WORD
    ldi        TX_DATA_WORD, 0xd555
    NOP
    M_PUSH_WORD

; 4 bytes header
    ldi32     TEMP_REG_1, SYNC_P
    mov        TX_DATA_BYTE, TEMP_REG_1.b0
    NOP
    M_PUSH_BYTE
    mov        TX_DATA_BYTE, TEMP_REG_1.b1
    NOP
    M_PUSH_BYTE
    ldi        TEMP_REG_2.w0, 1023
    ;qbne    STATE_SYNC_LAST, TEMP_REG_4.w0, TEMP_REG_2.w0
    qbne    STATE_SYNC_LAST, TEMP_REG_4.w0, 1    ; frame counter counts down to zero
    ldi        TEMP_REG_1.b3, 0x08

STATE_SYNC_LAST:
    mov        TX_DATA_WORD, TEMP_REG_1.w2
    NOP
    M_PUSH_WORD

; insert time stamp of outgoing packet which is cmp3+ld+3.5 bytes of PA (280ns)
    lbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP3_REG, 4
    add        TEMP_REG_1, TEMP_REG_1, TEMP_REG_5.w2
    add        TEMP_REG_1, TEMP_REG_1, 100
    add        TEMP_REG_1, TEMP_REG_1, 180

    mov        TX_DATA_WORD, TEMP_REG_1.w0
    NOP
    M_PUSH_WORD

    mov        TX_DATA_WORD, TEMP_REG_1.w2
    NOP
    M_PUSH_WORD

    mov        TX_DATA_WORD, TEMP_REG_5.w2
    NOP
    M_PUSH_WORD

; end packet with crc generated by PRU
    M_CMD16 D_PUSH_CRC_MSWORD_CMD | D_PUSH_CRC_LSWORD_CMD | D_TX_EOF

; wait ~5 us after packet was sent
    ldi        TEMP_REG_2, 5000
    add        TEMP_REG_1, TEMP_REG_1, TEMP_REG_2
STATE_SYNC_WAIT:
    lbco      &TEMP_REG_2, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG, 4
    qblt    STATE_SYNC_WAIT, TEMP_REG_1,TEMP_REG_2

; add 10 us to cmp3
    ldi        TEMP_REG_1, 10000
    add        TEMP_REG_3, TEMP_REG_3, TEMP_REG_1
    sbco    &TEMP_REG_3, ICSS_IEP_CONST, ICSS_IEP_CMP3_REG, 4
    sbco    &TEMP_REG_3, ICSS_IEP_CONST, ICSS_IEP_CMP0_REG, 4

; clear cmp3 register
    ldi        TEMP_REG_1.b0, 0x08
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1

    sub        TEMP_REG_4.w0,TEMP_REG_4.w0, 1
    qbne    STATE_SYNC_ITERATION,TEMP_REG_4.w0, 0
; ------------------------------------------------------------------------------
; state: IO Exchange
; Regsiter defines:
; n = TEMP_REG_4.b0 (iterations)
; m = TEMP_REG_4.b1 (counter for 32 bytes blocks in payload field)
; previous cycle counter = TEMP_REG_3
; IO_CYCLE_CNT = cycle counter which start from 0, overlapps with PRU_CC
; ------------------------------------------------------------------------------
STATE_IOEXHANGE:
; start IO cycle count to 0
; IO cycle count is used for sample application
; 32 ms = 4 us * 8192 (2^13)
; 64 ms = 4 us * 16384 (2^14)
; 128 ms = 4us * 32768 (2^15)
; 256 ms = 4us * 65536 (2^16)
    ldi   IO_CYCLE_CNT, 0

; set protocol state
    M_SET_STATE S_IOEXCHANGE, TEMP_REG_1.b1

; set SYNC0 pulse width to 2 us
    ldi     TEMP_REG_1.w0, 400
    ldi     TEMP_REG_1.w2, (ICSS_IEP_SYNC_BLK_INDEX << 8) + ICSS_IEP_SYNC_PWIDTH_REG
    sbco    &TEMP_REG_1.w0, ICSS_IEP_CONST, TEMP_REG_1.w2, 2
    ldi32   TEMP_REG_1, 2000           ; SYNC0 should output
    sbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP1_REG, 4
    lbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 4
    set     TEMP_REG_1, TEMP_REG_1, 1<<(1+1) ; CMP[1]
    sbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 4

; set CMP0 wrap around mode
; load the IEP CMP CFG register and enable the cmp0 with wrap around mode
    lbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 1
    or      TEMP_REG_1.b0, TEMP_REG_1.b0, 0x07
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_CFG_REG, 1

; wait for CMP0 hit and loop back to new cycle
STATE_IO_WAIT0:
    lbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1
    qbbc    STATE_IO_WAIT0,TEMP_REG_1.b0,0

;    clear cmp0, cmp1 and cmp3 events
    ldi     TEMP_REG_1.b0, 0x0b
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1

; set IEP CMP0 wrap around to 4 us
; enhancement: Should read from configuration register instead of hard-coded value
    ldi32   TEMP_REG_1, 4000-5
    sbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_CMP0_REG, 4

; set 500 ns offset for the out packet
    ldi32   TEMP_REG_3, 500
    sbco    &TEMP_REG_3, ICSS_IEP_CONST, ICSS_IEP_CMP3_REG, 4

; debug pointer
    ldi     TEMP_REG_6.w0, 0

; send master out packet after 500 ns
; infininte loop for packet transmition with slave devices
; will exit loop on error condition ie link status down
STATE_IOEX_LOOP:
    M_SET_MIIRT_TTS
; reset RX- and TX-FIFO and clear TX errors
    ldi     R31.w2, (D_RESET_RXFIFO | D_RX_ERROR_CLEAR | D_RESET_TXFIFO)

; load 16 byte payload from PRU data memory, 4 bytes for each slave
    ldi     TEMP_REG_1.w0, OUT_DATA_OFFSET
    lbco    &r2.b2, PRU0_DMEM_CONST, TEMP_REG_1.w0, 16
    ldi     r2.w0, 0x3000

; send 1 byte pre-amble
    ;ldi        TX_DATA_BYTE, 0x5d
    ldi        TX_DATA_WORD, 0xd555
    NOP
    M_PUSH_WORD

; 2 bytes header SA = 0 and Sataus = IO Exchange master state
; use r2 for header to support crc calculation
    ldi     r2.w0, 0x3000
    mov        TX_DATA_BYTE, r2.b0
    NOP
    M_PUSH_BYTE
    mov        TX_DATA_BYTE, r2.b1
    NOP
    M_PUSH_BYTE

; send data field
    ldi        R1.b1, 16
    ldi        R1.b0, &R2.b2

;send out data
    loop    STATE_IO_SEND, R1.b1
    mvib    TX_DATA_BYTE, *R1.b0++
    M_PUSH_BYTE
STATE_IO_SEND:

; timing critical code:
;    packet went out at 500ns of new cycle
;   19 bytes are already in TX Fifo which takes 19 x 80 ns = 1520 ns
;   crc calculation over 18 bytes takes 650 ns. It is save to put the code here.

; calculate crc8 over 2 byte header and 16 data bytes - takes 35 ns per byte!
    ldi        TEMP_REG_3.b0, 0
    CRC8_CALC  TEMP_REG_3.b0, r2.b0, 18, TEMP_REG_4

; send crc8
    mov        TX_DATA_BYTE, TEMP_REG_3.b0
    NOP
    M_PUSH_BYTE

;  add actual tx time stamp to packet
    lbco    &TX_DATA_WORD,ICSS_IEP_CONST, ICSS_IEP_CAPR4_REG, 2
    M_PUSH_WORD

; send packet with crc8 inserted by PRU
   M_CMD16 D_TX_EOF


   .if $defined("application_io")
; now is time to generate new output data
; running LEDs for slave 1..4 with 2^n rate difference
; takes 31 cycles = 155 ns

; slave 1 = 32 ms runnig LED
    lsr     TEMP_REG_1, IO_CYCLE_CNT, 13
    and     TEMP_REG_1.b0,TEMP_REG_1, 0x07
    ldi     TEMP_REG_1.b1, 1
    lsl     TEMP_REG_1.b0, TEMP_REG_1.b1, TEMP_REG_1.b0
    ldi     TEMP_REG_2.w0, OUT_DATA_OFFSET
    sbco    &TEMP_REG_1.b0, PRU0_DMEM_CONST, TEMP_REG_2.w0, 1

; slave 2 = 64 ms runnig LED
    lsr     TEMP_REG_1, IO_CYCLE_CNT, 14
    and     TEMP_REG_1.b0,TEMP_REG_1, 0x07
    ldi     TEMP_REG_1.b1, 1
    lsl     TEMP_REG_1.b0, TEMP_REG_1.b1, TEMP_REG_1.b0
    ldi     TEMP_REG_2.w0, OUT_DATA_OFFSET
    add     TEMP_REG_2.w0, TEMP_REG_2.w0, 4
    sbco    &TEMP_REG_1.b0, PRU0_DMEM_CONST, TEMP_REG_2.w0, 1

; slave 3 = 128 ms runnig LED
    lsr     TEMP_REG_1, IO_CYCLE_CNT, 15
    and     TEMP_REG_1.b0,TEMP_REG_1, 0x07
    ldi     TEMP_REG_1.b1, 1
    lsl     TEMP_REG_1.b0, TEMP_REG_1.b1, TEMP_REG_1.b0
    ldi     TEMP_REG_2.w0, OUT_DATA_OFFSET
    add     TEMP_REG_2.w0, TEMP_REG_2.w0, 8
    sbco    &TEMP_REG_1.b0, PRU0_DMEM_CONST, TEMP_REG_2.w0, 1
; slave 4 = 256 ms runnig LED
    lsr     TEMP_REG_1, IO_CYCLE_CNT, 16
    and     TEMP_REG_1.b0,TEMP_REG_1, 0x07
    ldi     TEMP_REG_1.b1, 1
    lsl     TEMP_REG_1.b0, TEMP_REG_1.b1, TEMP_REG_1.b0
    ldi     TEMP_REG_2.w0, OUT_DATA_OFFSET
    add     TEMP_REG_2.w0, TEMP_REG_2.w0, 12
    sbco    &TEMP_REG_1.b0, PRU0_DMEM_CONST, TEMP_REG_2.w0, 1

    .endif

; increment cycle count and store to interface register
    add     IO_CYCLE_CNT, IO_CYCLE_CNT, 1
    sbco    &IO_CYCLE_CNT, PRU0_DMEM_CONST, CYCLE_CNT_P0_OFFSET, 4
    sbco    &R22,PRU0_DMEM_CONST, 0x60, 32
    lbco    &TEMP_REG_1, ICSS_IEP_CONST, ICSS_IEP_COUNT_REG, 4

; debug (write pulse settings)
    .if $defined("trace_cmp0_left")
    ldi     TEMP_REG_2.w0, OUT_DATA_OFFSET
    sbco    &TEMP_REG_1, PRU1_DMEM_CONST, TEMP_REG_6.w0, 4
    add     TEMP_REG_6.w0,TEMP_REG_6.w0, 4
    ldi     r2, 2048
    QBGT    STATE_IO_WAIT, TEMP_REG_6.w0, r2
    ldi     TEMP_REG_6.w0, 0
    .endif

; wait for CMP0 hit and loop back to new cycle
STATE_IO_WAIT:
    lbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1
    qbbc    STATE_IO_WAIT,TEMP_REG_1.b0,0

; clear cmp0, cmp1 and cmp3 events
    ldi        TEMP_REG_1.b0, 0x0b
    sbco    &TEMP_REG_1.b0, ICSS_IEP_CONST, ICSS_IEP_CMP_STATUS_REG, 1

; re-enable SYNC0
; clear and set sync_en bit in IEP timer to re-enable trigger
    ldi    TEMP_REG_1, 0x06    ; clear sync_en (sync0_en, sync1_en)
    ldi    TEMP_REG_2.w0, (ICSS_IEP_SYNC_BLK_INDEX << 8) + ICSS_IEP_SYNC_CTRL_REG
    sbco   &TEMP_REG_1, ICSS_IEP_CONST, TEMP_REG_2.w0, 4
    ldi    TEMP_REG_1, 0x07    ;  set sync_en (sync0_en, sync1_en)
    sbco   &TEMP_REG_1, ICSS_IEP_CONST, TEMP_REG_2.w0, 4


; read and store input from slaves
    xin    RXL2_BANK0, &R18.b0, 1

; check on missing packet, bit 6 and 7 define retrain mode if packet is not received
    lbco    &r2, PRU0_DMEM_CONST, CTRL_REG_OFFSET , 1
    and     r2.b0, r2.b0, 0xc0
    qbeq    STATE_IOEX_SKIP_RETRAIN,r2.b0,0

; restart protocol
    qbne    STATE_IOEX_SKIP_RETRAIN, r18.b0, 0
    jmp     IDLE_WAIT_FOR_LINK_ACTIVE

STATE_IOEX_SKIP_RETRAIN:
    xin     RXL2_BANK0, &r2, 32
    ldi     TEMP_REG_2.w0, IN_DATA_OFFSET
    sbco    &r2.b0, PRU0_DMEM_CONST, TEMP_REG_2.w0, 32

    qba        STATE_IOEX_LOOP

firmware_version:
    .if $defined(PRU0)
    .word 0x00        ; PRU0
    .else
    .word 0x01        ; PRU1
    .endif

    .word   ICSS_FIRMWARE_RELEASE_1
    .word   ICSS_FIRMWARE_RELEASE_2