/*******************************************************************************
* Function Name: I2C_I2CResposeInsert
****************************************************************************//**
*
*  Releases the read buffer to be read when a response is copied to the buffer
*  and a new read transaction starts.
*  Closes the read buffer when write transaction is started.
*
* \globalvars
*  I2C_applyBuffer - the flag to release the buffer with a response
*  to be read by the host.
*
*******************************************************************************/
static void I2C_I2CResposeInsert(void)
{
    if (I2C_CHECK_INTR_SLAVE_MASKED(I2C_INTR_SLAVE_I2C_ADDR_MATCH))
    {
        if (I2C_CHECK_I2C_STATUS(I2C_I2C_STATUS_S_READ))
        {
            /* Address phase, host reads: release read buffer */
            if (0u != I2C_applyBuffer)
            {
                I2C_slRdBufSize  = I2C_applyBuffer;
                I2C_slRdBufIndex = 0u;
                I2C_applyBuffer  = 0u;
            }
        }
        else
        {
            /* Address phase, host writes: close read buffer */
            if (I2C_slRdBufIndex != I2C_slRdBufSize)
            {
                I2C_slRdBufIndex = I2C_slRdBufSize;
            }
        }
    }
}
Example #2
0
/*******************************************************************************
* Function Name: I2C_I2CReStartGeneration
********************************************************************************
*
* Summary:
*  Generates a ReStart condition:
*  SCB IP V1 and later: Generates ReStart using the scb IP functionality
*    Sets the I2C_MASTER_CMD_M_START and I2C_MASTER_CMD_M_NACK (if the previous
*    transaction was read) bits in the SCB.I2C_MASTER_CMD register.
*    This combination forces the master to generate ReStart.
*
*  SCB IP V0: Generates Restart using the GPIO and scb IP functionality.
*   After the master completes write or read, the SCL is stretched.
*   The master waits until SDA line is released by the slave. Then the GPIO
*   function is enabled and the scb IP disabled as it already does not drive
*   the bus. In case of the previous transfer was read, the NACK is generated
*   by the GPIO. The delay of tLOW is added to manage the hold time.
*   Set I2C_M_CMD.START and enable the scb IP. The ReStart generation
*   is started after the I2C function is enabled for the SCL.
*   Note1: the scb IP due re-enable generates Start but on the I2C bus it
*          appears as ReStart.
*   Note2: the I2C_M_CMD.START is queued if scb IP is disabled.
*   Note3: the I2C_STATUS_M_READ is cleared is address was NACKed before.
*
* Parameters:
*  None
*
* Return:
*  None
*
* Side Effects:
*  SCB IP V0: The NACK generation by the GPIO may cause a greater SCL period
*             than expected for the selected master data rate.
*
*******************************************************************************/
void I2C_I2CReStartGeneration(void)
{
#if(I2C_CY_SCBIP_V0)
    /* Generates Restart use GPIO and scb IP functionality. Ticket ID#143715,
    ID#145238 and ID#173656 */
    uint32 status = I2C_I2C_STATUS_REG;

    while(I2C_WAIT_SDA_SET_HIGH)
    {
        /* Wait when slave release SDA line: SCL tHIGH is complete */
    }

    /* Prepare DR register to drive SCL line */
    I2C_SET_I2C_SCL_DR(I2C_I2C_SCL_LOW);

    /* Switch HSIOM to GPIO: SCL goes low */
    I2C_SET_I2C_SCL_HSIOM_SEL(I2C_HSIOM_GPIO_SEL);

    /* Disable SCB block */
    I2C_CTRL_REG &= (uint32) ~I2C_CTRL_ENABLED;

    if(0u != (status & I2C_I2C_STATUS_M_READ))
    {
        /* Generate NACK use GPIO functionality */
        I2C_SET_I2C_SCL_DR(I2C_I2C_SCL_LOW);
        CyDelayUs(I2C_I2C_TLOW_TIME); /* Count tLOW */

        I2C_SET_I2C_SCL_DR(I2C_I2C_SCL_HIGH);
        while(I2C_WAIT_SCL_SET_HIGH)
        {
            /* Wait until slave releases SCL in case if it stretches */
        }
        CyDelayUs(I2C_I2C_THIGH_TIME); /* Count tHIGH */
    }

    /* Count tLOW as hold time for write and read */
    I2C_SET_I2C_SCL_DR(I2C_I2C_SCL_LOW);
    CyDelayUs(I2C_I2C_TLOW_TIME); /* Count tLOW */

    /* Set command for Start generation: it will appear */
    I2C_I2C_MASTER_CMD_REG = I2C_I2C_MASTER_CMD_M_START;

    /* Enable SCB block */
    I2C_CTRL_REG |= (uint32) I2C_CTRL_ENABLED;

    /* Switch HSIOM to I2C: */
    I2C_SET_I2C_SCL_HSIOM_SEL(I2C_HSIOM_I2C_SEL);

    /* Revert SCL DR register */
    I2C_SET_I2C_SCL_DR(I2C_I2C_SCL_HIGH);
#else
    uint32 cmd;

    /* Generates ReStart use scb IP functionality */
    cmd  = I2C_I2C_MASTER_CMD_M_START;
    cmd |= I2C_CHECK_I2C_STATUS(I2C_I2C_STATUS_M_READ) ?
                (I2C_I2C_MASTER_CMD_M_NACK) : (0u);

    I2C_I2C_MASTER_CMD_REG = cmd;
#endif /* (I2C_CY_SCBIP_V1) */
}
Example #3
0
/*******************************************************************************
* Function Name: I2C_I2CMasterWriteBuf
********************************************************************************
*
* Summary:
* Automatically writes an entire buffer of data to a slave device.
* Once the data transfer is initiated by this function, further data transfer
* is handled by the included ISR.
* Enables the I2C interrupt and clears SCB_ I2C_MSTAT_WR_CMPLT status.
*
* Parameters:
*  slaveAddr: 7-bit slave address.
*  xferData:  Pointer to buffer of data to be sent.
*  cnt:       Size of buffer to send.
*  mode:      Transfer mode defines: start or restart condition generation at
*             begin of the transfer and complete the transfer or halt before
*             generating a stop.
*
* Return:
*  Error status.
*
* Global variables:
*  I2C_mstrStatus  - used to store current status of I2C Master.
*  I2C_state       - used to store current state of software FSM.
*  I2C_mstrControl - used to control master end of transaction with
*  or without the Stop generation.
*  I2C_mstrWrBufPtr - used to store pointer to master write buffer.
*  I2C_mstrWrBufIndex - used to current index within master write
*  buffer.
*  I2C_mstrWrBufSize - used to store master write buffer size.
*
*******************************************************************************/
uint32 I2C_I2CMasterWriteBuf(uint32 slaveAddress, uint8 * wrData, uint32 cnt, uint32 mode)
{
    uint32 errStatus;

    errStatus = I2C_I2C_MSTR_NOT_READY;

    if(NULL != wrData)  /* Check buffer pointer */
    {
        /* Check FSM state and bus before generating Start/ReStart condition */
        if(I2C_CHECK_I2C_FSM_IDLE)
        {
            I2C_DisableInt();  /* Lock from interruption */

            /* Check bus state */
            errStatus = I2C_CHECK_I2C_STATUS(I2C_I2C_STATUS_BUS_BUSY) ?
                            I2C_I2C_MSTR_BUS_BUSY : I2C_I2C_MSTR_NO_ERROR;
        }
        else if(I2C_CHECK_I2C_FSM_HALT)
        {
            I2C_mstrStatus &= (uint16) ~I2C_I2C_MSTAT_XFER_HALT;
                              errStatus  = I2C_I2C_MSTR_NO_ERROR;
        }
        else
        {
            /* Unexpected FSM state: exit */
        }
    }

    /* Check if master is ready to start  */
    if(I2C_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */
    {
    #if (!I2C_CY_SCBIP_V0 && \
        I2C_I2C_MULTI_MASTER_SLAVE_CONST && I2C_I2C_WAKE_ENABLE_CONST)
            I2C_I2CMasterDisableEcAm();
    #endif /* (!I2C_CY_SCBIP_V0) */

        /* Set up write transaction */
        I2C_state = I2C_I2C_FSM_MSTR_WR_ADDR;
        I2C_mstrWrBufIndexTmp = 0u;
        I2C_mstrWrBufIndex    = 0u;
        I2C_mstrWrBufSize     = cnt;
        I2C_mstrWrBufPtr      = (volatile uint8 *) wrData;
        I2C_mstrControl       = (uint8) mode;

        slaveAddress = I2C_GET_I2C_8BIT_ADDRESS(slaveAddress);

        I2C_mstrStatus &= (uint16) ~I2C_I2C_MSTAT_WR_CMPLT;

        I2C_ClearMasterInterruptSource(I2C_INTR_MASTER_ALL);
        I2C_ClearTxInterruptSource(I2C_INTR_TX_UNDERFLOW);

        /* The TX and RX FIFO have to be EMPTY */

        /* Enable interrupt source to catch when address is sent */
        I2C_SetTxInterruptMode(I2C_INTR_TX_UNDERFLOW);

        /* Generate Start or ReStart */
        if(I2C_CHECK_I2C_MODE_RESTART(mode))
        {
            I2C_I2C_MASTER_GENERATE_RESTART;
            I2C_TX_FIFO_WR_REG = slaveAddress;
        }
        else
        {
            I2C_TX_FIFO_WR_REG = slaveAddress;
            I2C_I2C_MASTER_GENERATE_START;
        }
    }

    I2C_EnableInt();   /* Release lock */

    return(errStatus);
}
Example #4
0
/*******************************************************************************
* Function Name: I2C_I2CMasterSendStart
********************************************************************************
*
* Summary:
*  Generates Start condition and sends slave address with read/write bit.
*  Disables the I2C interrupt.
*  This function is blocking and does not return until start condition and
*  address byte are sent and ACK/NACK response is received or errors occurred.
*
* Parameters:
*  slaveAddress: Right justified 7-bit Slave address (valid range 8 to 120).
*  bitRnW:       Direction of the following transfer. It is defined by
*                read/write bit within address byte.
*
* Return:
*  Error status.
*
* Global variables:
*  I2C_state - used to store current state of software FSM.
*
*******************************************************************************/
uint32 I2C_I2CMasterSendStart(uint32 slaveAddress, uint32 bitRnW)
{
    uint32  resetIp;
    uint32 errStatus;

    resetIp   = 0u;
    errStatus = I2C_I2C_MSTR_NOT_READY;

    /* Check FSM state before generating Start condition */
    if(I2C_CHECK_I2C_FSM_IDLE)
    {
        /* If bus is free, generate Start condition */
        if(I2C_CHECK_I2C_STATUS(I2C_I2C_STATUS_BUS_BUSY))
        {
            errStatus = I2C_I2C_MSTR_BUS_BUSY;
        }
        else
        {
            I2C_DisableInt();  /* Lock from interruption */

        #if (!I2C_CY_SCBIP_V0 && \
            I2C_I2C_MULTI_MASTER_SLAVE_CONST && I2C_I2C_WAKE_ENABLE_CONST)
            I2C_I2CMasterDisableEcAm();
        #endif /* (!I2C_CY_SCBIP_V0) */

            slaveAddress = I2C_GET_I2C_8BIT_ADDRESS(slaveAddress);

            if(0u == bitRnW) /* Write direction */
            {
                I2C_state = I2C_I2C_FSM_MSTR_WR_DATA;
            }
            else /* Read direction */
            {
                I2C_state = I2C_I2C_FSM_MSTR_RD_DATA;
                         slaveAddress |= I2C_I2C_READ_FLAG;
            }

            /* TX and RX FIFO have to be EMPTY */

            I2C_TX_FIFO_WR_REG = slaveAddress; /* Put address in TX FIFO */
            I2C_ClearMasterInterruptSource(I2C_INTR_MASTER_ALL);

            I2C_I2C_MASTER_GENERATE_START;


            while(!I2C_CHECK_INTR_MASTER(I2C_INTR_MASTER_I2C_ACK      |
                                                      I2C_INTR_MASTER_I2C_NACK     |
                                                      I2C_INTR_MASTER_I2C_ARB_LOST |
                                                      I2C_INTR_MASTER_I2C_BUS_ERROR))
            {
                /*
                * Write: wait until address has been transferred
                * Read : wait until address has been transferred, data byte is going to RX FIFO as well.
                */
            }

            /* Check the results of the address phase */
            if(I2C_CHECK_INTR_MASTER(I2C_INTR_MASTER_I2C_ACK))
            {
                errStatus = I2C_I2C_MSTR_NO_ERROR;
            }
            else if(I2C_CHECK_INTR_MASTER(I2C_INTR_MASTER_I2C_NACK))
            {
                errStatus = I2C_I2C_MSTR_ERR_LB_NAK;
            }
            else if(I2C_CHECK_INTR_MASTER(I2C_INTR_MASTER_I2C_ARB_LOST))
            {
                I2C_state = I2C_I2C_FSM_IDLE;
                             errStatus = I2C_I2C_MSTR_ERR_ARB_LOST;
                             resetIp   = I2C_I2C_RESET_ERROR;
            }
            else /* I2C_INTR_MASTER_I2C_BUS_ERROR set is else condition */
            {
                I2C_state = I2C_I2C_FSM_IDLE;
                             errStatus = I2C_I2C_MSTR_ERR_BUS_ERR;
                             resetIp   = I2C_I2C_RESET_ERROR;
            }

            I2C_ClearMasterInterruptSource(I2C_INTR_MASTER_I2C_ACK      |
                                                        I2C_INTR_MASTER_I2C_NACK     |
                                                        I2C_INTR_MASTER_I2C_ARB_LOST |
                                                        I2C_INTR_MASTER_I2C_BUS_ERROR);

            /* Reset block in case of: LOST_ARB or BUS_ERR */
            if(0u != resetIp)
            {
                I2C_SCB_SW_RESET;
            }
        }
    }

    return(errStatus);
}
Example #5
0
/*******************************************************************************
* Function Name: I2C_I2CMasterReadBuf
********************************************************************************
*
* Summary:
*  Automatically reads an entire buffer of data from a slave device.
*  Once the data transfer is initiated by this function, further data transfer
*  is handled by the included ISR.
* Enables the I2C interrupt and clears SCB_ I2C_MSTAT_RD_CMPLT status.
*
* Parameters:
*  slaveAddr: 7-bit slave address.
*  xferData:  Pointer to buffer where to put data from slave.
*  cnt:       Size of buffer to read.
*  mode:      Transfer mode defines: start or restart condition generation at
*             begin of the transfer and complete the transfer or halt before
*             generating a stop.
*
* Return:
*  Error status.
*
* Global variables:
*  I2C_mstrStatus  - used to store current status of I2C Master.
*  I2C_state       - used to store current state of software FSM.
*  I2C_mstrControl - used to control master end of transaction with
*  or without the Stop generation.
*  I2C_mstrRdBufPtr - used to store pointer to master write buffer.
*  I2C_mstrRdBufIndex - used to current index within master write
*  buffer.
*  I2C_mstrRdBufSize - used to store master write buffer size.
*
*******************************************************************************/
uint32 I2C_I2CMasterReadBuf(uint32 slaveAddress, uint8 * rdData, uint32 cnt, uint32 mode)
{
    uint32 errStatus;

    errStatus = I2C_I2C_MSTR_NOT_READY;

    if(NULL != rdData)
    {
        /* Check FSM state and bus before generating Start/ReStart condition */
        if(I2C_CHECK_I2C_FSM_IDLE)
        {
            I2C_DisableInt();  /* Lock from interruption */

            /* Check bus state */
            errStatus = I2C_CHECK_I2C_STATUS(I2C_I2C_STATUS_BUS_BUSY) ?
                            I2C_I2C_MSTR_BUS_BUSY : I2C_I2C_MSTR_NO_ERROR;
        }
        else if(I2C_CHECK_I2C_FSM_HALT)
        {
            I2C_mstrStatus &= (uint16) ~I2C_I2C_MSTAT_XFER_HALT;
                              errStatus  =  I2C_I2C_MSTR_NO_ERROR;
        }
        else
        {
            /* Unexpected FSM state: exit */
        }
    }

    /* Check master ready to proceed */
    if(I2C_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */
    {
        #if (!I2C_CY_SCBIP_V0 && \
        I2C_I2C_MULTI_MASTER_SLAVE_CONST && I2C_I2C_WAKE_ENABLE_CONST)
            I2C_I2CMasterDisableEcAm();
        #endif /* (!I2C_CY_SCBIP_V0) */

        /* Set up read transaction */
        I2C_state = I2C_I2C_FSM_MSTR_RD_ADDR;
        I2C_mstrRdBufIndex = 0u;
        I2C_mstrRdBufSize  = cnt;
        I2C_mstrRdBufPtr   = (volatile uint8 *) rdData;
        I2C_mstrControl    = (uint8) mode;

        slaveAddress = (I2C_GET_I2C_8BIT_ADDRESS(slaveAddress) | I2C_I2C_READ_FLAG);

        I2C_mstrStatus &= (uint16) ~I2C_I2C_MSTAT_RD_CMPLT;

        I2C_ClearMasterInterruptSource(I2C_INTR_MASTER_ALL);

        /* TX and RX FIFO have to be EMPTY */

        /* Prepare reading */
        if(I2C_mstrRdBufSize < I2C_I2C_FIFO_SIZE)
        {
            /* Reading byte-by-byte */
            I2C_SetRxInterruptMode(I2C_INTR_RX_NOT_EMPTY);
        }
        else
        {
            /* Receive RX FIFO chunks */
            I2C_ENABLE_MASTER_AUTO_DATA_ACK;
            I2C_SetRxInterruptMode(I2C_INTR_RX_FULL);
        }

        /* Generate Start or ReStart */
        if(I2C_CHECK_I2C_MODE_RESTART(mode))
        {
            I2C_I2C_MASTER_GENERATE_RESTART;
            I2C_TX_FIFO_WR_REG = (slaveAddress);
        }
        else
        {
            I2C_TX_FIFO_WR_REG = (slaveAddress);
            I2C_I2C_MASTER_GENERATE_START;
        }
    }

    I2C_EnableInt();   /* Release lock */

    return(errStatus);
}