/*******************************************************************************
 * @file	app_raw_main.c
 * @author	CandyPops Co.
 * @version V1.0.0
 * @date	2022-09-05
 * @brief
 ******************************************************************************/

/*******************************************************************************
 * 2026.03.26 jhChun
 * 현재 이 파일은 실제 런타임에 실행되지 않고 있음
 * 인터럽트 방식 대신 app_raw.c imu_read_direct()에서 직접 레지스터 읽는 방식 사용 중
 * 추후 필요 여부에 따라 정리 예정
 ******************************************************************************/

/*******************************************************************************
 * [모듈 개요] ICM42670P 메인 초기화 및 폴링 루프
 *
 * ICM42670P IMU 센서의 전체 초기화 시퀀스와 메인 루프를 담당한다.
 *
 * 초기화 흐름 (icm42670_init):
 *   1) setup_mcu()             - I2C 시리얼 인터페이스 구조체 설정 및 TWI 초기화
 *   2) setup_imu_device()      - IMU 드라이버 초기화 + WHOAMI 확인
 *   3) configure_imu_device()  - 센서 파라미터 설정 (FSR, ODR, 전원 모드)
 *   4) inv_gpio_sensor_irq_init() - INT1(P1.13) GPIO 인터럽트 설정
 *
 * 메인 루프 (icm42670_main):
 *   - INT1 인터럽트 발생 시 irq_from_device 플래그가 세팅됨
 *   - 메인 루프에서 플래그를 확인하고, 세팅되어 있으면 센서 데이터를 읽음
 *   - 인터럽트는 하강 에지(HITOLO)에서 발생 (INT1 핀 풀업 설정)
 *
 * 보조 함수:
 *   - inv_imu_sleep_us()     - nrf_delay_us 래퍼 (IMU 드라이버가 사용)
 *   - inv_imu_get_time_us()  - RTC1 카운터로 타임스탬프 제공
 ******************************************************************************/
#include "sdk_config.h"
#include "app_raw.h"
#include "app_raw_main.h"
#include "RingBuffer.h"
#include "inv_imu_driver.h"

#include "system_interface.h"

/* std */
#include <stdio.h>
#include "nrf.h"
#include "app_error.h"
#include "boards.h"
#include "nrfx_gpiote.h"
#include "nrf_delay.h"

#include "app_util_platform.h"
#include "main.h"  /* 2026-03-17: cmd_parse.h 삭제 → main.h */
#include "i2c_manager.h"
/* --------------------------------------------------------------------------------------
 *  Global variables
 * -------------------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------------------
 *  Static variables
 * -------------------------------------------------------------------------------------- */

/*
 * IMU 인터럽트 플래그
 * INT1 핀의 하강 에지 인터럽트 발생 시 1로 세팅된다.
 * 메인 루프에서 이 플래그를 확인 후 데이터를 읽고 0으로 클리어한다.
 * volatile: ISR에서 변경되므로 컴파일러 최적화 방지
 */
static volatile int irq_from_device;


/* --------------------------------------------------------------------------------------
 *  Forward declaration
 * -------------------------------------------------------------------------------------- */
static int setup_mcu(struct inv_imu_serif *icm_serif);

/*!
* @brief	Sensor general interrupt handler, calls specific handlers.
*
* This function is called when an external interrupt is triggered by the sensor,
* checks interrupt registers of InvenSense Sensor to determine the source and type of interrupt
* and calls the specific interrupt handler accordingly.
*
* @param[in]	NULL
*
* @param[out]	NULL
*
* @return		NULL
*
*/
/*
 * inv_gpio_sensor_interrupt_handler()
 * INT1 핀 인터럽트 핸들러 (ISR).
 * 센서가 새 데이터를 준비했을 때 호출되며, 플래그만 세팅하고 즉시 반환한다.
 * 실제 데이터 처리는 메인 루프(icm42670_main)에서 수행한다.
 */
static void inv_gpio_sensor_interrupt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
	irq_from_device = 1;
}


/*
 * inv_gpio_sensor_irq_init()
 * INT1(P1.13) GPIO 인터럽트를 초기화한다.
 *
 * 설정:
 *   - 트리거: 하강 에지 (HITOLO) — 센서가 INT를 Low로 끌어내릴 때
 *   - 풀업 저항: 내부 풀업 활성화
 *   - 핸들러: inv_gpio_sensor_interrupt_handler
 *   - GPIOTE 모듈이 미초기화 상태이면 먼저 초기화
 */
void inv_gpio_sensor_irq_init(void)
{
    ret_code_t err_code;

	/* GPIOTE 모듈 초기화 (이미 초기화되어 있으면 건너뜀) */
	if (!nrfx_gpiote_is_init())
	{
	  err_code = nrfx_gpiote_init();
	  APP_ERROR_CHECK(err_code);
	}

    /* 하강 에지 인터럽트 설정: High→Low 전환 시 트리거, 내부 풀업 사용 */
    nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;

    /* INT1 핀에 인터럽트 핸들러 등록 */
    err_code = nrfx_gpiote_in_init(ICM42670_INT1_PIN, &in_config, inv_gpio_sensor_interrupt_handler);
    APP_ERROR_CHECK(err_code);

    /* 인터럽트 이벤트 활성화 */
    nrfx_gpiote_in_event_enable(ICM42670_INT1_PIN, true);
}


/*
 * inv_gpio_sensor_irq_uninit()
 * INT1 GPIO 인터럽트를 비활성화하고 해제한다.
 * 센서 비활성화 시 또는 재초기화 전에 호출된다.
 */
