Skip to content

Commit

Permalink
Improve Linux part, implement functions in libsddc
Browse files Browse the repository at this point in the history
  • Loading branch information
kpd200081 committed May 10, 2021
1 parent 92323c1 commit 39777f7
Show file tree
Hide file tree
Showing 14 changed files with 328 additions and 123 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,9 @@ __pycache__/
/bugz03.png
/bugz04.png
*.png

# SDK output files
SDDC_FX3/SDDC_FX3.elf
SDDC_FX3/SDDC_FX3.img
SDDC_FX3/SDDC_FX3.map
SDDC_FX3/elf2img
59 changes: 44 additions & 15 deletions Core/arch/linux/FX3handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ fx3class* CreateUsbHandler()

fx3handler::fx3handler()
{
stream = nullptr;
dev = nullptr;
}

fx3handler::~fx3handler()
Expand All @@ -25,28 +27,36 @@ bool fx3handler::Open(uint8_t* fw_data, uint32_t fw_size)

bool fx3handler::Control(FX3Command command, uint8_t data)
{
return usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
bool ret = usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
return ret;
}

bool fx3handler::Control(FX3Command command, uint32_t data)
{
return usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
bool ret = usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
return ret;
}

bool fx3handler::Control(FX3Command command, uint64_t data)
{
return usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
bool ret = usb_device_control(this->dev, command, 0, 0, (uint8_t *) &data, sizeof(data), 0) == 0;
return ret;
}

bool fx3handler::SetArgument(uint16_t index, uint16_t value)
{
uint8_t data = 0;
return usb_device_control(this->dev, SETARGFX3, value, index, (uint8_t *) &data, sizeof(data), 0) == 0;
bool ret = usb_device_control(this->dev, SETARGFX3, value, index, (uint8_t *) &data, sizeof(data), 0) == 0;
return ret;
}

bool fx3handler::GetHardwareInfo(uint32_t* data)
{
#ifdef _DEBUG
return usb_device_control(this->dev, TESTFX3, 1, 1, (uint8_t *) data, sizeof(*data), 1) == 0; //enable debug in firmware
#else
return usb_device_control(this->dev, TESTFX3, 0, 0, (uint8_t *) data, sizeof(*data), 1) == 0;
#endif
}

void fx3handler::StartStream(ringbuffer<int16_t>& input, int numofblock)
Expand All @@ -55,29 +65,46 @@ void fx3handler::StartStream(ringbuffer<int16_t>& input, int numofblock)
auto readsize = input.getWriteCount() * sizeof(uint16_t);
stream = streaming_open_async(this->dev, readsize, numofblock, PacketRead, this);

if(stream) {
streaming_start(stream);
} else {
return;
}

// Start background thread to poll the events
run = true;
poll_thread = std::thread(
[this]() {
while(run)
while(run && stream)
{
usb_device_handle_events(this->dev);
if(!stream || !run) {
break;
}
if(streaming_status(stream) == STREAMING_STATUS_FAILED) {
fprintf(stderr, "Restart\n");
streaming_stop(stream);
streaming_reset_status(stream);
// hack to make FX3 stream again - need to send some control, this one works best
usb_device_control(this->dev, READINFODEBUG, 0, 0, 0, 0, 1);
streaming_start(stream);
}
}
});

if (stream)
{
streaming_start(stream);
}
}

void fx3handler::StopStream()
{
run = false;
poll_thread.join();
if(stream) {
streaming_stop(stream);
streaming_close(stream);
}
stream = nullptr;

streaming_stop(stream);
streaming_close(stream);
run = false;
if(poll_thread.joinable()) {
poll_thread.join();
}
}

void fx3handler::PacketRead(uint32_t data_size, uint8_t *data, void *context)
Expand All @@ -91,5 +118,7 @@ void fx3handler::PacketRead(uint32_t data_size, uint8_t *data, void *context)

