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; }