Exemplo n.º 1
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_HAL_SlaveSendDataPolling
 * Description   : Send out multiple bytes of data using polling method.
 *
 *END*/
i2c_status_t I2C_HAL_SlaveSendDataPolling(I2C_Type * base, const uint8_t* txBuff, uint32_t txSize)
{
#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
     /** Wait until start detected */
   while(!I2C_HAL_GetStartFlag(base))
   {}
   I2C_HAL_ClearStartFlag(base);
#endif
     /** Wait until addressed as a slave */
    while(!I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave))
    {}

     /** Wait interrupt flag is set */
    while(!I2C_HAL_IsIntPending(base))
    {}
         /** Clear interrupt flag */
    I2C_HAL_ClearInt(base);

     /** Set direction mode */
    if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit))
    {
         /** Switch to TX mode*/
        I2C_HAL_SetDirMode(base, kI2CSend);
    }
    else
    {
         /** Switch to RX mode.*/
        I2C_HAL_SetDirMode(base, kI2CReceive);

         /** Read dummy character.*/
        I2C_HAL_ReadByte(base);
    }

     /** While loop to transmit data */
    while(txSize--)
    {
         /** Write byte to data register */
        I2C_HAL_WriteByte(base, *txBuff++);

         /** Wait tranfer byte complete */
        while(!I2C_HAL_IsIntPending(base))
        {}

         /** Clear interrupt flag */
        I2C_HAL_ClearInt(base);

         /** if NACK received */
        if ((I2C_HAL_GetStatusFlag(base, kI2CReceivedNak)) && (txSize != 0))
        {
            return kStatus_I2C_ReceivedNak;
        }
    }
     /** Switch to RX mode.*/
    I2C_HAL_SetDirMode(base, kI2CReceive);

     /** Read dummy character.*/
    I2C_HAL_ReadByte(base);

    return kStatus_I2C_Success;
}
Exemplo n.º 2
0
int i2c_byte_read(i2c_t *obj, int last) {
    char data;
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    // set rx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive);

    // Setup read
    i2c_do_read(obj, &data, last);

    // set tx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend);
    return I2C_HAL_ReadByte(i2c_addrs[obj->instance]);
}
Exemplo n.º 3
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_HAL_SlaveReceiveDataPolling
 * Description   : Receive multiple bytes of data using polling method.
 *
 *END*/
