pothosware / SoapySDR

Vendor and platform neutral SDR support library.
https://github.com/pothosware/SoapySDR/wiki
Boost Software License 1.0
1.13k stars 179 forks source link

Launch dedicated Soapy Hack RF support module #34

Closed guruofquality closed 9 years ago

guruofquality commented 9 years ago

There's now quite a handful of dedicated support modules for various SDR devices. Its about time Hack RF joined the ranks. Currently supported through SoapyOsmo, unfortunately there are issues. I will get started with stubs and filling in discovery, factory, and stream calls. Then I will need volunteers to help test the module. This issue is put in place to track progress and will be closed out when the support module is up and running.

Current issues with gr-osmosdr

So it looks like there are some problems in the gr-osmosdr hackrf wrapper. Although I think most of these bugs don't come up under normal gr-osmosdr use. But with SoapyOsmo we need to instantiate and control both tx and rx sides, and support arbitrary stream buffer sizes. More details here: https://github.com/pothosware/SoapyOsmo/issues/1

dc1rdb commented 9 years ago

Incidentally, I've placed a similar request a couple of days ago at https://github.com/mossmann/hackrf/issues/221https://github.com/mossmann/hackrf/issues/221

Volunteering for testing (Mac OS X 10.9, CubicSDR).

jocover commented 9 years ago

https://github.com/jocover/SoapyHackRF my code,without testing

guruofquality commented 9 years ago

@jocover it was very awesome to wake up to this, and it looks complete!

I'd like to host it here and give you repo access -- if thats ok. FYI, you have to move it to guruofquality, and then I can move it to pothosware, as we found out with the SoapyRTLSDR.

Gain defaults

Reasonable and safe defaults for the gain values. This would help apps that don't modify the gain by default to have useful and safe initial values. Example from gr-osmosdr comments:

https://github.com/pothosware/SoapyOsmo/blob/update_gr_osmo/gr-osmosdr/lib/hackrf/hackrf_source_c.cc#L205

set_gain( 0 ); /* disable AMP gain stage by default to protect full sprectrum pre-amp from physical damage */

  set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */

  set_bb_gain( 20 ); /* preset to a reasonable default (non-GRC use case) */

https://github.com/pothosware/SoapyOsmo/blob/update_gr_osmo/gr-osmosdr/lib/hackrf/hackrf_sink_c.cc

set_gain( 0 ); /* disable AMP gain stage by default to protect full sprectrum pre-amp from physical damage */

  set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */

Init/exit for mutliple devices

The only issue that I can find is how we deal with hackrf_init/exit() when using multiple devices. This is my idea in pseudo-code.

SoapyHackRF.hpp

struct HackRFSession
{
    HackRFSession(void);
    ~HackRFSession(void);
}

HackRF_Session.cpp

static mutex;
static count = 0;

HackRFSession::HackRFSession(void)
{
lock mutex
if (count == 0) hackrf_init()
//log error if hackrf_init fails...
count++
}

HackRFSession::~HackRFSession(void)
{
lock mutex
count--;
if (count == 0) hackrf_exit()
//log error if hackrf_exit fails...
}

Then use it like so to replace init/exit in the code

class SoapyHackRF
{

private:
    HackRFSession _sess;
}

find_HackRF(const SoapySDR::Kwargs &args)
{
    HackRFSession _sess;
}
bobobo1618 commented 9 years ago

Just compiled and tested this and all the SoapySDRUtil commands (probe, info, make) work!

Unfortunately, using it does not:

(lldb) target create "../CubicSDR/x64/CubicSDR"
Current executable set to '../CubicSDR/x64/CubicSDR' (x86_64).
(lldb) run
Process 27144 launched: '../CubicSDR/x64/CubicSDR' (x86_64)
Loading:: configuration file '/Users/lucas/Library/Application Support/CubicSDR/config.xml'
Loaded PPM for device 'HackRF HackRF One' at 0ppm
Loaded I/Q Swap for device 'HackRF HackRF One' as not swapped
Loaded Direct Sampling Mode for device 'HackRF HackRF One':  off
Loaded offset for device 'HackRF HackRF One' at 0Hz
Loaded PPM for device 'Realtek RTL2838UHIDIR SN: 00000001' at 0ppm
Loaded I/Q Swap for device 'Realtek RTL2838UHIDIR SN: 00000001' as not swapped
Loaded Direct Sampling Mode for device 'Realtek RTL2838UHIDIR SN: 00000001':  off
Loaded offset for device 'Realtek RTL2838UHIDIR SN: 00000001' at 0Hz
SoapySDR init..
    API Version: v0.3.0-g9671ca26
    ABI Version: v0.3-0
    Install root: /usr/local
    Module found: /usr/local/lib/SoapySDR/modules/libHackRFSupport.so
    Loading modules... done
    Available factories...hackrf, null
Found device 0
  device = HackRF One
  driver = hackrf
  part_id = a000cb3c004e474d
  serial = 000000000000000014d463dc2f3caee1
  version = 2015.07.2
Make device 0
  Buffer Size=3.750000MB

Spectrum visual data thread started.
SDR posStD-SRppr eotccehstsrrienuga mtdh r veiiansdiu tasilta aldriatzteiadn .gt..h
.r
eaUds isntga rdteevdi.c
e #0
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: setFrequency(CORR) unknown name
Process 27144 stopped
* thread #9: tid = 0x235088, 0x00007fff8639c286 libsystem_kernel.dylib`__pthread_kill + 10, stop reason = signal SIGABRT
    frame #0: 0x00007fff8639c286 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff8639c286 <+10>: jae    0x7fff8639c290            ; <+20>
    0x7fff8639c288 <+12>: movq   %rax, %rdi
    0x7fff8639c28b <+15>: jmp    0x7fff86397c53            ; cerror_nocancel
    0x7fff8639c290 <+20>: retq   
(lldb) thread backtrace
* thread #9: tid = 0x235088, 0x00007fff8639c286 libsystem_kernel.dylib`__pthread_kill + 10, stop reason = signal SIGABRT
  * frame #0: 0x00007fff8639c286 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff85ad942f libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x00007fff8ac79b53 libsystem_c.dylib`abort + 129
    frame #3: 0x00007fff84ce9a21 libc++abi.dylib`abort_message + 257
    frame #4: 0x00007fff84d119b9 libc++abi.dylib`default_terminate_handler() + 243
    frame #5: 0x00007fff805b77eb libobjc.A.dylib`_objc_terminate() + 124
    frame #6: 0x00007fff84d0f0a1 libc++abi.dylib`std::__terminate(void (*)()) + 8
    frame #7: 0x00007fff84d0eb30 libc++abi.dylib`__cxa_throw + 121
    frame #8: 0x0000000107d3851c libHackRFSupport.so`SoapyHackRF::setFrequency(this=0x0000000100e5af90, direction=1, channel=0, name=0x000000010810ad70, frequency=0, args=0x000000010810ad58) + 316 at HackRF_Settings.cpp:350
    frame #9: 0x000000010017dc8b CubicSDR`SDRThread::run(this=0x0000000100f261e0) + 4779 at SoapySDRThread.cpp:157
    frame #10: 0x000000010004d0aa CubicSDR`IOThread::threadMain(this=0x0000000100f261e0) + 154 at IOThread.cpp:14
    frame #11: 0x000000010000d51d CubicSDR`void* std::__1::__thread_proxy<std::__1::tuple<void* (IOThread::*)(), SDRThread*> >(void*) [inlined] decltype(__f=0x0000000102213d70, __a0=0x0000000102213d80)).*fp(std::__1::forward<>(fp1))) std::__1::__invoke<void* (IOThread::*)(), SDRThread*, void>(void* (IOThread::*&&)(), SDRThread*&&) + 136 at __functional_base:380
    frame #12: 0x000000010000d495 CubicSDR`void* std::__1::__thread_proxy<std::__1::tuple<void* (IOThread::*)(), SDRThread*> >(void*) [inlined] void std::__1::__thread_execute<void* (IOThread::*)(), SDRThread*, 1ul>(__t=0x0000000102213d70, (null)=__tuple_indices<1> at 0x000000010810bea0)(), SDRThread*>&, std::__1::__tuple_indices<1ul>) + 40 at thread:332
    frame #13: 0x000000010000d46d CubicSDR`void* std::__1::__thread_proxy<std::__1::tuple<void* (IOThread::*)(), SDRThread*> >(__vp=0x0000000102213d70) + 365 at thread:342
    frame #14: 0x00007fff85ad7268 libsystem_pthread.dylib`_pthread_body + 131
    frame #15: 0x00007fff85ad71e5 libsystem_pthread.dylib`_pthread_start + 176
    frame #16: 0x00007fff85ad541d libsystem_pthread.dylib`thread_start + 13

