Compare commits
No commits in common. "ae9b468be74c69e420bf2bbfb1dbdda8e5e2202e" and "8d1b69d3044804d976b151664acf9fe52e44b68e" have entirely different histories.
ae9b468be7
...
8d1b69d304
6 changed files with 0 additions and 892 deletions
|
@ -1,302 +0,0 @@
|
|||
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
306
RP2040_Slave.py
|
@ -1,306 +0,0 @@
|
|||
### 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
84
distance.py
|
@ -1,84 +0,0 @@
|
|||
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
124
i2c_handler.py
|
@ -1,124 +0,0 @@
|
|||
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
36
led.py
|
@ -1,36 +0,0 @@
|
|||
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
40
usage.py
|
@ -1,40 +0,0 @@
|
|||
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