Avoid runtime conversions of floats in UnloadToFinda

Introduce axisUnitToTruncatedUnit to convert from an AxisUnit (now
conveniently returned from Motion::CurPosition) to a physical unit *but*
directly into a truncated integer type, avoiding conversions to long
double types at runtime.

The related function truncatedUnit perform the same truncation of a
constant unit, so that the result of axisUnitToTruncatedUnit and
truncatedUnit(unit) result in the same type for clarity.

Both functions accept a pre-multiplier, which is applied at compile
time for constant values when optimizations are enabled.
pull/150/head
Yuri D'Elia 2022-01-31 19:47:54 +01:00 committed by DRracer
parent 86d5e87a09
commit 53d285280d
2 changed files with 25 additions and 16 deletions

View File

@ -24,7 +24,7 @@ void UnloadToFinda::Reset(uint8_t maxTries) {
// @@TODO this may end up somewhere else as more code may need to check the distance traveled by the filament // @@TODO this may end up somewhere else as more code may need to check the distance traveled by the filament
int32_t CurrentPositionPulley_mm() { int32_t CurrentPositionPulley_mm() {
return mm::stepsToUnit<mm::P_pos_t>(mm::P_pos_t({ mm::motion.CurPosition(mm::Pulley) })); return mm::axisUnitToTruncatedUnit<config::U_mm>(mm::motion.CurPosition<mm::Pulley>());
} }
bool UnloadToFinda::Step() { bool UnloadToFinda::Step() {
@ -48,7 +48,7 @@ bool UnloadToFinda::Step() {
return false; return false;
case WaitingForFINDA: { case WaitingForFINDA: {
int32_t currentPulley_mm = CurrentPositionPulley_mm(); int32_t currentPulley_mm = CurrentPositionPulley_mm();
if ((abs(unloadStart_mm - currentPulley_mm) > config::fsensorUnloadCheckDistance.v) && mfs::fsensor.Pressed()) { if ((abs(unloadStart_mm - currentPulley_mm) > mm::truncatedUnit(config::fsensorUnloadCheckDistance)) && mfs::fsensor.Pressed()) {
// fsensor didn't trigger within the first fsensorUnloadCheckDistance mm -> stop pulling, something failed, report an error // fsensor didn't trigger within the first fsensorUnloadCheckDistance mm -> stop pulling, something failed, report an error
// This scenario should not be tried again - repeating it may cause more damage to filament + potentially more collateral damage // This scenario should not be tried again - repeating it may cause more damage to filament + potentially more collateral damage
state = FailedFSensor; state = FailedFSensor;

View File

@ -112,14 +112,30 @@ static constexpr AU unitToAxisUnit(U v) {
return { (typename AU::type_t)(v.v * axisScale[AU::axis].stepsPerUnit) }; return { (typename AU::type_t)(v.v * axisScale[AU::axis].stepsPerUnit) };
} }
/// Convert an AxisUnit to unit::Unit. /// Convert an AxisUnit to a physical unit with a truncated integer type (normally int32_t).
/// The scaling factor is stored with the pair config::AxisConfig::uSteps and /// Inverse of unitToAxisUnit, with the additional constraint that type casts are
/// config::AxisConfig::stepsPerUnit (one per-axis). /// performed earlier so that no floating point computation is required at runtime.
template <typename U, typename AU> /// @param U Base unit type (normally U_mm)
static constexpr typename U::type_t axisUnitToUnit(AU v) { /// @param AU AxisUnit type (implicit)
/// @param T Resulting integer type
/// @param v Value to truncate
/// @param mul Optional pre-multiplier
/// @returns Truncated unit (v * mul)
/// @see unitToAxisUnit
template <typename U, typename AU, typename T = int32_t>
static constexpr T axisUnitToTruncatedUnit(AU v, long double mul = 1.) {
static_assert(AU::unit == U::unit, "incorrect unit type conversion"); static_assert(AU::unit == U::unit, "incorrect unit type conversion");
//static_assert(U::base == axisScale[AU::axis].base, "incorrect unit base conversion"); static_assert(U::base == axisScale[AU::axis].base, "incorrect unit base conversion");
return { (typename U::type_t)(v.v / axisScale[AU::axis].stepsPerUnit) }; return { ((T)v.v / (T)(axisScale[AU::axis].stepsPerUnit / mul)) };
}
/// Truncate an Unit type to an integer (normally int32_t)
/// @param v Value to truncate
/// @param mul Optional pre-multiplier
/// @returns Truncated unit (v * mul)
template <typename U, typename T = int32_t>
static constexpr T truncatedUnit(U v, long double mul = 1.) {
return (T)(v.v * mul);
} }
/// Convert a unit::Unit to a steps type (pos_t or steps_t). /// Convert a unit::Unit to a steps type (pos_t or steps_t).
@ -129,13 +145,6 @@ static constexpr typename AU::type_t unitToSteps(U v) {
return unitToAxisUnit<AU>(v).v; return unitToAxisUnit<AU>(v).v;
} }
/// Convert a steps type (pos_t or steps_t) to a unit::Unit.
/// Extract the raw step count from an AxisUnit with type checking.
template <typename U, typename AU>
static constexpr typename U::type_t stepsToUnit(AU pos) {
return axisUnitToUnit<U, AU>(pos);
}
// Pulley // Pulley
typedef AxisUnit<pos_t, Pulley, Lenght> P_pos_t; ///< Pulley position type (steps) typedef AxisUnit<pos_t, Pulley, Lenght> P_pos_t; ///< Pulley position type (steps)
typedef AxisUnit<steps_t, Pulley, Speed> P_speed_t; ///< Pulley speed type (steps/s) typedef AxisUnit<steps_t, Pulley, Speed> P_speed_t; ///< Pulley speed type (steps/s)