void inv_gpio_sensor_irq_uninit(void)
{
	/* 인터럽트 이벤트 비활성화 */
	nrfx_gpiote_in_event_disable(ICM42670_INT1_PIN);

	/* INT1 핀 인터럽트 설정 해제 */
	nrfx_gpiote_in_uninit(ICM42670_INT1_PIN);

	/* GPIOTE 모듈 해제 (초기화된 경우에만) */
	if (nrfx_gpiote_is_init())
	{
	  nrfx_gpiote_uninit();

	}
}

/* --------------------------------------------------------------------------------------
 *  Main
 * -------------------------------------------------------------------------------------- */

/*
 * icm42670_init()
 * ICM42670P 전체 초기화 시퀀스를 수행한다.
 *
 * 초기화 순서:
 *   1) setup_mcu()             - I2C 인터페이스 구조체 설정 및 TWI 하드웨어 초기화
 *   2) setup_imu_device()      - IMU 드라이버 초기화, WHOAMI(0x67) 확인
 *   3) configure_imu_device()  - FSR, ODR, 전원 모드 설정
 *   4) inv_gpio_sensor_irq_init() - INT1 인터럽트 활성화 (데이터 준비 알림)
 *
 * 반환값: 0=성공, -1=초기화 실패
 */
int icm42670_init(void)
{
	int rc = 0;
	struct inv_imu_serif icm_serif;

	rc |= setup_mcu(&icm_serif);
	rc |= setup_imu_device(&icm_serif);
	rc |= configure_imu_device();

	if(rc != 0){
		printf("!!!error during initialization\r\n");
		return -1;
	}

	/* 초기화 성공 후 INT1 인터럽트 활성화 — 이후 데이터 준비 시 ISR이 호출됨 */
	inv_gpio_sensor_irq_init();

	return rc;
}


/*
 * icm42670_main()
 * ICM42670P 메인 폴링 루프.
 * 메인 애플리케이션 루프에서 주기적으로 호출되어야 한다.
 *
 * 동작:
 *   1) I2C 하드웨어가 초기화되었는지 확인 (hw_i2c_init_once)
 *   2) irq_from_device 플래그 확인 (ISR에서 세팅됨)
 *   3) 플래그가 세팅되어 있으면 센서 데이터 읽기 (get_imu_data)
 *   4) 데이터 읽기 완료 후 플래그 클리어
 *
 * 참고: 인터럽트 기반 폴링 방식으로, ISR에서는 플래그만 세팅하고 실제 I2C 통신은 메인 컨텍스트에서 수행한다.
 */
void icm42670_main(void)
{
	int rc = 0;
   hw_i2c_init_once();
	/* 인터럽트 발생 여부 확인 후 데이터 읽기 */

	if (irq_from_device) {
		rc = get_imu_data();

		if(rc < 0) {
			printf("error while getting data\r\n");
		}

		/* 플래그 클리어 — 다음 인터럽트까지 대기 */
		irq_from_device = 0;
	}

}


/* --------------------------------------------------------------------------------------
 *  Functions definitions
 * -------------------------------------------------------------------------------------- */

/*
 * setup_mcu()
 * MCU 측 시리얼 인터페이스를 설정한다.
 *
 * inv_imu_serif 구조체에 다음을 등록:
 *   - read_reg / write_reg : I2C 읽기/쓰기 콜백 함수 (system_interface.c에서 구현)
 *   - max_read / max_write : 최대 전송 크기 (32KB)
 *   - serif_type           : 통신 타입 (UI_I2C)
 *
 * 설정 후 inv_io_hal_init()을 호출하여 실제 TWI 하드웨어를 초기화한다.
 */
static int setup_mcu(struct inv_imu_serif *icm_serif)
{
	int rc = 0;

	/* IMU 드라이버용 시리얼 인터페이스 구조체 설정 */
	icm_serif->context   = 0;        /* 컨텍스트 미사용 */
	icm_serif->read_reg  = inv_io_hal_read_reg;   /* 레지스터 읽기 콜백 */
	icm_serif->write_reg = inv_io_hal_write_reg;   /* 레지스터 쓰기 콜백 */
	icm_serif->max_read  = 1024*32;  /* 1회 읽기 최대 바이트 수 */
	icm_serif->max_write = 1024*32;  /* 1회 쓰기 최대 바이트 수 */
	icm_serif->serif_type = SERIF_TYPE;  /* UI_I2C (app_raw.h에서 정의) */

	/* TWI 하드웨어 초기화 */
	rc |= inv_io_hal_init(icm_serif);

	return rc;
}


/* --------------------------------------------------------------------------------------
 *  Extern functions definition
 * -------------------------------------------------------------------------------------- */

/*
 * inv_imu_sleep_us()
 * IMU 드라이버가 사용하는 마이크로초 단위 슬립 함수.
 * nrf_delay_us()를 래핑하여 플랫폼 독립적 인터페이스를 제공한다.
 * 예: 자이로 스타트업 대기(GYR_STARTUP_TIME_US) 시 사용
 */
void inv_imu_sleep_us(uint32_t us)
{
	nrf_delay_us(us);
}


/*
 * inv_imu_get_time_us()
 * IMU 드라이버가 사용하는 타임스탬프 함수.
 * nRF52840의 RTC1 카운터 값을 반환한다.
 *
 * 주의: RTC1은 32.768kHz로 동작하므로, 반환값의 단위는 엄밀히
 * 마이크로초가 아닌 RTC 틱(약 30.5us/tick)이다.
 * 드라이버 내부에서 상대적 시간 비교 용도로 사용된다.
 */
uint64_t inv_imu_get_time_us(void)
{
	return NRF_RTC1->COUNTER;
}
