コード例 #1
0
ファイル: rxtx.c プロジェクト: DanielG/bladeRF
void rxtx_task_exec_stop(struct rxtx_data *rxtx, unsigned char *requests,
                         struct bladerf *dev)
{
    int status;

    *requests = rxtx_get_requests(rxtx,
                                  RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN);

    pthread_mutex_lock(&rxtx->data_mgmt.lock);
    bladerf_deinit_stream(rxtx->data_mgmt.stream);
    rxtx->data_mgmt.stream = NULL;
    pthread_mutex_unlock(&rxtx->data_mgmt.lock);

    pthread_mutex_lock(&rxtx->file_mgmt.file_lock);
    if (rxtx->file_mgmt.file != NULL) {
        fclose(rxtx->file_mgmt.file);
        rxtx->file_mgmt.file = NULL;
    }
    pthread_mutex_unlock(&rxtx->file_mgmt.file_lock);

    if (*requests & RXTX_TASK_REQ_SHUTDOWN) {
        rxtx_set_state(rxtx, RXTX_STATE_SHUTDOWN);
    } else {
        rxtx_set_state(rxtx, RXTX_STATE_IDLE);
    }

    status = bladerf_enable_module(dev, rxtx->module, false);
    if (status < 0) {
        set_last_error(&rxtx->last_error, ETYPE_BLADERF, status);
    }

    *requests = 0;

