예제 #1
0
파일: bladegps.c 프로젝트: mfkiwl/bladeGPS
void *tx_task(void *arg)
{
	sim_t *s = (sim_t *)arg;
	size_t samples_populated;

	while (1) {
		int16_t *tx_buffer_current = s->tx.buffer;
		unsigned int buffer_samples_remaining = SAMPLES_PER_BUFFER;

		while (buffer_samples_remaining > 0) {
			
			samples_populated = fifo_read(tx_buffer_current, 
						buffer_samples_remaining,
						s);

			if (is_fifo_write_ready(s)) {
				pthread_cond_signal(&(s->fifo_write_ready));
				/*
				printf("\rTime = %4.1f", s->time);
				s->time += 0.1;
				fflush(stdout);
				*/
			}

			// Advance the buffer pointer.
			buffer_samples_remaining -= (unsigned int)samples_populated;
			tx_buffer_current += (2 * samples_populated);
		}

		// If there were no errors, transmit the data buffer.
		bladerf_sync_tx(s->tx.dev, s->tx.buffer, SAMPLES_PER_BUFFER, NULL, TIMEOUT_MS);
	}
}
예제 #2
0
static inline int dummy_tx(struct bladerf *dev)
{
    int status;
    const unsigned int buf_len = CAL_BUF_LEN;
    uint16_t *buf = (uint16_t*) calloc(2 * buf_len, sizeof(buf[0]));

    if (buf == NULL) {
        return BLADERF_ERR_MEM;
    }

    status = bladerf_sync_config(dev, BLADERF_MODULE_TX,
                                 BLADERF_FORMAT_SC16_Q11,
                                 CAL_NUM_BUFS, buf_len,
                                 CAL_NUM_XFERS, CAL_TIMEOUT);

    if (status != 0) {
        goto error;
    }

    status = bladerf_sync_tx(dev, buf, buf_len, NULL, CAL_TIMEOUT);

error:
    free(buf);
    return status;
}
void BladeRfTxComponent::process()
{
    //Get a DataSet from the input DataBuffer
    DataSet< complex<float> >* readDataSet = NULL;
    inBuf_->getReadData(readDataSet);

    // Check if we have to append dummy frames, samps must be multiple of 1024
    size_t size = readDataSet->data.size();
    if (size % BLADERF_SAMPLE_BLOCK_SIZE != 0) {
        int num_samps_to_append = BLADERF_SAMPLE_BLOCK_SIZE - (size % BLADERF_SAMPLE_BLOCK_SIZE);
        std::vector<std::complex<float> > samples(num_samps_to_append, std::complex<float>(0.0, 0.0));
        readDataSet->data.insert(readDataSet->data.end(), samples.begin(), samples.end());
        size += num_samps_to_append;
    }

    // Adjust raw buffer if needed
    if (rawSampleBuffer_.data.capacity() < size) rawSampleBuffer_.data.resize(size);

    // convert samples to bladeRF format
    for (int i = 0; i < size; i++) {
        rawSampleBuffer_.data[i].real(0xa000 | (int16_t)((readDataSet->data[i].real()) * 2000));
        rawSampleBuffer_.data[i].imag(0x5000 | (int16_t)((readDataSet->data[i].imag()) * 2000));
    }

    // Write samples to device
    int ret = bladerf_sync_tx(device_, &(rawSampleBuffer_.data.front()), size, NULL, BLADERF_SYNC_TIMEOUT_MS);
    if (ret != 0) {
        throw IrisException("Failed to send samples to device!");
        LOG(LERROR) << bladerf_strerror(ret);
    }

    //Release the DataSet
    inBuf_->releaseReadData(readDataSet);
}
예제 #4
0
static void * exec_tx_task(void *args)
{
    bool run;
    int status = 0;
    struct cal_tx_task *task = (struct cal_tx_task*) args;

    MUTEX_LOCK(&task->lock);
    run = task->run;
    MUTEX_UNLOCK(&task->lock);

    while (run && status == 0) {
        status = bladerf_sync_tx(task->s->dev, task->samples, CAL_BUF_LEN,
                                 NULL, CAL_TIMEOUT);


        MUTEX_LOCK(&task->lock);
        run = task->run;
        MUTEX_UNLOCK(&task->lock);
    }

    MUTEX_LOCK(&task->lock);
    task->status = status;
    MUTEX_UNLOCK(&task->lock);

    return NULL;
}
예제 #5
0
/** [tx_meta_now] */
int sync_tx_meta_now_example(struct bladerf *dev, int16_t *samples,
                             unsigned int num_samples, unsigned int tx_count,
                             unsigned int timeout_ms)
{
    int status = 0;
    struct bladerf_metadata meta;
    unsigned int i;

    memset(&meta, 0, sizeof(meta));

    /* Send entire burst worth of samples in one function call */
    meta.flags = BLADERF_META_FLAG_TX_BURST_START |
                 BLADERF_META_FLAG_TX_NOW |
                 BLADERF_META_FLAG_TX_BURST_END;

    for (i = 0; i < tx_count && status == 0; i++) {
        /* Fetch or produce IQ samples...*/
        produce_samples(samples, num_samples);

        status = bladerf_sync_tx(dev, samples, num_samples, &meta, timeout_ms);
        if (status != 0) {
            fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
        } else {
            uint64_t curr_ts;

            status = bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &curr_ts);
            if (status != 0) {
                fprintf(stderr, "Failed to get current TX timestamp: %s\n",
                        bladerf_strerror(status));
            } else {
                printf("TX'd at approximately t=%016"PRIu64"\n", curr_ts);
            }

            /* Delay next transmission by approximately 5 ms
             *
             * This is a very imprecise, "quick and dirty" means to do so in
             * cases where no particular intra-burst time is required. */
            usleep(5000);
        }
    }

    /* Wait for samples to be TX'd before completing.  */
    if (status == 0) {
        status = bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp);
        if (status != 0) {
            fprintf(stderr, "Failed to get current TX timestamp: %s\n",
                    bladerf_strerror(status));
            return status;
        } else {
            status = wait_for_timestamp(dev, BLADERF_MODULE_TX,
                                        meta.timestamp + 2 * num_samples,
                                        timeout_ms);
            if (status != 0) {
                fprintf(stderr, "Failed to wait for timestamp.\n");
            }
        }
    }

    return status;
}
예제 #6
0
void *tx_task(void *arg)
{
	sim_t *s = (sim_t *)arg;
	size_t samples_populated;

	while (1) {
		int16_t *tx_buffer_current = s->tx.buffer;
		unsigned int buffer_samples_remaining = SAMPLES_PER_BUFFER;

		while (buffer_samples_remaining > 0) {
			
			pthread_mutex_lock(&(s->gps.lock));
			while (get_sample_length(s) == 0)
			{
				pthread_cond_wait(&(s->fifo_read_ready), &(s->gps.lock));
			}
//			assert(get_sample_length(s) > 0);

			samples_populated = fifo_read(tx_buffer_current,
				buffer_samples_remaining,
				s);
			pthread_mutex_unlock(&(s->gps.lock));

			pthread_cond_signal(&(s->fifo_write_ready));
#if 0
			if (is_fifo_write_ready(s)) {
				/*
				printf("\rTime = %4.1f", s->time);
				s->time += 0.1;
				fflush(stdout);
				*/
			}
			else if (is_finished_generation(s))
			{
				goto out;
			}
#endif
			// Advance the buffer pointer.
			buffer_samples_remaining -= (unsigned int)samples_populated;
			tx_buffer_current += (2 * samples_populated);
		}

		// If there were no errors, transmit the data buffer.
		bladerf_sync_tx(s->tx.dev, s->tx.buffer, SAMPLES_PER_BUFFER, NULL, TIMEOUT_MS);
		if (is_fifo_write_ready(s)) {
			/*
			printf("\rTime = %4.1f", s->time);
			s->time += 0.1;
			fflush(stdout);
			*/
		}
		else if (is_finished_generation(s))
		{
			goto out;
		}

	}
out:
	return NULL;
}
예제 #7
0
static void * exec_tx_task(void *args)
{
    bool run;
    int status = 0;
    struct cal_tx_task *task = (struct cal_tx_task*) args;

    pthread_mutex_lock(&task->lock);
    run = task->run;
    pthread_mutex_unlock(&task->lock);

    while (run && status == 0) {
        status = bladerf_sync_tx(task->dev, task->samples, CAL_BUF_LEN,
                                 NULL, CAL_TIMEOUT);


        pthread_mutex_lock(&task->lock);
        run = task->run;
        pthread_mutex_unlock(&task->lock);
    }

    pthread_mutex_lock(&task->lock);
    task->status = status;
    pthread_mutex_unlock(&task->lock);

    return NULL;
}
예제 #8
0
/** [tx_meta_sched] */
int sync_tx_meta_sched_example(struct bladerf *dev,
                             int16_t *samples, unsigned int num_samples,
                             unsigned int tx_count, unsigned int samplerate,
                             unsigned int timeout_ms)
{
    int status = 0;
    unsigned int i;
    struct bladerf_metadata meta;

    memset(&meta, 0, sizeof(meta));

    /* Send entire burst worth of samples in one function call */
    meta.flags = BLADERF_META_FLAG_TX_BURST_START |
                 BLADERF_META_FLAG_TX_BURST_END;

    /* Retrieve the current timestamp so we can schedule our transmission
     * in the future. */
    status = bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp);
    if (status != 0) {
        fprintf(stderr, "Failed to get current TX timestamp: %s\n",
                bladerf_strerror(status));
        return status;
    } else {
        printf("Current TX timestamp: %016"PRIu64"\n", meta.timestamp);
    }

    for (i = 0; i < tx_count && status == 0; i++) {
        /* Get sample to transmit... */
        produce_samples(samples, num_samples);

        /* Schedule burst 5 ms into the future */
        meta.timestamp += samplerate / 200;

        status = bladerf_sync_tx(dev, samples, num_samples, &meta, timeout_ms);
        if (status != 0) {
            fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
            return status;
        } else {
            printf("TX'd @ t=%016"PRIu64"\n", meta.timestamp);
        }
    }

    /* Wait for samples to finish being transmitted. */
    if (status == 0) {
        meta.timestamp += 2 * num_samples;

        status = wait_for_timestamp(dev, BLADERF_MODULE_TX,
                                    meta.timestamp, timeout_ms);

        if (status != 0) {
            fprintf(stderr, "Failed to wait for timestamp.\n");
        }
    }

    return status;
}
예제 #9
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;
}
예제 #10
0
static void * tx_task(void *args)
{
    int status;
    int16_t *samples;
    unsigned int i;
    struct bladerf_metadata meta;
    uint64_t samples_left;
    struct test *t = (struct test *) args;
    bool stop = false;
    int16_t zeros[] = { 0, 0, 0, 0 };

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

    memset(&meta, 0, sizeof(meta));

    for (i = 0; i < (2 * t->params->buf_size); i += 2) {
        samples[i] = samples[i + 1] = TX_MAGNITUDE;
    }

    status = bladerf_get_timestamp(t->dev, BLADERF_MODULE_TX, &meta.timestamp);
    if (status != 0) {
        fprintf(stderr, "Failed to get current timestamp: %s\n",
                bladerf_strerror(status));
    }

    meta.timestamp += 400000;

    for (i = 0; i < t->num_bursts && !stop; i++) {
        meta.flags = BLADERF_META_FLAG_TX_BURST_START;
        samples_left = t->bursts[i].duration;

        assert(samples_left <= UINT_MAX);

        if (i != 0) {
            meta.timestamp += (t->bursts[i-1].duration + t->bursts[i].gap);
        }

        while (samples_left != 0 && status == 0) {
            unsigned int to_send = uint_min(t->params->buf_size,
                                            (unsigned int) samples_left);

            status = bladerf_sync_tx(t->dev, samples, to_send, &meta,
                                     t->params->timeout_ms);

            if (status != 0) {
                fprintf(stderr, "Failed to TX @ burst %-4u with %"PRIu64
                        " samples left: %s\n",
                        i + 1, samples_left, bladerf_strerror(status));

                /* Stop the RX worker */
                pthread_mutex_lock(&t->lock);
                t->stop = true;
                pthread_mutex_unlock(&t->lock);
            }

            meta.flags &= ~BLADERF_META_FLAG_TX_BURST_START;
            samples_left -= to_send;
        }

        /* Flush TX samples by ensuring we have 2 zero samples at the end
         * of our burst (as required by libbladeRF) */
        if (status == 0) {
            meta.flags = BLADERF_META_FLAG_TX_BURST_END;
            status = bladerf_sync_tx(t->dev, zeros, 2, &meta,
                                     t->params->timeout_ms);

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

                /* Stop the RX worker */
                pthread_mutex_lock(&t->lock);
                t->stop = true;
                pthread_mutex_unlock(&t->lock);
            }
        }

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

    /* Wait for samples to finish */
    printf("TX: Waiting for samples to finish.\n");
    fflush(stdout);
    status = wait_for_timestamp(t->dev, BLADERF_MODULE_TX,
                                meta.timestamp + t->bursts[i - 1].duration,
                                3000);

    if (status != 0) {
        fprintf(stderr, "Failed to wait for TX to complete: %s\n",
                bladerf_strerror(status));
    }

    free(samples);

    printf("TX: Exiting task.\n");
    fflush(stdout);
    return NULL;
}
예제 #11
0
/** [tx_meta_update] */
int sync_tx_meta_update_example(struct bladerf *dev,
                                int16_t *samples, unsigned int num_samples,
                                unsigned int tx_count, unsigned int samplerate,
                                unsigned int timeout_ms)
{
    int status = 0;
    unsigned int i;
    struct bladerf_metadata meta;
    int16_t zeros[] = { 0, 0, 0, 0 }; /* Two 0+0j samples */

    memset(&meta, 0, sizeof(meta));

    /* The first call to bladerf_sync_tx() will start our long "burst" at
     * a specific timestamp.
     *
     * In successive calls, we'll break this long "burst" up into shorter bursts
     * by using the BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP flag with new
     * timestamps.  The discontinuities will be zero-padded.
     */
    meta.flags = BLADERF_META_FLAG_TX_BURST_START;

    /* Retrieve the current timestamp so we can schedule our transmission
     * in the future. */
    status = bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp);
    if (status != 0) {
        fprintf(stderr, "Failed to get current TX timestamp: %s\n",
                bladerf_strerror(status));
        return status;
    } else {
        printf("Current TX timestamp: %016"PRIu64"\n", meta.timestamp);
    }

    /* Start 5 ms in the future */
    meta.timestamp += samplerate / 200;

    for (i = 0; i < tx_count && status == 0; i++) {
        /* Get sample to transmit... */
        produce_samples(samples, num_samples);

        status = bladerf_sync_tx(dev, samples, num_samples, &meta, timeout_ms);
        if (status != 0) {
            fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
            return status;
        } else {
            printf("TX'd @ t=%016"PRIu64"\n", meta.timestamp);
        }

        /* Instruct bladerf_sync_tx() to position samples within this burst at
         * the specified timestamp. 0+0j will be transmitted up until that
         * point. */
        meta.flags = BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP;

        /* Schedule samples to be transmitted 1.25 ms after the completion of
         * the previous burst */
        meta.timestamp += num_samples + samplerate / 800;

    }

    /* End the burst and flush remaining samples. */
    meta.flags = BLADERF_META_FLAG_TX_BURST_END;
    status = bladerf_sync_tx(dev, zeros, 2, &meta, timeout_ms);

    /* Wait for samples to finish being transmitted. */
    if (status == 0) {
        meta.timestamp += 2 * num_samples;

        status = wait_for_timestamp(dev, BLADERF_MODULE_TX,
                                    meta.timestamp, timeout_ms);

        if (status != 0) {
            fprintf(stderr, "Failed to wait for timestamp.\n");
        }
    } else {
        fprintf(stderr, "Failed to complete burst: %s\n",
                bladerf_strerror(status));
    }


    return status;
}
예제 #12
0
int rf_blade_send_timed(void *h,
                     void *data,
                     int nsamples,
                     time_t secs,
                     double frac_secs,                      
                     bool has_time_spec,
                     bool blocking,
                     bool is_start_of_burst,
                     bool is_end_of_burst) 
{
  rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
  struct bladerf_metadata meta;
  int status; 
  
  if (!handler->tx_stream_enabled) {
    rf_blade_start_tx_stream(h);
  }
  
  if (2*nsamples > CONVERT_BUFFER_SIZE) {
    fprintf(stderr, "TX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
    return -1;
  }

  srslte_vec_convert_fi(data, handler->tx_buffer, 2048, 2*nsamples);
  
  memset(&meta, 0, sizeof(meta));
  if (is_start_of_burst) {
    if (has_time_spec) {
      secs_to_timestamps(handler->tx_rate, secs, frac_secs, &meta.timestamp);
    } else {
      meta.flags |= BLADERF_META_FLAG_TX_NOW;
    }
    meta.flags |= BLADERF_META_FLAG_TX_BURST_START;
  }
  if (is_end_of_burst) {
    meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
  }
  srslte_rf_error_t error; 
  bzero(&error, sizeof(srslte_rf_error_t));
  
  status = bladerf_sync_tx(handler->dev, handler->tx_buffer, nsamples, &meta, 2000);
  if (status == BLADERF_ERR_TIME_PAST) {
    if (blade_error_handler) {
      error.type = SRSLTE_RF_ERROR_LATE;
      blade_error_handler(error);
    } else {
      fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));      
    }
  } else if (status) {
    fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
    return status;
  } else if (meta.status == BLADERF_META_STATUS_UNDERRUN) {
    if (blade_error_handler) {
      error.type = SRSLTE_RF_ERROR_UNDERFLOW;
      blade_error_handler(error);
    } else {
      fprintf(stderr, "TX warning: underflow detected.\n");
    }
  }
  
  return nsamples;
}
예제 #13
0
/* We've found that running samples through the LMS6 tends to be required
 * for the TX LPF calibration to converge */
