Added attenuator, preamplifier and RSSI to FUNcube

The Attenuator/Preamp has been added: not all the LNA values have been
added because Hamlib can only have maximum 8 values and FUNcube has
more.

The RSSI readout is performed on the IF and it is not calibrated. To
calibrate it, it would be necessary to read all the gains in the
complete chain to compute the real RSSI.

The driver now also supports firmware versions 1.x.

Author: Stefano Speretta, Innovative Solutions In Space BV
<s.speretta@isispace.nl>

Signed-off-by: Stefano Speretta <s.speretta@isispace.nl>

git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@3053 7ae35d74-ebe9-4afe-98af-79ac388436b8
Hamlib-1.2.13
Nate Bargmann, N0NB 2011-02-17 12:22:20 +00:00
rodzic db27b38041
commit 931ae29e3c
2 zmienionych plików z 347 dodań i 32 usunięć

Wyświetl plik

@ -52,12 +52,18 @@ static int funcube_init(RIG *rig);
static int funcube_cleanup(RIG *rig);
static int funcube_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
static int funcube_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
static int funcube_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val);
static int funcube_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val);
static const char *funcube_get_info(RIG *rig);
static const struct confparams funcube_cfg_params[] = {
{ RIG_CONF_END, NULL, }
};
// functions used set / read frequency, working on FUNcube version 0 and 1
int set_freq_v0(usb_dev_handle *udh, unsigned int f, int timeout);
int set_freq_v1(usb_dev_handle *udh, unsigned int f, int timeout);
/*
* Common data struct
*/
@ -67,7 +73,7 @@ struct funcube_priv_data {
};
/*
* FunCUBE Dongle description
* FUNcube Dongle description
*
* Based on Jan Axelson HID examples
* http://www.lvr.com/
@ -92,16 +98,16 @@ const struct rig_caps funcube_caps = {
.has_get_func = RIG_FUNC_NONE,
.has_set_func = RIG_FUNC_NONE,
.has_get_level = RIG_LEVEL_NONE,
.has_set_level = RIG_LEVEL_NONE,
.has_get_level = RIG_LEVEL_ATT | RIG_LEVEL_STRENGTH | RIG_LEVEL_PREAMP,
.has_set_level = RIG_LEVEL_ATT | RIG_LEVEL_PREAMP,
.has_get_parm = RIG_PARM_NONE,
.has_set_parm = RIG_PARM_NONE,
.level_gran = {},
.parm_gran = {},
.ctcss_list = NULL,
.dcs_list = NULL,
.preamp = { RIG_DBLST_END },
.attenuator = { RIG_DBLST_END },
.preamp = { 5, 10, 15, 20, 25, 30, RIG_DBLST_END, },
.attenuator = { 2, 5, RIG_DBLST_END, },
.max_rit = Hz(0),
.max_xit = Hz(0),
.max_ifshift = Hz(0),
@ -130,6 +136,8 @@ const struct rig_caps funcube_caps = {
.rig_cleanup = funcube_cleanup,
.set_freq = funcube_set_freq,
.get_freq = funcube_get_freq,
.get_level = funcube_get_level,
.set_level = funcube_set_level,
.get_info = funcube_get_info,
};
@ -183,35 +191,247 @@ const char * funcube_get_info(RIG *rig)
return buf;
}
int set_freq_v0(usb_dev_handle *udh, unsigned int f, int timeout)
{
int ret;
char au8BufOut[64]; // endpoint size
char au8BufIn[64]; // endpoint size
// frequency is in Hz, while the dongle expects it in kHz
f = f / 1e3;
au8BufOut[0]=REQUEST_SET_FREQ; // Command to Set Frequency on dongle
au8BufOut[1]=(char)f;
au8BufOut[2]=(char)(f>>8);
au8BufOut[3]=(char)(f>>16);
rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n",
__func__, (unsigned)au8BufOut[0] & 0xFF, (unsigned)au8BufOut[1] & 0xFF, (unsigned)au8BufOut[2] & 0xFF, (unsigned)au8BufOut[3] & 0xFF);
ret = usb_interrupt_write(udh, OUTPUT_ENDPOINT, au8BufOut, sizeof(au8BufOut), timeout);
if( ret < 0 )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_write failed (%d): %s\n",
__func__,ret, usb_strerror ());
return -RIG_EIO;
}
ret = usb_interrupt_read(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), timeout);
if( ret != sizeof(au8BufIn) )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_read failed (%d): %s\n",
__func__, ret, usb_strerror ());
return -RIG_EIO;
}
rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x\n",
__func__, (unsigned)au8BufIn[0] & 0xFF, (unsigned)au8BufIn[1] & 0xFF);
if (au8BufIn[1] != FUNCUBE_SUCCESS) {
rig_debug (RIG_DEBUG_ERR, "%s: REQUEST_SET_FREQ not supported\n",
__func__);
return -RIG_EIO;
}
return RIG_OK;
}
int set_freq_v1(usb_dev_handle *udh, unsigned int f, int timeout)
{
int ret;
char au8BufOut[64]; // endpoint size
char au8BufIn[64]; // endpoint size
au8BufOut[0]=REQUEST_SET_FREQ_HZ; // Command to Set Frequency in Hz on dongle
au8BufOut[1]=(char)f;
au8BufOut[2]=(char)(f>>8);
au8BufOut[3]=(char)(f>>16);
au8BufOut[4]=(char)(f>>24);
rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x%02x\n",
__func__, (unsigned)au8BufOut[0] & 0xFF, (unsigned)au8BufOut[1] & 0xFF, (unsigned)au8BufOut[2] & 0xFF, (unsigned)au8BufOut[3] & 0xFF,
(unsigned)au8BufOut[4] & 0xFF);
ret = usb_interrupt_write(udh, OUTPUT_ENDPOINT, au8BufOut, sizeof(au8BufOut), timeout);
if( ret < 0 )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_write failed (%d): %s\n",
__func__,ret,
usb_strerror ());
return -RIG_EIO;
}
ret = usb_interrupt_read(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), timeout);
if( ret != sizeof(au8BufIn) )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_read failed (%d): %s\n",
__func__, ret,
usb_strerror ());
return -RIG_EIO;
}
rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x%02x%02x%02x%02x\n",
__func__, (unsigned)au8BufIn[0] & 0xFF, (unsigned)au8BufIn[1] & 0xFF, (unsigned)au8BufIn[2] & 0xFF, (unsigned)au8BufIn[3] & 0xFF,
(unsigned)au8BufIn[4] & 0xFF, (unsigned)au8BufIn[5] & 0xFF);
if (au8BufIn[1] != FUNCUBE_SUCCESS) {
rig_debug (RIG_DEBUG_ERR, "%s: REQUEST_SET_FREQ_HZ not supported\n",
__func__);
return -RIG_EIO;
}
return RIG_OK;
}
int funcube_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
struct funcube_priv_data *priv = (struct funcube_priv_data *)rig->state.priv;
struct usb_dev_handle *udh = rig->state.rigport.handle;
int ret;
if ((ret = set_freq_v1(udh, freq, rig->state.rigport.timeout)) != RIG_OK) {
if ((ret = set_freq_v0(udh, freq, rig->state.rigport.timeout)) == RIG_OK) {
priv->freq = freq;
}
}
else {
priv->freq = freq;
}
return ret;
}
int get_freq_v0(RIG *rig, vfo_t vfo, freq_t *freq)
{
struct funcube_priv_data *priv = (struct funcube_priv_data *)rig->state.priv;
rig_debug(RIG_DEBUG_TRACE, "%s: frequency is not read from the device, the value shown is the last succesfully set.\n",__func__);
*freq = priv->freq;
return RIG_OK;
}
int get_freq_v1(RIG *rig, vfo_t vfo, freq_t *freq)
{
struct usb_dev_handle *udh = rig->state.rigport.handle;
int ret;
unsigned int f;
char au8BufOut[64]; // endpoint size
char au8BufIn[64]; // endpoint size
if (freq < funcube_caps.rx_range_list1[0].start) {
rig_debug(RIG_DEBUG_WARN, "Error in %s: frequency is lower than minimum supported value (%.0f Hz)\n",
__FUNCTION__, funcube_caps.rx_range_list1[0].start);
return -RIG_EPROTO;
au8BufOut[0]=REQUEST_GET_FREQ_HZ; // Command to Set Frequency on dongle
rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n",
__func__, (unsigned)au8BufOut[0] & 0xFF, (unsigned)au8BufOut[1] & 0xFF, (unsigned)au8BufOut[2] & 0xFF, (unsigned)au8BufOut[3] & 0xFF);
ret = usb_interrupt_write(udh, OUTPUT_ENDPOINT, au8BufOut, sizeof(au8BufOut), rig->state.rigport.timeout);
if( ret < 0 )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_write failed (%d): %s\n",
__func__,ret,
usb_strerror ());
}
ret = usb_interrupt_read(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), rig->state.rigport.timeout);
if( ret != sizeof(au8BufIn) )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_read failed (%d): %s\n",
__func__, ret,
usb_strerror ());
}
rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x%02x%02x%02x%02x\n",
__func__, (unsigned)au8BufIn[0] & 0xFF, (unsigned)au8BufIn[1] & 0xFF, (unsigned)au8BufIn[2] & 0xFF, (unsigned)au8BufIn[3] & 0xFF,
(unsigned)au8BufIn[4] & 0xFF, (unsigned)au8BufIn[5] & 0xFF);
if (au8BufIn[1] != FUNCUBE_SUCCESS) {
rig_debug (RIG_DEBUG_ERR, "%s: REQUEST_GET_FREQ_HZ not supported\n",
__func__);
return -RIG_EIO;
}
if (freq > funcube_caps.rx_range_list1[0].end) {
rig_debug(RIG_DEBUG_WARN, "Error in %s: frequency is higher than maximum supported value (%.0f Hz)\n",
__FUNCTION__, funcube_caps.rx_range_list1[0].end);
return -RIG_EPROTO;
f = ((unsigned int)au8BufIn[2] & 0xFF) | (((unsigned int)au8BufIn[3] & 0xFF) << 8) |
(((unsigned int)au8BufIn[4] & 0xFF) << 16) | (((unsigned int)au8BufIn[5] & 0xFF) << 24),
*freq = f;
return RIG_OK;
}
int funcube_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
{
int ret;
if ((ret = get_freq_v1(rig, vfo, freq)) != RIG_OK) {
ret = get_freq_v0(rig, vfo, freq);
}
// frequency is in Hz, while the dongle expects it in kHz
f = freq / 1e3;
return ret;
}
au8BufOut[0]=REQUEST_SET_FREQ; // Command to Set Frequency on dongle
au8BufOut[1]=(char)f;
au8BufOut[2]=(char)(f>>8);
au8BufOut[3]=(char)(f>>16);
int funcube_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
{
struct usb_dev_handle *udh = rig->state.rigport.handle;
int ret;
char au8BufOut[64]; // endpoint size
char au8BufIn[64]; // endpoint size
switch (level) {
case RIG_LEVEL_PREAMP:
au8BufOut[0]=REQUEST_SET_LNA_GAIN; // Command to Set LNA gain
switch (val.i) {
case 5:
au8BufOut[1]=6;
break;
case 10:
au8BufOut[1]=8;
break;
case 15:
au8BufOut[1]=10;
break;
case 20:
au8BufOut[1]=12;
break;
case 25:
au8BufOut[1]=13;
break;
case 30:
au8BufOut[1]=14;
break;
default:
au8BufOut[1]=4;
}
break;
case RIG_LEVEL_ATT:
au8BufOut[0]=REQUEST_SET_LNA_GAIN; // Command to Set LNA gain
switch (val.i) {
case 2:
au8BufOut[1]=1;
break;
case 5:
au8BufOut[1]=0;
break;
default:
au8BufOut[1]=4;
}
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported level %d\n", __func__, level);
return -RIG_EINVAL;
}
rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n",
__func__, (unsigned)au8BufOut[0] & 0xFF, (unsigned)au8BufOut[1] & 0xFF, (unsigned)au8BufOut[2] & 0xFF, (unsigned)au8BufOut[3] & 0xFF);
@ -237,26 +457,114 @@ int funcube_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x\n",
__func__, (unsigned)au8BufIn[0] & 0xFF, (unsigned)au8BufIn[1] & 0xFF);
if (!ret) {
rig_debug (RIG_DEBUG_ERR, "%s: usb_control_msg failed: %s\n",
__func__,
usb_strerror ());
if (au8BufIn[1] != FUNCUBE_SUCCESS) {
rig_debug (RIG_DEBUG_ERR, "%s: REQUEST_GET_FREQ_HZ not supported\n",
__func__);
return -RIG_EIO;
}
priv->freq = freq;
return RIG_OK;
}
int funcube_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
int funcube_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
{
struct funcube_priv_data *priv = (struct funcube_priv_data *)rig->state.priv;
struct usb_dev_handle *udh = rig->state.rigport.handle;
int ret;
char au8BufOut[64]; // endpoint size
char au8BufIn[64]; // endpoint size
rig_debug(RIG_DEBUG_TRACE, "%s: frequency is not read from the device, the value shown is the last succesfully set.\n",__func__);
*freq = priv->freq;
switch (level) {
case RIG_LEVEL_ATT:
case RIG_LEVEL_PREAMP:
au8BufOut[0]=REQUEST_GET_LNA_GAIN; // Command to Get LNA / ATT gain
break;
case RIG_LEVEL_STRENGTH:
au8BufOut[0]=REQUEST_GET_RSSI;
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported level %d\n", __func__, level);
return -RIG_EINVAL;
}
rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n",
__func__, (unsigned)au8BufOut[0] & 0xFF, (unsigned)au8BufOut[1] & 0xFF, (unsigned)au8BufOut[2] & 0xFF, (unsigned)au8BufOut[3] & 0xFF);
ret = usb_interrupt_write(udh, OUTPUT_ENDPOINT, au8BufOut, sizeof(au8BufOut), rig->state.rigport.timeout);
if( ret < 0 )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_write failed (%d): %s\n",
__func__,ret,
usb_strerror ());
}
ret = usb_interrupt_read(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), rig->state.rigport.timeout);
if( ret != sizeof(au8BufIn) )
{
rig_debug (RIG_DEBUG_ERR, "%s: usb_interrupt_read failed (%d): %s\n",
__func__, ret,
usb_strerror ());
}
rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x%02x\n",
__func__, (unsigned)au8BufIn[0] & 0xFF, (unsigned)au8BufIn[1] & 0xFF, (unsigned)au8BufIn[2] & 0xFF);
if (au8BufIn[1] != FUNCUBE_SUCCESS) {
rig_debug (RIG_DEBUG_ERR, "%s: REQUEST_GET_FREQ_HZ not supported\n",
__func__);
return -RIG_EIO;
}
switch (level) {
case RIG_LEVEL_PREAMP:
switch (au8BufIn[2]) {
case 6:
val->i = 5;
break;
case 8:
val->i = 10;
break;
case 10:
val->i = 15;
break;
case 12:
val->i = 20;
break;
case 13:
val->i = 25;
break;
case 14:
val->i = 30;
break;
default:
val->i = 0;
}
break;
case RIG_LEVEL_ATT:
switch (au8BufIn[2]) {
case 0:
val->i = 5;
break;
case 1:
val->i = 2;
break;
default:
val->i = 0;
}
break;
case RIG_LEVEL_STRENGTH:
val->i = (int)((float)au8BufIn[2] * 2.8 - 35);
break;
default:
rig_debug(RIG_DEBUG_ERR,"%s: Unsupported level %d\n", __func__, level);
return -RIG_EINVAL;
}
return RIG_OK;
}
#endif /* defined(HAVE_LIBUSB) && defined(HAVE_USB_H) */

Wyświetl plik

@ -28,7 +28,7 @@
#define VID 0x04D8
#define PID 0xFB56
#define VENDOR_NAME "Hanlincrest Ltd. "
#define PRODUCT_NAME "FunCube Dongle V0.0 "
#define PRODUCT_NAME "FunCube Dongle"
#define FUNCUBE_INTERFACE 0x02
#define FUNCUBE_CONFIGURATION 0x00
@ -39,5 +39,12 @@
// Commands
#define REQUEST_SET_FREQ 0x64
#define REQUEST_SET_FREQ_HZ 0x65
#define REQUEST_GET_FREQ_HZ 0x66
#define REQUEST_SET_LNA_GAIN 0x6E
#define REQUEST_GET_LNA_GAIN 0x96
#define REQUEST_GET_RSSI 0x68
#define FUNCUBE_SUCCESS 0x01
#endif /* _FUNCUBE_H */