2011-08-23 02:32:35 +00:00
|
|
|
/*
|
2011-02-04 23:20:09 +00:00
|
|
|
* Hamlib KIT backend - FiFi-SDR Receiver(/Tuner) description
|
|
|
|
* Copyright (c) 2010 by Rolf Meeser
|
|
|
|
*
|
|
|
|
* Derived from si570avrusb backend:
|
|
|
|
* Copyright (C) 2004-2010 Stephane Fillod
|
|
|
|
*
|
|
|
|
*
|
2011-08-21 02:34:44 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2011-02-04 23:20:09 +00:00
|
|
|
*
|
2011-08-21 02:34:44 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2011-02-04 23:20:09 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-08-21 02:34:44 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2011-02-04 23:20:09 +00:00
|
|
|
*
|
2011-08-21 02:34:44 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2011-02-04 23:20:09 +00:00
|
|
|
* License along with this library; if not, write to the Free Software
|
2011-08-21 02:34:44 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
2011-02-04 23:20:09 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_STDINT_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "hamlib/rig.h"
|
|
|
|
#include "token.h"
|
|
|
|
|
|
|
|
#include "kit.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compile this model only if libusb is available
|
|
|
|
*/
|
|
|
|
#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <usb.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Selected request codes of the original AVR USB Si570 firmware */
|
2011-02-04 23:20:27 +00:00
|
|
|
#define REQUEST_SET_FREQ_BY_VALUE (0x32)
|
|
|
|
#define REQUEST_SET_XTALL_FREQ (0x33)
|
|
|
|
#define REQUEST_READ_MULTIPLY_LO (0x39)
|
|
|
|
#define REQUEST_READ_FREQUENCY (0x3A)
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
/* FiFi-SDR specific requests */
|
|
|
|
#define REQUEST_FIFISDR_READ (0xAB)
|
|
|
|
#define REQUEST_FIFISDR_WRITE (0xAC)
|
|
|
|
|
|
|
|
|
|
|
|
/* USB VID/PID, vendor name (idVendor), product name (idProduct).
|
|
|
|
* Use obdev's generic shared VID/PID pair and follow the rules outlined
|
|
|
|
* in firmware/usbdrv/USBID-License.txt.
|
|
|
|
*/
|
|
|
|
#define USBDEV_SHARED_VID 0x16C0 /* VOTI */
|
|
|
|
#define USBDEV_SHARED_PID 0x05DC /* Obdev's free shared PID */
|
|
|
|
#define FIFISDR_VENDOR_NAME "www.ov-lennestadt.de"
|
|
|
|
#define FIFISDR_PRODUCT_NAME "FiFi-SDR"
|
|
|
|
|
|
|
|
|
2012-01-08 00:26:25 +00:00
|
|
|
/* All level controls */
|
|
|
|
#define FIFISDR_LEVEL_ALL (0 \
|
|
|
|
| RIG_LEVEL_PREAMP \
|
|
|
|
| RIG_LEVEL_STRENGTH \
|
|
|
|
| RIG_LEVEL_AF \
|
|
|
|
| RIG_LEVEL_AGC \
|
|
|
|
| RIG_LEVEL_SQL \
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
static int fifisdr_init(RIG *rig);
|
|
|
|
static int fifisdr_cleanup(RIG *rig);
|
|
|
|
static int fifisdr_open(RIG *rig);
|
2011-02-04 23:20:27 +00:00
|
|
|
static int fifisdr_set_freq(RIG *rig, vfo_t vfo, freq_t freq);
|
|
|
|
static int fifisdr_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);
|
2011-02-04 23:20:09 +00:00
|
|
|
static const char *fifisdr_get_info(RIG *rig);
|
|
|
|
static int fifisdr_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width);
|
|
|
|
static int fifisdr_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t * width);
|
2011-02-04 23:20:27 +00:00
|
|
|
static int fifisdr_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val);
|
2011-02-04 23:20:09 +00:00
|
|
|
static int fifisdr_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val);
|
|
|
|
static int fifisdr_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Private tokens. */
|
2011-02-04 23:20:27 +00:00
|
|
|
#define TOK_LVL_FMCENTER TOKEN_BACKEND(1) /* FM center frequency deviation */
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Extra levels definitions */
|
|
|
|
static const struct confparams fifisdr_ext_levels[] = {
|
|
|
|
{ TOK_LVL_FMCENTER, "fmcenter", "FM center", "Center frequency deviation of FM signal",
|
2012-01-08 00:26:25 +00:00
|
|
|
NULL, RIG_CONF_NUMERIC, { .n = { -kHz(5), kHz(5), Hz(1) } }
|
2011-02-04 23:20:09 +00:00
|
|
|
},
|
|
|
|
{ RIG_CONF_END, NULL, }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/** Private instance data. */
|
|
|
|
struct fifisdr_priv_instance_data {
|
|
|
|
double multiplier;
|
2011-02-04 23:20:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/** FiFi-SDR receiver description. */
|
2011-02-04 23:20:09 +00:00
|
|
|
const struct rig_caps fifisdr_caps = {
|
|
|
|
.rig_model = RIG_MODEL_FIFISDR,
|
|
|
|
.model_name = "FiFi-SDR",
|
|
|
|
.mfg_name = "FiFi",
|
2012-01-08 00:26:25 +00:00
|
|
|
.version = "0.4",
|
|
|
|
.copyright = "LGPL",
|
2011-02-04 23:20:09 +00:00
|
|
|
.status = RIG_STATUS_BETA,
|
|
|
|
|
|
|
|
.rig_type = RIG_TYPE_RECEIVER,
|
|
|
|
.ptt_type = RIG_PTT_NONE,
|
|
|
|
.dcd_type = RIG_DCD_NONE,
|
|
|
|
.port_type = RIG_PORT_USB,
|
|
|
|
|
|
|
|
.write_delay = 0,
|
|
|
|
.post_write_delay = 0,
|
|
|
|
.timeout = 500,
|
|
|
|
.retry = 0,
|
|
|
|
|
|
|
|
.has_get_func = RIG_FUNC_NONE,
|
|
|
|
.has_set_func = RIG_FUNC_NONE,
|
2012-01-08 00:26:25 +00:00
|
|
|
.has_get_level = FIFISDR_LEVEL_ALL,
|
|
|
|
.has_set_level = RIG_LEVEL_SET(FIFISDR_LEVEL_ALL),
|
2011-02-04 23:20:09 +00:00
|
|
|
.has_get_parm = RIG_PARM_NONE,
|
|
|
|
.has_set_parm = RIG_PARM_SET(RIG_PARM_NONE),
|
|
|
|
|
|
|
|
.level_gran = {},
|
|
|
|
.parm_gran = {},
|
|
|
|
|
|
|
|
.extparms = NULL,
|
|
|
|
.extlevels = fifisdr_ext_levels,
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
.preamp = { 6, RIG_DBLST_END },
|
2011-02-04 23:20:09 +00:00
|
|
|
.attenuator = { RIG_DBLST_END },
|
|
|
|
.max_rit = Hz(0),
|
|
|
|
.max_xit = Hz(0),
|
|
|
|
.max_ifshift = Hz(0),
|
|
|
|
|
|
|
|
.vfo_ops = RIG_OP_NONE,
|
|
|
|
.scan_ops = RIG_SCAN_NONE,
|
|
|
|
.targetable_vfo = 0,
|
|
|
|
.transceive = RIG_TRN_OFF,
|
|
|
|
|
|
|
|
.bank_qty = 0,
|
|
|
|
.chan_desc_sz = 0,
|
|
|
|
.chan_list = {
|
|
|
|
RIG_CHAN_END,
|
|
|
|
},
|
|
|
|
|
|
|
|
.rx_range_list1 = {
|
|
|
|
{.start = kHz(39.1), .end = MHz(175.0),
|
|
|
|
.modes = RIG_MODE_AM | RIG_MODE_SSB | RIG_MODE_FM,
|
|
|
|
.low_power = -1, .high_power = -1,
|
|
|
|
.vfo = RIG_VFO_A, .ant = RIG_ANT_1},
|
|
|
|
RIG_FRNG_END,
|
|
|
|
},
|
|
|
|
.tx_range_list1 = { RIG_FRNG_END, },
|
|
|
|
.rx_range_list2 = {
|
|
|
|
{.start = kHz(39.1), .end = MHz(175.0),
|
|
|
|
.modes = RIG_MODE_AM | RIG_MODE_SSB | RIG_MODE_FM,
|
|
|
|
.low_power = -1, .high_power = -1,
|
|
|
|
.vfo = RIG_VFO_A, .ant = RIG_ANT_1},
|
|
|
|
RIG_FRNG_END,
|
|
|
|
},
|
|
|
|
.tx_range_list2 = { RIG_FRNG_END, },
|
|
|
|
|
|
|
|
.tuning_steps = {
|
2012-01-08 00:26:25 +00:00
|
|
|
{RIG_MODE_SSB, Hz(1)},
|
|
|
|
{RIG_MODE_SSB, Hz(10)},
|
|
|
|
{RIG_MODE_SSB, Hz(50)},
|
|
|
|
{RIG_MODE_AM, Hz(10)},
|
|
|
|
{RIG_MODE_AM, Hz(50)},
|
|
|
|
{RIG_MODE_AM, Hz(100)},
|
|
|
|
{RIG_MODE_FM, kHz(0.1)},
|
|
|
|
{RIG_MODE_FM, kHz(5)},
|
|
|
|
{RIG_MODE_FM, kHz(6.25)},
|
|
|
|
{RIG_MODE_FM, kHz(10)},
|
|
|
|
{RIG_MODE_FM, kHz(12.5)},
|
|
|
|
{RIG_MODE_FM, kHz(20)},
|
|
|
|
{RIG_MODE_FM, kHz(25)},
|
|
|
|
{RIG_MODE_FM, kHz(100)},
|
2011-02-04 23:20:09 +00:00
|
|
|
RIG_TS_END,
|
|
|
|
},
|
|
|
|
/* mode/filter list, remember: order matters! */
|
|
|
|
.filters = {
|
2012-01-08 00:26:25 +00:00
|
|
|
{RIG_MODE_SSB, kHz(2.7)}, /* normal */
|
|
|
|
{RIG_MODE_SSB, kHz(2.2)},
|
2011-02-04 23:20:42 +00:00
|
|
|
{RIG_MODE_SSB, kHz(3.3)},
|
2012-01-08 00:26:25 +00:00
|
|
|
{RIG_MODE_AM, kHz(8.0)}, /* normal */
|
|
|
|
{RIG_MODE_AM, kHz(6.2)},
|
|
|
|
{RIG_MODE_AM, kHz(10.0)},
|
|
|
|
{RIG_MODE_FM, kHz(9.0)}, /* normal */
|
|
|
|
{RIG_MODE_FM, kHz(6.0)},
|
2011-02-04 23:20:09 +00:00
|
|
|
{RIG_MODE_FM, kHz(12.5)},
|
|
|
|
RIG_FLT_END,
|
|
|
|
},
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
.cfgparams = NULL,
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
.rig_init = fifisdr_init,
|
|
|
|
.rig_cleanup = fifisdr_cleanup,
|
|
|
|
.rig_open = fifisdr_open,
|
|
|
|
.rig_close = NULL,
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
.set_freq = fifisdr_set_freq,
|
|
|
|
.get_freq = fifisdr_get_freq,
|
2011-02-04 23:20:09 +00:00
|
|
|
.set_mode = fifisdr_set_mode,
|
|
|
|
.get_mode = fifisdr_get_mode,
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
.set_level = fifisdr_set_level,
|
2011-02-04 23:20:09 +00:00
|
|
|
.get_level = fifisdr_get_level,
|
|
|
|
.get_ext_level = fifisdr_get_ext_level,
|
|
|
|
|
|
|
|
.get_info = fifisdr_get_info,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/** Convert from host endianness to FiFi-SDR little endian. */
|
2011-02-04 23:20:09 +00:00
|
|
|
static uint32_t fifisdr_tole32 (uint32_t x)
|
|
|
|
{
|
|
|
|
return
|
|
|
|
(((((x) / 1ul) % 256ul) << 0) |
|
|
|
|
((((x) / 256ul) % 256ul) << 8) |
|
|
|
|
((((x) / 65536ul) % 256ul) << 16) |
|
|
|
|
((((x) / 16777216ul) % 256ul) << 24));
|
|
|
|
}
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
/** Convert FiFi-SDR little endian to host endianness. */
|
2011-02-04 23:20:09 +00:00
|
|
|
static uint32_t fifisdr_fromle32 (uint32_t x)
|
|
|
|
{
|
|
|
|
return
|
|
|
|
(((((x) >> 24) & 0xFF) * 16777216ul) +
|
|
|
|
((((x) >> 16) & 0xFF) * 65536ul) +
|
|
|
|
((((x) >> 8) & 0xFF) * 256ul) +
|
|
|
|
((((x) >> 0) & 0xFF) * 1ul));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
/** USB OUT transfer via vendor device command. */
|
2011-02-04 23:20:09 +00:00
|
|
|
static int fifisdr_usb_write (RIG *rig,
|
|
|
|
int request, int value, int index,
|
|
|
|
char *bytes, int size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct usb_dev_handle *udh = rig->state.rigport.handle;
|
|
|
|
|
|
|
|
ret = usb_control_msg(udh, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
|
|
|
|
request, value, index,
|
|
|
|
bytes, size, rig->state.rigport.timeout);
|
|
|
|
|
|
|
|
if (ret != size) {
|
|
|
|
rig_debug (RIG_DEBUG_ERR, "%s: usb_control_msg (%d/%d) failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
request, value,
|
|
|
|
usb_strerror ());
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/** USB IN transfer via vendor device command. */
|
2011-02-04 23:20:09 +00:00
|
|
|
static int fifisdr_usb_read (RIG *rig,
|
|
|
|
int request, int value, int index,
|
|
|
|
char *bytes, int size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct usb_dev_handle *udh = rig->state.rigport.handle;
|
|
|
|
|
|
|
|
ret = usb_control_msg(udh, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
|
|
|
|
request, value, index,
|
|
|
|
bytes, size, rig->state.rigport.timeout);
|
|
|
|
|
|
|
|
if (ret != size) {
|
|
|
|
rig_debug (RIG_DEBUG_ERR, "%s: usb_control_msg (%d/%d) failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
request, value,
|
|
|
|
usb_strerror ());
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
int fifisdr_init (RIG *rig)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
|
|
|
hamlib_port_t *rp = &rig->state.rigport;
|
2011-02-04 23:20:27 +00:00
|
|
|
struct fifisdr_priv_instance_data *priv;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
priv = (struct fifisdr_priv_instance_data*)calloc(sizeof(struct fifisdr_priv_instance_data), 1);
|
2011-02-04 23:20:09 +00:00
|
|
|
if (!priv) {
|
|
|
|
/* whoops! memory shortage! */
|
|
|
|
return -RIG_ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->multiplier = 4;
|
|
|
|
|
|
|
|
rp->parm.usb.vid = USBDEV_SHARED_VID;
|
|
|
|
rp->parm.usb.pid = USBDEV_SHARED_PID;
|
|
|
|
|
|
|
|
/* no usb_set_configuration() and usb_claim_interface() */
|
|
|
|
rp->parm.usb.iface = -1;
|
|
|
|
rp->parm.usb.conf = 1;
|
2011-02-04 23:20:27 +00:00
|
|
|
rp->parm.usb.alt = 0;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
rp->parm.usb.vendor_name = FIFISDR_VENDOR_NAME;
|
|
|
|
rp->parm.usb.product = FIFISDR_PRODUCT_NAME;
|
|
|
|
|
|
|
|
rig->state.priv = (void*)priv;
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
int fifisdr_cleanup (RIG *rig)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
|
|
|
if (!rig)
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
|
|
|
|
if (rig->state.priv)
|
|
|
|
free(rig->state.priv);
|
|
|
|
rig->state.priv = NULL;
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
int fifisdr_open (RIG *rig)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
2011-02-04 23:20:27 +00:00
|
|
|
int ret;
|
|
|
|
uint32_t multiply;
|
|
|
|
struct fifisdr_priv_instance_data *priv;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
priv = (struct fifisdr_priv_instance_data*)rig->state.priv;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/* The VCO is a multiple of the RX frequency. Typically 4 */
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
11, /* Read virtual VCO factor */
|
|
|
|
(char *)&multiply, sizeof(multiply));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
priv->multiplier = fifisdr_fromle32(multiply);
|
|
|
|
}
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
const char * fifisdr_get_info (RIG *rig)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
|
|
|
static char buf[64];
|
|
|
|
int ret;
|
|
|
|
uint32_t svn_version;
|
|
|
|
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0, 0, (char *)&svn_version, sizeof(svn_version));
|
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Firmware version: %d", svn_version);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
int fifisdr_set_freq (RIG *rig, vfo_t vfo, freq_t freq)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
2011-02-04 23:20:27 +00:00
|
|
|
struct fifisdr_priv_instance_data *priv = (struct fifisdr_priv_instance_data *)rig->state.priv;
|
2011-02-04 23:20:09 +00:00
|
|
|
int ret;
|
2011-02-04 23:20:27 +00:00
|
|
|
double mhz;
|
|
|
|
uint32_t freq1121;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
/* Need frequency in 11.21 format */
|
|
|
|
mhz = (freq * priv->multiplier) / 1e6;
|
|
|
|
freq1121 = fifisdr_tole32(round(mhz * 2097152.0));
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_SET_FREQ_BY_VALUE, 0, 0,
|
2011-02-04 23:20:27 +00:00
|
|
|
(char *)&freq1121, sizeof(freq1121));
|
2011-02-04 23:20:09 +00:00
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
int fifisdr_get_freq (RIG *rig, vfo_t vfo, freq_t *freq)
|
2011-02-04 23:20:09 +00:00
|
|
|
{
|
2011-02-04 23:20:27 +00:00
|
|
|
struct fifisdr_priv_instance_data *priv = (struct fifisdr_priv_instance_data *)rig->state.priv;
|
2011-02-04 23:20:09 +00:00
|
|
|
int ret;
|
2011-02-04 23:20:27 +00:00
|
|
|
uint32_t freq1121;
|
|
|
|
|
2011-02-04 23:20:09 +00:00
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_READ_FREQUENCY, 0, 0, (char *)&freq1121, sizeof(freq1121));
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
if (ret == RIG_OK) {
|
2011-02-04 23:20:27 +00:00
|
|
|
freq1121 = fifisdr_fromle32(freq1121);
|
|
|
|
*freq = MHz(((double)freq1121 / (1ul << 21)) / priv->multiplier);
|
2011-02-04 23:20:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int fifisdr_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
uint8_t fifi_mode;
|
|
|
|
uint32_t fifi_width;
|
|
|
|
|
|
|
|
/* Translate mode into FiFi-SDR language */
|
|
|
|
fifi_mode = 0;
|
|
|
|
switch (mode) {
|
|
|
|
case RIG_MODE_AM:
|
|
|
|
fifi_mode = 2;
|
|
|
|
break;
|
|
|
|
case RIG_MODE_LSB:
|
|
|
|
fifi_mode = 0;
|
|
|
|
break;
|
|
|
|
case RIG_MODE_USB:
|
|
|
|
fifi_mode = 1;
|
|
|
|
break;
|
|
|
|
case RIG_MODE_FM:
|
|
|
|
fifi_mode = 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
}
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
15, /* Demodulator mode */
|
|
|
|
(char *)&fifi_mode, sizeof(fifi_mode));
|
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set filter width */
|
|
|
|
fifi_width = fifisdr_tole32(width);
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
16, /* Filter width */
|
|
|
|
(char *)&fifi_width, sizeof(fifi_width));
|
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int fifisdr_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t * width)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
uint8_t fifi_mode;
|
|
|
|
uint32_t fifi_width;
|
|
|
|
|
|
|
|
|
|
|
|
/* Read current mode */
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
15, /* Demodulator mode */
|
|
|
|
(char *)&fifi_mode, sizeof(fifi_mode));
|
|
|
|
|
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Translate mode coding */
|
|
|
|
*mode = RIG_MODE_NONE;
|
|
|
|
switch (fifi_mode) {
|
|
|
|
case 0:
|
|
|
|
*mode = RIG_MODE_LSB;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
*mode = RIG_MODE_USB;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
*mode = RIG_MODE_AM;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
*mode = RIG_MODE_FM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read current filter width */
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
16, /* Filter width */
|
|
|
|
(char *)&fifi_width, sizeof(fifi_width));
|
|
|
|
if (ret != RIG_OK) {
|
|
|
|
return -RIG_EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
*width = s_Hz(fifisdr_fromle32(fifi_width));
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
static int fifisdr_set_level (RIG * rig, vfo_t vfo, setting_t level, value_t val)
|
|
|
|
{
|
|
|
|
int ret = RIG_OK;
|
|
|
|
uint8_t fifi_preamp;
|
2012-01-08 00:26:25 +00:00
|
|
|
int16_t fifi_volume;
|
|
|
|
uint8_t fifi_squelch;
|
|
|
|
uint8_t fifi_agc;
|
2011-02-04 23:20:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
switch (level) {
|
|
|
|
/* Preamplifier (ADC 0/+6dB switch) */
|
|
|
|
case RIG_LEVEL_PREAMP:
|
|
|
|
/* Value can be 0 (0 dB) or 1 (+6 dB) */
|
|
|
|
fifi_preamp = 0;
|
|
|
|
if (val.i == 6) {
|
|
|
|
fifi_preamp = 1;
|
|
|
|
}
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
19, /* Preamp */
|
|
|
|
(char *)&fifi_preamp, sizeof(fifi_preamp));
|
|
|
|
break;
|
|
|
|
|
2012-01-08 00:26:25 +00:00
|
|
|
/* RX volume control */
|
|
|
|
case RIG_LEVEL_AF:
|
|
|
|
/* Transform Hamlib value (float: 0...1) to an integer range (0...100) */
|
|
|
|
fifi_volume = (int16_t)(val.f * 100.0f);
|
|
|
|
if (fifi_volume < 0) {
|
|
|
|
fifi_volume = 0;
|
|
|
|
}
|
|
|
|
if (fifi_volume > 100) {
|
|
|
|
fifi_volume = 100;
|
|
|
|
}
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
14, /* Demodulator volume */
|
|
|
|
(char *)&fifi_volume, sizeof(fifi_volume));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Squelch level */
|
|
|
|
case RIG_LEVEL_SQL:
|
|
|
|
/* Transform Hamlib value (float: 0...1) to an integer range (0...100) */
|
|
|
|
fifi_squelch = (uint8_t)(val.f * 100.0f);
|
|
|
|
if (fifi_squelch < 0) {
|
|
|
|
fifi_squelch = 0;
|
|
|
|
}
|
|
|
|
if (fifi_squelch > 100) {
|
|
|
|
fifi_squelch = 100;
|
|
|
|
}
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
20, /* Squelch control */
|
|
|
|
(char *)&fifi_squelch, sizeof(fifi_squelch));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* AGC */
|
|
|
|
case RIG_LEVEL_AGC:
|
|
|
|
/* Transform Hamlib enum value to FiFi-SDR selector */
|
|
|
|
fifi_agc = 0;
|
|
|
|
switch ((enum agc_level_e)val.i) {
|
|
|
|
case RIG_AGC_OFF: fifi_agc = 0; break;
|
|
|
|
case RIG_AGC_SUPERFAST: fifi_agc = 1; break;
|
|
|
|
case RIG_AGC_FAST: fifi_agc = 2; break;
|
|
|
|
case RIG_AGC_SLOW: fifi_agc = 3; break;
|
|
|
|
case RIG_AGC_USER: fifi_agc = 4; break;
|
|
|
|
case RIG_AGC_MEDIUM: fifi_agc = 5; break;
|
|
|
|
case RIG_AGC_AUTO: fifi_agc = 6; break;
|
|
|
|
}
|
|
|
|
ret = fifisdr_usb_write(rig, REQUEST_FIFISDR_WRITE, 0,
|
|
|
|
21, /* AGC template */
|
|
|
|
(char *)&fifi_agc, sizeof(fifi_agc));
|
|
|
|
break;
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
/* Unsupported option */
|
|
|
|
default:
|
|
|
|
ret = -RIG_ENIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int fifisdr_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
|
|
|
|
{
|
|
|
|
int ret = RIG_OK;
|
|
|
|
uint32_t fifi_meter = 0;
|
2011-02-04 23:20:27 +00:00
|
|
|
uint8_t fifi_preamp = 0;
|
2012-01-08 00:26:25 +00:00
|
|
|
int16_t fifi_volume = 0;
|
|
|
|
uint8_t fifi_squelch = 0;
|
|
|
|
uint8_t fifi_agc = 0;
|
2011-02-04 23:20:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
switch (level) {
|
2011-02-04 23:20:27 +00:00
|
|
|
/* Preamplifier (ADC 0/+6dB switch) */
|
|
|
|
case RIG_LEVEL_PREAMP:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
19, /* Preamp */
|
|
|
|
(char *)&fifi_preamp, sizeof(fifi_preamp));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
/* Value can be 0 (0 dB) or 1 (+6 dB) */
|
|
|
|
val->i = 0;
|
|
|
|
if (fifi_preamp != 0) {
|
|
|
|
val->i = 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-01-08 00:26:25 +00:00
|
|
|
/* RX volume control */
|
|
|
|
case RIG_LEVEL_AF:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
14, /* Demodulator volume */
|
|
|
|
(char *)&fifi_volume, sizeof(fifi_volume));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
/* Value is in % (0...100) */
|
|
|
|
val->f = 0.0f;
|
|
|
|
if ((fifi_volume >=0) && (fifi_volume <= 100)) {
|
|
|
|
val->f = (float)fifi_volume / 100.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Squelch level */
|
|
|
|
case RIG_LEVEL_SQL:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
20, /* Squelch control */
|
|
|
|
(char *)&fifi_squelch, sizeof(fifi_squelch));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
/* Value is in % (0...100) */
|
|
|
|
val->f = 0.0f;
|
|
|
|
if (fifi_squelch <= 100) {
|
|
|
|
val->f = (float)fifi_squelch / 100.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* AGC */
|
|
|
|
case RIG_LEVEL_AGC:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
21, /* AGC template */
|
|
|
|
(char *)&fifi_agc, sizeof(fifi_agc));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
val->i = 0;
|
|
|
|
switch (fifi_agc) {
|
|
|
|
case 0: val->f = RIG_AGC_OFF; break;
|
|
|
|
case 1: val->f = RIG_AGC_SUPERFAST; break;
|
|
|
|
case 2: val->f = RIG_AGC_FAST; break;
|
|
|
|
case 3: val->f = RIG_AGC_SLOW; break;
|
|
|
|
case 4: val->f = RIG_AGC_USER; break;
|
|
|
|
case 5: val->f = RIG_AGC_MEDIUM; break;
|
|
|
|
case 6: val->f = RIG_AGC_AUTO; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-02-04 23:20:09 +00:00
|
|
|
/* Signal strength */
|
|
|
|
case RIG_LEVEL_STRENGTH:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
17, /* S-Meter */
|
|
|
|
(char *)&fifi_meter, sizeof(fifi_meter));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
val->i = fifisdr_fromle32(fifi_meter);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Unsupported option */
|
|
|
|
default:
|
|
|
|
ret = -RIG_ENIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-04 23:20:27 +00:00
|
|
|
|
2011-02-04 23:20:09 +00:00
|
|
|
static int fifisdr_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val)
|
|
|
|
{
|
|
|
|
int ret = RIG_OK;
|
|
|
|
uint32_t u32;
|
|
|
|
|
|
|
|
|
|
|
|
switch (token) {
|
2011-02-04 23:20:27 +00:00
|
|
|
/* FM center frequency deviation */
|
2011-02-04 23:20:09 +00:00
|
|
|
case TOK_LVL_FMCENTER:
|
|
|
|
ret = fifisdr_usb_read(rig, REQUEST_FIFISDR_READ, 0,
|
|
|
|
18, /* FM center frequency */
|
|
|
|
(char *)&u32, sizeof(u32));
|
|
|
|
if (ret == RIG_OK) {
|
|
|
|
val->f = Hz((int32_t)fifisdr_fromle32(u32));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Unsupported option */
|
|
|
|
default:
|
|
|
|
ret = -RIG_ENIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* defined(HAVE_LIBUSB) && defined(HAVE_USB_H) */
|