/* Отрисовка графика значений в плоттере

* Вы можете точно настроить показания, изменив STALL_VALUE.
 * Это позволит вам контролировать, при какой нагрузке значение будет равно 0
 * и сработает флаг остановки. Это также установит высокий уровень на выводе DIAG1.
 * Более высокое значение STALL_VALUE сделает чтение менее чувствительным и
 * меньшее значение STALL_VALUE сделает его более чувствительным.
 *
 * Если отправить 0 в консоль - остановка
 * 1 - движение
 * + увеличить скорость / При слишком большой скорости шаги будут проскакивать. 
 * - Уменьшить скорость
 */

#include <TMCStepper.h>

#define MAX_SPEED 40 // Значение таймера в Millis для скорости
#define MIN_SPEED 1000

#define STALL_VALUE 15 // [-64..63]

/*
Меньшее значение дает более высокую чувствительность. Нуль
начальное значение, которое работает с большинством двигателей.
От -64 до +63: чем выше значение, тем меньше stallGuard2.
чувствителен и требует большего крутящего момента для
определения остановки (залипания).
*/

//Настройка пинов для Software SPI. На Arduino Mega все пины кроме Аналоговых

#define EN_PIN 46   // Enable
#define DIR_PIN 24  // Direction
#define STEP_PIN 26 // Step
#define CS_PIN 30   // Chip select
#define SW_MOSI 34  // Software Master Out Slave In (MOSI)
#define SW_MISO 28  // Software Master In Slave Out (MISO)
#define SW_SCK 32   // Software Slave Clock (SCK)

#define R_SENSE 0.11f // Резистор с которого будет делаться замер на драйвере - уточнить. \
                      // SilentStepStick series use 0.11 - выбрать данный параметр                                        \
                      // UltiMachine Einsy and Archim2 boards use 0.2                                                                          \
                      // Panucatt BSD2660 uses 0.1                                                                                             \
                      // Watterott TMC5160 uses 0.075

//Silent-Step-Stick 0.11 - это плата драйвера шагового двигателя для двухфазных двигателей,
//основанная на драйверах Trinamic: TMC 2100 / TMC 2130 / TMC 2208 / TMC 2209 / TMC 5160 / TMC 5161.

// Тип подключения
//TMC2130Stepper driver(CS_PIN, R_SENSE);                           // Hardware SPI будут использоваться стандратные пины
TMC2130Stepper driver(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK); // Software SPI

using namespace TMC2130_n;

// Using direct register manipulation can reach faster stepping times
#define STEP_PORT PORTF // Match with STEP_PIN
#define STEP_BIT_POS 0  // Match with STEP_PIN

ISR(TIMER1_COMPA_vect)
{
    //STEP_PORT ^= 1 << STEP_BIT_POS;
    digitalWrite(STEP_PIN, !digitalRead(STEP_PIN));
}