i2c_status_t I2C_HAL_SlaveReceiveDataPolling(I2C_Type * base, uint8_t *rxBuff, uint32_t rxSize)
{
#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
     /** Wait until start detected */
   while(!I2C_HAL_GetStartFlag(base))
   {}
   I2C_HAL_ClearStartFlag(base);
#endif
     /** Wait until addressed as a slave */
    while(!I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave))
    {}

     /** Wait interrupt flag is set */
    while(!I2C_HAL_IsIntPending(base))
    {}
         /** Clear interrupt flag */
    I2C_HAL_ClearInt(base);

     /** Set direction mode */
    if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit))
    {
         /** Switch to TX mode*/
        I2C_HAL_SetDirMode(base, kI2CSend);
    }
    else
    {
         /** Switch to RX mode.*/
        I2C_HAL_SetDirMode(base, kI2CReceive);

         /** Read dummy character.*/
        I2C_HAL_ReadByte(base);
    }

     /** While loop to receive data */
    while(rxSize--)
    {
         /** Wait interrupt flag is set */
        while(!I2C_HAL_IsIntPending(base))
        {}

         /** Read byte from data register  */
        *rxBuff++ = I2C_HAL_ReadByte(base);

         /** Clear interrupt flag */
        I2C_HAL_ClearInt(base);
    }
    return kStatus_I2C_Success;
}
Exemplo n.º 4
0
int i2c_slave_read(i2c_t *obj, char *data, int length) {
    uint8_t dummy_read;
    uint8_t *ptr;
    int count;
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    // set rx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend);

    // first dummy read
    dummy_read = I2C_HAL_ReadByte(i2c_addrs[obj->instance]);
    if (i2c_wait_end_rx_transfer(obj))
        return 0;

    // read address
    dummy_read = I2C_HAL_ReadByte(i2c_addrs[obj->instance]);
    if (i2c_wait_end_rx_transfer(obj))
        return 0;

    // read (length - 1) bytes
    for (count = 0; count < (length - 1); count++) {
        data[count] = I2C_HAL_ReadByte(i2c_addrs[obj->instance]);
        if (i2c_wait_end_rx_transfer(obj))
            return count;
    }

    // read last byte
    ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
    *ptr = I2C_HAL_ReadByte(i2c_addrs[obj->instance]);

    return (length) ? (count + 1) : 0;
}
Exemplo n.º 5
0
int i2c_byte_write(i2c_t *obj, int data) {
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    // set tx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend);

    return !i2c_do_write(obj, (data & 0xFF));
}
//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
    /* Set direction to send for sending of address and data. */
    uint8_t result = (uint8_t)getWriteError();
    if(result != 0)
    {
        // reset tx buffer iterator vars
        txBufferIndex = 0;
        txBufferLength = 0;
        // indicate that we are done transmitting
        transmitting_master = false;
        return 1;
    }

    uint32_t t0 = millis();

    while(I2C_HAL_GetStatusFlag(instance, kI2CBusBusy) && !I2C_HAL_IsMaster(instance))
    {
        if(millis() - t0 >= 25)
            return 4; //timeout
    }

    uint16_t slaveAddress;
    slaveAddress = (txAddress << 1U) & 0x00FFU;
    bool sent = sendAddress(slaveAddress);
    //tx buffer also sent by interrupt

    // reset tx buffer iterator vars
    txBufferIndex = 0;
    txBufferLength = 0;
    // indicate that we are done transmitting
    transmitting_master = false;
    clearWriteError();

    result = 4;

    if(sent) //sent without timeout
    {
        if(master_state == MASTER_STATE_COMPLETE)
        {
            result = 0;
        }
        else if(master_state == MASTER_STATE_TX_NAK) //failed
        {
            result = (txBufferIndex == 0) ? 2 : 3; //address or data fail
            sendStop = true;
        }

        if(sendStop)
        {
            I2C_HAL_SendStop(instance);
        }
    }
    I2C_HAL_SetDirMode(instance, kI2CReceive);

    return result;
}
Exemplo n.º 7
0
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
    int i, count = 0;
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;

    // set tx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend);

    for (i = 0; i < length; i++) {
        if (i2c_do_write(obj, data[count++]) == 2)
            return i;
    }

    // set rx mode
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive);

    // dummy rx transfer needed
    // otherwise the master cannot generate a stop bit
    I2C_HAL_ReadByte(i2c_addrs[obj->instance]);
    if (i2c_wait_end_rx_transfer(obj) == 2)
        return count;

    return count;
}
bool TwoWire::sendAddress(uint16_t slaveAddress)
{
    master_state = MASTER_STATE_IDLE;

    I2C_HAL_SetDirMode(instance, kI2CSend);

    if(master_send_stop)
        I2C_HAL_SendStart(instance);

    I2C_HAL_WriteByte(instance, slaveAddress);

    uint32_t t0 = millis();

    while(master_state == MASTER_STATE_IDLE || master_state == MASTER_STATE_ARB_LOST)
    {
        if(millis() - t0 >= 25 || master_state == MASTER_STATE_ARB_LOST)
        {
            I2C_HAL_SendStop(instance);
            I2C_HAL_SetDirMode(instance, kI2CReceive);
            return false; //timeout
        }
    }
    return true;
}
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveReceiveData
 * Description   : Receive the data using a non-blocking method.
 * This function set buffer pointer and length to Rx buffer & Rx Size
 * A non-blocking (also known as synchronous) function means that the function
 * returns immediately after initiating the receive function. The application
 * has to get the receive status to see when the receive is complete.
 *
 *END**************************************************************************/
