Move motion.Step() directly inside the __AVR__ code, silencing an unused
variable warning.
Calling motion.Step() without getting or setting the timer is not useful
anyway.
Avoid calling PulseGen::Step() on idle axes by checking for a non-zero
queue size (which is more efficient to compute).
Increase stepTimerQuantum to 128us to ensure acceleration can be
computed in realtime for 3 axes at the same time.
Fix the logic of the static assertion, which was flipped: we need to
create slices larger than the maximal step frequency in order to ensure
no axis is starved while moving.
This is a tentative/crude implementation of an Init and ISR for the MMU
in order to check the motion API.
We remove the "extern void Isr", declaring it "static inline" instead.
We need to inline the ISR here in order to avoid the function call.
Include the missing speed_table data in the executable. This bumps the
code size to ~60% of the flash.
Implemement motion::Init to setup the ISR and timers, and replace the
call in main from tmc::Init to motion::Init. Motion will init each
driver every time the axis is enabled, so there should be no need for
a global module initialization (we need SPI, but this is initialized
earlier on by it's own module anyway).
The timer is currently setup without any HAL or proper TIMER1 wrapper.
This is to be improved later.
The real MMU unit seems to slow down quite a bit during acceleration.
At this point we need to inline some methods in PulseGen to avoid
overhead, however this breaks the stubs.
The parameter config::AxisConfig::uSteps was supposed to be
microstepping resolution, but it's instead being used as the driver's
MRES directly.
To avoid a runtime conversion, rename the field to mRes and define a new
enum listing all the possible (and valid) microstepping resolutions.
This simplifies the code and makes clear the stepsPerUnit scale.
Assign correct stepsPerUnit to all axes as a result, including working
limits.
This allows Unit<> and AxisUnit<> to be scaled with a fraction as
expected, promoting the scaler to the same unit:
0.2_mm * 10 => 2_mm (mm*f => mm)
Multiplication type is commutative:
10 * 0.2_mm => 2_mm (f*mm => mm)
Division isn't:
0.2_mm / 10 => 0.02_mm (mm*1/f => mm)
10 / 0.2_mm => error (illegal type conversion)
Introduces a nasty hack to forcefully write into the constexpr SPI descriptor's registers
(which is the correct way in ASM, but kind of cumbersome in C++ now)
Please note Windows CRLF sequence is not supported,
but a separate CR xor a separate LF works now.
This is a workaround for stupid terminals for debugging purposes,
and it is not necessary for the protocol to work on its own.
It may be removed in the future.
- Move unit/step conversion to modules/axisunit.h
- Unify motion::unitToAxisUnit<> and motion::unitToSteps<>,
making conversion in other modules just as easy as motion.
- Improve the documentation
Introduces:
- config::Unit: base class for physical quantities
- motion::AxisUnit: type-checked steps type
"config/unit.h" defines basic physical quantities, which are not
normally used elsewhere besides config.h.
"modules/axisunit.h" extends the modules::motion namespace with
Axis-aware units, with one type per axis per unit.
P_pos_t defines step positions for the pulley, I_pos_t for the idler,
etc. These are defined through the literar operators which are
similarly named and automatically convert a physical quantity to an
AxisUnit at compile time:
P_pos_t pulley_pos = 10.0_P_mm;
Besides type-checking, AxisUnit are otherwise identical to raw step
counts and are intended to be used along with the updated Motion API.
PlanMove/PlanMoveTo has been extended to support moves using these units
or physical quantities. Again, conversion is performed at compile time.
This matches PulseGen::Position() and avoids confusion around the term
"current": Position() returns the head position in the queue, not the
"live" axis position.
We have PulseGen::CurPosition() now for this purpose, although we don't
expose it to Motion yet.
CurPosition() returns the live axis position, which in this
implementation is inherently expensive to compute.
This shouldn't be required for the MMU, but it /will/ come in handy to
check for the axis position/s in Motion tests.
Motion::Full() (without a specific axis) is counter-productive.
When planning new moves the axis needs to be known beforehand, so it
might be as well be given to Full() to check the proper queue.
Implement Motion::SetEnabled (for symmetry with TMC2130::SetEnabled).
Rename DisableAxis to Disable and use the new SetEnabled. This makes the
member names more consistent.
We might want to schedule new moves while a single motor is moving.
Allow to do that by introducing per-axis query functions.
The main QueueEmpty() and Full() still function as before:
- Call QueueEmpty() to wait for all moves to finish.
- Use !Full() to know that a Plan() move will never be discarded.
Since scheduling a move on a block which is being executed will jolt the
motors, be extra-safe and perform an extra lower-level check before
committing even if the caller is responsible.
Return the status, which can be useful to build a simple busy loop.
- Remove the combined PlanMove(a,b,c,rate) call. If we allow the units
of the various motors to be changed at compile time, the unit of
rate can vary between axes.
- Build PlanMove on top of the absolute PlanMoveTo.
- Add required stubs for TMC2130.
- Allow each axis mode to be set independently, since we have this
feature for free anyway.
- Rework internals to use PulseGen data types and structs.
+ start shaping up main.cpp
+ make the usage of namespaces and class names more consistent throughout the whole project
+ refactor related unit tests accordingly