samcrow / uhd-rust

Rust bindings to the UHD (USRP Hardware Driver) library
14 stars 14 forks source link

Invalid Over the Wire Format in examples #3

Closed samcarey closed 1 year ago

samcarey commented 1 year ago

According to the UHD documentation for the OTW format (doc string is above that line), only values of "sc8", "sc12", and "sc16" are implemented.

In the transmit and receive examples, StreamArgs is initialized with new("f32"), which sets its parameter to the wire_format field.

This breaks when run on an E3xx.

What is also concerning is that uhd threw an error that just said "uhd::runtime_error - Other runtime error", which wasn't super helpful for debugging. I would have hoped for what the usrp1 implementation does, which is throw a "value_error".

Strangely enough, the b200 implementation seems to allow it, so this might be a device specific issue.

samcrow commented 1 year ago

Yes, we should change the wire format in the examples to sc16, which seems to be most widely supported, or leave it empty and let the UHD library choose the default.

Exceptions get categorized into this enum. There is a value error option, so it should get converted into a Value error in Rust. That looks like a bug somewhere.

I don't have a USRP right now for testing, so I'd especially appreciate pull requests to fix this.

richardeoin commented 1 year ago

I tried to reproduce this on some 2xx series USRPs but found that:

The usrp2 driver calls the convert::get_bytes_per_item method. In the case of a garbage otw format it raises a Key error here, but fc32 is seemingly always accepted.

@samcarey I suspect uhd is using the usrp2 driver for your E3xx. In that case convert::get_bytes_per_item accepts fc32 (so no error raised there), and the runtime error you're seeing is instead raised at some lower, hardware-specific level. In any case this is definitely an upstream bug in uhd that we can't or shouldn't fix here.

I do agree that we should change the examples to sc16, since this seems to have a better chance of working on all USRP devices. I'll make a PR for this!

samcarey commented 1 year ago

Thank you!

varenius commented 1 year ago

This is my first time playing with rust, so apologies for my ignorance but: I can add that I just tried to run let mut receiver = usrp.get_rx_stream(&uhd::StreamArgs::<Complex32>::new("fc32")).unwrap(); for my USRP N210 and it failed miserably. Using "sc16" instead works. However, I can set cpu_format="fc32" using gnuradio 3.8.1.0 for this device through old python code (https://github.com/varenius/salsa/blob/main/Control_program/receiver.py#L48). Does it make sense to you who know more about the uhd-rust crate? In my naïve mind: either fc32 should work or not? Both uhd-rust and gnuradio would rely on the underlying ettus c++ usrp code, right?

samcrow commented 1 year ago

StreamArgs::<Complex32>::new("fc32") sets both the host/CPU format and the wire format to fc32. It looks like some USRPs don't support fc32 as a wire format.

StreamArgs::<Complex32>::new("sc16") sets the host/CPU format to fc32 and the wire format to sc16. That matches what the linked Python code does, and is more likely to work.

Yes, they both use the UHD library C++ code.