2021-11-09 00:00:13 +01:00

132 lines
4.1 KiB
C++

#include <rfspace_client.h>
#include <volk/volk.h>
#include <cstring>
#include <spdlog/spdlog.h>
using namespace std::chrono_literals;
namespace rfspace {
RFspaceClientClass::RFspaceClientClass(net::Conn conn, net::Conn udpConn, dsp::stream<dsp::complex_t>* out) {
client = std::move(conn);
udpClient = std::move(udpConn);
output = out;
rbuffer = new uint8_t[RFSPACE_MAX_SIZE];
sbuffer = new uint8_t[RFSPACE_MAX_SIZE];
ubuffer = new uint8_t[RFSPACE_MAX_SIZE];
output->clearWriteStop();
uint8_t test = 0x5A;
udpClient->write(1, &test);
// Start readers
client->readAsync(sizeof(tcpHeader), (uint8_t*)&tcpHeader, tcpHandler, this);
udpClient->readAsync(sizeof(udpHeader), (uint8_t*)&udpHeader, udpHandler, this);
// Start SDR
uint8_t args[4] = {0x70, 2, 0, 0};
setControlItem(0x18, args, 4);
}
RFspaceClientClass::~RFspaceClientClass() {
close();
delete[] rbuffer;
delete[] sbuffer;
delete[] ubuffer;
}
int RFspaceClientClass::getControlItem(uint16_t item, void* param, int len) {
// Build packet
uint16_t* header = (uint16_t*)&sbuffer[0];
uint16_t* item_val = (uint16_t*)&sbuffer[2];
*header = 4 | (RFSPACE_MSG_TYPE_H2T_REQ_CTRL_ITEM << 13);
*item_val = item;
// Send packet
SCIRRecv.release();
client->write(4, sbuffer);
// Wait for a response
if (!SCIRRecv.await(2000)) {
SCIRRecv.release();
return -1;
}
// Forward data
int toRead = ((SCIRSize - 4) < len) ? (SCIRSize - 4) : len;
memcpy(param, &rbuffer[4], toRead);
// Release receiving thread
SCIRRecv.release();
return toRead;
}
void RFspaceClientClass::setControlItem(uint16_t item, void* param, int len) {
// Build packet
uint16_t* header = (uint16_t*)&sbuffer[0];
uint16_t* item_val = (uint16_t*)&sbuffer[2];
*header = (len + 4) | (RFSPACE_MSG_TYPE_H2T_SET_CTRL_ITEM << 13);
*item_val = item;
memcpy(&sbuffer[4], param, len);
// Send packet
client->write(len + 4, sbuffer);
}
void RFspaceClientClass::close() {
output->stopWriter();
client->close();
udpClient->close();
}
bool RFspaceClientClass::isOpen() {
return client->isOpen();
}
void RFspaceClientClass::tcpHandler(int count, uint8_t* buf, void* ctx) {
RFspaceClientClass* _this = (RFspaceClientClass*)ctx;
uint8_t type = _this->tcpHeader >> 13;
uint16_t size = _this->tcpHeader & 0b1111111111111;
// Read the rest of the data
if (size > 2) {
_this->client->read(size - 2, &_this->rbuffer[2]);
}
spdlog::warn("TCP received: {0} {1}", type, size);
// Process data
if (type == RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP) {
_this->SCIRSize = size;
_this->SCIRRecv.trigger();
}
// Restart an async read
_this->client->readAsync(sizeof(_this->tcpHeader), (uint8_t*)&_this->tcpHeader, tcpHandler, _this);
}
void RFspaceClientClass::udpHandler(int count, uint8_t* buf, void* ctx) {
RFspaceClientClass* _this = (RFspaceClientClass*)ctx;
uint8_t type = _this->udpHeader >> 13;
uint16_t size = _this->udpHeader & 0b1111111111111;
spdlog::warn("UDP received: {0} {1}", type, size);
// Read the rest of the data
if (size > 2) {
_this->client->read(size - 2, &_this->rbuffer[2]);
}
// Restart an async read
_this->client->readAsync(sizeof(_this->udpHeader), (uint8_t*)&_this->udpHeader, udpHandler, _this);
}
RFspaceClient connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out) {
net::Conn conn = net::connect(host, port);
if (!conn) { return NULL; }
net::Conn udpConn = net::openUDP("0.0.0.0", port, host, port, true);
if (!udpConn) { return NULL; }
return RFspaceClient(new RFspaceClientClass(std::move(conn), std::move(udpConn), out));
}
}