Tweaks to PIO clkdiv-setting code (#254)
- refactor to reduce duplication - add extra param-validation
This commit is contained in:
parent
a47d6d6e14
commit
0c941d9767
@ -196,29 +196,6 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool
|
||||
(bool_to_bit(pindirs) << PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB);
|
||||
}
|
||||
|
||||
/*! \brief Set the state machine clock divider (from a floating point value) in a state machine configuration
|
||||
* \ingroup sm_config
|
||||
*
|
||||
* The clock divider slows the state machine's execution by masking the
|
||||
* system clock on some cycles, in a repeating pattern, so that the state
|
||||
* machine does not advance. Effectively this produces a slower clock for the
|
||||
* state machine to run from, which can be used to generate e.g. a particular
|
||||
* UART baud rate. See the datasheet for further detail.
|
||||
*
|
||||
* \param c Pointer to the configuration structure to modify
|
||||
* \param div The fractional divisor to be set. 1 for full speed. An integer clock divisor of n
|
||||
* will cause the state machine to run 1 cycle in every n.
|
||||
* Note that for small n, the jitter introduced by a fractional divider (e.g. 2.5) may be unacceptable
|
||||
* although it will depend on the use case.
|
||||
*/
|
||||
static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
|
||||
uint div_int = (uint)div;
|
||||
uint div_frac = (uint)((div - (float)div_int) * (1u << 8u));
|
||||
c->clkdiv =
|
||||
(div_frac << PIO_SM0_CLKDIV_FRAC_LSB) |
|
||||
(div_int << PIO_SM0_CLKDIV_INT_LSB);
|
||||
}
|
||||
|
||||
/*! \brief Set the state machine clock divider (from integer and fractional parts - 16:8) in a state machine configuration
|
||||
* \ingroup sm_config
|
||||
*
|
||||
@ -238,6 +215,38 @@ static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_
|
||||
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
|
||||
}
|
||||
|
||||
static inline void pio_calculate_clkdiv_from_float(float div, uint16_t *div_int, uint8_t *div_frac) {
|
||||
valid_params_if(PIO, div >= 1 && div <= 65536);
|
||||
*div_int = (uint16_t)div;
|
||||
if (*div_int == 0) {
|
||||
*div_frac = 0;
|
||||
} else {
|
||||
*div_frac = (uint8_t)((div - (float)*div_int) * (1u << 8u));
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Set the state machine clock divider (from a floating point value) in a state machine configuration
|
||||
* \ingroup sm_config
|
||||
*
|
||||
* The clock divider slows the state machine's execution by masking the
|
||||
* system clock on some cycles, in a repeating pattern, so that the state
|
||||
* machine does not advance. Effectively this produces a slower clock for the
|
||||
* state machine to run from, which can be used to generate e.g. a particular
|
||||
* UART baud rate. See the datasheet for further detail.
|
||||
*
|
||||
* \param c Pointer to the configuration structure to modify
|
||||
* \param div The fractional divisor to be set. 1 for full speed. An integer clock divisor of n
|
||||
* will cause the state machine to run 1 cycle in every n.
|
||||
* Note that for small n, the jitter introduced by a fractional divider (e.g. 2.5) may be unacceptable
|
||||
* although it will depend on the use case.
|
||||
*/
|
||||
static inline void sm_config_set_clkdiv(pio_sm_config *c, float div) {
|
||||
uint16_t div_int;
|
||||
uint8_t div_frac;
|
||||
pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
|
||||
sm_config_set_clkdiv_int_frac(c, div_int, div_frac);
|
||||
}
|
||||
|
||||
/*! \brief Set the wrap addresses in a state machine configuration
|
||||
* \ingroup sm_config
|
||||
*
|
||||
@ -978,23 +987,6 @@ static inline uint32_t pio_sm_get_blocking(PIO pio, uint sm) {
|
||||
*/
|
||||
void pio_sm_drain_tx_fifo(PIO pio, uint sm);
|
||||
|
||||
/*! \brief set the current clock divider for a state machine
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param sm State machine index (0..3)
|
||||
* \param div the floating point clock divider
|
||||
*/
|
||||
static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
uint div_int = (uint16_t) div;
|
||||
uint div_frac = (uint8_t) ((div - (float)div_int) * (1u << 8u));
|
||||
pio->sm[sm].clkdiv =
|
||||
(div_frac << PIO_SM0_CLKDIV_FRAC_LSB) |
|
||||
(div_int << PIO_SM0_CLKDIV_INT_LSB);
|
||||
}
|
||||
|
||||
/*! \brief set the current clock divider for a state machine using a 16:8 fraction
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
@ -1011,6 +1003,22 @@ static inline void pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int
|
||||
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
|
||||
}
|
||||
|
||||
/*! \brief set the current clock divider for a state machine
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param sm State machine index (0..3)
|
||||
* \param div the floating point clock divider
|
||||
*/
|
||||
static inline void pio_sm_set_clkdiv(PIO pio, uint sm, float div) {
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
uint16_t div_int;
|
||||
uint8_t div_frac;
|
||||
pio_calculate_clkdiv_from_float(div, &div_int, &div_frac);
|
||||
pio_sm_set_clkdiv_int_frac(pio, sm, div_int, div_frac);
|
||||
}
|
||||
|
||||
/*! \brief Clear a state machine's TX and RX FIFOs
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user