00001 // This file has been prepared for Doxygen automatic documentation generation. 00032 #include <inavr.h> 00033 #include <iotiny24.h> // standard IAR header file with 4.11A and later 00034 #include "USI_TWI_Master.h" 00035 00036 unsigned char USI_TWI_Master_Transfer( unsigned char ); 00037 unsigned char USI_TWI_Master_Stop( void ); 00038 00039 union USI_TWI_state 00040 { 00041 unsigned char errorState; // Can reuse the TWI_state for error states due to that it will not be need if there exists an error. 00042 struct 00043 { 00044 unsigned char addressMode : 1; 00045 unsigned char masterWriteDataMode : 1; 00046 unsigned char unused : 6; 00047 }; 00048 } USI_TWI_state; 00049 00050 #pragma vector = USI_START_vect 00051 __interrupt void USI_START_ISR(void) 00052 { 00053 USISR |= (1<<USISIF); // ignore start condition 00054 } 00055 00056 /*--------------------------------------------------------------- 00057 USI TWI single master initialization function 00058 ---------------------------------------------------------------*/ 00059 void USI_TWI_Master_Initialise( void ) 00060 { 00061 PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state. 00062 PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state. 00063 00064 DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output. 00065 DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. 00066 00067 USIDR = 0xFF; // Preload dataregister with "released level" data. 00068 /* 00069 USICR = (1<<USISIE)|(0<<USIOIE)| // ENABLE Interrupts. 00070 */ 00071 USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts. 00072 (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. 00073 (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source 00074 (0<<USITC); 00075 USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags, 00076 (0x0<<USICNT0); // and reset counter. 00077 } 00078 00079 /*--------------------------------------------------------------- 00080 Use this function to get hold of the error message from the last transmission 00081 ---------------------------------------------------------------*/ 00082 unsigned char USI_TWI_Get_State_Info( void ) 00083 { 00084 return ( USI_TWI_state.errorState ); // Return error state. 00085 } 00086 00087 /*--------------------------------------------------------------- 00088 USI Transmit and receive function. LSB of first byte in data 00089 indicates if a read or write cycles is performed. If set a read 00090 operation is performed. 00091 00092 Function generates (Repeated) Start Condition, sends address and 00093 R/W, Reads/Writes Data, and verifies/sends ACK. 00094 00095 Success or error code is returned. Error codes are defined in 00096 USI_TWI_Master.h 00097 ---------------------------------------------------------------*/ 00098 00099 //__x unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, unsigned char msgSize) 00100 unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, unsigned char msgSize) 00101 { 00102 unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 00103 (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges. 00104 unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 00105 (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges. 00106 00107 USI_TWI_state.errorState = 0; 00108 USI_TWI_state.addressMode = TRUE; 00109 00110 #ifdef PARAM_VERIFICATION 00111 if(msg > (unsigned char*)RAMEND) // Test if address is outside SRAM space 00112 { 00113 USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND; 00114 return (FALSE); 00115 } 00116 if(msgSize <= 1) // Test if the transmission buffer is empty 00117 { 00118 USI_TWI_state.errorState = USI_TWI_NO_DATA; 00119 return (FALSE); 00120 } 00121 #endif 00122 00123 #ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to this execution. 00124 if( USISR & (1<<USISIF) ) 00125 { 00126 USI_TWI_state.errorState = USI_TWI_UE_START_CON; 00127 return (FALSE); 00128 } 00129 if( USISR & (1<<USIPF) ) 00130 { 00131 USI_TWI_state.errorState = USI_TWI_UE_STOP_CON; 00132 return (FALSE); 00133 } 00134 if( USISR & (1<<USIDC) ) 00135 { 00136 USI_TWI_state.errorState = USI_TWI_UE_DATA_COL; 00137 return (FALSE); 00138 } 00139 #endif 00140 00141 if ( !(*msg & (1<<TWI_READ_BIT)) ) // The LSB in the address byte determines if is a masterRead or masterWrite operation. 00142 { 00143 USI_TWI_state.masterWriteDataMode = TRUE; 00144 } 00145 00146 /* Release SCL to ensure that (repeated) Start can be performed */ 00147 PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. 00148 while( !(PORT_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high. 00149 #ifdef TWI_FAST_MODE 00150 __delay_cycles( T4_TWI ); // Delay for T4TWI if TWI_FAST_MODE 00151 #else 00152 __delay_cycles( T2_TWI ); // Delay for T2TWI if TWI_STANDARD_MODE 00153 #endif 00154 00155 /* Generate Start Condition */ 00156 PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW. 00157 __delay_cycles( T4_TWI ); 00158 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00159 PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. 00160 00161 #ifdef SIGNAL_VERIFY 00162 if( !(USISR & (1<<USISIF)) ) 00163 { 00164 USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; 00165 return (FALSE); 00166 } 00167 #endif 00168 00169 /*Write address and Read/Write data */ 00170 do 00171 { 00172 /* If masterWrite cycle (or inital address tranmission)*/ 00173 if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode) 00174 { 00175 /* Write a byte */ 00176 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00177 USIDR = *(msg++); // Setup data. 00178 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00179 00180 /* Clock and verify (N)ACK from slave */ 00181 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00182 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00183 { 00184 if ( USI_TWI_state.addressMode ) 00185 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; 00186 else 00187 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 00188 return (FALSE); 00189 } 00190 USI_TWI_state.addressMode = FALSE; // Only perform address transmission once. 00191 } 00192 /* Else masterRead cycle*/ 00193 else 00194 { 00195 /* Read a data byte */ 00196 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00197 *(msg++) = USI_TWI_Master_Transfer( tempUSISR_8bit ); 00198 00199 /* Prepare to generate ACK (or NACK in case of End Of Transmission) */ 00200 if( msgSize == 1) // If transmission of last byte was performed. 00201 { 00202 USIDR = 0xFF; // Load NACK to confirm End Of Transmission. 00203 } 00204 else 00205 { 00206 USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low. 00207 } 00208 USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK. 00209 } 00210 }while( --msgSize) ; // Until all data sent/received. 00211 00212 USI_TWI_Master_Stop(); // Send a STOP condition on the TWI bus. 00213 00214 /* Transmission successfully completed*/ 00215 return (TRUE); 00216 } 00217 00218 unsigned char USI_TWI_LCD_Test(void) 00219 { 00220 unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 00221 (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges. 00222 unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and 00223 (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges. 00224 00225 USI_TWI_state.errorState = 0; 00226 USI_TWI_state.addressMode = TRUE; 00227 00228 /* Release SCL to ensure that (repeated) Start can be performed */ 00229 PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. 00230 while( !(PORT_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high. 00231 #ifdef TWI_FAST_MODE 00232 __delay_cycles( T4_TWI ); // Delay for T4TWI if TWI_FAST_MODE 00233 #else 00234 __delay_cycles( T2_TWI ); // Delay for T2TWI if TWI_STANDARD_MODE 00235 #endif 00236 00237 /* Generate Start Condition */ 00238 PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW. 00239 __delay_cycles( T4_TWI ); 00240 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00241 PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. 00242 00243 // Inital address tranmission 00244 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW 00245 USIDR = 0x76 | (FALSE<<TWI_READ_BIT); // Setup address + R/W bit 00246 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00247 00248 // Clock and verify (N)ACK from slave 00249 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00250 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00251 { 00252 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; 00253 return (FALSE); 00254 } 00255 00256 // Write control byte 00257 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00258 USIDR = 0x80; // Setup data. 00259 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00260 00261 // Clock and verify (N)ACK from slave 00262 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00263 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00264 { 00265 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 00266 return (FALSE); 00267 } 00268 00269 // Write data byte 00270 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00271 USIDR = 0x0E; // displ & curs on 00272 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00273 00274 // Clock and verify (N)ACK from slave 00275 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00276 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00277 { 00278 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 00279 return (FALSE); 00280 } 00281 00282 // Write control byte 00283 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00284 USIDR = 0x00; // Last control byte 00285 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00286 00287 // Clock and verify (N)ACK from slave 00288 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00289 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00290 { 00291 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 00292 return (FALSE); 00293 } 00294 00295 // Write data byte 00296 PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. 00297 USIDR = 0x06; // addr incr & curs shift 00298 USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. 00299 00300 // Clock and verify (N)ACK from slave 00301 DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. 00302 if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 00303 { 00304 USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 00305 return (FALSE); 00306 } 00307 00308 USI_TWI_Master_Stop(); // Send a STOP condition on the TWI bus. 00309 00310 /* Transmission successfully completed*/ 00311 return (TRUE); 00312 } 00313 00314 00315 /*--------------------------------------------------------------- 00316 Core function for shifting data in and out from the USI. 00317 Data to be sent has to be placed into the USIDR prior to calling 00318 this function. Data read, will be return'ed from the function. 00319 ---------------------------------------------------------------*/ 00320 unsigned char USI_TWI_Master_Transfer( unsigned char temp ) 00321 { 00322 USISR = temp; // Set USISR according to temp. 00323 // Prepare clocking. 00324 temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled 00325 (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. 00326 (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source. 00327 (1<<USITC); // Toggle Clock Port. 00328 00329 do 00330 { 00331 __delay_cycles( T2_TWI ); 00332 USICR = temp; // Generate positve SCL edge. 00333 00334 while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high. 00335 00336 __delay_cycles( T4_TWI ); 00337 USICR = temp; // Generate negative SCL edge. 00338 }while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete. 00339 00340 __delay_cycles( T2_TWI ); 00341 temp = USIDR; // Read out data. 00342 USIDR = 0xFF; // Release SDA. 00343 DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. 00344 00345 return temp; // Return the data from the USIDR 00346 } 00347 00348 /*--------------------------------------------------------------- 00349 Function for generating a TWI Stop Condition. Used to release 00350 the TWI bus. 00351 ---------------------------------------------------------------*/ 00352 unsigned char USI_TWI_Master_Stop( void ) 00353 { 00354 PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low. 00355 PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. 00356 while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high. 00357 __delay_cycles( T4_TWI ); 00358 PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. 00359 __delay_cycles( T2_TWI ); 00360 00361 #ifdef SIGNAL_VERIFY 00362 if( !(USISR & (1<<USIPF)) ) 00363 { 00364 USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; 00365 return (FALSE); 00366 } 00367 #endif 00368 00369 return (TRUE); 00370 }
1.4.4