1
0
mirror of https://github.com/JvanKatwijk/qt-dab.git synced 2025-10-06 08:12:40 +02:00
Files
SDR-DAB_Qt-DAB/devices/hackrf-handler/hackrf-handler.cpp

392 lines
12 KiB
C++
Raw Normal View History

2018-05-15 21:57:28 +02:00
#
/*
* Copyright (C) 2014 .. 2017
* Jan van Katwijk (J.vanKatwijk@gmail.com)
* Lazy Chair Computing
*
* This file is part of Qt-DAB
*
* Qt-DAB 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 version 2 of the License.
*
* Qt-DAB 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 Qt-DAB if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <QThread>
#include <QSettings>
#include <QHBoxLayout>
#include <QLabel>
#include "hackrf-handler.h"
#define DEFAULT_GAIN 30
hackrfHandler::hackrfHandler (QSettings *s) {
int err;
int res;
hackrfSettings = s;
this -> myFrame = new QFrame (NULL);
setupUi (this -> myFrame);
this -> myFrame -> show ();
this -> inputRate = Khz (2048);
2018-05-17 10:48:38 +02:00
_I_Buffer = NULL;
#ifdef __MINGW32__
const char *libraryString = "hackrf.dll";
Handle = LoadLibrary ((wchar_t *)L"hackrf.dll");
#else
const char *libraryString = "libhackrf.so";
Handle = dlopen (libraryString, RTLD_NOW);
#endif
if (Handle == NULL) {
fprintf (stderr, "failed to open %s\n", libraryString);
delete myFrame;
throw (20);
}
libraryLoaded = true;
if (!load_hackrfFunctions ()) {
#ifdef __MINGW32__
FreeLibrary (Handle);
#else
dlclose (Handle);
#endif
delete myFrame;
throw (21);
}
//
// From here we have a library available
2018-05-15 21:57:28 +02:00
_I_Buffer = new RingBuffer<std::complex<float>>(1024 * 1024);
vfoFrequency = Khz (220000);
//
// See if there are settings from previous incarnations
hackrfSettings -> beginGroup ("hackrfSettings");
lnagainSlider -> setValue (
hackrfSettings -> value ("hack_lnaGain", DEFAULT_GAIN). toInt ());
vgagainSlider -> setValue (
hackrfSettings -> value ("hack_vgaGain", DEFAULT_GAIN). toInt ());
hackrfSettings -> endGroup ();
//
2018-05-17 10:48:38 +02:00
res = this -> hackrf_init ();
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_init:");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
delete myFrame;
throw (21);
}
2018-05-17 10:48:38 +02:00
res = this -> hackrf_open (&theDevice);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_open:");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
delete myFrame;
throw (22);
}
2018-05-17 10:48:38 +02:00
res = this -> hackrf_set_sample_rate (theDevice, 2048000.0);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_set_samplerate:");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
delete myFrame;
throw (23);
}
2018-05-17 10:48:38 +02:00
res = this -> hackrf_set_baseband_filter_bandwidth (theDevice,
1750000);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_set_bw:");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
delete myFrame;
throw (24);
}
2018-05-17 10:48:38 +02:00
res = this -> hackrf_set_freq (theDevice, 220000000);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_set_freq: ");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
delete myFrame;
throw (25);
}
setLNAGain (lnagainSlider -> value ());
setVGAGain (vgagainSlider -> value ());
// and be prepared for future changes in the settings
connect (lnagainSlider, SIGNAL (valueChanged (int)),
this, SLOT (setLNAGain (int)));
connect (vgagainSlider, SIGNAL (valueChanged (int)),
this, SLOT (setVGAGain (int)));
2018-05-17 10:48:38 +02:00
hackrf_device_list_t *deviceList = this -> hackrf_device_list ();
if (deviceList != NULL) { // well, it should be
2018-05-17 10:48:38 +02:00
char *serial = deviceList -> serial_numbers [0];
serial_number_display -> setText (serial);
enum hackrf_usb_board_id board_id =
deviceList -> usb_board_ids [0];
usb_board_id_display ->
setText (this -> hackrf_usb_board_id_name (board_id));
}
2018-05-15 21:57:28 +02:00
running. store (false);
}
hackrfHandler::~hackrfHandler (void) {
stopReader ();
delete myFrame;
if (_I_Buffer != NULL)
delete _I_Buffer;
2018-05-17 10:48:38 +02:00
hackrfSettings -> beginGroup ("hackrfSettings");
hackrfSettings -> setValue ("hack_lnaGain",
lnagainSlider -> value ());
hackrfSettings -> setValue ("hack_vgaGain",
vgagainSlider -> value ());
hackrfSettings -> endGroup ();
this -> hackrf_close (theDevice);
this -> hackrf_exit ();
2018-05-15 21:57:28 +02:00
}
//
void hackrfHandler::setVFOFrequency (int32_t newFrequency) {
int res;
2018-05-17 10:48:38 +02:00
res = this -> hackrf_set_freq (theDevice, newFrequency);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_set_freq: \n");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
return;
}
vfoFrequency = newFrequency;
}
int32_t hackrfHandler::getVFOFrequency (void) {
return vfoFrequency;
}
void hackrfHandler::setLNAGain (int newGain) {
int res;
2018-05-17 10:48:38 +02:00
if ((newGain <= 40) && (newGain >= 0)) {
res = this -> hackrf_set_lna_gain (theDevice, newGain);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_lna_gain :\n");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
return;
}
lnagainDisplay -> display (newGain);
}
}
void hackrfHandler::setVGAGain (int newGain) {
int res;
if ((newGain <= 62) && (newGain >= 0)) {
2018-05-17 10:48:38 +02:00
res = this -> hackrf_set_vga_gain (theDevice, newGain);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_vga_gain :\n");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
return;
}
vgagainDisplay -> display (newGain);
}
}
2018-05-17 10:48:38 +02:00
//
// we use a static large buffer, rather than trying to allocate
// a buffer on the stack
2018-05-15 21:57:28 +02:00
static std::complex<float>buffer [32 * 32768];
static
int callback (hackrf_transfer *transfer) {
hackrfHandler *ctx = static_cast <hackrfHandler *>(transfer -> rx_ctx);
int i;
uint8_t *p = transfer -> buffer;
RingBuffer<std::complex<float> > * q = ctx -> _I_Buffer;
for (i = 0; i < transfer -> valid_length / 2; i ++) {
2018-05-17 10:48:38 +02:00
float re = (int8_t)(p [2 * i]) / 128.0;
float im = (int8_t)(p [2 * i + 1]) / 128.0;
2018-05-15 21:57:28 +02:00
buffer [i] = std::complex<float> (re, im);
}
q -> putDataIntoBuffer (buffer, transfer -> valid_length / 2);
return 0;
}
bool hackrfHandler::restartReader (void) {
int res;
2018-05-17 10:48:38 +02:00
if (running. load ())
return true;
2018-05-15 21:57:28 +02:00
2018-05-17 10:48:38 +02:00
res = this -> hackrf_start_rx (theDevice, callback, this);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_start_rx :\n");
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
return false;
}
2018-05-17 10:48:38 +02:00
running. store (this -> hackrf_is_streaming (theDevice));
2018-05-15 21:57:28 +02:00
return running. load ();
}
void hackrfHandler::stopReader (void) {
int res;
if (!running. load ())
return;
2018-05-17 10:48:38 +02:00
res = this -> hackrf_stop_rx (theDevice);
2018-05-15 21:57:28 +02:00
if (res != HACKRF_SUCCESS) {
2018-05-17 10:48:38 +02:00
fprintf (stderr, "Problem with hackrf_stop_rx :\n", res);
fprintf (stderr, "%s \n",
this -> hackrf_error_name (hackrf_error (res)));
2018-05-15 21:57:28 +02:00
return;
}
running. store (false);
}
//
// The brave old getSamples. For the hackrf, we get
// size still in I/Q pairs
int32_t hackrfHandler::getSamples (std::complex<float> *V, int32_t size) {
return _I_Buffer -> getDataFromBuffer (V, size);
}
int32_t hackrfHandler::Samples (void) {
return _I_Buffer -> GetRingBufferReadAvailable ();
}
void hackrfHandler::resetBuffer (void) {
_I_Buffer -> FlushRingBuffer ();
}
int16_t hackrfHandler::bitDepth (void) {
return 8;
}
2018-05-17 10:48:38 +02:00
bool hackrfHandler::load_hackrfFunctions (void) {
//
// link the required procedures
this -> hackrf_init = (pfn_hackrf_init)
GETPROCADDRESS (Handle, "hackrf_init");
if (this -> hackrf_init == NULL) {
fprintf (stderr, "Could not find hackrf_init\n");
return false;
}
this -> hackrf_open = (pfn_hackrf_open)
GETPROCADDRESS (Handle, "hackrf_open");
if (this -> hackrf_open == NULL) {
fprintf (stderr, "Could not find hackrf_open\n");
return false;
}
this -> hackrf_close = (pfn_hackrf_close)
GETPROCADDRESS (Handle, "hackrf_close");
if (this -> hackrf_close == NULL) {
fprintf (stderr, "Could not find hackrf_close\n");
return false;
}
this -> hackrf_exit = (pfn_hackrf_exit)
GETPROCADDRESS (Handle, "hackrf_exit");
if (this -> hackrf_exit == NULL) {
fprintf (stderr, "Could not find hackrf_exit\n");
return false;
}
this -> hackrf_start_rx = (pfn_hackrf_start_rx)
GETPROCADDRESS (Handle, "hackrf_start_rx");
if (this -> hackrf_start_rx == NULL) {
fprintf (stderr, "Could not find hackrf_start_rx\n");
return false;
}
this -> hackrf_stop_rx = (pfn_hackrf_stop_rx)
GETPROCADDRESS (Handle, "hackrf_stop_rx");
if (this -> hackrf_stop_rx == NULL) {
fprintf (stderr, "Could not find hackrf_stop_rx\n");
return false;
}
this -> hackrf_device_list = (pfn_hackrf_device_list)
GETPROCADDRESS (Handle, "hackrf_device_list");
if (this -> hackrf_device_list == NULL) {
fprintf (stderr, "Could not find hackrf_device_list\n");
return false;
}
this -> hackrf_set_baseband_filter_bandwidth =
(pfn_hackrf_set_baseband_filter_bandwidth)
GETPROCADDRESS (Handle,
"hackrf_set_baseband_filter_bandwidth");
if (this -> hackrf_set_baseband_filter_bandwidth == NULL) {
fprintf (stderr, "Could not find hackrf_set_baseband_filter_bandwidth\n");
return false;
}
2018-05-15 21:57:28 +02:00
2018-05-17 10:48:38 +02:00
this -> hackrf_set_lna_gain = (pfn_hackrf_set_lna_gain)
GETPROCADDRESS (Handle, "hackrf_set_lna_gain");
if (this -> hackrf_set_lna_gain == NULL) {
fprintf (stderr, "Could not find hackrf_set_lna_gain\n");
return false;
}
this -> hackrf_set_vga_gain = (pfn_hackrf_set_vga_gain)
GETPROCADDRESS (Handle, "hackrf_set_vga_gain");
if (this -> hackrf_set_vga_gain == NULL) {
fprintf (stderr, "Could not find hackrf_set_vga_gain\n");
return false;
}
this -> hackrf_set_freq = (pfn_hackrf_set_freq)
GETPROCADDRESS (Handle, "hackrf_set_freq");
if (this -> hackrf_set_freq == NULL) {
fprintf (stderr, "Could not find hackrf_set_freq\n");
return false;
}
this -> hackrf_set_sample_rate = (pfn_hackrf_set_sample_rate)
GETPROCADDRESS (Handle, "hackrf_set_sample_rate");
if (this -> hackrf_set_sample_rate == NULL) {
fprintf (stderr, "Could not find hackrf_set_sample_rate\n");
return false;
}
this -> hackrf_is_streaming = (pfn_hackrf_is_streaming)
GETPROCADDRESS (Handle, "hackrf_is_streaming");
if (this -> hackrf_is_streaming == NULL) {
fprintf (stderr, "Could not find hackrf_is_streaming\n");
return false;
}
this -> hackrf_error_name = (pfn_hackrf_error_name)
GETPROCADDRESS (Handle, "hackrf_error_name");
if (this -> hackrf_error_name == NULL) {
fprintf (stderr, "Could not find hackrf_error_name\n");
return false;
}
this -> hackrf_usb_board_id_name = (pfn_hackrf_usb_board_id_name)
GETPROCADDRESS (Handle, "hackrf_usb_board_id_name");
if (this -> hackrf_usb_board_id_name == NULL) {
fprintf (stderr, "Could not find hackrf_usb_board_id_name\n");
return false;
}
fprintf (stderr, "OK, functions seem to be loaded\n");
return true;
}