示例#1
0
static int rx_avg(struct bladerf *dev, int16_t *samples,
                  int16_t *avg_i, int16_t *avg_q)
{
    int status;
    int64_t accum_i, accum_q;
    unsigned int i;

    /* Flush out samples and read a buffer's worth of data */
    for (i = 0; i < 2 * CAL_NUM_BUFS + 1; i++) {
        status = bladerf_sync_rx(dev, samples, CAL_BUF_LEN, NULL, CAL_TIMEOUT);
        if (status != 0) {
            return status;
        }
    }

    for (i = 0, accum_i = accum_q = 0; i < 2 * CAL_BUF_LEN; i += 2) {
        accum_i += samples[i];
        accum_q += samples[i + 1];
    }

    accum_i /= CAL_BUF_LEN;
    accum_q /= CAL_BUF_LEN;

    assert(accum_i < (1 << 12) && accum_i >= (-(1 << 12)) );
    assert(accum_q < (1 << 12) && accum_i >= (-(1 << 12)) );

    *avg_i = (int16_t) accum_i;
    *avg_q = (int16_t) accum_q;

    return 0;
}
示例#2
0
/* RX samples, retrying if the machine is struggling to keep up. */
static int rx_samples(struct bladerf *dev, int16_t *samples,
                      unsigned int count, uint64_t *ts, uint64_t ts_inc)
{
    int status = 0;
    struct bladerf_metadata meta;
    int retry = 0;
    const int max_retries = 10;
    bool overrun = true;

    memset(&meta, 0, sizeof(meta));
    meta.timestamp = *ts;

    while (status == 0 && overrun && retry < max_retries) {
        meta.timestamp = *ts;
        status = bladerf_sync_rx(dev, samples, count, &meta, 2000);

        if (status == BLADERF_ERR_TIME_PAST) {
            status = bladerf_get_timestamp(dev, BLADERF_MODULE_RX, ts);
            if (status != 0) {
                return status;
            } else {
                *ts += 20 * ts_inc;
                retry++;
                status = 0;
            }
        } else if (status == 0) {
            overrun = (meta.flags & BLADERF_META_STATUS_OVERRUN) != 0;
            if (overrun) {
                *ts += count + ts_inc;
                retry++;
            }
        } else {
            return status;
        }
    }

    if (retry >= max_retries) {
        status = BLADERF_ERR_IO;
    } else if (status == 0) {
        *ts += count + ts_inc;
    }

    return status;
}
示例#3
0
int rf_blade_recv_with_time(void *h,
                    void *data,
                    uint32_t nsamples,
                    bool blocking,
                    time_t *secs,
                    double *frac_secs) 
{
  rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
  struct bladerf_metadata meta;
  int status; 
  
  memset(&meta, 0, sizeof(meta));
  meta.flags = BLADERF_META_FLAG_RX_NOW;
  
  if (2*nsamples > CONVERT_BUFFER_SIZE) {
    fprintf(stderr, "RX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
    return -1;
  }
  status = bladerf_sync_rx(handler->dev, handler->rx_buffer, nsamples, &meta, 2000);
  if (status) {
    fprintf(stderr, "RX failed: %s\n\n", bladerf_strerror(status));
    return -1;
  } else if (meta.status & BLADERF_META_STATUS_OVERRUN) {
    if (blade_error_handler) {
      srslte_rf_error_t error; 
      error.opt = meta.actual_count;
      error.type = SRSLTE_RF_ERROR_OVERFLOW;
      blade_error_handler(error);
    } else {     
      fprintf(stderr, "Overrun detected in scheduled RX. "
            "%u valid samples were read.\n\n", meta.actual_count);
    }
  }
  
  timestamp_to_secs(handler->rx_rate, meta.timestamp, secs, frac_secs);
  srslte_vec_convert_if(handler->rx_buffer, data, 2048, 2*nsamples);
  
  return nsamples;
}
示例#4
0
// Fetch a bunch of samples from the device.
bool BladeRFSource::get_samples(IQSampleVector *samples)
{
    int res;
    std::vector<int16_t> buf(2*m_blockSize);

    if ((res = bladerf_sync_rx(m_this->m_dev, buf.data(), m_blockSize, 0, 10000)) < 0)
    {
        m_this->m_error = "bladerf_sync_rx failed";
        return false;
    }

    samples->resize(m_blockSize);

    for (int i = 0; i < m_blockSize; i++)
    {
        int16_t re = buf[2*i];
        int16_t im = buf[2*i+1];
        (*samples)[i] = IQSample(re, im);
    }

    return true;
}
示例#5
0
int rx_avg_magnitude(struct bladerf *dev, int16_t *samples,
                     int16_t dc_i, int16_t dc_q, float *avg_magnitude)
{
    int status;
    unsigned int i;
    float var_i, var_q;

    status = set_tx_dc(dev, dc_i, dc_q);
    if (status != 0) {
        return status;
    }

    /* Flush out samples and read a buffer's worth of data */
    for (i = 0; i < 2 * CAL_NUM_BUFS + 1; i++) {
        status = bladerf_sync_rx(dev, samples, CAL_BUF_LEN, NULL, CAL_TIMEOUT);
        if (status != 0) {
            return status;
        }
    }

    variance(samples, &var_i, &var_q);
    *avg_magnitude = (float) sqrt(var_i + var_q);
    return status;
}
示例#6
0
文件: sync_rxtx.c 项目: Nuand/bladeRF
int sync_rx_example(struct bladerf *dev)
{
    int status, ret;
    bool done         = false;
    bool have_tx_data = false;

    /** [user_buffers] */

    /* "User" samples buffers and their associated sizes, in units of samples.
     * Recall that one sample = two int16_t values. */
    int16_t *rx_samples            = NULL;
    int16_t *tx_samples            = NULL;
    const unsigned int samples_len = 10000; /* May be any (reasonable) size */

    /* Allocate a buffer to store received samples in */
    rx_samples = malloc(samples_len * 2 * 1 * sizeof(int16_t));
    if (rx_samples == NULL) {
        perror("malloc");
        return BLADERF_ERR_MEM;
    }

    /* Allocate a buffer to prepare transmit data in */
    tx_samples = malloc(samples_len * 2 * 1 * sizeof(int16_t));
    if (tx_samples == NULL) {
        perror("malloc");
        free(rx_samples);
        return BLADERF_ERR_MEM;
    }

    /** [user_buffers] */

    /* Initialize synch interface on RX and TX */
    status = init_sync(dev);
    if (status != 0) {
        goto out;
    }

    /** [enable_modules] */

    status = bladerf_enable_module(dev, BLADERF_RX, true);
    if (status != 0) {
        fprintf(stderr, "Failed to enable RX: %s\n", bladerf_strerror(status));
        goto out;
    }

    status = bladerf_enable_module(dev, BLADERF_TX, true);
    if (status != 0) {
        fprintf(stderr, "Failed to enable TX: %s\n", bladerf_strerror(status));
        goto out;
    }

    /** [enable_modules] */
    /** [rxtx_loop] */

    while (status == 0 && !done) {
        /* Receive samples */
        status = bladerf_sync_rx(dev, rx_samples, samples_len, NULL, 5000);
        if (status == 0) {
            /* Process these samples, and potentially produce a response
             * to transmit */
            done = do_work(rx_samples, samples_len, &have_tx_data, tx_samples,
                           samples_len);

            if (!done && have_tx_data) {
                /* Transmit a response */
                status =
                    bladerf_sync_tx(dev, tx_samples, samples_len, NULL, 5000);

                if (status != 0) {
                    fprintf(stderr, "Failed to TX samples: %s\n",
                            bladerf_strerror(status));
                }
            }
        } else {
            fprintf(stderr, "Failed to RX samples: %s\n",
                    bladerf_strerror(status));
        }
    }

    if (status == 0) {
        /* Wait a few seconds for any remaining TX samples to finish
         * reaching the RF front-end */
        usleep(2000000);
    }

/** [rxtx_loop] */

out:
    ret = status;

    /** [disable_modules] */

    /* Disable RX, shutting down our underlying RX stream */
    status = bladerf_enable_module(dev, BLADERF_RX, false);
    if (status != 0) {
        fprintf(stderr, "Failed to disable RX: %s\n", bladerf_strerror(status));
    }

    /* Disable TX, shutting down our underlying TX stream */
    status = bladerf_enable_module(dev, BLADERF_TX, false);
    if (status != 0) {
        fprintf(stderr, "Failed to disable TX: %s\n", bladerf_strerror(status));
    }


    /* Free up our resources */
    free(rx_samples);
    free(tx_samples);

    /** [disable_modules] */

    return ret;
}
示例#7
0
void *rx_task(void *args)
{
    struct test *t = (struct test *) args;
    int16_t *samples;
    int status;
    unsigned int burst_num;
    struct bladerf_metadata meta;
    unsigned int idx;
    state curr_state, next_state;
    uint64_t burst_start, burst_end, burst_end_prev;
    bool stop;
    unsigned int transient_delay = 0;

#if ENABLE_RX_FILE
    FILE *debug = fopen("debug.bin", "wb");
    if (!debug) {
        perror("fopen");
    }
#endif

    samples = (int16_t*) malloc(2 * sizeof(samples[0]) * t->params->buf_size);
    if (samples == NULL) {
        perror("malloc");
        return NULL;
    }

    idx = 0;
    status = 0;
    burst_num = 0;

    memset(&meta, 0, sizeof(meta));
    meta.flags |= BLADERF_META_FLAG_RX_NOW;

    curr_state = GET_SAMPLES;
    next_state = FLUSH_INITIAL_SAMPLES;
    burst_start = burst_end = burst_end_prev = 0;
    stop = false;

    while (status == 0 && burst_num < t->num_bursts && !stop) {
        switch (curr_state) {
            case GET_SAMPLES:
                status = bladerf_sync_rx(t->dev, samples, t->params->buf_size,
                                         &meta, t->params->timeout_ms);

                if (status != 0) {
                    fprintf(stderr, "RX failed in burst %-4u: %s\n",
                            burst_num, bladerf_strerror(status));
                } else if (meta.status & BLADERF_META_STATUS_OVERRUN) {
                    fprintf(stderr, "Error: RX overrun detected.\n");
                    pthread_mutex_lock(&t->lock);
                    t->stop = true;
                    t->rx_ready = true;
                    pthread_mutex_unlock(&t->lock);
                } else {
                    /*
                    printf("Read %-8u samples @ 0x%08"PRIx64" (%-8"PRIu64")\n",
                           t->params->buf_size, meta.timestamp, meta.timestamp);
                    */

#if ENABLE_RX_FILE
                    fwrite(samples, 2 * sizeof(samples[0]), t->params->buf_size, debug);
#endif
                }

                idx = 0;
                curr_state = next_state;
                break;

            case FLUSH_INITIAL_SAMPLES:
            {
                bool had_transient_spike = false;
                curr_state = GET_SAMPLES;
                next_state = FLUSH_INITIAL_SAMPLES;

                for (; idx < (2 * t->params->buf_size); idx += 2) {
                    const uint32_t sig_pow =
                        samples[idx] * samples[idx] +
                        samples[idx + 1] * samples[idx + 1];


                    /* Keep flushing samples if we encounter any transient "ON"
                     * samples prior to the TX task being started. */
                    if (sig_pow >= RX_POWER_THRESH) {
                        had_transient_spike = true;
                        fprintf(stderr, "Flushed an initial buffer due to a "
                                "transient spike.\n");
                        break;
                    }
                }

                if (had_transient_spike) {
                    /* Reset transient delay counter */
                    transient_delay = 0;
                } else {
                    transient_delay++;

                    if (transient_delay == 10) {
                        /* After 10 buffers of no transients, we've most likely
                         * rid ourselves of any junk in the RX FIFOs and are
                         * ready to start the test */
                        next_state = WAIT_FOR_BURST_START;
                        pthread_mutex_lock(&t->lock);
                        t->rx_ready = true;
                        pthread_mutex_unlock(&t->lock);
                    }
                }
                break;
            }

            case WAIT_FOR_BURST_START:
                for (; idx < (2 * t->params->buf_size); idx += 2) {
                    const uint32_t sig_pow =
                        samples[idx] * samples[idx] +
                        samples[idx + 1] * samples[idx + 1];

                    if (sig_pow >= RX_POWER_THRESH) {
                        burst_start = meta.timestamp + (idx / 2);
                        burst_end_prev = burst_end;
                        burst_end = 0;

                        curr_state = WAIT_FOR_BURST_END;
                        assert(burst_start > burst_end_prev);

                        if (burst_num != 0) {
                            const uint64_t gap = burst_start - burst_end_prev;
                            uint64_t delta;

                            if (gap > t->bursts[burst_num].gap) {
                                delta = gap - t->bursts[burst_num].gap;
                            } else {
                                delta = t->bursts[burst_num].gap - gap;
                            }

                            if (delta > 1) {
                                status = BLADERF_ERR_UNEXPECTED;
                                fprintf(stderr, "Burst #%-4u Failed. "
                                        " Gap varied by %"PRIu64 " samples."
                                        " Expected=%-8"PRIu64
                                        " rx'd=%-8"PRIu64"\n",
                                        burst_num + 1, delta,
                                        t->bursts[burst_num].gap, gap);
                            }
                        }
                        break;
                    }
                }

                /* Need to fetch more samples */
                if (idx >= (2 * t->params->buf_size)) {
                    next_state = curr_state;
                    curr_state = GET_SAMPLES;
                }

                break;

            case WAIT_FOR_BURST_END:
                for (; idx < (2 * t->params->buf_size); idx += 2) {
                    const uint32_t sig_pow =
                        samples[idx] * samples[idx] +
                        samples[idx + 1] * samples[idx + 1];

                    if (sig_pow < RX_POWER_THRESH) {
                        uint64_t duration, delta;

                        burst_end = meta.timestamp + (idx / 2);
                        assert(burst_end > burst_start);
                        duration = burst_end - burst_start;

                        if (duration > t->bursts[burst_num].duration) {
                            delta  = duration - t->bursts[burst_num].duration;
                        } else {
                            delta  = t->bursts[burst_num].duration - duration;
                        }

                        if (delta > 1) {
                            status = BLADERF_ERR_UNEXPECTED;
                            fprintf(stderr, "Burst #%-4u Failed. "
                                    "Duration varied by %"PRIu64" samples. "
                                    "Expected=%-8"PRIu64"rx'd=%-8"PRIu64"\n",
                                    burst_num + 1, delta,
                                    t->bursts[burst_num].duration, duration);

                        } else {
                            const uint64_t gap =
                                (burst_num == 0) ? 0 : t->bursts[burst_num].gap;

                            printf("Burst #%-4u Passed. gap=%-8"PRIu64
                                   "duration=%-8"PRIu64"\n",
                                   burst_num + 1, gap,
                                   t->bursts[burst_num].duration);

                            curr_state = WAIT_FOR_BURST_START;
                            burst_num++;
                        }

                        break;
                    }
                }

                /* Need to fetch more samples */
                if (idx >= (2 * t->params->buf_size)) {
                    next_state = curr_state;
                    curr_state = GET_SAMPLES;
                }

                break;
        }

        pthread_mutex_lock(&t->lock);
        stop = t->stop;
        pthread_mutex_unlock(&t->lock);
    }

    free(samples);

#if ENABLE_RX_FILE
    fclose(debug);
#endif

    /* Ensure the TX side is signalled to stop, if it isn't already */
    pthread_mutex_lock(&t->lock);
    t->stop = true;
    pthread_mutex_unlock(&t->lock);

    return NULL;
}
示例#8
0
static int run(struct bladerf *dev, struct app_params *p,
               int16_t *samples, const struct test_case *t)
{
    int status, status_out;
    struct bladerf_metadata meta;
    uint64_t timestamp;
    unsigned int gap;
    uint32_t counter;
    uint64_t tscount_diff;
    unsigned int i;
    bool suppress_overrun_msg = false;
    unsigned int overruns = 0;
    bool prev_iter_overrun = false;

    /* Clear out metadata and request that we just received any available
     * samples, with the timestamp filled in for us */
    memset(&meta, 0, sizeof(meta));
    meta.flags = BLADERF_META_FLAG_RX_NOW;

    status = enable_counter_mode(dev, true);
    if (status != 0) {
        goto out;
    }

    status = perform_sync_init(dev, BLADERF_MODULE_RX, 0, p);
    if (status != 0) {
        goto out;
    }

    /* Initial read to get a starting timestamp, and counter value */
    gap = get_gap(p, t);
    status = bladerf_sync_rx(dev, samples, gap, &meta, p->timeout_ms);
    if (status != 0) {
        fprintf(stderr, "Intial RX failed: %s\n", bladerf_strerror(status));
        goto out;
    }

    counter = extract_counter_val((uint8_t*) samples);
    timestamp = meta.timestamp;

    assert(timestamp >= (uint64_t) counter);
    tscount_diff = timestamp - (uint64_t) counter;

    if (t->gap != 0) {
        printf("\nTest Case: Read size=%"PRIu64" samples, %u iterations\n",
                t->gap, t->iterations);
    } else {
        printf("\nTest Case: Random read size, %u iterations\n", t->iterations);
    }

    printf("--------------------------------------------------------\n");

    assert((timestamp - tscount_diff) <= UINT32_MAX);
    status = check_data(samples, &meta, UINT64_MAX,
                        (uint32_t) (timestamp - tscount_diff),
                        meta.actual_count, &suppress_overrun_msg);

    if (status == DETECTED_OVERRUN) {
        overruns++;
        status = 0;
    }

    printf("Timestamp-counter diff: %"PRIu64"\n", tscount_diff);
    printf("Initial timestamp:      0x%016"PRIx64"\n", meta.timestamp);
    printf("Intital counter value:  0x%08"PRIx32"\n", counter);
    printf("Initial status:         0x%08"PRIu32"\n", meta.status);

    for (i = 0; i < t->iterations && status == 0; i++) {

        timestamp = meta.timestamp + gap;
        gap = get_gap(p, t);

        status = bladerf_sync_rx(dev, samples, gap, &meta, p->timeout_ms);
        if (status != 0) {
            fprintf(stderr, "RX %u failed: %s\n", i, bladerf_strerror(status));
            goto out;
        }

        /* If an overrun occured on the previous iteration, we don't know what
         * the timestamp will actually be on this iteration. */
        if (prev_iter_overrun) {
            timestamp = meta.timestamp;
        }

        status = check_data(samples, &meta, timestamp,
                            (uint32_t) (timestamp - tscount_diff),
                            gap, &suppress_overrun_msg);

        if (status == DETECTED_OVERRUN) {
            overruns++;
            status = 0;

            prev_iter_overrun = true;
        }
    }

    if (status != 0) {
        printf("Test failed due to errors.\n");
    } else if (overruns != 0) {
        printf("Test failed due to %u overruns.\n", overruns);
        status = -1;
    } else {
        printf("Test passed.\n");
    }

out:
    status_out = bladerf_enable_module(dev, BLADERF_MODULE_RX, false);
    if (status_out != 0) {
        fprintf(stderr, "Failed to disable RX module: %s\n",
                bladerf_strerror(status));
    }

    status = first_error(status, status_out);

    status_out = enable_counter_mode(dev, false);
    status = first_error(status, status_out);

    return status;
}
示例#9
0
/** [example_snippet] */
int sync_rx_example(struct bladerf *dev)
{
    int status, ret;
    bool done = false;

    /* "User" samples buffers and their associated sizes, in units of samples.
     * Recall that one sample = two int16_t values. */
    int16_t *rx_samples = NULL;
    int16_t *tx_samples = NULL;
    const unsigned int samples_len = 10000; /* May be any (reasonable) size */

    /* These items configure the underlying asynch stream used by the sync
     * interface. The "buffer" here refers to those used internally by worker
     * threads, not the `samples` buffer above. */
    const unsigned int num_buffers = 16;
    const unsigned int buffer_size = 8192;  /* Must be a multiple of 1024 */
    const unsigned int num_transfers = 8;
    const unsigned int timeout_ms  = 3500;


    /* Allocate a buffer to store received samples in */
    rx_samples = malloc(samples_len * 2 * sizeof(int16_t));
    if (rx_samples == NULL) {
        perror("malloc");
        return BLADERF_ERR_MEM;
    }

    /* Allocate a buffer to prepare transmit data in */
    tx_samples = malloc(samples_len * 2 * sizeof(int16_t));
    if (tx_samples == NULL) {
        perror("malloc");
        free(rx_samples);
        return BLADERF_ERR_MEM;
    }

    /* Configure both the device's RX and TX modules for use with the synchronous
     * interface. SC16 Q11 samples *without* metadata are used. */
    status = bladerf_sync_config(dev,
            BLADERF_MODULE_RX,
            BLADERF_FORMAT_SC16_Q11,
            num_buffers,
            buffer_size,
            num_transfers,
            timeout_ms);

    if (status != 0) {
        fprintf(stderr, "Failed to configure RX sync interface: %s\n",
                bladerf_strerror(status));
        goto out;
    }

    status = bladerf_sync_config(dev,
                                 BLADERF_MODULE_TX,
                                 BLADERF_FORMAT_SC16_Q11,
                                 num_buffers,
                                 buffer_size,
                                 num_transfers,
                                 timeout_ms);

    if (status != 0) {
        fprintf(stderr, "Failed to configure TX sync interface: %s\n",
                bladerf_strerror(status));
        goto out;
    }

    /* We must always enable the modules *after* calling bladerf_sync_config(),
     * and *before* attempting to RX or TX samples. */
    status = bladerf_enable_module(dev, BLADERF_MODULE_RX, true);
    if (status != 0) {
        fprintf(stderr, "Failed to enable RX module: %s\n",
                bladerf_strerror(status));
        goto out;
    }

    status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true);
    if (status != 0) {
        fprintf(stderr, "Failed to enable RX module: %s\n",
                bladerf_strerror(status));
        goto out;
    }

    /* Receive samples and do work on them and then transmit a response.
     *
     * Note we transmit more than `buffer_size` samples to ensure that our
     * samples are written to the FPGA. (The samples are sent when the
     * synchronous interface's internal buffer of `buffer_size` samples is
     * filled.) This is generally not nececssary if you are continuously
     * streaming TX data. Otherwise, you may need to zero-pad your TX data to
     * achieve this.
     */
    while (status == 0 && !done) {
        status = bladerf_sync_rx(dev, rx_samples, samples_len, NULL, 5000);
        if (status == 0) {
            done = do_work(rx_samples, samples_len,
                           tx_samples, samples_len);

            if (!done) {
                status = bladerf_sync_tx(dev, tx_samples, samples_len,
                                         NULL, 5000);

                if (status != 0) {
                    fprintf(stderr, "Failed to TX samples: %s\n",
                            bladerf_strerror(status));
                }
            }
        } else {
            fprintf(stderr, "Failed to RX samples: %s\n",
                    bladerf_strerror(status));
        }
    }

    if (status == 0) {
        /* Wait a few seconds for any remaining TX samples to finish */
        usleep(2000000);
    }


out:
    ret = status;

    /* Disable RX module, shutting down our underlying RX stream */
    status = bladerf_enable_module(dev, BLADERF_MODULE_RX, false);
    if (status != 0) {
        fprintf(stderr, "Failed to disable RX module: %s\n",
                bladerf_strerror(status));
    }

    /* Disable TX module, shutting down our underlying TX stream */
    status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false);
    if (status != 0) {
        fprintf(stderr, "Failed to disable TX module: %s\n",
                bladerf_strerror(status));
    }

    /* Free up our resources */
    free(rx_samples);
    free(tx_samples);

    return ret;
}