int TwMasterTransact(unsigned char sla, void *txdata, unsigned short txlen, void *rxdata, unsigned short rxsiz, unsigned long tmo) { int rc = 0; unsigned char *cp; if (txlen) { TwStart(); /* Send SLA+W and check for ACK. */ if ((rc = TwPut(sla << 1)) == 0) { for (cp = (unsigned char *) txdata; txlen--; cp++) { if ((rc = TwPut(*cp)) != 0) { break; } } } } if (rc == 0 && rxsiz) { TwStart(); /* Send SLA+R and check for ACK. */ if ((rc = TwPut((sla << 1) | 1)) == 0) { for (cp = rxdata;; cp++) { *cp = TwGet(); if (++rc >= rxsiz) { break; } TwAck(); } } } TwStop(); return rc; }
/*! * \brief Transmit and/or receive data as a master. * * The two-wire serial interface must have been initialized by calling * TwInit() before this function can be used. * * \param sla Slave address of the destination. This slave address * must be specified as a 7-bit address. For example, the * PCF8574A may be configured to slave addresses from 0x38 * to 0x3F. * \param txdata Points to the data to transmit. Ignored, if the number * of data bytes to transmit is zero. * \param txlen Number of data bytes to transmit. If zero, then the * interface will not send any data to the slave device * and will directly enter the master receive mode. * \param rxdata Points to a buffer, where the received data will be * stored. Ignored, if the maximum number of bytes to * receive is zero. * \param rxsiz Maximum number of bytes to receive. Set to zero, if * no bytes are expected from the slave device. * \param tmo Timeout in milliseconds. To disable timeout, set this * parameter to NUT_WAIT_INFINITE. * * \return The number of bytes received, -1 in case of an error or timeout. * * \note Timeout is not used in the bit banging version. */ int NutTwiMasterTranceive(NUTTWIBUS *bus, uint8_t sla, const void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo) { int rc = 0; uint8_t *cp; NUTTWIICB *icb = bus->bus_icb; if (!twibb_initialized) { TwInit(0); } /* This routine is marked reentrant, so lock the interface. */ if (NutEventWait(&bus->bus_mutex, tmo)) { icb->tw_mm_error = TWERR_IF_LOCKED; return -1; } TwStart(); /* Send SLA+W and check for ACK. */ if ((rc = TwPut(sla << 1)) == 0) { for (cp = (uint8_t *)txdata; txlen--; cp++) { if ((rc = TwPut(*cp)) != 0) { break; } } } if (rc == 0 && rxsiz) { TwStart(); /* Send SLA+R and check for ACK. */ if ((rc = TwPut((sla << 1) | 1)) == 0) { for (cp = rxdata;; cp++) { *cp = TwGet(); if (++rc >= rxsiz) { break; } TwAck(); } } } TwStop(); if (rc == -1) { icb->tw_mm_error = TWERR_SLA_NACK; } /* Release the interface. */ NutEventPost(&bus->bus_mutex); return rc; }
/*! * \brief I2C bus transfer (GPIO TWI implementation). * * This function is called by the platform independent code via the * NUTI2C_BUS::bus_tran function pointer. */ static int TwiBusTran(NUTI2C_SLAVE *slave, NUTI2C_MSG *msg) { NUTI2C_BUS *bus; GPIO_TWICB *icb; int i, rc = 0; bus = slave->slave_bus; icb = (GPIO_TWICB *) bus->bus_icb; msg->msg_widx = 0; msg->msg_ridx = 0; if (msg->msg_wlen) { /* * Process I2C write operation. */ TwStart(icb); rc = TwPut(icb, (slave->slave_address << 1)); if (rc == 0) { for (i = 0; i < msg->msg_wlen; i++) { rc = TwPut(icb, msg->msg_wdat[i]); if (rc) break; msg->msg_widx++; } } } if ((rc == 0) && msg->msg_rsiz) { TwStart(icb); rc = TwPut(icb, (slave->slave_address << 1)|1); if (rc == 0) { for (i = 0; i < msg->msg_rsiz; i++) { msg->msg_rdat[i] = TwGet(icb, i < (msg->msg_rsiz-1)); msg->msg_ridx++; } } } TwStop(icb); if (rc) msg->msg_ridx = rc; return msg->msg_ridx; }
/*! * \brief Probe the I2C bus for a specified slave address (GPIO implementation). * * This function is called by the platform independent code via the * NUTI2C_BUS::bus_probe function pointer. This may happen even if no * slave device had been attached to the bus and thus without any * previous call to NUTI2C_BUS::bus_init. However, in that case * NUTI2C_BUS::bus_configure will have been called. */ static int TwiBusProbe(NUTI2C_BUS *bus, int sla) { int rc = -1; GPIO_TWICB *icb; icb = (GPIO_TWICB *) bus->bus_icb; if ((bus->bus_flags & I2C_BF_INITIALIZED) == 0) { int res; res = TwiBusInit(bus); if (res) return res; } TwStart(icb); rc = TwPut(icb, (sla<<1)); TwStop(icb); return rc; }