Exemple #1
0
// * imu_i2c_start_transaction ************************************************
// * Start a receive/send' from LM4F to I2C slave device.                     *
// * dev_address    should be a 7b right justified number                     *
// * done_callback  Will be called when txn done, argument of # bytes remain, *
// *                if # bytes remain nonzero, an error occured.              *
// * Returns 0 for success, 1 for bus busy (send could not be started now).   *
// *                                                                          *
// * Portions for initialization of softi2c library copied/modified from      *
// * "soft_i2c_atmel.c" example code.                                         *
// ****************************************************************************
unsigned char imu_i2c_start_transaction(unsigned char dev_address, unsigned char reg_address, unsigned char* data, unsigned int data_byte_count, tBoolean dir_is_receive, imu_i2c_xfer_done_t done_callback)
{
  if(data_byte_count == 0 || data == 0 || done_callback == 0)
  {                                                       // no data to send or no place to take it from
    return IMU_RET_INVALID_ARGS;                          // invalid argument(s)
  }
  else if(SoftI2CBusy(&g_sI2C))                           // if bus busy
  {
    return IMU_RET_BUSY;                                  // return bus busy
  }
  xfer_done_cb = done_callback;                           // store callback function pointer
  imu_i2c_dev_address = dev_address;                      // store copy of device address for use in interrupt handler
  imu_i2c_reg_address = reg_address;                      // store register address
  SoftI2CSlaveAddrSet(&g_sI2C, dev_address, false);  
                                                          // set the slave address, always transmit first to get register address transmitted
  imu_i2c_dir_is_receive = dir_is_receive;                // make copy of current direction
  imu_i2c_data_buff = data;                               // initialize buffer pointer
  imu_i2c_data_byte_count = data_byte_count;              // initialize data byte count - will downcount during send
  imu_i2c_int_en();                                       // enable 'interrupts' (callbacks) for I2C
  imu_i2c_is_addressing = true;                           // first interrupt will be to finish register addressing stage
  imu_i2c_in_progress = true;                             // transaction is currently taking place
  imu_i2c_is_multibyte = false;                           // default to single byte
  if(data_byte_count > 1)
  {
    imu_i2c_reg_address |= 0x80;                          // turn msb on to indicate sequential read to chip
    imu_i2c_is_multibyte = true;                          // multi byte txn
  }
                                                          // start txn with address and send register address
  SoftI2CDataPut(&g_sI2C, imu_i2c_reg_address);           // load register address as data
  SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_START);  // instruct softi2c to generate start, send dev address, and 'data' (register address in part)
  
  return IMU_RET_SUCCESS;                                 // successfully started transfer of register address!
                                                          // now we will wait for interrupt to see what happened
}
//*****************************************************************************
//
// Read from the Atmel device.
//
//*****************************************************************************
void
AtmelRead(unsigned char *pucData, unsigned long ulOffset,
          unsigned long ulCount)
{
    //
    // Save the data buffer to be read.
    //
    g_pucData = pucData;
    g_ulCount = ulCount;

    //
    // Set the next state of the callback state machine based on the number of
    // bytes to read.
    //
    if(ulCount == 1)
    {
        g_ulState = STATE_READ_ONE;
    }
    else
    {
        g_ulState = STATE_READ_FIRST;
    }

    //
    // Start with a dummy write to get the address set in the EEPROM.
    //
    SoftI2CSlaveAddrSet(&g_sI2C, SLAVE_ADDR | (ulOffset >> 8), false);

    //
    // Write the address to be written as the first data byte.
    //
    SoftI2CDataPut(&g_sI2C, ulOffset);

    //
    // Perform a single send, writing the address as the only byte.
    //
    SoftI2CControl(&g_sI2C, SOFTI2C_CMD_SINGLE_SEND);

    //
    // Wait until the SoftI2C callback state machine is idle.
    //
    while(g_ulState != STATE_IDLE)
    {
    }
}
//*****************************************************************************
//
// Write to the Atmel device.
//
//*****************************************************************************
void
AtmelWrite(unsigned char *pucData, unsigned long ulOffset,
           unsigned long ulCount)
{
    //
    // Save the data buffer to be written.
    //
    g_pucData = pucData;
    g_ulCount = ulCount;

    //
    // Set the next state of the callback state machine based on the number of
    // bytes to write.
    //
    if(ulCount != 1)
    {
        g_ulState = STATE_WRITE_NEXT;
    }
    else
    {
        g_ulState = STATE_WRITE_FINAL;
    }

    //
    // Set the slave address and setup for a transmit operation.
    //
    SoftI2CSlaveAddrSet(&g_sI2C, SLAVE_ADDR | (ulOffset >> 8), false);

    //
    // Write the address to be written as the first data byte.
    //
    SoftI2CDataPut(&g_sI2C, ulOffset);

    //
    // Start the burst cycle, writing the address as the first byte.
    //
    SoftI2CControl(&g_sI2C, SOFTI2C_CMD_BURST_SEND_START);

    //
    // Wait until the SoftI2C callback state machine is idle.
    //
    while(g_ulState != STATE_IDLE)
    {
    }
}
Exemple #4
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;
        }
    }
}
Exemple #5
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
      }
    }
  }

}