static inline int tx_lpf_dummy_tx(struct bladerf *dev)
{
    int status;
    int retval = 0;
    struct bladerf_metadata meta;
    int16_t zero_sample[] = { 0, 0 };

    bladerf_loopback loopback_backup;
    struct bladerf_rational_rate sample_rate_backup;

    memset(&meta, 0, sizeof(meta));

    status = bladerf_get_loopback(dev, &loopback_backup);
    if (status != 0) {
        return status;
    }

    status = bladerf_get_rational_sample_rate(dev, BLADERF_MODULE_TX,
                                              &sample_rate_backup);
    if (status != 0) {
        return status;
    }

    status = bladerf_set_loopback(dev, BLADERF_LB_BB_TXVGA1_RXVGA2);
    if (status != 0) {
        goto out;
    }

    status = bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, 3000000, NULL);
    if (status != 0) {
        goto out;
    }

    status = bladerf_sync_config(dev, BLADERF_MODULE_TX,
                                 BLADERF_FORMAT_SC16_Q11_META,
                                 64, 16384, 16, 1000);
    if (status != 0) {
        goto out;
    }

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

    meta.flags = BLADERF_META_FLAG_TX_BURST_START |
                 BLADERF_META_FLAG_TX_BURST_END   |
                 BLADERF_META_FLAG_TX_NOW;

    status = bladerf_sync_tx(dev, zero_sample, 1, &meta, 2000);
    if (status != 0) {
        goto out;
    }

