mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-10-22 23:31:59 +00:00
zpu: Get basi GPSDO information and en/dis debug over the control socket.
This commit is contained in:
@@ -32,7 +32,7 @@ extern "C" {
|
||||
//fpga and firmware compatibility numbers
|
||||
#define USRP2_FPGA_COMPAT_NUM 9
|
||||
#define USRP2_FW_COMPAT_NUM 12
|
||||
#define USRP2_FW_VER_MINOR 2
|
||||
#define USRP2_FW_VER_MINOR 3
|
||||
|
||||
//used to differentiate control packets over data port
|
||||
#define USRP2_INVALID_VRT_HEADER 0
|
||||
@@ -127,8 +127,12 @@ typedef enum{
|
||||
|
||||
typedef enum{
|
||||
UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC = 1,
|
||||
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2
|
||||
/* GPSDO control to be here */
|
||||
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2,
|
||||
UMTRX_ZPU_REQUEST_SET_GPSDO_DEBUG = 3,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ = 4,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ_LPF = 5,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_PPS_SECS = 6,
|
||||
UMTRX_ZPU_REQUEST_SET_GPSDO_PPS_TICKS = 7
|
||||
} umtrx_zpu_action_t;
|
||||
|
||||
typedef struct{
|
||||
|
@@ -167,6 +167,21 @@ static void handle_udp_ctrl_packet(
|
||||
case UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC:
|
||||
gpsdo_set_dac((uint16_t)ctrl_data_in->data.zpu_action.data);
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_SET_GPSDO_DEBUG:
|
||||
gpsdo_set_debug((bool)ctrl_data_in->data.zpu_action.data);
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_freq();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ_LPF:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_lpf_freq();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_PPS_SECS:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_pps_secs();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_SET_GPSDO_PPS_TICKS:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_pps_ticks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@@ -47,4 +47,5 @@ SET(COMMON_SRCS
|
||||
${CMAKE_SOURCE_DIR}/lib/banal.c
|
||||
${CMAKE_SOURCE_DIR}/lib/udp_uart.c
|
||||
${CMAKE_SOURCE_DIR}/lib/gpsdo.c
|
||||
${CMAKE_SOURCE_DIR}/lib/time64.c
|
||||
)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include "u2_init.h"
|
||||
#include "pic.h"
|
||||
#include "spi.h"
|
||||
#include "time64.h"
|
||||
|
||||
#include "memory_map.h"
|
||||
|
||||
@@ -153,6 +154,9 @@ _gpsdo_pid_step(int32_t val)
|
||||
#define VAL_LPF_INIT_VALUE (PID_TARGET<<VAL_LPF_PRECISION)
|
||||
|
||||
static uint32_t g_val_lpf = VAL_LPF_INIT_VALUE;
|
||||
static uint32_t g_prev_secs = 0;
|
||||
static uint32_t g_prev_ticks = 0;
|
||||
static uint32_t g_last_calc_freq = 0; /* Last calculated VCTCXO frequency */
|
||||
|
||||
static void
|
||||
_gpsdo_irq_handler(unsigned irq)
|
||||
@@ -161,18 +165,21 @@ _gpsdo_irq_handler(unsigned irq)
|
||||
{
|
||||
/* Counter value */
|
||||
uint32_t val = gpsdo_regs->cnt;
|
||||
/* Read the current wall time */
|
||||
uint32_t cur_secs, cur_ticks;
|
||||
time64_read(&cur_secs, &cur_ticks);
|
||||
|
||||
/* Next request */
|
||||
gpsdo_regs->csr = GPSDO_CSR_REQ;
|
||||
|
||||
/* TODO:: Save the current wall time to be able check
|
||||
time passed since the last lock later. This is useful
|
||||
e.g. to check whether we still have a GPS lock.*/
|
||||
if (gpsdo_debug) printf("GPSDO: Counter = %u @ %u sec %u ticks\n", val, cur_secs, cur_ticks);
|
||||
|
||||
/* Check validity of value */
|
||||
if (abs(val - PID_TARGET) < 100000)
|
||||
{
|
||||
/* Save calculated frequency */
|
||||
g_last_calc_freq = val;
|
||||
|
||||
/* LPF the value */
|
||||
/* Integer overlow warning! */
|
||||
/* This works for val ~= 52M, but don't try to use it with much larger values - it will overflow */
|
||||
@@ -183,12 +190,19 @@ _gpsdo_irq_handler(unsigned irq)
|
||||
/* Update PID */
|
||||
_gpsdo_pid_step(g_val_lpf>>VAL_LPF_PRECISION);
|
||||
}
|
||||
|
||||
/* Save the current wall time */
|
||||
g_prev_secs = cur_secs;
|
||||
g_prev_ticks = cur_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gpsdo_init(void)
|
||||
{
|
||||
/* Set last saved freq to an invalid value */
|
||||
g_last_calc_freq = 0;
|
||||
|
||||
/* Set the DAC to mid value */
|
||||
_set_vctcxo_dac( PID_MID_VAL );
|
||||
|
||||
@@ -200,6 +214,15 @@ gpsdo_init(void)
|
||||
|
||||
/* Start request */
|
||||
gpsdo_regs->csr = GPSDO_CSR_REQ;
|
||||
|
||||
/* Save the current wall time.
|
||||
* We can use it to estimate time to lock */
|
||||
time64_read(&g_prev_secs, &g_prev_ticks);
|
||||
}
|
||||
|
||||
void gpsdo_set_debug(int level)
|
||||
{
|
||||
gpsdo_debug = level;
|
||||
}
|
||||
|
||||
void gpsdo_set_dac(uint16_t v)
|
||||
@@ -214,3 +237,23 @@ uint16_t gpsdo_get_dac(void)
|
||||
{
|
||||
return _get_vctcxo_dac();
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_freq(void)
|
||||
{
|
||||
return g_last_calc_freq;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_lpf_freq(void)
|
||||
{
|
||||
return g_val_lpf;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_pps_secs(void)
|
||||
{
|
||||
return g_prev_secs;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_pps_ticks(void)
|
||||
{
|
||||
return g_prev_ticks;
|
||||
}
|
||||
|
@@ -21,10 +21,25 @@
|
||||
|
||||
void gpsdo_init(void);
|
||||
|
||||
/* Enable/disable GPSDO debug printing */
|
||||
void gpsdo_set_debug(int level);
|
||||
|
||||
/* Set value of the VCTCXO DAC */
|
||||
void gpsdo_set_dac(uint16_t v);
|
||||
|
||||
/* Get the current VCTCXO DAC value */
|
||||
uint16_t gpsdo_get_dac(void);
|
||||
|
||||
/* Get the last calculated VCTCXO frequency */
|
||||
uint32_t gpsdo_get_last_freq(void);
|
||||
|
||||
/* Get the last alpha/8 filtered VCTCXO frequency (29.3 fixed point) */
|
||||
uint32_t gpsdo_get_lpf_freq(void);
|
||||
|
||||
/* Get time (seconds part) of the last PPS pulse */
|
||||
uint32_t gpsdo_get_last_pps_secs(void);
|
||||
|
||||
/* Get time (ticks part) of the last PPS pulse */
|
||||
uint32_t gpsdo_get_last_pps_ticks(void);
|
||||
|
||||
#endif /* INCLUDED_GPSDO_H */
|
||||
|
93
zpu/lib/time64.c
Normal file
93
zpu/lib/time64.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 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 "memory_map.h"
|
||||
|
||||
/* printf headers */
|
||||
//#include "nonstdio.h"
|
||||
|
||||
/* standard headers */
|
||||
#include <stddef.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#define UINT32_MAX UINT_MAX
|
||||
|
||||
void
|
||||
time64_read(uint32_t *secs, uint32_t *ticks)
|
||||
{
|
||||
uint32_t cur_secs, cur_secs2;
|
||||
|
||||
cur_secs = readback_mux->time64_secs_rb;
|
||||
*ticks = readback_mux->time64_ticks_rb;
|
||||
cur_secs2 = readback_mux->time64_secs_rb;
|
||||
|
||||
/* Check for seconds wrap */
|
||||
if (cur_secs2 != cur_secs) {
|
||||
/* Decide which seconds reading is correct.
|
||||
* Here we assume that we're reading fast and time between
|
||||
* two readings is negligible compared to a 32-bit counter
|
||||
* wrap time.
|
||||
*/
|
||||
if (*ticks < UINT32_MAX/2) {
|
||||
/* First half of the time - wrap has just happened */
|
||||
*secs = cur_secs2;
|
||||
} else {
|
||||
/* Second half - wrap has not happened yet */
|
||||
*secs = cur_secs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
time64_compare(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2)
|
||||
{
|
||||
if (secs1 == secs2) {
|
||||
if (ticks1 < ticks2) {
|
||||
return -1;
|
||||
} else if (ticks1 == ticks2) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (secs1 < secs2) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
time64_add_ticks(uint32_t *secs, uint32_t *ticks,
|
||||
uint32_t ticks2)
|
||||
{
|
||||
if (UINT32_MAX - *ticks > ticks2) {
|
||||
*secs += 1;
|
||||
}
|
||||
*ticks += ticks2;
|
||||
}
|
||||
|
||||
bool
|
||||
time64_is_elapsed(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2,
|
||||
uint32_t ticks_elapsed)
|
||||
{
|
||||
time64_add_ticks(&secs1, &ticks1, ticks_elapsed);
|
||||
return time64_compare(secs1, ticks1, secs2, ticks2) >= 0;
|
||||
}
|
42
zpu/lib/time64.h
Normal file
42
zpu/lib/time64.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 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/>.
|
||||
*/
|
||||
|
||||
/* Operations with time64 counters handling wrapping safely */
|
||||
|
||||
/* Read counters */
|
||||
void
|
||||
time64_read(uint32_t *secs, uint32_t *ticks);
|
||||
|
||||
/* Compare two counters.
|
||||
* Return -1 if conter 1 is less than counter 2.
|
||||
* Return 0 if conter 1 is equal counter 2.
|
||||
* Return 1 if conter 1 is larger than counter 2.
|
||||
*/
|
||||
int
|
||||
time64_compare(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2);
|
||||
|
||||
/* Add ticks to a counter */
|
||||
void
|
||||
time64_add_ticks(uint32_t *secs, uint32_t *ticks,
|
||||
uint32_t ticks2);
|
||||
|
||||
/* Is a given amount of ticks elapsed? */
|
||||
bool
|
||||
time64_is_elapsed(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2,
|
||||
uint32_t ticks_elapsed);
|
Reference in New Issue
Block a user