📄 i2c-algo-ip0105.c
字号:
static __inline void iic_interrupt_master_transmitter(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){ switch (i2c_state) { case 0x10: /* Master Transmitter or Master Receiver: A repeated START condition has been transmitted */ /* Note : A repeated START should not occur when in MasterReceiver mode in this implementation */ if( ( busptr->mst_txbufindex < busptr->mst_txbuflen ) || ( busptr->mst_rxbufindex == busptr->mst_rxbuflen ) ) /* if bytes to transmit or no bytes to receive ? */ { int myaddr = (busptr->mst_address & 0xFE); dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit cleared addr = %x\n", myaddr); write_IP0105_I2C_DAT(busptr, myaddr); /* Read bit cleared */ busptr->mode = MasterTransmitter; } else { int myaddr = ((busptr->mst_address & 0xFE) | 0x01); dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit set(%x)\n", myaddr); write_IP0105_I2C_DAT(busptr, myaddr); /* Read bit set */ busptr->mode = MasterReceiver; } STAOUT( busptr, 0 );/* Clear STA flag */ CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ break; case 0x18: /* Master Transmitter: SLA+W has been transmitted; ACK has been received */ /* fall through; */ case 0x28: /* Master Transmitter: Data byte in I2DAT has been transmitted; ACK has been received */ if( busptr->mst_txbufindex < busptr->mst_txbuflen ) /* transmit buffer not empty ? */ { write_IP0105_I2C_DAT(busptr, *( busptr->mst_txbuf + busptr->mst_txbufindex )); busptr->mst_txbufindex++; STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ } else { if( busptr->mst_rxbufindex < busptr->mst_rxbuflen ) /* if bytes to receive ? */ { STAOUT( busptr, 1 ); /* Generate repeated START condition */ } else { STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ STOOUT( busptr, 1 ); /* Generate STOP condition */ busptr->mode = Idle; busptr->isr_event |= evMasterReady; wake_up_interruptible(&(busptr->iic_wait_master)); } } CLEAR_I2C_INTERRUPT( busptr ); /* reset interrupt */ break; case 0x20: /* Master Transmitter: SLA+W has been transmitted; NOT ACK has been received */ dev_dbg(&i2c_adap->dev, "Master Transmitter : SLA+W, NOT ACK has been received\n"); /* fall through; */ case 0x30: /* Master Transmitter: Data byte in I2DAT has been transmitted; NOT ACK has been received */ STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ STOOUT( busptr, 1 ); /* Generate STOP condition */ busptr->mode = Idle; busptr->mst_status = ( i2c_state == 0x20 ) ? errids_IsI2cDeviceError : errids_IsI2cWriteError; busptr->isr_event |= evMasterReady; CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ wake_up_interruptible(&(busptr->iic_wait_master)); break; case 0x38: /* Arbitration lost in SLA+R/~W or Data bytes */ busptr->mode = Idle; STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after slave address reception */ CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ break; case 0x68: /* Arbitration lost in SLA+R/~W as master; Own SLA+W has been received, ACK has been returned */ STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; busptr->slv_bufindex = 1; /* reset buffer pointer !!! */ AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after next byte reception */ busptr->mode = SlaveReceiver;// Todo : Start timeout timer in tasklet// slave_device = i2c_adap;// tasklet_schedule(&IP0105_slave_tasklet); CLEAR_I2C_INTERRUPT(busptr); /* Don't reset i2c interrupt */ break; case 0xB0: /* Arbitration lost in SLA+R/~W as master; Own SLA+R has been received, ACK has been returned */ STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; busptr->mode = SlaveTransmitter; busptr->isr_event |= evSlaveReadRequest; slave_device = i2c_adap; tasklet_schedule(&IP0105_slave_tasklet); /* Don't reset i2c interrupt */ break; case 0x70: /* General call address (0x00) has been received; ACK has been returned */ /* fall through; */ case 0x78: /* Arbitration lost in SLA+R/~W as master; General call address (0x00) has been received; ACK has been returned */ /* fall through; */ default: recover_from_hardware_error( i2c_adap ); break; }}static __inline void iic_interrupt_master_receiver(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){ switch(i2c_state) { /* 0x10 : A repeated START should not occur when in MasterReceiver mode in this implementation */ case 0x38: /* Arbitration lost in NOT ACK bit */ busptr->mode = Idle; STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; AAOUT( busptr, busptr->slv_enabled); /* ACK bit will be returned, or not, after slave address reception */ CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ break; case 0x50: /* Data byte has been received; ACK has been returned */ if ( busptr->mst_rxbufindex < busptr->mst_rxbuflen ) /* bytes to receive ? */ { *( busptr->mst_rxbuf + busptr->mst_rxbufindex++ ) = read_IP0105_I2C_DAT(busptr); } else { (void)read_IP0105_I2C_DAT(busptr); /* Ignore received byte, no storage space available */ } /* fall through; */ case 0x40: /* SLA+R has been transmitted; ACK has been received */ if ( busptr->mst_rxbufindex < ( busptr->mst_rxbuflen - 1 ) ) { AAOUT( busptr, 1 ); /* ACK bit will be returned after byte reception */ } else { AAOUT( busptr, 0 ); /* NOT ACK bit will be returned after (last) byte reception */ } STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ CLEAR_I2C_INTERRUPT( busptr ); /* reset interrupt */ break; case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */ STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ STOOUT( busptr, 1 ); /* Generate STOP condition */ busptr->mode = Idle; busptr->mst_status = errids_IsI2cDeviceError; busptr->isr_event |= evMasterReady; wake_up_interruptible(&(busptr->iic_wait_master)); CLEAR_I2C_INTERRUPT( busptr ); /* reset interrupt */ break; case 0x58: /* Data byte has been received; NOT ACK has been returned */ if ( busptr->mst_rxbufindex < busptr->mst_rxbuflen ) /* bytes to receive ? */ { *( busptr->mst_rxbuf + busptr->mst_rxbufindex++ ) = read_IP0105_I2C_DAT(busptr);dev_dbg(&i2c_adap->dev, "received byte %x\n", *(busptr->mst_rxbuf + busptr->mst_rxbufindex -1)); } else { (void)read_IP0105_I2C_DAT(busptr);dev_dbg(&i2c_adap->dev, "ignore received byte\n"); } AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after slave address reception */ STAOUT( busptr, 0 ); /* Don't generate (repeated) START condition */ STOOUT( busptr, 1 ); /* Generate STOP condition */ busptr->mode = Idle; busptr->isr_event |= evMasterReady; CLEAR_I2C_INTERRUPT( busptr ); /* reset interrupt */ wake_up_interruptible(&(busptr->iic_wait_master)); break; case 0x68: /* Arbitration lost in SLA+R/~W as master; Own SLA+W has been received, ACK has been returned */ STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; busptr->slv_bufindex = 1; /* reset buffer pointer !!! */ AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after next byte reception */ busptr->mode = SlaveReceiver;// Todo : Start timeout timer in tasklet// tasklet_schedule(&IP0105_slave_tasklet); CLEAR_I2C_INTERRUPT(busptr); /* Don't reset i2c interrupt */ break; case 0xB0: /* Arbitration lost in SLA+R/~W as master; Own SLA+R has been received, ACK has been returned */ STAOUT( busptr, 1 ); /* Retry the master operation */ busptr->mst_txbufindex = 0; busptr->mst_rxbufindex = 0; busptr->mode = SlaveReceiver; busptr->isr_event |= evSlaveReadRequest; slave_device = i2c_adap; tasklet_schedule(&IP0105_slave_tasklet); /* Don't reset i2c interrupt */ break; case 0x70: /* General call address (0x00) has been received; ACK has been returned */ /* fall through; */ case 0x78: /* Arbitration lost in SLA+R/~W as master; General call address (0x00) has been received; ACK has been returned */ /* fall through; */ default: recover_from_hardware_error( i2c_adap ); break; }}static __inline void iic_interrupt_slave_receiver(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){ switch (i2c_state) { case 0x80: /* Previously addressed with own SLA; DATA byte has been received; ACK has been returned */ if( busptr->slv_bufindex < busptr->slv_bufsize ) { *( busptr->slv_buf + busptr->slv_bufindex++ ) = read_IP0105_I2C_DAT(busptr); } else { (void)read_IP0105_I2C_DAT(busptr); } AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after next byte reception */ CLEAR_I2C_INTERRUPT( busptr ); /* Reset i2c interrupt */ break; case 0x88: /* Previously addressed with own SLA; DATA byte has been received; NOT ACK has been returned */ if ( busptr->slv_bufindex < busptr->slv_bufsize ) { *( busptr->slv_buf + busptr->slv_bufindex++ ) = read_IP0105_I2C_DAT(busptr); } else { (void)read_IP0105_I2C_DAT(busptr); } AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after slave address reception */ CLEAR_I2C_INTERRUPT( busptr ); /* reset i2c interrupt */ break; case 0xA0: /* A STOP condition or repeated START has been received while still address as SLV/REC or SLV/TRX */ // Slave will be enabled again when data is out of the buffer AAOUT( busptr, 0 ); /* NOT ACK bit will be returned after slave address reception */ busptr->isr_event |= evSlaveStopCondition; slave_device = i2c_adap; tasklet_schedule(&IP0105_slave_tasklet); CLEAR_I2C_INTERRUPT( busptr ); /* Reset i2c interrupt */ break; case 0x70: /* General call address (0x00) has been received; ACK has been returned */ /* fall through; */ case 0x78: /* Arbitration lost in SLA+R/~W as master; General call address (0x00) has been received; ACK has been returned */ /* fall through; */ case 0x90: /* Previously addressed with General call; DATA byte has been received; ACK has been returned */ /* fall through; */ case 0x98: /* Previously addressed with General call; DATA byte has been received; NOT ACK has been returned */ /* fall through; */ default: recover_from_hardware_error( i2c_adap ); break; }}static __inline void iic_interrupt_slave_transmitter(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){ switch (i2c_state) { case 0xA0: /* A STOP condition or repeated START has been received while still address as SLV/TRX */ // Slave will be enabled again when data is out of the buffer AAOUT( busptr, 0 ); /* NOT ACK bit will be returned after slave address reception */ busptr->isr_event |= evSlaveStopCondition; slave_device = i2c_adap; tasklet_schedule(&IP0105_slave_tasklet); CLEAR_I2C_INTERRUPT( busptr ); /* Reset i2c interrupt */ break; case 0xB8: /* Data byte in I2DAT has been transmitted; ACK has been received */ if ( busptr->slv_bufindex < busptr->slv_bufsize ) { write_IP0105_I2C_DAT(busptr, *( busptr->slv_buf + busptr->slv_bufindex )); busptr->slv_bufindex++; if ( busptr->slv_bufindex < busptr->slv_buflen ) { AAOUT( busptr, 1 ); /* Data byte will be transmitted */ } else { AAOUT( busptr, 0 ); /* Last data byte will be transmitted */ } CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -