From f4f02a51c0c1b0150b4a1d726802f63aa5e2bb28 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 27 Jul 2017 01:18:28 +0300 Subject: [PATCH] zpu: Get basi GPSDO information and en/dis debug over the control socket. --- host/usrp2/fw_common.h | 10 +++-- zpu/apps/txrx_uhd.c | 15 +++++++ zpu/lib/CMakeLists.txt | 1 + zpu/lib/gpsdo.c | 49 ++++++++++++++++++++-- zpu/lib/gpsdo.h | 15 +++++++ zpu/lib/time64.c | 93 ++++++++++++++++++++++++++++++++++++++++++ zpu/lib/time64.h | 42 +++++++++++++++++++ 7 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 zpu/lib/time64.c create mode 100644 zpu/lib/time64.h diff --git a/host/usrp2/fw_common.h b/host/usrp2/fw_common.h index 6d54cea7..5164cc55 100644 --- a/host/usrp2/fw_common.h +++ b/host/usrp2/fw_common.h @@ -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{ diff --git a/zpu/apps/txrx_uhd.c b/zpu/apps/txrx_uhd.c index 1c4960dd..e7afa722 100644 --- a/zpu/apps/txrx_uhd.c +++ b/zpu/apps/txrx_uhd.c @@ -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; diff --git a/zpu/lib/CMakeLists.txt b/zpu/lib/CMakeLists.txt index a70f8a52..06c5d26c 100644 --- a/zpu/lib/CMakeLists.txt +++ b/zpu/lib/CMakeLists.txt @@ -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 ) diff --git a/zpu/lib/gpsdo.c b/zpu/lib/gpsdo.c index 855cf78f..f96e9a98 100644 --- a/zpu/lib/gpsdo.c +++ b/zpu/lib/gpsdo.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<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; +} diff --git a/zpu/lib/gpsdo.h b/zpu/lib/gpsdo.h index bc6a045a..7891d1a2 100644 --- a/zpu/lib/gpsdo.h +++ b/zpu/lib/gpsdo.h @@ -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 */ diff --git a/zpu/lib/time64.c b/zpu/lib/time64.c new file mode 100644 index 00000000..26ad4997 --- /dev/null +++ b/zpu/lib/time64.c @@ -0,0 +1,93 @@ +/* + * Copyright 2017 Alexander Chemeris + * + * 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 . + */ + +#include "memory_map.h" + +/* printf headers */ +//#include "nonstdio.h" + +/* standard headers */ +#include +//#include +//#include +#include +#include +#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; +} diff --git a/zpu/lib/time64.h b/zpu/lib/time64.h new file mode 100644 index 00000000..a5670a71 --- /dev/null +++ b/zpu/lib/time64.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexander Chemeris + * + * 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 . + */ + +/* 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);