From e0ca48aacb73208de2aecf18b6f3a1bdf3f597f6 Mon Sep 17 00:00:00 2001 From: roman Date: Sun, 10 Dec 2023 03:56:26 +0300 Subject: [PATCH] it is working up to ~30.5M freq. so far no tight tests though. --- CMakeLists.txt | 9 ++- piodco/dco2.pio | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ piodco/piodco.c | 40 +++++++++++++- piodco/piodco.h | 1 + test.c | 23 ++++++-- 5 files changed, 203 insertions(+), 13 deletions(-) create mode 100644 piodco/dco2.pio diff --git a/CMakeLists.txt b/CMakeLists.txt index e5e6686..cb305a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_BUILD_TYPE "Release") set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) +# set(CMAKE_CXX_STANDARD 17) # Initialise pico_sdk from installed location # (note this can come from environment, CMake cache etc) @@ -22,13 +22,13 @@ project(pico-hf-oscillator-test C CXX ASM) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() - +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Og") add_executable(pico-hf-oscillator-test) -pico_generate_pio_header(pico-hf-oscillator-test ${CMAKE_CURRENT_LIST_DIR}/piodco/dco.pio) +pico_generate_pio_header(pico-hf-oscillator-test ${CMAKE_CURRENT_LIST_DIR}/piodco/dco2.pio) target_sources(pico-hf-oscillator-test PUBLIC - ${CMAKE_CURRENT_LIST_DIR}/lib/assert.c + ${CMAKE_CURRENT_LIST_DIR}/lib/assert.c ${CMAKE_CURRENT_LIST_DIR}/lib/thirdparty/strnstr.c ${CMAKE_CURRENT_LIST_DIR}/piodco/piodco.c ${CMAKE_CURRENT_LIST_DIR}/gpstime/GPStime.c @@ -60,7 +60,6 @@ target_link_libraries( hardware_timer hardware_clocks hardware_pio - #hardware_vreg ) pico_add_extra_outputs(pico-hf-oscillator-test) diff --git a/piodco/dco2.pio b/piodco/dco2.pio new file mode 100644 index 0000000..68b5914 --- /dev/null +++ b/piodco/dco2.pio @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Roman Piksaykin [piksaykin@gmail.com], R2BDY +// https://www.qrz.com/db/r2bdy +// +/////////////////////////////////////////////////////////////////////////////// +// +// +// dco2.pio Digital controlled radio freq oscillator based on PIO. +// +// +// DESCRIPTION +// - +// +// PLATFORM +// Raspberry Pi pico. +// +// REVISION HISTORY +// +// Rev 2.0 09 Dec 2023 +// New algo devising. +// +// LICENCE +// MIT License (http://www.opensource.org/licenses/mit-license.php) +// +// Copyright (c) 2023 by Roman Piksaykin +// +// Permission is hereby granted, free of charge,to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction,including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +/////////////////////////////////////////////////////////////////////////////// +.program dco + +.wrap_target + out y, 32 + mov x, y +LOOP0: + jmp x-- LOOP0 + set pins, 1 + + mov x, y [1] +LOOP1: + jmp x-- LOOP1 + set pins, 0 + + mov x, y [1] +LOOP2: + jmp x-- LOOP2 + set pins, 1 + + mov x, y [1] +LOOP3: + jmp x-- LOOP3 + set pins, 0 +.wrap + +/* +// it is OK for ~20.5M +.wrap_target + out y, 32 + mov x, y +LOOP0: + jmp x-- LOOP0 + set pins, 1 + + mov x, y [1] +LOOP1: + jmp x-- LOOP1 + set pins, 0 +.wrap +*/ +/* +.wrap_target + // CYCLES COUNT + out y, 8 // 1. +LOOP0: + jmp y-- LOOP0 // 2 + y0. + set pins, 1 // 1 * PI 3 + y0. + + out y, 8 // 4 + y0. +LOOP1: + jmp y-- LOOP1 // 5 + y0 + y1. + set pins, 0 // 2 * PI 6 + y0 + y1. + // 6 cycles min.=> 270MHz / 6 = 45MHz (VHF low-band). + // 3rd harmonic is 135M. + // 5th is 225M. + // 7th is 315M. +.wrap +*/ + +% c-sdk { + +#define PIOASM_DELAY_CYCLES 4 + +static inline void dco_program_init(PIO pio, uint sm, uint offset, uint pin) +{ + pio_sm_config c = dco_program_get_default_config(offset); + + sm_config_set_out_shift(&c, true, true, 32); // Autopull. + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + sm_config_set_out_pins(&c, pin, 1); + pio_gpio_init(pio, pin); + + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + + sm_config_set_clkdiv_int_frac(&c, 1u, 0u); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +// +static inline void dco_program_puts(PIO pio, uint sm, const uint32_t *s) +{ + pio_sm_put_blocking(pio, sm, s[0]); + pio_sm_put_blocking(pio, sm, s[1]); + pio_sm_put_blocking(pio, sm, s[2]); + pio_sm_put_blocking(pio, sm, s[3]); + pio_sm_put_blocking(pio, sm, s[4]); + pio_sm_put_blocking(pio, sm, s[5]); + pio_sm_put_blocking(pio, sm, s[6]); + pio_sm_put_blocking(pio, sm, s[7]); +} + +static inline void dco_program_puts1w(PIO pio, uint sm, const uint32_t val) +{ + pio_sm_put_blocking(pio, sm, val); +} +%} diff --git a/piodco/piodco.c b/piodco/piodco.c index fc2170e..a8560cd 100644 --- a/piodco/piodco.c +++ b/piodco/piodco.c @@ -67,7 +67,7 @@ #include #include "../lib/assert.h" -#include "build/dco.pio.h" +#include "build/dco2.pio.h" int32_t si32precise_cycles; /* External in order to support ISR. */ @@ -89,11 +89,16 @@ int PioDCOInit(PioDco *pdco, int gpio, int cpuclkhz) pdco->_offset = pio_add_program(pdco->_pio, &dco_program); pdco->_ism = pio_claim_unused_sm(pdco->_pio, true); + gpio_init(pdco->_gpio); + pio_gpio_init(pdco->_pio, pdco->_gpio); + dco_program_init(pdco->_pio, pdco->_ism, pdco->_offset, pdco->_gpio); pdco->_pio_sm = dco_program_get_default_config(pdco->_offset); + sm_config_set_out_shift(&pdco->_pio_sm, true, true, 32); // Autopull. + sm_config_set_fifo_join(&pdco->_pio_sm, PIO_FIFO_JOIN_TX); sm_config_set_set_pins(&pdco->_pio_sm, pdco->_gpio, 1); - pio_gpio_init(pdco->_pio, pdco->_gpio); + pio_sm_init(pdco->_pio, pdco->_ism, pdco->_offset, &pdco->_pio_sm); return 0; @@ -169,6 +174,37 @@ void PioDCOStop(PioDco *pdco) pio_sm_set_enabled(pdco->_pio, pdco->_ism, false); } +void RAM (PioDCOWorker2)(PioDco *pDCO) +{ + register PIO pio = pDCO->_pio; + register uint sm = pDCO->_ism; + register int32_t i32acc_error = 0; + const int32_t ui32_frq_hz = 30455133; + const int64_t i64denominator = 2000LL * (int64_t)ui32_frq_hz; + pDCO->_frq_cycles_per_pi = (int32_t)(((int64_t)pDCO->_clkfreq_hz * (int64_t)(1<<24) * 1000LL + +(i64denominator>>1)) / i64denominator); + const register uint32_t i32reg = pDCO->_frq_cycles_per_pi - (4<<24); + + register uint32_t i32wc; + //const register uint32_t i23left = 8388608U; +LOOP: + + i32wc = i32reg; + i32wc -= i32acc_error; + //i32wc += i23left; + i32wc >>= 24U; + pio_sm_put_blocking(pio, sm, i32wc); + i32wc <<= 24U; + i32acc_error += i32wc - i32reg; + + //const int32_t i32wc2 = iSAR32(i32reg - i32acc_error + (1<<23), 24); + //i32acc_error += (i32wc2<<24) - i32reg; + + //pio_sm_put_blocking(pio, sm, i32wc - 4); + + goto LOOP; +} + /// @brief Main worker task of DCO. It is time critical, so it ought to be run on /// @brief the dedicated pi pico core. /// @param pDCO Ptr to DCO context. diff --git a/piodco/piodco.h b/piodco/piodco.h index 27c94c6..6f967c9 100644 --- a/piodco/piodco.h +++ b/piodco/piodco.h @@ -111,5 +111,6 @@ void PioDCOStop(PioDco *pdco); void PioDCOSetMode(PioDco *pdco, enum PioDcoMode emode); void RAM (PioDCOWorker)(PioDco *pDCO); +void RAM (PioDCOWorker2)(PioDco *pDCO); #endif diff --git a/test.c b/test.c index e79bd71..d8e462b 100644 --- a/test.c +++ b/test.c @@ -73,7 +73,7 @@ #include "defines.h" #include "piodco/piodco.h" -#include "build/dco.pio.h" +#include "build/dco2.pio.h" #include "hardware/vreg.h" #include "pico/multicore.h" #include "pico/stdio/driver.h" @@ -84,7 +84,7 @@ #include -#define GEN_FRQ_HZ 9400000L +#define GEN_FRQ_HZ 10000000L PioDco DCO; /* External in order to access in both cores. */ @@ -93,7 +93,7 @@ PioDco DCO; /* External in order to access in both cores. */ void core1_entry() { const uint32_t clkhz = PLL_SYS_MHZ * 1000000L; - const uint32_t freq_hz = GEN_FRQ_HZ; + //const uint32_t freq_hz = GEN_FRQ_HZ; /* Initialize DCO */ assert_(0 == PioDCOInit(&DCO, 6, clkhz)); @@ -102,10 +102,10 @@ void core1_entry() PioDCOStart(&DCO); /* Set initial freq. */ - assert_(0 == PioDCOSetFreq(&DCO, freq_hz, 0u)); + //assert_(0 == PioDCOSetFreq(&DCO, freq_hz, 0u)); /* Run the main DCO algorithm. It spins forever. */ - PioDCOWorker(&DCO); + PioDCOWorker2(&DCO); } void RAM (SpinnerMFSKTest)(void) @@ -251,6 +251,15 @@ void RAM (SpinnerGPSreferenceTest)(void) } } +void RAM (SpinnerDummyTest)(void) +{ + for(;;) + { + tight_loop_contents(); + //PioDCOSetFreq(&DCO, GEN_FRQ_HZ, 0u); + } +} + int main() { const uint32_t clkhz = PLL_SYS_MHZ * 1000000L; @@ -265,11 +274,13 @@ int main() multicore_launch_core1(core1_entry); + SpinnerDummyTest(); + //SpinnerSweepTest(); //SpinnerMFSKTest(); //SpinnerRTTYTest(); //SpinnerMilliHertzTest(); //SpinnerWide4FSKTest(); - SpinnerGPSreferenceTest(); + //SpinnerGPSreferenceTest(); }