/**
 * @file Motion.h
 * @author Jonathan Schulze, Nick Hübenthal, Hans Haupt
 * @brief This component controls the ability to rotate and change position. 
 * @version 0.2
 * @date 2023-12-13
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#ifndef Motion_h
#define Motion_h
#include <stdint.h>
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "driver/ledc.h"
#define LEDC_MODE          LEDC_LOW_SPEED_MODE
#define TIMER              LEDC_TIMER_2
#define CHANNEL_LEFT       LEDC_CHANNEL_3 
#define CHANNEL_RIGHT      LEDC_CHANNEL_4  
#define DUTY_RES           LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define FREQUENCY          (5000) // Frequency in Hertz. Set frequency at 5 kHz
class Motor{
    public:
        Motor(uint8_t pin, ledc_timer_t timer, ledc_channel_t channel);
        void begin(void);
        void setSpeed(uint16_t duty);
        uint16_t getSpeed(void); 
    protected:
        uint8_t pin;
        ledc_timer_t timer;
        ledc_channel_t channel;
       
        uint16_t duty;
};

class Motion{
protected:
    static const uint16_t RIGHT_MOTOR_DUTY = 4096;
    static const uint16_t LEFT_MOTOR_DUTY = 4096;
    static const int MOTOR_RIGHT_PIN = 11; 
    static const int MOTOR_LEFT_PIN = 12;
    static void moveTask(void * args);
    static void leftMotorTask(void * args);
    static void rightMotorTask(void * args);

public:
    //Shared Timer to sync movement
    static inline Motor left = Motor(MOTOR_LEFT_PIN,TIMER,CHANNEL_LEFT);
    static inline Motor right = Motor(MOTOR_RIGHT_PIN,TIMER,CHANNEL_RIGHT);

    /**
     * @brief Initialize the movement component.
     * 
    */
    void begin(void);

    /**
     * @brief Move forward for a certain amount of time.
     * Call with moveForMs 0 will start movement, that must be stopped explicit by call to stop().
     * @param moveForMs Representing the duration of forward moving in milliseconds.
    */
    static void move(uint32_t moveForMs=0);

    /**
     * @brief Rotate clockwise for a certain amount of time.
     * Call with moveForMs 0 will start movement, that must be stopped explicit by call to stop().
     * @param rotateForMs Representing the duration of rotating clockwise in milliseconds.
    */
    static void rotateClockwise(uint32_t rotateForMs=0);
    
    /**
     * @brief Rotate anticlockwise for a certain amount of time.
     * Call with moveForMs 0 will start movement, that must be stopped explicit by call to stop().
     * @param rotateForMs Representing the duration of rotating anticlockwise in milliseconds.
    */
    static void rotateAntiClockwise(uint32_t rotateForMs=0);

    /**
     * @brief stops any current movement, no matter if timebased or endless
     * 
     */
    static void stop(void);

};


#endif //Motion_h