예제 #1
0
/* Get the mean for one of the coarse estimate points. If it seems that this
 * value might be (or close) causing us to clamp, adjust it and retry */
static int rx_cal_coarse_means(struct rx_cal *cal, int16_t *corr_value,
                               float *mean_i, float *mean_q)
{
    int status;
    const int16_t mean_limit_high = 2000;
    const int16_t mean_limit_low  = -mean_limit_high;
    const int16_t corr_limit = 128;
    bool retry = false;

    do {
        status = set_rx_dc_corr(cal->dev, *corr_value, *corr_value);
        if (status != 0) {
            return status;
        }

        status = rx_samples(cal->dev, cal->samples, cal->num_samples,
                            &cal->ts, RX_CAL_TS_INC);
        if (status != 0) {
            return status;
        }

        sample_mean(cal->samples, cal->num_samples, mean_i, mean_q);

        if (*mean_i > mean_limit_high || *mean_q > mean_limit_high ||
            *mean_i < mean_limit_low  || *mean_q < mean_limit_low    ) {

            if (*corr_value < 0) {
                retry = (*corr_value <= -corr_limit);
            } else {
                retry = (*corr_value >= corr_limit);
            }

            if (retry) {
                PR_DBG("Coarse estimate point Corr=%4d yields extreme means: "
                       "(%4f, %4f). Retrying...\n",
                       *corr_value, *mean_i, *mean_q);

                *corr_value = *corr_value / 2;
            }
        } else {
            retry = false;
        }
    } while (retry);

    if (retry) {
        PR_DBG("Non-ideal values are being used.\n");
    }

    return 0;
}
예제 #2
0
/* Estimate the DC correction values that yield zero DC offset via a linear
 * approximation */
static int rx_cal_coarse_estimate(struct rx_cal *cal,
                                  int16_t *i_est, int16_t *q_est)
{
    int status;
    int16_t x1 = -2048;
    int16_t x2 = 2048;
    float y1i, y1q, y2i, y2q;
    float mi, mq;
    float bi, bq;
    float i_guess, q_guess;

    status = rx_cal_coarse_means(cal, &x1, &y1i, &y1q);
    if (status != 0) {
        *i_est = 0;
        *q_est = 0;
        return status;
    }

    PR_VERBOSE("Means for x1=%d: y1i=%f, y1q=%f\n", x1, y1i, y1q);

    status = rx_cal_coarse_means(cal, &x2, &y2i, &y2q);
    if (status != 0) {
        *i_est = 0;
        *q_est = 0;
        return status;
    }

    PR_VERBOSE("Means for x2: y2i=%f, y2q=%f\n", y2i, y2q);

    mi = (y2i - y1i) / (x2 - x1);
    mq = (y2q - y1q) / (x2 - x1);

    bi = y1i - mi * x1;
    bq = y1q - mq * x1;

    PR_VERBOSE("mi=%f, bi=%f, mq=%f, bq=%f\n", mi, bi, mq, bq);

    i_guess = -bi/mi + 0.5f;
    if (i_guess < -2048) {
        i_guess = -2048;
    } else if (i_guess > 2048) {
        i_guess = 2048;
    }

    q_guess = -bq/mq + 0.5f;
    if (q_guess < -2048) {
        q_guess = -2048;
    } else if (q_guess > 2048) {
        q_guess = 2048;
    }

    *i_est = (int16_t) i_guess;
    *q_est = (int16_t) q_guess;

    PR_DBG("Coarse estimate: I=%d, Q=%d\n", *i_est, *q_est);

    return 0;
}
예제 #3
0
/* Ensure TX >= 1 MHz away from the RX frequency to avoid any potential
 * artifacts from the PLLs interfering with one another */
