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;
}
示例#3
0
/*!
 * \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;
}