bool fx3handler::ReadDebugTrace(uint8_t* pdata, uint8_t len)
{
return true;
return true;
// TODO: works bad because of strange libusb behavior in multithreading
// return usb_device_control(this->dev, READINFODEBUG, 0, 0, pdata, len, 1) == 0;
}
2 changes: 1 addition & 1 deletion Core/arch/linux/FX3handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class fx3handler : public fx3class
fx3handler();
virtual ~fx3handler(void);
bool Open(uint8_t* fw_data, uint32_t fw_size) override;
bool Control(FX3Command command, uint8_t data) override;
bool Control(FX3Command command, uint8_t data = 0) override;
bool Control(FX3Command command, uint32_t data) override;
bool Control(FX3Command command, uint64_t data) override;
bool SetArgument(uint16_t index, uint16_t value) override;
Expand Down
76 changes: 29 additions & 47 deletions Core/arch/linux/streaming.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,11 @@
#include "usb_device_internals.h"
#include "logging.h"


typedef struct streaming streaming_t;

/* internal functions */
static void streaming_read_async_callback(struct libusb_transfer *transfer);


enum StreamingStatus {
STREAMING_STATUS_OFF,
STREAMING_STATUS_READY,
STREAMING_STATUS_STREAMING,
STREAMING_STATUS_CANCELLED,
STREAMING_STATUS_FAILED = 0xff
};

