const char*
WiFlyDevice::ip()
{
   /*

     The return value is intended to be dropped directly
     into calls to 'print' or 'println' style methods.

   */
   static char ip[IP_ADDRESS_BUFFER_SIZE] = "";

   // TODO: Ensure we're not in a connection?

   _enter_command_mode();

   // Version 2.19 of the WiFly firmware has a "get ip a" command but
   // we can't use it because we want to work with 2.18 too.
   _send_command( F( "get ip" ), false, "IP=" );

   char newChar;
   byte offset = 0;

   // Copy the IP address from the response into our buffer
   while( offset < IP_ADDRESS_BUFFER_SIZE )
   {
      newChar = _uart->read();

      if( newChar == ':' )
      {
         ip[offset] = '\x00';
         break;
      }
      else if( newChar != -1 )
      {
         ip[offset] = newChar;
         offset++;
      }
   }

   // This handles the case when we reach the end of the buffer
   // in the loop. (Which should never happen anyway.)
   // And hopefully this prevents us from failing completely if
   // there's a mistake above.
   ip[IP_ADDRESS_BUFFER_SIZE-1] = '\x00';

   // This should skip the remainder of the output.
   // TODO: Handle this better?
   _wait_for_response( "<" );
   while (_uart->read() != ' '); // Skip the prompt.

   // For some reason the "sendCommand" approach leaves the system
   // in a state where it misses the first/next connection so for
   // now we don't check the response.
   // TODO: Fix this
   _uart->println( "exit" );
   //_send_command("exit", false, "EXIT");

   return ip;
}
Beispiel #2
0
static int _start(SercomI2cm *dev, uint16_t addr)
{
    /* Wait for hardware module to sync */
    DEBUG("Wait for device to be ready\n");
    while (dev->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) {}

    /* Set action to ACK. */
    dev->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;

    /* Send Start | Address | Write/Read */
    DEBUG("Generate start condition by sending address\n");
    dev->ADDR.reg = (addr) | (0 << SERCOM_I2CM_ADDR_HS_Pos);

    /* Wait for response on bus. */
    if (addr & I2C_READ) {
        /* Some devices (e.g. SHT2x) can hold the bus while
        preparing the reply */
        if (_wait_for_response(dev, 100 * SAMD21_I2C_TIMEOUT) < 0)
            return -ETIMEDOUT;
    }
    else {
        if (_wait_for_response(dev, SAMD21_I2C_TIMEOUT) < 0)
            return -ETIMEDOUT;
    }

    /* Check for address response error unless previous error is detected. */
    /* Check for error and ignore bus-error; workaround for BUSSTATE
     * stuck in BUSY */
    if (dev->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB) {
        /* Clear write interrupt flag */
        dev->INTFLAG.reg = SERCOM_I2CM_INTFLAG_SB;
        /* Check arbitration. */
        if (dev->STATUS.reg & SERCOM_I2CM_STATUS_ARBLOST) {
            DEBUG("STATUS_ERR_PACKET_COLLISION\n");
            return -EAGAIN;
        }
    }
    /* Check that slave responded with ack. */
    else if (dev->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
        /* Slave busy. Issue ack and stop command. */
        dev->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
        DEBUG("STATUS_ERR_BAD_ADDRESS\n");
        return -ENXIO;
    }
    return 0;
}
Beispiel #3
0
static inline int _read(SercomI2cm *dev, uint8_t *data, int length,
                        uint8_t stop)
{
    uint8_t count = 0;

    /* Set action to ack. */
    dev->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;

    /* Read data buffer. */
    while (length--) {
        /* Check that bus ownership is not lost. */
        if ((dev->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE_Msk)
            != BUSSTATE_OWNER) {
            DEBUG("STATUS_ERR_PACKET_COLLISION\n");
            return -EAGAIN;
        }

        /* Wait for hardware module to sync */
        while (dev->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) {}
        /* Check if this is the last byte to read */
        if (length == 0 && stop) {
            /* Send NACK before STOP */
            dev->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
            /* Prepare stop command before read last byte otherwise
               hardware will request an extra byte to read */
            _stop(dev);
        }
        /* Save data to buffer. */
        data[count] = dev->DATA.reg;

        /* Wait for response on bus. */
        if (length > 0) {
            if (_wait_for_response(dev, SAMD21_I2C_TIMEOUT) < 0)
                return -ETIMEDOUT;
        }
        count++;
    }
    return 0;
}
Beispiel #4
0
static inline int _write(SercomI2cm *dev, const uint8_t *data, int length,
                         uint8_t stop)
{
    uint8_t count = 0;

    /* Write data buffer until the end. */
    DEBUG("Looping through bytes\n");
    while (length--) {
        /* Check that bus ownership is not lost. */
        if ((dev->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE_Msk)
            != BUSSTATE_OWNER) {
            DEBUG("STATUS_ERR_PACKET_COLLISION\n");
            return -EAGAIN;
        }

        /* Wait for hardware module to sync */
        while (dev->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) {}

        DEBUG("Written byte #%i to data reg, now waiting for DR"
              " to be empty again\n", count);
        dev->DATA.reg = data[count++];

        /* Wait for response on bus. */
        if (_wait_for_response(dev, SAMD21_I2C_TIMEOUT) < 0) {
            return -ETIMEDOUT;
        }

        /* Check for NACK from slave. */
        if (dev->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
            DEBUG("STATUS_ERR_OVERFLOW\n");
            return -EIO;
        }
    }
    if (stop) {
        /* Issue stop command */
        _stop(dev);
    }
    return 0;
}