Ejemplo n.º 1
0
//*****************************************************************************
//
// 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;
        }
    }
}
Ejemplo n.º 2
0
// * 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
      }
    }
  }

}