549 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			549 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * @brief LPC13xx I2C driver
 | |
|  *
 | |
|  * @note
 | |
|  * Copyright(C) NXP Semiconductors, 2012
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * @par
 | |
|  * Software that is described herein is for illustrative purposes only
 | |
|  * which provides customers with programming information regarding the
 | |
|  * LPC products.  This software is supplied "AS IS" without any warranties of
 | |
|  * any kind, and NXP Semiconductors and its licensor disclaim any and
 | |
|  * all warranties, express or implied, including all implied warranties of
 | |
|  * merchantability, fitness for a particular purpose and non-infringement of
 | |
|  * intellectual property rights.  NXP Semiconductors assumes no responsibility
 | |
|  * or liability for the use of the software, conveys no license or rights under any
 | |
|  * patent, copyright, mask work right, or any other intellectual property rights in
 | |
|  * or to any products. NXP Semiconductors reserves the right to make changes
 | |
|  * in the software without notification. NXP Semiconductors also makes no
 | |
|  * representation or warranty that such application will be suitable for the
 | |
|  * specified use without further testing or modification.
 | |
|  *
 | |
|  * @par
 | |
|  * Permission to use, copy, modify, and distribute this software and its
 | |
|  * documentation is hereby granted, under NXP Semiconductors' and its
 | |
|  * licensor's relevant copyrights in the software, without fee, provided that it
 | |
|  * is used in conjunction with NXP Semiconductors microcontrollers.  This
 | |
|  * copyright, permission, and disclaimer notice must appear in all copies of
 | |
|  * this code.
 | |
|  */
 | |
| 
 | |
| #include "chip.h"
 | |
| 
 | |
| /*****************************************************************************
 | |
|  * Private types/enumerations/variables
 | |
|  ****************************************************************************/
 | |
| 
 | |
| /* Control flags */
 | |
| #define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
 | |
| #define LPC_I2Cx(id)      ((i2c[id].ip))
 | |
| #define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
 | |
| 
 | |
| /* I2C common interface structure */
 | |
| struct i2c_interface {
 | |
| 	LPC_I2C_T *ip;		/* IP base address of the I2C device */
 | |
| 	CHIP_SYSCTL_CLOCK_T clk;	/* Clock used by I2C */
 | |
| 	I2C_EVENTHANDLER_T mEvent;	/* Current active Master event handler */
 | |
| 	I2C_EVENTHANDLER_T sEvent;	/* Slave transfer events */
 | |
| 	I2C_XFER_T *mXfer;	/* Current active xfer pointer */
 | |
| 	I2C_XFER_T *sXfer;	/* Pointer to store xfer when bus is busy */
 | |
| 	uint32_t flags;		/* Flags used by I2C master and slave */
 | |
| };
 | |
| 
 | |
| /* Slave interface structure */
 | |
| struct i2c_slave_interface {
 | |
| 	I2C_XFER_T *xfer;
 | |
| 	I2C_EVENTHANDLER_T event;
 | |
| };
 | |
| 
 | |
| /* I2C interfaces */
 | |
| static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
 | |
| 	{LPC_I2C, SYSCTL_CLOCK_I2C, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
 | |
| };
 | |
| 
 | |
| static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
 | |
| 
 | |
| /*****************************************************************************
 | |
|  * Public types/enumerations/variables
 | |
|  ****************************************************************************/
 | |
| 
 | |
| /*****************************************************************************
 | |
|  * Private functions
 | |
|  ****************************************************************************/
 | |
| 
 | |
| STATIC INLINE void enableClk(I2C_ID_T id)
 | |
| {
 | |
|     Chip_Clock_EnablePeriphClock(i2c[id].clk);
 | |
| }
 | |
| 
 | |
| STATIC INLINE void disableClk(I2C_ID_T id)
 | |
| {
 | |
|     Chip_Clock_DisablePeriphClock(i2c[id].clk);
 | |
| }
 | |
| 
 | |
| /* Get the ADC Clock Rate */
 | |
| STATIC INLINE uint32_t getClkRate(I2C_ID_T id)
 | |
| {
 | |
| 	return Chip_Clock_GetSystemClockRate();
 | |
| }
 | |
| 
 | |
| /* Enable I2C and start master transfer */
 | |