typedef struct streaming {
enum StreamingStatus status;
int random;
Expand All @@ -69,12 +59,14 @@ typedef struct streaming {
atomic_int active_transfers;
} streaming_t;


static const uint32_t DEFAULT_SAMPLE_RATE = 64000000; /* 64Msps */
static const uint32_t DEFAULT_FRAME_SIZE = (2 * 64000000 / 1000); /* ~ 1 ms */
static const uint32_t DEFAULT_FRAME_SIZE = (2 * DEFAULT_SAMPLE_RATE / 1000); /* ~ 1 ms */
static const uint32_t DEFAULT_NUM_FRAMES = 96; /* we should not exceed 120 ms in total! */
const unsigned int BULK_XFER_TIMEOUT = 5000; // timeout (in ms) for each bulk transfer
const unsigned int BULK_XFER_TIMEOUT = 50; // timeout (in ms) for each bulk transfer

enum StreamingStatus streaming_status(streaming_t *that) {
return that->status;
}

streaming_t *streaming_open_sync(usb_device_t *usb_device)
{
Expand Down Expand Up @@ -104,7 +96,6 @@ streaming_t *streaming_open_sync(usb_device_t *usb_device)
return ret_val;
}


streaming_t *streaming_open_async(usb_device_t *usb_device, uint32_t frame_size,
uint32_t num_frames, sddc_read_async_cb_t callback,
void *callback_context)
Expand Down Expand Up @@ -177,13 +168,9 @@ streaming_t *streaming_open_async(usb_device_t *usb_device, uint32_t frame_size,
return ret_val;
}


void streaming_close(streaming_t *this)
{
if (this->transfers) {
for (uint32_t i = 0; i < this->num_frames; ++i) {
libusb_free_transfer(this->transfers[i]);
}
free(this->transfers);
}
if (this->frames != 0) {
Expand All @@ -197,35 +184,41 @@ void streaming_close(streaming_t *this)
return;
}


int streaming_set_sample_rate(streaming_t *this, uint32_t sample_rate)
{
/* no checks yet */
this->sample_rate = sample_rate;
return 0;
}


int streaming_set_random(streaming_t *this, int random)
{
this->random = random;
return 0;
}


int streaming_start(streaming_t *this)
{
if (this->status != STREAMING_STATUS_READY) {
fprintf(stderr, "ERROR - streaming_start() called with streaming status not READY: %d\n", this->status);
return -1;
}

this->status = STREAMING_STATUS_STREAMING;

/* if there is no callback, then streaming is synchronous - nothing to do */
if (this->callback == 0) {
this->status = STREAMING_STATUS_STREAMING;
return 0;
}

for (uint32_t i = 0; i < this->num_frames; ++i) {
this->transfers[i] = libusb_alloc_transfer(0); // iso_packets_per_frame ?
libusb_fill_bulk_transfer(this->transfers[i], this->usb_device->dev_handle,
this->usb_device->bulk_in_endpoint_address,
this->frames[i], this->frame_size, streaming_read_async_callback,
this, BULK_XFER_TIMEOUT);
}

/* submit all the transfers */
atomic_init(&this->active_transfers, 0);
for (uint32_t i = 0; i < this->num_frames; ++i) {
Expand All @@ -238,12 +231,9 @@ int streaming_start(streaming_t *this)
atomic_fetch_add(&this->active_transfers, 1);
}

this->status = STREAMING_STATUS_STREAMING;

return 0;
}


int streaming_stop(streaming_t *this)
{
/* if there is no callback, then streaming is synchronous - nothing to do */
Expand All @@ -260,6 +250,7 @@ int streaming_stop(streaming_t *this)
int ret = libusb_cancel_transfer(this->transfers[i]);
if (ret < 0) {
if (ret == LIBUSB_ERROR_NOT_FOUND) {
atomic_fetch_sub(&this->active_transfers, 1);
continue;
}
log_usb_error(ret, __func__, __FILE__, __LINE__);
Expand All @@ -268,17 +259,18 @@ int streaming_stop(streaming_t *this)
}

/* flush all the events */
struct timeval noblock = { 0, 0 };
int ret = libusb_handle_events_timeout_completed(this->usb_device->context, &noblock, 0);
if (ret < 0) {
log_usb_error(ret, __func__, __FILE__, __LINE__);
this->status = STREAMING_STATUS_FAILED;
while (this->active_transfers > 0){
usb_device_handle_events(this->usb_device);
}
atomic_init(&this->active_transfers, 0);

for (uint32_t i = 0; i < this->num_frames; ++i) {
libusb_free_transfer(this->transfers[i]);
}

return 0;
}


int streaming_reset_status(streaming_t *this)
{
switch (this->status) {
Expand All @@ -304,7 +296,6 @@ int streaming_reset_status(streaming_t *this)
return 0;
}


int streaming_read_sync(streaming_t *this, uint8_t *data, int length, int *transferred)
{
int ret = libusb_bulk_transfer(this->usb_device->dev_handle,
Expand All @@ -329,7 +320,6 @@ int streaming_read_sync(streaming_t *this, uint8_t *data, int length, int *trans
return 0;
}


/* internal functions */
static void LIBUSB_CALL streaming_read_async_callback(struct libusb_transfer *transfer)
{
Expand Down Expand Up @@ -359,29 +349,21 @@ static void LIBUSB_CALL streaming_read_async_callback(struct libusb_transfer *tr
}
break;
case LIBUSB_TRANSFER_CANCELLED:
atomic_fetch_sub(&this->active_transfers, 1);
/* librtlsdr does also ignore LIBUSB_TRANSFER_CANCELLED */
return;
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_TIMED_OUT:
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_STALL:
case LIBUSB_TRANSFER_NO_DEVICE:
case LIBUSB_TRANSFER_OVERFLOW:
log_usb_error(transfer->status, __func__, __FILE__, __LINE__);
break;
}

this->status = STREAMING_STATUS_FAILED;
atomic_fetch_sub(&this->active_transfers, 1);
fprintf(stderr, "Cancelling\n");
/* cancel all the active transfers */
for (uint32_t i = 0; i < this->num_frames; ++i) {
int ret = libusb_cancel_transfer(transfer);
if (ret < 0) {
if (ret == LIBUSB_ERROR_NOT_FOUND) {
continue;
}
log_usb_error(ret, __func__, __FILE__, __LINE__);
}
if(this->status == STREAMING_STATUS_FAILED || this->status == STREAMING_STATUS_CANCELLED) {
return;
}
return;

this->status = STREAMING_STATUS_FAILED;
}
10 changes: 10 additions & 0 deletions Core/arch/linux/streaming.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ typedef struct streaming streaming_t;
typedef void (*sddc_read_async_cb_t)(uint32_t data_size, uint8_t *data,
void *context);

enum StreamingStatus {
STREAMING_STATUS_OFF,
STREAMING_STATUS_READY,
STREAMING_STATUS_STREAMING,
STREAMING_STATUS_CANCELLED,
STREAMING_STATUS_FAILED = 0xff
};

enum StreamingStatus streaming_status(streaming_t *that);

streaming_t *streaming_open_sync(usb_device_t *usb_device);

streaming_t *streaming_open_async(usb_device_t *usb_device, uint32_t frame_size,
Expand Down
Loading

0 comments on commit 39777f7

Please sign in to comment.