/*******************************************************************************
 * @file    meas_pd_48.h
 * @brief   M48 LED-PD Measurement Module Header for NIRS System
 * @author  Charles KWON <charleskwon@medithings.co.kr>
 * @version V2.0.0
 * @date    2025-12-31
 *
 * Copyright (c) 2025 Medithings Inc.
 * All rights reserved.
 *
 * This header defines the interface for the M48 measurement module which
 * controls 24/48 LED-PD pair measurements using SAADC with PPI triggering
 * from the ADA2200 Lock-in Amplifier SYNCO signal.
 *
 * Hardware Configuration:
 * - ADC Input: Differential measurement on AIN0/AIN1
 * - Trigger: ADA2200 SYNCO pin (P0.17) via GPIOTE/PPI
 * - Gain Control: MCP4725 DAC via I2C
 * - LED Control: CAT9532 via I2C
 ******************************************************************************/

#ifndef _MEAS_PD_48_H__
#define _MEAS_PD_48_H__

/*============================================================================*/
/* Includes - Charles KWON                                                    */
/*============================================================================*/
#include "sdk_common.h"
#include "nrf_drv_saadc.h"

/*============================================================================*/
/* Hardware Pin Configuration - Charles KWON                                  */
/*============================================================================*/

/**
 * @brief ADA2200 Lock-in Amplifier SYNCO output pin
 * - Charles KWON
 *
 * This pin provides the synchronization signal for ADC sampling.
 * Connected to GPIOTE for triggering SAADC via PPI.
 */
#ifndef ADA2200_SYNCO_PIN
#define ADA2200_SYNCO_PIN       NRF_GPIO_PIN_MAP(0, 17)
#endif

/*============================================================================*/
/* Measurement Configuration Constants - Charles KWON                         */
/*============================================================================*/

/**
 * @brief Number of photodetectors in the system
 * - Charles KWON
 *
 * Currently configured for single PD operation (PD0).
 */
#define m48_PD_NO               1

/**
 * @brief Number of LEDs for full measurement sequence
 * - Charles KWON
 *
 * Full measurement uses 24 LEDs (LED0-LED23) with single PD.
 * Modified from original 48 LED configuration (cj edit 25/10/14).
 */
#define m48_LED_NO              24

/**
 * @brief Number of LEDs for half measurement sequence
 * - Charles KWON
 *
 * Half measurement uses 24 LEDs for either:
 * - Part A: LED0-LED23 (ADC_PD_MODE 3)
 * - Part B: LED24-LED47 (ADC_PD_MODE 4)
 */
#define m48_LED_NO_H            24

/**
 * @brief Number of ADC samples per LED measurement cycle
 * - Charles KWON
 *
 * Each LED measurement consists of 32 consecutive ADC samples
 * triggered by SYNCO signal for averaging/processing.
 */
#define m48_CYCLE_CNT           32

/*============================================================================*/
/* PPI Configuration Functions - Charles KWON                                 */
/*============================================================================*/

/**
 * @brief Initialize PPI channel for SYNCO-triggered ADC sampling
 * - Charles KWON
 *
 * Configures PPI to connect GPIOTE SYNCO event to SAADC SAMPLE task.
 * This enables hardware-triggered ADC sampling synchronized with
 * the ADA2200 lock-in amplifier output.
 */
void m48_ppi_init(void);

/**
 * @brief Uninitialize PPI channel
 * - Charles KWON
 *
 * Releases PPI resources after measurement completion.
 */
void m48_ppi_uninit(void);

/**
 * @brief Enable PPI sampling event
 * - Charles KWON
 *
 * Activates the SYNCO-to-SAADC PPI channel to begin
 * hardware-triggered sampling.
 */
void m48_sampling_event_enable(void);

/**
 * @brief Disable PPI sampling event
 * - Charles KWON
 *
 * Deactivates the PPI channel to stop hardware-triggered sampling.
 */
void m48_sampling_event_disable(void);

/*============================================================================*/
/* SAADC Functions - Charles KWON                                             */
/*============================================================================*/

/**
 * @brief ADC interrupt handler for voltage measurements
 * - Charles KWON
 *
 * Callback function invoked when ADC buffer is full.
 * Processes raw ADC values and advances to next LED in sequence.
 *
 * @param[in] p_event Pointer to SAADC event structure containing
 *                    conversion results and event type
 *
 * @note This is a static function - declaration kept for documentation
 */
static void m48_voltage_handler(nrf_drv_saadc_evt_t const * p_event);

/**
 * @brief Initialize and start first ADC measurement sequence
 * - Charles KWON
 *
 * Entry point for M48 measurement. Initializes hardware,
 * configures first LED, and begins ADC sampling.
 */
void m48_adc_start_init(void);

/**
 * @brief Start ADC sampling for current LED
 * - Charles KWON
 *
 * Configures ADC buffer and enables sampling for the
 * currently selected LED in the measurement sequence.
 */
void m48_adc_start(void);

/**
 * @brief Start ADC sampling with secondary buffer
 * - Charles KWON
 *
 * Alternative start function using secondary ADC buffer
 * for double-buffered operation.
 */
void m48_adc_start2(void);

/**
 * @brief End current LED measurement and advance to next
 * - Charles KWON
 *
 * Called after ADC interrupt to transition to next LED
 * in the measurement sequence.
 */
void m48_adc_end(void);

/**
 * @brief Finalize measurement sequence
 * - Charles KWON
 *
 * Called when all LEDs have been measured. Sends results
 * over BLE and cleans up hardware resources.
 */
void m48_adc_end_final(void);

/**
 * @brief Initialize SAADC for differential measurement
 * - Charles KWON
 *
 * Configures SAADC with:
 * - Differential input on AIN0 (positive) / AIN1 (negative)
 * - Internal reference (0.6V)
 * - 1/4 gain for optimal range
 * - 14-bit resolution
 */
void m48_adc_init(void);

/**
 * @brief Uninitialize SAADC
 * - Charles KWON
 *
 * Releases SAADC resources for use by other modules.
 */
void m48_adc_uninit(void);

/*============================================================================*/
/* GPIO Interrupt Functions - Charles KWON                                    */
/*============================================================================*/

/**
 * @brief Initialize GPIOTE for SYNCO signal detection
 * - Charles KWON
 *
 * Configures GPIOTE channel to detect rising edges on
 * ADA2200 SYNCO pin for PPI triggering.
 */
void m48_irq_init(void);

/**
 * @brief Uninitialize GPIOTE
 * - Charles KWON
 *
 * Releases GPIOTE resources after measurement completion.
 */
void m48_irq_uninit(void);

/*============================================================================*/
/* Measurement Timer Functions - Charles KWON                                 */
/*============================================================================*/

/**
 * @brief Measurement check timer callback
 * - Charles KWON
 *
 * Periodic timer callback for monitoring measurement progress
 * and handling timeout conditions.
 *
 * @param[in] p_context Unused timer context parameter
 */
void m48_check_loop(void * p_context);

/**
 * @brief Start measurement check timer
 * - Charles KWON
 */
void m48_check_timer_start(void);

/**
 * @brief Stop measurement check timer
 * - Charles KWON
 */
void m48_check_timer_stop(void);

/**
 * @brief Initialize measurement check timer
 * - Charles KWON
 *
 * Creates the timer used for measurement monitoring.
 * Must be called during system initialization.
 */
void m48_check_timer_init(void);

#endif /* _MEAS_PD_48_H__ */
