mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			194 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|     @file ConnectionSTREAM.h
 | |
|     @author Lime Microsystems
 | |
|     @brief Implementation of STREAM board connection.
 | |
| */
 | |
| 
 | |
| #pragma once
 | |
| #include <ConnectionRegistry.h>
 | |
| #include <IConnection.h>
 | |
| #include <ILimeSDRStreaming.h>
 | |
| #include <vector>
 | |
| #include <set>
 | |
| #include <string>
 | |
| #include <atomic>
 | |
| #include <memory>
 | |
| #include <thread>
 | |
| #include "fifo.h"
 | |
| #include <ciso646>
 | |
| 
 | |
| #define __unix__
 | |
| #include "windows.h"
 | |
| 
 | |
| #ifndef __unix__
 | |
| #include "windows.h"
 | |
| #include "CyAPI.h"
 | |
| #else
 | |
| #include <libusb-1.0/libusb.h>
 | |
| #include <mutex>
 | |
| #include <condition_variable>
 | |
| #include <chrono>
 | |
| #endif
 | |
| 
 | |
| namespace lime
 | |
| {
 | |
| 
 | |
| #define USB_MAX_CONTEXTS 64 //maximum number of contexts for asynchronous transfers
 | |
| 
 | |
| /** @brief Wrapper class for holding USB asynchronous transfers contexts
 | |
| */
 | |
| class USBTransferContext
 | |
| {
 | |
| public:
 | |
|     USBTransferContext() : used(false)
 | |
|     {
 | |
|         id = idCounter++;
 | |
| #ifndef __unix__
 | |
|         inOvLap = new OVERLAPPED;
 | |
|         memset(inOvLap, 0, sizeof(OVERLAPPED));
 | |
|         inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
 | |
|         context = NULL;
 | |
|         EndPt = nullptr;
 | |
| #else
 | |
|         transfer = libusb_alloc_transfer(0);
 | |
|         bytesXfered = 0;
 | |
|         bytesExpected = 0;
 | |
|         done = 0;
 | |
| #endif
 | |
|     }
 | |
|     ~USBTransferContext()
 | |
|     {
 | |
| #ifndef __unix__
 | |
|         CloseHandle(inOvLap->hEvent);
 | |
|         delete inOvLap;
 | |
| #else
 | |
|         libusb_free_transfer(transfer);
 | |
| #endif
 | |
|     }
 | |
|     bool reset()
 | |
|     {
 | |
|         if(used)
 | |
|             return false;
 | |
| #ifndef __unix__
 | |
|         CloseHandle(inOvLap->hEvent);
 | |
|         memset(inOvLap, 0, sizeof(OVERLAPPED));
 | |
|         inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
 | |
| #endif
 | |
|         return true;
 | |
|     }
 | |
|     bool used;
 | |
|     int id;
 | |
|     static int idCounter;
 | |
| #ifndef __unix__
 | |
|     PUCHAR context;
 | |
|     CCyUSBEndPoint* EndPt;
 | |
|     OVERLAPPED* inOvLap;
 | |
| #else
 | |
|     libusb_transfer* transfer;
 | |
|     long bytesXfered;
 | |
|     long bytesExpected;
 | |
|     std::atomic<bool> done;
 | |
|     std::mutex transferLock;
 | |
|     std::condition_variable cv;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| class ConnectionSTREAM : public ILimeSDRStreaming
 | |
| {
 | |
| public:
 | |
|     ConnectionSTREAM(void* arg, const std::string &vidpid, const std::string &serial, const unsigned index);
 | |
|     ~ConnectionSTREAM(void);
 | |
|     void VersionCheck(void);
 | |
| 
 | |
|     int Open(const std::string &vidpid, const std::string &serial, const unsigned index);
 | |
|     void Close();
 | |
|     bool IsOpen();
 | |
|     int GetOpenedIndex();
 | |
| 
 | |
|     virtual int Write(const unsigned char* buffer, int length, int timeout_ms = 100) override;
 | |
|     virtual int Read(unsigned char* buffer, int length, int timeout_ms = 100) override;
 | |
| 
 | |
|     //hooks to update FPGA plls when baseband interface data rate is changed
 | |
|     virtual int UpdateExternalDataRate(const size_t channel, const double txRate, const double rxRate) override;
 | |
|     virtual int UpdateExternalDataRate(const size_t channel, const double txRate, const double rxRate, const double txPhase, const double rxPhase) override;
 | |
|     virtual int ProgramWrite(const char *buffer, const size_t length, const int programmingMode, const int device, ProgrammingCallback callback) override;
 | |
|     int ProgramUpdate(const bool download, ProgrammingCallback callback);
 | |
|     int ReadRawStreamData(char* buffer, unsigned length, int epIndex, int timeout_ms = 100)override;
 | |
| protected:
 | |
|     virtual void ReceivePacketsLoop(Streamer* args) override;
 | |
|     virtual void TransmitPacketsLoop(Streamer* args) override;
 | |
|     int SendData(const char* buffer, int length, int epIndex = 0, int timeout = 100)override;
 | |
|     int ReceiveData(char* buffer, int length, int epIndex = 0, int timeout = 100)override;
 | |
| 
 | |
|     virtual int BeginDataReading(char* buffer, uint32_t length, const uint8_t streamBulkInAddr = 0x81);
 | |
|     virtual int WaitForReading(int contextHandle, unsigned int timeout_ms);
 | |
|     virtual int FinishDataReading(char* buffer, uint32_t length, int contextHandle);
 | |
|     virtual void AbortReading(int ep);
 | |
| 
 | |
|     virtual int BeginDataSending(const char* buffer, uint32_t length, const uint8_t streamBulkOutAddr = 0x01);
 | |
|     virtual int WaitForSending(int contextHandle, uint32_t timeout_ms);
 | |
|     virtual int FinishDataSending(const char* buffer, uint32_t length, int contextHandle);
 | |
|     virtual void AbortSending(int ep);
 | |
| 
 | |
|     int ResetStreamBuffers() override;
 | |
|     eConnectionType GetType(void) {return USB_PORT;}
 | |
| 
 | |
|     double DetectRefClk(void);
 | |
| 
 | |
|     USBTransferContext contexts[USB_MAX_CONTEXTS];
 | |
|     USBTransferContext contextsToSend[USB_MAX_CONTEXTS];
 | |
| 
 | |
|     bool isConnected;
 | |
| 
 | |
| #ifndef __unix__
 | |
|     static const int MAX_EP_CNT = 16;
 | |
|     CCyFX3Device* USBDevicePrimary;
 | |
|     //control endpoints
 | |
|     CCyControlEndPoint* InCtrlEndPt3;
 | |
|     CCyControlEndPoint* OutCtrlEndPt3;
 | |
| 
 | |
|     //end points for samples reading and writing
 | |
|     CCyUSBEndPoint* InEndPt[MAX_EP_CNT];
 | |
|     CCyUSBEndPoint* OutEndPt[MAX_EP_CNT];
 | |
| 
 | |
|     CCyUSBEndPoint* InCtrlBulkEndPt;
 | |
|     CCyUSBEndPoint* OutCtrlBulkEndPt;
 | |
| #else
 | |
|     libusb_device_handle* dev_handle; //a device handle
 | |
|     libusb_context* ctx; //a libusb session
 | |
|     int read_firmware_image(unsigned char *buf, int len);
 | |
|     int fx3_usbboot_download(unsigned char *buf, int len);
 | |
|     int ram_write(unsigned char *buf, unsigned int ramAddress, int len);
 | |
| #endif
 | |
|     static const uint8_t ctrlBulkOutAddr;
 | |
|     static const uint8_t ctrlBulkInAddr;
 | |
|     static const std::set<uint8_t> commandsToBulkCtrlHw1;
 | |
|     static const std::set<uint8_t> commandsToBulkCtrlHw2;
 | |
|     std::set<uint8_t> commandsToBulkCtrl;
 | |
|     bool bulkCtrlInProgress;
 | |
|     bool bulkCtrlAvailable;
 | |
|     std::mutex mExtraUsbMutex;
 | |
| };
 | |
| 
 | |
| class ConnectionSTREAMEntry : public ConnectionRegistryEntry
 | |
| {
 | |
| public:
 | |
|     ConnectionSTREAMEntry(void);
 | |
|     ConnectionSTREAMEntry(const std::string entryName);
 | |
|     virtual ~ConnectionSTREAMEntry(void);
 | |
|     virtual std::vector<ConnectionHandle> enumerate(const ConnectionHandle& hint);
 | |
|     virtual IConnection* make(const ConnectionHandle& handle);
 | |
| protected:
 | |
| #ifndef __unix__
 | |
|     std::string DeviceName(unsigned int index);
 | |
|     void *ctx; //not used, just for mirroring unix
 | |
| #else
 | |
|     libusb_context* ctx; //a libusb session
 | |
|     std::thread mUSBProcessingThread;
 | |
|     void handle_libusb_events();
 | |
|     std::atomic<bool> mProcessUSBEvents;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| }
 |