    rxtx_release_wait(rxtx);
}
コード例 #2
0
ファイル: rx.c プロジェクト: amberadams/bladeRF
static void *rx_callback(struct bladerf *dev,
                         struct bladerf_stream *stream,
                         struct bladerf_metadata *meta,
                         void *samples,
                         size_t num_samples,
                         void *user_data)
{
    struct rx_callback_data *cb_data = (struct rx_callback_data *)user_data;
    struct rxtx_data *rx = cb_data->rx;
    unsigned char requests;
    void *ret;
    size_t n_to_write;

    /* Stop stream on STOP or SHUTDOWN, but only clear STOP. This will keep
     * the SHUTDOWN request around so we can read it when determining
     * our state transition */
    requests = rxtx_get_requests(rx, RXTX_TASK_REQ_STOP);
    if (requests & (RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN)) {
        return NULL;
    }

    pthread_mutex_lock(&rx->data_mgmt.lock);

    if (!cb_data->inf) {
        n_to_write = min_sz(cb_data->samples_left, num_samples);
        cb_data->samples_left -= n_to_write;
    } else {
        n_to_write = num_samples;
    }

    /* We assume we have IQ pairs */
    assert((n_to_write & 1) == 0);

    if (n_to_write > 0) {
        sc16q12_sample_fixup(samples, n_to_write);

        /* Write the samples out */
        cb_data->write_samples(rx, (int16_t*)samples, n_to_write);

        /* Fetch the next buffer */
        rx->data_mgmt.next_idx++;
        rx->data_mgmt.next_idx %= rx->data_mgmt.num_buffers;
        ret = rx->data_mgmt.buffers[rx->data_mgmt.next_idx];
    } else {
        /* We've already written the request number of samples */
        ret = NULL;
    }

    pthread_mutex_unlock(&rx->data_mgmt.lock);
    return ret;
}
コード例 #3
0
ファイル: rxtx.c プロジェクト: HKingz/bladeRF
void rxtx_task_exec_stop(struct rxtx_data *rxtx, unsigned char *requests)
{
    *requests = rxtx_get_requests(rxtx,
                                  RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN);

    MUTEX_LOCK(&rxtx->file_mgmt.file_lock);
    if (rxtx->file_mgmt.file != NULL) {
        fclose(rxtx->file_mgmt.file);
        rxtx->file_mgmt.file = NULL;
    }
    MUTEX_UNLOCK(&rxtx->file_mgmt.file_lock);

    if (*requests & RXTX_TASK_REQ_SHUTDOWN) {
        rxtx_set_state(rxtx, RXTX_STATE_SHUTDOWN);
    } else {
        rxtx_set_state(rxtx, RXTX_STATE_IDLE);
    }

    *requests = 0;

    rxtx_release_wait(rxtx);
}
コード例 #4
0
ファイル: tx.c プロジェクト: anew5tart/bladeRF
static int tx_task_exec_running(struct rxtx_data *tx, struct cli_state *s)
{
    int status = 0;
    unsigned int samples_per_buffer;
    int16_t *tx_buffer;
    struct tx_params *tx_params = tx->params;
    unsigned int repeats_remaining;
    unsigned int delay_us;
    unsigned int delay_samples;
    unsigned int delay_samples_remaining;
    bool repeat_infinite;
    unsigned int timeout_ms;
    unsigned int sample_rate;

    enum state { INIT, READ_FILE, DELAY, PAD_TRAILING, DONE };
    enum state state = INIT;

    /* Fetch the parameters required for the TX operation */
    MUTEX_LOCK(&tx->param_lock);
    repeats_remaining = tx_params->repeat;
    delay_us = tx_params->repeat_delay;
    MUTEX_UNLOCK(&tx->param_lock);

    repeat_infinite = (repeats_remaining == 0);

    MUTEX_LOCK(&tx->data_mgmt.lock);
    samples_per_buffer = (unsigned int)tx->data_mgmt.samples_per_buffer;
    timeout_ms = tx->data_mgmt.timeout_ms;
    MUTEX_UNLOCK(&tx->data_mgmt.lock);

    status = bladerf_get_sample_rate(s->dev, tx->module, &sample_rate);
    if (status != 0) {
        set_last_error(&tx->last_error, ETYPE_BLADERF, status);
        return CLI_RET_LIBBLADERF;
    }

    /* Compute delay time as a sample count */
    delay_samples = (unsigned int)((uint64_t)sample_rate * delay_us / 1000000);
    delay_samples_remaining = delay_samples;

    /* Allocate a buffer to hold each block of samples to transmit */
    tx_buffer = (int16_t*) malloc(samples_per_buffer * 2 * sizeof(int16_t));
    if (tx_buffer == NULL) {
        status = CLI_RET_MEM;
        set_last_error(&tx->last_error, ETYPE_ERRNO,
                       errno == 0 ? ENOMEM : errno);
    }

    /* Keep writing samples while there is more data to send and no failures
     * have occurred */
    while (state != DONE && status == 0) {

        unsigned char requests;
        unsigned int buffer_samples_remaining = samples_per_buffer;
        int16_t *tx_buffer_current = tx_buffer;

        /* Stop stream on STOP or SHUTDOWN, but only clear STOP. This will keep
         * the SHUTDOWN request around so we can read it when determining
         * our state transition */
        requests = rxtx_get_requests(tx, RXTX_TASK_REQ_STOP);
        if (requests & (RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN)) {
            break;
        }

        /* Keep adding to the buffer until it is full or a failure occurs */
        while (buffer_samples_remaining > 0 && status == 0 && state != DONE) {
            size_t samples_populated = 0;

            switch (state) {
                case INIT:
                case READ_FILE:

                    MUTEX_LOCK(&tx->file_mgmt.file_lock);

                    /* Read from the input file */
                    samples_populated = fread(tx_buffer_current,
                                              2 * sizeof(int16_t),
                                              buffer_samples_remaining,
                                              tx->file_mgmt.file);

                    assert(samples_populated <= UINT_MAX);

                    /* If the end of the file was reached, determine whether
                     * to delay, re-read from the file, or pad the rest of the
                     * buffer and finish */
                    if (feof(tx->file_mgmt.file)) {
                        repeats_remaining--;

                        if ((repeats_remaining > 0) || repeat_infinite) {
                            if (delay_samples != 0) {
                                delay_samples_remaining = delay_samples;
                                state = DELAY;
                            }
                        }
                        else {
                            state = PAD_TRAILING;
                        }

                        /* Clear the EOF condition and rewind the file */
                        clearerr(tx->file_mgmt.file);
                        rewind(tx->file_mgmt.file);
                    }

                    /* Check for errors */
                    else if (ferror(tx->file_mgmt.file)) {
                        status = errno;
                        set_last_error(&tx->last_error, ETYPE_ERRNO, status);
                    }

                    MUTEX_UNLOCK(&tx->file_mgmt.file_lock);
                    break;

                case DELAY:
                    /* Insert as many zeros as are necessary to realize the
                     * specified repeat delay */
                    samples_populated = uint_min(buffer_samples_remaining,
                                                 delay_samples_remaining);

                    memset(tx_buffer_current, 0,
                           samples_populated * 2 * sizeof(uint16_t));

                    delay_samples_remaining -= (unsigned int)samples_populated;

                    if (delay_samples_remaining == 0) {
                        state = READ_FILE;
                    }
                    break;

                case PAD_TRAILING:
                    /* Populate the remainder of the buffer with zeros */
                    memset(tx_buffer_current, 0,
                            buffer_samples_remaining * 2 * sizeof(uint16_t));

                    state = DONE;
                    break;

                case DONE:
                default:
                    break;
            }

            /* Advance the buffer pointer.
             * Remember, two int16_t's make up 1 sample in the SC16Q11 format */
            buffer_samples_remaining -= (unsigned int)samples_populated;
            tx_buffer_current += (2 * samples_populated);
        }

        /* If there were no errors, transmit the data buffer */
        if (status == 0) {
            bladerf_sync_tx(s->dev, tx_buffer, samples_per_buffer, NULL,
                            timeout_ms);
        }
    }

    free(tx_buffer);
    return status;
}
コード例 #5
0
ファイル: tx.c プロジェクト: 13572293130/bladeRF
/* This callback reads SC16 Q11 data from a file (assumed to be little endian)
 * and ships this data off in the provided sample buffers */
