-/*****************************************************************************
-*
-* Atmel Corporation
-*
-* File : USI_TWI_Master.c
-* Compiler : AVRGCC Toolchain version 3.4.2
-* Revision : $Revision: 992 $
-* Date : $Date: 2013-11-07 $
-* Updated by : $Author: Atmel $
-*
-* Support mail : avr@atmel.com
-*
-* Supported devices : All device with USI module can be used.
-* The example is written for the ATmega169, ATtiny26 and ATtiny2313
-*
-* AppNote : AVR310 - Using the USI module as a TWI Master
-*
-* Description : This is an implementation of an TWI master using
-* the USI module as basis. The implementation assumes the AVR to
-* be the only TWI master in the system and can therefore not be
-* used in a multi-master system.
-* Usage : Initialize the USI module by calling the USI_TWI_Master_Initialise()
-* function. Hence messages/data are transceived on the bus using
-* the USI_TWI_Transceive() function. The transceive function
-* returns a status byte, which can be used to evaluate the
-* success of the transmission.
-*
-****************************************************************************/
-#define F_CPU 8000000UL
-#include <avr/io.h>
-#include "USI_TWI_Master.h"
-#include <util/delay.h>
-
-unsigned char USI_TWI_Master_Transfer( unsigned char );
-unsigned char USI_TWI_Master_Stop( void );
-
-union USI_TWI_state
-{
- unsigned char errorState; // Can reuse the TWI_state for error states due to that it will not be need if there exists an error.
- struct
- {
- unsigned char addressMode : 1;
- unsigned char masterWriteDataMode : 1;
- unsigned char unused : 6;
- };
-} USI_TWI_state;
-
-/*---------------------------------------------------------------
- USI TWI single master initialization function
----------------------------------------------------------------*/
-void USI_TWI_Master_Initialise( void )
-{
- PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.
- PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state.
-
- DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output.
- DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.
-
- USIDR = 0xFF; // Preload dataregister with "released level" data.
- USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.
- (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.
- (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source
- (0<<USITC);
- USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,
- (0x0<<USICNT0); // and reset counter.
-}
-
-/*---------------------------------------------------------------
-Use this function to get hold of the error message from the last transmission
----------------------------------------------------------------*/
-unsigned char USI_TWI_Get_State_Info( void )
-{
- return ( USI_TWI_state.errorState ); // Return error state.
-}
-
-/*---------------------------------------------------------------
- USI Transmit and receive function. LSB of first byte in data
- indicates if a read or write cycles is performed. If set a read
- operation is performed.
-
- Function generates (Repeated) Start Condition, sends address and
- R/W, Reads/Writes Data, and verifies/sends ACK.
-
- Success or error code is returned. Error codes are defined in
- USI_TWI_Master.h
----------------------------------------------------------------*/
-unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)
-{
- unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.
- unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.
-
- USI_TWI_state.errorState = 0;
- USI_TWI_state.addressMode = TRUE;
-
-#ifdef PARAM_VERIFICATION
- if(msg > (unsigned char*)RAMEND) // Test if address is outside SRAM space
- {
- USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND;
- return (FALSE);
- }
- if(msgSize <= 1) // Test if the transmission buffer is empty
- {
- USI_TWI_state.errorState = USI_TWI_NO_DATA;
- return (FALSE);
- }
-#endif
-
-#ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to this execution.
- if( USISR & (1<<USISIF) )
- {
- USI_TWI_state.errorState = USI_TWI_UE_START_CON;
- return (FALSE);
- }
- if( USISR & (1<<USIPF) )
- {
- USI_TWI_state.errorState = USI_TWI_UE_STOP_CON;
- return (FALSE);
- }
- if( USISR & (1<<USIDC) )
- {
- USI_TWI_state.errorState = USI_TWI_UE_DATA_COL;
- return (FALSE);
- }
-#endif
-
- if ( !(*msg & (1<<TWI_READ_BIT)) ) // The LSB in the address byte determines if is a masterRead or masterWrite operation.
- {
- USI_TWI_state.masterWriteDataMode = TRUE;
- }
-
-/* Release SCL to ensure that (repeated) Start can be performed */
- PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.
- while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high.
-#ifdef TWI_FAST_MODE
- _delay_us( T4_TWI/4 ); // Delay for T4TWI if TWI_FAST_MODE
-#else
- _delay_us( T2_TWI/4 ); // Delay for T2TWI if TWI_STANDARD_MODE
-#endif
-
-/* Generate Start Condition */
- PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW.
- _delay_us( T4_TWI/4 );
- PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
- PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.
-
-#ifdef SIGNAL_VERIFY
- if( !(USISR & (1<<USISIF)) )
- {
- USI_TWI_state.errorState = USI_TWI_MISSING_START_CON;
- return (FALSE);
- }
-#endif
-
-/*Write address and Read/Write data */
- do
- {
- /* If masterWrite cycle (or inital address tranmission)*/
- if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)
- {
- /* Write a byte */
- PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
- USIDR = *(msg++); // Setup data.
- USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus.
-
- /* Clock and verify (N)ACK from slave */
- DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
- if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
- {
- if ( USI_TWI_state.addressMode )
- USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
- else
- USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
- return (FALSE);
- }
- USI_TWI_state.addressMode = FALSE; // Only perform address transmission once.
- }
- /* Else masterRead cycle*/
- else
- {
- /* Read a data byte */
- DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
- *(msg++) = USI_TWI_Master_Transfer( tempUSISR_8bit );
-
- /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
- if( msgSize == 1) // If transmission of last byte was performed.
- {
- USIDR = 0xFF; // Load NACK to confirm End Of Transmission.
- }
- else
- {
- USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low.
- }
- USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK.
- }
- }while( --msgSize) ; // Until all data sent/received.
-
- USI_TWI_Master_Stop(); // Send a STOP condition on the TWI bus.
-
-/* Transmission successfully completed*/
- return (TRUE);
-}
-
-/*---------------------------------------------------------------
- Core function for shifting data in and out from the USI.
- Data to be sent has to be placed into the USIDR prior to calling
- this function. Data read, will be return'ed from the function.
----------------------------------------------------------------*/
-unsigned char USI_TWI_Master_Transfer( unsigned char temp )
-{
- USISR = temp; // Set USISR according to temp.
- // Prepare clocking.
- temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled
- (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.
- (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.
- (1<<USITC); // Toggle Clock Port.
- do
- {
- _delay_us( T2_TWI/4 );
- USICR = temp; // Generate positve SCL edge.
- while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
- _delay_us( T4_TWI/4 );
- USICR = temp; // Generate negative SCL edge.
- }while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete.
-
- _delay_us( T2_TWI/4 );
- temp = USIDR; // Read out data.
- USIDR = 0xFF; // Release SDA.
- DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.
-
- return temp; // Return the data from the USIDR
-}
-
-/*---------------------------------------------------------------
- Function for generating a TWI Stop Condition. Used to release
- the TWI bus.
----------------------------------------------------------------*/
-unsigned char USI_TWI_Master_Stop( void )
-{
- PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low.
- PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.
- while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high.
- _delay_us( T4_TWI/4 );
- PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.
- _delay_us( T2_TWI/4 );
-
-#ifdef SIGNAL_VERIFY
- if( !(USISR & (1<<USIPF)) )
- {
- USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON;
- return (FALSE);
- }
-#endif
-
- return (TRUE);
-}
-
-
-
-unsigned char I2c_WriteByte(unsigned char msg) {
- unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.
- unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.
-
- /* Write a byte */
- PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
- USIDR = msg; // Setup data.
- USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus.
- /* Clock and verify (N)ACK from slave */
- DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
- if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ){
- if ( USI_TWI_state.addressMode )
- USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
- else
- USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
- return 2;
- }
- return 0;
-}
-unsigned char I2c_ReadByte(unsigned char ack_mode) {
- unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.
- unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and
- (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.
-
- /* Read a data byte */
- DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.
- unsigned char msg = USI_TWI_Master_Transfer( tempUSISR_8bit );
-
- /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
- if( ack_mode == NO_ACK) { // If transmission of last byte was performed.
- USIDR = 0xFF; // Load NACK to confirm End Of Transmission.
- } else {
- USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low.
- }
- USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK.
- return msg;
-}
-
-void I2c_StartCondition() {
-/* Release SCL to ensure that (repeated) Start can be performed */
-PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.
-while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high.
-#ifdef TWI_FAST_MODE
-_delay_us( T4_TWI/4 ); // Delay for T4TWI if TWI_FAST_MODE
-#else
-_delay_us( T2_TWI/4 ); // Delay for T2TWI if TWI_STANDARD_MODE
-#endif
-
-/* Generate Start Condition */
-PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW.
-_delay_us( T4_TWI/4 );
-PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.
-PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.
-
-
-}
-void I2c_StopCondition() {
- USI_TWI_Master_Stop();
-}
+/*****************************************************************************\r
+*\r
+* Atmel Corporation\r
+*\r
+* File : USI_TWI_Master.c\r
+* Compiler : AVRGCC Toolchain version 3.4.2\r
+* Revision : $Revision: 992 $\r
+* Date : $Date: 2013-11-07 $\r
+* Updated by : $Author: Atmel $\r
+*\r
+* Support mail : avr@atmel.com\r
+*\r
+* Supported devices : All device with USI module can be used.\r
+* The example is written for the ATmega169, ATtiny26 and ATtiny2313\r
+*\r
+* AppNote : AVR310 - Using the USI module as a TWI Master\r
+*\r
+* Description : This is an implementation of an TWI master using\r
+* the USI module as basis. The implementation assumes the AVR to\r
+* be the only TWI master in the system and can therefore not be\r
+* used in a multi-master system.\r
+* Usage : Initialize the USI module by calling the USI_TWI_Master_Initialise() \r
+* function. Hence messages/data are transceived on the bus using\r
+* the USI_TWI_Transceive() function. The transceive function \r
+* returns a status byte, which can be used to evaluate the \r
+* success of the transmission.\r
+*\r
+****************************************************************************/\r
+#define F_CPU 8000000UL\r
+#include <avr/io.h>\r
+#include "USI_TWI_Master.h"\r
+#include <util/delay.h>\r
+\r
+unsigned char USI_TWI_Master_Transfer( unsigned char );\r
+unsigned char USI_TWI_Master_Stop( void );\r
+\r
+union USI_TWI_state\r
+{\r
+ unsigned char errorState; // Can reuse the TWI_state for error states due to that it will not be need if there exists an error.\r
+ struct\r
+ {\r
+ unsigned char addressMode : 1;\r
+ unsigned char masterWriteDataMode : 1;\r
+ unsigned char unused : 6;\r
+ }; \r
+} USI_TWI_state;\r
+\r
+/*---------------------------------------------------------------\r
+ USI TWI single master initialization function\r
+---------------------------------------------------------------*/\r
+void USI_TWI_Master_Initialise( void )\r
+{\r
+ PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state.\r
+ PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state.\r
+ \r
+ DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output.\r
+ DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.\r
+ \r
+ USIDR = 0xFF; // Preload dataregister with "released level" data.\r
+ USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.\r
+ (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.\r
+ (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source\r
+ (0<<USITC);\r
+ USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,\r
+ (0x0<<USICNT0); // and reset counter.\r
+}\r
+\r
+/*---------------------------------------------------------------\r
+Use this function to get hold of the error message from the last transmission\r
+---------------------------------------------------------------*/\r
+unsigned char USI_TWI_Get_State_Info( void )\r
+{\r
+ return ( USI_TWI_state.errorState ); // Return error state.\r
+}\r
+\r
+/*---------------------------------------------------------------\r
+ USI Transmit and receive function. LSB of first byte in data \r
+ indicates if a read or write cycles is performed. If set a read\r
+ operation is performed.\r
+\r
+ Function generates (Repeated) Start Condition, sends address and\r
+ R/W, Reads/Writes Data, and verifies/sends ACK.\r
+ \r
+ Success or error code is returned. Error codes are defined in \r
+ USI_TWI_Master.h\r
+---------------------------------------------------------------*/\r
+unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)\r
+{\r
+ unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.\r
+ unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.\r
+\r
+ USI_TWI_state.errorState = 0;\r
+ USI_TWI_state.addressMode = TRUE;\r
+\r
+#ifdef PARAM_VERIFICATION\r
+ if(msg > (unsigned char*)RAMEND) // Test if address is outside SRAM space\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND;\r
+ return (FALSE);\r
+ }\r
+ if(msgSize <= 1) // Test if the transmission buffer is empty\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_NO_DATA;\r
+ return (FALSE);\r
+ }\r
+#endif\r
+\r
+#ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to this execution.\r
+ if( USISR & (1<<USISIF) )\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_UE_START_CON;\r
+ return (FALSE);\r
+ }\r
+ if( USISR & (1<<USIPF) )\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_UE_STOP_CON;\r
+ return (FALSE);\r
+ }\r
+ if( USISR & (1<<USIDC) )\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_UE_DATA_COL;\r
+ return (FALSE);\r
+ }\r
+#endif\r
+\r
+ if ( !(*msg & (1<<TWI_READ_BIT)) ) // The LSB in the address byte determines if is a masterRead or masterWrite operation.\r
+ {\r
+ USI_TWI_state.masterWriteDataMode = TRUE;\r
+ }\r
+\r
+/* Release SCL to ensure that (repeated) Start can be performed */\r
+ PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.\r
+ while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high.\r
+#ifdef TWI_FAST_MODE\r
+ _delay_us( T4_TWI/4 ); // Delay for T4TWI if TWI_FAST_MODE\r
+#else\r
+ _delay_us( T2_TWI/4 ); // Delay for T2TWI if TWI_STANDARD_MODE\r
+#endif\r
+\r
+/* Generate Start Condition */\r
+ PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW.\r
+ _delay_us( T4_TWI/4 ); \r
+ PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.\r
+ PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.\r
+\r
+#ifdef SIGNAL_VERIFY\r
+ if( !(USISR & (1<<USISIF)) )\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; \r
+ return (FALSE);\r
+ }\r
+#endif\r
+\r
+/*Write address and Read/Write data */\r
+ do\r
+ {\r
+ /* If masterWrite cycle (or inital address tranmission)*/\r
+ if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)\r
+ {\r
+ /* Write a byte */\r
+ PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.\r
+ USIDR = *(msg++); // Setup data.\r
+ USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus.\r
+ \r
+ /* Clock and verify (N)ACK from slave */\r
+ DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.\r
+ if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) \r
+ {\r
+ if ( USI_TWI_state.addressMode )\r
+ USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;\r
+ else\r
+ USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;\r
+ return (FALSE);\r
+ }\r
+ USI_TWI_state.addressMode = FALSE; // Only perform address transmission once.\r
+ }\r
+ /* Else masterRead cycle*/\r
+ else\r
+ {\r
+ /* Read a data byte */\r
+ DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.\r
+ *(msg++) = USI_TWI_Master_Transfer( tempUSISR_8bit );\r
+\r
+ /* Prepare to generate ACK (or NACK in case of End Of Transmission) */\r
+ if( msgSize == 1) // If transmission of last byte was performed.\r
+ {\r
+ USIDR = 0xFF; // Load NACK to confirm End Of Transmission.\r
+ }\r
+ else\r
+ {\r
+ USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low.\r
+ }\r
+ USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK.\r
+ }\r
+ }while( --msgSize) ; // Until all data sent/received.\r
+ \r
+ USI_TWI_Master_Stop(); // Send a STOP condition on the TWI bus.\r
+\r
+/* Transmission successfully completed*/\r
+ return (TRUE);\r
+}\r
+\r
+/*---------------------------------------------------------------\r
+ Core function for shifting data in and out from the USI.\r
+ Data to be sent has to be placed into the USIDR prior to calling\r
+ this function. Data read, will be return'ed from the function.\r
+---------------------------------------------------------------*/\r
+unsigned char USI_TWI_Master_Transfer( unsigned char temp )\r
+{\r
+ USISR = temp; // Set USISR according to temp.\r
+ // Prepare clocking.\r
+ temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled\r
+ (1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.\r
+ (1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.\r
+ (1<<USITC); // Toggle Clock Port.\r
+ do\r
+ {\r
+ _delay_us( T2_TWI/4 ); \r
+ USICR = temp; // Generate positve SCL edge.\r
+ while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.\r
+ _delay_us( T4_TWI/4 ); \r
+ USICR = temp; // Generate negative SCL edge.\r
+ }while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete.\r
+ \r
+ _delay_us( T2_TWI/4 ); \r
+ temp = USIDR; // Read out data.\r
+ USIDR = 0xFF; // Release SDA.\r
+ DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output.\r
+\r
+ return temp; // Return the data from the USIDR\r
+}\r
+\r
+/*---------------------------------------------------------------\r
+ Function for generating a TWI Stop Condition. Used to release \r
+ the TWI bus.\r
+---------------------------------------------------------------*/\r
+unsigned char USI_TWI_Master_Stop( void )\r
+{\r
+ PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low.\r
+ PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.\r
+ while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high.\r
+ _delay_us( T4_TWI/4 ); \r
+ PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.\r
+ _delay_us( T2_TWI/4 ); \r
+ \r
+#ifdef SIGNAL_VERIFY\r
+ if( !(USISR & (1<<USIPF)) )\r
+ {\r
+ USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; \r
+ return (FALSE);\r
+ }\r
+#endif\r
+\r
+ return (TRUE);\r
+}\r
+\r
+\r
+\r
+unsigned char I2c_WriteByte(unsigned char msg) {\r
+ unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.\r
+ unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.\r
+\r
+ /* Write a byte */\r
+ PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.\r
+ USIDR = msg; // Setup data.\r
+ USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus.\r
+ /* Clock and verify (N)ACK from slave */\r
+ DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.\r
+ if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ){\r
+ if ( USI_TWI_state.addressMode )\r
+ USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;\r
+ else\r
+ USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;\r
+ return 2;\r
+ }\r
+ return 0;\r
+}\r
+unsigned char I2c_ReadByte(unsigned char ack_mode) {\r
+ unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges.\r
+ unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and\r
+ (0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges.\r
+ \r
+ /* Read a data byte */\r
+ DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input.\r
+ unsigned char msg = USI_TWI_Master_Transfer( tempUSISR_8bit );\r
+\r
+ /* Prepare to generate ACK (or NACK in case of End Of Transmission) */\r
+ if( ack_mode == NO_ACK) { // If transmission of last byte was performed.\r
+ USIDR = 0xFF; // Load NACK to confirm End Of Transmission.\r
+ } else {\r
+ USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low.\r
+ }\r
+ USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK.\r
+ return msg;\r
+}\r
+\r
+void I2c_StartCondition(void) {\r
+/* Release SCL to ensure that (repeated) Start can be performed */\r
+PORT_USI |= (1<<PIN_USI_SCL); // Release SCL.\r
+while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high.\r
+#ifdef TWI_FAST_MODE\r
+_delay_us( T4_TWI/4 ); // Delay for T4TWI if TWI_FAST_MODE\r
+#else\r
+_delay_us( T2_TWI/4 ); // Delay for T2TWI if TWI_STANDARD_MODE\r
+#endif\r
+\r
+/* Generate Start Condition */\r
+PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW.\r
+_delay_us( T4_TWI/4 );\r
+PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW.\r
+PORT_USI |= (1<<PIN_USI_SDA); // Release SDA.\r
+ \r
+ \r
+}\r
+void I2c_StopCondition(void) {\r
+ USI_TWI_Master_Stop();\r
+}\r