Skip to content

Commit 87255fb

Browse files
committed
Add a new field_width macro, and make the calculation of the clock-dividers more consistent
1 parent c4c6256 commit 87255fb

File tree

6 files changed

+30
-24
lines changed
  • src
    • common/pico_base_headers/include/pico
    • rp2_common

6 files changed

+30
-24
lines changed

src/common/pico_base_headers/include/pico/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,7 @@ typedef struct {
117117

118118
#define bool_to_bit(x) ((uint)!!(x))
119119

120+
#define field_width(f) (f ## _MSB + 1 - f ## _LSB)
121+
120122
#endif
121123
#endif

src/rp2_common/hardware_adc/include/hardware/adc.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,12 @@ static inline void adc_run(bool run) {
202202
* \param clkdiv If non-zero, conversion will be started at intervals rather than back to back.
203203
*/
204204
static inline void adc_set_clkdiv(float clkdiv) {
205-
invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1));
205+
invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << field_width(ADC_DIV_INT));
206+
const int frac_bit_count = field_width(ADC_DIV_FRAC);
206207
#if PICO_ADC_CLKDIV_ROUND_NEAREST
207-
clkdiv += 0.5f / (1 << (ADC_DIV_FRAC_MSB + 1 - ADC_DIV_FRAC_LSB)); // round to the nearest fraction
208+
clkdiv += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
208209
#endif
209-
adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB));
210+
adc_hw->div = (uint32_t)(clkdiv * (float) (1 << frac_bit_count));
210211
}
211212

