Compare commits
	
		
			2 commits
		
	
	
		
			8d1b69d304
			...
			ae9b468be7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ae9b468be7 | |||
| 16ca573610 | 
					 6 changed files with 892 additions and 0 deletions
				
			
		
							
								
								
									
										302
									
								
								RP2040_I2C_Registers.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								RP2040_I2C_Registers.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,302 @@
 | 
				
			||||||
 | 
					I2C_OFFSET = {
 | 
				
			||||||
 | 
					    "I2C_IC_CON":            0x00000000,
 | 
				
			||||||
 | 
					    "I2C_IC_TAR":            0x00000004,
 | 
				
			||||||
 | 
					    "I2C_IC_SAR":            0x00000008,
 | 
				
			||||||
 | 
					    "I2C_IC_DATA_CMD":       0x00000010,
 | 
				
			||||||
 | 
					    "I2C_IC_SS_SCL_HCNT":    0x00000014,
 | 
				
			||||||
 | 
					    "I2C_IC_SS_SCL_LCNT":    0x00000018,
 | 
				
			||||||
 | 
					    "I2C_IC_FS_SCL_HCNT":    0x0000001c,
 | 
				
			||||||
 | 
					    "I2C_IC_FS_SCL_LCNT":    0x00000020,
 | 
				
			||||||
 | 
					    "I2C_IC_INTR_STAT":      0x0000002c,
 | 
				
			||||||
 | 
					    "I2C_IC_INTR_MASK":      0x00000030,
 | 
				
			||||||
 | 
					    "I2C_IC_RAW_INTR_STAT":  0x00000034,
 | 
				
			||||||
 | 
					    "I2C_IC_RX_TL":          0x00000038,
 | 
				
			||||||
 | 
					    "I2C_IC_TX_TL":          0x0000003c,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_INTR":       0x00000040,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_RX_UNDER":   0x00000044,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_RX_OVER":    0x00000048,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_TX_OVER":    0x0000004c,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_RD_REQ":     0x00000050,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_TX_ABRT":    0x00000054,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_RX_DONE":    0x00000058,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_ACTIVITY":   0x0000005c,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_STOP_DET":   0x00000060,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_START_DET":  0x00000064,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_GEN_CALL":   0x00000068,
 | 
				
			||||||
 | 
					    "I2C_IC_ENABLE":         0x0000006c,
 | 
				
			||||||
 | 
					    "I2C_IC_STATUS":         0x00000070,
 | 
				
			||||||
 | 
					    "I2C_IC_TXFLR":          0x00000074,
 | 
				
			||||||
 | 
					    "I2C_IC_RXFLR":          0x00000078,
 | 
				
			||||||
 | 
					    "I2C_IC_SDA_HOLD":       0x0000007c,
 | 
				
			||||||
 | 
					    "I2C_IC_TX_ABRT_SOURCE": 0x00000080,
 | 
				
			||||||
 | 
					    "I2C_IC_SLV_DATA_NACK_ONLY": 0x00000084,
 | 
				
			||||||
 | 
					    "I2C_IC_DMA_CR":             0x00000088,
 | 
				
			||||||
 | 
					    "I2C_IC_DMA_TDLR":           0x0000008c,
 | 
				
			||||||
 | 
					    "I2C_IC_DMA_RDLR":           0x00000090,
 | 
				
			||||||
 | 
					    "I2C_IC_SDA_SETUP":          0x00000094,
 | 
				
			||||||
 | 
					    "I2C_IC_ACK_GENERAL_CALL":   0x00000098,
 | 
				
			||||||
 | 
					    "I2C_IC_ENABLE_STATUS":      0x0000009c,
 | 
				
			||||||
 | 
					    "I2C_IC_FS_SPKLEN":          0x000000a0,
 | 
				
			||||||
 | 
					    "I2C_IC_CLR_RESTART_DET":    0x000000a8,
 | 
				
			||||||
 | 
					    "I2C_IC_COMP_PARAM_1":       0x000000f4,
 | 
				
			||||||
 | 
					    "I2C_IC_COMP_VERSION":       0x000000f8,
 | 
				
			||||||
 | 
					    "I2C_IC_COMP_TYPE":          0x000000fc,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CON = {
 | 
				
			||||||
 | 
					    0x00000400: "STOP_DET_IF_MASTER_ACTIVE",    # Master issues the STOP_DET interrupt irrespective of whether...
 | 
				
			||||||
 | 
					    0x00000200: "RX_FIFO_FULL_HLD_CTRL",        # This bit controls whether DW_apb_i2c should hold the bus when the Rx...
 | 
				
			||||||
 | 
					    0x00000100: "TX_EMPTY_CTRL",                # This bit controls the generation of the TX_EMPTY interrupt, as described in...
 | 
				
			||||||
 | 
					    0x00000080: "STOP_DET_IFADDRESSED",         # In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is...
 | 
				
			||||||
 | 
					    0x00000040: "IC_SLAVE_DISABLE",             # This bit controls whether I2C has its slave disabled, which means once...
 | 
				
			||||||
 | 
					    0x00000020: "IC_RESTART_EN",                # Determines whether RESTART conditions may be sent when acting as a master.
 | 
				
			||||||
 | 
					    0x00000010: "IC_10BITADDR_MASTER",          # Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit...
 | 
				
			||||||
 | 
					    0x00000008: "IC_10BITADDR_SLAVE",           # When acting as a slave, this bit controls whether the DW_apb_i2c...
 | 
				
			||||||
 | 
					    0x00000006: "SPEED",                        # These bits control at which speed the DW_apb_i2c operates; its setting is relevant...
 | 
				
			||||||
 | 
					    0x00000001: "MASTER_MODE",                  # This bit controls whether the DW_apb_i2c master is enabled.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_TAR = {
 | 
				
			||||||
 | 
					    0x00000800: "SPECIAL",                      # This bit indicates whether software performs a Device-ID or General Call or START...
 | 
				
			||||||
 | 
					    0x00000400: "GC_OR_START",                  # If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this...
 | 
				
			||||||
 | 
					    0x000003FF: "IC_TAR",                       # This is the target address for any master transaction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SAR = {
 | 
				
			||||||
 | 
					    0x000003FF: "IC_SAR",                       # The IC_SAR holds the slave address when the I2C is operating as a slave
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_DATA_CMD = {
 | 
				
			||||||
 | 
					    0x00000800: "FIRST_DATA_BYTE",              # Indicates the first data byte received after the address phase for receive...
 | 
				
			||||||
 | 
					    0x00000400: "RESTART",                      # This bit controls whether a RESTART is issued before the byte is sent or received
 | 
				
			||||||
 | 
					    0x00000200: "STOP",                         # This bit controls whether a STOP is issued after the byte is sent or received
 | 
				
			||||||
 | 
					    0x00000100: "CMD",                          # This bit controls whether a read or a write is performed
 | 
				
			||||||
 | 
					    0x000000FF: "DAT",                          # This register contains the data to be transmitted or received on the I2C bus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SS_SCL_HCNT = {
 | 
				
			||||||
 | 
					    0x0000FFFF: "IC_SS_SCL_HCNT",               # This register must be set before any I2C bus transaction can take place...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SS_SCL_LCNT = {
 | 
				
			||||||
 | 
					    0x0000FFFF: "IC_SS_SCL_LCNT",               # This register must be set before any I2C bus transaction can take place...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_FS_SCL_HCNT = {
 | 
				
			||||||
 | 
					    0x0000FFFF: "IC_FS_SCL_HCNT",               # This register must be set before any I2C bus transaction can take place...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_FS_SCL_LCNT = {
 | 
				
			||||||
 | 
					    0x0000FFFF: "IC_FS_SCL_LCNT",               # This register must be set before any I2C bus transaction can take place...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_INTR_STAT = {
 | 
				
			||||||
 | 
					    0x00001000: "R_RESTART_DET",                # See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit
 | 
				
			||||||
 | 
					    0x00000800: "R_GEN_CALL",                   # See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit
 | 
				
			||||||
 | 
					    0x00000400: "R_START_DET",                  # See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit
 | 
				
			||||||
 | 
					    0x00000200: "R_STOP_DET",                   # See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit
 | 
				
			||||||
 | 
					    0x00000100: "R_ACTIVITY",                   # See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit
 | 
				
			||||||
 | 
					    0x00000080: "R_RX_DONE",                    # See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit
 | 
				
			||||||
 | 
					    0x00000040: "R_TX_ABRT",                    # See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit
 | 
				
			||||||
 | 
					    0x00000020: "R_RD_REQ",                     # See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit
 | 
				
			||||||
 | 
					    0x00000010: "R_TX_EMPTY",                   # See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit
 | 
				
			||||||
 | 
					    0x00000008: "R_TX_OVER",                    # See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit
 | 
				
			||||||
 | 
					    0x00000004: "R_RX_FULL",                    # See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit
 | 
				
			||||||
 | 
					    0x00000002: "R_RX_OVER",                    # See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit
 | 
				
			||||||
 | 
					    0x00000001: "R_RX_UNDER",                   # See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_INTR_MASK = {
 | 
				
			||||||
 | 
					    0x00001000: "M_RESTART_DET",                # This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000800: "M_GEN_CALL",                   # This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000400: "M_START_DET",                  # This bit masks the R_START_DET interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000200: "M_STOP_DET",                   # This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000100: "M_ACTIVITY",                   # This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000080: "M_RX_DONE",                    # This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000040: "M_TX_ABRT",                    # This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000020: "M_RD_REQ",                     # This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000010: "M_TX_EMPTY",                   # This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000008: "M_TX_OVER",                    # This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000004: "M_RX_FULL",                    # This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000002: "M_RX_OVER",                    # This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					    0x00000001: "M_RX_UNDER",                   # This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_RAW_INTR_STAT = {
 | 
				
			||||||
 | 
					    0x00001000: "RESTART_DET",                  # Indicates whether a RESTART condition has occurred on the I2C interface when...
 | 
				
			||||||
 | 
					    0x00000800: "GEN_CALL",                     # Set only when a General Call address is received and it is acknowledged
 | 
				
			||||||
 | 
					    0x00000400: "START_DET",                    # Indicates whether a START or RESTART condition has occurred on the I2C interface...
 | 
				
			||||||
 | 
					    0x00000200: "STOP_DET",                     # Indicates whether a STOP condition has occurred on the I2C interface regardless...
 | 
				
			||||||
 | 
					    0x00000100: "ACTIVITY",                     # This bit captures DW_apb_i2c activity and stays set until it is cleared
 | 
				
			||||||
 | 
					    0x00000080: "RX_DONE",                      # When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the...
 | 
				
			||||||
 | 
					    0x00000040: "TX_ABRT",                      # This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the...
 | 
				
			||||||
 | 
					    0x00000020: "RD_REQ",                       # This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is...
 | 
				
			||||||
 | 
					    0x00000010: "TX_EMPTY",                     # The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL...
 | 
				
			||||||
 | 
					    0x00000008: "TX_OVER",                      # Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the...
 | 
				
			||||||
 | 
					    0x00000004: "RX_FULL",                      # Set when the receive buffer reaches or goes above the RX_TL threshold in the...
 | 
				
			||||||
 | 
					    0x00000002: "RX_OVER",                      # Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an...
 | 
				
			||||||
 | 
					    0x00000001: "RX_UNDER",                     # Set if the processor attempts to read the receive buffer when it is empty by...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_RX_TL = {
 | 
				
			||||||
 | 
					    0x000000FF: "RX_TL",                        # Receive FIFO Threshold Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_TX_TL = {
 | 
				
			||||||
 | 
					    0x000000FF: "TX_TL",                        # Transmit FIFO Threshold Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_INTR = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_INTR",                     # Read this register to clear the combined interrupt, all individual interrupts,...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_RX_UNDER = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_RX_UNDER",                 # Read this register to clear the RX_UNDER interrupt (bit 0) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_RX_OVER = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_RX_OVER",                  # Read this register to clear the RX_OVER interrupt (bit 1) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_TX_OVER = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_TX_OVER",                  # Read this register to clear the TX_OVER interrupt (bit 3) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_RD_REQ = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_RD_REQ",                   # Read this register to clear the RD_REQ interrupt (bit 5) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_TX_ABRT = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_TX_ABRT",                  # Read this register to clear the TX_ABRT interrupt (bit 6) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_RX_DONE = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_RX_DONE",                  # Read this register to clear the RX_DONE interrupt (bit 7) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_ACTIVITY = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_ACTIVITY",                 # Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_STOP_DET = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_STOP_DET",                 # Read this register to clear the STOP_DET interrupt (bit 9) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_START_DET = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_START_DET",                # Read this register to clear the START_DET interrupt (bit 10) of the...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_GEN_CALL = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_GEN_CALL",                 # Read this register to clear the GEN_CALL interrupt (bit 11) of...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_ENABLE = {
 | 
				
			||||||
 | 
					    0x00000004: "TX_CMD_BLOCK",                 # In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx...
 | 
				
			||||||
 | 
					    0x00000002: "ABORT",                        # When set, the controller initiates the transfer abort
 | 
				
			||||||
 | 
					    0x00000001: "ENABLE",                       # Controls whether the DW_apb_i2c is enabled
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_STATUS = {
 | 
				
			||||||
 | 
					    0x00000040: "SLV_ACTIVITY",                 # Slave FSM Activity Status
 | 
				
			||||||
 | 
					    0x00000020: "MST_ACTIVITY",                 # Master FSM Activity Status
 | 
				
			||||||
 | 
					    0x00000010: "RFF",                          # Receive FIFO Completely Full
 | 
				
			||||||
 | 
					    0x00000008: "RFNE",                         # Receive FIFO Not Empty
 | 
				
			||||||
 | 
					    0x00000004: "TFE",                          # Transmit FIFO Completely Empty
 | 
				
			||||||
 | 
					    0x00000002: "TFNF",                         # Transmit FIFO Not Full
 | 
				
			||||||
 | 
					    0x00000001: "ACTIVITY",                     # I2C Activity Status
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_TXFLR = {
 | 
				
			||||||
 | 
					    0x0000001F: "TXFLR",                        # Transmit FIFO Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_RXFLR = {
 | 
				
			||||||
 | 
					    0x0000001F: "RXFLR",                        # Receive FIFO Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SDA_HOLD = {
 | 
				
			||||||
 | 
					    0x00FF0000: "IC_SDA_RX_HOLD",               # Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c...
 | 
				
			||||||
 | 
					    0x0000FFFF: "IC_SDA_TX_HOLD",               # Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_TX_ABRT_SOURCE = {
 | 
				
			||||||
 | 
					    0xFF800000: "TX_FLUSH_CNT",                 # This field indicates the number of Tx FIFO Data Commands which are flushed...
 | 
				
			||||||
 | 
					    0x00010000: "ABRT_USER_ABRT",               # This is a master-mode-only bit
 | 
				
			||||||
 | 
					    0x00008000: "ABRT_SLVRD_INTX",              # 1: When the processor side responds to a slave mode request for data to be...
 | 
				
			||||||
 | 
					    0x00004000: "ABRT_SLV_ARBLOST",             # This field indicates that a Slave has lost the bus while transmitting...
 | 
				
			||||||
 | 
					    0x00002000: "ABRT_SLVFLUSH_TXFIFO",         # This field specifies that the Slave has received a read command and...
 | 
				
			||||||
 | 
					    0x00001000: "ARB_LOST",                     # This field specifies that the Master has lost arbitration, or if...
 | 
				
			||||||
 | 
					    0x00000800: "ABRT_MASTER_DIS",              # This field indicates that the User tries to initiate a Master operation...
 | 
				
			||||||
 | 
					    0x00000400: "ABRT_10B_RD_NORSTRT",          # This field indicates that the restart is disabled (IC_RESTART_EN bit...
 | 
				
			||||||
 | 
					    0x00000200: "ABRT_SBYTE_NORSTRT",           # To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed...
 | 
				
			||||||
 | 
					    0x00000100: "ABRT_HS_NORSTRT",              # This field indicates that the restart is disabled (IC_RESTART_EN bit...
 | 
				
			||||||
 | 
					    0x00000080: "ABRT_SBYTE_ACKDET",            # This field indicates that the Master has sent a START Byte and the START...
 | 
				
			||||||
 | 
					    0x00000040: "ABRT_HS_ACKDET",               # This field indicates that the Master is in High Speed mode and the High...
 | 
				
			||||||
 | 
					    0x00000020: "ABRT_GCALL_READ",              # This field indicates that DW_apb_i2c in the master mode has sent a General...
 | 
				
			||||||
 | 
					    0x00000010: "ABRT_GCALL_NOACK",             # This field indicates that DW_apb_i2c in master mode has sent a General...
 | 
				
			||||||
 | 
					    0x00000008: "ABRT_TXDATA_NOACK",            # This field indicates the master-mode only bit
 | 
				
			||||||
 | 
					    0x00000004: "ABRT_10ADDR2_NOACK",           # This field indicates that the Master is in 10-bit address mode and that...
 | 
				
			||||||
 | 
					    0x00000002: "ABRT_10ADDR1_NOACK",           # This field indicates that the Master is in 10-bit address mode and the...
 | 
				
			||||||
 | 
					    0x00000001: "ABRT_7B_ADDR_NOACK",           # This field indicates that the Master is in 7-bit addressing mode and...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SLV_DATA_NACK_ONLY = {
 | 
				
			||||||
 | 
					    0x00000001: "NACK",                         # Generate NACK
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_DMA_CR = {
 | 
				
			||||||
 | 
					    0x00000002: "TDMAE",                        # Transmit DMA Enable
 | 
				
			||||||
 | 
					    0x00000001: "RDMAE",                        # Receive DMA Enable
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_DMA_TDLR = {
 | 
				
			||||||
 | 
					    0x0000000F: "DMATDL",                       # Transmit Data Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_DMA_RDLR = {
 | 
				
			||||||
 | 
					    0x0000000F: "DMARDL",                       # Receive Data Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_SDA_SETUP = {
 | 
				
			||||||
 | 
					    0x000000FF: "SDA_SETUP",                    # SDA Setup
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_ACK_GENERAL_CALL = {
 | 
				
			||||||
 | 
					    0x00000001: "ACK_GEN_CALL",                 # ACK General Call
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_ENABLE_STATUS = {
 | 
				
			||||||
 | 
					    0x00000004: "SLV_RX_DATA_LOST",             # Slave Received Data Lost
 | 
				
			||||||
 | 
					    0x00000002: "SLV_DISABLED_WHILE_BUSY",      # Slave Disabled While Busy (Transmit, Receive)
 | 
				
			||||||
 | 
					    0x00000001: "IC_EN",                        # ic_en Status
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_FS_SPKLEN = {
 | 
				
			||||||
 | 
					    0x000000FF: "IC_FS_SPKLEN",                 # I2C SS, FS or FM+ spike suppression limit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_CLR_RESTART_DET = {
 | 
				
			||||||
 | 
					    0x00000001: "CLR_RESTART_DET",              # Clear RESTART_DET Interrupt Register
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_COMP_PARAM_1 = {
 | 
				
			||||||
 | 
					    0x00FF0000: "TX_BUFFER_DEPTH",              # TX Buffer Depth = 16
 | 
				
			||||||
 | 
					    0x0000FF00: "RX_BUFFER_DEPTH",              # RX Buffer Depth = 16
 | 
				
			||||||
 | 
					    0x00000080: "ADD_ENCODED_PARAMS",           # Encoded parameters not visible
 | 
				
			||||||
 | 
					    0x00000040: "HAS_DMA",                      # DMA handshaking signals are enabled
 | 
				
			||||||
 | 
					    0x00000020: "INTR_IO",                      # COMBINED Interrupt outputs
 | 
				
			||||||
 | 
					    0x00000010: "HC_COUNT_VALUES",              # Programmable count values for each mode
 | 
				
			||||||
 | 
					    0x0000000C: "MAX_SPEED_MODE",               # MAX SPEED MODE = FAST MODE
 | 
				
			||||||
 | 
					    0x00000003: "APB_DATA_WIDTH",               # APB data bus width is 32 bits
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_COMP_VERSION = {
 | 
				
			||||||
 | 
					    0xFFFFFFFF: "IC_COMP_VERSION",              # IC_COMP_VERSION = 0x3230312a
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I2C_IC_COMP_TYPE = {
 | 
				
			||||||
 | 
					    0xFFFFFFFF: "IC_COMP_TYPE",                 # IC_COMP_TYPE = 0x44570140 (Designware Component Type number = 0x44_57_01_40)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										306
									
								
								RP2040_Slave.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								RP2040_Slave.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,306 @@
 | 
				
			||||||
 | 
					### i2cSlave.py
 | 
				
			||||||
 | 
					from machine import mem32
 | 
				
			||||||
 | 
					from RP2040_I2C_Registers import*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class i2c_slave:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    RP2040 I2C Slave implementation using direct register access.
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    This class implements an I2C slave interface for the RP2040 microcontroller,
 | 
				
			||||||
 | 
					    allowing it to receive and transmit data as an I2C peripheral device.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    I2C0_BASE = 0x40044000
 | 
				
			||||||
 | 
					    I2C1_BASE = 0x40048000
 | 
				
			||||||
 | 
					    IO_BANK0_BASE = 0x40014000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Atomic Register Access 
 | 
				
			||||||
 | 
					    mem_rw = 0x0000     # Normal read/write access
 | 
				
			||||||
 | 
					    mem_xor = 0x1000    # XOR on write
 | 
				
			||||||
 | 
					    mem_set = 0x2000    # Bitmask set on write
 | 
				
			||||||
 | 
					    mem_clr = 0x3000    # Bitmask clear on write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_Bits_Mask(self, bits, register):
 | 
				
			||||||
 | 
					        """ This function return the bit mask based on bit name """
 | 
				
			||||||
 | 
					        bits_to_clear = bits
 | 
				
			||||||
 | 
					        bit_mask = sum([key for key, value in register.items() if value in bits_to_clear])
 | 
				
			||||||
 | 
					        return bit_mask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def RP2040_Write_32b_i2c_Reg(self, register, data, atr=0):
 | 
				
			||||||
 | 
					        """ Write RP2040 I2C 32bits register """
 | 
				
			||||||
 | 
					        # < Base Addr > | < Atomic Register Access > | < Register > 
 | 
				
			||||||
 | 
					        mem32[self.i2c_base | atr | register] = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def RP2040_Set_32b_i2c_Reg(self, register, data):
 | 
				
			||||||
 | 
					        """ Set bits in RP2040 I2C 32bits register """
 | 
				
			||||||
 | 
					        # < Base Addr > | 0x2000 | < Register > 
 | 
				
			||||||
 | 
					        self.RP2040_Write_32b_i2c_Reg(register, data, atr=self.mem_set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def RP2040_Clear_32b_i2c_Reg(self, register, data):
 | 
				
			||||||
 | 
					        """ Clear bits in RP2040 I2C 32bits register """
 | 
				
			||||||
 | 
					        # < Base Addr > | 0x3000 | < Register > 
 | 
				
			||||||
 | 
					        self.RP2040_Write_32b_i2c_Reg(register, data, atr=self.mem_clr)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def RP2040_Read_32b_i2c_Reg(self, offset):
 | 
				
			||||||
 | 
					        """ Read RP2040 I2C 32bits register """
 | 
				
			||||||
 | 
					        return mem32[self.i2c_base | offset]
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def RP2040_Get_32b_i2c_Bits(self, offset, bit_mask):
 | 
				
			||||||
 | 
					        return mem32[self.i2c_base | offset] & bit_mask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, i2cID=0, sda=0, scl=1, slaveAddress=0x41, enable_clock_stretch=True):
 | 
				
			||||||
 | 
					        self.scl = scl
 | 
				
			||||||
 | 
					        self.sda = sda
 | 
				
			||||||
 | 
					        self.slaveAddress = slaveAddress
 | 
				
			||||||
 | 
					        self.i2c_ID = i2cID
 | 
				
			||||||
 | 
					        if self.i2c_ID == 0:
 | 
				
			||||||
 | 
					            self.i2c_base = self.I2C0_BASE
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.i2c_base = self.I2C1_BASE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					          I2C Slave Mode Intructions
 | 
				
			||||||
 | 
					          https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 1. Disable the DW_apb_i2c by writing a ‘0’ to IC_ENABLE.ENABLE
 | 
				
			||||||
 | 
					        self.RP2040_Clear_32b_i2c_Reg(I2C_OFFSET["I2C_IC_ENABLE"], 
 | 
				
			||||||
 | 
					                                  self.get_Bits_Mask("ENABLE", I2C_IC_ENABLE))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 2. Write to the IC_SAR register (bits 9:0) to set the slave address. 
 | 
				
			||||||
 | 
					        # This is the address to which the DW_apb_i2c responds.
 | 
				
			||||||
 | 
					        self.RP2040_Clear_32b_i2c_Reg(I2C_OFFSET["I2C_IC_SAR"], 
 | 
				
			||||||
 | 
					                                  self.get_Bits_Mask("IC_SAR", I2C_IC_SAR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.RP2040_Set_32b_i2c_Reg(I2C_OFFSET["I2C_IC_SAR"], 
 | 
				
			||||||
 | 
					                                self.slaveAddress & self.get_Bits_Mask("IC_SAR", I2C_IC_SAR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 3. Write to the IC_CON register to specify which type of addressing is supported (7-bit or 10-bit by setting bit 3).
 | 
				
			||||||
 | 
					        # Enable the DW_apb_i2c in slave-only mode by writing a ‘0’ into bit six (IC_SLAVE_DISABLE) and a ‘0’ to bit zero 
 | 
				
			||||||
 | 
					        # (MASTER_MODE).
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Disable Master mode
 | 
				
			||||||
 | 
					        self.RP2040_Clear_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CON"], 
 | 
				
			||||||
 | 
					                                      self.get_Bits_Mask("MASTER_MODE", I2C_IC_CON))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Enable slave mode 
 | 
				
			||||||
 | 
					        self.RP2040_Clear_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CON"], 
 | 
				
			||||||
 | 
					                                      self.get_Bits_Mask("IC_SLAVE_DISABLE", I2C_IC_CON))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Enable clock strech 
 | 
				
			||||||
 | 
					        if enable_clock_stretch:
 | 
				
			||||||
 | 
					            self.RP2040_Set_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CON"], 
 | 
				
			||||||
 | 
					                                      self.get_Bits_Mask("RX_FIFO_FULL_HLD_CTRL", I2C_IC_CON))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 4. Enable the DW_apb_i2c by writing a ‘1’ to IC_ENABLE.ENABLE.
 | 
				
			||||||
 | 
					        self.RP2040_Set_32b_i2c_Reg(I2C_OFFSET["I2C_IC_ENABLE"], 
 | 
				
			||||||
 | 
					                                self.get_Bits_Mask("IC_ENABLE", I2C_IC_ENABLE))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Reset GPIO0 function 
 | 
				
			||||||
 | 
					        mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.sda) ] = 0x1f
 | 
				
			||||||
 | 
					        # Set GPIO0 as IC0_SDA function 
 | 
				
			||||||
 | 
					        mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.sda) ] = 0x03
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Reset GPIO1 function
 | 
				
			||||||
 | 
					        mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.scl) ] = 0x1f
 | 
				
			||||||
 | 
					        # Set GPIO1 as IC0_SCL function 
 | 
				
			||||||
 | 
					        mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.scl) ] = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class I2CStateMachine:
 | 
				
			||||||
 | 
					        I2C_RECEIVE = 0
 | 
				
			||||||
 | 
					        I2C_REQUEST = 1
 | 
				
			||||||
 | 
					        I2C_FINISH  = 2
 | 
				
			||||||
 | 
					        I2C_START   = 3
 | 
				
			||||||
 | 
					        I2C_IDLE    = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					    class I2CTransaction:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def __init__(self, address: int, data_byte: list):
 | 
				
			||||||
 | 
					            self.address = address  
 | 
				
			||||||
 | 
					            self.data_byte = data_byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def handle_event(self):
 | 
				
			||||||
 | 
					        """Optimized event detection by reading interrupt status register once"""
 | 
				
			||||||
 | 
					        # Read entire interrupt status register in one operation
 | 
				
			||||||
 | 
					        intr_stat = self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_INTR_STAT"])
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Check for restart condition
 | 
				
			||||||
 | 
					        if intr_stat & self.get_Bits_Mask("R_RESTART_DET", I2C_IC_INTR_STAT):
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_RESTART_DET"])
 | 
				
			||||||
 | 
					            # Handle restart logic here
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        # Check other conditions using the same intr_stat value
 | 
				
			||||||
 | 
					        # I2C Master has abort the transactions
 | 
				
			||||||
 | 
					        if (intr_stat & self.get_Bits_Mask("R_TX_ABRT", I2C_IC_INTR_STAT)):
 | 
				
			||||||
 | 
					            # Clear int
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_TX_ABRT"])
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_FINISH
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Last byte transmitted by I2C Slave but NACK from I2C Master 
 | 
				
			||||||
 | 
					        if (intr_stat & self.get_Bits_Mask("R_RX_DONE", I2C_IC_INTR_STAT)):
 | 
				
			||||||
 | 
					            # Clear int
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_RX_DONE"])
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_FINISH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Start condition detected by I2C Slave
 | 
				
			||||||
 | 
					        if (intr_stat & self.get_Bits_Mask("R_START_DET", I2C_IC_INTR_STAT)):
 | 
				
			||||||
 | 
					            # Clear start detection 
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_START_DET"])
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_START
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Stop condition detected by I2C Slave
 | 
				
			||||||
 | 
					        if (intr_stat & self.get_Bits_Mask("R_STOP_DET", I2C_IC_INTR_STAT)):
 | 
				
			||||||
 | 
					            # Clear stop detection
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_STOP_DET"])
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_FINISH
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Check if RX FIFO is not empty
 | 
				
			||||||
 | 
					        if (self.RP2040_Get_32b_i2c_Bits(I2C_OFFSET["I2C_IC_STATUS"],
 | 
				
			||||||
 | 
					                                 self.get_Bits_Mask("RFNE", I2C_IC_STATUS))):
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_RECEIVE
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Check if Master is requesting data 
 | 
				
			||||||
 | 
					        if (intr_stat & self.get_Bits_Mask("R_RD_REQ", I2C_IC_INTR_STAT)):
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            # Shall Wait until transfer is done, timing recommended 10 * fastest SCL clock period
 | 
				
			||||||
 | 
					            # for 100 Khz = (1/100E3) * 10 = 100 uS
 | 
				
			||||||
 | 
					            # for 400 Khz = (1/400E3) * 10 = 25 uS
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            return i2c_slave.I2CStateMachine.I2C_REQUEST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Add at the end
 | 
				
			||||||
 | 
					        return i2c_slave.I2CStateMachine.I2C_IDLE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_Master_Req_Read(self):
 | 
				
			||||||
 | 
					        """ Return status if I2C Master is requesting a read sequence """
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Check RD_REQ Interrupt bit (master wants to read data from the slave)
 | 
				
			||||||
 | 
					        status = self.RP2040_Get_32b_i2c_Bits(I2C_OFFSET["I2C_IC_RAW_INTR_STAT"],
 | 
				
			||||||
 | 
					                                 self.get_Bits_Mask("RD_REQ", I2C_IC_RAW_INTR_STAT))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if status :
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def is_Master_Req_Seq_Write(self):
 | 
				
			||||||
 | 
					        # Return true if I2C Master is requesting a sequential data writing 
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					        # Check whether is FIRST_DATA_BYTE bit is active in IC_DATA_CMD. 
 | 
				
			||||||
 | 
					        first_data_byte_stat = self.RP2040_Get_32b_i2c_Bits(I2C_OFFSET["I2C_IC_DATA_CMD"],
 | 
				
			||||||
 | 
					                                 self.get_Bits_Mask("FIRST_DATA_BYTE", I2C_IC_DATA_CMD))
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        # Check whether is STOP_DET_IFADDRESSED bit is active in IC_CON.
 | 
				
			||||||
 | 
					        stop_stat = self.RP2040_Get_32b_i2c_Bits(I2C_OFFSET["I2C_IC_CON"],
 | 
				
			||||||
 | 
					                                 self.get_Bits_Mask("STOP_DET_IFADDRESSED", I2C_IC_CON))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (stop_stat):
 | 
				
			||||||
 | 
					            # Clear stop bit int 
 | 
				
			||||||
 | 
					            self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_STOP_DET"])
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Master sequential write true if FIRST_DATA_BYTE bit is active and no stop condition detected. 
 | 
				
			||||||
 | 
					        if first_data_byte_stat and not(stop_stat):
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def Slave_Write_Data(self, data):
 | 
				
			||||||
 | 
					        """ Write 8bits of data at destination of I2C Master """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        # Send data
 | 
				
			||||||
 | 
					        self.RP2040_Write_32b_i2c_Reg(I2C_OFFSET["I2C_IC_DATA_CMD"], data & 
 | 
				
			||||||
 | 
					                                  self.get_Bits_Mask("DAT", I2C_IC_DATA_CMD))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_CLR_RD_REQ"]) 
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def Available(self):
 | 
				
			||||||
 | 
					        """ Return true if data has been received from I2C Master """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Get RFNE Bit (Receive FIFO Not Empty)
 | 
				
			||||||
 | 
					        return self.RP2040_Get_32b_i2c_Bits(I2C_OFFSET["I2C_IC_STATUS"],
 | 
				
			||||||
 | 
					                                self.get_Bits_Mask("RFNE", I2C_IC_STATUS))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def Read_Data_Received(self):
 | 
				
			||||||
 | 
					        """ Return data from I2C Master """
 | 
				
			||||||
 | 
					              
 | 
				
			||||||
 | 
					        return self.RP2040_Read_32b_i2c_Reg(I2C_OFFSET["I2C_IC_DATA_CMD"]) &  self.get_Bits_Mask("DAT", I2C_IC_DATA_CMD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deinit(self):
 | 
				
			||||||
 | 
					        """Disable the I2C slave and release pins"""
 | 
				
			||||||
 | 
					        # Disable I2C interface
 | 
				
			||||||
 | 
					        self.RP2040_Clear_32b_i2c_Reg(I2C_OFFSET["I2C_IC_ENABLE"], 
 | 
				
			||||||
 | 
					                              self.get_Bits_Mask("ENABLE", I2C_IC_ENABLE))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Reset GPIO pins back to default state
 | 
				
			||||||
 | 
					        mem32[self.IO_BANK0_BASE | self.mem_clr | (4 + 8 * self.sda)] = 0x1f
 | 
				
			||||||
 | 
					        mem32[self.IO_BANK0_BASE | self.mem_clr | (4 + 8 * self.scl)] = 0x1f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    import machine
 | 
				
			||||||
 | 
					    from machine import mem32
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    def main():
 | 
				
			||||||
 | 
					        data_buf = []
 | 
				
			||||||
 | 
					        addr = 0x00
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Create I2C slave instance
 | 
				
			||||||
 | 
					        s_i2c = i2c_slave(0, sda=0, scl=1, slaveAddress=0x41, enable_clock_stretch=True)
 | 
				
			||||||
 | 
					        state = i2c_slave.I2CStateMachine.I2C_IDLE
 | 
				
			||||||
 | 
					        currentTransaction = i2c_slave.I2CTransaction(addr, data_buf)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        counter = 0
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        print("I2C Slave test")
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            while True:
 | 
				
			||||||
 | 
					                state = s_i2c.handle_event()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if state == s_i2c.I2CStateMachine.I2C_START:
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                if state == s_i2c.I2CStateMachine.I2C_RECEIVE:
 | 
				
			||||||
 | 
					                    if currentTransaction.address == 0x00:
 | 
				
			||||||
 | 
					                        # First byte received is the register address
 | 
				
			||||||
 | 
					                        currentTransaction.address = s_i2c.Read_Data_Received() 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Read all data byte received until RX FIFO is empty
 | 
				
			||||||
 | 
					                    while (s_i2c.Available()):
 | 
				
			||||||
 | 
					                        currentTransaction.data_byte.append(s_i2c.Read_Data_Received())
 | 
				
			||||||
 | 
					                        # Virtually Increase register address
 | 
				
			||||||
 | 
					                        # s_i2c.I2CTransaction.address += 1
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                if state == s_i2c.I2CStateMachine.I2C_REQUEST:
 | 
				
			||||||
 | 
					                    # Send some dummy data back 
 | 
				
			||||||
 | 
					                    while (s_i2c.is_Master_Req_Read()):
 | 
				
			||||||
 | 
					                        counter += 1
 | 
				
			||||||
 | 
					                        s_i2c.Slave_Write_Data(counter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Virtually Increase register address
 | 
				
			||||||
 | 
					                        # s_i2c.I2CTransaction.address += 1
 | 
				
			||||||
 | 
					                        print ("Sendind data : ", counter)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                if state == s_i2c.I2CStateMachine.I2C_FINISH:
 | 
				
			||||||
 | 
					                    print ("Register : ", currentTransaction.address ,"Received : ", currentTransaction.data_byte)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                    currentTransaction.address = 0x00
 | 
				
			||||||
 | 
					                    currentTransaction.data_byte = []
 | 
				
			||||||
 | 
					                    state= s_i2c.I2CStateMachine.I2C_IDLE
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except KeyboardInterrupt:
 | 
				
			||||||
 | 
					            s_i2c.deinit()  # Clean up when done
 | 
				
			||||||
 | 
					            print("I2C slave stopped")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										84
									
								
								distance.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								distance.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,84 @@
 | 
				
			||||||
 | 
					import machine
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					from i2c_handler import I2CSlaveHandler, Packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DistanceHandler(I2CSlaveHandler):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    I2C handler that responds to master requests by sending distance values
 | 
				
			||||||
 | 
					    from an HC-SR04 ultrasonic sensor.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, i2c_id, sda, scl, slave_addr, trig_pin, echo_pin):
 | 
				
			||||||
 | 
					        super().__init__(i2c_id, sda, scl, slave_addr)
 | 
				
			||||||
 | 
					        self.trig = machine.Pin(trig_pin, machine.Pin.OUT)
 | 
				
			||||||
 | 
					        self.echo = machine.Pin(echo_pin, machine.Pin.IN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def read_distance_mm(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Measure distance using the HC-SR04 sensor.
 | 
				
			||||||
 | 
					        Returns distance in millimeters as an integer.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # Send a 10us pulse to trigger
 | 
				
			||||||
 | 
					        self.trig.low()
 | 
				
			||||||
 | 
					        time.sleep_us(2)
 | 
				
			||||||
 | 
					        self.trig.high()
 | 
				
			||||||
 | 
					        time.sleep_us(10)
 | 
				
			||||||
 | 
					        self.trig.low()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Wait for echo high (timeout after 25ms)
 | 
				
			||||||
 | 
					        timeout = 25000
 | 
				
			||||||
 | 
					        start = time.ticks_us()
 | 
				
			||||||
 | 
					        while not self.echo.value():
 | 
				
			||||||
 | 
					            if time.ticks_diff(time.ticks_us(), start) > timeout:
 | 
				
			||||||
 | 
					                return 0  # sensor error
 | 
				
			||||||
 | 
					        t1 = time.ticks_us()
 | 
				
			||||||
 | 
					        while self.echo.value():
 | 
				
			||||||
 | 
					            if time.ticks_diff(time.ticks_us(), t1) > timeout:
 | 
				
			||||||
 | 
					                return 0  # sensor error
 | 
				
			||||||
 | 
					        t2 = time.ticks_us()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Calculate duration and distance
 | 
				
			||||||
 | 
					        duration = time.ticks_diff(t2, t1)
 | 
				
			||||||
 | 
					        distance_mm = (duration * 100) // 582
 | 
				
			||||||
 | 
					        # HC-SR04: distance (mm) = duration (us) / 5.82
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Clamp to 0..65535
 | 
				
			||||||
 | 
					        return max(0, min(distance_mm, 65535))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_request(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Called when master requests data. Responds with a packet containing distance.
 | 
				
			||||||
 | 
					        Packet format:
 | 
				
			||||||
 | 
					        Byte 0: 0x01 (distance command)
 | 
				
			||||||
 | 
					        Byte 1: reserved
 | 
				
			||||||
 | 
					        Byte 2-3: distance (uint16, mm, little-endian)
 | 
				
			||||||
 | 
					        Byte 4-6: reserved
 | 
				
			||||||
 | 
					        Byte 7: checksum (xor of bytes 0-6)
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        #dist = self.read_distance_mm()
 | 
				
			||||||
 | 
					        dist = 155
 | 
				
			||||||
 | 
					        data = [0] * Packet.LENGTH
 | 
				
			||||||
 | 
					        data[0] = 0x01  # Command: distance
 | 
				
			||||||
 | 
					        data[2] = dist & 0xFF  # Low byte
 | 
				
			||||||
 | 
					        data[3] = (dist >> 8) & 0xFF  # High byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Checksum: XOR of bytes 0-6
 | 
				
			||||||
 | 
					        cs = 0
 | 
				
			||||||
 | 
					        for b in data[:-1]:
 | 
				
			||||||
 | 
					            cs ^= b
 | 
				
			||||||
 | 
					        data[7] = cs
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        print(Packet.from_bytes(data))
 | 
				
			||||||
 | 
					        return Packet.from_bytes(data)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    handler = DistanceHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41, trig_pin=3, echo_pin=2)
 | 
				
			||||||
 | 
					    print("Distance handler I2C slave started")
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        handler.handle()
 | 
				
			||||||
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        handler.deinit()
 | 
				
			||||||
 | 
					        print("I2C slave stopped")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										124
									
								
								i2c_handler.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								i2c_handler.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,124 @@
 | 
				
			||||||
 | 
					import machine
 | 
				
			||||||
 | 
					from RP2040_Slave import i2c_slave
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Packet Definition ===
 | 
				
			||||||
 | 
					class Packet:
 | 
				
			||||||
 | 
					    """Represents an 8-byte I2C packet."""
 | 
				
			||||||
 | 
					    LENGTH = 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, data=None):
 | 
				
			||||||
 | 
					        if data is None:
 | 
				
			||||||
 | 
					            data = [0] * self.LENGTH
 | 
				
			||||||
 | 
					        if len(data) != self.LENGTH:
 | 
				
			||||||
 | 
					            raise ValueError(f"Packet must be {self.LENGTH} bytes")
 | 
				
			||||||
 | 
					        self.bytes = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def from_bytes(cls, byte_list):
 | 
				
			||||||
 | 
					        """Create Packet from list of bytes."""
 | 
				
			||||||
 | 
					        return cls(byte_list[:cls.LENGTH])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __getitem__(self, idx):
 | 
				
			||||||
 | 
					        return self.bytes[idx]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __setitem__(self, idx, value):
 | 
				
			||||||
 | 
					        self.bytes[idx] = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        fields = [f"Byte {i}: 0x{b:02X}" for i, b in enumerate(self.bytes)]
 | 
				
			||||||
 | 
					        return "\n".join(fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def as_list(self):
 | 
				
			||||||
 | 
					        return self.bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_valid(self):
 | 
				
			||||||
 | 
					        """Verify checksum (XOR of bytes 0-6 equals byte 7)."""
 | 
				
			||||||
 | 
					        cs = 0
 | 
				
			||||||
 | 
					        for b in self.bytes[:-1]:
 | 
				
			||||||
 | 
					            cs ^= b
 | 
				
			||||||
 | 
					        return cs == self.bytes[-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === I2C Slave Handler ===
 | 
				
			||||||
 | 
					class I2CSlaveHandler:
 | 
				
			||||||
 | 
					    def __init__(self, i2c_id, sda, scl, slave_addr):
 | 
				
			||||||
 | 
					        self.s_i2c = i2c_slave(i2c_id, sda=sda, scl=scl, slaveAddress=slave_addr)
 | 
				
			||||||
 | 
					        self.packet_buf = []
 | 
				
			||||||
 | 
					        self.response_buf = None
 | 
				
			||||||
 | 
					        self.response_idx = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle(self):
 | 
				
			||||||
 | 
					        state = self.s_i2c.I2CStateMachine.I2C_IDLE
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            state = self.s_i2c.handle_event()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if state == self.s_i2c.I2CStateMachine.I2C_RECEIVE:
 | 
				
			||||||
 | 
					                while self.s_i2c.Available():
 | 
				
			||||||
 | 
					                    byte = self.s_i2c.Read_Data_Received()
 | 
				
			||||||
 | 
					                    self.packet_buf.append(byte)
 | 
				
			||||||
 | 
					                    #print(f"Received byte: 0x{byte:02X}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Only process when full packet is received
 | 
				
			||||||
 | 
					                if len(self.packet_buf) == Packet.LENGTH:
 | 
				
			||||||
 | 
					                    packet = Packet.from_bytes(self.packet_buf)
 | 
				
			||||||
 | 
					                    print("Received 8-byte packet:")
 | 
				
			||||||
 | 
					                    print(packet)
 | 
				
			||||||
 | 
					                    print("Packet valid:", packet.is_valid())
 | 
				
			||||||
 | 
					                    self.process_packet(packet)
 | 
				
			||||||
 | 
					                    self.packet_buf = []  # Clear buffer after processing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if state == self.s_i2c.I2CStateMachine.I2C_FINISH:
 | 
				
			||||||
 | 
					                if self.packet_buf and len(self.packet_buf) < Packet.LENGTH:
 | 
				
			||||||
 | 
					                    #print(f"Incomplete packet ({len(self.packet_buf)} bytes): {[f'0x{b:02X}' for b in self.packet_buf]}")
 | 
				
			||||||
 | 
					                    print(f"Incomplete packet ({len(self.packet_buf)} bytes): {self.packet_buf}")
 | 
				
			||||||
 | 
					                    self.packet_buf = []  # Clear buffer on incomplete packet
 | 
				
			||||||
 | 
					                state = self.s_i2c.I2CStateMachine.I2C_IDLE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if state == self.s_i2c.I2CStateMachine.I2C_REQUEST:
 | 
				
			||||||
 | 
					                print("Master requested data, sending response packet:")
 | 
				
			||||||
 | 
					                #self.s_i2c.Slave_Write_Data(self.process_request().as_list())
 | 
				
			||||||
 | 
					                # Prepare response buffer if not set
 | 
				
			||||||
 | 
					                if self.response_buf is None:
 | 
				
			||||||
 | 
					                    self.response_buf = self.process_request().as_list()
 | 
				
			||||||
 | 
					                    self.response_idx = 0
 | 
				
			||||||
 | 
					                    print("Prepared response packet:", self.response_buf)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                # Send next byte
 | 
				
			||||||
 | 
					                if self.response_idx < Packet.LENGTH:
 | 
				
			||||||
 | 
					                    self.s_i2c.Slave_Write_Data(self.response_buf[self.response_idx])
 | 
				
			||||||
 | 
					                    print("write")
 | 
				
			||||||
 | 
					                    self.response_idx += 1
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    # Reset response for next transaction
 | 
				
			||||||
 | 
					                    self.response_buf = None
 | 
				
			||||||
 | 
					                    self.response_idx = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_packet(self, packet):
 | 
				
			||||||
 | 
					        """Override this method to process packets."""
 | 
				
			||||||
 | 
					        # Example: Print command/type and target/channel
 | 
				
			||||||
 | 
					        cmd = packet[0]
 | 
				
			||||||
 | 
					        target = packet[1]
 | 
				
			||||||
 | 
					        print(f"Command/Type: 0x{cmd:02X}, Target/Channel: 0x{target:02X}")
 | 
				
			||||||
 | 
					        # Add custom logic for your robot here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_request(self):
 | 
				
			||||||
 | 
					        """Override this method to process requests"""
 | 
				
			||||||
 | 
					        return Packet.from_bytes([0x12, 0, 0, 0, 0, 0, 0, 0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deinit(self):
 | 
				
			||||||
 | 
					        self.s_i2c.deinit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Example usage for RP2040 ===
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    # Change slaveAddress as needed for each RP2040
 | 
				
			||||||
 | 
					    SLAVE_ADDR = 0x41
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handler = I2CSlaveHandler(i2c_id=0, sda=0, scl=1, slave_addr=SLAVE_ADDR)
 | 
				
			||||||
 | 
					    print(f"I2C Slave started at address 0x{SLAVE_ADDR:02X}")
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        handler.handle()
 | 
				
			||||||
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        handler.deinit()
 | 
				
			||||||
 | 
					        print("I2C slave stopped")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										36
									
								
								led.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								led.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					from i2c_handler import I2CSlaveHandler, Packet
 | 
				
			||||||
 | 
					import neopixel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LedDistanceHandler(I2CSlaveHandler):
 | 
				
			||||||
 | 
					    def __init__(self, i2c_id, sda, scl, slave_addr):
 | 
				
			||||||
 | 
					        super().__init__(i2c_id, sda, scl, slave_addr)
 | 
				
			||||||
 | 
					        self.last_led_color = (0, 0, 0)  # RGB tuple
 | 
				
			||||||
 | 
					        self.np = neopixel.NeoPixel(machine.Pin(23), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_packet(self, packet: Packet):
 | 
				
			||||||
 | 
					        cmd = packet[0]
 | 
				
			||||||
 | 
					        # Assume LED color command is 0x10, RGB in bytes 2,3,4
 | 
				
			||||||
 | 
					        if cmd == 0x10:  # Set LED Color
 | 
				
			||||||
 | 
					            r = packet[2]
 | 
				
			||||||
 | 
					            g = packet[3]
 | 
				
			||||||
 | 
					            b = packet[4]
 | 
				
			||||||
 | 
					            self.last_led_color = (r, g, b)
 | 
				
			||||||
 | 
					            print(f"Set LED color to RGB({r},{g},{b})")
 | 
				
			||||||
 | 
					            # TODO: Set the hardware LED to this color
 | 
				
			||||||
 | 
					            self.np[0] = self.last_led_color
 | 
				
			||||||
 | 
					            self.np.write()
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print(f"Unknown command 0x{cmd:02X}")
 | 
				
			||||||
 | 
					            self.response_packet = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    handler = LedDistanceHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41)
 | 
				
			||||||
 | 
					    print("LED/Distance handler I2C slave started")
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        handler.handle()
 | 
				
			||||||
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        handler.deinit()
 | 
				
			||||||
 | 
					        print("I2C slave stopped")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										40
									
								
								usage.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								usage.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					from i2c_handler import I2CSlaveHandler, Packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MyRobotHandler(I2CSlaveHandler):
 | 
				
			||||||
 | 
					    def process_packet(self, packet: Packet):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Example: Override process_packet to perform actions based on packet command/type.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        cmd = packet[0]
 | 
				
			||||||
 | 
					        target = packet[1]
 | 
				
			||||||
 | 
					        speed = (packet[2] << 8) | packet[3]
 | 
				
			||||||
 | 
					        # Convert speed from unsigned to signed if needed
 | 
				
			||||||
 | 
					        if speed & 0x8000:
 | 
				
			||||||
 | 
					            speed -= 0x10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print(f"Custom handler: Command 0x{cmd:02X}, Target 0x{target:02X}, Speed {speed}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Example: Perform a motor action for command 0x01
 | 
				
			||||||
 | 
					        if cmd == 0x01:  # Set Motor Speed
 | 
				
			||||||
 | 
					            print(f"Setting motor {target} speed to {speed}")
 | 
				
			||||||
 | 
					            # TODO: Add your motor control code here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif cmd == 0xFF:  # Emergency Stop
 | 
				
			||||||
 | 
					            print("Emergency stop received!")
 | 
				
			||||||
 | 
					            # TODO: Add your emergency stop code here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print("Unknown command")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Usage example
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    handler = MyRobotHandler(i2c_id=0, sda=0, scl=1, slave_addr=0x41)
 | 
				
			||||||
 | 
					    print("MyRobotHandler I2C slave started")
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        handler.handle()
 | 
				
			||||||
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        handler.deinit()
 | 
				
			||||||
 | 
					        print("I2C slave stopped")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue