int main (void) { InitPeripherals(); m_clockdivide(0); TWI_Slave_Initialise(I2C_ADDR<<TWI_ADR_BITS); sei(); TWI_Start_Transceiver(); ADC_Init ADC_test; ADC_test.ADC_CHANNEL = ADC0; ADC_test.ADC_REF = VCC; ADC_test.ADC_PRESCALAR = 64; ADC_test.ADC_MODE = FREE_RUN; adc_init(ADC_test); adcInterruptEnable; adcEnable; adcAutoTriggerEnable; adcStart; while(1) { process_command(); } }
unsigned char TrataErroTransI2C ( unsigned char TWIerrorMsg ) { // Se houver falha, reinicia a recepcao e acende LED TWI_Start_Transceiver(); PD3 = 1; return TWIerrorMsg; }
int main() { uint8_t messageBuf[TWI_BUFFER_SIZE]; InitPWM(); TWI_Slave_Initialise((PWM_ADDRESS << TWI_ADR_BITS) | (0 << TWI_GEN_BIT)); TWI_Start_Transceiver(); sei(); // enable interrupts while(1) { TWI_Get_Data_From_Transceiver(messageBuf, 1); SetPWM(messageBuf[0]); TWI_Start_Transceiver(); } }
/** * Call this function to set up the TWI slave. * Remember to enable interrupts from the main application after initializing the TWI. * ---------------------------------------------------------------------------------------------- */ void TWI_Slave_Initialise( unsigned char TWI_ownAddress ) { TWAR = TWI_ownAddress << 1; // Set own TWI slave address. Reject TWI General Calls. TWDR = 0xFF; // Default content = SDA released. LOW(TWSR, TWPS0); LOW(TWSR, TWPS1); TWI_Start_Transceiver(1); }
unsigned char TWI_Act_On_Failure_In_Last_Transmission ( unsigned char TWIerrorMsg ) { // A failure has occurred, use TWIerrorMsg to determine the nature of the failure // and take appropriate actions. // See header file for a list of possible failures messages. TWI_Start_Transceiver(); return ( TWIerrorMsg ); }
int main(void) { init(); _delay_ms(100); DDRD |= (1 << PIN7); PORTD |= (1 << PIN7); // enable TWI TWI_Start_Transceiver(); pwm_enable(); uint8_t _cache = 0; while(1) { if(!TWI_Transceiver_Busy()) { if(TWI_statusReg.RxDataInBuf){ TWI_Get_Data_From_Transceiver(message_buff, 1); switch(message_buff[0] & MOTORPROTO_HEAD_GET) { case MOTORPROTO_INSTR_READ: ATOMIC_BLOCK(ATOMIC_FORCEON) { data.value = enc.counter_b; message_buff[0] = data.byte[0]; message_buff[1] = data.byte[1]; message_buff[2] = data.byte[2]; message_buff[3] = data.byte[3]; } TWI_Start_Transceiver_With_Data(message_buff, 4); message_buff[0] = 0; break; case MOTORPROTO_INSTR_RESET: ATOMIC_BLOCK(ATOMIC_FORCEON) { enc.counter_a = 0; enc.counter_b = 0; message_buff[0] = 0; } break; case MOTORPROTO_INSTR_SET_FORWARD: TWI_Get_Data_From_Transceiver(message_buff, 2); _cache = message_buff[1]; pwm_set1a(_cache); pwm_set1b(0); message_buff[0] = 0; break; case MOTORPROTO_INSTR_SET_BACKWARD: TWI_Get_Data_From_Transceiver(message_buff, 2); _cache = message_buff[1]; pwm_set1a(0); pwm_set1b(_cache); message_buff[0] = 0; break; default: break; } } } }
unsigned char TWI_Act_On_Failure_In_Last_Transmission ( unsigned char TWIerrorMsg ) { // A failure has occurred, use TWIerrorMsg to determine the nature of the failure // and take appropriate actions. // Se header file for a list of possible failures messages. // This very simple example puts the error code on PORTB and restarts the transceiver with // all the same data in the transmission buffers. PORTB = TWIerrorMsg; TWI_Start_Transceiver(); return TWIerrorMsg; }
unsigned char TWI_Act_On_Failure_In_Last_Transmission(unsigned char TWIerrorMsg) { // A failure has occurred, use TWIerrorMsg to determine the nature of the failure // and take appropriate actions. // Se header file for a list of possible failures messages. // Here is a simple sample, where if received a NACK on the slave address, // then a retransmission will be initiated. if ((TWIerrorMsg == TWI_MTX_ADR_NACK) | (TWIerrorMsg == TWI_MRX_ADR_NACK)) TWI_Start_Transceiver(); return TWIerrorMsg; }
uint8_t handle_error(uint8_t rc) { /* A failure has occurred, use TWIerrorMsg to determine the * nature of the failure and take appropriate actions. Se * header file for a list of possible failures messages. * * Here is a simple sample, where if received a NACK on the * slave address, then a retransmission will be initiated. */ if (rc == TWI_MTX_ADR_NACK || rc == TWI_MRX_ADR_NACK) TWI_Start_Transceiver(); return rc; }
int main() { joint::init(); // i2c TWI_Slave_Initialise((unsigned char) ((I2C_SLAVE_ADDRESS << TWI_ADR_BITS) | (1 << TWI_GEN_BIT)), processCommands); TWI_Start_Transceiver(); #if WATCHD0G_ENABLE wdt_enable(WDTO_120MS); #endif sei(); while (true) { if (joint::startCalibration) joint::calibrate(); #if WATCHD0G_ENABLE wdt_reset(); #endif } }
void main( void ) { unsigned char messageBuf[TWI_BUFFER_SIZE]; unsigned char TWI_slaveAddress; // LED feedback port - connect port B to the STK500 LEDS DDRB = 0xFF; // Set to ouput PORTB = 0x55; // Startup pattern // Own TWI slave address TWI_slaveAddress = 0x10; // Initialise TWI module for slave operation. Include address and/or enable General Call. TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); __enable_interrupt(); // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); // This example is made to work together with the AVR315 TWI Master application note. In adition to connecting the TWI // pins, also connect PORTB to the LEDS. The code reads a message as a TWI slave and acts according to if it is a // general call, or an address call. If it is an address call, then the first byte is considered a command byte and // it then responds differently according to the commands. // This loop runs forever. If the TWI is busy the execution will just continue doing other operations. for(;;) { #ifdef POWER_MANAGEMENT_ENABLED // Sleep while waiting for TWI transceiver to complete or waiting for new commands. // If we have data in the buffer, we can't enter sleep because we have to take care // of it first. // If the transceiver is busy, we enter idle mode because it will wake up by all TWI // interrupts. // If the transceiver not is busy, we can enter power-down mode because next receive // should be a TWI address match and it wakes the device up from all sleep modes. if( ! TWI_statusReg.RxDataInBuf ) { if(TWI_Transceiver_Busy()) { MCUCR = (1<<SE)|(0<<SM2)|(0<<SM1)|(0<<SM0); // Enable sleep with idle mode } else { MCUCR = (1<<SE)|(0<<SM2)|(1<<SM1)|(0<<SM0); // Enable sleep with power-down mode } __sleep(); } else { __no_operation(); // There is data in the buffer, code below takes care of it. } #else // No power management // Here you can add your own code that should be run while waiting for the TWI to finish __no_operation(); // Put own code here. #endif // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver(messageBuf, 2); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // Put data received out to PORTB as an example. PORTB = messageBuf[0]; } else // Ends up here if the last operation was a reception as Slave Address Match { // Example of how to interpret a command and respond. // TWI_CMD_MASTER_WRITE stores the data to PORTB if (messageBuf[0] == TWI_CMD_MASTER_WRITE) { PORTB = messageBuf[1]; } // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if (messageBuf[0] == TWI_CMD_MASTER_READ) { messageBuf[0] = PINB; TWI_Start_Transceiver_With_Data( messageBuf, 1 ); } } } else // Ends up here if the last operation was a transmission { __no_operation(); // Put own code here. } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else // Ends up here if the last operation completed unsuccessfully { TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() ); } } } }
void main( void ) { unsigned char messageBuf[TWI_BUFFER_SIZE]; unsigned char TWI_slaveAddress; // Feedback (opcional) /* DDRB = 0xFF; // Set to output PORTB = 0x55; // Startup pattern */ // Le os pinos 0-2 para endereçamento DDRC = ~((1 << 0) | (1 << 1) | (1 << 2)); //Bits 0-2 como entrada // Own TWI slave address TWI_slaveAddress = 0x10 + 0b00000111 & PORTD; // Initialise TWI module for slave operation. Include address and/or enable General Call. TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); __enable_interrupt(); // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); // This example is made to work together with the AVR315 TWI Master application note. In adition to connecting the TWI // pins, also connect PORTB to the LEDS. The code reads a message as a TWI slave and acts according to if it is a // general call, or an address call. If it is an address call, then the first byte is considered a command byte and // it then responds differently according to the commands. // This loop runs forever. If the TWI is busy the execution will just continue doing other operations. for(;;) { // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Confere se ha algo no buffer if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver(messageBuf, 2); // Confere se o ultimo pedido foi um General Call if ( TWI_statusReg.genAddressCall ) { // Trata o "broadcast" PORTB = messageBuf[0]; } else // Ends up here if the last operation was a reception as Slave Address Match { // Example of how to interpret a command and respond. // TWI_CMD_MASTER_WRITE stores the data to PORTB if (messageBuf[0] == TWI_CMD_MASTER_WRITE) { PORTB = messageBuf[1]; } // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if (messageBuf[0] == TWI_CMD_MASTER_READ) { messageBuf[0] = PINB; TWI_Start_Transceiver_With_Data( messageBuf, 1 ); } } } // Apos a operacao ele reinicia o receptor if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else // Trata erro de transmissao { TrataErroTransI2C( TWI_Get_State_Info() ); } } } }
void main( void ) { unsigned char messageBuf[4]; unsigned char TWI_slaveAddress, TWI_slaveAddress2, TWI_slaveAddressMask, temp; // LED feedback port - connect port B to the STK500 LEDS DDRB = 0xFF; // Set to ouput PORTB = 0x55; // Startup pattern // Own TWI slave address TWI_slaveAddress = (0x10<<TWI_ADR_BITS); TWI_slaveAddress2 = (0x11<<TWI_ADR_BITS); // Alternativ slave address to respond to. TWI_slaveAddressMask = TWI_slaveAddress ^ TWI_slaveAddress2; // XOR the addresses to get the address mask. // Initialise TWI module for slave operation. Include address and/or enable General Call. TWI_Slave_Initialise( TWI_slaveAddress | (TRUE<<TWI_GEN_BIT), TWI_slaveAddressMask); __enable_interrupt(); // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); // This example is made to work together with the AVR315 TWI Master application note. In adition to connecting the TWI // pins, also connect PORTB to the LEDS. The code reads a message as a TWI slave and acts according to if it is a // general call, or an address call. If it is an address call, then the first byte is considered a command byte and // it then responds differently according to the commands. // This loop runs forever. If the TWI is busy the execution will just continue doing other operations. for(;;) { // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver(messageBuf, 3); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // Put data received out to PORTB as an example. PORTB = messageBuf[1]; } // Ends up here if the last operation was a reception as Slave Address Match else { // Take action dependant on what slave address that was used in the message if (messageBuf[0] == TWI_slaveAddress) { // Example of how to interpret a command and respond. // TWI_CMD_MASTER_WRITE stores the data to PORTB if (messageBuf[1] == TWI_CMD_MASTER_WRITE) PORTB = messageBuf[2]; // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if (messageBuf[1] == TWI_CMD_MASTER_READ) { messageBuf[0] = PINB; TWI_Start_Transceiver_With_Data( messageBuf, 1 ); } } else { PORTB = messageBuf[1]; // Put TWI address data on PORTB } } } // Ends up here if the last operation was a transmission else { __no_operation(); // Put own code here. } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } // Ends up here if the last operation completed unsuccessfully else { TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() ); } } // Do something else while waiting for the TWI transceiver to complete. __no_operation(); // Put own code here. } }
int main( void ) { uint32_t val = 0; char textbuf [ (2*16) + 1 ]; // lcd /* setup */ // LCD lcd_init(); // Timer: enable a timer so we can measure passage of time // // Given: 20MHz clock // --> if we want resolution of ms (1/1000th second) .. actually, we want us (1/10th of a ms) so we can measure partial ms // --> and we have 1/20000000 clock resolution // -----> 2000 ticks will get us there (20,000 will get us ms) // // Goal: Use CTC interupt mode (CTC -> Clear on Timer Compare) // So a compare matches, it clears to zero and triggers interupt TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode OCR1A = 2000; // number to compare against TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt TCCR1B |= (1 << CS10); // Set up timer , with no prescaler (works at full MHz of clock) // Receiver setup - set up pin change interupt #if 1 EICRA &= ~ ( (1 << ISC01) | (1 << ISC01) ); // clear ISC01+ISC00 EICRA |= ( (1 << ISC00) ); // 00 set and 01 unset means any edge will make event PCMSK0 |= ( (1 << PCINT0) | (1 << PCINT1) ); // Pins to monitor: PA0 and PA1 PCICR |= (1 << PCIE0); // PA is monitored #endif // Serial - setup (for motor controller) mc_setup(); // TWI - set up unsigned char twibuf [ TWI_BUFFER_SIZE ]; unsigned char TWI_slaveAddress; TWI_slaveAddress = 0x10; // our TWI address TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); // Initialise TWI module as slave; include addr+general unsigned char twi_heartbeat_counter = 0; // setup done - kick up interupts sei(); // lets burn the first couple of seconds, so the receiver can get some signal // before we start blasting stuff into the motor controllers { unsigned int start_sec = g_time_s; while ( g_time_s - start_sec < 3 ) { nop(); } } // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); #if 1 // timer test .. show per-second counter update on lcd if ( 1 ) { unsigned int last_sec = g_time_s; unsigned int last_us = _g_time_us_tick; unsigned char sent_l = 0, sent_r = 0; char message [ 17 ]; while(1) { unsigned int ch1 = g_ch1_duration; unsigned int ch2 = g_ch2_duration; // 100ms has past? if ( _g_time_us_tick - last_us > 1000 ) { if ( g_control_twi ) { // we're on TWI control, but if nothing comes in.. revert back to RC if ( g_time_s - g_control_last_s > 2 ) { g_control_twi = 0; } } else { mc_set_by_receiver ( ch1, ch2, &sent_l, &sent_r, message ); } last_us = _g_time_us_tick; } // .1sec tick // one second has past? update lcd if ( g_time_s != last_sec ) { //sprintf ( textbuf, "recv %2d %2d ", g_ch1_duration, g_ch2_duration ); sprintf ( textbuf, "m %2d %2d th %2d %2d #", sent_l, sent_r, ch1, ch2 ); lcd_xy ( 0, 0 ); lcd_puts( textbuf ); // display number right adjusted //sprintf ( textbuf, "t%2d #", g_time_s ); sprintf ( textbuf, "t%2d # %s", g_time_s, message ); lcd_xy ( 0, 1 ); lcd_puts( textbuf ); // display number right adjusted last_sec = g_time_s; } // 1 sec tick // TWI/I2C stuff, talk to r-pi // // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver ( twibuf, 3 ); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // don't care } else { // Ends up here if the last operation was a reception as Slave Address Match // Example of how to interpret a command and respond. #if 0 // TWI_CMD_MASTER_WRITE stores the data to PORTB if (twibuf[0] == TWI_CMD_MASTER_WRITE) { PORTB = twibuf[1]; } #endif // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if ( twibuf[0] == tc_heartbeat ) { twibuf [ 0 ] = 1; twibuf [ 1 ] = twi_heartbeat_counter++; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_gethello ) { sprintf ( twibuf + 1, "hello" ); twibuf [ 0 ] = strlen ( twibuf + 1 ); // len TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_setmotors ) { g_control_last_s = g_time_s; mc_speed ( mcm_left, twibuf [ 1 ] ); mc_speed ( mcm_right, twibuf [ 2 ] ); } else if ( twibuf[0] == tc_takeover ) { g_control_last_s = g_time_s; g_control_twi = 1; } else if ( twibuf[0] == tc_release ) { g_control_twi = 0; } else { twibuf [ 0 ] = 1; twibuf [ 1 ] = 0xde; twibuf [ 2 ] = 0xad; twibuf [ 3 ] = 0xbe; twibuf [ 4 ] = 0xef; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } } } else { // Ends up here if the last operation was a transmission // don't care } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else { // Ends up here if the last operation completed unsuccessfully TWI_Act_On_Failure_In_Last_Transmission ( TWI_Get_State_Info() ); } // success/fail } // TWI busy? // spin _delay_ms ( 20 ); } // while forever } // if 1 #endif /* churn forever */ while(1); return ( 0 ); }
int main(void) { unsigned char messageBuf[TWI_BUFFER_SIZE]; unsigned char responseBuf[1]; unsigned char TWI_slaveAddress; CMotor *m = NULL; int speed = 0; int direction = 0; // Own TWI slave address TWI_slaveAddress = 0x10; // Initialise TWI module for slave operation. Include address and/or enable General Call. TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); sei(); // Start the TWI transceiver to enable reception of the first command from the TWI Master. TWI_Start_Transceiver(); //start out withe the last tx being OK - to make sure we don't end up blocking on the first request TWI_statusReg.lastTransOK = TRUE; m = motor_new(0); // This loop runs forever. If the TWI is busy the execution will just continue doing other operations. for(;;) { // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver(messageBuf, 4); if (messageBuf[1] == TWI_CMD_MOTOR_HALT) { motor_halt(m); responseBuf[0] = TWI_CMD_MOTOR_HALT; TWI_Start_Transceiver_With_Data( responseBuf, 1 ); } else if (messageBuf[1] == TWI_CMD_MOTOR_SETSPEED) { speed = messageBuf[2]; direction = messageBuf[3]; motor_setspeed_and_direction(m,speed,direction); responseBuf[0] = TWI_CMD_MOTOR_SETSPEED; TWI_Start_Transceiver_With_Data( responseBuf, 1 ); } else { //log an error? UNknown CMD } } else // Ends up here if the last operation was a transmission { //__no_operation(); // Put own code here. responseBuf[0] = TWI_CMD_CONFIRM; TWI_Start_Transceiver_With_Data( responseBuf, 1 ); } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else // Ends up here if the last operation completed unsuccessfully { //fail safe - halt the motor motor_halt(m); TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() ); } } } }
int main(){ unsigned char messageBuf[TWI_BUFFER_SIZE]; unsigned char TWI_slaveAddress; // Own TWI slave address TWI_slaveAddress = 0x20; InitIO(); defset(); InitTimer(); OSCCAL=0xA8; // wdt_reset(); /* Write logical one to WDCE and WDE */ // WDTCR = (1<<WDCE) | (1<<WDE) | (2<<WDP0); // WDTCR = (1<<WDE) | (2<<WDP0); TIMING=eeprom_read_word(&EETIMING); TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_GEN_BIT) )); sei(); TWI_Start_Transceiver(); while (1){ // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { PORTB^=1<<PB3; TWI_Get_Data_From_Transceiver(messageBuf, 2); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // Put data received out to PORTB as an example. // PORTB = messageBuf[0]; } else // Ends up here if the last operation was a reception as Slave Address Match { // Example of how to interpret a command and respond. switch (messageBuf[0]){ case xval: OCR1A=255-messageBuf[1]; break; case yval: OCR1B=255-messageBuf[1]; break; // TWI_Start_Transceiver_With_Data( messageBuf, 1 ); } } } else // Ends up here if the last operation was a transmission { // __no_operation(); // Put own code here. } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else // Ends up here if the last operation completed unsuccessfully { TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() ); } } } }