diff options
| author | Ashish Chaudhari <ashish@ettus.com> | 2015-08-10 23:14:20 -0700 | 
|---|---|---|
| committer | Ashish Chaudhari <ashish@ettus.com> | 2015-08-10 23:14:20 -0700 | 
| commit | b5c81677078f56b3e671ebeaca1e3b803c2f4ef9 (patch) | |
| tree | a1b17b4be203331de7e146e94051f26be5a20102 /host/examples/rx_samples_c.c | |
| parent | 16e149fe6fcc1bc18adea3eeeefad2c7ee93b2e0 (diff) | |
| parent | 28327c8e8a810b19da126116d0dc4c26b643baed (diff) | |
| download | uhd-b5c81677078f56b3e671ebeaca1e3b803c2f4ef9.tar.gz uhd-b5c81677078f56b3e671ebeaca1e3b803c2f4ef9.tar.bz2 uhd-b5c81677078f56b3e671ebeaca1e3b803c2f4ef9.zip | |
Merge branch 'master' into ashish/register_api
Diffstat (limited to 'host/examples/rx_samples_c.c')
| -rw-r--r-- | host/examples/rx_samples_c.c | 291 | 
1 files changed, 291 insertions, 0 deletions
| diff --git a/host/examples/rx_samples_c.c b/host/examples/rx_samples_c.c new file mode 100644 index 000000000..b5882b79b --- /dev/null +++ b/host/examples/rx_samples_c.c @@ -0,0 +1,291 @@ +/* + * Copyright 2015 Ettus Research LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <uhd.h> + +#include "getopt.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define EXECUTE_OR_GOTO(label, ...) \ +    if(__VA_ARGS__){ \ +        return_code = EXIT_FAILURE; \ +        goto label; \ +    } + +void print_help(void){ +    fprintf(stderr, "rx_samples_c - A simple RX example using UHD's C API\n\n" + +                    "Options:\n" +                    "    -a (device args)\n" +                    "    -f (frequency in Hz)\n" +                    "    -r (sample rate in Hz)\n" +                    "    -g (gain)\n" +                    "    -n (number of samples to receive)\n" +                    "    -o (output filename, default = \"out.dat\")\n" +                    "    -v (enable verbose prints)\n" +                    "    -h (print this help message)\n"); +}; + +int main(int argc, char* argv[]) +{ +    if(uhd_set_thread_priority(uhd_default_thread_priority, true)){ +        fprintf(stderr, "Unable to set thread priority. Continuing anyway.\n"); +    } + +    int option = 0; +    double freq = 500e6; +    double rate = 1e6; +    double gain = 5.0; +    char* device_args = ""; +    size_t channel = 0; +    char* filename = "out.dat"; +    size_t n_samples = 1000000; +    bool verbose = false; +    int return_code = EXIT_SUCCESS; +    bool custom_filename = false; +    char error_string[512]; + +    // Process options +    while((option = getopt(argc, argv, "a:f:r:g:n:o:vh")) != -1){ +        switch(option){ +            case 'a': +                device_args = strdup(optarg); +                break; + +            case 'f': +                freq = atof(optarg); +                break; + +            case 'r': +                rate = atof(optarg); +                break; + +            case 'g': +                gain = atof(optarg); +                break; + +            case 'n': +                n_samples = atoi(optarg); +                break; + +            case 'o': +                filename = strdup(optarg); +                custom_filename = true; +                break; + +            case 'v': +                verbose = true; +                break; + +            case 'h': +                print_help(); +                goto free_option_strings; + +            default: +                print_help(); +                return_code = EXIT_FAILURE; +                goto free_option_strings; +        } +    } + +    // Create USRP +    uhd_usrp_handle usrp; +    fprintf(stderr, "Creating USRP with args \"%s\"...\n", device_args); +    EXECUTE_OR_GOTO(free_option_strings, +        uhd_usrp_make(&usrp, device_args) +    ) + +    // Create RX streamer +    uhd_rx_streamer_handle rx_streamer; +    EXECUTE_OR_GOTO(free_usrp, +        uhd_rx_streamer_make(&rx_streamer) +    ) + +    // Create RX metadata +    uhd_rx_metadata_handle md; +    EXECUTE_OR_GOTO(free_rx_streamer, +        uhd_rx_metadata_make(&md) +    ) + +    // Create other necessary structs +    uhd_tune_request_t tune_request = { +        .target_freq = freq, +        .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, +        .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, +    }; +    uhd_tune_result_t tune_result; + +    uhd_stream_args_t stream_args = { +        .cpu_format = "fc32", +        .otw_format = "sc16", +        .args = "", +        .channel_list = &channel, +        .n_channels = 1 +    }; + +    uhd_stream_cmd_t stream_cmd = { +        .stream_mode = UHD_STREAM_MODE_NUM_SAMPS_AND_DONE, +        .num_samps = n_samples, +        .stream_now = true +    }; + +    size_t samps_per_buff; +    float *buff = NULL; +    void **buffs_ptr = NULL; +    FILE *fp = NULL; +    size_t num_acc_samps = 0; + +    // Set rate +    fprintf(stderr, "Setting RX Rate: %f...\n", rate); +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_set_rx_rate(usrp, rate, channel) +    ) + +    // See what rate actually is +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_get_rx_rate(usrp, channel, &rate) +    ) +    fprintf(stderr, "Actual RX Rate: %f...\n", rate); + +    // Set gain +    fprintf(stderr, "Setting RX Gain: %f dB...\n", gain); +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_set_rx_gain(usrp, gain, channel, "") +    ) + +    // See what gain actually is +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_get_rx_gain(usrp, channel, "", &gain) +    ) +    fprintf(stderr, "Actual RX Gain: %f...\n", gain); + +    // Set frequency +    fprintf(stderr, "Setting RX frequency: %f MHz...\n", freq/1e6); +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_set_rx_freq(usrp, &tune_request, channel, &tune_result) +    ) + +    // See what frequency actually is +    EXECUTE_OR_GOTO(free_rx_metadata, +        uhd_usrp_get_rx_freq(usrp, channel, &freq) +    ) +    fprintf(stderr, "Actual RX frequency: %f MHz...\n", freq / 1e6); + +    // Set up streamer +    stream_args.channel_list = &channel; +    EXECUTE_OR_GOTO(free_rx_streamer, +        uhd_usrp_get_rx_stream(usrp, &stream_args, rx_streamer) +    ) + +    // Set up buffer +    EXECUTE_OR_GOTO(free_rx_streamer, +        uhd_rx_streamer_max_num_samps(rx_streamer, &samps_per_buff) +    ) +    fprintf(stderr, "Buffer size in samples: %zu\n", samps_per_buff); +    buff = malloc(samps_per_buff * 2 * sizeof(float)); +    buffs_ptr = (void**)&buff; + +    // Issue stream command +    fprintf(stderr, "Issuing stream command.\n"); +    EXECUTE_OR_GOTO(free_buffer, +        uhd_rx_streamer_issue_stream_cmd(rx_streamer, &stream_cmd) +    ) + +    // Set up file output +    fp = fopen(filename, "wb"); + +    // Actual streaming +    while (num_acc_samps < n_samples) { +        size_t num_rx_samps = 0; +        EXECUTE_OR_GOTO(close_file, +            uhd_rx_streamer_recv(rx_streamer, buffs_ptr, samps_per_buff, md, 3.0, false, &num_rx_samps) +        ) + +        uhd_rx_metadata_error_code_t error_code; +        EXECUTE_OR_GOTO(close_file, +            uhd_rx_metadata_error_code(md, &error_code) +        ) +        if(return_code != UHD_RX_METADATA_ERROR_CODE_NONE){ +            fprintf(stderr, "Error code 0x%x was returned during streaming. Aborting.\n", return_code); +            goto close_file; +        } + +        // Handle data +        fwrite(buff, sizeof(float) * 2, num_rx_samps, fp); +        if (verbose) { +            time_t full_secs; +            double frac_secs; +            uhd_rx_metadata_time_spec(md, &full_secs, &frac_secs); +            fprintf(stderr, "Received packet: %zu samples, %zu full secs, %f frac secs\n", +                    num_rx_samps, +                    full_secs, +                    frac_secs); +        } + +        num_acc_samps += num_rx_samps; +    } + +    // Cleanup +    close_file: +        fclose(fp); + +    free_buffer: +        if(buff){ +            if(verbose){ +                fprintf(stderr, "Freeing buffer.\n"); +            } +            free(buff); +        } +        buff = NULL; +        buffs_ptr = NULL; + +    free_rx_streamer: +        if(verbose){ +            fprintf(stderr, "Cleaning up RX streamer.\n"); +        } +        uhd_rx_streamer_free(&rx_streamer); + +    free_rx_metadata: +        if(verbose){ +            fprintf(stderr, "Cleaning up RX metadata.\n"); +        } +        uhd_rx_metadata_free(&md); + +    free_usrp: +        if(verbose){ +            fprintf(stderr, "Cleaning up USRP.\n"); +        } +        if(return_code != EXIT_SUCCESS && usrp != NULL){ +            uhd_usrp_last_error(usrp, error_string, 512); +            fprintf(stderr, "USRP reported the following error: %s\n", error_string); +        } +        uhd_usrp_free(&usrp); + +    free_option_strings: +        if(strcmp(device_args,"")){ +            free(device_args); +        } +        if(custom_filename){ +            free(filename); +        } + +    fprintf(stderr, (return_code ? "Failure\n" : "Success\n")); +    return return_code; +} | 
