uint8_t i2c_do(i2c_struct *i2c) { for(;;) { i2c_step(i2c); if ( i2c->state == I2C_STATE_NONE ) return 1; if ( i2c->state == I2C_STATE_ERROR ) return 0; } }
// Interrupt service routine to handle the compass communications void __ISR_COMPASS_I2C(void) // Called at 24896Hz { // I2C clock stretching if(i2c_scl_read() != g_i2c_scl_cmd) return; // Step the low level FSM i2c_step(); // Retrieve the current high level FSM command const struct Command* cmd = &g_script[current_entry]; // Perform the required action for the command switch(cmd->type) { // Signal a start condition case CMD_START: if(g_i2c_state == I2C_IDLE) i2c_start(); else if(g_i2c_state == I2C_READY) current_entry++; break; // Write a byte of data case CMD_WRITE: switch(g_i2c_state) { case I2C_READY: i2c_write(cmd->data); break; case I2C_WRITE_GOT_ACK: g_i2c_state = I2C_READY; current_entry++; break; case I2C_WRITE_GOT_NACK: g_i2c_state = I2C_READY; current_entry++; break; default: break; } break; // Read a byte of data case CMD_READ: switch(g_i2c_state) { case I2C_READY: i2c_read(); break; case I2C_READ_ENDED: read_data[cmd->data] = g_i2c_read; g_i2c_state = I2C_READY; current_entry++; break; default: break; } break; // Signal a stop condition case CMD_STOP: if(g_i2c_state == I2C_READY) i2c_stop(); else if(g_i2c_state == I2C_IDLE) current_entry++; break; // Process the last read data and loop back to a particular command (zero-based index in g_script) case CMD_LOOP: ProcessData(); current_entry = cmd->data; break; // Wait some time case CMD_WAIT: if(wait_counter == 0) wait_counter = cmd->data; else if(wait_counter == 1) { wait_counter = 0; current_entry++; } else wait_counter--; break; // Should never happen default: break; } }