AVR: Do not use __builtin_abs() for long types

In AVR __builtin_abs() breaks for non-base types.

Provide a generic function and use an overload when it is safe to use
instead.

This fixes the underlying step count calculation in PlanMove, thus
removing the need for the PlanLongMove work-around.
pull/136/head
Yuri D'Elia 2021-11-05 14:44:25 +01:00 committed by DRracer
parent 2d81332626
commit b6a676e093
5 changed files with 10 additions and 38 deletions

View File

@ -15,18 +15,22 @@ using std::min;
#include <math.h> #include <math.h>
template <typename T> template <typename T>
static inline const T min(T a, T b) { static inline const T min(const T a, const T b) {
return a <= b ? a : b; return a <= b ? a : b;
} }
template <typename T> template <typename T>
static inline const T max(T a, T b) { static inline const T max(const T a, const T b) {
return a > b ? a : b; return a > b ? a : b;
} }
template <typename T> template <typename T>
static inline const T abs(T n) { static inline const T abs(const T n) {
// Use builtin function when available return n < 0 ? -n : n;
}
static inline const int16_t abs(const int16_t n) {
// Use builtin function only when possible
return __builtin_abs((n)); return __builtin_abs((n));
} }

View File

@ -53,7 +53,6 @@ static constexpr uint16_t maxStepFrequency = 40000;
static constexpr uint16_t minStepRate = 120; static constexpr uint16_t minStepRate = 120;
/// Size for the motion planner block buffer size /// Size for the motion planner block buffer size
/// Beware of too low setting (esp. because of Motion::PlanLongMove)
static constexpr uint8_t blockBufferSize = 4; static constexpr uint8_t blockBufferSize = 4;
/// Step timer frequency divider (F = F_CPU / divider) /// Step timer frequency divider (F = F_CPU / divider)

View File

@ -27,7 +27,7 @@ bool FeedToBondtech::Step() {
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley)); dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
state = PushingFilamentToFSensor; state = PushingFilamentToFSensor;
mm::motion.InitAxis(mm::Pulley); mm::motion.InitAxis(mm::Pulley);
mm::motion.PlanLongMove<mm::Pulley>(config::defaultBowdenLength, config::pulleyFeedrate, config::pulleySlowFeedrate); mm::motion.PlanMove<mm::Pulley>(config::defaultBowdenLength, config::pulleyFeedrate, config::pulleySlowFeedrate);
} }
return false; return false;
case PushingFilamentToFSensor: case PushingFilamentToFSensor:

View File

@ -36,7 +36,7 @@ bool UnloadToFinda::Step() {
if (mi::idler.Engaged()) { if (mi::idler.Engaged()) {
state = WaitingForFINDA; state = WaitingForFINDA;
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector); mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
mm::motion.PlanLongMove<mm::Pulley>(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU, config::pulleyFeedrate); mm::motion.PlanMove<mm::Pulley>(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU, config::pulleyFeedrate);
} }
return false; return false;
case WaitingForFINDA: case WaitingForFINDA:

View File

@ -162,37 +162,6 @@ public:
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(end_rate)); unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(end_rate));
} }
/// This function exists solely because of some mysterious overflow bug in planning/stepping
/// which occurrs when number of steps exceeds 32K. The bug doesn't even exhibit in unit tests :( .
/// Therefore it plans multiple segments in case the desired distance is longer than 32K steps.
/// So far this is only used for moving the Pulley...
template <Axis A, config::UnitBase B>
constexpr void PlanLongMove(config::Unit<long double, B, Lenght> delta,
config::Unit<long double, B, Speed> feed_rate, config::Unit<long double, B, Speed> end_rate = { 0 }) {
auto steps = unitToAxisUnit<AxisUnit<pos_t, A, Lenght>>(delta);
if (steps.v >= 0) {
while (steps.v > 32767) {
PlanMove<A>(
{ 32767 },
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(feed_rate),
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(feed_rate)); // keep the end feedrate the same to continue with the next segment
steps.v -= 32767;
}
} else {
while (steps.v < -32767) {
PlanMove<A>(
{ -32767 },
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(feed_rate),
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(feed_rate)); // keep the end feedrate the same to continue with the next segment
steps.v += 32767;
}
}
PlanMove<A>( // last segment
steps,
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(feed_rate),
unitToAxisUnit<AxisUnit<steps_t, A, Speed>>(end_rate));
}
/// @returns head position of an axis (last enqueued position) /// @returns head position of an axis (last enqueued position)
/// @param axis axis affected /// @param axis axis affected
pos_t Position(Axis axis) const; pos_t Position(Axis axis) const;