#ifndef UNO_PWM_H
#define UNO_PWM_H

#include "GenericPWM.h"

/**
 * @class UnoPWM
 * @brief Class for configuring and controlling PWM on an Arduino Uno.
 *
 * This class allows generating PWM signals on pins 3, 9, 10, and 11 with configurable frequencies.
 * It provides fine control over Timer1 (for pins 9 and 10) and Timer2 (for pins 3 and 11), allowing
 * phase-correct PWM operation with adjustable duty cycles.
 *
 * Features:
 * - Supports configuring Timer1 and Timer2 for PWM output.
 * - Allows enabling/disabling individual PWM pins via flags.
 * - Computes appropriate timer top values based on the desired frequency.
 * - Provides functions to set PWM duty cycle dynamically.
 */
class UnoPWM : public GenericPWM {
private:
    word pwmFreqHz; ///< Desired PWM frequency in Hz
    word tcnt1Top;  ///< Computed TOP value for Timer1
    byte tcnt2Top;  ///< Computed TOP value for Timer2

    byte pwmPin1; ///< Pin assigned to Timer1 Channel A (default: 9)
    byte pwmPin2; ///< Pin assigned to Timer1 Channel B (default: 10)
    byte pwmPin3; ///< Pin assigned to Timer2 Channel B (default: 3)
    byte pwmPin4; ///< Pin assigned to Timer2 Channel A (default: 11)

    byte flags; ///< Configuration flags to enable specific timers and PWM pins

    /**
     * @brief Calculates the TOP value for Timer1 and Timer2 based on the desired frequency.
     */
    void calculateTop();

    /**
     * @brief Configures Timer1 for phase-correct PWM operation.
     */
    void setupTimer1();

    /**
     * @brief Configures Timer2 for fast PWM operation.
     */
    void setupTimer2();

public:
    // Default PWM pin assignments
    static constexpr byte PWM_PIN1 = 9;
    static constexpr byte PWM_PIN2 = 10;
    static constexpr byte PWM_PIN3 = 3;
    static constexpr byte PWM_PIN4 = 11;

    // Flags for configuring timers
    static constexpr byte FLAG_CONFIG_TIMER1 = 1;  ///< Enable Timer1 (pins 9, 10)
    static constexpr byte FLAG_CONFIG_TIMER2 = 2;  ///< Enable Timer2 (pins 3, 11)

    // Flags for enabling individual PWM pins
    static constexpr byte FLAG_ENABLE_PIN1 = 4;  ///< Enable PWM on pin 9
    static constexpr byte FLAG_ENABLE_PIN2 = 8;  ///< Enable PWM on pin 10
    static constexpr byte FLAG_ENABLE_PIN3 = 16; ///< Enable PWM on pin 3
    static constexpr byte FLAG_ENABLE_PIN4 = 32; ///< Enable PWM on pin 11

    /**
     * @brief Constructor to initialize the UnoPWM object.
     *
     * @param pwmFreqHz Desired PWM frequency.
     * @param pwmPin1 PWM pin associated with Timer1 Channel A (default: 9).
     * @param pwmPin2 PWM pin associated with Timer1 Channel B (default: 10).
     * @param pwmPin3 PWM pin associated with Timer2 Channel B (default: 3).
     * @param pwmPin4 PWM pin associated with Timer2 Channel A (default: 11).
     * @param flags Configuration flags for enabling timers and PWM pins.
     */
    UnoPWM(word pwmFreqHz, byte pwmPin1 = PWM_PIN1, byte pwmPin2 = PWM_PIN2, byte pwmPin3 = PWM_PIN3, byte pwmPin4 = PWM_PIN4, byte flags = (FLAG_CONFIG_TIMER1 | FLAG_ENABLE_PIN1));

    /**
     * @brief Sets up the timers based on the provided flags.
     */
    void setupTimer() override;

    /**
     * @brief Sets the PWM duty cycle for a given pin.
     *
     * @param duty Duty cycle percentage (0-100).
     * @param pwmPin The pin on which to set the duty cycle.
     */
    void setPwmDuty(byte duty, byte pwmPin) override;

    /**
     * @brief Retrieves the computed TOP value for Timer1.
     *
     * @return Timer1 TOP value.
     */
    word getTcnt1Top() const { return tcnt1Top; }

    /**
     * @brief Retrieves the computed TOP value for Timer2.
     *
     * @return Timer2 TOP value.
     */
    byte getTcnt2Top() const { return tcnt2Top; }
};


#endif
