Exemplo n.º 1
0
/*******************************************************************************
* Function Name: HandleAddress
****************************************************************************//**
*
* Prepares the EZI2C slave for the following read or write transfer after the
* matched address was received.
*
* \param base
* The pointer to the EZI2C SCB instance.
*
* \param context
* The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
* by the user. The structure is used during the EZI2C operation for internal
* configuration and data retention. The user must not modify anything
* in this structure.
*
*******************************************************************************/
static void HandleAddress(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
{
    /* Default actions: ACK address 1 */
    uint32_t cmd = SCB_I2C_S_CMD_S_ACK_Msk;
    context->addr1Active = true;

    if (0U != context->address2)
    {
        /* Get an address from the RX FIFO and make it a 7-bit address */
        uint32_t address = (Cy_SCB_ReadRxFifo(base) >> 1UL);
        Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);

        /* Decide whether the address matches */
        if ((address == context->address1) || (address == context->address2))
        {
            /* ACK the address */
            if (address == context->address2)
            {
                context->addr1Active = false;
            }

            /* Clear and enable the stop interrupt source */
            Cy_SCB_ClearSlaveInterrupt  (base, CY_SCB_SLAVE_INTR_I2C_STOP);
            Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR);
        }
        else
        {
            /* NACK the address */
            cmd = SCB_I2C_S_CMD_S_NACK_Msk;

            /* Disable the stop interrupt source */
            Cy_SCB_SetI2CInterruptMask(base, CY_SCB_EZI2C_SLAVE_INTR_NO_STOP);
        }
    }
Exemplo n.º 2
0
int  i2c_start(i2c_t *obj_in)
{
    i2c_obj_t *obj = OBJ_P(obj_in);

    if (CY_SCB_I2C_IDLE == obj->context.state) {
        /* Set the read or write direction */
        obj->context.state = CY_SCB_I2C_MASTER_ADDR;

        /* Clean up the hardware before a transfer. Note RX FIFO is empty at here */
        Cy_SCB_ClearMasterInterrupt(obj->base, CY_SCB_I2C_MASTER_INTR_ALL);
        Cy_SCB_ClearRxInterrupt(obj->base, CY_SCB_RX_INTR_NOT_EMPTY);
        Cy_SCB_ClearTxFifo(obj->base);

        /* Generate a Start and send address byte */
        SCB_I2C_M_CMD(obj->base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;

        /* Wait until Start is generated */
        while (0 != (SCB_I2C_M_CMD(obj->base) & SCB_I2C_M_CMD_M_START_ON_IDLE_Msk)) {
        }

        return 0;
    }

    return (-1);
}
Exemplo n.º 3
0
/*******************************************************************************
* Function Name: Cy_SCB_EZI2C_Interrupt
****************************************************************************//**
*
* This is the interrupt function for the SCB configured in the EZI2C mode.
* This function must be called inside the user-defined interrupt service
* routine to make the EZI2C slave work.
*
* \param base
* The pointer to the EZI2C SCB instance.
*
* \param context
* The pointer to the context structure \ref cy_stc_scb_ezi2c_context_t allocated
* by the user. The structure is used during the EZI2C operation for internal
* configuration and data retention. The user must not modify anything
* in this structure.
*
*******************************************************************************/
void Cy_SCB_EZI2C_Interrupt(CySCB_Type *base, cy_stc_scb_ezi2c_context_t *context)
{
    uint32_t slaveIntrStatus;

    /* Handle an I2C wake-up event */
    if (0UL != (CY_SCB_I2C_INTR_WAKEUP & Cy_SCB_GetI2CInterruptStatusMasked(base)))
    {
        /* Move from IDLE state, the slave was addressed. Following address match 
        * interrupt continue transfer.
        */
        context->state = CY_SCB_EZI2C_STATE_ADDR;
        
        Cy_SCB_ClearI2CInterrupt(base, CY_SCB_I2C_INTR_WAKEUP);
    }

    /* Get the slave interrupt sources */
    slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);

    /* Handle the error conditions */
    if (0UL != (CY_SCB_EZI2C_SLAVE_INTR_ERROR & slaveIntrStatus))
    {
        HandleErrors(base, context);

        Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_EZI2C_SLAVE_INTR_ERROR);

        /* Trigger the stop handling to complete the transaction */
        slaveIntrStatus |= CY_SCB_SLAVE_INTR_I2C_STOP;
    }
    else
    {
        if ((CY_SCB_EZI2C_STATE_RX_DATA1 == context->state) &&
            (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus)))
        {
            /* Get data from the RX FIFO after Stop is generated */
            Cy_SCB_SetRxInterrupt    (base, CY_SCB_RX_INTR_LEVEL);
            Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
        }
    }

    /* Handle the receive direction (master writes data) */
    if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
    {
        HandleDataReceive(base, context);

        Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
    }

    /* Handle the transaction completion */
    if (0UL != (CY_SCB_SLAVE_INTR_I2C_STOP & slaveIntrStatus))
    {
        HandleStop(base, context);

        Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_STOP);

        /* Update the slave interrupt status */
        slaveIntrStatus = Cy_SCB_GetSlaveInterruptStatusMasked(base);
    }

    /* Handle the address byte */
    if (0UL != (CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH & slaveIntrStatus))
    {
        HandleAddress(base, context);

        Cy_SCB_ClearI2CInterrupt  (base, CY_SCB_I2C_INTR_WAKEUP);
        Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_I2C_ADDR_MATCH);
    }

    /* Handle the transmit direction (master reads data) */
    if (0UL != (CY_SCB_TX_INTR_LEVEL & Cy_SCB_GetTxInterruptStatusMasked(base)))
    {
        HandleDataTransmit(base, context);

        Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
    }
}