From 9ebaa646d8c77827e71e6091be3899a32260d385 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Nov 2024 19:50:48 -0600 Subject: [PATCH] chage rounding of all float clkdivs to round to neareset; default to nearest (which is a backwards incompatible change, but I think OK), and add ability to turn it off --- src/rp2040/pico_platform/include/pico/platform.h | 5 +++++ src/rp2350/pico_platform/include/pico/platform.h | 5 +++++ src/rp2_common/hardware_adc/include/hardware/adc.h | 8 ++++++++ src/rp2_common/hardware_clocks/include/hardware/clocks.h | 8 ++++++++ src/rp2_common/hardware_pio/include/hardware/pio.h | 8 ++++++++ src/rp2_common/hardware_pwm/include/hardware/pwm.h | 8 ++++++++ 6 files changed, 42 insertions(+) diff --git a/src/rp2040/pico_platform/include/pico/platform.h b/src/rp2040/pico_platform/include/pico/platform.h index c1f9ad330..2b0d2ead5 100644 --- a/src/rp2040/pico_platform/include/pico/platform.h +++ b/src/rp2040/pico_platform/include/pico/platform.h @@ -70,6 +70,11 @@ #define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS) #endif +// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group-pico_platform +#ifndef PICO_CLKDIV_ROUND_NEAREST +#define PICO_CLKDIV_ROUND_NEAREST 1 +#endif + #ifndef __ASSEMBLER__ /*! \brief No-op function for the body of tight loops diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h index bfc4fabe6..7cc05f462 100644 --- a/src/rp2350/pico_platform/include/pico/platform.h +++ b/src/rp2350/pico_platform/include/pico/platform.h @@ -63,6 +63,11 @@ #define PICO_USE_STACK_GUARDS 0 #endif +// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group-pico_platform +#ifndef PICO_CLKDIV_ROUND_NEAREST +#define PICO_CLKDIV_ROUND_NEAREST 1 +#endif + #ifndef __ASSEMBLER__ /*! \brief No-op function for the body of tight loops diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h index 095a3f5b8..fe0ce55b4 100644 --- a/src/rp2_common/hardware_adc/include/hardware/adc.h +++ b/src/rp2_common/hardware_adc/include/hardware/adc.h @@ -70,6 +70,11 @@ #define ADC_TEMPERATURE_CHANNEL_NUM (NUM_ADC_CHANNELS - 1) #endif +// PICO_CONFIG: PICO_ADC_CLKDIV_ROUND_NEAREST, True if floating point ADC clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group-hardware_pio +#ifndef PICO_ADC_CLKDIV_ROUND_NEAREST +#define PICO_ADC_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST +#endif + #ifdef __cplusplus extern "C" { #endif @@ -198,6 +203,9 @@ static inline void adc_run(bool run) { */ static inline void adc_set_clkdiv(float clkdiv) { invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1)); +#if PICO_ADC_CLKDIV_ROUND_NEAREST + clkdiv += 0.5f / (1 << ADC_DIV_INT_LSB); // round to the nearest fraction +#endif adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB)); } diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index cd8acfa3c..e0f886d5c 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -253,6 +253,11 @@ extern "C" { #else #define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0 #endif +#endif + + // PICO_CONFIG: PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST, True if floating point GPIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group-hardware_pio +#ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST +#define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST #endif typedef clock_num_t clock_handle_t; @@ -387,6 +392,9 @@ static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_in static inline void clock_gpio_init(uint gpio, uint src, float div) { uint div_int = (uint)div; +#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST + div += 0.5f / (1 << (CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB + 1 - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB)); // round to the nearest fraction +#endif #if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15 uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << 16)); clock_gpio_init_int_frac16(gpio, src, div_int, frac); diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index 5c76103d5..4c9d79025 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -31,6 +31,12 @@ #define PICO_PIO_VERSION 0 #endif #endif + +// PICO_CONFIG: PICO_PIO_CLKDIV_ROUND_NEAREST, True if floating point PIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group-hardware_pio +#ifndef PICO_PIO_CLKDIV_ROUND_NEAREST +#define PICO_PIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST +#endif + /** \file hardware/pio.h * \defgroup hardware_pio hardware_pio * @@ -488,7 +494,9 @@ static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_ static inline void pio_calculate_clkdiv8_from_float(float div, uint32_t *div_int, uint8_t *div_frac8) { valid_params_if(HARDWARE_PIO, div >= 1 && div <= 65536); +#if PICO_PIO_CLKDIV_ROUND_NEAREST div += 0.5f / 256; // round to the nearest 1/256 +#endif *div_int = (uint16_t)div; // not a strictly necessary check, but if this changes, then this method should // probably no longer be used in favor of one with a larger fraction diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h index cce5464f7..f1e5a27db 100644 --- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h +++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h @@ -103,6 +103,11 @@ static_assert(DREQ_PWM_WRAP7 == DREQ_PWM_WRAP0 + 7, ""); }) #endif +// PICO_CONFIG: PICO_PWM_CLKDIV_ROUND_NEAREST, True if floating point PWM clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group-hardware_pio +#ifndef PICO_PWM_CLKDIV_ROUND_NEAREST +#define PICO_PWM_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST +#endif + static inline void check_slice_num_param(__unused uint slice_num) { valid_params_if(HARDWARE_PWM, slice_num < NUM_PWM_SLICES); } @@ -155,6 +160,9 @@ static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correc */ static inline void pwm_config_set_clkdiv(pwm_config *c, float div) { valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f); +#if PICO_PWM_CLKDIV_ROUND_NEAREST + div += 0.5f / (1 << PWM_CH0_DIV_INT_LSB); // round to the nearest fraction +#endif c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB)); }