/******************************************************************************* * Function Name: I2C_1_I2CSlaveSetAddress ******************************************************************************** * * Summary: * Sets the I2C slave address. * * Parameters: * address: I2C slave address for the primary device. This value may be any * address between 0 and 127. * * Return: * None * *******************************************************************************/ void I2C_1_I2CSlaveSetAddress(uint32 address) { uint32 matchReg; matchReg = I2C_1_RX_MATCH_REG; matchReg &= ((uint32) ~I2C_1_RX_MATCH_ADDR_MASK); /* Clear address bits */ matchReg |= ((uint32) I2C_1_GET_I2C_8BIT_ADDRESS(address)); I2C_1_RX_MATCH_REG = matchReg; }
/******************************************************************************* * Function Name: I2C_1_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_1_mstrStatus - used to store current status of I2C Master. * I2C_1_state - used to store current state of software FSM. * I2C_1_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2C_1_mstrWrBufPtr - used to store pointer to master write buffer. * I2C_1_mstrWrBufIndex - used to current index within master write * buffer. * I2C_1_mstrWrBufSize - used to store master write buffer size. * *******************************************************************************/ uint32 I2C_1_I2CMasterWriteBuf(uint32 slaveAddress, uint8 * wrData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2C_1_I2C_MSTR_NOT_READY; if(NULL != wrData) /* Check buffer pointer */ { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { I2C_1_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY) ? I2C_1_I2C_MSTR_BUS_BUSY : I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_I2C_FSM_HALT) { I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_XFER_HALT; errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check if master is ready to start */ if(I2C_1_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ /* Set up write transaction */ I2C_1_state = I2C_1_I2C_FSM_MSTR_WR_ADDR; I2C_1_mstrWrBufIndexTmp = 0u; I2C_1_mstrWrBufIndex = 0u; I2C_1_mstrWrBufSize = cnt; I2C_1_mstrWrBufPtr = (volatile uint8 *) wrData; I2C_1_mstrControl = (uint8) mode; slaveAddress = I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress); I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_WR_CMPLT; I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); I2C_1_ClearTxInterruptSource(I2C_1_INTR_TX_UNDERFLOW); /* The TX and RX FIFO have to be EMPTY */ /* Generate Start or ReStart */ if(I2C_1_CHECK_I2C_MODE_RESTART(mode)) { I2C_1_I2C_MASTER_GENERATE_RESTART; I2C_1_TX_FIFO_WR_REG = slaveAddress; } else { I2C_1_TX_FIFO_WR_REG = slaveAddress; I2C_1_I2C_MASTER_GENERATE_START; } /* Catch when address is sent */ I2C_1_SetTxInterruptMode(I2C_1_INTR_TX_UNDERFLOW); } I2C_1_EnableInt(); /* Release lock */ return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_I2CMasterSendRestart ******************************************************************************** * * Summary: * Generates Restart condition and sends slave address with read/write bit. * This function is blocking and does not return until start condition and * address 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_1_state - used to store current state of software FSM. * *******************************************************************************/ uint32 I2C_1_I2CMasterSendRestart(uint32 slaveAddress, uint32 bitRnW) { uint32 resetIp; uint32 errStatus; resetIp = 0u; errStatus = I2C_1_I2C_MSTR_NOT_READY; /* Check FSM state before generating ReStart condition */ if(I2C_1_CHECK_I2C_MASTER_ACTIVE) { slaveAddress = I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress); if(0u == bitRnW) /* Write direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_WR_DATA; } else /* Read direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_RD_DATA; slaveAddress |= I2C_1_I2C_READ_FLAG; } /* TX and RX FIFO have to be EMPTY */ /* Clean-up interrupt status */ I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); /* A proper ReStart sequence is: generate ReStart, then put an address byte in the TX FIFO. * Otherwise the master treats the address in the TX FIFO as a data byte if a previous transfer is write. * The write transfer continues instead of ReStart. */ I2C_1_I2C_MASTER_GENERATE_RESTART; while(I2C_1_CHECK_I2C_MASTER_CMD(I2C_1_I2C_MASTER_CMD_M_START)) { /* Wait until ReStart has been generated */ } /* Put address into TX FIFO */ I2C_1_TX_FIFO_WR_REG = slaveAddress; /* Wait for address to be transferred */ while(!I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_INTR_MASTER_I2C_BUS_ERROR)) { /* Wait until address has been transferred */ } /* Check results of address phase */ if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK)) { errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_NACK)) { errStatus = I2C_1_I2C_MSTR_ERR_LB_NAK; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ARB_LOST)) { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_ARB_LOST; resetIp = I2C_1_I2C_RESET_ERROR; } else /* I2C_1_INTR_MASTER_I2C_BUS_ERROR set is else condition */ { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_BUS_ERR; resetIp = I2C_1_I2C_RESET_ERROR; } I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_INTR_MASTER_I2C_BUS_ERROR); /* Reset block in case of: LOST_ARB or BUS_ERR */ if(0u != resetIp) { I2C_1_SCB_SW_RESET; } } return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_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: * Erorr status. * * Global variables: * I2C_1_state - used to store current state of software FSM. * *******************************************************************************/ uint32 I2C_1_I2CMasterSendStart(uint32 slaveAddress, uint32 bitRnW) { uint32 resetIp; uint32 errStatus; resetIp = 0u; errStatus = I2C_1_I2C_MSTR_NOT_READY; /* Check FSM state before generating Start condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { /* If bus is free, generate Start condition */ if(I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY)) { errStatus = I2C_1_I2C_MSTR_BUS_BUSY; } else { I2C_1_DisableInt(); /* Lock from interruption */ #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ slaveAddress = I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress); if(0u == bitRnW) /* Write direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_WR_DATA; } else /* Read direction */ { I2C_1_state = I2C_1_I2C_FSM_MSTR_RD_DATA; slaveAddress |= I2C_1_I2C_READ_FLAG; } /* TX and RX FIFO have to be EMPTY */ I2C_1_TX_FIFO_WR_REG = slaveAddress; /* Put address in TX FIFO */ I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); I2C_1_I2C_MASTER_GENERATE_START; while(!I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_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_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ACK)) { errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_NACK)) { errStatus = I2C_1_I2C_MSTR_ERR_LB_NAK; } else if(I2C_1_CHECK_INTR_MASTER(I2C_1_INTR_MASTER_I2C_ARB_LOST)) { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_ARB_LOST; resetIp = I2C_1_I2C_RESET_ERROR; } else /* I2C_1_INTR_MASTER_I2C_BUS_ERROR set is else condition */ { I2C_1_state = I2C_1_I2C_FSM_IDLE; errStatus = I2C_1_I2C_MSTR_ERR_BUS_ERR; resetIp = I2C_1_I2C_RESET_ERROR; } I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_I2C_ACK | I2C_1_INTR_MASTER_I2C_NACK | I2C_1_INTR_MASTER_I2C_ARB_LOST | I2C_1_INTR_MASTER_I2C_BUS_ERROR); /* Reset block in case of: LOST_ARB or BUS_ERR */ if(0u != resetIp) { I2C_1_SCB_SW_RESET; } } } return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_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_1_mstrStatus - used to store current status of I2C Master. * I2C_1_state - used to store current state of software FSM. * I2C_1_mstrControl - used to control master end of transaction with * or without the Stop generation. * I2C_1_mstrRdBufPtr - used to store pointer to master write buffer. * I2C_1_mstrRdBufIndex - used to current index within master write * buffer. * I2C_1_mstrRdBufSize - used to store master write buffer size. * *******************************************************************************/ uint32 I2C_1_I2CMasterReadBuf(uint32 slaveAddress, uint8 * rdData, uint32 cnt, uint32 mode) { uint32 errStatus; errStatus = I2C_1_I2C_MSTR_NOT_READY; if(NULL != rdData) { /* Check FSM state and bus before generating Start/ReStart condition */ if(I2C_1_CHECK_I2C_FSM_IDLE) { I2C_1_DisableInt(); /* Lock from interruption */ /* Check bus state */ errStatus = I2C_1_CHECK_I2C_STATUS(I2C_1_I2C_STATUS_BUS_BUSY) ? I2C_1_I2C_MSTR_BUS_BUSY : I2C_1_I2C_MSTR_NO_ERROR; } else if(I2C_1_CHECK_I2C_FSM_HALT) { I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_XFER_HALT; errStatus = I2C_1_I2C_MSTR_NO_ERROR; } else { /* Unexpected FSM state: exit */ } } /* Check master ready to proceed */ if(I2C_1_I2C_MSTR_NO_ERROR == errStatus) /* No error proceed */ { #if (!I2C_1_CY_SCBIP_V0 && \ I2C_1_I2C_MULTI_MASTER_SLAVE_CONST && I2C_1_I2C_WAKE_ENABLE_CONST) I2C_1_I2CMasterDisableEcAm(); #endif /* (!I2C_1_CY_SCBIP_V0) */ /* Set up read transaction */ I2C_1_state = I2C_1_I2C_FSM_MSTR_RD_ADDR; I2C_1_mstrRdBufIndex = 0u; I2C_1_mstrRdBufSize = cnt; I2C_1_mstrRdBufPtr = (volatile uint8 *) rdData; I2C_1_mstrControl = (uint8) mode; slaveAddress = (I2C_1_GET_I2C_8BIT_ADDRESS(slaveAddress) | I2C_1_I2C_READ_FLAG); I2C_1_mstrStatus &= (uint16) ~I2C_1_I2C_MSTAT_RD_CMPLT; I2C_1_ClearMasterInterruptSource(I2C_1_INTR_MASTER_ALL); /* TX and RX FIFO have to be EMPTY */ /* Generate Start or ReStart */ if(I2C_1_CHECK_I2C_MODE_RESTART(mode)) { I2C_1_I2C_MASTER_GENERATE_RESTART; I2C_1_TX_FIFO_WR_REG = (slaveAddress); } else { I2C_1_TX_FIFO_WR_REG = (slaveAddress); I2C_1_I2C_MASTER_GENERATE_START; } /* Prepare reading */ if(I2C_1_mstrRdBufSize < I2C_1_I2C_FIFO_SIZE) /* Reading byte-by-byte */ { I2C_1_SetRxInterruptMode(I2C_1_INTR_RX_NOT_EMPTY); } else /* Receive RX FIFO chunks */ { I2C_1_ENABLE_MASTER_AUTO_DATA_ACK; I2C_1_SetRxInterruptMode(I2C_1_INTR_RX_FULL); } } I2C_1_EnableInt(); /* Release lock */ return(errStatus); }
/******************************************************************************* * Function Name: I2C_1_I2CInit ******************************************************************************** * * Summary: * Configures the SCB for I2C operation. * * Parameters: * config: Pointer to a structure that contains the following ordered list of * fields. These fields match the selections available in the * customizer. * * Return: * None * *******************************************************************************/ void I2C_1_I2CInit(const I2C_1_I2C_INIT_STRUCT *config) { if(NULL == config) { CYASSERT(0u != 0u); /* Halt execution due bad function parameter */ } else { /* Configure pins */ I2C_1_SetPins(I2C_1_SCB_MODE_I2C, I2C_1_DUMMY_PARAM, I2C_1_DUMMY_PARAM); /* Store internal configuration */ I2C_1_scbMode = (uint8) I2C_1_SCB_MODE_I2C; I2C_1_scbEnableWake = (uint8) config->enableWake; I2C_1_scbEnableIntr = (uint8) I2C_1_SCB_IRQ_INTERNAL; I2C_1_mode = (uint8) config->mode; I2C_1_acceptAddr = (uint8) config->acceptAddr; /* Configure I2C interface */ I2C_1_CTRL_REG = I2C_1_GET_CTRL_ADDR_ACCEPT(config->acceptAddr) | I2C_1_GET_CTRL_EC_AM_MODE (config->enableWake); I2C_1_I2C_CTRL_REG = I2C_1_GET_I2C_CTRL_HIGH_PHASE_OVS(config->oversampleHigh) | I2C_1_GET_I2C_CTRL_LOW_PHASE_OVS (config->oversampleLow) | I2C_1_GET_I2C_CTRL_SL_MSTR_MODE (config->mode) | I2C_1_I2C_CTRL; #if(I2C_1_CY_SCBIP_V0) /* Adjust SDA filter settings. Ticket ID#150521 */ I2C_1_SET_I2C_CFG_SDA_FILT_TRIM(I2C_1_EC_AM_I2C_CFG_SDA_FILT_TRIM); #endif /* (I2C_1_CY_SCBIP_V0) */ /* Configure RX direction */ I2C_1_RX_CTRL_REG = I2C_1_GET_RX_CTRL_MEDIAN(config->enableMedianFilter) | I2C_1_I2C_RX_CTRL; I2C_1_RX_FIFO_CTRL_REG = I2C_1_CLEAR_REG; /* Set default address and mask */ I2C_1_RX_MATCH_REG = ((I2C_1_I2C_SLAVE) ? (I2C_1_GET_I2C_8BIT_ADDRESS(config->slaveAddr) | I2C_1_GET_RX_MATCH_MASK(config->slaveAddrMask)) : (I2C_1_CLEAR_REG)); /* Configure TX direction */ I2C_1_TX_CTRL_REG = I2C_1_I2C_TX_CTRL; I2C_1_TX_FIFO_CTRL_REG = I2C_1_CLEAR_REG; /* Configure interrupt with I2C handler but do not enable it */ CyIntDisable (I2C_1_ISR_NUMBER); CyIntSetPriority(I2C_1_ISR_NUMBER, I2C_1_ISR_PRIORITY); (void) CyIntSetVector(I2C_1_ISR_NUMBER, &I2C_1_I2C_ISR); /* Configure interrupt sources */ #if(!I2C_1_CY_SCBIP_V1_I2C_ONLY) I2C_1_INTR_SPI_EC_MASK_REG = I2C_1_NO_INTR_SOURCES; #endif /* (!I2C_1_CY_SCBIP_V1_I2C_ONLY) */ I2C_1_INTR_I2C_EC_MASK_REG = I2C_1_NO_INTR_SOURCES; I2C_1_INTR_RX_MASK_REG = I2C_1_NO_INTR_SOURCES; I2C_1_INTR_TX_MASK_REG = I2C_1_NO_INTR_SOURCES; I2C_1_INTR_SLAVE_MASK_REG = ((I2C_1_I2C_SLAVE) ? (I2C_1_I2C_INTR_SLAVE_MASK) : (I2C_1_CLEAR_REG)); I2C_1_INTR_MASTER_MASK_REG = ((I2C_1_I2C_MASTER) ? (I2C_1_I2C_INTR_MASTER_MASK) : (I2C_1_CLEAR_REG)); /* Configure global variables */ I2C_1_state = I2C_1_I2C_FSM_IDLE; /* Internal slave variables */ I2C_1_slStatus = 0u; I2C_1_slRdBufIndex = 0u; I2C_1_slWrBufIndex = 0u; I2C_1_slOverFlowCount = 0u; /* Internal master variables */ I2C_1_mstrStatus = 0u; I2C_1_mstrRdBufIndex = 0u; I2C_1_mstrWrBufIndex = 0u; } }