| STATIC INLINE void startMasterXfer(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	/* Reset STA, STO, SI */
 | |
| 	pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
 | |
| 
 | |
| 	/* Enter to Master Transmitter mode */
 | |
| 	pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA;
 | |
| }
 | |
| 
 | |
| /* Enable I2C and enable slave transfers */
 | |
| STATIC INLINE void startSlaverXfer(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	/* Reset STA, STO, SI */
 | |
| 	pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA;
 | |
| 
 | |
| 	/* Enter to Master Transmitter mode */
 | |
| 	pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA;
 | |
| }
 | |
| 
 | |
| /* Check if I2C bus is free */
 | |
| STATIC INLINE int isI2CBusFree(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	return !(pI2C->CONSET & I2C_CON_STO);
 | |
| }
 | |
| 
 | |
| /* Get current state of the I2C peripheral */
 | |
| STATIC INLINE int getCurState(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK);
 | |
| }
 | |
| 
 | |
| /* Check if the active state belongs to master mode*/
 | |
| STATIC INLINE int isMasterState(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	return getCurState(pI2C) < 0x60;
 | |
| }
 | |
| 
 | |
| /* Set OWN slave address for specific slave ID */
 | |
| STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask)
 | |
| {
 | |
| 	uint32_t index = (uint32_t) sid - 1;
 | |
| 	pI2C->MASK[index] = mask;
 | |
| 	if (sid == I2C_SLAVE_0) {
 | |
| 		pI2C->ADR0 = addr;
 | |
| 	}
 | |
| 	else {
 | |
| 		volatile uint32_t *abase = &pI2C->ADR1;
 | |
| 		abase[index - 1] = addr;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Match the slave address */
 | |
| STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask)
 | |
| {
 | |
| 	mask |= 1;
 | |
| 	return (addr1 & ~mask) == (addr2 & ~mask);
 | |
| }
 | |
| 
 | |
| /* Get the index of the active slave */
 | |
| STATIC I2C_SLAVE_ID lookupSlaveIndex(LPC_I2C_T *pI2C, uint8_t slaveAddr)
 | |
| {
 | |
| 	if (!(slaveAddr >> 1)) {
 | |
| 		return I2C_SLAVE_GENERAL;					/* General call address */
 | |
| 	}
 | |
| 	if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
 | |
| 		return I2C_SLAVE_0;
 | |
| 	}
 | |
| 	if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
 | |
| 		return I2C_SLAVE_1;
 | |
| 	}
 | |
| 	if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
 | |
| 		return I2C_SLAVE_2;
 | |
| 	}
 | |
| 	if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
 | |
| 		return I2C_SLAVE_3;
 | |
| 	}
 | |
| 
 | |
| 	/* If everything is fine the code should never come here */
 | |
| 	return I2C_SLAVE_GENERAL;
 | |
| }
 | |
| 
 | |
| /* Master transfer state change handler handler */
 | |
| int handleMasterXferState(LPC_I2C_T *pI2C, I2C_XFER_T  *xfer)
 | |