i2c_status_t I2C_DRV_SlaveReceiveData(uint32_t instance,
                                      uint8_t * rxBuff,
                                      uint32_t rxSize)
{
    assert(rxBuff);
    assert(instance < HW_I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        if (i2cSlaveState->isRxBusy)
        {
            return kStatus_I2C_Busy;
        }

        i2cSlaveState->rxBuff = rxBuff;
        i2cSlaveState->rxSize = rxSize;
        i2cSlaveState->isRxBusy = true;

        /* If IAAS event already comes, read dummy to release the bus.*/
        if(I2C_HAL_GetStatusFlag(g_i2cBaseAddr[instance], kI2CAddressAsSlave))
        {
             /* Switch to RX mode.*/
            I2C_HAL_SetDirMode(g_i2cBaseAddr[instance], kI2CReceive);
            I2C_HAL_ReadByte(g_i2cBaseAddr[instance]);
        }

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
        I2C_HAL_ClearStartFlag(g_i2cBaseAddr[instance]);
#endif
        I2C_HAL_ClearInt(g_i2cBaseAddr[instance]);
        I2C_HAL_SetIntCmd(g_i2cBaseAddr[instance], true);

        return kStatus_I2C_Success;
    }
    else /* i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
Exemplo n.º 10
0
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
    int count;
    char dummy_read, *ptr;

    if (i2c_start(obj)) {
        i2c_stop(obj);
        return I2C_ERROR_BUS_BUSY;
    }

    if (i2c_do_write(obj, (address | 0x01))) {
        i2c_stop(obj);
        return I2C_ERROR_NO_SLAVE;
    }

    // set rx mode
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive);

    // Read in bytes
    for (count = 0; count < (length); count++) {
        ptr = (count == 0) ? &dummy_read : &data[count - 1];
        uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
        if (i2c_do_read(obj, ptr, stop_)) {
            i2c_stop(obj);
            return count;
        }
    }

    // If not repeated start, send stop.
    if (stop)
        i2c_stop(obj);

    // last read
    data[count-1] = I2C_HAL_ReadByte(i2c_addrs[obj->instance]);

    return length;
}
Exemplo n.º 11
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveIRQHandler
 * Description   : I2C Slave Generic ISR.
 * ISR action be called inside I2C IRQ handler entry.
 *
 *END*/
void I2C_DRV_SlaveIRQHandler(uint32_t instance)
{
    assert(instance < I2C_INSTANCE_COUNT);

    I2C_Type * base = g_i2cBase[instance];
    uint8_t  i2cData  = 0x00;
    bool     doTransmit = false;
    bool     wasArbLost = I2C_HAL_GetStatusFlag(base, kI2CArbitrationLost);
    bool     addressed = I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave);
    bool     stopIntEnabled = false;

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    bool     startDetected = I2C_HAL_GetStartFlag(base);
    bool     startIntEnabled = I2C_HAL_GetStartStopIntCmd(base);
    bool     stopDetected = I2C_HAL_GetStopFlag(base);
    stopIntEnabled = startIntEnabled;
#endif

#if FSL_FEATURE_I2C_HAS_STOP_DETECT
    bool     stopDetected = I2C_HAL_GetStopFlag(base);
    stopIntEnabled = I2C_HAL_GetStopIntCmd(base);
#endif

     /** Get current runtime structure */
    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

     /** Get current slave transfer direction */
    i2c_direction_t direction = I2C_HAL_GetDirMode(base);

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    /*--------------- Handle START ------------------*/
    if (startIntEnabled && startDetected)
    {
        I2C_HAL_ClearStartFlag(base);
        I2C_HAL_ClearInt(base);

        if(i2cSlaveState->slaveCallback != NULL)
        {
            /*Call callback to handle when the driver detect START signal*/
            i2cSlaveState->slaveCallback(instance,
                                         kI2CSlaveStartDetect,
                                         i2cSlaveState->callbackParam);
        }

        return;
    }
#endif

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT || FSL_FEATURE_I2C_HAS_STOP_DETECT
    /*--------------- Handle STOP ------------------*/
    if (stopIntEnabled && stopDetected)
    {
        I2C_HAL_ClearStopFlag(base);
        I2C_HAL_ClearInt(base);

        if(!i2cSlaveState->slaveListening)
        {
             /** Disable I2C interrupt in the peripheral.*/
            I2C_HAL_SetIntCmd(base, false);
        }

        if(i2cSlaveState->slaveCallback != NULL)
        {
             /*Call callback to handle when the driver detect STOP signal*/
            i2cSlaveState->slaveCallback(instance,
                                         kI2CSlaveStopDetect,
                                         i2cSlaveState->callbackParam);
        }

        if (i2cSlaveState->isRxBlocking)
        {
            OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveStopDetect);
        }

        i2cSlaveState->status = kStatus_I2C_Idle;

        return;
    }
