//***************************************************************************** // // The callback function for the SoftI2C module. // //***************************************************************************** void SoftI2CCallback(void) { // // Clear the SoftI2C interrupt. // SoftI2CIntClear(&g_sI2C); // // Determine what to do based on the current state. // switch(g_ui32State) { // // The idle state. // case STATE_IDLE: { // // There is nothing to be done. // break; } // // The state for the middle of a burst write. // case STATE_WRITE_NEXT: { // // Write the next data byte. // SoftI2CDataPut(&g_sI2C, *g_pui8Data++); g_ui32Count--; // // Continue the burst write. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_CONT); // // If there is one byte left, set the next state to the final write // state. // if(g_ui32Count == 1) { g_ui32State = STATE_WRITE_FINAL; } // // This state is done. // break; } // // The state for the final write of a burst sequence. // case STATE_WRITE_FINAL: { // // Write the final data byte. // SoftI2CDataPut(&g_sI2C, *g_pui8Data++); g_ui32Count--; // // Finish the burst write. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_FINISH); // // The next state is to wait for the burst write to complete. // g_ui32State = STATE_SEND_ACK; // // This state is done. // break; } // // Wait for an ACK on the read after a write. // case STATE_WAIT_ACK: { // // See if there was an error on the previously issued read. // if(SoftI2CErr(&g_sI2C) == SOFTI2C_ERR_NONE) { // // Read the byte received. // SoftI2CDataGet(&g_sI2C); // // There was no error, so the state machine is now idle. // g_ui32State = STATE_IDLE; // // This state is done. // break; } // // Fall through to STATE_SEND_ACK. // } // // Send a read request, looking for the ACK to indicate that the write // is done. // case STATE_SEND_ACK: { // // Put the I2C master into receive mode. // SoftI2CSlaveAddrSet(&g_sI2C, SLAVE_ADDR, true); // // Perform a single byte read. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_SINGLE_RECEIVE); // // The next state is the wait for the ack. // g_ui32State = STATE_WAIT_ACK; // // This state is done. // break; } // // The state for a single byte read. // case STATE_READ_ONE: { // // Put the SoftI2C module into receive mode. // SoftI2CSlaveAddrSet(&g_sI2C, SLAVE_ADDR, true); // // Perform a single byte read. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_SINGLE_RECEIVE); // // The next state is the wait for final read state. // g_ui32State = STATE_READ_WAIT; // // This state is done. // break; } // // The state for the start of a burst read. // case STATE_READ_FIRST: { // // Put the SoftI2C module into receive mode. // SoftI2CSlaveAddrSet(&g_sI2C, SLAVE_ADDR, true); // // Start the burst receive. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_START); // // The next state is the middle of the burst read. // g_ui32State = STATE_READ_NEXT; // // This state is done. // break; } // // The state for the middle of a burst read. // case STATE_READ_NEXT: { // // Read the received character. // *g_pui8Data++ = SoftI2CDataGet(&g_sI2C); g_ui32Count--; // // Continue the burst read. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_CONT); // // If there are two characters left to be read, make the next // state be the end of burst read state. // if(g_ui32Count == 2) { g_ui32State = STATE_READ_FINAL; } // // This state is done. // break; } // // The state for the end of a burst read. // case STATE_READ_FINAL: { // // Read the received character. // *g_pui8Data++ = SoftI2CDataGet(&g_sI2C); g_ui32Count--; // // Finish the burst read. // SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_FINISH); // // The next state is the wait for final read state. // g_ui32State = STATE_READ_WAIT; // // This state is done. // break; } // // This state is for the final read of a single or burst read. // case STATE_READ_WAIT: { // // Read the received character. // *g_pui8Data++ = SoftI2CDataGet(&g_sI2C); g_ui32Count--; // // The state machine is now idle. // g_ui32State = STATE_IDLE; // // This state is done. // break; } } }
// * imu_SoftI2CCallback ****************************************************** // * Callback function for soft I2C driver to give us an event. * // * * // * Portions for initialization of softi2c library copied/modified from * // * "soft_i2c_atmel.c" example code. * // **************************************************************************** void imu_SoftI2CCallback(void) { unsigned long errcode; // holds error code SoftI2CIntClear(&g_sI2C); // clear softi2c callback if(!imu_i2c_in_progress) // we shouldn't be here { imu_i2c_int_dis(); // try to make sure we don't spuriously get back here again return; } errcode = SoftI2CErr(&g_sI2C); // grab error code from softi2c if(errcode != SOFTI2C_ERR_NONE) // if error { // could be address nak or data nak imu_i2c_abort_transaction(); // abort current transaction } else if(imu_i2c_is_addressing) // first time here, addressing phase done, now ready for data phase { imu_i2c_is_addressing = false; // handled. clear flag. if(imu_i2c_dir_is_receive) // data is to be received, need to turn direction around then start data phase { SoftI2CSlaveAddrSet(&g_sI2C, imu_i2c_dev_address, imu_i2c_dir_is_receive); // update R/S' if(imu_i2c_is_multibyte == false) // single byte SoftI2CControl(&g_sI2C, SOFTI2C_CMD_SINGLE_RECEIVE); // receive a single byte (START, TRANSMIT, STOP) else // byte stream (>1 bytes) { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_START); // start a multi byte receive cycle (START, TRANSMIT...) // (receives first byte as well) } } else // data is to be sent, already in correct direction, can continue with data phase { SoftI2CDataPut(&g_sI2C, *imu_i2c_data_buff); // load first data byte if(imu_i2c_is_multibyte == false) // single byte SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_FINISH); // single byte send cycle ((already started) TRANSMIT, STOP) else // byte stream (>1 bytes) { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_CONT); // continue a multi byte send cycle ((already started) TRANSMIT...) // (sends first byte as well) } } } else // no error, transaction completed successfully, continuing with data after addressing { if(imu_i2c_dir_is_receive) // received a byte { *imu_i2c_data_buff = (unsigned char)SoftI2CDataGet(&g_sI2C); // grab byte from data register imu_i2c_data_buff++; // prepare for next byte imu_i2c_data_byte_count--; // another byte received if(imu_i2c_is_multibyte) // multibyte transaction { if(imu_i2c_data_byte_count == 1) // 1 Byte remaining { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_FINISH); // receive one more byte } else if(imu_i2c_data_byte_count == 0) // transfer complete { imu_i2c_complete_transaction(); // complete current transaction } else // more bytes to go { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_RECEIVE_CONT); // receive next byte } } else // single byte transaction { imu_i2c_complete_transaction(); // complete current transaction } } else // sent a byte { imu_i2c_data_buff++; // prepare to send next byte imu_i2c_data_byte_count--; // another byte sent if(imu_i2c_is_multibyte) // multibyte transaction { if(imu_i2c_data_byte_count > 0) // more byte(s) to go { SoftI2CDataPut(&g_sI2C, *imu_i2c_data_buff); // load next data byte to register if(imu_i2c_data_byte_count == 1) // one more byte to go { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_FINISH); // send last byte and stop } else // more than one byte remaining { SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_CONT); // send next byte and remain in send state } } else // transfer complete { imu_i2c_complete_transaction(); // complete current transaction } } else // single byte transaction { imu_i2c_complete_transaction(); // complete current transaction } } } }