Not much feedback from the TeensyStep users, but here's another status update.
I've spent some time trying to understand TeensyStep for T3.x, and I'll share my progress here for anyone who is interested.
TeensyStep allows for control of up to 4 groups of motors, with up to 10 motors in each group. Each of the 4 possible groups uses 3 timer resources (1 x PIT and 2 x FTM). The PIT instance is referred to as stepTimer, and is configured to interrupt at the desired step frequency. The leading edges of the step pulses for all of the motors in a group are generated in stepTimerISR(). The two FTM channels are referred to as delay timers. They are both used in output compare mode to produce interrupts at some future time ("delay"). One is referred to as delayTimer, and is used to generate the trailing edges of all step pulses for the group, and the other is referred to as accTimer. It occurs at lower frequency, and controls motor acceleration (steps/sec^2) by computing a new motor velocity (steps/sec) and modifying the PIT stepTimer to interrupt at that frequency.
The PIT channel's stepTimerISR() generates the leading edge of each step pulse and also calls the delayTimer FTM channel's trigger() function to configure the FTM channel to generate an interrupt at the desired time for the trailing edges. The FTM channel's trigger() function reads the CNT register, adds the desired delay, and writes that sum to the compare value (CV) register. When the counter (CNT) reaches the value written to CV, an FTM interrupt occurs, and delayTimerISR() writes the trailing edge of the pulse. The second FTM channel is used to control acceleration, and is referred to as accTimer. By default, the FTM accTimer channel is configured to interrupt every 5 ms (5000 us). Since both FTM channels are part of the same FTM module, they share an interrupt, and thus delayTimerISR(). When either match occurs, delayTimer or accTimer, delayTimerISR() checks both channel flags. If the flag for the delayTimer channel is set, the ISR generates the pulse trailing edges, and if the flag for the accTimer channel is set, it calls the acceleration update function, which computes a new velocity, modifies the PIT frequency accordingly, and configures the FTM channel to generate the next acceleration interrupt.
As a side note, I'm not sure why a separate FTM channel is used as accTimer, as opposed to updating velocity on every N occurences of either the leading edge (PIT) or trailing edge (FTM) interrupts.
Control of the step and direction pins for all motors is done via the T3's "bitband" I/O feature. This feature provides separate register locations to set or clear a given I/O bit that controls a pin. So, step pulse leading and trailing edges and direction changes are generated by writing 1 to the appropriate register locations.
There are 4 PIT channels, and each FTM has 8 channels, so 4 groups of motors can be controlled. Each group can contain up to 10 motors. Within the group, the one with the highest step frequency is the "lead" motor, and the PIT interrupt frequency is set according to the current step frequency for that motor. All other motors in the group are "slave" motors. They are optionally stepped on each PIT interrupt, with the composite frequency yielding the desired speed for each motor. The decision whether to step each slave motor on a step of the lead motor is made according to the Bresenham algorithm.
TeensyStep4 is quite different. It uses just one QuadTimer (TMR) channel for a motor group. That single TMR channel is used in PWM mode, with the PWM period set for the desired step frequency, and the PWM pulse width set of the desired step pulse width. Perhpas because the T4 has so much more computing power, acceleration is controlling updating the velocity (steps/sec) and therefore the PWM frequency, on every cyles.
I don't know of any reason why the T3 approach (1 x PIT + 2 x FTM) could not be mapped onto the T4 (1 x PIT + 2 x TMR), so perhaps
@luni just decided it made more sense to use a single TMR channel in PWM mode to go from 3 timer resources to 1, and to take advantage of the T4's greater computing power to control acceleration by updating velocity on every step. I wonder whether the T4 approach could be mapped back onto the T3, using a single FTM channel in edge-aligned PWM mode rather than 1 PIT and 2 FTM channels in output compare mode. That would actually allow support for more groups, though I doubt that more than 4 would be necessary. Also, the T4 does not have bitband I/O functions, so TeensyStep4 uses digitalWriteFast() and digitalToggleFast() to change the state of step and direction pins.
So, the possibilities are:
- modify TeensyStep(3) to support T4 via the same timer approach used for T3 (1 x PIT + 2 x TMR)
- update TeensyStep4 to have the same API as TeensyStep, so applications can easily move to TeensyStep4
@elfren and other TeensyStep users, now that I've shown that RoseFollower_T41 can run without getting "stuck", can you please comment on what else you cannot do with TeensyStep4 that you can do with TeensyStep(s)?