diff --git a/rigs/kit/funcube.c b/rigs/kit/funcube.c index 1402471fc..b79b5f724 100644 --- a/rigs/kit/funcube.c +++ b/rigs/kit/funcube.c @@ -36,10 +36,11 @@ #include #include "hamlib/rig.h" #include "token.h" +#include "misc.h" #include "kit.h" -#define BACKEND_VER "20200112" +#define BACKEND_VER "20210830" /* * Compile this model only if libusb is available @@ -56,6 +57,8 @@ #include "funcube.h" +static int funcube_hid_cmd(RIG *rig, unsigned char *au8BufOut, unsigned char *au8BufIn, int inputSize); + static int funcube_init(RIG *rig); static int funcubeplus_init(RIG *rig); static int funcube_cleanup(RIG *rig); @@ -180,23 +183,17 @@ const struct rig_caps funcubeplus_caps = .has_get_func = RIG_FUNC_NONE, .has_set_func = RIG_FUNC_NONE, - .has_get_level = RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_RF, // RIG_LEVEL_ATT: Mixer gain on/off - // RIG_LEVEL_PREAMP: LNA gain on/off + .has_get_level = RIG_LEVEL_PREAMP | RIG_LEVEL_RF, + // RIG_LEVEL_PREAMP: 10dB=LNAon MixGainOff. 20dB=LNAoff, MixGainOn. 30dB=LNAOn, MixGainOn // RIG_LEVEL_RF 0..1 : IF gain 0 .. 59 dB - - - .has_set_level = RIG_LEVEL_ATT | RIG_LEVEL_PREAMP | RIG_LEVEL_RF, // RIG_LEVEL_ATT: Mixer gain on/off - // RIG_LEVEL_PREAMP: LNA gain on/off - // RIG_LEVEL_RF 0..1 : IF gain 0 .. 59 dB - // so values have to be mapped + .has_set_level = RIG_LEVEL_PREAMP | RIG_LEVEL_RF, .has_get_parm = RIG_PARM_NONE, .has_set_parm = RIG_PARM_NONE, .level_gran = {}, .parm_gran = {}, .ctcss_list = NULL, .dcs_list = NULL, - //.preamp = { 5, 10, 15, 20, 25, 30, RIG_DBLST_END, }, - //.attenuator = { 0, 1, 2, RIG_DBLST_END, }, + .preamp = { 10, 20, 30, RIG_DBLST_END, }, .max_rit = Hz(0), .max_xit = Hz(0), .max_ifshift = Hz(0), @@ -638,6 +635,7 @@ int funcube_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) return RIG_OK; } + int funcube_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) { libusb_device_handle *udh = rig->state.rigport.handle; @@ -761,44 +759,12 @@ int funcube_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) return RIG_OK; } -int funcubepro_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) + +int funcube_hid_cmd(RIG *rig, unsigned char *au8BufOut, unsigned char *au8BufIn, int inputSize) { libusb_device_handle *udh = rig->state.rigport.handle; int ret; int actual_length; - unsigned char au8BufOut[64] = { 0 }; // endpoint size - unsigned char au8BufIn[64] = { 0 }; // endpoint size - - switch (level) - { - case RIG_LEVEL_PREAMP: - au8BufOut[0] = REQUEST_SET_LNA_GAIN; // Command to set LNA gain - au8BufOut[1] = val.i & 0x1; - break; - - case RIG_LEVEL_ATT: - au8BufOut[0] = REQUEST_SET_MIXER_GAIN; // Command to Mixer gain - au8BufOut[1] = val.i & 0x1; - break; - - case RIG_LEVEL_RF: - au8BufOut[0] = REQUEST_SET_IF_GAIN; // Command to set IF gain - au8BufOut[1] = (int)(val.f * 100) ; - - if (au8BufOut[1] > 59) - { - au8BufOut[1] = 59; - } - - break; - - - default: - rig_debug(RIG_DEBUG_ERR, "%s: unsupported level %s\n", __func__, - rig_strlevel(level)); - return -RIG_EINVAL; - } - rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n", __func__, au8BufOut[0] & 0xFF, au8BufOut[1] & 0xFF, au8BufOut[2] & 0xFF, au8BufOut[3] & 0xFF); @@ -813,10 +779,10 @@ int funcubepro_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) libusb_error_name(ret)); } - ret = libusb_interrupt_transfer(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), + ret = libusb_interrupt_transfer(udh, INPUT_ENDPOINT, au8BufIn, inputSize, &actual_length, rig->state.rigport.timeout); - if (ret < 0 || actual_length != sizeof(au8BufIn)) + if (ret < 0 || actual_length != inputSize) { rig_debug(RIG_DEBUG_ERR, "%s: libusb_interrupt_transfer failed (%d): %s\n", __func__, ret, @@ -828,85 +794,140 @@ int funcubepro_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) if (au8BufIn[1] != FUNCUBE_SUCCESS) { - rig_debug(RIG_DEBUG_ERR, "%s: REQUEST_GET_FREQ_HZ not supported\n", - __func__); + rig_debug(RIG_DEBUG_ERR, "%s: failed to perform FUNCube HID command %d.\n", + __func__, au8BufOut[0]); return -RIG_EIO; } return RIG_OK; } -int funcubepro_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) + +int funcubepro_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) { - libusb_device_handle *udh = rig->state.rigport.handle; + ENTERFUNC; int ret; - int actual_length; unsigned char au8BufOut[64] = { 0 }; // endpoint size unsigned char au8BufIn[64] = { 0 }; // endpoint size switch (level) { - case RIG_LEVEL_ATT: - au8BufOut[0] = REQUEST_GET_MIXER_GAIN; // Command to Mixer gain enabled - break; - case RIG_LEVEL_PREAMP: - au8BufOut[0] = REQUEST_GET_LNA_GAIN; // Command to get LNA gain enabled - break; + rig_debug(RIG_DEBUG_TRACE, "%s: Setting PREAMP state to %d.\n", + __func__, val.i); + au8BufOut[0] = REQUEST_SET_LNA_GAIN; // Command to set LNA gain + + if( val.i == 10 || val.i == 30 ) + { + au8BufOut[1] = 1; + } + else + { + au8BufOut[1] = 0; + } + + ret = funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); + + if( ret < 0 ) + { + return ret; + } + + au8BufOut[0] = REQUEST_SET_MIXER_GAIN; // Set mixer gain + + if( val.i == 20 || val.i == 30 ) + { + au8BufOut[1] = 1; + } + else + { + au8BufOut[1] = 0; + } + + return funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); case RIG_LEVEL_RF: - au8BufOut[0] = REQUEST_GET_IF_GAIN; - break; + au8BufOut[0] = REQUEST_SET_IF_GAIN; // Command to set IF gain + au8BufOut[1] = (int)(val.f * 100) ; + + if (au8BufOut[1] > 59) + { + au8BufOut[1] = 59; + } + + return funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported level %s\n", __func__, rig_strlevel(level)); return -RIG_EINVAL; } +} - rig_debug(RIG_DEBUG_TRACE, "%s: HID packet set to %02x%02x%02x%02x\n", - __func__, au8BufOut[0] & 0xFF, au8BufOut[1] & 0xFF, au8BufOut[2] & 0xFF, - au8BufOut[3] & 0xFF); - - ret = libusb_interrupt_transfer(udh, OUTPUT_ENDPOINT, au8BufOut, - sizeof(au8BufOut), &actual_length, rig->state.rigport.timeout); - - if (ret < 0) - { - rig_debug(RIG_DEBUG_ERR, "%s: libusb_interrupt_transfer failed (%d): %s\n", - __func__, ret, - libusb_error_name(ret)); - } - - ret = libusb_interrupt_transfer(udh, INPUT_ENDPOINT, au8BufIn, sizeof(au8BufIn), - &actual_length, rig->state.rigport.timeout); - - if (ret < 0 || actual_length != sizeof(au8BufIn)) - { - rig_debug(RIG_DEBUG_ERR, "%s: libusb_interrupt_transfer failed (%d): %s\n", - __func__, ret, - libusb_error_name(ret)); - } - - rig_debug(RIG_DEBUG_TRACE, "%s: Answer buf=%02x%02x%02x\n", - __func__, au8BufIn[0] & 0xFF, au8BufIn[1] & 0xFF, au8BufIn[2] & 0xFF); - - if (au8BufIn[1] != FUNCUBE_SUCCESS) - { - rig_debug(RIG_DEBUG_ERR, "%s: REQUEST_LEVEL_x failed\n", - __func__); - return -RIG_EIO; - } +int funcubepro_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) +{ + ENTERFUNC; + int ret; + int gain_state; + unsigned char au8BufOut[64] = { 0 }; // endpoint size + unsigned char au8BufIn[64] = { 0 }; // endpoint size switch (level) { + case RIG_LEVEL_PREAMP: - case RIG_LEVEL_ATT: - val->i = au8BufIn[2] & 0x01; - break; + au8BufOut[0] = REQUEST_GET_MIXER_GAIN; // Command to get mixer gain enabled + ret = funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); + + if( ret < 0 ) + { + return ret; + } + + rig_debug(RIG_DEBUG_TRACE, "%s: Mixer gain state returned %d.\n", + __func__, au8BufIn[2] & 0xFF); + + gain_state = au8BufIn[2] & 0x1; + + au8BufOut[0] = REQUEST_GET_LNA_GAIN; // Command to get LNA gain enabled + + ret = funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); + + if( ret < 0 ) + { + return ret; + } + + rig_debug(RIG_DEBUG_TRACE, "%s: LNA gain state returned %d.\n", + __func__, au8BufIn[2] & 0xFF); + + //Mixer gain is 20dB 0x2 + gain_state *= 2; + + //Add the LNA gain if present (10dB) 0x1 + gain_state += ( au8BufIn[2] & 0x1 ); + + //Scale it to tens 1->10dB 2->20dB 3->30dB + gain_state *= 10; + + rig_debug(RIG_DEBUG_TRACE, "%s: Calculated gain state is %d.\n", + __func__, gain_state); + + if( gain_state > 30 || gain_state < 0 || gain_state % 10 != 0) + { + rig_debug(RIG_DEBUG_ERR, "%s: unrecognized composite gain: %d\n", __func__, + gain_state); + return -RIG_EINVAL; + } + + val->i = gain_state; + + return RIG_OK; case RIG_LEVEL_RF: + au8BufOut[0] = REQUEST_GET_IF_GAIN; + ret = funcube_hid_cmd(rig, au8BufOut, au8BufIn, sizeof(au8BufIn)); val->f = ((float)au8BufIn[2]) / 100.; - break; + return ret; default: rig_debug(RIG_DEBUG_ERR, "%s: unsupported level %s\n", __func__,