#endif

     /** Clear I2C IRQ.*/
    I2C_HAL_ClearInt(base);

    if (wasArbLost)
    {
        I2C_HAL_ClearArbitrationLost(base);
        if (!addressed)
        {
            i2cSlaveState->status = kStatus_I2C_AribtrationLost;
            if(!i2cSlaveState->slaveListening)
            {
                 /** Disable I2C interrupt in the peripheral.*/
                I2C_HAL_SetIntCmd(base, false);
            }
            return;
        }
    }

    /*--------------- Handle Address ------------------*/
     /** Addressed only happens when receiving address. */
    if (addressed)  /** Slave is addressed. */
    {
         /** Master read from Slave. Slave transmit.*/
        if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit))
        {
             /** Switch to TX mode*/
            I2C_HAL_SetDirMode(base, kI2CSend);

            if(i2cSlaveState->slaveCallback != NULL)
            {
                /*Call callback to handle when the driver get read request*/
                i2cSlaveState->slaveCallback(instance,
                                             kI2CSlaveTxReq,
                                             i2cSlaveState->callbackParam);
            }

            doTransmit = true;
        }
        else  /** Master write to Slave. Slave receive.*/
        {
             /** Switch to RX mode.*/
            I2C_HAL_SetDirMode(base, kI2CReceive);

            if(i2cSlaveState->slaveCallback != NULL)
            {
                /*Call callback to handle when the driver get write request*/
                i2cSlaveState->slaveCallback(instance,
                                             kI2CSlaveRxReq,
                                             i2cSlaveState->callbackParam);
            }

             /** Read dummy character.*/
            I2C_HAL_ReadByte(base);
        }
    }
    /*--------------- Handle Transfer ------------------*/
    else
    {
         /** Handle transmit */
        if (direction == kI2CSend)
        {
            if (I2C_HAL_GetStatusFlag(base, kI2CReceivedNak))
            {
                 /** Switch to RX mode.*/
                I2C_HAL_SetDirMode(base, kI2CReceive);
                 /** Read dummy character to release bus */
                I2C_HAL_ReadByte(base);

                if ((!i2cSlaveState->slaveListening) && (!stopIntEnabled))
                {
                     /** Disable I2C interrupt in the peripheral.*/
                    I2C_HAL_SetIntCmd(base, false);
                }

                if(i2cSlaveState->slaveCallback != NULL)
                {
                      /** Receive TX NAK, mean transaction is finished, call callback to handle */
                    i2cSlaveState->slaveCallback(instance,
                                                 kI2CSlaveTxNAK,
                                                 i2cSlaveState->callbackParam);
                }

                if (i2cSlaveState->isTxBlocking)
                {
                    OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveTxNAK);
                }

                i2cSlaveState->txSize = 0;
                i2cSlaveState->txBuff = NULL;
                i2cSlaveState->isTxBusy = false;
            }
            else  /** ACK from receiver.*/
            {
                doTransmit = true;
            }
        }
         /** Handle receive */
        else
        {
             /** Get byte from data register */
            i2cData = I2C_HAL_ReadByte(base);

            if (i2cSlaveState->rxSize)
            {
                *(i2cSlaveState->rxBuff) = i2cData;
                ++ i2cSlaveState->rxBuff;
                -- i2cSlaveState->rxSize;

                if (!i2cSlaveState->rxSize)
                {
                    if (!stopIntEnabled)
                    {
                        if(!i2cSlaveState->slaveListening)
                        {
                             /** Disable I2C interrupt in the peripheral.*/
                            I2C_HAL_SetIntCmd(base, false);
                        }

                         /** All bytes are received, so we're done with this transfer */
                        if (i2cSlaveState->isRxBlocking)
                        {
                            OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveRxFull);
                        }
                    }

                    i2cSlaveState->isRxBusy = false;
                    i2cSlaveState->rxBuff = NULL;

                    if(i2cSlaveState->slaveCallback != NULL)
                    {
                         /** Rx buffer is full, call callback to handle */
                        i2cSlaveState->slaveCallback(instance,
                                                     kI2CSlaveRxFull,
                                                     i2cSlaveState->callbackParam);
                    }
                }
            }
            else
            {
                 /** The Rxbuff is full --> Set kStatus_I2C_SlaveRxOverrun*/
                i2cSlaveState->status = kStatus_I2C_SlaveRxOverrun;
            }
        }
    }

     /** DO TRANSMIT*/
    if (doTransmit)
    {
         /** Send byte to data register */
        if (i2cSlaveState->txSize)
        {
            i2cData = *(i2cSlaveState->txBuff);
            I2C_HAL_WriteByte(base, i2cData);
            ++ i2cSlaveState->txBuff;
            -- i2cSlaveState->txSize;
            if (!i2cSlaveState->txSize)
            {
                 /** All bytes are received, so we're done with this transfer */
                i2cSlaveState->txBuff = NULL;
                i2cSlaveState->isTxBusy = false;

                if(i2cSlaveState->slaveCallback != NULL)
                {
                     /** Tx buffer is empty, finish transaction, call callback to handle */
                    i2cSlaveState->slaveCallback(instance,
                                                 kI2CSlaveTxEmpty,
                                                 i2cSlaveState->callbackParam);
                }

            }
        }
        else
        {
             /** The Txbuff is empty --> set kStatus_I2C_SlaveTxUnderrun*/
            i2cSlaveState->status = kStatus_I2C_SlaveTxUnderrun ;
        }
    }
}
Exemplo n.º 12
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveReceiveDataBlocking
 * Description   : Receive the data using a blocking method.
 * This function set buffer pointer and length to Rx buffer &Rx Size. Then wait
 * until the transmission is end (all data are received or STOP signal is
 * detected)
 *
 *END*/
i2c_status_t I2C_DRV_SlaveReceiveDataBlocking(uint32_t instance,
                                              uint8_t * rxBuff,
                                              uint32_t rxSize,
                                              uint32_t timeout_ms)
{
    assert(rxBuff);
    assert(instance < I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        event_flags_t i2cIrqSetFlags;
        osa_status_t syncStatus;

        if (i2cSlaveState->isRxBusy)
        {
            return kStatus_I2C_Busy;
        }

        i2cSlaveState->rxBuff = rxBuff;
        i2cSlaveState->rxSize = rxSize;
        i2cSlaveState->isRxBusy = true;
        i2cSlaveState->isRxBlocking = true;

         /** If IAAS event already comes, read dummy to release the bus.*/
        if(I2C_HAL_GetStatusFlag(g_i2cBase[instance], kI2CAddressAsSlave))
        {
             /** Switch to RX mode.*/
            I2C_HAL_SetDirMode(g_i2cBase[instance], kI2CReceive);
            I2C_HAL_ReadByte(g_i2cBase[instance]);
        }

        I2C_HAL_SetIntCmd(g_i2cBase[instance], true);

         /** Wait until the transmit is complete. */
        do
        {
            syncStatus = OSA_EventWait(&i2cSlaveState->irqEvent,
                                       #if (FSL_FEATURE_I2C_HAS_START_STOP_DETECT || FSL_FEATURE_I2C_HAS_STOP_DETECT)
                                       kI2CSlaveStopDetect |
                                       #endif
                                       kI2CSlaveRxFull | kI2CSlaveAbort,
                                       false,
                                       timeout_ms,
                                       &i2cIrqSetFlags);
        } while(syncStatus == kStatus_OSA_Idle);

        if (syncStatus != kStatus_OSA_Success)
        {
            I2C_HAL_SetIntCmd(g_i2cBase[instance], false);
            i2cSlaveState->status = kStatus_I2C_Timeout;
        }

        i2cSlaveState->isRxBlocking = false;

        return i2cSlaveState->status;
    }
    else  /** i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
void TwoWire::onService(void)
{
    //interrupt handler
    uint8_t  i2cData  = 0x00;
    bool     wasArbLost = I2C_HAL_GetStatusFlag(instance, kI2CArbitrationLost);
    bool     addressed = I2C_HAL_GetStatusFlag(instance, kI2CAddressAsSlave);
    bool     stopIntEnabled = false;

    bool     startDetected = I2C_HAL_GetStartFlag(instance);
    bool     startIntEnabled = I2C_HAL_GetStartStopIntCmd(instance);
    bool     stopDetected = I2C_HAL_GetStopFlag(instance);
    stopIntEnabled = startIntEnabled;

    /* Get current slave transfer direction */
    i2c_direction_t direction = I2C_HAL_GetDirMode(instance);

    /*--------------- Handle START, STOP or REPEAT START ------------------*/
    if (stopIntEnabled && (startDetected || stopDetected))
    {
        if(startDetected)
            I2C_HAL_ClearStartFlag(instance);
        if(stopDetected)
            I2C_HAL_ClearStopFlag(instance);
        I2C_HAL_ClearInt(instance);
        if(slaveBufferLength)
        {
            if(onReceiveCallback)
            {
                receiving_slave = true;
                onReceiveCallback(slaveBufferLength);
                receiving_slave = false;
            }
            slaveBufferIndex = 0;
            slaveBufferLength = 0;
        }
        return;
    }

    /* Clear I2C IRQ.*/
    I2C_HAL_ClearInt(instance);

    if (wasArbLost)
    {
        I2C_HAL_ClearArbitrationLost(instance);
        if (!addressed)
        {
            master_state = MASTER_STATE_ARB_LOST;
            return;
        }
    }

    if(I2C_HAL_IsMaster(instance))
    {
        if (direction == kI2CSend)
        {
            //check for NAK
            /* Check whether we got an ACK or NAK from the former byte we sent */
            if (I2C_HAL_GetStatusFlag(instance, kI2CReceivedNak))
            {
                master_state = MASTER_STATE_TX_NAK;
            }
            else if(transmitting_master)
            {
                /* Continue send if still have data. TxSize/txBuff index need
                 * increment first because one byte is already sent in order
                 * to trigger interrupt */
                 if (txBufferIndex < txBufferLength)
                 {
                     /* Transmit next byte and update buffer index */
                     I2C_HAL_WriteByte(instance, txBuffer[txBufferIndex++]);
                 }
                 else
                 {
                     /* Finish send data, send STOP, disable interrupt */
                     master_state = MASTER_STATE_COMPLETE;
                 }
             }
             else
             {
                 master_state = MASTER_STATE_READ_READY; //address sent for a read
             }
        }
        else
        {
            switch (--rxBufferQuantity)
            {
                case 0x0U:
                    /* Finish receive data, send STOP, disable interrupt */
                    master_state = MASTER_STATE_COMPLETE;
                    if(master_send_stop)
                        I2C_HAL_SendStop(instance);
                    else
                        I2C_HAL_SendStart(instance);
                    break;
                case 0x1U:
                    /* For the byte before last, we need to set NAK */
                    I2C_HAL_SendNak(instance);
                    break;
                default :
                    I2C_HAL_SendAck(instance);
                    break;
            }

            rxBuffer[rxBufferLength++] = I2C_HAL_ReadByte(instance);
        }
        return;
    }

    /*--------------- Handle Address ------------------*/
    /* Addressed only happens when receiving address. */
    if (addressed) /* Slave is addressed. */
    {
        /* Master read from Slave. Slave transmit.*/
        if (I2C_HAL_GetStatusFlag(instance, kI2CSlaveTransmit))
        {
            /* Switch to TX mode*/
            I2C_HAL_SetDirMode(instance, kI2CSend);

            transmitting_slave = true;
            slaveBufferIndex = 0;
            slaveBufferLength = 0;

            if (onRequestCallback)
                onRequestCallback(); //this needs to load the transmit buffer
            else
                // create a default 1-byte response
                write((uint8_t) 0);

        }
        else /* Master write to Slave. Slave receive.*/
        {
            /* Switch to RX mode.*/
            I2C_HAL_SetDirMode(instance, kI2CReceive);
            I2C_HAL_SendAck(instance);

            /* Read dummy character.*/
            I2C_HAL_ReadByte(instance);

            slaveBufferIndex = 0;
            slaveBufferLength = 0;
        }
    }
    /*--------------- Handle Transfer ------------------*/
    else
    {
        /* Handle transmit */
        if (direction == kI2CSend)
        {
            if (I2C_HAL_GetStatusFlag(instance, kI2CReceivedNak))
            {
                /* Switch to RX mode.*/
                I2C_HAL_SetDirMode(instance, kI2CReceive);
                /* Read dummy character to release bus */
                I2C_HAL_ReadByte(instance);

                transmitting_slave = false;
                slaveBufferIndex = 0;
                slaveBufferLength = 0;
            }
            else /* ACK from receiver.*/
            {
                transmitting_slave = true;
            }
        }
        /* Handle receive */
        else
        {
            /* Get byte from data register */
            I2C_HAL_SendAck(instance);
            i2cData = I2C_HAL_ReadByte(instance);
            if(slaveBufferLength < BUFFER_LENGTH)
                slaveBuffer[slaveBufferLength++] = i2cData;
        }
    }

    if (transmitting_slave)
    {
        /* Send byte to data register */
        if (slaveBufferIndex < slaveBufferLength)
        {
            I2C_HAL_WriteByte(instance, slaveBuffer[slaveBufferIndex++]);
            if (slaveBufferIndex >= slaveBufferLength)
            {
                slaveBufferIndex = 0;
                slaveBufferLength = 0;
                transmitting_slave = false;
            }
        }
        else
            transmitting_slave = false;
    }
}
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
    if(quantity == 0) return 0;

    uint32_t t0 = millis();

    while(I2C_HAL_GetStatusFlag(instance, kI2CBusBusy) && !I2C_HAL_IsMaster(instance))
    {
        if(millis() - t0 >= 25)
            return 4; //timeout
    }

    if(quantity > BUFFER_LENGTH){
        quantity = BUFFER_LENGTH;
    }

    rxBufferQuantity = quantity;
    rxBufferIndex = 0;
    rxBufferLength = 0;

    uint16_t slaveAddr = (address << 1U) | 1;

    if(!sendAddress(slaveAddr) || master_state != MASTER_STATE_READ_READY)
    {
        I2C_HAL_SendStop(instance);
        I2C_HAL_SetDirMode(instance, kI2CReceive);
        return 0;
    }

    master_send_stop = sendStop;

    master_state = MASTER_STATE_IDLE;

    I2C_HAL_SetDirMode(instance, kI2CReceive);

    /* Send NAK if only one byte to read. */
    if (rxBufferQuantity == 0x1U)
    {
        I2C_HAL_SendNak(instance);
    }
    else
    {
        I2C_HAL_SendAck(instance);
    }

    I2C_HAL_ReadByte(instance);

    t0 = millis();

    while(master_state == MASTER_STATE_IDLE)
    {
        if(millis() - t0 >= 25)
        {
            rxBufferIndex = 0;
            rxBufferLength = 0;
            I2C_HAL_SendStop(instance);
            I2C_HAL_SetDirMode(instance, kI2CReceive);
            return 0; //timeout
        }
    }

    if(master_state == MASTER_STATE_COMPLETE)
    {
        rxBufferIndex = 0;
        return rxBufferLength;
    }
    else
    {
        rxBufferIndex = 0;
        rxBufferLength = 0;
        rxBufferQuantity = 0;
        I2C_HAL_SendStop(instance);
        I2C_HAL_SetDirMode(instance, kI2CReceive);
        return 0; //timeout
    }
}
Exemplo n.º 15
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_HAL_MasterSendDataPolling
 * Description   : Performs a polling send transaction on the I2C bus.
 *
 *END*/
