#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::ManualStatusV1) Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult) Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint) 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(); static void RegisterTypes(); bool SendPacket(const Protocol::PacketInfo& packet, std::function cb = nullptr, unsigned int timeout = 500); bool Configure(Protocol::SweepSettings settings, std::function cb = nullptr); bool Configure(Protocol::SpectrumAnalyzerSettings settings, std::function cb = nullptr); bool SetManual(Protocol::ManualControlV1 manual); bool SetIdle(std::function cb = nullptr); bool SendFirmwareChunk(Protocol::FirmwarePacket &fw); bool SendCommandWithoutPayload(Protocol::PacketType type, std::function cb = nullptr); QString serial() const; const Protocol::DeviceInfo& Info(); static const Protocol::DeviceInfo& Info(Device *dev); Protocol::DeviceStatusV1& StatusV1(); static const Protocol::DeviceStatusV1& StatusV1(Device *dev); QString getLastDeviceInfoString(); // Returns serial numbers of all connected devices static std::set GetDevices(); signals: void DatapointReceived(Protocol::VNADatapoint<32>*); void ManualStatusReceived(Protocol::ManualStatusV1); void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult); void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint); void FrequencyCorrectionReceived(float ppm); void DeviceInfoUpdated(); void DeviceStatusUpdated(); void ConnectionLost(); void AckReceived(); void NackReceived(); void LogLineReceived(QString line); void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol); 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, bool ignoreOpenError); 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 info; bool infoValid; union { Protocol::DeviceStatusV1 v1; } status; }; #endif // DEVICE_H