mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-30 20:40:20 -04:00 
			
		
		
		
	Deep redesign: Better support for FCD dongles #1
This commit is contained in:
		
							parent
							
								
									3a6f2b5481
								
							
						
					
					
						commit
						a909c4c40c
					
				| @ -329,3 +329,4 @@ qt5_use_modules(sdrangel Widgets Multimedia) | |||||||
| ############################################################################## | ############################################################################## | ||||||
| 
 | 
 | ||||||
| add_subdirectory(plugins) | add_subdirectory(plugins) | ||||||
|  | add_subdirectory(fcdhid) | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								Readme.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Readme.md
									
									
									
									
									
								
							| @ -18,11 +18,16 @@ These plugins come from the parent code base and are still present in the source | |||||||
| - Channels: | - Channels: | ||||||
|   - tetra  |   - tetra  | ||||||
| - Sample sources: | - Sample sources: | ||||||
|  |   - fcd | ||||||
|   - gnuradio |   - gnuradio | ||||||
|   - osmosdr |   - osmosdr | ||||||
|   - v4l-msi |   - v4l-msi | ||||||
|   - v4l-rtl |   - v4l-rtl | ||||||
|    |    | ||||||
|  | <h3>Funcube Dongle (fcd)</h3> | ||||||
|  | 
 | ||||||
|  | This is the old driver. | ||||||
|  | 
 | ||||||
| <h3>Gnuradio</h3> | <h3>Gnuradio</h3> | ||||||
| 
 | 
 | ||||||
| The Gnuradio plugin source needs extra packages, including `liblog4cpp-dev libboost-system-dev gnuradio-dev libosmosdr-dev` | The Gnuradio plugin source needs extra packages, including `liblog4cpp-dev libboost-system-dev gnuradio-dev libosmosdr-dev` | ||||||
| @ -51,11 +56,11 @@ If you use your own location for libbladeRF install directory you need to specif | |||||||
| 
 | 
 | ||||||
| `-DLIBBLADERF_LIBRARIES=/opt/install/libbladeRF/lib/libbladeRF.so -DLIBBLADERF_INCLUDE_DIR=/opt/install/libbladeRF/include` | `-DLIBBLADERF_LIBRARIES=/opt/install/libbladeRF/lib/libbladeRF.so -DLIBBLADERF_INCLUDE_DIR=/opt/install/libbladeRF/include` | ||||||
| 
 | 
 | ||||||
| <h2>Funcube Dongle</h2> | <h2>FunCube Dongle</h2> | ||||||
| 
 | 
 | ||||||
| Only the original Funcube Dongle Pro is supported. Funcube Dongle Pro+ will come later. | At the moment only the Pro+ is supported with the plugin in fcdpro. This is a work in progress. Support of features is still limited (no IF gain, no filter settings). | ||||||
| 
 | 
 | ||||||
| The interface is built in the software and do not require additional libraries other than USB support with libusb.  | The control interface is based on qthid and has been built in the software in the fcdhid library. You don't need anything else than libusb support. | ||||||
| 
 | 
 | ||||||
| <h2>RTL-SDR</h2> | <h2>RTL-SDR</h2> | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								fcdhid/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								fcdhid/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | project(fcdhid) | ||||||
|  | 
 | ||||||
