/********************************************************************* * @fn hali2cStart * @brief Initiates SM-Bus communication. Makes sure that both the * clock and data lines of the SM-Bus are high. Then the data * line is set high and clock line is set low to start I/O. * @param void * @return void */ STATIC void hali2cStart( void ) { uint8 retry = HAL_I2C_RETRY_CNT; // set SCL to input but with pull-up. if slave is pulling down it will stay down. hali2cClock(1); do { // wait for slave to release clock line... if (OCM_SCL) // wait until the line is high... { break; } hali2cWait(1); } while ( --retry ); // SCL low to set SDA high so the transition will be correct. hali2cClock(0); OCM_DATA_HIGH(); // SDA high hali2cClock(1); // set up for transition hali2cWait(1); OCM_DATA_LOW(); // start hali2cWait(1); hali2cClock( 0 ); }
/********************************************************************* * @fn hali2cRead * @brief Toggle the clock line to let the slave set the data line. * Then read the data line. * @param void * @return TRUE if bit read is 1 else FALSE */ STATIC _Bool hali2cRead( void ) { // SCL low to let slave set SDA. SCL high for SDA // valid and then get bit hali2cClock( 0 ); hali2cWait(1); hali2cClock( 1 ); hali2cWait(1); return OCM_SDA; }
/********************************************************************* * @fn hali2cStop * @brief Terminates SM-Bus communication. Waits unitl the data line * is low and the clock line is high. Then sets the data line * high, keeping the clock line high to stop I/O. * @param void * @return void */ STATIC void hali2cStop( void ) { // Wait for clock high and data low hali2cClock(0); OCM_DATA_LOW(); // force low with SCL low hali2cWait(1); hali2cClock( 1 ); OCM_DATA_HIGH(); // stop condition hali2cWait(1); }
/********************************************************************* * @fn hali2cClock * @brief Clocks the SM-Bus. If a negative edge is going out, the * I/O pin is set as an output and driven low. If a positive * edge is going out, the pin is set as an input and the pin * pull-up drives the line high. This way, the slave device * can hold the node low if longer setup time is desired. * @param dir - clock line direction * @return void */ STATIC void hali2cClock( bool dir ) { if ( dir ) { IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_IN ); while(!OCM_SCL) /* Wait until clock is high */ hali2cWait(1); } else { IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_OUT ); OCM_SCL = 0; } hali2cWait(1); }
/********************************************************************* * @fn hali2cWrite * @brief Send one bit to SM-Bus device * @param dBit - data bit to clock onto SM-Bus * @return void */ STATIC void hali2cWrite( bool dBit ) { hali2cClock( 0 ); hali2cWait(1); if ( dBit ) { OCM_DATA_HIGH(); } else { OCM_DATA_LOW(); } hali2cClock(1); hali2cWait(1); }
/********************************************************************* * @fn hali2cClock * @brief Clocks the SM-Bus. If a negative edge is going out, the * I/O pin is set as an output and driven low. If a positive * edge is going out, the pin is set as an input and the pin * pull-up drives the line high. This way, the slave device * can hold the node low if longer setup time is desired. * @param dir - clock line direction * @return void */ STATIC void hali2cClock( bool dir ) { if ( dir ) { IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_IN ); } else { IO_DIR_PORT_PIN( OCM_CLK_PORT, OCM_CLK_PIN, IO_OUT ); OCM_SCL = 0; } hali2cWait(1); }
/********************************************************************* * @fn hali2cSendByte * @brief Serialize and send one byte to SM-Bus device * @param dByte - data byte to send * @return ACK status - 0=none, 1=received */ STATIC _Bool hali2cSendByte( uint8 dByte ) { uint8 i; for ( i = 0; i < 8; i++ ) { // Send the MSB hali2cWrite( dByte & 0x80 ); // Next bit into MSB dByte <<= 1; } // need clock low so if the SDA transitions on the next statement the // slave doesn't stop. Also give opportunity for slave to set SDA hali2cClock( 0 ); OCM_DATA_HIGH(); // set to input to receive ack... hali2cClock( 1 ); hali2cWait(1); return ( !OCM_SDA ); // Return ACK status }