📄 dev_i2c_main.c
字号:
{ /* ERROR: Slave failed to release SCL */ return ( retcode ); } /* Read the state of the serial data line (SDA) */ sdastate = dev_i2c_io_sdastate (); /* If SCL was not released */ if ( sdastate != DEV_I2C_SIGNAL_ACK ) { /* ERROR: Acknowledgement bit not received */ return ( DEV_I2C_RETCODE_NOACK ); } else { /* SUCCESS: Acknowledgement received */ return ( DEV_I2C_RETCODE_SUCCESS ); }}/***************************************************************************** * * DEV_I2C_WAIT4SCLRLS - Wait for SCL Release * * PURPOSE: * To wait for the slave device to release the SCL line to signal * that it is ready to complete the current bus transaction. * * PARAMETERS: * None * * RETURNS: * DEV_I2C_RETCODE_SUCCESS => Data sent successfully * DEV_I2C_RETCODE_SCLRLSTO => Error: Slave SCL release timeout error * (possible physical layer fault) * * NOTE: * A slow device may hold the SCL line low for a protracted period * of time to achieve a quasi-'wait state' effect. * * It is not currently clear what the wait timeout period should * be to accommodate a generic set of devices. * *****************************************************************************/Int16 dev_i2c_wait4sclrls ( void ){ Word i; /* For each 2.5 us interval in the timeout value */ for ( i = 0; i < DEV_I2C_TIMEOUT_SCLRLS; i++ ) { /* If the slave has released the SCL signal */ if ( dev_i2c_io_sclstate () == DEV_I2C_SIGNAL_INACTIVE ) { /* SUCCESS: SCL released */ return ( DEV_I2C_RETCODE_SUCCESS ); } } /* ERROR: Slave failed to release SCL */ return ( DEV_I2C_RETCODE_SCLRLSTO );}Int16 dev_i2c_Uim_read ( Byte deviceaddr, Byte *databufp ){ /* empty, for DEV build only */}void dev_uim_wakeup ( void ){ /* empty, for DEV build only */}void dev_uim_reset ( void ){ /* empty, for DEV build only */}#else /* BOARD_PHOENIX *//****************** UIM I2C Very Slow, 80kHz clock speed for TDA8029 ********/#define DEV_I2C_CLK_WAIT 2 /* 4*5us: - 20 us *//***************************************************************************** * dev_i2c_write - Write Data to I2C Device *****************************************************************************/Int16 dev_i2c_write ( Byte deviceaddr, Byte *databufp, Word len ){ Word i; Int16 retcode; /* If the bus is currently in use */ if ( dev_i2c_busstate () == DEV_I2C_BUS_BUSY ) { /* ERROR: Failed to acquire the bus */ return ( DEV_I2C_RETCODE_BUSBUSY ); } retcode = dev_i2c_txdevaddr ( deviceaddr ); if ( retcode == DEV_I2C_RETCODE_SUCCESS ) { /* For each byte in the message */ for ( i = 0; i < len; i++ ) { retcode = dev_i2c_txdatabyte ( *databufp++, DEV_I2C_NOT_LAST_BYTE ); if ( retcode < 0 ) { break; /* ERROR */ } } } if ( retcode < 0 ) { dev_i2c_txstopbit (); } else { return ( dev_i2c_txdatabyte ( *databufp++, DEV_I2C_LAST_BYTE ) ); } return( retcode );}/***************************************************************************** * dev_i2c_Uim_read - Read Data from UIM I2C Device *****************************************************************************/Int16 dev_i2c_Uim_read ( Byte deviceaddr, Byte *databufp ){ Int16 retcode; /* return code */ Word i, length; Byte alpar_header[4]; /* If the bus is currently in use */ if ( dev_i2c_busstate () == DEV_I2C_BUS_BUSY ) { /* ERROR: Failed to acquire the bus */ return ( DEV_I2C_RETCODE_BUSBUSY ); } retcode = dev_i2c_txdevaddr ( deviceaddr ); if ( retcode == DEV_I2C_RETCODE_SUCCESS ) { /* For each byte in the message (except the last one) */ for ( i = 0; i < 4; i++ ) { retcode = dev_i2c_rxdatabyte( DEV_I2C_NOT_LAST_BYTE ); if ( retcode < 0 ) { break; } /* Add the received data byte to the buffer */ *databufp++ = (Byte) retcode; alpar_header[i] = retcode; } } if ( retcode < 0 ) { dev_i2c_txstopbit (); return ( retcode ); } length = alpar_header[1]*256 + alpar_header[2]; if( length <= MAX_ALPAR_DATA_LENGTH ) { /* For each byte in the message */ for ( i = 0; i < length; i++ ) { /* Receive the data byte */ retcode = dev_i2c_rxdatabyte( DEV_I2C_NOT_LAST_BYTE ); if ( retcode < 0 ) { break; } /* Add the received data byte to the buffer */ *databufp++ = (Byte) retcode; } } else { retcode = DEV_I2C_RETCODE_TOOLONG; } if ( retcode >= 0 ) { retcode = dev_i2c_rxdatabyte ( DEV_I2C_LAST_BYTE ); *databufp++ = (Byte) retcode; } dev_i2c_txstopbit (); return ( retcode );}/***************************************************************************** * DEV_I2C_TXDEVADDR - Transmit I2C Device Address *****************************************************************************/Int16 dev_i2c_txdevaddr ( Byte deviceaddr ){ /* Send a start bit */ dev_i2c_txstartbit (); /* Transmit the address byte, check for acknowledgement and return status */ return ( dev_i2c_txdatabyte ( deviceaddr, DEV_I2C_NOT_LAST_BYTE ) );}/***************************************************************************** * DEV_I2C_TXSTARTBIT - Send I2C Start Bit *****************************************************************************/void dev_i2c_txstartbit ( void ){ dev_i2c_io_sdalow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scllow ();}/***************************************************************************** * DEV_I2C_TXSTOPBIT - Send a Stop Bit *****************************************************************************/void dev_i2c_txstopbit ( void ){ /* Drive the clock line (SCL) low */ dev_i2c_io_scllow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* Drive the data line (SDA) low */ dev_i2c_io_sdalow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* Tri-state the clock line (SCL) (it will be pulled high) */ dev_i2c_io_scltristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* Tri-state the data line (SDA) (it will be pulled high) */ dev_i2c_io_sdatristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT);}/***************************************************************************** * DEV_I2C_TXDATABYTE - Send Data Byte to I2C Bus *****************************************************************************/Int16 dev_i2c_txdatabyte ( Byte data, Bool Last ){ Int16 retcode; /* Bit transmit return code */ Word i; /* For each bit in the data byte */ for ( i = 0; i < 8; i++ ) { /* Send the current data bit */ dev_i2c_txdatabit ( data & 0x80 ); /* Shift the data */ data = data << 1; } dev_i2c_io_scllow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* Tri-state the data (SDA) line */ dev_i2c_io_sdatristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scltristate (); retcode = DEV_I2C_RETCODE_SUCCESS; if ( Last == DEV_I2C_NOT_LAST_BYTE ) { if ( READ_SDA() ) /* If the SDA line is high */ { retcode = DEV_I2C_RETCODE_NOACK; /* ... No Ack */ } dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scllow (); } else { dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scllow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scltristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_txstopbit (); } return ( retcode );}/***************************************************************************** * DEV_I2C_TXDATABIT - Send Data Bit To I2C *****************************************************************************/void dev_i2c_txdatabit( Byte bit ){ /* Drive the clock line low */ dev_i2c_io_scllow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* If the data bit is a 'high' */ if ( bit ) { dev_i2c_io_sdatristate (); } else { dev_i2c_io_sdalow (); } dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scltristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT);}/***************************************************************************** * DEV_I2C_RXDATABYTE - Receive Data Byte From I2C Slave *****************************************************************************/Int16 dev_i2c_rxdatabyte( Bool Last ){ Byte databyte; /* Received data byte */ Int16 databit; /* Received data bit */ Word i; /* For each bit in the data (except the last one) */ for ( i = 0, databyte = 0; i < 7; i++ ) { /* Receive the current data bit */ databit = dev_i2c_rxdatabit (); /* Add the current data bit to the accumulation */ databyte |= databit; /* Shift the data */ databyte = databyte << 1; } /* Receive the last bit */ databyte |= dev_i2c_rxdatabit (); /* Send Ack To Slave */ dev_i2c_io_scllow (); if ( Last == DEV_I2C_NOT_LAST_BYTE ) { dev_i2c_io_sdalow (); } else { dev_i2c_io_sdatristate (); } dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scltristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scllow (); /* Return the received data */ return ( databyte );}/***************************************************************************** * DEV_I2C_RXDATABIT - Receive Data Bit From I2C *****************************************************************************/Int16 dev_i2c_rxdatabit ( void ){ Bool databit; dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scllow (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_sdatristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); dev_i2c_io_scltristate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); databit = dev_i2c_io_sdastate (); dev_i2c_wait(DEV_I2C_CLK_WAIT); /* Return the data line state */ return ( ( databit ? DEV_I2C_SIGNAL_HIGH : DEV_I2C_SIGNAL_LOW ) );}/***************************************************************************** * DEV_UIM_RESET - Reset UIM *****************************************************************************/#define UIM_RESET_WAIT 30 /* 0.1 ms */#define CLKGEN_CPUSS_RESET 0xFFFF9020#define RESET_OUT_B 4void dev_uim_reset ( void ){ REG32( CLKGEN_CPUSS_RESET ) |= BIT(RESET_OUT_B); /* Pull up Reset_Out_B */ dev_i2c_wait(UIM_RESET_WAIT); REG32( CLKGEN_CPUSS_RESET ) &= ~BIT(RESET_OUT_B); /* Pull down Reset_Out_B */ }/***************************************************************************** * DEV_UIM_WAKEUP - Wake UIM *****************************************************************************/#define UIM_WAKEUP_WAIT 100 /* 0.5 ms */void dev_uim_wakeup ( void ){ dev_i2c_wait(UIM_WAKEUP_WAIT); DEV_PIO_WRITE_LOW(UIM_WAKEUP_SLAVE); dev_i2c_wait(UIM_WAKEUP_WAIT); DEV_PIO_WRITE_HIGH(UIM_WAKEUP_SLAVE);}#endif /* BOARD PHOENIX *//***************************************************************************** * * DEV_I2C_WAIT - Wait * * PURPOSE: * To Adjust Timing * * PARAMETERS: * microSec - wait time in microseconds * * RETURNS: * None * *****************************************************************************/void dev_i2c_wait(Int16 five_microSec){#define FIVE_MICRO_SEC_LOOP 2 Int16 i, j; for( i=0; i<five_microSec; i++ ) { for( j=0; j<FIVE_MICRO_SEC_LOOP; j++ ) { } }}/***************************************************************************** * * DEV_I2C_BUSSTATE - Get I2C Bus State * * PURPOSE: * To check the I2C bus for availability. The current SDA and SCL signal * states are examined as they indicate bus activity. * * PARAMETERS: * None * * RETURNS: * DEV_I2C_BUS_IDLE => Bus is ready * DEV_I2C_BUS_BUSY => Bus is busy * * NOTE: * Both the SDA and the SCL signals must be de-asserted for the bus to * to be considered free. * *****************************************************************************/Bool dev_i2c_busstate ( void ){ /* If neither the serial data nor the clock line is being driven */ if ( ( dev_i2c_io_sclstate () == DEV_I2C_SIGNAL_INACTIVE ) && ( dev_i2c_io_sdastate () == DEV_I2C_SIGNAL_INACTIVE ) ) { /* The I2C bus is inactive */ return ( DEV_I2C_BUS_IDLE ); } else { /* The I2C bus is being accessed */ return ( DEV_I2C_BUS_BUSY ); }}#endif /* NOT_HOST_BUILD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -