From 4bf91aa35f9bfd7b9d977dc1c06f2405704bad9c Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Nov 2024 19:30:36 -0600 Subject: [PATCH 1/5] making pio_calculate_clkdiv8_from_float round to the neareset 1/256 (not lower 1/256) --- src/rp2_common/hardware_pio/include/hardware/pio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index 40716dec9..5c76103d5 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -488,6 +488,7 @@ 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); + div += 0.5f / 256; // round to the nearest 1/256 *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 From 9ebaa646d8c77827e71e6091be3899a32260d385 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Nov 2024 19:50:48 -0600 Subject: [PATCH 2/5] 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)); } From 3a693bc235fc8c80940685f4aed1e2e86d49d282 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Nov 2024 19:54:55 -0600 Subject: [PATCH 3/5] fix copy/paste errors in PICO_CONFIG --- src/rp2040/pico_platform/include/pico/platform.h | 2 +- src/rp2350/pico_platform/include/pico/platform.h | 2 +- src/rp2_common/hardware_adc/include/hardware/adc.h | 2 +- src/rp2_common/hardware_clocks/include/hardware/clocks.h | 2 +- src/rp2_common/hardware_pio/include/hardware/pio.h | 2 +- src/rp2_common/hardware_pwm/include/hardware/pwm.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rp2040/pico_platform/include/pico/platform.h b/src/rp2040/pico_platform/include/pico/platform.h index 2b0d2ead5..47aa119a7 100644 --- a/src/rp2040/pico_platform/include/pico/platform.h +++ b/src/rp2040/pico_platform/include/pico/platform.h @@ -70,7 +70,7 @@ #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 +// 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 diff --git a/src/rp2350/pico_platform/include/pico/platform.h b/src/rp2350/pico_platform/include/pico/platform.h index 7cc05f462..24fec75bb 100644 --- a/src/rp2350/pico_platform/include/pico/platform.h +++ b/src/rp2350/pico_platform/include/pico/platform.h @@ -63,7 +63,7 @@ #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 +// 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 diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h index fe0ce55b4..0d53766be 100644 --- a/src/rp2_common/hardware_adc/include/hardware/adc.h +++ b/src/rp2_common/hardware_adc/include/hardware/adc.h @@ -70,7 +70,7 @@ #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 +// 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_adc #ifndef PICO_ADC_CLKDIV_ROUND_NEAREST #define PICO_ADC_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST #endif diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index e0f886d5c..43fb08e2b 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -255,7 +255,7 @@ extern "C" { #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 + // 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_clocks #ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST #define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST #endif diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index 4c9d79025..e8b16276a 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -32,7 +32,7 @@ #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 +// 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 diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h index f1e5a27db..e05ce26ff 100644 --- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h +++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h @@ -103,7 +103,7 @@ 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 +// 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_pwm #ifndef PICO_PWM_CLKDIV_ROUND_NEAREST #define PICO_PWM_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST #endif From c4c62568c1d009248e88e9cde74d753e385c3be6 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Wed, 20 Nov 2024 17:12:20 +0000 Subject: [PATCH 4/5] Calculate size of FRAC field using its own MSB and LSB, rather than hoping that INT_LSB is in the right place --- src/rp2_common/hardware_adc/include/hardware/adc.h | 2 +- src/rp2_common/hardware_pio/include/hardware/pio.h | 2 +- src/rp2_common/hardware_pwm/include/hardware/pwm.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h index 0d53766be..66fdeecc3 100644 --- a/src/rp2_common/hardware_adc/include/hardware/adc.h +++ b/src/rp2_common/hardware_adc/include/hardware/adc.h @@ -204,7 +204,7 @@ 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 + clkdiv += 0.5f / (1 << (ADC_DIV_FRAC_MSB + 1 - ADC_DIV_FRAC_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_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index e8b16276a..5fc354814 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -495,7 +495,7 @@ 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 + div += 0.5f / (1 << (PIO_SM0_CLKDIV_FRAC_MSB + 1 - PIO_SM0_CLKDIV_FRAC_LSB)); // 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 diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h index e05ce26ff..48c2673df 100644 --- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h +++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h @@ -161,7 +161,7 @@ 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 + div += 0.5f / (1 << (PWM_CH0_DIV_FRAC_MSB + 1 - PWM_CH0_DIV_FRAC_LSB)); // round to the nearest fraction #endif c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB)); } From 4b8488031c917d20dda88fd419dedfc79c2b92a6 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Wed, 20 Nov 2024 18:43:35 +0000 Subject: [PATCH 5/5] Add a new REG_FIELD_WIDTH macro, and make the calculation of the clock-dividers more consistent --- .../include/hardware/platform_defs.h | 2 ++ .../include/hardware/platform_defs.h | 2 ++ .../hardware_adc/include/hardware/adc.h | 7 ++++--- src/rp2_common/hardware_clocks/clocks.c | 8 ++++---- .../hardware_clocks/include/hardware/clocks.h | 11 ++++++----- .../hardware_pio/include/hardware/pio.h | 15 ++++++++------- .../hardware_pwm/include/hardware/pwm.h | 11 ++++++----- 7 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h index 54d9344c8..1d23b9d12 100644 --- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h @@ -116,4 +116,6 @@ #define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS) #define VTABLE_FIRST_IRQ 16 +#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB) + #endif diff --git a/src/rp2350/hardware_regs/include/hardware/platform_defs.h b/src/rp2350/hardware_regs/include/hardware/platform_defs.h index 6e5eba2f7..bd8b68a9f 100644 --- a/src/rp2350/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2350/hardware_regs/include/hardware/platform_defs.h @@ -160,4 +160,6 @@ #endif #define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS) +#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB) + #endif diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h index 66fdeecc3..40bdb3260 100644 --- a/src/rp2_common/hardware_adc/include/hardware/adc.h +++ b/src/rp2_common/hardware_adc/include/hardware/adc.h @@ -202,11 +202,12 @@ static inline void adc_run(bool run) { * \param clkdiv If non-zero, conversion will be started at intervals rather than back to back. */ static inline void adc_set_clkdiv(float clkdiv) { - invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1)); + invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << REG_FIELD_WIDTH(ADC_DIV_INT)); + const int frac_bit_count = REG_FIELD_WIDTH(ADC_DIV_FRAC); #if PICO_ADC_CLKDIV_ROUND_NEAREST - clkdiv += 0.5f / (1 << (ADC_DIV_FRAC_MSB + 1 - ADC_DIV_FRAC_LSB)); // round to the nearest fraction + clkdiv += 0.5f / (1 << frac_bit_count); // round to the nearest fraction #endif - adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB)); + adc_hw->div = (uint32_t)(clkdiv * (float) (1 << frac_bit_count)); } /*! \brief Setup the ADC FIFO diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 1800164f0..cd76c1354 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -245,13 +245,13 @@ void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t invalid_params_if(HARDWARE_CLOCKS, true); } - invalid_params_if(HARDWARE_CLOCKS, div_int >> (CLOCKS_CLK_GPOUT0_DIV_INT_MSB - CLOCKS_CLK_GPOUT0_DIV_INT_LSB + 1)); + invalid_params_if(HARDWARE_CLOCKS, div_int >> REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_INT)); // Set up the gpclk generator clocks_hw->clk[gpclk].ctrl = (src << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB) | CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS; -#if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15 +#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16 clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | (div_frac16 << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB); -#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7 +#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8 clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | ((div_frac16>>8u) << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB); #else #error unsupported number of fractional bits @@ -439,4 +439,4 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u } } return false; -} \ No newline at end of file +} diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 43fb08e2b..8fd50a20e 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -392,14 +392,15 @@ 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; + const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC); #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 + div += 0.5f / (1 << frac_bit_count); // 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)); +#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16 + uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count)); clock_gpio_init_int_frac16(gpio, src, div_int, frac); -#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7 - uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << 8)); +#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8 + uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count)); clock_gpio_init_int_frac8(gpio, src, div_int, frac); #else #error unsupported number of fractional bits diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index 5fc354814..30c919b36 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -478,10 +478,10 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool * \sa sm_config_set_clkdiv() */ static inline void sm_config_set_clkdiv_int_frac8(pio_sm_config *c, uint32_t div_int, uint8_t div_frac8) { - static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, ""); + static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, ""); invalid_params_if(HARDWARE_PIO, div_int >> 16); invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0); - static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, ""); + static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, ""); c->clkdiv = (((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) | (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB); @@ -494,17 +494,18 @@ 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); + const int frac_bit_count = REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC); #if PICO_PIO_CLKDIV_ROUND_NEAREST - div += 0.5f / (1 << (PIO_SM0_CLKDIV_FRAC_MSB + 1 - PIO_SM0_CLKDIV_FRAC_LSB)); // round to the nearest 1/256 + div += 0.5f / (1 << frac_bit_count); // 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 - static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, ""); + static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, ""); if (*div_int == 0) { *div_frac8 = 0; } else { - *div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << 8u)); + *div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << frac_bit_count)); } } @@ -1675,10 +1676,10 @@ void pio_sm_drain_tx_fifo(PIO pio, uint sm); static inline void pio_sm_set_clkdiv_int_frac8(PIO pio, uint sm, uint32_t div_int, uint8_t div_frac8) { check_pio_param(pio); check_sm_param(sm); - static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, ""); + static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, ""); invalid_params_if(HARDWARE_PIO, div_int >> 16); invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0); - static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, ""); + static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, ""); pio->sm[sm].clkdiv = (((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) | (((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB); diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h index 48c2673df..2dd6da8f7 100644 --- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h +++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h @@ -160,10 +160,11 @@ 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); + const int frac_bit_count = REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC); #if PICO_PWM_CLKDIV_ROUND_NEAREST - div += 0.5f / (1 << (PWM_CH0_DIV_FRAC_MSB + 1 - PWM_CH0_DIV_FRAC_LSB)); // round to the nearest fraction + div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction #endif - c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB)); + c->div = (uint32_t)(div * (float)(1u << frac_bit_count)); } /** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value @@ -178,9 +179,9 @@ static inline void pwm_config_set_clkdiv(pwm_config *c, float div) { * before passing them on to the PWM counter. */ static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) { - static_assert(PWM_CH0_DIV_INT_MSB - PWM_CH0_DIV_INT_LSB == 7, ""); + static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_INT) == 8, ""); valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256); - static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, ""); + static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, ""); valid_params_if(HARDWARE_PWM, div_frac4 < 16); c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB); } @@ -447,7 +448,7 @@ static inline void pwm_retard_count(uint slice_num) { static inline void pwm_set_clkdiv_int_frac4(uint slice_num, uint8_t div_int, uint8_t div_frac4) { check_slice_num_param(slice_num); valid_params_if(HARDWARE_PWM, div_int >= 1); - static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, ""); + static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, ""); valid_params_if(HARDWARE_PWM, div_frac4 < 16); pwm_hw->slice[slice_num].div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB); }