#ifndef DEVICE_H #define DEVICE_H #include "../VNA_embedded/Application/Communication/Protocol.hpp" #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(Protocol::Datapoint); Q_DECLARE_METATYPE(Protocol::ManualStatus); Q_DECLARE_METATYPE(Protocol::DeviceInfo); Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult); class USBInBuffer : public QObject { Q_OBJECT; public: USBInBuffer(libusb_device_handle *handle, unsigned char endpoint, int buffer_size); ~USBInBuffer(); void removeBytes(int handled_bytes); int getReceived() const; uint8_t *getBuffer() const; signals: void DataReceived(); void TransferError(); private: void Callback(libusb_transfer *transfer); static void LIBUSB_CALL CallbackTrampoline(libusb_transfer *transfer); libusb_transfer *transfer; unsigned char *buffer; int buffer_size; int received_size; bool inCallback; std::condition_variable cv; }; class Device : public QObject { Q_OBJECT public: enum class TransmissionResult { Ack, Nack, Timeout, InternalError, }; Q_ENUM(TransmissionResult) // connect to a VNA device. If serial is specified only connecting to this device, otherwise to the first one found Device(QString serial = QString()); ~Device(); bool SendPacket(const Protocol::PacketInfo& packet, std::function cb = nullptr, unsigned int timeout = 200); bool Configure(Protocol::SweepSettings settings, std::function cb = nullptr); bool Configure(Protocol::SpectrumAnalyzerSettings settings); bool SetManual(Protocol::ManualControl manual); bool SetIdle(); bool SendFirmwareChunk(Protocol::FirmwarePacket &fw); bool SendCommandWithoutPayload(Protocol::PacketType type); QString serial() const; Protocol::DeviceInfo getLastInfo() const; QString getLastDeviceInfoString(); // Returns serial numbers of all connected devices static std::set GetDevices(); static Protocol::DeviceLimits Limits(); signals: void DatapointReceived(Protocol::Datapoint); void ManualStatusReceived(Protocol::ManualStatus); void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult); void DeviceInfoUpdated(); void ConnectionLost(); void AckReceived(); void NackReceived(); void LogLineReceived(QString line); private slots: void ReceivedData(); void ReceivedLog(); void transmissionTimeout() { transmissionFinished(TransmissionResult::Timeout); } void transmissionFinished(TransmissionResult result); signals: void receivedAnswer(TransmissionResult result); private: static constexpr int EP_Data_Out_Addr = 0x01; static constexpr int EP_Data_In_Addr = 0x81; static constexpr int EP_Log_In_Addr = 0x82; void USBHandleThread(); // foundCallback is called for every device that is found. If it returns true the search continues, otherwise it is aborted. // When the search is aborted the last found device is still opened static void SearchDevices(std::function foundCallback, libusb_context *context); libusb_device_handle *m_handle; libusb_context *m_context; USBInBuffer *dataBuffer; USBInBuffer *logBuffer; using Transmission = struct { Protocol::PacketInfo packet; unsigned int timeout; std::function callback; }; QQueue transmissionQueue; bool startNextTransmission(); QTimer transmissionTimer; bool transmissionActive; QString m_serial; bool m_connected; std::thread *m_receiveThread; Protocol::DeviceInfo lastInfo; bool lastInfoValid; }; #endif // DEVICE_H