void I2C_SetMode(I2C_CHANNEL eCh, I2C_MODE eMode) { HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) &= ~(0x1 << 4); // Disable I2C HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) &= ~(0x3 << 6); // Clear Mode I2C_ClearIntStatus(eCh); I2C_DisableInt(eCh); // Disable Interrupt switch (eMode) { case MASTER_TX_MODE: HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) |= (0x3 << 6); // Set Mode break; case MASTER_RX_MODE: HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) |= (0x2 << 6); // Set Mode break; case SLAVE_TX_MODE: HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) |= (0x1 << 6); // Set Mode break; case SLAVE_RX_MODE: HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) |= (0x0 << 6); // Set Mode break; default: return; } I2C_EnableInt(eCh); HW_REG32(g_aI2c[eCh].uBase, I2C_STAT) |= (0x1 << 4); // Enable I2C }
/******************************************************************************* * Function Name: I2C_I2CMasterClearWriteBuf ******************************************************************************** * * Summary: * Resets the write buffer pointer back to the first byte in the buffer. * * Parameters: * None * * Return: * None * * Global variables: * I2C_mstrRdBufIndex - used to current index within master read * buffer. * I2C_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ void I2C_I2CMasterClearWriteBuf(void) { I2C_DisableInt(); /* Lock from interruption */ I2C_mstrWrBufIndex = 0u; I2C_mstrStatus &= (uint16) ~I2C_I2C_MSTAT_WR_CMPLT; I2C_EnableInt(); /* Release lock */ }
void I2C0_Close(void) { /* Disable I2C0 interrupt and clear corresponding NVIC bit */ I2C_DisableInt(I2C0); NVIC_DisableIRQ(I2C0_IRQn); /* Disable I2C0 and close I2C0 clock */ I2C_Close(I2C0); CLK_DisableModuleClock(I2C0_MODULE); }
/******************************************************************************* * Function Name: I2C_I2CMasterClearStatus ******************************************************************************** * * Summary: * Clears all status flags and returns the master status. * * Parameters: * None * * Return: * Current status of I2C master. * * Global variables: * I2C_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2C_I2CMasterClearStatus(void) { uint32 status; I2C_DisableInt(); /* Lock from interruption */ /* Read and clear master status */ status = (uint32) I2C_mstrStatus; I2C_mstrStatus = I2C_I2C_MSTAT_CLEAR; I2C_EnableInt(); /* Release lock */ return(status); }
/******************************************************************************* * Function Name: I2C_I2CMasterStatus ******************************************************************************** * * Summary: * Returns the master's communication status. * * Parameters: * None * * Return: * Current status of I2C master. * * Global variables: * I2C_mstrStatus - used to store current status of I2C Master. * *******************************************************************************/ uint32 I2C_I2CMasterStatus(void) { uint32 status; I2C_DisableInt(); /* Lock from interruption */ status = (uint32) I2C_mstrStatus; if (I2C_CHECK_I2C_MASTER_ACTIVE) { /* Add status of master pending transaction: MSTAT_XFER_INP */ status |= (uint32) I2C_I2C_MSTAT_XFER_INP; } I2C_EnableInt(); /* Release lock */ return(status); }
void HandleI2CNotifications(CYBLE_GATTC_HANDLE_VALUE_NTF_PARAM_T *I2CDataNotification) { uint8 i; /* Check if its I2C read notitifications */ if(I2CDataNotification->handleValPair.attrHandle == I2CReadDataCharHandle) { /* Disable I2C interrupts before updating the data */ I2C_DisableInt(); /* Update I2C read registers with the notification data*/ for(i=0;i<I2CDataNotification->handleValPair.value.len;i++) rdBuf[i] = I2CDataNotification->handleValPair.value.val[i]; /* Enable I2C interrupts after updating the data */ I2C_EnableInt(); } }
/******************************************************************************* * 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); }
/******************************************************************************* * 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); }
/******************************************************************************* * 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); }
void AppCallBack(uint32 event, void *eventParam) { uint8 i; CYBLE_GATTS_WRITE_REQ_PARAM_T *wrReqParam; switch (event) { case CYBLE_EVT_STACK_ON: /* start advertising */ apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult == CYBLE_ERROR_OK) { #ifdef LED_INDICATION ADV_LED_ON(); #endif /* LED_INDICATION */ } break; case CYBLE_EVT_GAP_DEVICE_DISCONNECTED: sendNotifications = 0; #ifdef ENABLE_I2C_ONLY_WHEN_CONNECTED /* Stop I2C Slave operation */ I2C_Stop(); #endif #ifdef LED_INDICATION /* Indicate disconnect event to user */ DISCON_LED_ON(); CyDelay(3000); #endif /* LED_INDICATION */ /* start advertising */ apiResult = CyBle_GappStartAdvertisement(CYBLE_ADVERTISING_FAST); if(apiResult == CYBLE_ERROR_OK) { #ifdef LED_INDICATION ADV_LED_ON(); #endif /* LED_INDICATION */ } break; case CYBLE_EVT_GATT_CONNECT_IND: #ifdef LED_INDICATION CONNECT_LED_ON(); #endif /* LED_INDICATION */ #ifdef ENABLE_I2C_ONLY_WHEN_CONNECTED /* Start I2C Slave operation */ I2C_Start(); /* Initialize I2C write buffer */ I2C_I2CSlaveInitWriteBuf((uint8 *) wrBuf, I2C_WRITE_BUFFER_SIZE); /* Initialize I2C read buffer */ I2C_I2CSlaveInitReadBuf((uint8 *) rdBuf, I2C_READ_BUFFER_SIZE); #endif break; /* Client may do Write Value or Write Value without Response. Handle both */ case CYBLE_EVT_GATTS_WRITE_REQ: case CYBLE_EVT_GATTS_WRITE_CMD_REQ: wrReqParam = (CYBLE_GATTS_WRITE_REQ_PARAM_T *) eventParam; /* Handling Notification Enable */ if(wrReqParam->handleValPair.attrHandle == CYBLE_I2C_READ_I2C_READ_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE) { CYBLE_GATT_HANDLE_VALUE_PAIR_T I2CNotificationCCDHandle; uint8 I2CCCDValue[2]; /* Extract CCCD Notification enable flag */ sendNotifications = wrReqParam->handleValPair.value.val[0]; /* Write the present I2C notification status to the local variable */ I2CCCDValue[0] = sendNotifications; I2CCCDValue[1] = 0x00; /* Update CCCD handle with notification status data*/ I2CNotificationCCDHandle.attrHandle = CYBLE_I2C_READ_I2C_READ_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE; I2CNotificationCCDHandle.value.val = I2CCCDValue; I2CNotificationCCDHandle.value.len = 2; /* Report data to BLE component for sending data when read by Central device */ CyBle_GattsWriteAttributeValue(&I2CNotificationCCDHandle, 0, &cyBle_connHandle, CYBLE_GATT_DB_LOCALLY_INITIATED); } /* Handling Write data from Client */ else if(wrReqParam->handleValPair.attrHandle == CYBLE_I2C_WRITE_I2C_WRITE_DATA_CHAR_HANDLE) { /* Turn off I2C interrupt before updating read registers */ I2C_DisableInt(); /*The data received from I2C client is extracted */ for(i=0;i<(wrReqParam->handleValPair.value.len);i++) rdBuf[i] = wrReqParam->handleValPair.value.val[i]; /* Turn on I2C interrupt after updating read registers */ I2C_EnableInt(); } if (event == CYBLE_EVT_GATTS_WRITE_REQ) { CyBle_GattsWriteRsp(cyBle_connHandle); } break; default: break; } }
/******************************************************************************* * Function Name: I2C_Stop ******************************************************************************** * * Summary: * Disables I2C hardware and disables I2C interrupt. Disables Active mode power * template bits or clock gating as appropriate. * * Parameters: * None * * Return: * None * *******************************************************************************/ void I2C_Stop(void) { #if((I2C_FF_IMPLEMENTED) || \ (I2C_UDB_IMPLEMENTED && I2C_MODE_SLAVE_ENABLED)) uint8 enableInterrupts; #endif /* ((I2C_FF_IMPLEMENTED) || \ (I2C_UDB_IMPLEMENTED && I2C_MODE_SLAVE_ENABLED)) */ I2C_DisableInt(); I2C_DISABLE_INT_ON_STOP; /* Interrupt on Stop can be enabled by write */ (void) I2C_CSR_REG; /* Clear CSR reg */ #if(I2C_TIMEOUT_ENABLED) I2C_TimeoutStop(); #endif /* End (I2C_TIMEOUT_ENABLED) */ #if(I2C_FF_IMPLEMENTED) #if(CY_PSOC3 || CY_PSOC5LP) /* Store registers which are held in reset when Master and Slave bits are cleared */ #if(I2C_MODE_SLAVE_ENABLED) I2C_backup.addr = I2C_ADDR_REG; #endif /* (I2C_MODE_SLAVE_ENABLED) */ I2C_backup.clkDiv1 = I2C_CLKDIV1_REG; I2C_backup.clkDiv2 = I2C_CLKDIV2_REG; /* Reset FF block */ I2C_CFG_REG &= ((uint8) ~I2C_ENABLE_MS); CyDelayUs(I2C_FF_RESET_DELAY); I2C_CFG_REG |= ((uint8) I2C_ENABLE_MS); /* Restore registers */ #if(I2C_MODE_SLAVE_ENABLED) I2C_ADDR_REG = I2C_backup.addr; #endif /* (I2C_MODE_SLAVE_ENABLED) */ I2C_CLKDIV1_REG = I2C_backup.clkDiv1; I2C_CLKDIV2_REG = I2C_backup.clkDiv2; #endif /* (CY_PSOC3 || CY_PSOC5LP) */ /* Disable power to I2C block */ enableInterrupts = CyEnterCriticalSection(); I2C_ACT_PWRMGR_REG &= ((uint8) ~I2C_ACT_PWR_EN); I2C_STBY_PWRMGR_REG &= ((uint8) ~I2C_STBY_PWR_EN); CyExitCriticalSection(enableInterrupts); #else #if(I2C_MODE_SLAVE_ENABLED) /* Disable slave bit counter */ enableInterrupts = CyEnterCriticalSection(); I2C_COUNTER_AUX_CTL_REG &= ((uint8) ~I2C_CNT7_ENABLE); CyExitCriticalSection(enableInterrupts); #endif /* (I2C_MODE_SLAVE_ENABLED) */ I2C_CFG_REG &= ((uint8) ~I2C_ENABLE_MS); #endif /* (I2C_FF_IMPLEMENTED) */ I2C_ClearPendingInt(); /* Clear interrupt triggers on reset */ I2C_state = I2C_SM_IDLE; /* Reset software FSM */ }
/******************************************************************************* * Function Name: I2C_Stop ******************************************************************************** * * Summary: * Disables I2C hardware and disables I2C interrupt. Disables Active mode power * template bits or clock gating as appropriate. * * Parameters: * None. * * Return: * None. * *******************************************************************************/ void I2C_Stop(void) { I2C_DisableInt(); #if (I2C_TIMEOUT_ENABLED) I2C_TimeoutStop(); #endif /* End (I2C_TIMEOUT_ENABLED) */ #if (I2C_FF_IMPLEMENTED) { uint8 intState; uint16 blockResetCycles; /* Store registers effected by block disable */ I2C_backup.addr = I2C_ADDR_REG; I2C_backup.clkDiv1 = I2C_CLKDIV1_REG; I2C_backup.clkDiv2 = I2C_CLKDIV2_REG; /* Calculate number of cycles to reset block */ blockResetCycles = ((uint16) ((uint16) I2C_CLKDIV2_REG << 8u) | I2C_CLKDIV1_REG) + 1u; /* Disable block */ I2C_CFG_REG &= (uint8) ~I2C_CFG_EN_SLAVE; /* Wait for block reset before disable power */ CyDelayCycles((uint32) blockResetCycles); /* Disable power to block */ intState = CyEnterCriticalSection(); I2C_ACT_PWRMGR_REG &= (uint8) ~I2C_ACT_PWR_EN; I2C_STBY_PWRMGR_REG &= (uint8) ~I2C_STBY_PWR_EN; CyExitCriticalSection(intState); /* Enable block */ I2C_CFG_REG |= (uint8) I2C_ENABLE_MS; /* Restore registers effected by block disable. Ticket ID#198004 */ I2C_ADDR_REG = I2C_backup.addr; I2C_ADDR_REG = I2C_backup.addr; I2C_CLKDIV1_REG = I2C_backup.clkDiv1; I2C_CLKDIV2_REG = I2C_backup.clkDiv2; } #else /* Disable slave or master bits */ I2C_CFG_REG &= (uint8) ~I2C_ENABLE_MS; #if (I2C_MODE_SLAVE_ENABLED) { /* Disable bit counter */ uint8 intState = CyEnterCriticalSection(); I2C_COUNTER_AUX_CTL_REG &= (uint8) ~I2C_CNT7_ENABLE; CyExitCriticalSection(intState); } #endif /* (I2C_MODE_SLAVE_ENABLED) */ /* Clear interrupt source register */ (void) I2C_CSR_REG; #endif /* (I2C_FF_IMPLEMENTED) */ /* Disable interrupt on stop (enabled by write transaction) */ I2C_DISABLE_INT_ON_STOP; I2C_ClearPendingInt(); /* Reset FSM to default state */ I2C_state = I2C_SM_IDLE; /* Clear busy statuses */ #if (I2C_MODE_SLAVE_ENABLED) I2C_slStatus &= (uint8) ~(I2C_SSTAT_RD_BUSY | I2C_SSTAT_WR_BUSY); #endif /* (I2C_MODE_SLAVE_ENABLED) */ }
/******************************************************************************* * Function Name: I2C_MasterSendStart ******************************************************************************** * * Summary: * Generates Start condition and sends slave address with read/write bit. * * Parameters: * slaveAddress: 7-bit slave address. * R_nW: Zero, send write command, non-zero send read command. * * Return: * Status error - zero means no errors. * * Side Effects: * This function is entered without a 'byte complete' bit set in the I2C_CSR * register. It does not exit until it will be set. * * Global variables: * I2C_state - used to store current state of software FSM. * * Reentrant: * No * *******************************************************************************/ uint8 I2C_MasterSendStart(uint8 slaveAddress, uint8 R_nW) { uint8 errStatus; errStatus = I2C_MSTR_NOT_READY; /* If IDLE, check if bus is free */ if(I2C_SM_IDLE == I2C_state) { /* If bus is free, generate Start condition */ if(I2C_CHECK_BUS_FREE(I2C_MCSR_REG)) { I2C_DisableInt(); /* Disable ISR for Manual functions */ slaveAddress = ((uint8) (slaveAddress << I2C_SLAVE_ADDR_SHIFT)); /* Set Address */ if(0u != R_nW) /* Set the Read/Write flag */ { slaveAddress |= I2C_READ_FLAG; I2C_state = I2C_SM_MSTR_RD_ADDR; } else { I2C_state = I2C_SM_MSTR_WR_ADDR; } I2C_DATA_REG = slaveAddress; /* Write address to data reg */ I2C_GENERATE_START; while(I2C_WAIT_BYTE_COMPLETE(I2C_CSR_REG)) { ; /* Wait for the address to be transfered */ } #if(I2C_MODE_MULTI_MASTER_SLAVE_ENABLED) if(I2C_CHECK_START_GEN(I2C_MCSR_REG)) { I2C_CLEAR_START_GEN; /* Start condition was not generated: reset FSM to IDLE */ I2C_state = I2C_SM_IDLE; errStatus = I2C_MSTR_ERR_ABORT_START_GEN; } else #endif /* (I2C_MODE_MULTI_MASTER_SLAVE_ENABLED) */ #if(I2C_MODE_MULTI_MASTER_ENABLED) if(I2C_CHECK_LOST_ARB(I2C_CSR_REG)) { I2C_BUS_RELEASE; /* Master lost arbitrage: reset FSM to IDLE */ I2C_state = I2C_SM_IDLE; errStatus = I2C_MSTR_ERR_ARB_LOST; } else #endif /* (I2C_MODE_MULTI_MASTER_ENABLED) */ if(I2C_CHECK_ADDR_NAK(I2C_CSR_REG)) { /* Address has been NACKed: reset FSM to IDLE */ I2C_state = I2C_SM_IDLE; errStatus = I2C_MSTR_ERR_LB_NAK; } else { /* Start was sent witout errors */ errStatus = I2C_MSTR_NO_ERROR; } } else { errStatus = I2C_MSTR_BUS_BUSY; /* Bus is busy */ } } return(errStatus); }
/******************************************************************************* * Function Name: I2C_SaveConfig ******************************************************************************** * * Summary: * Wakeup on address match enabled: disables I2C Master(if was enabled before go * to sleep), enables I2C backup regulator. Waits while on-going transaction be * will completed and I2C will be ready go to sleep. All incoming transaction * will be NACKed till power down will be asserted. The address match event * wakes up the chip. * Wakeup on address match disabled: saves I2C configuration and non-retention * register values. * * Parameters: * None * * Return: * None * * Global Variables: * I2C_backup - used to save component configuration and * none-retention registers before enter sleep mode. * * Reentrant: * No * *******************************************************************************/ void I2C_SaveConfig(void) { #if(I2C_FF_IMPLEMENTED) #if(I2C_WAKEUP_ENABLED) uint8 enableInterrupts; #endif /* (I2C_WAKEUP_ENABLED) */ /* Store regiters in either Sleep mode */ I2C_backup.cfg = I2C_CFG_REG; I2C_backup.xcfg = I2C_XCFG_REG; #if(I2C_MODE_SLAVE_ENABLED) I2C_backup.addr = I2C_ADDR_REG; #endif /* (I2C_MODE_SLAVE_ENABLED) */ #if(CY_PSOC5A) I2C_backup.clkDiv = I2C_CLKDIV_REG; #else I2C_backup.clkDiv1 = I2C_CLKDIV1_REG; I2C_backup.clkDiv2 = I2C_CLKDIV2_REG; #endif /* (CY_PSOC5A) */ #if(I2C_WAKEUP_ENABLED) /* Need to disable Master */ I2C_CFG_REG &= ((uint8) ~I2C_ENABLE_MASTER); /* Enable the I2C regulator backup */ enableInterrupts = CyEnterCriticalSection(); I2C_PWRSYS_CR1_REG |= I2C_PWRSYS_CR1_I2C_REG_BACKUP; CyExitCriticalSection(enableInterrupts); /* 1) Set force NACK to ignore I2C transactions 2) Wait while I2C will be ready go to Sleep 3) These bits are cleared on wake up */ I2C_XCFG_REG |= I2C_XCFG_FORCE_NACK; while(0u == (I2C_XCFG_REG & I2C_XCFG_RDY_TO_SLEEP)) { ; /* Wait when block is ready to Sleep */ } /* Setup wakeup interrupt */ I2C_DisableInt(); (void) CyIntSetVector(I2C_ISR_NUMBER, &I2C_WAKEUP_ISR); I2C_wakeupSource = 0u; I2C_EnableInt(); #endif /* (I2C_WAKEUP_ENABLED) */ #else /* Store only address match bit */ I2C_backup.control = (I2C_CFG_REG & I2C_CTRL_ANY_ADDRESS_MASK); #if(CY_UDB_V0) /* Store interrupt mask bits */ I2C_backup.intMask = I2C_INT_MASK_REG; #if(I2C_MODE & I2C_MODE_SLAVE) I2C_backup.addr = I2C_ADDR_REG; #endif /* (I2C_MODE & I2C_MODE_SLAVE) */ #endif /* (CY_UDB_V0) */ #endif /* (I2C_FF_IMPLEMENTED) */ #if(I2C_TIMEOUT_ENABLED) I2C_TimeoutSaveConfig(); /* Save Timeout config */ #endif /* (I2C_TIMEOUT_ENABLED) */ }
/******************************************************************************* * Function Name: I2C_RestoreConfig ******************************************************************************** * * Summary: * Wakeup on address match enabled: enables I2C Master (if was enabled before go * to sleep), disables I2C backup regulator. * Wakeup on address match disabled: Restores I2C configuration and * non-retention register values. * * Parameters: * None * * Return: * None * * Global Variables: * I2C_backup - used to save component configuration and * none-retention registers before exit sleep mode. * *******************************************************************************/ void I2C_RestoreConfig(void) { #if(I2C_FF_IMPLEMENTED) uint8 enableInterrupts; if(I2C_CHECK_PWRSYS_I2C_BACKUP) /* Enabled if was in Sleep */ { /* Disable back-up regulator */ enableInterrupts = CyEnterCriticalSection(); I2C_PWRSYS_CR1_REG &= ((uint8) ~I2C_PWRSYS_CR1_I2C_REG_BACKUP); CyExitCriticalSection(enableInterrupts); /* Re-enable Master */ I2C_CFG_REG = I2C_backup.cfg; } else /* The I2C_REG_BACKUP was cleaned by PM API: it means Hibernate or wake-up not set */ { #if(I2C_WAKEUP_ENABLED) /* Disable power to I2C block before register restore */ enableInterrupts = CyEnterCriticalSection(); I2C_ACT_PWRMGR_REG &= ((uint8) ~I2C_ACT_PWR_EN); I2C_STBY_PWRMGR_REG &= ((uint8) ~I2C_STBY_PWR_EN); CyExitCriticalSection(enableInterrupts); /* Enable component after restore complete */ I2C_backup.enableState = I2C_ENABLE; #endif /* (I2C_WAKEUP_ENABLED) */ /* Restore component registers: Hibernate disable power */ I2C_XCFG_REG = I2C_backup.xcfg; I2C_CFG_REG = I2C_backup.cfg; #if(I2C_MODE_SLAVE_ENABLED) I2C_ADDR_REG = I2C_backup.addr; #endif /* (I2C_MODE_SLAVE_ENABLED) */ #if(CY_PSOC5A) I2C_CLKDIV_REG = I2C_backup.clkDiv; #else I2C_CLKDIV1_REG = I2C_backup.clkDiv1; I2C_CLKDIV2_REG = I2C_backup.clkDiv2; #endif /* (CY_PSOC5A) */ } #if(I2C_WAKEUP_ENABLED) I2C_DisableInt(); (void) CyIntSetVector(I2C_ISR_NUMBER, &I2C_ISR); if(0u != I2C_wakeupSource) { I2C_SetPendingInt(); /* Generate interrupt to process incomming transcation */ } I2C_EnableInt(); #endif /* (I2C_WAKEUP_ENABLED) */ #else #if(CY_UDB_V0) uint8 enableInterrupts; I2C_INT_MASK_REG |= I2C_backup.intMask; enableInterrupts = CyEnterCriticalSection(); I2C_INT_ENABLE_REG |= I2C_INT_ENABLE_MASK; CyExitCriticalSection(enableInterrupts); #if(I2C_MODE_MASTER_ENABLED) /* Restore Master Clock generator */ I2C_MCLK_PRD_REG = I2C_DEFAULT_MCLK_PRD; I2C_MCLK_CMP_REG = I2C_DEFAULT_MCLK_CMP; #endif /* (I2C_MODE_MASTER_ENABLED) */ #if(I2C_MODE_SLAVE_ENABLED) I2C_ADDR_REG = I2C_backup.addr; /* Restore slave bit counter period */ I2C_PERIOD_REG = I2C_DEFAULT_PERIOD; #endif /* (I2C_MODE_SLAVE_ENABLED) */ #endif /* (CY_UDB_V0) */ I2C_CFG_REG = I2C_backup.control; #endif /* (I2C_FF_IMPLEMENTED) */ #if(I2C_TIMEOUT_ENABLED) I2C_TimeoutRestoreConfig(); #endif /* (I2C_TIMEOUT_ENABLED) */ }
/******************************************************************************* * Function Name: I2C_SaveConfig ******************************************************************************** * * Summary: * Wakeup on address match enabled: disables I2C Master(if was enabled before go * to sleep), enables I2C backup regulator. Waits while on-going transaction be * will completed and I2C will be ready go to sleep. All incoming transaction * will be NACKed till power down will be asserted. The address match event * wakes up the chip. * Wakeup on address match disabled: saves I2C configuration and non-retention * register values. * * Parameters: * None * * Return: * None * * Global Variables: * I2C_backup - used to save component configuration and none-retention * registers before enter sleep mode. * * Reentrant: * No * *******************************************************************************/ void I2C_SaveConfig(void) { #if (I2C_IMPLEMENTATION == I2C_FF) #if (I2C_ENABLE_WAKEUP) uint8 enableInterrupts; #endif /* End (I2C_ENABLE_WAKEUP) */ /* Store regiters in either Sleep mode */ I2C_backup.cfg = I2C_CFG_REG; I2C_backup.xcfg = I2C_XCFG_REG; #if (0u != (I2C_MODE & I2C_MODE_SLAVE)) I2C_backup.addr = I2C_ADDR_REG; #endif /* End (0u != (I2C_MODE & I2C_MODE_SLAVE)) */ #if (CY_PSOC3_ES2 || CY_PSOC5_ES1) I2C_backup.clk_div = I2C_CLKDIV_REG; #else I2C_backup.clk_div1 = I2C_CLKDIV1_REG; I2C_backup.clk_div2 = I2C_CLKDIV2_REG; #endif /* End (CY_PSOC3_ES2 || CY_PSOC5_ES1) */ #if (I2C_ENABLE_WAKEUP) /* Need to disable Master */ #if (0u != (I2C_MODE & I2C_MODE_MASTER)) if (0u != (I2C_CFG_REG & I2C_ENABLE_MASTER)) { I2C_CFG_REG &= ~I2C_ENABLE_MASTER; /* Store state of I2C Master */ I2C_backup.enableState = I2C_ENABLE_MASTER; } #endif /* ((0u != (I2C_MODE & I2C_MODE_MASTER)) */ /* Enable the I2C regulator backup */ enableInterrupts = CyEnterCriticalSection(); I2C_PWRSYS_CR1_REG |= I2C_PWRSYS_CR1_I2C_REG_BACKUP; CyExitCriticalSection(enableInterrupts); /* 1) Set force NACK to ignore I2C transactions 2) Wait while I2C will be ready go to Sleep 3) These bits are cleared on wake up */ I2C_XCFG_REG |= I2C_XCFG_FORCE_NACK; while (0u == (I2C_XCFG_REG & I2C_XCFG_RDY_TO_SLEEP)); #endif /* End (I2C_ENABLE_WAKEUP) */ #else /* Store only address match bit */ I2C_backup.control = (I2C_CFG_REG & I2C_CTRL_ANY_ADDRESS_MASK); #if (CY_PSOC3_ES2 || CY_PSOC5_ES1) /* Store interrupt mask bits */ I2C_backup.int_mask = I2C_INT_MASK_REG; #if (I2C_MODE & I2C_MODE_SLAVE) /* Store slave address */ I2C_backup.addr = I2C_ADDR_REG; #endif /* End (I2C_MODE & I2C_MODE_SLAVE) */ #else /* Retention registers for ES3: - Status Int mask: int_mask; - D0 register: addr; - Auxiliary Control: aux_ctl; - Period Register: always 7; - D0 and D1: clock generator 7, 15; */ #endif /* End (CY_PSOC3_ES2 || CY_PSOC5_ES1) */ #endif /* End (I2C_IMPLEMENTATION == I2C_FF) */ /* Disable interrupts */ I2C_DisableInt(); }