out:
    status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false);
    if (status != 0 && retval == 0) {
        retval = status;
    }

    status = bladerf_set_rational_sample_rate(dev, BLADERF_MODULE_TX,
                                              &sample_rate_backup, NULL);
    if (status != 0 && retval == 0) {
        retval = status;
    }

    status = bladerf_set_loopback(dev, loopback_backup);
    if (status != 0 && retval == 0) {
        retval = status;
    }

    return retval;
}
예제 #14
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;
}
예제 #15
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;
}
예제 #16
0
static int run(struct bladerf *dev, struct app_params *p,
               const struct test_case *t)
{
    int status, status_out, status_wait;
    unsigned int samples_left;
    size_t i;
    struct bladerf_metadata meta;
    int16_t *samples, *buf;

    samples = calloc(2 * sizeof(int16_t), t->burst_len + 2);
    if (samples == NULL) {
        perror("malloc");
        return BLADERF_ERR_MEM;
    }

    /* Leave the last two samples zero */
    for (i = 0; i < (2 * t->burst_len); i += 2) {
        samples[i] = samples[i + 1] = MAGNITUDE;
    }

    memset(&meta, 0, sizeof(meta));

    status = perform_sync_init(dev, BLADERF_MODULE_TX, t->buf_len, p);
    if (status != 0) {
        goto out;
    }

    status = bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp);
    if (status != 0) {
        fprintf(stderr, "Failed to get timestamp: %s\n",
                bladerf_strerror(status));
        goto out;
    } else {
        printf("Initial timestamp: 0x%016"PRIx64"\n", meta.timestamp);
    }

    meta.timestamp += 200000;


    for (i = 0; i < t->iterations && status == 0; i++) {
        meta.flags = BLADERF_META_FLAG_TX_BURST_START;
        samples_left = t->burst_len + 2;
        buf = samples;


        printf("Sending burst @ %llu\n", (unsigned long long) meta.timestamp);

        while (samples_left && status == 0) {
            unsigned int to_send = uint_min(p->buf_size, samples_left);

            if (to_send == samples_left) {
                meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
            } else {
                meta.flags &= ~BLADERF_META_FLAG_TX_BURST_END;
            }

            status = bladerf_sync_tx(dev, buf, to_send, &meta, 10000); //p->timeout_ms);
            if (status != 0) {
                fprintf(stderr, "TX failed @ iteration (%u) %s\n",
                        (unsigned int )i, bladerf_strerror(status));
            }

            meta.flags &= ~BLADERF_META_FLAG_TX_BURST_START;
            samples_left -= to_send;
            buf += 2 * to_send;
        }

        meta.timestamp += (t->burst_len + t->gap_len - 2);
    }

    printf("Waiting for samples to finish...\n");
    fflush(stdout);

    /* Wait for samples to be transmitted before shutting down the TX module */
    status_wait = wait_for_timestamp(dev, BLADERF_MODULE_TX,
                                     meta.timestamp - t->gap_len + 2,
                                     3000);
    if (status_wait != 0) {
        status = first_error(status, status_wait);
        fprintf(stderr, "Failed to wait for TX to finish: %s\n",
                bladerf_strerror(status_wait));
    }

out:
    status_out = bladerf_enable_module(dev, BLADERF_MODULE_TX, false);
    if (status_out != 0) {
        fprintf(stderr, "Failed to disable TX module: %s\n",
                bladerf_strerror(status));
    } else {
        printf("Done waiting.\n");
        fflush(stdout);
    }

    status = first_error(status, status_out);

    free(samples);
    return status;
}