/*******************************************************************************
 * @file    pulse_gen.c
 * @brief   PWM Pulse Generator (Build-safe version)
 * @author  CandyPops Co. / ??? ????
 * @version V1.0.1
 * @date    2025-10-13
 ******************************************************************************/

#define SKIP_PWM   // ? ?? ???? PWM ?? ???

#include "pulse_gen.h"
#include "debug_print.h"
#include "app_timer.h"
#include "nrf_log.h"

#ifdef SKIP_PWM
/* ========================================================================== */
/*  PWM ?? ???? Stub ??                                              */
/* ========================================================================== */

ret_code_t pulse_gen_init(void)
{
    DBG_PRINTF("[PWM] skipped init\r\n");
	return NRF_SUCCESS;
}

void pulse_gen_start(void)
{
    DBG_PRINTF("[PWM] skipped start\r\n");
}

void pulse_gen_stop(void)
{
    DBG_PRINTF("[PWM] skipped stop\r\n");
}

#else   /* ==================================================================== */
/*  ?? PWM ?? ?? (SKIP_PWM ?? ?? ? ???)                         */
/* ========================================================================== */

#include "nrfx_pwm.h"

/* --- Configuration --- */
#define PULSE_PIN_1     28
#define PULSE_PIN_2     29
#define PULSE_PIN_3     30
#define PULSE_DELAY_MS  10

#define PWM_INSTANCE_ID 0
#define PWM_TOP_VALUE   8
#define SEQUENCE_LENGTH 6

static nrfx_pwm_t m_pwm = NRFX_PWM_INSTANCE(PWM_INSTANCE_ID);
APP_TIMER_DEF(m_pulse_delay_timer_id);
static volatile bool m_pulses_running = false;

static nrf_pwm_values_individual_t m_pulse_seq_values[SEQUENCE_LENGTH];
static nrf_pwm_sequence_t const m_pulse_sequence =
{
    .values.p_individual = m_pulse_seq_values,
    .length              = NRF_PWM_VALUES_LENGTH(m_pulse_seq_values),
    .repeats             = 0,
    .end_delay           = 0
};

/* -------------------------------------------------------------------------- */
/* Local Handlers                                                             */
/* -------------------------------------------------------------------------- */
static void prepare_pulse_sequence(void)
{
    m_pulse_seq_values[0].channel_0 = PWM_TOP_VALUE; m_pulse_seq_values[0].channel_1 = 0;             m_pulse_seq_values[0].channel_2 = 0;
    m_pulse_seq_values[1].channel_0 = 0;             m_pulse_seq_values[1].channel_1 = PWM_TOP_VALUE; m_pulse_seq_values[1].channel_2 = 0;
    m_pulse_seq_values[2].channel_0 = PWM_TOP_VALUE; m_pulse_seq_values[2].channel_1 = 0;             m_pulse_seq_values[2].channel_2 = 0;
    m_pulse_seq_values[3].channel_0 = 0;             m_pulse_seq_values[3].channel_1 = PWM_TOP_VALUE; m_pulse_seq_values[3].channel_2 = 0;
    m_pulse_seq_values[4].channel_0 = 0;             m_pulse_seq_values[4].channel_1 = 0;             m_pulse_seq_values[4].channel_2 = 0;
    m_pulse_seq_values[5].channel_0 = 0;             m_pulse_seq_values[5].channel_1 = 0;             m_pulse_seq_values[5].channel_2 = PWM_TOP_VALUE;
}

static void pulse_delay_timeout_handler(void * p_context)
{
    if (m_pulses_running)
    {
        (void)nrfx_pwm_simple_playback(&m_pwm, &m_pulse_sequence, 1, NRFX_PWM_FLAG_STOP);
        (void)app_timer_start(m_pulse_delay_timer_id, APP_TIMER_TICKS(PULSE_DELAY_MS), NULL);
    }
}

/* -------------------------------------------------------------------------- */
/* Public Functions                                                           */
/* -------------------------------------------------------------------------- */
ret_code_t pulse_gen_init(void)
{
    ret_code_t err_code;

    prepare_pulse_sequence();

    nrfx_pwm_config_t const config =
    {
        .output_pins =
        {
            PULSE_PIN_1,
            PULSE_PIN_2,
            PULSE_PIN_3,
            NRFX_PWM_PIN_NOT_USED
        },
        .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
        .base_clock   = NRF_PWM_CLK_16MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = PWM_TOP_VALUE,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };

    err_code = nrfx_pwm_init(&m_pwm, &config, NULL);
    if (err_code != NRF_SUCCESS)
        return err_code;

    err_code = app_timer_create(&m_pulse_delay_timer_id,
                                APP_TIMER_MODE_SINGLE_SHOT,
                                pulse_delay_timeout_handler);
    return err_code;
}

void pulse_gen_start(void)
{
    if (m_pulses_running) return;
    m_pulses_running = true;
    pulse_delay_timeout_handler(NULL);
}

void pulse_gen_stop(void)
{
    m_pulses_running = false;
    app_timer_stop(m_pulse_delay_timer_id);
    nrfx_pwm_stop(&m_pwm, true);
}

#endif  /* SKIP_PWM */