static int rx_cal_update_frequency(struct rx_cal *cal, uint64_t rx_freq)
{
    int status = 0;
    uint64_t f_diff;

    if (rx_freq < cal->tx_freq) {
        f_diff = cal->tx_freq - rx_freq;
    } else {
        f_diff = rx_freq - cal->tx_freq;
    }

    PR_DBG("Set F_RX = %u\n", rx_freq);
    PR_DBG("F_diff(RX, TX) = %u\n", f_diff);

    if (f_diff < 1000000) {
        if (rx_freq >= (BLADERF_FREQUENCY_MIN + 1000000)) {
            cal->tx_freq = rx_freq - 1000000;
        } else {
            cal->tx_freq = rx_freq + 1000000;
        }

        status = bladerf_set_frequency(cal->dev, BLADERF_MODULE_TX,
                                       cal->tx_freq);
        if (status != 0) {
            return status;
        }

        PR_DBG("Adjusted TX frequency: %u\n", cal->tx_freq);
    }

    status = bladerf_set_frequency(cal->dev, BLADERF_MODULE_RX, rx_freq);
    if (status != 0) {
        return status;
    }

    cal->ts += RX_CAL_TS_INC;

    return status;
}
예제 #4
0
static void init_rx_cal_sweep(int16_t *corr, unsigned int *sweep_len,
                              int16_t i_est, int16_t q_est)
{
    unsigned int actual_len = 0;
    unsigned int i;

    int16_t sweep_min, sweep_max, sweep_val;

    /* LMS6002D RX DC calibrations have a limited range. libbladeRF throws away
     * the lower 5 bits. */
    const int16_t sweep_inc = 32;

    const int16_t min_est = (i_est < q_est) ? i_est : q_est;
    const int16_t max_est = (i_est > q_est) ? i_est : q_est;

    sweep_min = min_est - 12 * 32;
    if (sweep_min < -2048) {
        sweep_min = -2048;
    }

    sweep_max = max_est + 12 * 32;
    if (sweep_max > 2048) {
        sweep_max = 2048;
    }

    /* Given that these lower bits are thrown away, it can be confusing to
     * see that values change in their LSBs that don't matter. Therefore,
     * we'll adjust to muliples of sweep_inc */
    sweep_min = (sweep_min / 32) * 32;
    sweep_max = (sweep_max / 32) * 32;


    PR_DBG("Sweeping [%d : %d : %d]\n", sweep_min, sweep_inc, sweep_max);

    sweep_val = sweep_min;
    for (i = 0; sweep_val < sweep_max && i < RX_CAL_MAX_SWEEP_LEN; i++) {
        corr[i] = sweep_val;
        sweep_val += sweep_inc;
        actual_len++;
    }

    *sweep_len = actual_len;
}
/*
 * Check getting attributes.
 */
static sns_ddf_status_e bmp085_get_all_attrib(sns_ddf_handle_t dd_handle,
                                       sns_ddf_memhandler_s memhandler)
{
    sns_ddf_status_e status;
    uint32_t num_elements = 0;
    sns_ddf_power_info_s *power_info = NULL;
    sns_ddf_range_s *range = NULL;
    sns_ddf_resolution_t *resolution = NULL;
    sns_ddf_lowpass_freq_t *freq = NULL;
    sns_ddf_delays_s *delay = NULL;
    sns_ddf_driver_info_s *driver_info = NULL;
    sns_ddf_device_info_s *device_info = NULL;
    int i;

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_POWER_INFO,
                                                         &memhandler,
                                                         (void **)&power_info,
                                                         &num_elements);

    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: active_current[i] = %d. uA\n",
               power_info->active_current);
        PR_DBG("BMP085: low-power current[i] = %d. uA \n",
               power_info->lowpower_current);
    }

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_RANGE,
                                                         &memhandler,
                                                         (void **)&range,
                                                         &num_elements);
    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: range[i]: min=%d, max=%d.\n",
               FX_TRUNC_Q16(range[i].min),
               FX_TRUNC_Q16(range[i].max));
    }

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_RESOLUTION,
                                                         &memhandler,
                                                         (void **)&resolution,
                                                         &num_elements);
    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: resolution[i] = %d.\n", resolution[i]);
    }


    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_LOWPASS,
                                                         &memhandler,
                                                         (void **)&freq,
                                                         &num_elements);
    if (status == 0)
    {
        return SNS_DDF_EFAIL; /* LOWPASS NOT SUPPORTED */
    }

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_DELAYS,
                                                         &memhandler,
                                                         (void **)&delay,
                                                         &num_elements);
    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: delay time_to_active= %d usec.\n",
               delay->time_to_active);
        PR_DBG("BMP085: delay time_to_data= %d usec.\n",
               delay->time_to_data);
    }

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_DRIVER_INFO,
                                                         &memhandler,
                                                         (void **)&driver_info,
                                                         &num_elements);
    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: driver_info name=%s,version=%s.\n",
               driver_info->name, driver_info->version);
    }

    status = sns_alt_bmp085_driver_fn_list.get_attrib(dd_handle,
                                                         SNS_DDF_SENSOR_PRESSURE,
                                                         SNS_DDF_ATTRIB_DEVICE_INFO,
                                                         &memhandler,
                                                         (void **)&device_info,
                                                         &num_elements);
    if (status)
    {
        return status;
    }

    for (i = 0; i < num_elements; i++)
    {
        PR_DBG("BMP085: device_info name=%s,vendor=%s,model=%s,version=%s.\n",
               device_info->name,
               device_info->vendor,
               device_info->model,
               device_info->version);

    }

	return SNS_DDF_SUCCESS;
}
/*
 * Test main function.
 */