static void *tx_callback(struct bladerf *dev,
                         struct bladerf_stream *stream,
                         struct bladerf_metadata *meta,
                         void *samples,
                         size_t num_samples,
                         void *user_data)
{
    struct tx_callback_data *cb_data = (struct tx_callback_data*)user_data;
    struct rxtx_data *tx = cb_data->tx;
    struct tx_params *tx_params = tx->params;
    unsigned int delay = cb_data->delay;

    unsigned char requests; /* Requests from main control thread */
    size_t read_status;     /* Status from read() calls */
    size_t n_read;          /* Number of bytes read from file */
    size_t to_read;         /* Temp var, # of samples to read */
    bool zero_pad;          /* We need to zero-pad the rest of the buffer */

    int16_t *samples_int16 = NULL;

    /* Stop stream on STOP or SHUTDOWN, but only clear STOP. This will keep
     * the SHUTDOWN request around so we can read it when determining
     * our state transition */
    requests = rxtx_get_requests(tx, RXTX_TASK_REQ_STOP);
    if (cb_data->done ||
        requests & (RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN)) {
        return NULL;
    }

    /* If we have a delay scheduled...wait around
     * TODO replace this with a buffer filled with the appropriate number
     * of 0's based upon the sample rate */
    if (delay) {
        usleep(delay);
        cb_data->delay = 0;
    }

    pthread_mutex_lock(&tx->data_mgmt.lock);
    pthread_mutex_lock(&tx->file_mgmt.file_lock);

    /* Get the next buffer */
    samples_int16 = (int16_t*)tx->data_mgmt.buffers[tx->data_mgmt.next_idx];
    tx->data_mgmt.next_idx++;
    tx->data_mgmt.next_idx %= tx->data_mgmt.num_buffers;

    n_read = 0;
    zero_pad = false;

    /* Keep reading from the file until we have enough data, or have a
     * a condition in which we'll just zero pad the rest of the buffer */
    while (n_read < tx->data_mgmt.samples_per_buffer && !zero_pad) {
        to_read = 2 * tx->data_mgmt.samples_per_buffer - n_read;
        read_status = fread(samples_int16 + n_read, sizeof(int16_t),
                            to_read, tx->file_mgmt.file);

        if (read_status != to_read && ferror(tx->file_mgmt.file)) {
            set_last_error(&tx->last_error, ETYPE_CLI, CMD_RET_FILEOP);
            samples_int16 = NULL;
            goto tx_callback_out;
        }

        n_read += read_status;

        /* Hit the end of the file */
        if (feof(tx->file_mgmt.file)) {

            /* We're going to repeat from the start of the file  */
            if (cb_data->repeat_inf || --cb_data->repeats_left > 0) {

                pthread_mutex_lock(&tx->param_lock);
                cb_data->delay = tx_params->repeat_delay;
                pthread_mutex_unlock(&tx->param_lock);

                if (fseek(tx->file_mgmt.file, 0, SEEK_SET) < 0) {
                    set_last_error(&tx->last_error, ETYPE_ERRNO, errno);
                    samples_int16 = NULL;
                    goto tx_callback_out;
                }

                /* We have to delay first, so we'll zero out and get some
                 * data in the next callback */
                if (cb_data->delay != 0) {
                    zero_pad = true;
                }
            } else {
                /* No repeats left. Finish off whatever we have and note
                 * that the next callback should start shutting things down */
                zero_pad = true;
                cb_data->done = true;
            }
        }
    }


tx_callback_out:
    pthread_mutex_unlock(&tx->file_mgmt.file_lock);

    if (zero_pad) {
        memset(samples_int16 + n_read, 0,
               tx->data_mgmt.samples_per_buffer - n_read);
    }

    pthread_mutex_unlock(&tx->data_mgmt.lock);

    return samples_int16;
}