i2c_status_t I2C_HAL_MasterSendDataPolling(I2C_Type * base,
                                           uint16_t slaveAddr,
                                           const uint8_t * cmdBuff,
                                           uint32_t cmdSize,
                                           const uint8_t * txBuff,
                                           uint32_t txSize)
{
    uint16_t slaveAddress;
    slaveAddress = (slaveAddr << 1U) & 0x00FFU;

     /** Return if current I2C is already set as master. */
    if (I2C_BRD_C1_MST(base))
    {
        return kStatus_I2C_Busy;
    }

     /** Set direction to send. */
    I2C_HAL_SetDirMode(base, kI2CSend);

     /** Generate START signal. */
    I2C_HAL_SendStart(base);

     /** Send slave address */
    if (!I2C_HAL_WriteByteBlocking(base, slaveAddress))
    {
         /** Send STOP if no ACK received */
        I2C_HAL_SendStop(base);
        return kStatus_I2C_ReceivedNak;
    }

     /** Send CMD buffer */
    if (cmdBuff != NULL)
    {
        while (cmdSize--)
        {
            if (!I2C_HAL_WriteByteBlocking(base, *cmdBuff--))
            {
                 /** Send STOP if no ACK received */
                I2C_HAL_SendStop(base);
                return kStatus_I2C_ReceivedNak;
            }
        }
    }

     /** Send data buffer */
    while (txSize--)
    {
        if (!I2C_HAL_WriteByteBlocking(base, *txBuff++))
        {
             /** Send STOP if no ACK received */
            I2C_HAL_SendStop(base);
            return kStatus_I2C_ReceivedNak;
        }
    }

     /** Generate STOP signal. */
    I2C_HAL_SendStop(base);

     /** Set direction back to receive. */
    I2C_HAL_SetDirMode(base, kI2CReceive);

    return kStatus_I2C_Success;
}
Exemplo n.º 16
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_HAL_MasterReceiveDataPolling
 * Description   : Performs a polling receive transaction on the I2C bus.
 *
 *END*/
