00001 // This file has been prepared for Doxygen automatic documentation generation. 00023 #include "config.h" 00024 #include "USI_TWI_Slave.h" 00025 00029 static unsigned char TWI_slaveAddress; 00030 static volatile unsigned char USI_TWI_Overflow_State; 00031 00032 00035 static uint8_t TWI_RxBuf[TWI_RX_BUFFER_SIZE]; 00036 static volatile uint8_t TWI_RxHead; 00037 static volatile uint8_t TWI_RxTail; 00038 00039 static uint8_t TWI_TxBuf[TWI_TX_BUFFER_SIZE]; 00040 static volatile uint8_t TWI_TxHead; 00041 static volatile uint8_t TWI_TxTail; 00042 00045 void Flush_TWI_Buffers(void) 00046 { 00047 TWI_RxTail = 0; 00048 TWI_RxHead = 0; 00049 TWI_TxTail = 0; 00050 TWI_TxHead = 0; 00051 } 00052 00053 //********** USI_TWI functions **********// 00054 00058 void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress ) 00059 { 00060 Flush_TWI_Buffers(); 00061 00062 TWI_slaveAddress = TWI_ownAddress; 00063 00064 PORT_USI |= (1<<PORT_USI_SCL); // Set SCL high 00065 PORT_USI |= (1<<PORT_USI_SDA); // Set SDA high 00066 DDR_USI |= (1<<PORT_USI_SCL); // Set SCL as output 00067 DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input 00068 USICR = (1<<USISIE)|(0<<USIOIE)| // Enable Start Condition Interrupt. Disable Overflow Interrupt. 00069 (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. No USI Counter overflow prior 00070 // to first Start Condition (potentail failure) 00071 (1<<USICS1)|(0<<USICS0)|(0<<USICLK)| // Shift Register Clock Source = External, positive edge 00072 (0<<USITC); 00073 USISR = 0xF0; // Clear all flags and reset overflow counter 00074 } 00075 00076 00079 void USI_TWI_Transmit_Byte( unsigned char byte_data ) 00080 { 00081 unsigned char tmphead; 00082 00083 tmphead = ( TWI_TxHead + 1 ) & TWI_TX_BUFFER_MASK; // Calculate buffer index. 00084 while ( tmphead == TWI_TxTail ); // Wait for free space in buffer. 00085 TWI_TxBuf[tmphead] = byte_data; // Store data in buffer. 00086 TWI_TxHead = tmphead; // Store new index. 00087 } 00088 00091 unsigned char USI_TWI_Receive_Byte( void ) 00092 { 00093 unsigned char tmptail; 00094 unsigned char tmpRxTail; // Temporary variable to store volatile 00095 tmpRxTail = TWI_RxTail; // Not necessary, but prevents warnings 00096 while ( TWI_RxHead == tmpRxTail ); 00097 tmptail = ( TWI_RxTail + 1 ) & TWI_RX_BUFFER_MASK; // Calculate buffer index 00098 TWI_RxTail = tmptail; // Store new index 00099 return TWI_RxBuf[tmptail]; // Return data from the buffer. 00100 } 00101 00104 unsigned char USI_TWI_Data_In_Receive_Buffer( void ) 00105 { 00106 unsigned char tmpRxTail; // Temporary variable to store volatile 00107 tmpRxTail = TWI_RxTail; // Not necessary, but prevents warnings 00108 return ( TWI_RxHead != tmpRxTail ); // Return 0 (FALSE) if the receive buffer is empty. 00109 } 00110 00115 #ifdef __GNUC__ 00116 ISR(USI_START_vect) 00117 #else 00118 #pragma vector=USI_START_VECTOR 00119 __interrupt void USI_Start_Condition_ISR(void) 00120 #endif 00121 { 00122 unsigned char tmpUSISR; // Temporary variable to store volatile 00123 tmpUSISR = USISR; // Not necessary, but prevents warnings 00124 // Set default starting conditions for new TWI package 00125 USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS; 00126 DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input 00127 while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) ); // Wait for SCL to go low to ensure the "Start Condition" has completed. 00128 // If a Stop condition arises then leave the interrupt to prevent waiting forever. 00129 USICR = (1<<USISIE)|(1<<USIOIE)| // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART) 00130 (1<<USIWM1)|(1<<USIWM0)| // Set USI in Two-wire mode. 00131 (1<<USICS1)|(0<<USICS0)|(0<<USICLK)| // Shift Register Clock Source = External, positive edge 00132 (0<<USITC); 00133 USISR = (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags 00134 (0x0<<USICNT0); // Set USI to sample 8 bits i.e. count 16 external pin toggles. 00135 } 00136 00137 00142 #ifdef __GNUC__ 00143 ISR(USI_OVF_vect) 00144 #else 00145 #pragma vector=USI_OVERFLOW_VECTOR 00146 __interrupt void USI_Counter_Overflow_ISR(void) 00147 #endif 00148 { 00149 unsigned char tmpTxTail; // Temporary variables to store volatiles 00150 unsigned char tmpUSIDR; 00151 00152 00153 switch (USI_TWI_Overflow_State) 00154 { 00155 // ---------- Address mode ---------- 00156 // Check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK, else reset USI. 00157 case USI_SLAVE_CHECK_ADDRESS: 00158 if ((USIDR == 0) || (( USIDR>>1 ) == TWI_slaveAddress)) 00159 { 00160 if ( USIDR & 0x01 ) 00161 USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA; 00162 else 00163 USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; 00164 SET_USI_TO_SEND_ACK(); 00165 } 00166 else 00167 { 00168 SET_USI_TO_TWI_START_CONDITION_MODE(); 00169 } 00170 break; 00171 00172 // ----- Master write data mode ------ 00173 // Check reply and goto USI_SLAVE_SEND_DATA if OK, else reset USI. 00174 case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA: 00175 if ( USIDR ) // If NACK, the master does not want more data. 00176 { 00177 SET_USI_TO_TWI_START_CONDITION_MODE(); 00178 return; 00179 } 00180 // From here we just drop straight into USI_SLAVE_SEND_DATA if the master sent an ACK 00181 00182 // Copy data from buffer to USIDR and set USI to shift byte. Next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA 00183 case USI_SLAVE_SEND_DATA: 00184 00185 // Get data from Buffer 00186 tmpTxTail = TWI_TxTail; // Not necessary, but prevents warnings 00187 if ( TWI_TxHead != tmpTxTail ) 00188 { 00189 TWI_TxTail = ( TWI_TxTail + 1 ) & TWI_TX_BUFFER_MASK; 00190 USIDR = TWI_TxBuf[TWI_TxTail]; 00191 } 00192 else // If the buffer is empty then: 00193 { 00194 SET_USI_TO_TWI_START_CONDITION_MODE(); 00195 return; 00196 } 00197 USI_TWI_Overflow_State = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA; 00198 SET_USI_TO_SEND_DATA(); 00199 break; 00200 00201 // Set USI to sample reply from master. Next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA 00202 case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA: 00203 USI_TWI_Overflow_State = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA; 00204 SET_USI_TO_READ_ACK(); 00205 break; 00206 00207 // ----- Master read data mode ------ 00208 // Set USI to sample data from master. Next USI_SLAVE_GET_DATA_AND_SEND_ACK. 00209 case USI_SLAVE_REQUEST_DATA: 00210 USI_TWI_Overflow_State = USI_SLAVE_GET_DATA_AND_SEND_ACK; 00211 SET_USI_TO_READ_DATA(); 00212 break; 00213 00214 // Copy data from USIDR and send ACK. Next USI_SLAVE_REQUEST_DATA 00215 case USI_SLAVE_GET_DATA_AND_SEND_ACK: 00216 // Put data into Buffer 00217 tmpUSIDR = USIDR; // Not necessary, but prevents warnings 00218 TWI_RxHead = ( TWI_RxHead + 1 ) & TWI_RX_BUFFER_MASK; 00219 TWI_RxBuf[TWI_RxHead] = tmpUSIDR; 00220 00221 USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; 00222 SET_USI_TO_SEND_ACK(); 00223 break; 00224 } 00225 }