/** [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; }
/** [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; }
int read_message(int message_num, int publish, int no_wait) { // char *line[MAX_LINE_LENGTH]; char *line; char *current_pos; int i, j; char command[100]; static double last_update = 0; double current_time; line = (char *) malloc(MAX_LINE_LENGTH * sizeof(char)); if (line == NULL) carmen_die("Could not alloc memory in playback.c:read_message()\n"); carmen_logfile_read_line(logfile_index, logfile, message_num, MAX_LINE_LENGTH, line); current_pos = carmen_next_word(line); for(i = 0; i < (int)(sizeof(logger_callbacks) / sizeof(logger_callback_t)); i++) { /* copy the command over */ j = 0; while(line[j] != ' ') { command[j] = line[j]; j++; } command[j] = '\0'; if(strncmp(command, logger_callbacks[i].logger_message_name, j) == 0) { if(!basic_messages || !logger_callbacks[i].interpreted) { current_pos = logger_callbacks[i].conv_func(current_pos, logger_callbacks[i].message_data); playback_timestamp = atof(current_pos); //printf("command = %s, playback_timestamp = %lf\n", command, playback_timestamp); if(publish) { current_time = carmen_get_time(); if(current_time - last_update > 0.2) { print_playback_status(); last_update = current_time; } if (!no_wait) wait_for_timestamp(playback_timestamp); IPC_publishData(logger_callbacks[i].ipc_message_name, logger_callbacks[i].message_data); } /* return 1 if it is a front laser message */ free(line); return (strcmp(command, "FLASER") == 0); } } } free(line); return 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; }
/** [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; }
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; }