i2c_status_t I2C_HAL_MasterReceiveDataPolling(I2C_Type * base,
                                              uint16_t slaveAddr,
                                              const uint8_t * cmdBuff,
                                              uint32_t cmdSize,
                                              uint8_t * rxBuff,
                                              uint32_t rxSize)
{
    int32_t i;
    uint8_t directionBit, address;

     /** Return if current I2C is already set as master. */
    if (I2C_BRD_C1_MST(base))
    {
        return kStatus_I2C_Busy;
    }

     /** Get r/w bit according to CMD buffer setting
     * read is 1, write is 0. */
    directionBit = (cmdBuff) ? 0x0U : 0x1U;

    address = (uint8_t)slaveAddr << 1U;

     /** Set direction to send */
    I2C_HAL_SetDirMode(base, kI2CSend);

     /** Generate START signal. */
    I2C_HAL_SendStart(base);

     /** Send slave address */
    if (!I2C_HAL_WriteByteBlocking(base, address | directionBit))
    {
         /** Send STOP if no ACK received */
        I2C_HAL_SendStop(base);
        return kStatus_I2C_ReceivedNak;
    }

     /** Send CMD buffer */
    if (cmdBuff != NULL)
    {
        while (cmdSize--)
        {
            if (!I2C_HAL_WriteByteBlocking(base, *cmdBuff--))
            {
                 /** Send STOP if no ACK received */
                I2C_HAL_SendStop(base);
                return kStatus_I2C_ReceivedNak;
            }
        }

         /** Need to generate a repeat start before changing to receive. */
        I2C_HAL_SendStart(base);

         /** Send slave address again */
        if (!I2C_HAL_WriteByteBlocking(base, address | 1U))
        {
             /** Send STOP if no ACK received */
            I2C_HAL_SendStop(base);
            return kStatus_I2C_ReceivedNak;
        }
    }

     /** Change direction to receive. */
    I2C_HAL_SetDirMode(base, kI2CReceive);

     /** Send NAK if only one byte to read. */
    if (rxSize == 0x1U)
    {
        I2C_HAL_SendNak(base);
    }
    else
    {
        I2C_HAL_SendAck(base);
    }

     /** Dummy read to trigger receive of next byte. */
    I2C_HAL_ReadByteBlocking(base);

     /** Receive data */
    for(i=rxSize-1; i>=0; i--)
    {
        switch (i)
        {
            case 0x0U:
                 /** Generate STOP signal. */
                I2C_HAL_SendStop(base);
                break;
            case 0x1U:
                 /** For the byte before last, we need to set NAK */
                I2C_HAL_SendNak(base);
                break;
            default :
                I2C_HAL_SendAck(base);
                break;
        }

         /** Read recently received byte into buffer and update buffer index */
        if (i==0)
        {
            *rxBuff++ = I2C_HAL_ReadByte(base);
        }
        else
        {
            *rxBuff++ = I2C_HAL_ReadByteBlocking(base);
        }
    }

    return kStatus_I2C_Success;
}