<commit_before>#pragma once

#include "MotorControlBase.h"
#include <algorithm>
#include "core_pins.h"

template <typename Accelerator, typename TimerField>
class RotateControlBase : public MotorControlBase<TimerField>
{
  public:
    RotateControlBase(unsigned pulseWidth = 5, unsigned accUpdatePeriod = 5000);    

    // Non-blocking movements ----------------
    template <typename... Steppers>
    void rotateAsync(Steppers &... steppers);
   
    template <size_t N>
    void rotateAsync(Stepper *(&motors)[N]);

    void stopAsync();
  
     // Blocking movements --------------------
     void stop();

     void overrideSpeed(float speedFac);
     void overrideAcceleration(float accFac);

 protected:
     void doRotate(int N, float speedFactor = 1.0);
     void accTimerISR();

     Accelerator accelerator;

     RotateControlBase(const RotateControlBase &) = delete;
     RotateControlBase &operator=(const RotateControlBase &) = delete;

     bool isStopping = false;
};

// Implementation *************************************************************************************************

template <typename a, typename t>
RotateControlBase<a, t>::RotateControlBase(unsigned pulseWidth, unsigned accUpdatePeriod)
    : MotorControlBase<t>(pulseWidth, accUpdatePeriod)
{
    this->mode = MotorControlBase<t>::Mode::notarget;
}

template <typename a, typename t>
void RotateControlBase<a, t>::doRotate(int N, float speedFactor)
{
     //Calculate Bresenham parameters ----------------------------------------------------------------
    std::sort(this->motorList, this->motorList + N, Stepper::cmpVmax);
    this->leadMotor = this->motorList[0];

    if (this->leadMotor->vMax == 0)
        return;

    this->leadMotor->currentSpeed = 0; 

    this->leadMotor->A = std::abs(this->leadMotor->vMax);
    for (int i = 1; i < N; i++)
    {
        this->motorList[i]->A = std::abs(this->motorList[i]->vMax);
        this->motorList[i]->B = 2 * this->motorList[i]->A - this->leadMotor->A;
    }
    uint32_t acceleration = (*std::min_element(this->motorList, this->motorList + N, Stepper::cmpAcc))->a; // use the lowest acceleration for the move
    
    // Start moving---------------------------------------------------------------------------------------  
    this->timerField.begin();
    accelerator.prepareRotation(this->leadMotor->current, this->leadMotor->vMax, acceleration, this->accUpdatePeriod, speedFactor);
    this->timerField.setStepFrequency(0);    
    this->timerField.accTimerStart();    <commit_msg>Bug: not restarting after stop() with on demand timers -> fixed<commit_after>#pragma once

#include "MotorControlBase.h"
#include <algorithm>
#include "core_pins.h"

template <typename Accelerator, typename TimerField>
class RotateControlBase : public MotorControlBase<TimerField>
{
  public:
    RotateControlBase(unsigned pulseWidth = 5, unsigned accUpdatePeriod = 5000);    

    // Non-blocking movements ----------------
    template <typename... Steppers>
    void rotateAsync(Steppers &... steppers);
   
    template <size_t N>
    void rotateAsync(Stepper *(&motors)[N]);

    void stopAsync();
  
     // Blocking movements --------------------
     void stop();

     void overrideSpeed(float speedFac);
     void overrideAcceleration(float accFac);

 protected:
     void doRotate(int N, float speedFactor = 1.0);
     void accTimerISR();

     Accelerator accelerator;

     RotateControlBase(const RotateControlBase &) = delete;
     RotateControlBase &operator=(const RotateControlBase &) = delete;

     bool isStopping = false;
};

// Implementation *************************************************************************************************

template <typename a, typename t>
RotateControlBase<a, t>::RotateControlBase(unsigned pulseWidth, unsigned accUpdatePeriod)
    : MotorControlBase<t>(pulseWidth, accUpdatePeriod)
{
    this->mode = MotorControlBase<t>::Mode::notarget;
}

template <typename a, typename t>
void RotateControlBase<a, t>::doRotate(int N, float speedFactor)
{
     //Calculate Bresenham parameters ----------------------------------------------------------------
    std::sort(this->motorList, this->motorList + N, Stepper::cmpVmax);
    this->leadMotor = this->motorList[0];

    if (this->leadMotor->vMax == 0)
        return;

    this->leadMotor->currentSpeed = 0; 

    this->leadMotor->A = std::abs(this->leadMotor->vMax);
    for (int i = 1; i < N; i++)
    {
        this->motorList[i]->A = std::abs(this->motorList[i]->vMax);
        this->motorList[i]->B = 2 * this->motorList[i]->A - this->leadMotor->A;
    }
    uint32_t acceleration = (*std::min_element(this->motorList, this->motorList + N, Stepper::cmpAcc))->a; // use the lowest acceleration for the move
    
    // Start moving----------------------------------------------------------------------------------------------  
    isStopping = false;
    this->timerField.begin();
    accelerator.prepareRotation(this->leadMotor->current, this->leadMotor->vMax, acceleration, this->accUpdatePeriod, speedFactor);
    this->timerField.setStepFrequency(0);    
    this->timerField.accTimerStart();    
{'fraction_non_alphanumeric': 0.22991635868508073, 'fraction_numerical': 0.00583544057576347, 'mean_word_length': 2.8545727136431784, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 94, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4788295', 'n_tokens_mistral': 1552, 'n_tokens_neox': 1408, 'n_words': 311}