void setup()
{
    SPI.begin();
    Serial.begin(115200);

    //Установка пинов как выходов и состояний
    pinMode(EN_PIN, OUTPUT);
    pinMode(STEP_PIN, OUTPUT);
    pinMode(CS_PIN, OUTPUT);
    pinMode(DIR_PIN, OUTPUT);
    pinMode(MISO, INPUT_PULLUP);
    digitalWrite(EN_PIN, LOW);

    driver.begin();
    driver.toff(4);        //Общее разрешение для управления двигателем 0 Драйвер выключен / 1… 15 Драйвер включен. значение не влияет на stealthChop
    driver.blank_time(24); //16 tCLK  1 24 tCLK  2 36 tCLK  3 54 tCLK
    /* Время холостого хода компаратора.Нужно безопасно
    охватить событие переключения и продолжительность
    звон на сенсорном резисторе. Выберите настройку
    1 или 2 для типичных приложений. Для больших
    емкостных нагрузок, может потребоваться 3. Нижние
    настройки позволяют StealthChop регулировать до
    более низкие значения тока катушки
    */

    driver.rms_current(1000); // mA
    driver.microsteps(16);    //Микрошагов за шаг 128, 64, 32, 16, 8, 4, 2, FULLSTEP
    driver.en_pwm_mode(true); //Разрешение работы со скоростями
    driver.pwm_autoscale(true);
    /*
            Автоматический режим с использованием обратной связи по току (pwm_autoscale = 1) и подачи
            режим управления скоростью поступательного движения (pwm_autoscale = 0). Режим управления скоростью прямой связи не
            реагирует на изменение напряжения питания или на такие события, как остановка двигателя, но обеспечивает очень стабильную работу
            амплитуда.
    */
    driver.TCOOLTHRS(0xFFFFF); // 20bit max  0 … 1048575
    /*
        Определяет верхнюю скорость для работы в
        StealthChop по напряжению в режиме ШИМ.
    */

    driver.THIGH(0); //0…1048575
    /*
        Настройка для управления
        верхний порог для
        работы с coolStep
        и stallGuard  - уточнить.
    */
    driver.semin(5); //0- выкл /  1..15
    /*
    4-битовое целое число без знака, задающее нижний порог.
    Если SG опускается ниже этого порога, coolStep
    увеличивает ток на обе катушки. 4-битный
    Значение SEMIN масштабируется на 32, чтобы покрыть нижнюю
    половина диапазона 10-битового значения SG.  StallGuard

    */
    driver.semax(2);   //0...15
    driver.sedn(0b01); // 0,1,2,3
    /*
    Устанавливает количество показаний stallGuard2 над
    верхний порог, необходимый для каждого тока
    уменьшение тока двигателя. number of stallGuard2 measurements per decrement: 32, 8, 2, 1
    */

    driver.sgt(STALL_VALUE); //Установка StallGuard

    // Set stepper interrupt
    {
        cli();       //stop interrupts
        TCCR1A = 0;  // set entire TCCR1A register to 0
        TCCR1B = 0;  // same for TCCR1B
        TCNT1 = 0;   //initialize counter value to 0
        OCR1A = 256; // = (16*10^6) / (1*1024) - 1 (must be <65536)
        // turn on CTC mode
        TCCR1B |= (1 << WGM12);
        // Set CS11 bits for 8 prescaler
        TCCR1B |= (1 << CS11); // | (1 << CS10);
        // enable timer compare interrupt
        TIMSK1 |= (1 << OCIE1A);
        sei(); //allow interrupts
    }
}

void loop()
{
    static uint32_t last_time = 0;
    uint32_t ms = millis();

    //При получении определенного символа из консоли происходит прерывание и установка параметров
    while (Serial.available() > 0)
    {
        int8_t read_byte = Serial.read();

        if (read_byte == '0')
        {
            TIMSK1 &= ~(1 << OCIE1A);
            digitalWrite(EN_PIN, HIGH);
        }
        else if (read_byte == '1')
        {
            TIMSK1 |= (1 << OCIE1A);
            digitalWrite(EN_PIN, LOW);
        }

        else if (read_byte == '+')
        {
            if (OCR1A > MAX_SPEED)
                OCR1A -= 20;
        }
        else if (read_byte == '-')
        {
            if (OCR1A < MIN_SPEED)
                OCR1A += 20;
        }
    }

    //Каждые 101 милисекунду опрашиваем статус драйвера
    if ((ms - last_time) > 100)
    {
        last_time = ms;

        DRV_STATUS_t drv_status{0};

        //Данная функция возвращает статус всего драйвера. Из данного результата возможно взять 1 или 0 для состояния StallGuard.        Сработал или нет
        //Описание регистра с флагами в файле TMC2130_datasheet.pdf на 38й странице.  DRV_STATUS – stallGuard2 Value and Driver Error Flags
        drv_status.sr = driver.DRV_STATUS();

        //    Serial.println(drv_status.sr);

        Serial.print(drv_status.sg_result, DEC); //Результат 1 или 0. Смена состояния при превышении установленного значения StallGuard
        Serial.print(" ");
        Serial.println(driver.cs2rms(drv_status.cs_actual), DEC); //Текущее состояние StallGuard
    }
}