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;
}
Пример #2
0
/*!
 * \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;
}