212213
/*! \brief Setup the ADC FIFO

src/rp2_common/hardware_clocks/clocks.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,13 @@ void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t
245245
invalid_params_if(HARDWARE_CLOCKS, true);
246246
}
247247

248-
invalid_params_if(HARDWARE_CLOCKS, div_int >> (CLOCKS_CLK_GPOUT0_DIV_INT_MSB - CLOCKS_CLK_GPOUT0_DIV_INT_LSB + 1));
248+
invalid_params_if(HARDWARE_CLOCKS, div_int >> field_width(CLOCKS_CLK_GPOUT0_DIV_INT));
249249
// Set up the gpclk generator
250250
clocks_hw->clk[gpclk].ctrl = (src << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB) |
251251
CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS;
252-
#if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15
252+
#if field_width(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
253253
clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | (div_frac16 << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
254-
#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7
254+
#elif field_width(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
255255
clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | ((div_frac16>>8u) << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
256256
#else
257257
#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
439439
}
440440
}
441441
return false;
442-
}
442+
}

src/rp2_common/hardware_clocks/include/hardware/clocks.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,15 @@ static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_in
392392
static inline void clock_gpio_init(uint gpio, uint src, float div)
393393
{
394394
uint div_int = (uint)div;
395+
const int frac_bit_count = field_width(CLOCKS_CLK_GPOUT0_DIV_FRAC);
395396
#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
396-
div += 0.5f / (1 << (CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB + 1 - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB)); // round to the nearest fraction
397+
div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
397398
#endif
398-
#if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15
399-
uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << 16));
399+
#if field_width(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
400+
uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
400401
clock_gpio_init_int_frac16(gpio, src, div_int, frac);
401-
#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7
402-
uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << 8));
402+
#elif field_width(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
403+
uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
403404
clock_gpio_init_int_frac8(gpio, src, div_int, frac);
404405
#else
405406
#error unsupported number of fractional bits

src/rp2_common/hardware_pio/include/hardware/pio.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,10 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool
478478
* \sa sm_config_set_clkdiv()
479479
*/
480480
static inline void sm_config_set_clkdiv_int_frac8(pio_sm_config *c, uint32_t div_int, uint8_t div_frac8) {
481-
static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, "");
481+
static_assert(field_width(PIO_SM0_CLKDIV_INT) == 16, "");
482482
invalid_params_if(HARDWARE_PIO, div_int >> 16);
483483
invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
484-
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
484+
static_assert(field_width(PIO_SM0_CLKDIV_FRAC) == 8, "");
485485
c->clkdiv =
486486
(((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
487487
(((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_
494494

495495
static inline void pio_calculate_clkdiv8_from_float(float div, uint32_t *div_int, uint8_t *div_frac8) {
496496
valid_params_if(HARDWARE_PIO, div >= 1 && div <= 65536);
497+
const int frac_bit_count = field_width(PIO_SM0_CLKDIV_FRAC);
497498
#if PICO_PIO_CLKDIV_ROUND_NEAREST
498-
div += 0.5f / (1 << (PIO_SM0_CLKDIV_FRAC_MSB + 1 - PIO_SM0_CLKDIV_FRAC_LSB)); // round to the nearest 1/256
499+
div += 0.5f / (1 << frac_bit_count); // round to the nearest 1/256
499500
#endif
500501
*div_int = (uint16_t)div;
501502
// not a strictly necessary check, but if this changes, then this method should
502503
// probably no longer be used in favor of one with a larger fraction
503-
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
504+
static_assert(field_width(PIO_SM0_CLKDIV_FRAC) == 8, "");
504505
if (*div_int == 0) {
505506
*div_frac8 = 0;
506507
} else {
507-
*div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << 8u));
508+
*div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << frac_bit_count));
508509
}
509510
}
510511

@@ -1675,10 +1676,10 @@ void pio_sm_drain_tx_fifo(PIO pio, uint sm);
16751676
static inline void pio_sm_set_clkdiv_int_frac8(PIO pio, uint sm, uint32_t div_int, uint8_t div_frac8) {
16761677
check_pio_param(pio);
16771678
check_sm_param(sm);
1678-
static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, "");
1679+
static_assert(field_width(PIO_SM0_CLKDIV_INT) == 16, "");
16791680
invalid_params_if(HARDWARE_PIO, div_int >> 16);
16801681
invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
1681-
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
1682+
static_assert(field_width(PIO_SM0_CLKDIV_FRAC) == 8, "");
16821683
pio->sm[sm].clkdiv =
16831684
(((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
16841685
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);

src/rp2_common/hardware_pwm/include/hardware/pwm.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,11 @@ static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correc
160160
*/
161161
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
162162
valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f);
163+
const int frac_bit_count = field_width(PWM_CH0_DIV_FRAC);
163164
#if PICO_PWM_CLKDIV_ROUND_NEAREST
164-
div += 0.5f / (1 << (PWM_CH0_DIV_FRAC_MSB + 1 - PWM_CH0_DIV_FRAC_LSB)); // round to the nearest fraction
165+
div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
165166
#endif
166-
c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB));
167+
c->div = (uint32_t)(div * (float)(1u << frac_bit_count));
167168
}
168169

169170
/** \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) {
178179
* before passing them on to the PWM counter.
179180
*/
180181
static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) {
181-
static_assert(PWM_CH0_DIV_INT_MSB - PWM_CH0_DIV_INT_LSB == 7, "");
182+
static_assert(field_width(PWM_CH0_DIV_INT) == 8, "");
182183
valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256);
183-
static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, "");
184+
static_assert(field_width(PWM_CH0_DIV_FRAC) == 4, "");
184185
valid_params_if(HARDWARE_PWM, div_frac4 < 16);
185186
c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
186187
}
@@ -447,7 +448,7 @@ static inline void pwm_retard_count(uint slice_num) {
447448
static inline void pwm_set_clkdiv_int_frac4(uint slice_num, uint8_t div_int, uint8_t div_frac4) {
448449
check_slice_num_param(slice_num);
449450
valid_params_if(HARDWARE_PWM, div_int >= 1);
450-
static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, "");
451+
static_assert(field_width(PWM_CH0_DIV_FRAC) == 4, "");
451452
valid_params_if(HARDWARE_PWM, div_frac4 < 16);
452453
pwm_hw->slice[slice_num].div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
453454
}

0 commit comments

Comments
 (0)