modm API documentation
|
Classes | |
class | modm::GenericPrescaler< T > |
class | modm::GenericPrescalerCounter< T > |
Functions | |
template<typename T , typename TIter = decltype(std::begin(std::declval<T>())), typename = decltype(std::end(std::declval<T>()))> | |
constexpr auto | modm::enumerate (T &&iterable) |
template<typename T > | |
constexpr detail::Range< T > | modm::range (const T &stop) |
template<typename T > | |
constexpr detail::Range< T > | modm::range (const T &start, const T &stop) |
template<typename T > | |
constexpr detail::Range< T > | modm::range (const T &start, const T &stop, const T &step) |
lbuild module: modm:math:algorithm
A collection of useful and lightweight algorithms.
Inspired by Python's built-in range
and enumerate
functions, you can use modm::range
and modm::enumerate
in for loops:
Peripheral output frequencies are usually generated by dividing an input clock with a prescaler in hardware. Finding the closest prescaler value for a desired output frequency can be unintuitive, therefore, these classes provide a simple interface for a constexpr calculator.
All calculators return a Result
struct containing desired, input, and output frequencies, the relative error of the output vs desired frequency, and the prescaler and its index. The prescaler index is typically the value to write to the register directly:
The index is particularly useful for non-contiguous prescalers, the most common being power-of-two values:
Non-contiguous prescalers can also be created with a modifier function:
For all other cases, prescalers can be passed as an initializer list or as any forward range. Note that the prescaler values must be sorted, otherwise the calculator will compute the wrong prescaler values!
A special case is made of two chained prescalers that are both linear powers-of-two. These are often called "fractional prescalers" and act as a single binary-scaled linear prescaler and can thus be modeled as such:
However, often chained prescalers cannot be converted to a linear prescaler, for example, a timer with a set of power-of-two prescalers and a 16 or 32-bit counter. These must be computed with a different class:
The calculator only picks the first prescaler with the lowest error, however, in this example, there can be multiple exact solutions:
32000 = 8 × 4000 = 16 × 2000 = ... = 128 × 250 = 256 × 125
If the prescaler and counter is used to generate a waveform like PWM, then it is beneficial to pick the combination with the largest counter value. However, if the use case is to preserve power, then a slow running counter requires the highest prescaler. Therefore the order of prescalers can be reversed:
The same applies to the PrescalerCounter::from_linear()
and PrescalerCounter::from_function()
calculators, while the order for lists and forward ranges can be entirely arbitrary:
frequency = 1.0 / duration
and then transforming the output back as duration = 1.0 / frequency
.Floating-Point Frequencies You can define the type used for frequency representation by using the GenericPrescaler<double>
and GenericPrescalerCounter<double>
classes.
Each Result
has a signed(!), relative error attached, which can be used to assert on the quality of the calculation. Note that using static_assert
on the error directly will only print the error values:
~~~ error: static assertion failed | static_assert(std::abs(result.error) < tolerance); | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~ note: the comparison reduces to '(0.10 < 0.05)'
~~~ In instantiation of 'static void modm::PeripheralDriver::assertBaudrateInTolerance() [with long long unsigned int available = 3000000; long long unsigned int requested = 115200000; float tolerance = 0.01f]': error: static assertion failed: The closest available baudrate exceeds the tolerance of the requested baudrate! | static_assert(modm::isValueInTolerance(requested, available, tolerance), | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: 'modm::isValueInTolerance<long long unsigned int>(115200000, 3000000, 0.01f)' evaluates to false ~~~
|
constexpr |
Returns an iterable range [start, stop) of step 1.
|
constexpr |
Returns an iterable range [start, stop) of step != 0.
|
constexpr |
Returns an iterable range [0, stop) of step 1.