icE1usb fw: Add USB control for the GPSDO function

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Change-Id: If92aa68d8a49349fa0d6d556eec81bbb80be989c
This commit is contained in:
Sylvain Munaut 2022-01-13 00:50:10 +01:00
parent e76b643298
commit c308334de7
4 changed files with 189 additions and 0 deletions

View File

@ -13,6 +13,8 @@
#include "gpsdo.h" #include "gpsdo.h"
#include "misc.h" #include "misc.h"
#include "ice1usb_proto.h"
struct { struct {
/* Current tuning */ /* Current tuning */
@ -74,6 +76,72 @@ vctxo_sensitivity[] = {
#define MAX_INVALID 5 #define MAX_INVALID 5
static void _gpsdo_coarse_start(void);
void
gpsdo_get_status(struct e1usb_gpsdo_status *status)
{
const uint8_t state_map[] = {
[STATE_DISABLED] = ICE1USB_GPSDO_STATE_DISABLED,
[STATE_HOLD_OVER] = ICE1USB_GPSDO_STATE_HOLD_OVER,
[STATE_TUNE_COARSE] = ICE1USB_GPSDO_STATE_TUNE_COARSE,
[STATE_TUNE_FINE] = ICE1USB_GPSDO_STATE_TUNE_FINE,
};
const uint8_t ant_map[] = {
[ANT_UNKNOWN] = ICE1USB_GPSDO_ANT_UNKNOWN,
[ANT_OK] = ICE1USB_GPSDO_ANT_OK,
[ANT_OPEN] = ICE1USB_GPSDO_ANT_OPEN,
[ANT_SHORT] = ICE1USB_GPSDO_ANT_SHORT,
};
status->state = state_map[g_gpsdo.state];
status->antenna_status = ant_map[gps_antenna_status()];
status->valid_fix = gps_has_valid_fix();
status->mode = (g_gpsdo.state == STATE_DISABLED) ? ICE1USB_GPSDO_MODE_DISABLED : ICE1USB_GPSDO_MODE_AUTO;
status->tune.coarse = g_gpsdo.tune.coarse;
status->tune.fine = g_gpsdo.tune.fine;
status->freq_est = g_gpsdo.meas.last;
}
void
gpsdo_enable(bool enable)
{
if (!enable)
g_gpsdo.state = STATE_DISABLED;
else if (g_gpsdo.state == STATE_DISABLED)
g_gpsdo.state = STATE_HOLD_OVER;
}
bool
gpsdo_enabled(void)
{
return g_gpsdo.state != STATE_DISABLED;
}
void
gpsdo_set_tune(uint16_t coarse, uint16_t fine)
{
/* Set value */
g_gpsdo.tune.coarse = coarse;
g_gpsdo.tune.fine = fine;
pdm_set(PDM_CLK_HI, true, g_gpsdo.tune.coarse, false);
pdm_set(PDM_CLK_LO, true, g_gpsdo.tune.fine, false);
/* If we were in 'fine' mode, reset to coarse */
if (g_gpsdo.state == STATE_TUNE_FINE)
_gpsdo_coarse_start();
}
void
gpsdo_get_tune(uint16_t *coarse, uint16_t *fine)
{
*coarse = g_gpsdo.tune.coarse;
*fine = g_gpsdo.tune.fine;
}
static void static void
_gpsdo_coarse_start(void) _gpsdo_coarse_start(void)
{ {

View File

@ -12,5 +12,16 @@ enum gpsdo_vctxo_model {
VCTXO_SITIME_SIT3808_E = 1, /* SIT3808AI-D2-33EE-30.720000T */ VCTXO_SITIME_SIT3808_E = 1, /* SIT3808AI-D2-33EE-30.720000T */
}; };
struct e1usb_gpsdo_status;
void gpsdo_get_status(struct e1usb_gpsdo_status *status);
void gpsdo_enable(bool enable);
bool gpsdo_enabled(void);
void gpsdo_set_tune(uint16_t coarse, uint16_t fine);
void gpsdo_get_tune(uint16_t *coarse, uint16_t *fine);
void gpsdo_poll(void); void gpsdo_poll(void);
void gpsdo_init(enum gpsdo_vctxo_model vctxo); void gpsdo_init(enum gpsdo_vctxo_model vctxo);

View File

@ -17,12 +17,51 @@
/*! returns a bit-mask of optional device capabilities (see enum e1usb_dev_capability) */ /*! returns a bit-mask of optional device capabilities (see enum e1usb_dev_capability) */
#define ICE1USB_DEV_GET_CAPABILITIES 0x01 #define ICE1USB_DEV_GET_CAPABILITIES 0x01
#define ICE1USB_DEV_GET_FW_BUILD 0x02 #define ICE1USB_DEV_GET_FW_BUILD 0x02
#define ICE1USB_DEV_GET_GPSDO_STATUS 0x10
#define ICE1USB_DEV_GET_GPSDO_MODE 0x12 /*!< uint8_t */
#define ICE1USB_DEV_SET_GPSDO_MODE 0x13 /*!< wValue = mode */
#define ICE1USB_DEV_GET_GPSDO_TUNE 0x14 /*!< data = struct e1usb_gpsdo_tune */
#define ICE1USB_DEV_SET_GPSDO_TUNE 0x15 /*!< data = struct e1usb_gpsdo_tune */
enum e1usb_dev_capability { enum e1usb_dev_capability {
/*! Does this board have a GPS-DO */ /*! Does this board have a GPS-DO */
ICE1USB_DEV_CAP_GPSDO, ICE1USB_DEV_CAP_GPSDO,
}; };
enum ice1usb_gpsdo_mode {
ICE1USB_GPSDO_MODE_DISABLED = 0,
ICE1USB_GPSDO_MODE_AUTO = 1,
};
enum ice1usb_gpsdo_antenna_state {
ICE1USB_GPSDO_ANT_UNKNOWN = 0,
ICE1USB_GPSDO_ANT_OK = 1,
ICE1USB_GPSDO_ANT_OPEN = 2,
ICE1USB_GPSDO_ANT_SHORT = 3,
};
enum ice1usb_gpsdo_state {
ICE1USB_GPSDO_STATE_DISABLED = 0,
ICE1USB_GPSDO_STATE_CALIBRATE = 1,
ICE1USB_GPSDO_STATE_HOLD_OVER = 2,
ICE1USB_GPSDO_STATE_TUNE_COARSE = 3,
ICE1USB_GPSDO_STATE_TUNE_FINE = 4,
};
struct e1usb_gpsdo_tune {
uint16_t coarse;
uint16_t fine;
} __attribute__((packed));
struct e1usb_gpsdo_status {
uint8_t state;
uint8_t antenna_status; /*!< Antenna status */
uint8_t valid_fix; /*!< Valid GPS Fix (0/1) */
uint8_t mode; /*!< Current configured operating mode */
struct e1usb_gpsdo_tune tune; /*!< Current VCXO tuning values */
uint32_t freq_est; /*!< Latest frequency estimate measurement */
} __attribute__((packed));
/* Interface Requests */ /* Interface Requests */

View File

@ -12,6 +12,7 @@
#include <no2usb/usb_proto.h> #include <no2usb/usb_proto.h>
#include "console.h" #include "console.h"
#include "gpsdo.h"
#include "misc.h" #include "misc.h"
#include "ice1usb_proto.h" #include "ice1usb_proto.h"
@ -20,6 +21,61 @@
const char *fw_build_str = BUILD_INFO; const char *fw_build_str = BUILD_INFO;
static void
_get_gpsdo_status(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{
struct e1usb_gpsdo_status status;
gpsdo_get_status(&status);
memcpy(xfer->data, &status, sizeof(struct e1usb_gpsdo_status));
xfer->len = sizeof(struct e1usb_gpsdo_status);
}
static void
_get_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{
xfer->data[0] = gpsdo_enabled() ? ICE1USB_GPSDO_MODE_DISABLED : ICE1USB_GPSDO_MODE_AUTO;
xfer->len = 1;
}
static void
_set_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{
gpsdo_enable(req->wValue != ICE1USB_GPSDO_MODE_DISABLED);
}
static void
_get_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{
uint16_t coarse, fine;
struct e1usb_gpsdo_tune tune;
gpsdo_get_tune(&coarse, &fine);
tune.coarse = coarse;
tune.fine = fine;
memcpy(xfer->data, &tune, sizeof(struct e1usb_gpsdo_tune));
xfer->len = sizeof(struct e1usb_gpsdo_tune);
}
static bool
_set_gpsdo_tune_done(struct usb_xfer *xfer)
{
const struct e1usb_gpsdo_tune *tune = (const void *) xfer->data;
gpsdo_set_tune(tune->coarse, tune->fine);
return true;
}
static void
_set_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{
xfer->cb_done = _set_gpsdo_tune_done;
xfer->cb_ctx = req;
xfer->len = sizeof(struct e1usb_gpsdo_tune);
}
static enum usb_fnd_resp static enum usb_fnd_resp
_usb_dev_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer) _usb_dev_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
{ {
@ -37,6 +93,21 @@ _usb_dev_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
xfer->data = (void*) fw_build_str; xfer->data = (void*) fw_build_str;
xfer->len = strlen(fw_build_str); xfer->len = strlen(fw_build_str);
break; break;
case ICE1USB_DEV_GET_GPSDO_STATUS:
_get_gpsdo_status(req, xfer);
break;
case ICE1USB_DEV_GET_GPSDO_MODE:
_get_gpsdo_mode(req, xfer);
break;
case ICE1USB_DEV_SET_GPSDO_MODE:
_set_gpsdo_mode(req, xfer);
break;
case ICE1USB_DEV_GET_GPSDO_TUNE:
_get_gpsdo_tune(req, xfer);
break;
case ICE1USB_DEV_SET_GPSDO_TUNE:
_set_gpsdo_tune(req, xfer);
break;
default: default:
return USB_FND_ERROR; return USB_FND_ERROR;
} }