sns_ddf_status_e sns_dd_alt_bmp085_on_target_test_main(void)
{
    sns_ddf_device_access_s       device_info;
    sns_ddf_i2c_config_s          i2c_config;
    uint32_t num_sensors = 0;
    sns_ddf_sensor_e *sensors = NULL;
    sns_ddf_handle_t dd_handle = NULL;
    sns_ddf_handle_t smgr_handle = NULL;
    sns_ddf_nv_params_s *nv_params = NULL;
    sns_ddf_memhandler_s memhandler;
    sns_ddf_sensor_data_s  *data = NULL;

    sns_ddf_status_e status;

    /* Device Info */
    device_info.device_select = 0;
    device_info.port_config.bus             = SNS_DDF_BUS_I2C;
    device_info.port_config.bus_config.i2c  = &i2c_config;

    /* I2C Info */
    i2c_config.addr_type            = SNS_DDF_I2C_ADDR_7BIT;
    i2c_config.bus_acq_timeout      = -1;
    i2c_config.xfer_timeout         = -1;
    i2c_config.bus_freq             = 400;
    i2c_config.dev_type             = SNS_DDF_I2C_DEVICE_REGADDR;
    i2c_config.read_opt             = SNS_DDF_I2C_START_BEFORE_RD;
    i2c_config.slave_addr           = 0xEE/2;

    /* get memory handler */
    sns_ddf_memhandler_init(&memhandler);

    status = sns_alt_bmp085_driver_fn_list.init(
                                                  &dd_handle,
                                                  smgr_handle,
                                                  nv_params,
                                                  &device_info,
                                                  1,
                                                  &memhandler,
                                                  &sensors,
                                                  &num_sensors);
    if (status != SNS_DDF_SUCCESS)
    {
        PR_ERR("error initializing\n", status);
        return status;
    }

    PR_DBG("num_sensors = %d.\n", num_sensors);
    PR_DBG("sensor type is %d.\n", *sensors);

    status = sns_alt_bmp085_driver_fn_list.get_data(
                                                      dd_handle,
                                                      &sensors[0],
                                                      1,
                                                      &memhandler,
                                                      &data);

    if (data[0].sensor != SNS_DDF_SENSOR_PRESSURE)
    {
        return SNS_DDF_EFAIL;
    }

    /* Expected Range 80K-120K Pascals = 800-1200 hPa*/
    /* P=1013.25 hPa At sea level */
    if ((data[0].samples->sample < FX_FLTTOFIX_Q16(800.0)) ||
        (data[0].samples->sample > FX_FLTTOFIX_Q16(1200.0)))
    {
        return SNS_DDF_EFAIL;
    }

    status = sns_alt_bmp085_driver_fn_list.get_data(
                                                      dd_handle,
                                                      &sensors[1],
                                                      1,
                                                      &memhandler,
                                                      &data);

    if (data[0].sensor != SNS_DDF_SENSOR_TEMP)
    {
        return SNS_DDF_EFAIL;
    }

    /* Expected Range 30-40 °C (Celcius).
       Expected 22°C at the lab + It is hotter inside the Fluid/Surf/FFA. */
    if ((data[0].samples->sample < FX_FLTTOFIX_Q16(30.0)) ||
        (data[0].samples->sample > FX_FLTTOFIX_Q16(40.0)))
    {
        return SNS_DDF_EFAIL;
    }

    status = bmp085_get_all_attrib(dd_handle, memhandler);

    if (status != SNS_DDF_SUCCESS)
    {
        PR_ERR("Get attrib err=%d.\n", status);
        return SNS_DDF_EFAIL;
    }

    status = bmp085_set_all_attrib(dd_handle);

    if (status != SNS_DDF_SUCCESS)
    {
        PR_ERR("Set attrib err=%d.\n", status);
        return SNS_DDF_EFAIL;
    }

    return SNS_DDF_SUCCESS;
}