--- /dev/null
+\r
+#ifdef __4MHZ__\r
+#define F_CPU 4000000UL\r
+#else\r
+#define F_CPU 8000000UL\r
+#endif\r
+#include <avr/io.h>\r
+#include "TWI_Master.h"\r
+#include <util/delay.h>\r
+\r
+#if defined(__AVR_AT90Mega169__) | defined(__AVR_ATmega169PA__) | \\r
+defined(__AVR_AT90Mega165__) | defined(__AVR_ATmega165__) | \\r
+defined(__AVR_ATmega325__) | defined(__AVR_ATmega3250__) | \\r
+defined(__AVR_ATmega645__) | defined(__AVR_ATmega6450__) | \\r
+defined(__AVR_ATmega329__) | defined(__AVR_ATmega3290__) | \\r
+defined(__AVR_ATmega649__) | defined(__AVR_ATmega6490__) |\\r
+defined(__AVR_ATtiny25__) | defined(__AVR_ATtiny45__) | defined(__AVR_ATtiny85__) | \\r
+defined(__AVR_AT90Tiny26__) | defined(__AVR_ATtiny26__) |\\r
+defined(__AVR_AT90Tiny2313__) | defined(__AVR_ATtiny2313__) |\\r
+defined(__AVR_ATtiny84__) | defined(__AVR_ATtiny84A__)\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 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
+\r
+#endif\r
+\r
+\r
+\r
+\r
+#if defined(__AVR_ATmega328PB__)| defined(__AVR_ATmega328P__)\r
+\r
+\r
+#include <util/twi.h>\r
+\r
+void TWI_Wait_Busy() {\r
+ _delay_us(100);\r
+ while (!( TWCR & (1<<TWINT) )); \r
+}\r
+\r
+\r
+void TWI_Master_Initialise( void ) {\r
+ TWBR = TWI_TWBR; // Set bit rate register (Baud rate). Defined in header file.Driver presumes prescaler to be 00.\r TWSR=0;\r TWDR = 0xFF; // Default content = SDA released.\r TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.\r (0<<TWIE)|(0<<TWINT)| // Disable Interrupt.\r (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.\r (0<<TWWC);\r
+ \r
+}\r
+\r
+unsigned char I2c_WriteByte(unsigned char msg) {\r
+ uint8_t twst;\r TWDR = msg;\r TWCR = (1<<TWINT) | (1<<TWEN);\r TWI_Wait_Busy();\r // check value of TWI Status Register. Mask prescaler bits\r twst = TW_STATUS & 0xF8;\r if( twst != TW_MT_DATA_ACK) return 1;\r return 0;\r
+}\r
+unsigned char I2c_ReadByte(unsigned char ack_mode) {\r
+ TWCR = (1<<TWINT) | (1<<TWEN) |ack_mode;\r TWI_Wait_Busy();\r return TWDR;\r
+\r
+}\r
+void I2c_StartCondition(void) {\r
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);\r
+ TWI_Wait_Busy();\r
+ uint8_t twst = TW_STATUS & 0xF8;\r if ( (twst != TW_START) && (twst != TW_REP_START)) return ;// return 1;\r}\r
+/*\r\r
+// send device address\r\r
+TWDR = address;\r\r
+TWCR = (1<<TWINT) | (1<<TWEN);\r\r
+\r\r
+// wail until transmission completed and ACK/NACK has been received\r\r
+while(!(TWCR & (1<<TWINT)));\r\r
+\r\r
+// check value of TWI Status Register. Mask prescaler bits.\r\r
+twst = TW_STATUS & 0xF8;\r\r
+if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;\r\r
+\r\r
+return 0;\r\r
+\r
+}\r
+*/\r
+void I2c_StopCondition(void) {\r
+\r
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);\r\r
+ while(TWCR & (1<<TWSTO));\r
+\r
+}\r
+\r
+#endif
\ No newline at end of file