| {
 | |
| 	uint32_t cclr = I2C_CON_FLAGS;
 | |
| 
 | |
| 	switch (getCurState(pI2C)) {
 | |
| 	case 0x08:		/* Start condition on bus */
 | |
| 	case 0x10:		/* Repeated start condition */
 | |
| 		pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
 | |
| 		break;
 | |
| 
 | |
| 	/* Tx handling */
 | |
| 	case 0x18:		/* SLA+W sent and ACK received */
 | |
| 	case 0x28:		/* DATA sent and ACK received */
 | |
| 		if (!xfer->txSz) {
 | |
| 			cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
 | |
| 		}
 | |
| 		else {
 | |
| 			pI2C->DAT = *xfer->txBuff++;
 | |
| 			xfer->txSz--;
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
| 	/* Rx handling */
 | |
| 	case 0x58:		/* Data Received and NACK sent */
 | |
| 		cclr &= ~I2C_CON_STO;
 | |
| 
 | |
| 	case 0x50:		/* Data Received and ACK sent */
 | |
| 		*xfer->rxBuff++ = pI2C->DAT;
 | |
| 		xfer->rxSz--;
 | |
| 
 | |
| 	case 0x40:		/* SLA+R sent and ACK received */
 | |
| 		if (xfer->rxSz > 1) {
 | |
| 			cclr &= ~I2C_CON_AA;
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
| 	/* NAK Handling */
 | |
| 	case 0x20:		/* SLA+W sent NAK received */
 | |
| 	case 0x30:		/* DATA sent NAK received */
 | |
| 	case 0x48:		/* SLA+R sent NAK received */
 | |
| 		xfer->status = I2C_STATUS_NAK;
 | |
| 		cclr &= ~I2C_CON_STO;
 | |
| 		break;
 | |
| 
 | |
| 	case 0x38:		/* Arbitration lost */
 | |
| 		xfer->status = I2C_STATUS_ARBLOST;
 | |
| 		break;
 | |
| 
 | |
| 	/* Bus Error */
 | |
| 	case 0x00:
 | |
| 		xfer->status = I2C_STATUS_BUSERR;
 | |
| 		cclr &= ~I2C_CON_STO;
 | |
| 	}
 | |
| 
 | |
| 	/* Set clear control flags */
 | |
| 	pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
 | |
| 	pI2C->CONCLR = cclr;
 | |
| 
 | |
| 	/* If stopped return 0 */
 | |
| 	if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
 | |
| 		if (xfer->status == I2C_STATUS_BUSY) {
 | |
| 			xfer->status = I2C_STATUS_DONE;
 | |
| 		}
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| /* Find the slave address of SLA+W or SLA+R */
 | |
| I2C_SLAVE_ID getSlaveIndex(LPC_I2C_T *pI2C)
 | |
| {
 | |
| 	switch (getCurState(pI2C)) {
 | |
| 	case 0x60:
 | |
| 	case 0x68:
 | |
| 	case 0x70:
 | |
| 	case 0x78:
 | |
| 	case 0xA8:
 | |
| 	case 0xB0:
 | |
| 		return lookupSlaveIndex(pI2C, pI2C->DAT);
 | |
| 	}
 | |
| 
 | |
| 	/* If everything is fine code should never come here */
 | |
| 	return I2C_SLAVE_GENERAL;
 | |
| }
 | |
| 
 | |
| /* Slave state machine handler */
 | |
| int handleSlaveXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer)
 | |
| {
 | |
| 	uint32_t cclr = I2C_CON_FLAGS;
 | |
| 	int ret = RET_SLAVE_BUSY;
 | |
| 
 | |
| 	xfer->status = I2C_STATUS_BUSY;
 | |
| 	switch (getCurState(pI2C)) {
 | |
| 	case 0x80:		/* SLA: Data received + ACK sent */
 | |
| 	case 0x90:		/* GC: Data received + ACK sent */
 | |
| 		*xfer->rxBuff++ = pI2C->DAT;
 | |
| 		xfer->rxSz--;
 | |
| 		ret = RET_SLAVE_RX;
 | |
| 		if (xfer->rxSz > 1) {
 | |
| 			cclr &= ~I2C_CON_AA;
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
| 	case 0x60:		/* Own SLA+W received */
 | |
| 	case 0x68:		/* Own SLA+W received after losing arbitration */
 | |
| 	case 0x70:		/* GC+W received */
 | |
| 	case 0x78:		/* GC+W received after losing arbitration */
 | |
| 		xfer->slaveAddr = pI2C->DAT & ~1;
 | |
| 		if (xfer->rxSz > 1) {
 | |
| 			cclr &= ~I2C_CON_AA;
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
| 	case 0xA8:		/* SLA+R received */
 | |
| 	case 0xB0:		/* SLA+R received after losing arbitration */
 | |
| 		xfer->slaveAddr = pI2C->DAT & ~1;
 | |
| 
 | |
| 	case 0xB8:		/* DATA sent and ACK received */
 | |
| 		pI2C->DAT = *xfer->txBuff++;
 | |
| 		xfer->txSz--;
 | |
| 		if (xfer->txSz > 0) {
 | |
| 			cclr &= ~I2C_CON_AA;
 | |
| 		}
 | |
| 		ret = RET_SLAVE_TX;
 | |
| 		break;
 | |
| 
 | |
| 	case 0xC0:		/* Data transmitted and NAK received */
 | |
| 	case 0xC8:		/* Last data transmitted and ACK received */
 | |
| 	case 0x88:		/* SLA: Data received + NAK sent */
 | |
| 	case 0x98:		/* GC: Data received + NAK sent */
 | |
| 	case 0xA0:		/* STOP/Repeated START condition received */
 | |
| 		ret = RET_SLAVE_IDLE;
 | |
| 		cclr &= ~I2C_CON_AA;
 | |
| 		xfer->status = I2C_STATUS_DONE;
 | |
| 		if (xfer->slaveAddr & 1) {
 | |
| 			cclr &= ~I2C_CON_STA;
 | |
| 		}
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	/* Set clear control flags */
 | |
| 	pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
 | |
| 	pI2C->CONCLR = cclr;
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************
 | |
|  * Public functions
 | |
|  ****************************************************************************/
 | |
| /* Chip event handler interrupt based */
 | |
| void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
 | |
| {
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 	volatile I2C_STATUS_T *stat;
 | |
| 
 | |
| 	/* Only WAIT event needs to be handled */
 | |
| 	if (event != I2C_EVENT_WAIT) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	stat = &iic->mXfer->status;
 | |
| 	/* Wait for the status to change */
 | |
| 	while (*stat == I2C_STATUS_BUSY) {}
 | |
| }
 | |
| 
 | |
| /* Chip polling event handler */
 | |
| void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
 | |
| {
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 	volatile I2C_STATUS_T *stat;
 | |
| 
 | |
| 	/* Only WAIT event needs to be handled */
 | |
| 	if (event != I2C_EVENT_WAIT) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	stat = &iic->mXfer->status;
 | |
| 	/* Call the state change handler till xfer is done */
 | |
| 	while (*stat == I2C_STATUS_BUSY) {
 | |
| 		if (Chip_I2C_IsStateChanged(id)) {
 | |
| 			Chip_I2C_MasterStateHandler(id);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Initializes the LPC_I2C peripheral with specified parameter */
 | |
| void Chip_I2C_Init(I2C_ID_T id)
 | |
| {
 | |
| 	enableClk(id);
 | |
| 
 | |
| 	/* Set I2C operation to default */
 | |
| 	LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
 | |
| }
 | |
| 
 | |
| /* De-initializes the I2C peripheral registers to their default reset values */
 | |
| void Chip_I2C_DeInit(I2C_ID_T id)
 | |
| {
 | |
| 	/* Disable I2C control */
 | |
| 	LPC_I2Cx(id)->CONCLR = I2C_CON_I2EN | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
 | |
| 
 | |
| 	disableClk(id);
 | |
| }
 | |
| 
 | |
| /* Set up clock rate for LPC_I2C peripheral */
 | |
| void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
 | |
| {
 | |
| 	uint32_t SCLValue;
 | |
| 
 | |
| 	SCLValue = (getClkRate(id) / clockrate);
 | |
| 	LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
 | |
| 	LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
 | |
| }
 | |
| 
 | |
| /* Get current clock rate for LPC_I2C peripheral */
 | |
| uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
 | |
| {
 | |
| 	return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
 | |
| }
 | |
| 
 | |
| /* Set the master event handler */
 | |
| int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
 | |
| {
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 	if (!iic->mXfer) {
 | |
| 		iic->mEvent = event;
 | |
| 	}
 | |
| 	return iic->mEvent == event;
 | |
| }
 | |
| 
 | |
| /* Get the master event handler */
 | |
| I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
 | |
| {
 | |
| 	return i2c[id].mEvent;
 | |
| }
 | |
| 
 | |
| /* Transmit and Receive data in master mode */
 | |
| int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
 | |
| {
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 
 | |
| 	iic->mEvent(id, I2C_EVENT_LOCK);
 | |
| 	xfer->status = I2C_STATUS_BUSY;
 | |
| 	iic->mXfer = xfer;
 | |
| 
 | |
| 	/* If slave xfer not in progress */
 | |
| 	if (!iic->sXfer) {
 | |
| 		startMasterXfer(iic->ip);
 | |
| 	}
 | |
| 	iic->mEvent(id, I2C_EVENT_WAIT);
 | |
| 	iic->mXfer = 0;
 | |
| 
 | |
| 	/* Wait for stop condition to appear on bus */
 | |
| 	while (!isI2CBusFree(iic->ip)) {}
 | |
| 
 | |
| 	/* Start slave if one is active */
 | |
| 	if (SLAVE_ACTIVE(iic)) {
 | |
| 		startSlaverXfer(iic->ip);
 | |
| 	}
 | |
| 
 | |
| 	iic->mEvent(id, I2C_EVENT_UNLOCK);
 | |
| 	return (int) xfer->status;
 | |
| }
 | |
| 
 | |
| /* Master tx only */
 | |
| int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
 | |
| {
 | |
| 	I2C_XFER_T xfer = {0};
 | |
| 	xfer.slaveAddr = slaveAddr;
 | |
| 	xfer.txBuff = buff;
 | |
| 	xfer.txSz = len;
 | |
| 	while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
 | |
| 	return len - xfer.txSz;
 | |
| }
 | |
| 
 | |
| /* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
 | |
|  * This function is useful for communicating with the I2C slave registers
 | |
|  */
 | |
| int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
 | |
| {
 | |
| 	I2C_XFER_T xfer = {0};
 | |
| 	xfer.slaveAddr = slaveAddr;
 | |
| 	xfer.txBuff = &cmd;
 | |
| 	xfer.txSz = 1;
 | |
| 	xfer.rxBuff = buff;
 | |
| 	xfer.rxSz = len;
 | |
| 	while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
 | |
| 	return len - xfer.rxSz;
 | |
| }
 | |
| 
 | |
| /* Sequential master read */
 | |
| int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
 | |
| {
 | |
| 	I2C_XFER_T xfer = {0};
 | |
| 	xfer.slaveAddr = slaveAddr;
 | |
| 	xfer.rxBuff = buff;
 | |
| 	xfer.rxSz = len;
 | |
| 	while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
 | |
| 	return len - xfer.rxSz;
 | |
| }
 | |
| 
 | |
| /* Check if master state is active */
 | |
| int Chip_I2C_IsMasterActive(I2C_ID_T id)
 | |
| {
 | |
| 	return isMasterState(i2c[id].ip);
 | |
| }
 | |
| 
 | |
| /* State change handler for master transfer */
 | |
| void Chip_I2C_MasterStateHandler(I2C_ID_T id)
 | |
| {
 | |
| 	if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
 | |
| 		i2c[id].mEvent(id, I2C_EVENT_DONE);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Setup slave function */
 | |
| void Chip_I2C_SlaveSetup(I2C_ID_T id,
 | |
| 						 I2C_SLAVE_ID sid,
 | |
| 						 I2C_XFER_T *xfer,
 | |
| 						 I2C_EVENTHANDLER_T event,
 | |
| 						 uint8_t addrMask)
 | |
| {
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 	struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
 | |
| 	si2c->xfer = xfer;
 | |
| 	si2c->event = event;
 | |
| 
 | |
| 	/* Set up the slave address */
 | |
| 	if (sid != I2C_SLAVE_GENERAL) {
 | |
| 		setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
 | |
| 	}
 | |
| 
 | |
| 	if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
 | |
| 		startSlaverXfer(iic->ip);
 | |
| 	}
 | |
| 	iic->flags |= 1 << (sid + 8);
 | |
| }
 | |
| 
 | |
| /* I2C Slave event handler */
 | |
| void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
 | |
| {
 | |
| 	int ret;
 | |
| 	struct i2c_interface *iic = &i2c[id];
 | |
| 
 | |
| 	/* Get the currently addressed slave */
 | |
| 	if (!iic->sXfer) {
 | |
| 		struct i2c_slave_interface *si2c;
 | |
| 
 | |
| 		I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
 | |
| 		si2c = &i2c_slave[id][sid];
 | |
| 		iic->sXfer = si2c->xfer;
 | |
| 		iic->sEvent = si2c->event;
 | |
| 	}
 | |
| 
 | |
| 	iic->sXfer->slaveAddr |= iic->mXfer != 0;
 | |
| 	ret = handleSlaveXferState(iic->ip, iic->sXfer);
 | |
| 	if (ret) {
 | |
| 		if (iic->sXfer->status == I2C_STATUS_DONE) {
 | |
| 			iic->sXfer = 0;
 | |
| 		}
 | |
| 		iic->sEvent(id, (I2C_EVENT_T) ret);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Disable I2C device */
 | |
| void Chip_I2C_Disable(I2C_ID_T id)
 | |
| {
 | |
| 	LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
 | |
| }
 | |
| 
 | |
| /* State change checking */
 | |
| int Chip_I2C_IsStateChanged(I2C_ID_T id)
 | |
| {
 | |
| 	return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
 | |
| }
 | 
