// This file has been prepared for Doxygen automatic documentation generation. /*! \file ******************************************************************** * * Atmel Corporation * * File : USI_TWI_Slave.c * Compiler : IAR EWAAVR 4.11A * Revision : $Revision: 1.14 $ * Date : $Date: Friday, December 09, 2005 17:25:38 UTC $ * Updated by : $Author: jtyssoe $ * * Support mail : avr@atmel.com * * Supported devices : All device with USI module can be used. * * AppNote : AVR312 - Using the USI module as a I2C slave * * Description : Functions for USI_TWI_receiver and USI_TWI_transmitter. * * ****************************************************************************/ #include #include #include "USI_TWI_Slave.h" /*! Static Variables */ static unsigned char TWI_slaveAddress; static volatile unsigned char USI_TWI_Overflow_State; /*! Local variables */ static uint8_t TWI_RxBuf[TWI_RX_BUFFER_SIZE]; static volatile uint8_t TWI_RxHead; static volatile uint8_t TWI_RxTail; static uint8_t TWI_TxBuf[TWI_TX_BUFFER_SIZE]; static volatile uint8_t TWI_TxHead; static volatile uint8_t TWI_TxTail; /*! \brief Flushes the TWI buffers */ void Flush_TWI_Buffers(void) { TWI_RxTail = 0; TWI_RxHead = 0; TWI_TxTail = 0; TWI_TxHead = 0; } //********** USI_TWI functions **********// /*! \brief * Initialise USI for TWI Slave mode. */ void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress ) { Flush_TWI_Buffers(); TWI_slaveAddress = TWI_ownAddress; PORT_USI |= (1<>1 ) == TWI_slaveAddress)) { if ( USIDR & 0x01 ) USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA; else USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; SET_USI_TO_SEND_ACK(); } else { SET_USI_TO_TWI_START_CONDITION_MODE(); } break; // ----- Master write data mode ------ // Check reply and goto USI_SLAVE_SEND_DATA if OK, else reset USI. case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA: if ( USIDR ) // If NACK, the master does not want more data. { SET_USI_TO_TWI_START_CONDITION_MODE(); return; } // From here we just drop straight into USI_SLAVE_SEND_DATA if the master sent an ACK // Copy data from buffer to USIDR and set USI to shift byte. Next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA case USI_SLAVE_SEND_DATA: // Get data from Buffer tmpTxTail = TWI_TxTail; // Not necessary, but prevents warnings if ( TWI_TxHead != tmpTxTail ) { TWI_TxTail = ( TWI_TxTail + 1 ) & TWI_TX_BUFFER_MASK; USIDR = TWI_TxBuf[TWI_TxTail]; } else // If the buffer is empty then: { SET_USI_TO_TWI_START_CONDITION_MODE(); return; } USI_TWI_Overflow_State = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA; SET_USI_TO_SEND_DATA(); break; // Set USI to sample reply from master. Next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA: USI_TWI_Overflow_State = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA; SET_USI_TO_READ_ACK(); break; // ----- Master read data mode ------ // Set USI to sample data from master. Next USI_SLAVE_GET_DATA_AND_SEND_ACK. case USI_SLAVE_REQUEST_DATA: USI_TWI_Overflow_State = USI_SLAVE_GET_DATA_AND_SEND_ACK; SET_USI_TO_READ_DATA(); break; // Copy data from USIDR and send ACK. Next USI_SLAVE_REQUEST_DATA case USI_SLAVE_GET_DATA_AND_SEND_ACK: // Put data into Buffer tmpUSIDR = USIDR; // Not necessary, but prevents warnings TWI_RxHead = ( TWI_RxHead + 1 ) & TWI_RX_BUFFER_MASK; TWI_RxBuf[TWI_RxHead] = tmpUSIDR; USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; SET_USI_TO_SEND_ACK(); break; } }