|  | set(fcdhid_SOURCES | ||||||
|  | 	hid-libusb.c | ||||||
|  | 	fcdhid.c | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(fcdhid_HEADERS | ||||||
|  | 	fcdhid.h | ||||||
|  | 	hid-libusb.h | ||||||
|  | 	hidapi.h | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | include_directories( | ||||||
|  | 	. | ||||||
|  | 	${CMAKE_CURRENT_BINARY_DIR} | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include-gpl | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | #add_definitions(-DQT_PLUGIN) | ||||||
|  | add_definitions(-DQT_SHARED) | ||||||
|  | 
 | ||||||
|  | add_library(fcdhid SHARED | ||||||
|  | 	${fcdhid_SOURCES} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | target_link_libraries(fcdhid | ||||||
|  | 	${LIBUSB_LIBRARIES} | ||||||
|  | ) | ||||||
							
								
								
									
										927
									
								
								fcdhid/fcdhid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										927
									
								
								fcdhid/fcdhid.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,927 @@ | |||||||
|  | /***************************************************************************
 | ||||||
|  |  *  This file is part of Qthid. | ||||||
|  |  *  | ||||||
|  |  *  Copyright (C) 2010  Howard Long, G6LVB | ||||||
|  |  *  CopyRight (C) 2011  Alexandru Csete, OZ9AEC | ||||||
|  |  *                      Mario Lorenz, DL5MLO | ||||||
|  |  *  | ||||||
|  |  *  Qthid is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  Qthid is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with Qthid.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #include "fcdhid.h" | ||||||
|  | 
 | ||||||
|  | /** \brief Open FCD device.
 | ||||||
|  |  * \return Pointer to the FCD HID device or NULL if none found | ||||||
|  |  * | ||||||
|  |  * This function looks for FCD devices connected to the computer and | ||||||
|  |  * opens the first one found. | ||||||
|  |  */ | ||||||
|  | hid_device *fcdOpen(uint16_t usVID, uint16_t usPID, int whichdongle) | ||||||
|  | { | ||||||
|  |     struct hid_device_info *phdi=NULL; | ||||||
|  |     hid_device *phd=NULL; | ||||||
|  |     char *pszPath=NULL; | ||||||
|  | 
 | ||||||
|  |     phdi = hid_enumerate(usVID, usPID); | ||||||
|  | 
 | ||||||
|  |     int which = whichdongle; | ||||||
|  | 
 | ||||||
|  |     while (phdi && which) | ||||||
|  |     { | ||||||
|  |         phdi=phdi->next;     | ||||||
|  |         which--; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (phdi==NULL) | ||||||
|  |     { | ||||||
|  |         return NULL; // No FCD device found
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pszPath=strdup(phdi->path); | ||||||
|  | 
 | ||||||
|  |     if (pszPath==NULL) | ||||||
|  |     { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     hid_free_enumeration(phdi); | ||||||
|  |     phdi=NULL; | ||||||
|  | 
 | ||||||
|  |     if ((phd=hid_open_path(pszPath)) == NULL) | ||||||
|  |     { | ||||||
|  |         free(pszPath); | ||||||
|  |         pszPath=NULL; | ||||||
|  | 
 | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     free(pszPath); | ||||||
|  |     pszPath=NULL; | ||||||
|  | 
 | ||||||
|  |     return phd; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Close FCD HID device. */ | ||||||
|  | void fcdClose(hid_device *phd) | ||||||
|  | { | ||||||
|  |     hid_close(phd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Get FCD mode.
 | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * \sa FCD_MODE_ENUM | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetMode(hid_device *phd) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_DEAD; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     /* Send a BL Query Command */ | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_QUERY; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     /* first check status bytes then check which mode */ | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { | ||||||
|  | 
 | ||||||
|  |         /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ | ||||||
|  |         if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { | ||||||
|  |             fcd_mode = FCD_MODE_BL; | ||||||
|  |         } | ||||||
|  |         /* In application mode we have "FCDAPP_18.06" where the number is the FW version */ | ||||||
|  |         else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { | ||||||
|  |             fcd_mode = FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |         /* either no FCD or firmware less than 18f */ | ||||||
|  |         else { | ||||||
|  |             fcd_mode = FCD_MODE_NONE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return fcd_mode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Get FCD firmware version as string.
 | ||||||
|  |  * \param str The returned vesion number as a 0 terminated string (must be pre-allocated) | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * \sa FCD_MODE_ENUM | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetFwVerStr(hid_device *phd, char *str) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     /* Send a BL Query Command */ | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_QUERY; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     /* first check status bytes then check which mode */ | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { | ||||||
|  | 
 | ||||||
|  |         /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ | ||||||
|  |         if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { | ||||||
|  |             fcd_mode = FCD_MODE_BL; | ||||||
|  |         } | ||||||
|  |         /* In application mode we have "FCDAPP_18.06" where the number is the FW version */ | ||||||
|  |         else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { | ||||||
|  |             strncpy(str, (char *)(aucBufIn+9), 5); | ||||||
|  |             str[5] = 0; | ||||||
|  |             fcd_mode = FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |         /* either no FCD or firmware less than 18f */ | ||||||
|  |         else { | ||||||
|  |             fcd_mode = FCD_MODE_NONE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return fcd_mode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Get hardware and firmware dependent FCD capabilities.
 | ||||||
|  |  * \param fcd_caps Pointer to an FCD_CAPS_STRUCT | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function queries the FCD and extracts the hardware and firmware dependent | ||||||
|  |  * capabilities. Currently these capabilities are: | ||||||
|  |  *  - Bias T (available since S/N TBD) | ||||||
|  |  *  - Cellular block (the certified version of the FCD) | ||||||
|  |  * When the FCD is in application mode, the string returned by the query command is | ||||||
|  |  * (starting at index 2): | ||||||
|  |  *    FCDAPP 18.08 Brd 1.0 No blk | ||||||
|  |  * 1.0 means no bias tee, 1.1 means there is a bias tee | ||||||
|  |  * 'No blk' means it is not cellular blocked. | ||||||
|  |  * | ||||||
|  |  * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
 | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetCaps(hid_device *phd, FCD_CAPS_STRUCT *fcd_caps) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  |     /* clear output buffer */ | ||||||
|  |     fcd_caps->hasBiasT = 0; | ||||||
|  |     fcd_caps->hasCellBlock = 0; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     /* Send a BL Query Command */ | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_QUERY; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     /* first check status bytes then check which mode */ | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { | ||||||
|  | 
 | ||||||
|  |         /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ | ||||||
|  |         if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { | ||||||
|  |             fcd_mode = FCD_MODE_BL; | ||||||
|  |         } | ||||||
|  |         /* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */ | ||||||
|  |         else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { | ||||||
|  | 
 | ||||||
|  |             /* Bias T */ | ||||||
|  |             fcd_caps->hasBiasT = (aucBufIn[21] == '1') ? 1 : 0; | ||||||
|  | 
 | ||||||
|  |             /* cellular block */ | ||||||
|  |             if (strncmp((char *)(aucBufIn+23), "No blk", 6) == 0) { | ||||||
|  |                 fcd_caps->hasCellBlock = 0; | ||||||
|  |             } else { | ||||||
|  |                 fcd_caps->hasCellBlock = 1; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             fcd_mode = FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |         /* either no FCD or firmware less than 18f */ | ||||||
|  |         else { | ||||||
|  |             fcd_mode = FCD_MODE_NONE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return fcd_mode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Get hardware and firmware dependent FCD capabilities as string.
 | ||||||
|  |  * \param caps_str Pointer to a pre-allocated string buffer where the info will be copied. | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function queries the FCD and copies the returned string into the caps_str parameter. | ||||||
|  |  * THe return buffer must be at least 28 characters. | ||||||
|  |  * When the FCD is in application mode, the string returned by the query command is | ||||||
|  |  * (starting at index 2): | ||||||
|  |  *    FCDAPP 18.08 Brd 1.0 No blk | ||||||
|  |  * 1.0 means no bias tee, 1.1 means there is a bias tee | ||||||
|  |  * 'No blk' means it is not cellular blocked. | ||||||
|  |  * | ||||||
|  |  * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
 | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetCapsStr(hid_device *phd, char *caps_str) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     /* Send a BL Query Command */ | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_QUERY; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     /* first check status bytes then check which mode */ | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { | ||||||
|  | 
 | ||||||
|  |         /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ | ||||||
|  |         if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { | ||||||
|  |             fcd_mode = FCD_MODE_BL; | ||||||
|  |         } | ||||||
|  |         /* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */ | ||||||
|  |         else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { | ||||||
|  | 
 | ||||||
|  |             strncpy(caps_str, (char *)(aucBufIn+2), 27); | ||||||
|  |             caps_str[27] = 0; | ||||||
|  | 
 | ||||||
|  |             fcd_mode = FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |         /* either no FCD or firmware less than 18f */ | ||||||
|  |         else { | ||||||
|  |             fcd_mode = FCD_MODE_NONE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return fcd_mode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Reset FCD to bootloader mode.
 | ||||||
|  |  * \return FCD_MODE_NONE | ||||||
|  |  * | ||||||
|  |  * This function is used to switch the FCD into bootloader mode in which | ||||||
|  |  * various firmware operations can be performed. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppReset(hid_device *phd) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     //unsigned char aucBufIn[65];
 | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Send an App reset command
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_APP_RESET; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  | 
 | ||||||
|  |     /** FIXME: hid_read() will occasionally hang due to a pthread_cond_wait() never returning.
 | ||||||
|  |       It seems that the read_callback() in hid-libusb.c will never receive any | ||||||
|  |       data during the reconfiguration. Since the same logic works in the native | ||||||
|  |       windows application, it could be a libusb thing. Anyhow, since the value | ||||||
|  |       returned by this function is not used, we may as well just skip the hid_read() | ||||||
|  |       and return FME_NONE. | ||||||
|  |       Correct switch from APP to BL mode can be observed in /var/log/messages (linux) | ||||||
|  |       (when in bootloader mode the device version includes 'BL') | ||||||
|  |       */ | ||||||
|  |     /*
 | ||||||
|  |        memset(aucBufIn,0xCC,65); // Clear out the response buffer
 | ||||||
|  |        hid_read(phd,aucBufIn,65); | ||||||
|  | 
 | ||||||
|  |        if (aucBufIn[0]==FCDCMDAPPRESET && aucBufIn[1]==1) | ||||||
|  |        { | ||||||
|  |        FCDClose(phd); | ||||||
|  |        phd=NULL; | ||||||
|  |        return FME_APP; | ||||||
|  |        } | ||||||
|  |        FCDClose(phd); | ||||||
|  |        phd=NULL; | ||||||
|  |        return FME_BL; | ||||||
|  |        */ | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Set FCD frequency with kHz resolution.
 | ||||||
|  |  * \param nFreq The new frequency in kHz. | ||||||
|  |  * \return The FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function sets the frequency of the FCD with 1 kHz resolution. The parameter | ||||||
|  |  * nFreq must already contain any necessary frequency correction. | ||||||
|  |  * | ||||||
|  |  * \sa fcdAppSetFreq | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetFreqkHz(hid_device *phd, int nFreq) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Send an App reset command
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_APP_SET_FREQ_KHZ; | ||||||
|  |     aucBufOut[2] = (unsigned char)nFreq; | ||||||
|  |     aucBufOut[3] = (unsigned char)(nFreq>>8); | ||||||
|  |     aucBufOut[4] = (unsigned char)(nFreq>>16); | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_KHZ && aucBufIn[1]==1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Set FCD frequency with Hz resolution.
 | ||||||
|  |  * \param nFreq The new frequency in Hz. | ||||||
|  |  * \return The FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function sets the frequency of the FCD with 1 Hz resolution. The parameter | ||||||
|  |  * nFreq must already contain any necessary frequency correction. | ||||||
|  |  * | ||||||
|  |  * \sa fcdAppSetFreq | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetFreq(hid_device *phd, int nFreq) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Send an App reset command
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_APP_SET_FREQ_HZ; | ||||||
|  |     aucBufOut[2] = (unsigned char)nFreq; | ||||||
|  |     aucBufOut[3] = (unsigned char)(nFreq>>8); | ||||||
|  |     aucBufOut[4] = (unsigned char)(nFreq>>16); | ||||||
|  |     aucBufOut[5] = (unsigned char)(nFreq>>24); | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_HZ && aucBufIn[1]==1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Reset FCD to application mode.
 | ||||||
|  |  * \return FCD_MODE_NONE | ||||||
|  |  * | ||||||
|  |  * This function is used to switch the FCD from bootloader mode | ||||||
|  |  * into application mode. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlReset(hid_device *phd) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     //    unsigned char aucBufIn[65];
 | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Send an BL reset command
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_RESET; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  | 
 | ||||||
|  |     /** FIXME: hid_read() will hang due to a pthread_cond_wait() never returning.
 | ||||||
|  |       It seems that the read_callback() in hid-libusb.c will never receive any | ||||||
|  |       data during the reconfiguration. Since the same logic works in the native | ||||||
|  |       windows application, it could be a libusb thing. Anyhow, since the value | ||||||
|  |       returned by this function is not used, we may as well jsut skip the hid_read() | ||||||
|  |       and return FME_NONE. | ||||||
|  |       Correct switch from BL to APP mode can be observed in /var/log/messages (linux) | ||||||
|  |       (when in bootloader mode the device version includes 'BL') | ||||||
|  |       */ | ||||||
|  |     /*
 | ||||||
|  |        memset(aucBufIn,0xCC,65); // Clear out the response buffer
 | ||||||
|  |        hid_read(phd,aucBufIn,65); | ||||||
|  | 
 | ||||||
|  |        if (aucBufIn[0]==FCDCMDBLRESET && aucBufIn[1]==1) | ||||||
|  |        { | ||||||
|  |        FCDClose(phd); | ||||||
|  |        phd=NULL; | ||||||
|  |        return FME_BL; | ||||||
|  |        } | ||||||
|  |        FCDClose(phd); | ||||||
|  |        phd=NULL; | ||||||
|  |        return FME_APP; | ||||||
|  |        */ | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_NONE; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Erase firmware from FCD.
 | ||||||
|  |  * \return The FCD mode | ||||||
|  |  * | ||||||
|  |  * This function deletes the firmware from the FCD. This is required | ||||||
|  |  * before writing new firmware into the FCD. | ||||||
|  |  * | ||||||
|  |  * \sa fcdBlWriteFirmware | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlErase(hid_device *phd) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Send an App reset command
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_ERASE; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]==FCD_CMD_BL_ERASE && aucBufIn[1]==1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_BL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_APP; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Write new firmware into the FCD.
 | ||||||
|  |  * \param pc Pointer to the new firmware data | ||||||
|  |  * \param n64size The number of bytes in the data | ||||||
|  |  * \return The FCD mode | ||||||
|  |  * | ||||||
|  |  * This function is used to upload new firmware into the FCD flash. | ||||||
|  |  * | ||||||
|  |  * \sa fcdBlErase | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlWriteFirmware(hid_device *phd, char *pc, int64_t n64Size) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     uint32_t u32AddrStart; | ||||||
|  |     uint32_t u32AddrEnd; | ||||||
|  |     uint32_t u32Addr; | ||||||
|  |     BOOL bFinished=FALSE; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd==NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Get the valid flash address range
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32AddrStart= | ||||||
|  |         aucBufIn[2]+ | ||||||
|  |         (((uint32_t)aucBufIn[3])<<8)+ | ||||||
|  |         (((uint32_t)aucBufIn[4])<<16)+ | ||||||
|  |         (((uint32_t)aucBufIn[5])<<24); | ||||||
|  |     u32AddrEnd= | ||||||
|  |         aucBufIn[6]+ | ||||||
|  |         (((uint32_t)aucBufIn[7])<<8)+ | ||||||
|  |         (((uint32_t)aucBufIn[8])<<16)+ | ||||||
|  |         (((uint32_t)aucBufIn[9])<<24); | ||||||
|  | 
 | ||||||
|  |     // Set start address for flash
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR; | ||||||
|  |     aucBufOut[2] = ((unsigned char)u32AddrStart); | ||||||
|  |     aucBufOut[3] = ((unsigned char)(u32AddrStart>>8)); | ||||||
|  |     aucBufOut[4] = ((unsigned char)(u32AddrStart>>16)); | ||||||
|  |     aucBufOut[5] = ((unsigned char)(u32AddrStart>>24)); | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Write blocks
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_WRITE_FLASH_BLOCK; | ||||||
|  |     for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48) | ||||||
|  |     { | ||||||
|  |         memcpy(&aucBufOut[3], &pc[u32Addr], 48); | ||||||
|  | 
 | ||||||
|  |         hid_write(phd, aucBufOut, 65); | ||||||
|  |         memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |         hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |         if (aucBufIn[0]!=FCD_CMD_BL_WRITE_FLASH_BLOCK || aucBufIn[1]!=1) | ||||||
|  |         { | ||||||
|  |             bFinished = TRUE; | ||||||
|  |             /*
 | ||||||
|  |             fcdClose(phd); | ||||||
|  |             phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |             return FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Verify firmware in FCd flash.
 | ||||||
|  |  * \param pc Pointer to firmware data to verify against. | ||||||
|  |  * \param n64Size Size of the data in pc. | ||||||
|  |  * \return The FCD_MODE_BL if verification was succesful. | ||||||
|  |  * | ||||||
|  |  * This function verifies the firmware currently in the FCd flash against the firmware | ||||||
|  |  * image pointed to by pc. The function return FCD_MODE_BL if the verification is OK and | ||||||
|  |  * FCD_MODE_APP otherwise. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlVerifyFirmware(hid_device *phd, char *pc, int64_t n64Size) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     uint32_t u32AddrStart; | ||||||
|  |     uint32_t u32AddrEnd; | ||||||
|  |     uint32_t u32Addr; | ||||||
|  |     BOOL bFinished=FALSE; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd==NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     // Get the valid flash address range
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE; | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32AddrStart= | ||||||
|  |         aucBufIn[2]+ | ||||||
|  |         (((uint32_t)aucBufIn[3])<<8)+ | ||||||
|  |         (((uint32_t)aucBufIn[4])<<16)+ | ||||||
|  |         (((uint32_t)aucBufIn[5])<<24); | ||||||
|  | 
 | ||||||
|  |     u32AddrEnd= | ||||||
|  |         aucBufIn[6]+ | ||||||
|  |         (((uint32_t)aucBufIn[7])<<8)+ | ||||||
|  |         (((uint32_t)aucBufIn[8])<<16)+ | ||||||
|  |         (((uint32_t)aucBufIn[9])<<24); | ||||||
|  | 
 | ||||||
|  |     // Set start address for flash
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR; | ||||||
|  |     aucBufOut[2] = ((unsigned char)u32AddrStart); | ||||||
|  |     aucBufOut[3] = ((unsigned char)(u32AddrStart>>8)); | ||||||
|  |     aucBufOut[4] = ((unsigned char)(u32AddrStart>>16)); | ||||||
|  |     aucBufOut[5] = ((unsigned char)(u32AddrStart>>24)); | ||||||
|  |     hid_write(phd, aucBufOut, 65); | ||||||
|  |     memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |     if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1) | ||||||
|  |     { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Read blocks
 | ||||||
|  |     aucBufOut[0] = 0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1] = FCD_CMD_BL_READ_FLASH_BLOCK; | ||||||
|  |     for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48) | ||||||
|  |     { | ||||||
|  |         hid_write(phd, aucBufOut, 65); | ||||||
|  |         memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
 | ||||||
|  |         hid_read(phd, aucBufIn, 65); | ||||||
|  | 
 | ||||||
|  |         if (aucBufIn[0]!=FCD_CMD_BL_READ_FLASH_BLOCK || aucBufIn[1]!=1) | ||||||
|  |         { | ||||||
|  |             bFinished = TRUE; | ||||||
|  |             /*
 | ||||||
|  |             fcdClose(phd); | ||||||
|  |             phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |             return FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (memcmp(&aucBufIn[2],&pc[u32Addr],48)!=0) | ||||||
|  |         { | ||||||
|  |             bFinished = TRUE; | ||||||
|  |             /*
 | ||||||
|  |             fcdClose(phd); | ||||||
|  |             phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |             return FCD_MODE_APP; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Write FCD parameter (e.g. gain or filter)
 | ||||||
|  |  * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_SET_* | ||||||
|  |  * \param pu8Data The parameter value to be written | ||||||
|  |  * \param u8len Length of pu8Data in bytes | ||||||
|  |  * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) | ||||||
|  |  * | ||||||
|  |  * This function can be used to set the value of a parameter in the FCD for which there is no | ||||||
|  |  * high level API call. It gives access to the low level API of the FCD and the caller is expected | ||||||
|  |  * to be aware of the various FCD commands, since they are required to be supplied as parameter | ||||||
|  |  * to this function. | ||||||
|  |  * | ||||||
|  |  * The return value can be used to determine the success or failure of the command execution: | ||||||
|  |  * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). | ||||||
|  |  * - FCD_MODE_BL : Reply from FCD was not as expected. | ||||||
|  |  * - FCD_MODE_NONE : No FCD was found | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetParam(hid_device *phd, uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  | 
 | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     aucBufOut[0]=0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1]=u8Cmd; | ||||||
|  |     memcpy(aucBufOut+2, pu8Data,u8len); | ||||||
|  |     hid_write(phd,aucBufOut,65); | ||||||
|  | 
 | ||||||
|  |     /* we must read after each write in order to empty FCD/HID buffer */ | ||||||
|  |     memset(aucBufIn,0xCC,65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd,aucBufIn,65); | ||||||
|  | 
 | ||||||
|  |     /* Check the response, if OK return FCD_MODE_APP */ | ||||||
|  |     if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Response did not contain the expected bytes */ | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** \brief Read FCD parameter (e.g. gain or filter)
 | ||||||
|  |  * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_GET_* | ||||||
|  |  * \param pu8Data TPointer to buffer where the parameter value(s) will be written | ||||||
|  |  * \param u8len Length of pu8Data in bytes | ||||||
|  |  * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) | ||||||
|  |  * | ||||||
|  |  * This function can be used to read the value of a parameter in the FCD for which there is no | ||||||
|  |  * high level API call. It gives access to the low level API of the FCD and the caller is expected | ||||||
|  |  * to be aware of the various FCD commands, since they are required to be supplied as parameter | ||||||
|  |  * to this function. | ||||||
|  |  * | ||||||
|  |  * The return value can be used to determine the success or failure of the command execution: | ||||||
|  |  * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). | ||||||
|  |  * - FCD_MODE_BL : Reply from FCD was not as expected. | ||||||
|  |  * - FCD_MODE_NONE : No FCD was found | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppGetParam(hid_device *phd, uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len) | ||||||
|  | { | ||||||
|  |     //hid_device *phd=NULL;
 | ||||||
|  |     unsigned char aucBufOut[65]; | ||||||
|  |     unsigned char aucBufIn[65]; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |     phd = fcdOpen(); | ||||||
|  |     if (phd == NULL) | ||||||
|  |     { | ||||||
|  |         return FCD_MODE_NONE; | ||||||
|  |     }*/ | ||||||
|  | 
 | ||||||
|  |     aucBufOut[0]=0; // Report ID, ignored
 | ||||||
|  |     aucBufOut[1]=u8Cmd; | ||||||
|  |     hid_write(phd,aucBufOut,65); | ||||||
|  | 
 | ||||||
|  |     memset(aucBufIn,0xCC,65); // Clear out the response buffer
 | ||||||
|  |     hid_read(phd,aucBufIn,65); | ||||||
|  |     /* Copy return data to output buffer (even if cmd exec failed) */ | ||||||
|  |     memcpy(pu8Data,aucBufIn+2,u8len); | ||||||
|  | 
 | ||||||
|  |     /* Check status bytes in returned data */ | ||||||
|  |     if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) { | ||||||
|  |     	/*
 | ||||||
|  |         fcdClose(phd); | ||||||
|  |         phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |         return FCD_MODE_APP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Response did not contain the expected bytes */ | ||||||
|  |     /*
 | ||||||
|  |     fcdClose(phd); | ||||||
|  |     phd = NULL;*/ | ||||||
|  | 
 | ||||||
|  |     return FCD_MODE_BL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										234
									
								
								fcdhid/fcdhid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								fcdhid/fcdhid.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,234 @@ | |||||||
|  | /***************************************************************************
 | ||||||
|  |  *  This file is part of Qthid. | ||||||
|  |  *  | ||||||
|  |  *  Copyright (C) 2010  Howard Long, G6LVB | ||||||
|  |  *  CopyRight (C) 2011  Alexandru Csete, OZ9AEC | ||||||
|  |  *                      Mario Lorenz, DL5MLO | ||||||
|  |  *  | ||||||
|  |  *  Qthid is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  Qthid is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with Qthid.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #ifndef _QTHID_H_ | ||||||
|  | #define _QTHID_H_ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "fcdhidcmd.h" | ||||||
|  | #include "hidapi.h" | ||||||
|  | 
 | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | #define FALSE 0 | ||||||
|  | #define TRUE 1 | ||||||
|  | typedef int BOOL; | ||||||
|  | 
 | ||||||
|  | /** \brief FCD mode enumeration. */ | ||||||
|  | typedef enum { | ||||||
|  |     FCD_MODE_NONE,  /*!< No FCD detected. */ | ||||||
|  |     FCD_MODE_DEAD, | ||||||
|  |     FCD_MODE_BL,    /*!< FCD present in bootloader mode. */ | ||||||
|  |     FCD_MODE_APP    /*!< FCD present in aplpication mode. */ | ||||||
|  | } FCD_MODE_ENUM; // The current mode of the FCD: none inserted, in bootloader mode or in normal application mode
 | ||||||
|  | 
 | ||||||
|  | /** \brief FCD capabilities that depend on both hardware and firmware. */ | ||||||
|  | typedef struct { | ||||||
|  |     unsigned char hasBiasT;     /*!< Whether FCD has hardware bias tee (1=yes, 0=no) */ | ||||||
|  |     unsigned char hasCellBlock; /*!< Whether FCD has cellular blocking. */ | ||||||
|  | } FCD_CAPS_STRUCT; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //#define FCDPP // FIXME: the Pro / Pro+ switch should be handled better than this!
 | ||||||
|  | //const unsigned short _usVID=0x04D8;  /*!< USB vendor ID. */
 | ||||||
|  | //#ifdef FCDPP
 | ||||||
|  | //const unsigned short _usPID=0xFB31;  /*!< USB product ID. */
 | ||||||
|  | //#else
 | ||||||
|  | //const unsigned short _usPID=0xFB56;  /*!< USB product ID. */
 | ||||||
|  | //#endif
 | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /** \brief Open FCD device.
 | ||||||
|  |  * \return Pointer to the FCD HID device or NULL if none found | ||||||
|  |  * | ||||||
|  |  * This function looks for FCD devices connected to the computer and | ||||||
|  |  * opens the first one found. | ||||||
|  |  */ | ||||||
|  | hid_device *fcdOpen(uint16_t usVID, uint16_t usPID, int whichdongle); | ||||||
|  | 
 | ||||||
|  | /** \brief Close FCD HID device. */ | ||||||
|  | void fcdClose(hid_device *phd); | ||||||
|  | 
 | ||||||
|  | /** \brief Get FCD mode.
 | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * \sa FCD_MODE_ENUM | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetMode(hid_device *phd); | ||||||
|  | 
 | ||||||
|  | /** \brief Get FCD firmware version as string.
 | ||||||
|  |  * \param str The returned vesion number as a 0 terminated string (must be pre-allocated) | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * \sa FCD_MODE_ENUM | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetFwVerStr(hid_device *phd, char *str); | ||||||
|  | 
 | ||||||
|  | /** \brief Get hardware and firmware dependent FCD capabilities.
 | ||||||
|  |  * \param fcd_caps Pointer to an FCD_CAPS_STRUCT | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function queries the FCD and extracts the hardware and firmware dependent | ||||||
|  |  * capabilities. Currently these capabilities are: | ||||||
|  |  *  - Bias T (available since S/N TBD) | ||||||
|  |  *  - Cellular block (the certified version of the FCD) | ||||||
|  |  * When the FCD is in application mode, the string returned by the query command is | ||||||
|  |  * (starting at index 2): | ||||||
|  |  *    FCDAPP 18.08 Brd 1.0 No blk | ||||||
|  |  * 1.0 means no bias tee, 1.1 means there is a bias tee | ||||||
|  |  * 'No blk' means it is not cellular blocked. | ||||||
|  |  * | ||||||
|  |  * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
 | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetCaps(hid_device *phd, FCD_CAPS_STRUCT *fcd_caps); | ||||||
|  | 
 | ||||||
|  | /** \brief Get hardware and firmware dependent FCD capabilities as string.
 | ||||||
|  |  * \param caps_str Pointer to a pre-allocated string buffer where the info will be copied. | ||||||
|  |  * \return The current FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function queries the FCD and copies the returned string into the caps_str parameter. | ||||||
|  |  * THe return buffer must be at least 28 characters. | ||||||
|  |  * When the FCD is in application mode, the string returned by the query command is | ||||||
|  |  * (starting at index 2): | ||||||
|  |  *    FCDAPP 18.08 Brd 1.0 No blk | ||||||
|  |  * 1.0 means no bias tee, 1.1 means there is a bias tee | ||||||
|  |  * 'No blk' means it is not cellular blocked. | ||||||
|  |  * | ||||||
|  |  * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
 | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdGetCapsStr(hid_device *phd, char *caps_str); | ||||||
|  | 
 | ||||||
|  | /** \brief Reset FCD to bootloader mode.
 | ||||||
|  |  * \return FCD_MODE_NONE | ||||||
|  |  * | ||||||
|  |  * This function is used to switch the FCD into bootloader mode in which | ||||||
|  |  * various firmware operations can be performed. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppReset(hid_device *phd); | ||||||
|  | 
 | ||||||
|  | /** \brief Set FCD frequency with kHz resolution.
 | ||||||
|  |  * \param nFreq The new frequency in kHz. | ||||||
|  |  * \return The FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function sets the frequency of the FCD with 1 kHz resolution. The parameter | ||||||
|  |  * nFreq must already contain any necessary frequency correction. | ||||||
|  |  * | ||||||
|  |  * \sa fcdAppSetFreq | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetFreqkHz(hid_device *phd, int nFreq); | ||||||
|  | 
 | ||||||
|  | /** \brief Set FCD frequency with Hz resolution.
 | ||||||
|  |  * \param nFreq The new frequency in Hz. | ||||||
|  |  * \return The FCD mode. | ||||||
|  |  * | ||||||
|  |  * This function sets the frequency of the FCD with 1 Hz resolution. The parameter | ||||||
|  |  * nFreq must already contain any necessary frequency correction. | ||||||
|  |  * | ||||||
|  |  * \sa fcdAppSetFreq | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetFreq(hid_device *phd, int nFreq); | ||||||
|  | 
 | ||||||
|  | /** \brief Reset FCD to application mode.
 | ||||||
|  |  * \return FCD_MODE_NONE | ||||||
|  |  * | ||||||
|  |  * This function is used to switch the FCD from bootloader mode | ||||||
|  |  * into application mode. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlReset(hid_device *phd); | ||||||
|  | 
 | ||||||
|  | /** \brief Erase firmware from FCD.
 | ||||||
|  |  * \return The FCD mode | ||||||
|  |  * | ||||||
|  |  * This function deletes the firmware from the FCD. This is required | ||||||
|  |  * before writing new firmware into the FCD. | ||||||
|  |  * | ||||||
|  |  * \sa fcdBlWriteFirmware | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlErase(hid_device *phd); | ||||||
|  | 
 | ||||||
|  | /** \brief Write new firmware into the FCD.
 | ||||||
|  |  * \param pc Pointer to the new firmware data | ||||||
|  |  * \param n64size The number of bytes in the data | ||||||
|  |  * \return The FCD mode | ||||||
|  |  * | ||||||
|  |  * This function is used to upload new firmware into the FCD flash. | ||||||
|  |  * | ||||||
|  |  * \sa fcdBlErase | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlWriteFirmware(hid_device *phd, char *pc, int64_t n64Size); | ||||||
|  | 
 | ||||||
|  | /** \brief Verify firmware in FCd flash.
 | ||||||
|  |  * \param pc Pointer to firmware data to verify against. | ||||||
|  |  * \param n64Size Size of the data in pc. | ||||||
|  |  * \return The FCD_MODE_BL if verification was succesful. | ||||||
|  |  * | ||||||
|  |  * This function verifies the firmware currently in the FCd flash against the firmware | ||||||
|  |  * image pointed to by pc. The function return FCD_MODE_BL if the verification is OK and | ||||||
|  |  * FCD_MODE_APP otherwise. | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdBlVerifyFirmware(hid_device *phd, char *pc, int64_t n64Size); | ||||||
|  | 
 | ||||||
|  | /** \brief Write FCD parameter (e.g. gain or filter)
 | ||||||
|  |  * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_SET_* | ||||||
|  |  * \param pu8Data The parameter value to be written | ||||||
|  |  * \param u8len Length of pu8Data in bytes | ||||||
|  |  * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) | ||||||
|  |  * | ||||||
|  |  * This function can be used to set the value of a parameter in the FCD for which there is no | ||||||
|  |  * high level API call. It gives access to the low level API of the FCD and the caller is expected | ||||||
|  |  * to be aware of the various FCD commands, since they are required to be supplied as parameter | ||||||
|  |  * to this function. | ||||||
|  |  * | ||||||
|  |  * The return value can be used to determine the success or failure of the command execution: | ||||||
|  |  * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). | ||||||
|  |  * - FCD_MODE_BL : Reply from FCD was not as expected. | ||||||
|  |  * - FCD_MODE_NONE : No FCD was found | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppSetParam(hid_device *phd, uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len); | ||||||
|  | 
 | ||||||
|  | /** \brief Read FCD parameter (e.g. gain or filter)
 | ||||||
|  |  * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_GET_* | ||||||
|  |  * \param pu8Data TPointer to buffer where the parameter value(s) will be written | ||||||
|  |  * \param u8len Length of pu8Data in bytes | ||||||
|  |  * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) | ||||||
|  |  * | ||||||
|  |  * This function can be used to read the value of a parameter in the FCD for which there is no | ||||||
|  |  * high level API call. It gives access to the low level API of the FCD and the caller is expected | ||||||
|  |  * to be aware of the various FCD commands, since they are required to be supplied as parameter | ||||||
|  |  * to this function. | ||||||
|  |  * | ||||||
|  |  * The return value can be used to determine the success or failure of the command execution: | ||||||
|  |  * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). | ||||||
|  |  * - FCD_MODE_BL : Reply from FCD was not as expected. | ||||||
|  |  * - FCD_MODE_NONE : No FCD was found | ||||||
|  |  */ | ||||||
|  | FCD_MODE_ENUM fcdAppGetParam(hid_device *phd, uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif // _QTHID_H_
 | ||||||
							
								
								
									
										305
									
								
								fcdhid/fcdhidcmd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								fcdhid/fcdhidcmd.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,305 @@ | |||||||
|  | /***************************************************************************
 | ||||||
|  |  *  This file is part of Qthid. | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2010  Howard Long, G6LVB | ||||||
|  |  *  CopyRight (C) 2011  Alexandru Csete, OZ9AEC | ||||||
|  |  *                      Mario Lorenz, DL5MLO | ||||||
|  |  * | ||||||
|  |  *  Qthid is free software: you can redistribute it and/or modify | ||||||
|  |  *  it under the terms of the GNU General Public License as published by | ||||||
|  |  *  the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  *  (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  Qthid is distributed in the hope that it will be useful, | ||||||
|  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *  GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with Qthid.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  |  * | ||||||
|  |  ***************************************************************************/ | ||||||
|  | #ifndef FCDHIDCMD_H | ||||||
|  | #define FCDHIDCMD_H | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Commands applicable in bootloader mode */ | ||||||
|  | #define FCD_CMD_BL_QUERY                1  /*!< Returns string with "FCDAPP version". */ | ||||||
|  | #define FCD_CMD_BL_RESET                8  /*!< Reset to application mode. */ | ||||||
|  | #define FCD_CMD_BL_ERASE               24  /*!< Erase firmware from FCD flash. */ | ||||||
|  | #define FCD_CMD_BL_SET_BYTE_ADDR       25  /*!< TBD */ | ||||||
|  | #define FCD_CMD_BL_GET_BYTE_ADDR_RANGE 26  /*!< Get address range. */ | ||||||
|  | #define FCD_CMD_BL_WRITE_FLASH_BLOCK   27  /*!< Write flash block. */ | ||||||
|  | #define FCD_CMD_BL_READ_FLASH_BLOCK    28  /*!< Read flash block. */ | ||||||
|  | 
 | ||||||
|  | /* Commands applicable in application mode */ | ||||||
|  | #define FCD_CMD_APP_SET_FREQ_KHZ     100 /*!< Send with 3 byte unsigned little endian frequency in kHz. */ | ||||||
|  | #define FCD_CMD_APP_SET_FREQ_HZ      101 /*!< Send with 4 byte unsigned little endian frequency in Hz, returns with actual frequency set in Hz */ | ||||||
|  | #define FCD_CMD_APP_GET_FREQ_HZ      102 /*!< Returns 4 byte unsigned little endian frequency in Hz. */ | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_GET_IF_RSSI      104 /*!< Supposed to return 1 byte unsigned IF RSSI (-35dBm=0, -10dBm=70) but it is not functional. */ | ||||||
|  | #define FCD_CMD_APP_GET_PLL_LOCK     105 /*!< Returns 1 bit, true if locked. */ | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_SET_DC_CORR      106 /*!< Send with 2 byte unsigned I DC correction followed by 2 byte unsigned Q DC correction. 32768 is the default centre value. */ | ||||||
|  | #define FCD_CMD_APP_GET_DC_CORR      107 /*!< Returns 2 byte unsigned I DC correction followed by 2 byte unsigned Q DC correction. 32768 is the default centre value. */ | ||||||
|  | #define FCD_CMD_APP_SET_IQ_CORR      108 /*!< Send with 2 byte signed phase correction followed by 2 byte unsigned gain correction. 0 is the default centre value for phase correction, 32768 is the default centre value for gain. */ | ||||||
|  | #define FCD_CMD_APP_GET_IQ_CORR      109 /*!< Returns 2 byte signed phase correction followed by 2 byte unsigned gain correction. 0 is the default centre value for phase correction, 32768 is the default centre value for gain. */ | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_SET_LNA_GAIN     110 /*!< Send a 1 byte value, see enums for reference. */ | ||||||
|  | #define FCD_CMD_APP_SET_LNA_ENHANCE  111 | ||||||
|  | #define FCD_CMD_APP_SET_BAND         112 | ||||||
|  | #define FCD_CMD_APP_SET_RF_FILTER    113 | ||||||
|  | #define FCD_CMD_APP_SET_MIXER_GAIN   114 | ||||||
|  | #define FCD_CMD_APP_SET_BIAS_CURRENT 115 | ||||||
|  | #define FCD_CMD_APP_SET_MIXER_FILTER 116 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN1     117 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN_MODE 118 | ||||||
|  | #define FCD_CMD_APP_SET_IF_RC_FILTER 119 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN2     120 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN3     121 | ||||||
|  | #define FCD_CMD_APP_SET_IF_FILTER    122 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN4     123 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN5     124 | ||||||
|  | #define FCD_CMD_APP_SET_IF_GAIN6     125 | ||||||
|  | #define FCD_CMD_APP_SET_BIAS_TEE     126 /*!< Bias T for ext LNA. Send with one byte: 1=ON, 0=OFF. */ | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_GET_LNA_GAIN     150 // Retrieve a 1 byte value, see enums for reference
 | ||||||
|  | #define FCD_CMD_APP_GET_LNA_ENHANCE  151 | ||||||
|  | #define FCD_CMD_APP_GET_BAND         152 | ||||||
|  | #define FCD_CMD_APP_GET_RF_FILTER    153 | ||||||
|  | #define FCD_CMD_APP_GET_MIXER_GAIN   154 | ||||||
|  | #define FCD_CMD_APP_GET_BIAS_CURRENT 155 | ||||||
|  | #define FCD_CMD_APP_GET_MIXER_FILTER 156 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN1     157 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN_MODE 158 | ||||||
|  | #define FCD_CMD_APP_GET_IF_RC_FILTER 159 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN2     160 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN3     161 | ||||||
|  | #define FCD_CMD_APP_GET_IF_FILTER    162 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN4     163 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN5     164 | ||||||
|  | #define FCD_CMD_APP_GET_IF_GAIN6     165 | ||||||
|  | #define FCD_CMD_APP_GET_BIAS_TEE     166 /*!< Bias T. 1=ON, 0=OFF. */ | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_SEND_I2C_BYTE    200 | ||||||
|  | #define FCD_CMD_APP_RECV_I2C_BYTE    201 | ||||||
|  | 
 | ||||||
|  | #define FCD_CMD_APP_RESET            255 // Reset to bootloader
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | typedef enum  | ||||||
|  | { | ||||||
|  | 	TLGE_N5_0DB=0, | ||||||
|  | 	TLGE_N2_5DB=1, | ||||||
|  | 	TLGE_P0_0DB=4, | ||||||
|  | 	TLGE_P2_5DB=5, | ||||||
|  | 	TLGE_P5_0DB=6, | ||||||
|  | 	TLGE_P7_5DB=7, | ||||||
|  | 	TLGE_P10_0DB=8, | ||||||
|  | 	TLGE_P12_5DB=9, | ||||||
|  | 	TLGE_P15_0DB=10, | ||||||
|  | 	TLGE_P17_5DB=11, | ||||||
|  | 	TLGE_P20_0DB=12, | ||||||
|  | 	TLGE_P25_0DB=13, | ||||||
|  | 	TLGE_P30_0DB=14 | ||||||
|  | } TUNER_LNA_GAIN_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TLEE_OFF=0, | ||||||
|  |   TLEE_0=1, | ||||||
|  |   TLEE_1=3, | ||||||
|  |   TLEE_2=5, | ||||||
|  |   TLEE_3=7 | ||||||
|  | } TUNER_LNA_ENHANCE_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TBE_VHF2, | ||||||
|  |   TBE_VHF3, | ||||||
|  |   TBE_UHF, | ||||||
|  |   TBE_LBAND | ||||||
|  | } TUNER_BAND_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   // Band 0, VHF II
 | ||||||
|  |   TRFE_LPF268MHZ=0, | ||||||
|  |   TRFE_LPF299MHZ=8, | ||||||
|  |   // Band 1, VHF III
 | ||||||
|  |   TRFE_LPF509MHZ=0, | ||||||
|  |   TRFE_LPF656MHZ=8, | ||||||
|  |   // Band 2, UHF
 | ||||||
|  |   TRFE_BPF360MHZ=0, | ||||||
|  |   TRFE_BPF380MHZ=1, | ||||||
|  |   TRFE_BPF405MHZ=2, | ||||||
|  |   TRFE_BPF425MHZ=3, | ||||||
|  |   TRFE_BPF450MHZ=4, | ||||||
|  |   TRFE_BPF475MHZ=5, | ||||||
|  |   TRFE_BPF505MHZ=6, | ||||||
|  |   TRFE_BPF540MHZ=7, | ||||||
|  |   TRFE_BPF575MHZ=8, | ||||||
|  |   TRFE_BPF615MHZ=9, | ||||||
|  |   TRFE_BPF670MHZ=10, | ||||||
|  |   TRFE_BPF720MHZ=11, | ||||||
|  |   TRFE_BPF760MHZ=12, | ||||||
|  |   TRFE_BPF840MHZ=13, | ||||||
|  |   TRFE_BPF890MHZ=14, | ||||||
|  |   TRFE_BPF970MHZ=15, | ||||||
|  |   // Band 2, L band
 | ||||||
|  |   TRFE_BPF1300MHZ=0, | ||||||
|  |   TRFE_BPF1320MHZ=1, | ||||||
|  |   TRFE_BPF1360MHZ=2, | ||||||
|  |   TRFE_BPF1410MHZ=3, | ||||||
|  |   TRFE_BPF1445MHZ=4, | ||||||
|  |   TRFE_BPF1460MHZ=5, | ||||||
|  |   TRFE_BPF1490MHZ=6, | ||||||
|  |   TRFE_BPF1530MHZ=7, | ||||||
|  |   TRFE_BPF1560MHZ=8, | ||||||
|  |   TRFE_BPF1590MHZ=9, | ||||||
|  |   TRFE_BPF1640MHZ=10, | ||||||
|  |   TRFE_BPF1660MHZ=11, | ||||||
|  |   TRFE_BPF1680MHZ=12, | ||||||
|  |   TRFE_BPF1700MHZ=13, | ||||||
|  |   TRFE_BPF1720MHZ=14, | ||||||
|  |   TRFE_BPF1750MHZ=15 | ||||||
|  | } TUNER_RF_FILTER_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TMGE_P4_0DB=0, | ||||||
|  |   TMGE_P12_0DB=1 | ||||||
|  | } TUNER_MIXER_GAIN_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TBCE_LBAND=0, | ||||||
|  |   TBCE_1=1, | ||||||
|  |   TBCE_2=2, | ||||||
|  |   TBCE_VUBAND=3 | ||||||
|  | } TUNER_BIAS_CURRENT_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TMFE_27_0MHZ=0, | ||||||
|  |   TMFE_4_6MHZ=8, | ||||||
|  |   TMFE_4_2MHZ=9, | ||||||
|  |   TMFE_3_8MHZ=10, | ||||||
|  |   TMFE_3_4MHZ=11, | ||||||
|  |   TMFE_3_0MHZ=12, | ||||||
|  |   TMFE_2_7MHZ=13, | ||||||
|  |   TMFE_2_3MHZ=14, | ||||||
|  |   TMFE_1_9MHZ=15 | ||||||
|  | } TUNER_MIXER_FILTER_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG1E_N3_0DB=0, | ||||||
|  |   TIG1E_P6_0DB=1 | ||||||
|  | } TUNER_IF_GAIN1_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIGME_LINEARITY=0, | ||||||
|  |   TIGME_SENSITIVITY=1 | ||||||
|  | } TUNER_IF_GAIN_MODE_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIRFE_21_4MHZ=0, | ||||||
|  |   TIRFE_21_0MHZ=1, | ||||||
|  |   TIRFE_17_6MHZ=2, | ||||||
|  |   TIRFE_14_7MHZ=3, | ||||||
|  |   TIRFE_12_4MHZ=4, | ||||||
|  |   TIRFE_10_6MHZ=5, | ||||||
|  |   TIRFE_9_0MHZ=6, | ||||||
|  |   TIRFE_7_7MHZ=7, | ||||||
|  |   TIRFE_6_4MHZ=8, | ||||||
|  |   TIRFE_5_3MHZ=9, | ||||||
|  |   TIRFE_4_4MHZ=10, | ||||||
|  |   TIRFE_3_4MHZ=11, | ||||||
|  |   TIRFE_2_6MHZ=12, | ||||||
|  |   TIRFE_1_8MHZ=13, | ||||||
|  |   TIRFE_1_2MHZ=14, | ||||||
|  |   TIRFE_1_0MHZ=15 | ||||||
|  | } TUNER_IF_RC_FILTER_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG2E_P0_0DB=0, | ||||||
|  |   TIG2E_P3_0DB=1, | ||||||
|  |   TIG2E_P6_0DB=2, | ||||||
|  |   TIG2E_P9_0DB=3 | ||||||
|  | } TUNER_IF_GAIN2_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG3E_P0_0DB=0, | ||||||
|  |   TIG3E_P3_0DB=1, | ||||||
|  |   TIG3E_P6_0DB=2, | ||||||
|  |   TIG3E_P9_0DB=3 | ||||||
|  | } TUNER_IF_GAIN3_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG4E_P0_0DB=0, | ||||||
|  |   TIG4E_P1_0DB=1, | ||||||
|  |   TIG4E_P2_0DB=2 | ||||||
|  | } TUNER_IF_GAIN4_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIFE_5_50MHZ=0, | ||||||
|  |   TIFE_5_30MHZ=1, | ||||||
|  |   TIFE_5_00MHZ=2, | ||||||
|  |   TIFE_4_80MHZ=3, | ||||||
|  |   TIFE_4_60MHZ=4, | ||||||
|  |   TIFE_4_40MHZ=5, | ||||||
|  |   TIFE_4_30MHZ=6, | ||||||
|  |   TIFE_4_10MHZ=7, | ||||||
|  |   TIFE_3_90MHZ=8, | ||||||
|  |   TIFE_3_80MHZ=9, | ||||||
|  |   TIFE_3_70MHZ=10, | ||||||
|  |   TIFE_3_60MHZ=11, | ||||||
|  |   TIFE_3_40MHZ=12, | ||||||
|  |   TIFE_3_30MHZ=13, | ||||||
|  |   TIFE_3_20MHZ=14, | ||||||
|  |   TIFE_3_10MHZ=15, | ||||||
|  |   TIFE_3_00MHZ=16, | ||||||
|  |   TIFE_2_95MHZ=17, | ||||||
|  |   TIFE_2_90MHZ=18, | ||||||
|  |   TIFE_2_80MHZ=19, | ||||||
|  |   TIFE_2_75MHZ=20, | ||||||
|  |   TIFE_2_70MHZ=21, | ||||||
|  |   TIFE_2_60MHZ=22, | ||||||
|  |   TIFE_2_55MHZ=23, | ||||||
|  |   TIFE_2_50MHZ=24, | ||||||
|  |   TIFE_2_45MHZ=25, | ||||||
|  |   TIFE_2_40MHZ=26, | ||||||
|  |   TIFE_2_30MHZ=27, | ||||||
|  |   TIFE_2_28MHZ=28, | ||||||
|  |   TIFE_2_24MHZ=29, | ||||||
|  |   TIFE_2_20MHZ=30, | ||||||
|  |   TIFE_2_15MHZ=31 | ||||||
|  | } TUNER_IF_FILTER_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG5E_P3_0DB=0, | ||||||
|  |   TIG5E_P6_0DB=1, | ||||||
|  |   TIG5E_P9_0DB=2, | ||||||
|  |   TIG5E_P12_0DB=3, | ||||||
|  |   TIG5E_P15_0DB=4 | ||||||
|  | } TUNER_IF_GAIN5_ENUM; | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   TIG6E_P3_0DB=0, | ||||||
|  |   TIG6E_P6_0DB=1, | ||||||
|  |   TIG6E_P9_0DB=2, | ||||||
|  |   TIG6E_P12_0DB=3, | ||||||
|  |   TIG6E_P15_0DB=4 | ||||||
|  | } TUNER_IF_GAIN6_ENUM; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #endif // FCDHIDCMD_H
 | ||||||
							
								
								
									
										1427
									
								
								fcdhid/hid-libusb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1427
									
								
								fcdhid/hid-libusb.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1432
									
								
								fcdhid/hid-libusb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1432
									
								
								fcdhid/hid-libusb.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										387
									
								
								fcdhid/hidapi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								fcdhid/hidapi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,387 @@ | |||||||
|  | /*******************************************************
 | ||||||
|  |  HIDAPI - Multi-Platform library for | ||||||
|  |  communication with HID devices. | ||||||
|  | 
 | ||||||
|  |  Alan Ott | ||||||
|  |  Signal 11 Software | ||||||
|  | 
 | ||||||
|  |  8/22/2009 | ||||||
|  | 
 | ||||||
|  |  Copyright 2009, All Rights Reserved. | ||||||
|  | 
 | ||||||
|  |  At the discretion of the user of this library, | ||||||
|  |  this software may be licensed under the terms of the | ||||||
|  |  GNU General Public License v3, a BSD-Style license, or the | ||||||
|  |  original HIDAPI license as outlined in the LICENSE.txt, | ||||||
|  |  LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt | ||||||
|  |  files located at the root of the source distribution. | ||||||
|  |  These files may also be found in the public source | ||||||
|  |  code repository located at: | ||||||
|  |         http://github.com/signal11/hidapi .
 | ||||||
|  | ********************************************************/ | ||||||
|  | 
 | ||||||
|  | /** @file
 | ||||||
|  |  * @defgroup API hidapi API | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef HIDAPI_H__ | ||||||
|  | #define HIDAPI_H__ | ||||||
|  | 
 | ||||||
|  | #include <wchar.h> | ||||||
|  | 
 | ||||||
|  | #ifdef _WIN32 | ||||||
|  |       #define HID_API_EXPORT __declspec(dllexport) | ||||||
|  |       #define HID_API_CALL | ||||||
|  | #else | ||||||
|  |       #define HID_API_EXPORT /**< API export macro */ | ||||||
|  |       #define HID_API_CALL /**< API call macro */ | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 		struct hid_device_; | ||||||
|  | 		typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ | ||||||
|  | 
 | ||||||
|  | 		/** hidapi info structure */ | ||||||
|  | 		struct hid_device_info { | ||||||
|  | 			/** Platform-specific device path */ | ||||||
|  | 			char *path; | ||||||
|  | 			/** Device Vendor ID */ | ||||||
|  | 			unsigned short vendor_id; | ||||||
|  | 			/** Device Product ID */ | ||||||
|  | 			unsigned short product_id; | ||||||
|  | 			/** Serial Number */ | ||||||
|  | 			wchar_t *serial_number; | ||||||
|  | 			/** Device Release Number in binary-coded decimal,
 | ||||||
|  | 			    also known as Device Version Number */ | ||||||
|  | 			unsigned short release_number; | ||||||
|  | 			/** Manufacturer String */ | ||||||
|  | 			wchar_t *manufacturer_string; | ||||||
|  | 			/** Product string */ | ||||||
|  | 			wchar_t *product_string; | ||||||
|  | 			/** Usage Page for this Device/Interface
 | ||||||
|  | 			    (Windows/Mac only). */ | ||||||
|  | 			unsigned short usage_page; | ||||||
|  | 			/** Usage for this Device/Interface
 | ||||||
|  | 			    (Windows/Mac only).*/ | ||||||
|  | 			unsigned short usage; | ||||||
|  | 			/** The USB interface which this logical device
 | ||||||
|  | 			    represents. Valid on both Linux implementations | ||||||
|  | 			    in all cases, and valid on the Windows implementation | ||||||
|  | 			    only if the device contains more than one interface. */ | ||||||
|  | 			int interface_number; | ||||||
|  | 
 | ||||||
|  | 			/** Pointer to the next device */ | ||||||
|  | 			struct hid_device_info *next; | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		/** @brief Initialize the HIDAPI library.
 | ||||||
|  | 
 | ||||||
|  | 			This function initializes the HIDAPI library. Calling it is not | ||||||
|  | 			strictly necessary, as it will be called automatically by | ||||||
|  | 			hid_enumerate() and any of the hid_open_*() functions if it is | ||||||
|  | 			needed.  This function should be called at the beginning of | ||||||
|  | 			execution however, if there is a chance of HIDAPI handles | ||||||
|  | 			being opened by different threads simultaneously. | ||||||
|  | 			 | ||||||
|  | 			@ingroup API | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT HID_API_CALL hid_init(void); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Finalize the HIDAPI library.
 | ||||||
|  | 
 | ||||||
|  | 			This function frees all of the static data associated with | ||||||
|  | 			HIDAPI. It should be called at the end of execution to avoid | ||||||
|  | 			memory leaks. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 
 | ||||||
|  | 		    @returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT HID_API_CALL hid_exit(void); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Enumerate the HID Devices.
 | ||||||
|  | 
 | ||||||
|  | 			This function returns a linked list of all the HID devices | ||||||
|  | 			attached to the system which match vendor_id and product_id. | ||||||
|  | 			If @p vendor_id is set to 0 then any vendor matches. | ||||||
|  | 			If @p product_id is set to 0 then any product matches. | ||||||
|  | 			If @p vendor_id and @p product_id are both set to 0, then | ||||||
|  | 			all HID devices will be returned. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param vendor_id The Vendor ID (VID) of the types of device | ||||||
|  | 				to open. | ||||||
|  | 			@param product_id The Product ID (PID) of the types of | ||||||
|  | 				device to open. | ||||||
|  | 
 | ||||||
|  | 		    @returns | ||||||
|  | 		    	This function returns a pointer to a linked list of type | ||||||
|  | 		    	struct #hid_device, containing information about the HID devices | ||||||
|  | 		    	attached to the system, or NULL in the case of failure. Free | ||||||
|  | 		    	this linked list by calling hid_free_enumeration(). | ||||||
|  | 		*/ | ||||||
|  | 		struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Free an enumeration Linked List
 | ||||||
|  | 
 | ||||||
|  | 		    This function frees a linked list created by hid_enumerate(). | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 		    @param devs Pointer to a list of struct_device returned from | ||||||
|  | 		    	      hid_enumerate(). | ||||||
|  | 		*/ | ||||||
|  | 		void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Open a HID device using a Vendor ID (VID), Product ID
 | ||||||
|  | 			(PID) and optionally a serial number. | ||||||
|  | 
 | ||||||
|  | 			If @p serial_number is NULL, the first device with the | ||||||
|  | 			specified VID and PID is opened. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param vendor_id The Vendor ID (VID) of the device to open. | ||||||
|  | 			@param product_id The Product ID (PID) of the device to open. | ||||||
|  | 			@param serial_number The Serial Number of the device to open | ||||||
|  | 				               (Optionally NULL). | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns a pointer to a #hid_device object on | ||||||
|  | 				success or NULL on failure. | ||||||
|  | 		*/ | ||||||
|  | 		HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Open a HID device by its path name.
 | ||||||
|  | 
 | ||||||
|  | 			The path name be determined by calling hid_enumerate(), or a | ||||||
|  | 			platform-specific path name can be used (eg: /dev/hidraw0 on | ||||||
|  | 			Linux). | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 		    @param path The path name of the device to open | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns a pointer to a #hid_device object on | ||||||
|  | 				success or NULL on failure. | ||||||
|  | 		*/ | ||||||
|  | 		HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Write an Output report to a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			The first byte of @p data[] must contain the Report ID. For | ||||||
|  | 			devices which only support a single report, this must be set | ||||||
|  | 			to 0x0. The remaining bytes contain the report data. Since | ||||||
|  | 			the Report ID is mandatory, calls to hid_write() will always | ||||||
|  | 			contain one more byte than the report contains. For example, | ||||||
|  | 			if a hid report is 16 bytes long, 17 bytes must be passed to | ||||||
|  | 			hid_write(), the Report ID (or 0x0, for devices with a | ||||||
|  | 			single report), followed by the report data (16 bytes). In | ||||||
|  | 			this example, the length passed in would be 17. | ||||||
|  | 
 | ||||||
|  | 			hid_write() will send the data on the first OUT endpoint, if | ||||||
|  | 			one exists. If it does not, it will send the data through | ||||||
|  | 			the Control Endpoint (Endpoint 0). | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param data The data to send, including the report number as | ||||||
|  | 				the first byte. | ||||||
|  | 			@param length The length in bytes of the data to send. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns the actual number of bytes written and | ||||||
|  | 				-1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Read an Input report from a HID device with timeout.
 | ||||||
|  | 
 | ||||||
|  | 			Input reports are returned | ||||||
|  | 			to the host through the INTERRUPT IN endpoint. The first byte will | ||||||
|  | 			contain the Report number if the device uses numbered reports. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param data A buffer to put the read data into. | ||||||
|  | 			@param length The number of bytes to read. For devices with | ||||||
|  | 				multiple reports, make sure to read an extra byte for | ||||||
|  | 				the report number. | ||||||
|  | 			@param milliseconds timeout in milliseconds or -1 for blocking wait. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns the actual number of bytes read and | ||||||
|  | 				-1 on error. If no packet was available to be read within | ||||||
|  | 				the timeout period, this function returns 0. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Read an Input report from a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			Input reports are returned | ||||||
|  | 		    to the host through the INTERRUPT IN endpoint. The first byte will | ||||||
|  | 			contain the Report number if the device uses numbered reports. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param data A buffer to put the read data into. | ||||||
|  | 			@param length The number of bytes to read. For devices with | ||||||
|  | 				multiple reports, make sure to read an extra byte for | ||||||
|  | 				the report number. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns the actual number of bytes read and | ||||||
|  | 				-1 on error. If no packet was available to be read and | ||||||
|  | 				the handle is in non-blocking mode, this function returns 0. | ||||||
|  | 		*/ | ||||||
|  | 		int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Set the device handle to be non-blocking.
 | ||||||
|  | 
 | ||||||
|  | 			In non-blocking mode calls to hid_read() will return | ||||||
|  | 			immediately with a value of 0 if there is no data to be | ||||||
|  | 			read. In blocking mode, hid_read() will wait (block) until | ||||||
|  | 			there is data to read before returning. | ||||||
|  | 
 | ||||||
|  | 			Nonblocking can be turned on and off at any time. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param nonblock enable or not the nonblocking reads | ||||||
|  | 			 - 1 to enable nonblocking | ||||||
|  | 			 - 0 to disable nonblocking. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Send a Feature report to the device.
 | ||||||
|  | 
 | ||||||
|  | 			Feature reports are sent over the Control endpoint as a | ||||||
|  | 			Set_Report transfer.  The first byte of @p data[] must | ||||||
|  | 			contain the Report ID. For devices which only support a | ||||||
|  | 			single report, this must be set to 0x0. The remaining bytes | ||||||
|  | 			contain the report data. Since the Report ID is mandatory, | ||||||
|  | 			calls to hid_send_feature_report() will always contain one | ||||||
|  | 			more byte than the report contains. For example, if a hid | ||||||
|  | 			report is 16 bytes long, 17 bytes must be passed to | ||||||
|  | 			hid_send_feature_report(): the Report ID (or 0x0, for | ||||||
|  | 			devices which do not use numbered reports), followed by the | ||||||
|  | 			report data (16 bytes). In this example, the length passed | ||||||
|  | 			in would be 17. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param data The data to send, including the report number as | ||||||
|  | 				the first byte. | ||||||
|  | 			@param length The length in bytes of the data to send, including | ||||||
|  | 				the report number. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns the actual number of bytes written and | ||||||
|  | 				-1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get a feature report from a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			Make sure to set the first byte of @p data[] to the Report | ||||||
|  | 			ID of the report to be read.  Make sure to allow space for | ||||||
|  | 			this extra byte in @p data[]. | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param data A buffer to put the read data into, including | ||||||
|  | 				the Report ID. Set the first byte of @p data[] to the | ||||||
|  | 				Report ID of the report to be read. | ||||||
|  | 			@param length The number of bytes to read, including an | ||||||
|  | 				extra byte for the report ID. The buffer can be longer | ||||||
|  | 				than the actual report. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns the number of bytes read and | ||||||
|  | 				-1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Close a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 		*/ | ||||||
|  | 		void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get The Manufacturer String from a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param string A wide string buffer to put the data into. | ||||||
|  | 			@param maxlen The length of the buffer in multiples of wchar_t. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get The Product String from a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param string A wide string buffer to put the data into. | ||||||
|  | 			@param maxlen The length of the buffer in multiples of wchar_t. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get The Serial Number String from a HID device.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param string A wide string buffer to put the data into. | ||||||
|  | 			@param maxlen The length of the buffer in multiples of wchar_t. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get a string from a HID device, based on its string index.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 			@param string_index The index of the string to get. | ||||||
|  | 			@param string A wide string buffer to put the data into. | ||||||
|  | 			@param maxlen The length of the buffer in multiples of wchar_t. | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns 0 on success and -1 on error. | ||||||
|  | 		*/ | ||||||
|  | 		int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); | ||||||
|  | 
 | ||||||
|  | 		/** @brief Get a string describing the last error which occurred.
 | ||||||
|  | 
 | ||||||
|  | 			@ingroup API | ||||||
|  | 			@param device A device handle returned from hid_open(). | ||||||
|  | 
 | ||||||
|  | 			@returns | ||||||
|  | 				This function returns a string containing the last error | ||||||
|  | 				which occurred or NULL if none has occurred. | ||||||
|  | 		*/ | ||||||
|  | 		HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| @ -18,7 +18,7 @@ if(LIBUSB_FOUND AND UNIX) | |||||||
| 	FIND_LIBRARY (LIBASOUND asound) | 	FIND_LIBRARY (LIBASOUND asound) | ||||||
| endif() | endif() | ||||||
| if(LIBASOUND AND ASOUNDH) | if(LIBASOUND AND ASOUNDH) | ||||||
| 	add_subdirectory(fcd) | 	add_subdirectory(fcdpro) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| find_package(LibRTLSDR) | find_package(LibRTLSDR) | ||||||
|  | |||||||
| @ -25,7 +25,7 @@ include_directories( | |||||||
| 	${CMAKE_CURRENT_BINARY_DIR} | 	${CMAKE_CURRENT_BINARY_DIR} | ||||||
| 	${CMAKE_SOURCE_DIR}/include | 	${CMAKE_SOURCE_DIR}/include | ||||||
| 	${CMAKE_SOURCE_DIR}/include-gpl | 	${CMAKE_SOURCE_DIR}/include-gpl | ||||||
| 	${LIBRTLSDR_INCLUDE_DIR} | 	${LIBBLADERF_INCLUDE_DIR} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| #include(${QT_USE_FILE}) | #include(${QT_USE_FILE}) | ||||||
|  | |||||||
| @ -171,7 +171,7 @@ const QString& FCDInput::getDeviceDescription() const | |||||||
| 
 | 
 | ||||||
| int FCDInput::getSampleRate() const | int FCDInput::getSampleRate() const | ||||||
| { | { | ||||||
| 	return 96000; | 	return 192000; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| quint64 FCDInput::getCenterFrequency() const | quint64 FCDInput::getCenterFrequency() const | ||||||
| @ -220,7 +220,7 @@ void FCDInput::applySettings(const Settings& settings, bool force) | |||||||
|      |      | ||||||
|     if (signalChange) |     if (signalChange) | ||||||
|     { |     { | ||||||
| 		DSPSignalNotification *notif = new DSPSignalNotification(96000, m_settings.centerFrequency); | 		DSPSignalNotification *notif = new DSPSignalNotification(192000, m_settings.centerFrequency); | ||||||
| 		getOutputMessageQueue()->push(notif);         | 		getOutputMessageQueue()->push(notif);         | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ void FCDThread::stopWork() | |||||||
| 
 | 
 | ||||||
| void FCDThread::run() | void FCDThread::run() | ||||||
| { | { | ||||||
| 	if ( !OpenSource("hw:CARD=V10") ) // FIXME: original is V10 pro is V20. Make it an option
 | 	if ( !OpenSource("hw:CARD=V20") ) // FIXME: pro is V10 pro+ is V20. Make it an option
 | ||||||
|                 return; |                 return; | ||||||
| 	// TODO: fallback to original fcd
 | 	// TODO: fallback to original fcd
 | ||||||
| 
 | 
 | ||||||
| @ -70,6 +70,7 @@ bool FCDThread::OpenSource(const char* cardname) | |||||||
| 
 | 
 | ||||||
| 	if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) | 	if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: cannot open %s", cardname); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -77,10 +78,12 @@ bool FCDThread::OpenSource(const char* cardname) | |||||||
| 
 | 
 | ||||||
| 	if (snd_pcm_hw_params_any(fcd_handle, params) < 0) | 	if (snd_pcm_hw_params_any(fcd_handle, params) < 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: snd_pcm_hw_params_any failed"); | ||||||
| 		fail = true; | 		fail = true; | ||||||
| 	} | 	} | ||||||
| 	else if (snd_pcm_hw_params(fcd_handle, params) < 0) | 	else if (snd_pcm_hw_params(fcd_handle, params) < 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: snd_pcm_hw_params failed"); | ||||||
| 		fail = true; | 		fail = true; | ||||||
| 		// TODO: check actual samplerate, may be crippled firmware
 | 		// TODO: check actual samplerate, may be crippled firmware
 | ||||||
| 	} | 	} | ||||||
| @ -88,6 +91,7 @@ bool FCDThread::OpenSource(const char* cardname) | |||||||
| 	{ | 	{ | ||||||
| 		if (snd_pcm_start(fcd_handle) < 0) | 		if (snd_pcm_start(fcd_handle) < 0) | ||||||
| 		{ | 		{ | ||||||
|  | 			qCritical("FCDThread::OpenSource: snd_pcm_start failed"); | ||||||
| 			fail = true; | 			fail = true; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ | |||||||
| typedef bool BOOL; | typedef bool BOOL; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| //#define FCDPP // FIXME: the Pro / Pro+ switch should be handled better than this!
 | #define FCDPP // FIXME: the Pro / Pro+ switch should be handled better than this!
 | ||||||
| const unsigned short _usVID=0x04D8;  /*!< USB vendor ID. */ | const unsigned short _usVID=0x04D8;  /*!< USB vendor ID. */ | ||||||
| #ifdef FCDPP | #ifdef FCDPP | ||||||
| const unsigned short _usPID=0xFB31;  /*!< USB product ID. */ | const unsigned short _usPID=0xFB31;  /*!< USB product ID. */ | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								plugins/samplesource/fcdpro/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								plugins/samplesource/fcdpro/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | project(fcdpro) | ||||||
|  | 
 | ||||||
|  | set(fcdpro_SOURCES | ||||||
|  | 	fcdgui.cpp | ||||||
|  | 	fcdinput.cpp | ||||||
|  | 	fcdplugin.cpp | ||||||
|  | 	fcdserializer.cpp | ||||||
|  | 	fcdthread.cpp | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(fcdpro_HEADERS | ||||||
|  | 	fcdgui.h | ||||||
|  | 	fcdinput.h | ||||||
|  | 	fcdplugin.h | ||||||
|  | 	fcdserializer.h | ||||||
|  | 	fcdthread.h | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(fcdpro_FORMS | ||||||
|  | 	fcdgui.ui | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | include_directories( | ||||||
|  | 	. | ||||||
|  | 	${CMAKE_CURRENT_BINARY_DIR} | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include | ||||||
|  | 	${CMAKE_SOURCE_DIR}/include-gpl | ||||||
|  | 	${CMAKE_SOURCE_DIR}/fcdhid | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | #include(${QT_USE_FILE}) | ||||||
|  | add_definitions(${QT_DEFINITIONS}) | ||||||
|  | add_definitions(-DQT_PLUGIN) | ||||||
|  | add_definitions(-DQT_SHARED) | ||||||
|  | 
 | ||||||
|  | #qt4_wrap_cpp(fcdpro_HEADERS_MOC ${fcdpro_HEADERS}) | ||||||
|  | qt5_wrap_ui(fcdpro_FORMS_HEADERS ${fcdpro_FORMS}) | ||||||
|  | 
 | ||||||
|  | add_library(inputfcdpro SHARED | ||||||
|  | 	${fcdpro_SOURCES} | ||||||
|  | 	${fcdpro_HEADERS_MOC} | ||||||
|  | 	${fcdpro_FORMS_HEADERS} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | target_link_libraries(inputfcdpro | ||||||
|  | 	${QT_LIBRARIES} | ||||||
|  | 	${LIBUSB_LIBRARIES} | ||||||
|  | 	asound | ||||||
|  | 	fcdhid | ||||||
|  | 	sdrbase | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | qt5_use_modules(inputfcdpro Core Widgets OpenGL Multimedia) | ||||||
							
								
								
									
										149
									
								
								plugins/samplesource/fcdpro/fcdgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								plugins/samplesource/fcdpro/fcdgui.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | |||||||
|  | #include "fcdgui.h" | ||||||
|  | #include "ui_fcdgui.h" | ||||||
|  | #include "plugin/pluginapi.h" | ||||||
|  | #include "gui/colormapper.h" | ||||||
|  | #include "dsp/dspengine.h" | ||||||
|  | 
 | ||||||
|  | FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) : | ||||||
|  | 	QWidget(parent), | ||||||
|  | 	ui(new Ui::FCDGui), | ||||||
|  | 	m_pluginAPI(pluginAPI), | ||||||
|  | 	m_settings(), | ||||||
|  | 	m_sampleSource(NULL) | ||||||
|  | { | ||||||
|  | 	ui->setupUi(this); | ||||||
|  | 	ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); | ||||||
|  | 	ui->centerFrequency->setValueRange(7, 64000U, 1700000U); | ||||||
|  | 	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); | ||||||
|  | 	displaySettings(); | ||||||
|  | 
 | ||||||
|  | 	m_sampleSource = new FCDInput(); | ||||||
|  | 	DSPEngine::instance()->setSource(m_sampleSource); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDGui::~FCDGui() | ||||||
|  | { | ||||||
|  | 	delete ui; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::destroy() | ||||||
|  | { | ||||||
|  | 	delete this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::setName(const QString& name) | ||||||
|  | { | ||||||
|  | 	setObjectName(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QString FCDGui::getName() const | ||||||
|  | { | ||||||
|  | 	return objectName(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::resetToDefaults() | ||||||
|  | { | ||||||
|  | 	m_settings.resetToDefaults(); | ||||||
|  | 	displaySettings(); | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QByteArray FCDGui::serialize() const | ||||||
|  | { | ||||||
|  | 	return m_settings.serialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDGui::deserialize(const QByteArray& data) | ||||||
|  | { | ||||||
|  | 	if(m_settings.deserialize(data)) | ||||||
|  | 	{ | ||||||
|  | 		displaySettings(); | ||||||
|  | 		sendSettings(); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		resetToDefaults(); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDGui::handleMessage(const Message& message) | ||||||
|  | { | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::displaySettings() | ||||||
|  | { | ||||||
|  | 	ui->centerFrequency->setValue(m_settings.centerFrequency / 1000); | ||||||
|  | 	ui->checkBoxR->setChecked(m_settings.range); | ||||||
|  | 	ui->checkBoxG->setChecked(m_settings.gain); | ||||||
|  | 	ui->checkBoxB->setChecked(m_settings.bias); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::sendSettings() | ||||||
|  | { | ||||||
|  | 	if(!m_updateTimer.isActive()) | ||||||
|  | 		m_updateTimer.start(100); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_centerFrequency_changed(quint64 value) | ||||||
|  | { | ||||||
|  | 	m_settings.centerFrequency = value * 1000; | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::updateHardware() | ||||||
|  | { | ||||||
|  | 	FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_settings); | ||||||
|  | 	m_sampleSource->getInputMessageQueue()->push(message); | ||||||
|  | 	m_updateTimer.stop(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_checkBoxR_stateChanged(int state) | ||||||
|  | { | ||||||
|  | 	if (state == Qt::Checked) // FIXME: this is for the Pro+ version only!
 | ||||||
|  | 	{ | ||||||
|  | 		ui->centerFrequency->setValueRange(7, 150U, 240000U); | ||||||
|  | 		ui->centerFrequency->setValue(7000); | ||||||
|  | 		m_settings.centerFrequency = 7000 * 1000; | ||||||
|  | 		m_settings.range = 1; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		ui->centerFrequency->setValueRange(7, 64000U, 1900000U); | ||||||
|  | 		ui->centerFrequency->setValue(435000); | ||||||
|  | 		m_settings.centerFrequency = 435000 * 1000; | ||||||
|  | 		m_settings.range = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_checkBoxG_stateChanged(int state) | ||||||
|  | { | ||||||
|  | 	if (state == Qt::Checked) | ||||||
|  | 	{ | ||||||
|  | 		m_settings.gain = 1; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		m_settings.gain = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDGui::on_checkBoxB_stateChanged(int state) | ||||||
|  | { | ||||||
|  | 	if (state == Qt::Checked) | ||||||
|  | 	{ | ||||||
|  | 		m_settings.bias = 1; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		m_settings.bias = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sendSettings(); | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								plugins/samplesource/fcdpro/fcdgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								plugins/samplesource/fcdpro/fcdgui.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | #ifndef INCLUDE_FCDGUI_H | ||||||
|  | #define INCLUDE_FCDGUI_H | ||||||
|  | 
 | ||||||
|  | #include <QTimer> | ||||||
|  | #include "plugin/plugingui.h" | ||||||
|  | #include "fcdinput.h" | ||||||
|  | 
 | ||||||
|  | class PluginAPI; | ||||||
|  | 
 | ||||||
|  | namespace Ui { | ||||||
|  | 	class FCDGui; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class FCDGui : public QWidget, public PluginGUI { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	explicit FCDGui(PluginAPI* pluginAPI, QWidget* parent = NULL); | ||||||
|  | 	virtual ~FCDGui(); | ||||||
|  | 	void destroy(); | ||||||
|  | 
 | ||||||
|  | 	void setName(const QString& name); | ||||||
|  | 	QString getName() const; | ||||||
|  | 
 | ||||||
|  | 	void resetToDefaults(); | ||||||
|  | 	QByteArray serialize() const; | ||||||
|  | 	bool deserialize(const QByteArray& data); | ||||||
|  | 
 | ||||||
|  | 	virtual bool handleMessage(const Message& message); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	Ui::FCDGui* ui; | ||||||
|  | 
 | ||||||
|  | 	PluginAPI* m_pluginAPI; | ||||||
|  | 	FCDInput::Settings m_settings; | ||||||
|  | 	QTimer m_updateTimer; | ||||||
|  | 	std::vector<int> m_gains; | ||||||
|  | 	SampleSource* m_sampleSource; | ||||||
|  | 
 | ||||||
|  | 	void displaySettings(); | ||||||
|  | 	void sendSettings(); | ||||||
|  | 
 | ||||||
|  | private slots: | ||||||
|  | 	void on_centerFrequency_changed(quint64 value); | ||||||
|  | 	void on_checkBoxR_stateChanged(int state); | ||||||
|  | 	void on_checkBoxG_stateChanged(int state); | ||||||
|  | 	void on_checkBoxB_stateChanged(int state); | ||||||
|  | 	void updateHardware(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCDGUI_H
 | ||||||
							
								
								
									
										144
									
								
								plugins/samplesource/fcdpro/fcdgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								plugins/samplesource/fcdpro/fcdgui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,144 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>FCDGui</class> | ||||||
|  |  <widget class="QWidget" name="FCDGui"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>132</width> | ||||||
|  |     <height>119</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="sizePolicy"> | ||||||
|  |    <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> | ||||||
|  |     <horstretch>0</horstretch> | ||||||
|  |     <verstretch>0</verstretch> | ||||||
|  |    </sizepolicy> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>FunCubeDongle</string> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |    <property name="spacing"> | ||||||
|  |     <number>3</number> | ||||||
|  |    </property> | ||||||
|  |    <property name="leftMargin"> | ||||||
|  |     <number>2</number> | ||||||
|  |    </property> | ||||||
|  |    <property name="topMargin"> | ||||||
|  |     <number>2</number> | ||||||
|  |    </property> | ||||||
|  |    <property name="rightMargin"> | ||||||
|  |     <number>2</number> | ||||||
|  |    </property> | ||||||
|  |    <property name="bottomMargin"> | ||||||
|  |     <number>2</number> | ||||||
|  |    </property> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||||||
|  |      <item> | ||||||
|  |       <spacer name="horizontalSpacer"> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="sizeHint" stdset="0"> | ||||||
|  |         <size> | ||||||
|  |          <width>0</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |       </spacer> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <widget class="ValueDial" name="centerFrequency" native="true"> | ||||||
|  |        <property name="sizePolicy"> | ||||||
|  |         <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||||
|  |          <horstretch>0</horstretch> | ||||||
|  |          <verstretch>0</verstretch> | ||||||
|  |         </sizepolicy> | ||||||
|  |        </property> | ||||||
|  |        <property name="minimumSize"> | ||||||
|  |         <size> | ||||||
|  |          <width>32</width> | ||||||
|  |          <height>16</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |        <property name="font"> | ||||||
|  |         <font> | ||||||
|  |          <family>Monospace</family> | ||||||
|  |          <pointsize>20</pointsize> | ||||||
|  |         </font> | ||||||
|  |        </property> | ||||||
|  |        <property name="focusPolicy"> | ||||||
|  |         <enum>Qt::StrongFocus</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="toolTip"> | ||||||
|  |         <string>Tuner center frequency in kHz</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <spacer name="horizontalSpacer_2"> | ||||||
|  |        <property name="orientation"> | ||||||
|  |         <enum>Qt::Horizontal</enum> | ||||||
|  |        </property> | ||||||
|  |        <property name="sizeHint" stdset="0"> | ||||||
|  |         <size> | ||||||
|  |          <width>0</width> | ||||||
|  |          <height>0</height> | ||||||
|  |         </size> | ||||||
|  |        </property> | ||||||
|  |       </spacer> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="Line" name="line_4"> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QHBoxLayout" name="horizontalLayoutR"> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QCheckBox" name="checkBoxR"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Low Range</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QHBoxLayout" name="horizontalLayoutG"> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QCheckBox" name="checkBoxG"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>LNA Gain</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QCheckBox" name="checkBoxB"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Bias T</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <customwidgets> | ||||||
|  |   <customwidget> | ||||||
|  |    <class>ValueDial</class> | ||||||
|  |    <extends>QWidget</extends> | ||||||
|  |    <header>gui/valuedial.h</header> | ||||||
|  |    <container>1</container> | ||||||
|  |   </customwidget> | ||||||
|  |  </customwidgets> | ||||||
|  |  <resources/> | ||||||
|  |  <connections/> | ||||||
|  | </ui> | ||||||
							
								
								
									
										286
									
								
								plugins/samplesource/fcdpro/fcdinput.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								plugins/samplesource/fcdpro/fcdinput.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | // FIXME: FCD is handled very badly!
 | ||||||
|  | 
 | ||||||
|  | #include <QDebug> | ||||||
|  | #include <string.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "fcdinput.h" | ||||||
|  | #include "fcdthread.h" | ||||||
|  | #include "fcdgui.h" | ||||||
|  | #include "dsp/dspcommands.h" | ||||||
|  | #include "fcdserializer.h" | ||||||
|  | 
 | ||||||
|  | MESSAGE_CLASS_DEFINITION(FCDInput::MsgConfigureFCD, Message) | ||||||
|  | //MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
 | ||||||
|  | 
 | ||||||
|  | const uint16_t FCDInput::m_vendorId  = 0x04D8; | ||||||
|  | 
 | ||||||
|  | const uint16_t FCDInput::m_productId = 0xFB31; | ||||||
|  | const int FCDInput::m_sampleRate = 192000; | ||||||
|  | const std::string FCDInput::m_deviceName("hw:CARD=V20"); | ||||||
|  | 
 | ||||||
|  | //const uint16_t FCDInput::m_productId = 0xFB56;
 | ||||||
|  | //const int FCDInput::m_sampleRate = 96000;
 | ||||||
|  | //const std::string FCDInput::m_deviceName("hw:CARD=V10");
 | ||||||
|  | 
 | ||||||
|  | FCDInput::Settings::Settings() : | ||||||
|  | 	centerFrequency(435000000), | ||||||
|  | 	range(0), | ||||||
|  | 	gain(0), | ||||||
|  | 	bias(0) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::Settings::resetToDefaults() | ||||||
|  | { | ||||||
|  | 	centerFrequency = 435000000; | ||||||
|  | 	range = 0; | ||||||
|  | 	gain = 0; | ||||||
|  | 	bias = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QByteArray FCDInput::Settings::serialize() const | ||||||
|  | { | ||||||
|  | 	FCDSerializer::FCDData data; | ||||||
|  | 
 | ||||||
|  | 	data.m_data.m_lnaGain = gain; | ||||||
|  | 	data.m_data.m_frequency = centerFrequency; | ||||||
|  | 	data.m_range = range; | ||||||
|  | 	data.m_bias = bias; | ||||||
|  | 
 | ||||||
|  | 	QByteArray byteArray; | ||||||
|  | 
 | ||||||
|  | 	FCDSerializer::writeSerializedData(data, byteArray); | ||||||
|  | 
 | ||||||
|  | 	return byteArray; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	SimpleSerializer s(1); | ||||||
|  | 	s.writeU64(1, centerFrequency); | ||||||
|  | 	s.writeS32(2, range); | ||||||
|  | 	s.writeS32(3, gain); | ||||||
|  | 	s.writeS32(4, bias); | ||||||
|  | 	return s.final();*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::Settings::deserialize(const QByteArray& serializedData) | ||||||
|  | { | ||||||
|  | 	FCDSerializer::FCDData data; | ||||||
|  | 
 | ||||||
|  | 	bool valid = FCDSerializer::readSerializedData(serializedData, data); | ||||||
|  | 
 | ||||||
|  | 	gain = data.m_data.m_lnaGain; | ||||||
|  | 	centerFrequency = data.m_data.m_frequency; | ||||||
|  | 	range = data.m_range; | ||||||
|  | 	bias = data.m_bias; | ||||||
|  | 
 | ||||||
|  | 	return valid; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	SimpleDeserializer d(data); | ||||||
|  | 
 | ||||||
|  | 	if (d.isValid() && d.getVersion() == 1) | ||||||
|  | 	{ | ||||||
|  | 		d.readU64(1, ¢erFrequency, 435000000); | ||||||
|  |         d.readS32(2, &range, 0); | ||||||
|  | 		d.readS32(3, &gain, 0); | ||||||
|  | 		d.readS32(4, &bias, 0); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	resetToDefaults(); | ||||||
|  | 	return true;*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDInput::FCDInput() : | ||||||
|  | 	m_dev(0), | ||||||
|  | 	m_settings(), | ||||||
|  | 	m_FCDThread(0), | ||||||
|  | 	m_deviceDescription() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDInput::~FCDInput() | ||||||
|  | { | ||||||
|  | 	stop(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::init(const Message& cmd) | ||||||
|  | { | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::start(int device) | ||||||
|  | { | ||||||
|  | 	qDebug() << "FCDInput::start with device #" << device; | ||||||
|  | 
 | ||||||
|  | 	QMutexLocker mutexLocker(&m_mutex); | ||||||
|  | 
 | ||||||
|  | 	if (m_FCDThread) | ||||||
|  | 	{ | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_dev = fcdOpen(m_vendorId, m_productId, device); | ||||||
|  | 
 | ||||||
|  | 	if (m_dev == 0) | ||||||
|  | 	{ | ||||||
|  | 		qCritical("FCDInput::start: could not open FCD"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Apply settings before streaming to avoid bus contention;
 | ||||||
|  | 	 * there is very little spare bandwidth on a full speed USB device. | ||||||
|  | 	 * Failure is harmless if no device is found */ | ||||||
|  | 
 | ||||||
|  | 	applySettings(m_settings, true); | ||||||
|  | 
 | ||||||
|  | 	if(!m_sampleFifo.setSize(96000*4)) | ||||||
|  | 	{ | ||||||
|  | 		qCritical("Could not allocate SampleFifo"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL) | ||||||
|  | 	{ | ||||||
|  | 		qFatal("out of memory"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_deviceDescription = QString("Funcube Dongle"); | ||||||
|  | 
 | ||||||
|  | 	qDebug("FCDInput::started"); | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::stop() | ||||||
|  | { | ||||||
|  | 	QMutexLocker mutexLocker(&m_mutex); | ||||||
|  | 
 | ||||||
|  | 	if (m_FCDThread) | ||||||
|  | 	{ | ||||||
|  | 		m_FCDThread->stopWork(); | ||||||
|  | 		// wait for thread to quit ?
 | ||||||
|  | 		delete m_FCDThread; | ||||||
|  | 		m_FCDThread = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fcdClose(m_dev); | ||||||
|  | 	m_dev = 0; | ||||||
|  | 
 | ||||||
|  | 	m_deviceDescription.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const QString& FCDInput::getDeviceDescription() const | ||||||
|  | { | ||||||
|  | 	return m_deviceDescription; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int FCDInput::getSampleRate() const | ||||||
|  | { | ||||||
|  | 	return m_sampleRate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | quint64 FCDInput::getCenterFrequency() const | ||||||
|  | { | ||||||
|  | 	return m_settings.centerFrequency; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDInput::handleMessage(const Message& message) | ||||||
|  | { | ||||||
|  | 	if(MsgConfigureFCD::match(message)) | ||||||
|  | 	{ | ||||||
|  | 		qDebug() << "FCDInput::handleMessage: MsgConfigureFCD"; | ||||||
|  | 		MsgConfigureFCD& conf = (MsgConfigureFCD&) message; | ||||||
|  | 		applySettings(conf.getSettings(), false); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::applySettings(const Settings& settings, bool force) | ||||||
|  | { | ||||||
|  | 	bool signalChange = false; | ||||||
|  | 
 | ||||||
|  | 	if ((m_settings.centerFrequency != settings.centerFrequency)) | ||||||
|  | 	{ | ||||||
|  | 		qDebug() << "FCDInput::applySettings: fc: " << settings.centerFrequency; | ||||||
|  | 		m_settings.centerFrequency = settings.centerFrequency; | ||||||
|  | 
 | ||||||
|  | 		if (m_dev != 0) | ||||||
|  | 		{ | ||||||
|  | 			set_center_freq((double) m_settings.centerFrequency); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		signalChange = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((m_settings.gain != settings.gain) || force) | ||||||
|  | 	{ | ||||||
|  | 		m_settings.gain = settings.gain; | ||||||
|  | 
 | ||||||
|  | 		if (m_dev != 0) | ||||||
|  | 		{ | ||||||
|  | 			set_lna_gain(settings.gain > 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((m_settings.bias != settings.bias) || force) | ||||||
|  | 	{ | ||||||
|  | 		m_settings.bias = settings.bias; | ||||||
|  | 
 | ||||||
|  | 		if (m_dev != 0) | ||||||
|  | 		{ | ||||||
|  | 			set_bias_t(settings.bias > 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |      | ||||||
|  |     if (signalChange) | ||||||
|  |     { | ||||||
|  | 		DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_settings.centerFrequency); | ||||||
|  | 		getOutputMessageQueue()->push(notif);         | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::set_center_freq(double freq) | ||||||
|  | { | ||||||
|  | 	if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE) | ||||||
|  | 	{ | ||||||
|  | 		qDebug("No FCD HID found for frquency change"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::set_bias_t(bool on) | ||||||
|  | { | ||||||
|  | 	quint8 cmd = on ? 1 : 0; | ||||||
|  | 
 | ||||||
|  | 	fcdAppSetParam(m_dev, FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDInput::set_lna_gain(bool on) | ||||||
|  | { | ||||||
|  | 	quint8 cmd = on ? 1 : 0; | ||||||
|  | 
 | ||||||
|  | 	fcdAppSetParam(m_dev, FCD_CMD_APP_SET_LNA_GAIN, &cmd, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										98
									
								
								plugins/samplesource/fcdpro/fcdinput.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								plugins/samplesource/fcdpro/fcdinput.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #ifndef INCLUDE_FCDINPUT_H | ||||||
|  | #define INCLUDE_FCDINPUT_H | ||||||
|  | 
 | ||||||
|  | #include "dsp/samplesource.h" | ||||||
|  | #include "fcdhid.h" | ||||||
|  | #include <QString> | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | struct fcd_buffer { | ||||||
|  | 	void *start; | ||||||
|  | 	std::size_t length; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class FCDThread; | ||||||
|  | 
 | ||||||
|  | class FCDInput : public SampleSource { | ||||||
|  | public: | ||||||
|  | 	struct Settings { | ||||||
|  | 		Settings(); | ||||||
|  | 		quint64 centerFrequency; | ||||||
|  | 		qint32 range; | ||||||
|  | 		qint32 gain; | ||||||
|  | 		qint32 bias; | ||||||
|  | 		void resetToDefaults(); | ||||||
|  | 		QByteArray serialize() const; | ||||||
|  | 		bool deserialize(const QByteArray& data); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	class MsgConfigureFCD : public Message { | ||||||
|  | 		MESSAGE_CLASS_DECLARATION | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		const Settings& getSettings() const { return m_settings; } | ||||||
|  | 
 | ||||||
|  | 		static MsgConfigureFCD* create(const Settings& settings) | ||||||
|  | 		{ | ||||||
|  | 			return new MsgConfigureFCD(settings); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	private: | ||||||
|  | 		Settings m_settings; | ||||||
|  | 
 | ||||||
|  | 		MsgConfigureFCD(const Settings& settings) : | ||||||
|  | 			Message(), | ||||||
|  | 			m_settings(settings) | ||||||
|  | 		{ } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	FCDInput(); | ||||||
|  | 	virtual ~FCDInput(); | ||||||
|  | 
 | ||||||
|  | 	virtual bool init(const Message& cmd); | ||||||
|  | 	virtual bool start(int device); | ||||||
|  | 	virtual void stop(); | ||||||
|  | 
 | ||||||
|  | 	virtual const QString& getDeviceDescription() const; | ||||||
|  | 	virtual int getSampleRate() const; | ||||||
|  | 	virtual quint64 getCenterFrequency() const; | ||||||
|  | 
 | ||||||
|  | 	virtual bool handleMessage(const Message& message); | ||||||
|  | 
 | ||||||
|  | 	void set_center_freq(double freq); | ||||||
|  | 	void set_bias_t(bool on); | ||||||
|  | 	void set_lna_gain(bool on); | ||||||
|  | 
 | ||||||
|  | 	static const uint16_t m_vendorId;  //!< USB vendor ID.
 | ||||||
|  | 	static const uint16_t m_productId; //!< USB product ID.
 | ||||||
|  | 	static const int m_sampleRate; | ||||||
|  | 	static const std::string m_deviceName; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	void applySettings(const Settings& settings, bool force); | ||||||
|  | 
 | ||||||
|  | 	hid_device *m_dev; | ||||||
|  | 	QMutex m_mutex; | ||||||
|  | 	Settings m_settings; | ||||||
|  | 	FCDThread* m_FCDThread; | ||||||
|  | 	QString m_deviceDescription; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCD_H
 | ||||||
							
								
								
									
										71
									
								
								plugins/samplesource/fcdpro/fcdplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								plugins/samplesource/fcdpro/fcdplugin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2015 Edouard Griffiths, F4EXB                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #include <QtPlugin> | ||||||
|  | #include <QAction> | ||||||
|  | #include "plugin/pluginapi.h" | ||||||
|  | #include "util/simpleserializer.h" | ||||||
|  | #include "fcdplugin.h" | ||||||
|  | #include "fcdgui.h" | ||||||
|  | 
 | ||||||
|  | const PluginDescriptor FCDPlugin::m_pluginDescriptor = { | ||||||
|  | 	QString("FunCube Pro Input"), | ||||||
|  | 	QString("---"), | ||||||
|  | 	QString("(c) Edouard Griffiths, F4EXB"), | ||||||
|  | 	QString("https://github.com/f4exb/sdrangel"), | ||||||
|  | 	true, | ||||||
|  | 	QString("https://github.com/f4exb/sdrangel") | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | FCDPlugin::FCDPlugin(QObject* parent) : | ||||||
|  | 	QObject(parent) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const PluginDescriptor& FCDPlugin::getPluginDescriptor() const | ||||||
|  | { | ||||||
|  | 	return m_pluginDescriptor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDPlugin::initPlugin(PluginAPI* pluginAPI) | ||||||
|  | { | ||||||
|  | 	m_pluginAPI = pluginAPI; | ||||||
|  | 
 | ||||||
|  | 	m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcdpro", this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PluginInterface::SampleSourceDevices FCDPlugin::enumSampleSources() | ||||||
|  | { | ||||||
|  | 	SampleSourceDevices result; | ||||||
|  | 
 | ||||||
|  | 	QString displayedName(QString("Funcube Dongle Pro #1")); | ||||||
|  | 	SimpleSerializer s(1); | ||||||
|  | 	s.writeS32(1, 0); | ||||||
|  | 	result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.fcdpro", s.final())); | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PluginGUI* FCDPlugin::createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address) | ||||||
|  | { | ||||||
|  | 	if(sourceName == "org.osmocom.sdr.samplesource.fcdpro") { | ||||||
|  | 		FCDGui* gui = new FCDGui(m_pluginAPI); | ||||||
|  | 		m_pluginAPI->setInputGUI(gui); | ||||||
|  | 		return gui; | ||||||
|  | 	} else { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								plugins/samplesource/fcdpro/fcdplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								plugins/samplesource/fcdpro/fcdplugin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | #ifndef INCLUDE_FCDPLUGIN_H | ||||||
|  | #define INCLUDE_FCDPLUGIN_H | ||||||
|  | 
 | ||||||
|  | #include <QObject> | ||||||
|  | #include "plugin/plugininterface.h" | ||||||
|  | 
 | ||||||
|  | class FCDPlugin : public QObject, public PluginInterface { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 	Q_INTERFACES(PluginInterface) | ||||||
|  | 	Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcdpro") | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	explicit FCDPlugin(QObject* parent = NULL); | ||||||
|  | 
 | ||||||
|  | 	const PluginDescriptor& getPluginDescriptor() const; | ||||||
|  | 	void initPlugin(PluginAPI* pluginAPI); | ||||||
|  | 
 | ||||||
|  | 	SampleSourceDevices enumSampleSources(); | ||||||
|  | 	PluginGUI* createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	static const PluginDescriptor m_pluginDescriptor; | ||||||
|  | 
 | ||||||
|  | 	PluginAPI* m_pluginAPI; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // INCLUDE_FCDPLUGIN_H
 | ||||||
							
								
								
									
										68
									
								
								plugins/samplesource/fcdpro/fcdserializer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								plugins/samplesource/fcdpro/fcdserializer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2015 Edouard Griffiths, F4EXB                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #include "fcdserializer.h" | ||||||
|  | 
 | ||||||
|  | void FCDSerializer::writeSerializedData(const FCDData& data, QByteArray& serializedData) | ||||||
|  | { | ||||||
|  | 	QByteArray sampleSourceSerialized; | ||||||
|  | 	SampleSourceSerializer::writeSerializedData(data.m_data, sampleSourceSerialized); | ||||||
|  | 
 | ||||||
|  | 	SimpleSerializer s(1); | ||||||
|  | 
 | ||||||
|  | 	s.writeBlob(1, sampleSourceSerialized); | ||||||
|  | 	s.writeS32(2, data.m_bias); | ||||||
|  | 	s.writeS32(3, data.m_range); | ||||||
|  | 
 | ||||||
|  | 	serializedData = s.final(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDSerializer::readSerializedData(const QByteArray& serializedData, FCDData& data) | ||||||
|  | { | ||||||
|  | 	bool valid = SampleSourceSerializer::readSerializedData(serializedData, data.m_data); | ||||||
|  | 
 | ||||||
|  | 	QByteArray sampleSourceSerialized; | ||||||
|  | 
 | ||||||
|  | 	SimpleDeserializer d(serializedData); | ||||||
|  | 
 | ||||||
|  | 	if (!d.isValid()) | ||||||
|  | 	{ | ||||||
|  | 		setDefaults(data); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (d.getVersion() == SampleSourceSerializer::getSerializerVersion()) | ||||||
|  | 	{ | ||||||
|  | 		int intval; | ||||||
|  | 
 | ||||||
|  | 		d.readBlob(1, &sampleSourceSerialized); | ||||||
|  | 		d.readS32(2, &data.m_bias); | ||||||
|  | 		d.readS32(3, &data.m_range); | ||||||
|  | 
 | ||||||
|  | 		return SampleSourceSerializer::readSerializedData(sampleSourceSerialized, data.m_data); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		setDefaults(data); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDSerializer::setDefaults(FCDData& data) | ||||||
|  | { | ||||||
|  | 	data.m_range = 0; | ||||||
|  | 	data.m_bias = 0; | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								plugins/samplesource/fcdpro/fcdserializer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								plugins/samplesource/fcdpro/fcdserializer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2015 Edouard Griffiths, F4EXB                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #ifndef PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_ | ||||||
|  | #define PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_ | ||||||
|  | 
 | ||||||
|  | #include "util/samplesourceserializer.h" | ||||||
|  | 
 | ||||||
|  | class FCDSerializer | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	struct FCDData | ||||||
|  | 	{ | ||||||
|  | 		SampleSourceSerializer::Data m_data; | ||||||
|  | 		qint32 m_bias; | ||||||
|  | 		qint32 m_range; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	static void writeSerializedData(const FCDData& data, QByteArray& serializedData); | ||||||
|  | 	static bool readSerializedData(const QByteArray& serializedData, FCDData& data); | ||||||
|  | 	static void setDefaults(FCDData& data); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #endif /* PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_ */ | ||||||
							
								
								
									
										150
									
								
								plugins/samplesource/fcdpro/fcdthread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								plugins/samplesource/fcdpro/fcdthread.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #include <QDebug> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "fcdthread.h" | ||||||
|  | #include "fcdinput.h" | ||||||
|  | #include "dsp/samplefifo.h" | ||||||
|  | 
 | ||||||
|  | FCDThread::FCDThread(SampleFifo* sampleFifo, QObject* parent) : | ||||||
|  | 	QThread(parent), | ||||||
|  | 	fcd_handle(NULL), | ||||||
|  | 	m_running(false), | ||||||
|  | 	m_convertBuffer(FCD_BLOCKSIZE), | ||||||
|  | 	m_sampleFifo(sampleFifo) | ||||||
|  | { | ||||||
|  | 	start(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FCDThread::~FCDThread() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDThread::stopWork() | ||||||
|  | { | ||||||
|  | 	m_running = false; | ||||||
|  | 	wait(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDThread::run() | ||||||
|  | { | ||||||
|  | 	if ( !OpenSource(FCDInput::m_deviceName.c_str()) ) | ||||||
|  | 	{ | ||||||
|  | 		qCritical() << "FCDThread::run: cannot open FCD sound card"; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	// TODO: fallback to original fcd
 | ||||||
|  | 
 | ||||||
|  | 	m_running = true; | ||||||
|  | 
 | ||||||
|  | 	while(m_running) | ||||||
|  | 	{ | ||||||
|  | 		if (work(FCD_BLOCKSIZE) < 0) | ||||||
|  | 		{ | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	CloseSource(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool FCDThread::OpenSource(const char* cardname) | ||||||
|  | { | ||||||
|  | 	bool fail = false; | ||||||
|  | 	snd_pcm_hw_params_t* params; | ||||||
|  | 	//fcd_rate = FCDPP_RATE;
 | ||||||
|  | 	//fcd_channels =2;
 | ||||||
|  | 	//fcd_format = SND_PCM_SFMT_U16_LE;
 | ||||||
|  | 	snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; | ||||||
|  | 
 | ||||||
|  | 	if (fcd_handle) | ||||||
|  | 	{ | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) | ||||||
|  | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: cannot open %s", cardname); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	snd_pcm_hw_params_alloca(¶ms); | ||||||
|  | 
 | ||||||
|  | 	if (snd_pcm_hw_params_any(fcd_handle, params) < 0) | ||||||
|  | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: snd_pcm_hw_params_any failed"); | ||||||
|  | 		fail = true; | ||||||
|  | 	} | ||||||
|  | 	else if (snd_pcm_hw_params(fcd_handle, params) < 0) | ||||||
|  | 	{ | ||||||
|  | 		qCritical("FCDThread::OpenSource: snd_pcm_hw_params failed"); | ||||||
|  | 		fail = true; | ||||||
|  | 		// TODO: check actual samplerate, may be crippled firmware
 | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (snd_pcm_start(fcd_handle) < 0) | ||||||
|  | 		{ | ||||||
|  | 			qCritical("FCDThread::OpenSource: snd_pcm_start failed"); | ||||||
|  | 			fail = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (fail) | ||||||
|  | 	{ | ||||||
|  | 		snd_pcm_close( fcd_handle ); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		qDebug("FCDThread::OpenSource: Funcube stream started"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FCDThread::CloseSource() | ||||||
|  | { | ||||||
|  | 	if (fcd_handle) | ||||||
|  | 	{ | ||||||
|  | 		snd_pcm_close( fcd_handle ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fcd_handle = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int FCDThread::work(int n_items) | ||||||
|  | { | ||||||
|  | 	int l; | ||||||
|  | 	SampleVector::iterator it; | ||||||
|  | 	void *out; | ||||||
|  | 
 | ||||||
|  | 	it = m_convertBuffer.begin(); | ||||||
|  | 	out = (void *)&it[0]; | ||||||
|  | 	l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items); | ||||||
|  | 	if (l > 0) | ||||||
|  | 		m_sampleFifo->write(it, it + l); | ||||||
|  | 	if (l == -EPIPE) { | ||||||
|  | 		qDebug("FCD: Overrun detected"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return l; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										56
									
								
								plugins/samplesource/fcdpro/fcdthread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								plugins/samplesource/fcdpro/fcdthread.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||||
|  | // written by Christian Daniel                                                   //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is free software; you can redistribute it and/or modify          //
 | ||||||
|  | // it under the terms of the GNU General Public License as published by          //
 | ||||||
|  | // the Free Software Foundation as version 3 of the License, or                  //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // This program is distributed in the hope that it will be useful,               //
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||||
|  | // GNU General Public License V3 for more details.                               //
 | ||||||
|  | //                                                                               //
 | ||||||
|  | // You should have received a copy of the GNU General Public License             //
 | ||||||
|  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||||
|  | ///////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | 
 | ||||||
|  | #ifndef INCLUDE_FCDTHREAD_H | ||||||
|  | #define INCLUDE_FCDTHREAD_H | ||||||
|  | 
 | ||||||
|  | #include <QThread> | ||||||
|  | #include <QMutex> | ||||||
|  | #include <QWaitCondition> | ||||||
|  | #include "dsp/samplefifo.h" | ||||||
|  | #include "dsp/inthalfbandfilter.h" | ||||||
|  | #include <alsa/asoundlib.h> | ||||||
|  | 
 | ||||||
|  | #define FCDPP_RATE 192000 // FIXME: The Pro / Pro+ switch should be handled better than this!
 | ||||||
|  | #define FCD_BLOCKSIZE (1<<11) | ||||||
|  | 
 | ||||||
|  | class FCDThread : public QThread { | ||||||
|  | 	Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	FCDThread(SampleFifo* sampleFifo, QObject* parent = NULL); | ||||||
|  | 	~FCDThread(); | ||||||
|  | 
 | ||||||
|  | 	void stopWork(); | ||||||
|  | 	bool OpenSource(const char *filename); | ||||||
|  | 	void CloseSource(); | ||||||
|  | 	int work(int n_items); | ||||||
|  | private: | ||||||
|  | 	snd_pcm_format_t fcd_format; | ||||||
|  | 	snd_pcm_t* fcd_handle; | ||||||
|  | 
 | ||||||
|  | 	QMutex m_startWaitMutex; | ||||||
|  | 	QWaitCondition m_startWaiter; | ||||||
|  | 	bool m_running; | ||||||
|  | 
 | ||||||
|  | 	SampleVector m_convertBuffer; | ||||||
|  | 	SampleFifo* m_sampleFifo; | ||||||
|  | 
 | ||||||
|  | 	void run(); | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | #endif // INCLUDE_FCDTHREAD_H
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user