My guess is that frame #8: 0x0000000107d3851c libHackRFSupport.soSoapyHackRF::setFrequency(this=0x0000000100e5af90, direction=1, channel=0, name=0x000000010810ad70, frequency=0, args=0x000000010810ad58) + 316 at HackRF_Settings.cpp:350` is the problem, since frequency is set to 0.

bobobo1618 commented 9 years ago

Actually sorry, I see the default frequency is sane, this is likely a CubicSDR bug.

bobobo1618 commented 9 years ago

Okay, CubicSDR now runs! The problem now is that CubicSDR can't go above 8MHz because the buffer length defined in the driver (https://github.com/jocover/SoapyHackRF/blob/master/SoapyHackRF.hpp#L29) can only support 131072 elements and 8M requires ~132096. I tried hardcoding the define to be larger (786432) but I have no idea what I'm doing and although CubicSDR runs, it runs... Badly... Weird glitchy FFT.

cjcliffe commented 9 years ago

With a quick review it looks like the readStream doesn't check if numElems requested exceeds the buffer size and will go off the rails with it.. It's permitted for the readStream to return less elements than requested and the internal buffer size should be configurable.

Suspected culprit: https://github.com/jocover/SoapyHackRF/blob/master/HackRF_Streaming.cpp#L250

cjcliffe commented 9 years ago

@bobobo1618 as a quick workaround does it work if you add the following line:

        numElems = std::min(numElems, _buf_len / BYTES_PER_SAMPLE);

Right before:

    if ( numElems <= _samp_avail )
        {  
            ...

Note you may have to add:

#include <algorithm>

for std::min

bobobo1618 commented 9 years ago

I didn't quite follow your fix (I made a new variable since numElems is const) but CubicSDR no longer crashes. Instead it shows jittery results like this:

screen shot 2015-09-26 at 19 19 34

Not sure if this is a CubicSDR issue or a Soapy/HackRF driver issue though. The audio output is also pretty bad (lots of digital sounding defects).

bobobo1618 commented 9 years ago

Oh, the jitter might actually be my laptop CPU getting eaten alive. I think this fixes the SoapySDR driver and I can move back to the CubicSDR thread.

For anyone coming back to this and catching up:

cjcliffe commented 9 years ago

@bobobo1618 there's some updates to @jocover 's HackRF branch as well that seem to fix the element issue and some other adjustments; have you tried that one yet?

CPU optimization for high bandwidth is probably something I'll need to work on heavily still.

bobobo1618 commented 9 years ago

Yep, jocover's updates fix the element issues.

guruofquality commented 9 years ago

Thanks @jocover this was really awesome. Everything is here now, and you should have access:

You may want to fill in your name or organization for the copyright in the files.

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 <name or organization>
 * Permission is hereby granted, free of charge, to any person obtaining a copy

Anyway, I'm closing this issue. Further issues can be tracked at https://github.com/pothosware/SoapyHackRF/issues