/*******************************************************************************
 * @file    i2c_manager.c
 * @brief   Robust HW/SW I2C switching logic with mutual exclusion
 ******************************************************************************/

#include "i2c_manager.h"
#include "debug_print.h"
#include "nrf_delay.h"
#include "nrf_drv_twi.h"
#include "nrfx_twi.h"
#include "boards.h"
#include "system_interface.h"

bool HW_I2C_FRQ = false;
bool SW_I2C_FRQ = false;

#define TWI_INSTANCE 0

/* TWI (I2C) 하드웨어 인스턴스 : IMU 드라이버에서 사용 - jhChun 26.03.16 */
const nrfx_twi_t m_twi = NRFX_TWI_INSTANCE(TWI_INSTANCE);

/* TWI (I2C) 해제 - jhChun 26.03.16 */
static void twi_uninitialize(void){
    nrfx_twi_disable(&m_twi);
    nrfx_twi_uninit(&m_twi);
}

/* TWI (I2C) 하드웨어 초기화 (SCL/SDA핀, 400kHz) - jhChun 26.03.16 */
static void twi_initialize(void){
    ret_code_t err_code;

    const nrfx_twi_config_t twi_config = {
       .scl                = ICM42670_I2C_SCL_PIN,
       .sda                = ICM42670_I2C_SDA_PIN,
       .frequency          = NRF_TWI_FREQ_400K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
    };

    err_code = nrfx_twi_init(&m_twi, &twi_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrfx_twi_enable(&m_twi);
}

/* -------------------------------------------------------------------------- */
/* HW (TWI) 초기화                                                           */
/* -------------------------------------------------------------------------- */
void hw_i2c_init_once(void)
{
    if (SW_I2C_FRQ)
    {
        DBG_PRINTF("[I2C] SW I2C active - forcing HW switch\r\n");
        // SW 비활성화 후 전환
        SW_I2C_FRQ = false;
    }

    if (HW_I2C_FRQ)
    {
        DBG_PRINTF("[I2C] HW I2C already initialized\r\n");
        return;
    }

    DBG_PRINTF("[I2C] Initializing HW (TWI) I2C...\r\n");
    twi_initialize();
    nrf_delay_ms(2);

    HW_I2C_FRQ = true;
    SW_I2C_FRQ = false;

    DBG_PRINTF("[I2C] HW I2C initialized\r\n");
}

/* -------------------------------------------------------------------------- */
/* SW (Port-Bang) 초기화                                                     */
/* -------------------------------------------------------------------------- */
void sw_i2c_init_once(void)
{
    if (HW_I2C_FRQ)
    {
        DBG_PRINTF("[I2C] HW I2C active -> switching to SW I2C\r\n");

        // HW 완전 종료
        nrfx_twi_disable(&m_twi);
        nrfx_twi_uninit(&m_twi);
        nrf_delay_ms(3);

        HW_I2C_FRQ = false;   // 반드시 false로 갱신
    }

    // HW 모드가 종료되었으니 SW 시작 가능
    if (!SW_I2C_FRQ)
    {
        DBG_PRINTF("[I2C] Initializing SW (Port Bang-Bang) I2C...\r\n");

        twi_uninitialize(); // SDA/SCL 해제
        nrf_delay_ms(1);

        SW_I2C_FRQ = true;
        HW_I2C_FRQ = false;

        DBG_PRINTF("[I2C] SW I2C initialized\r\n");
    }
    else
    {
        DBG_PRINTF("[I2C] SW I2C already active\r\n");
    }
}

/* -------------------------------------------------------------------------- */
/* RESET STATE                                                               */
/* -------------------------------------------------------------------------- */
void i2c_reset_state(void)
{
    HW_I2C_FRQ = false;
    SW_I2C_FRQ = false;
    DBG_PRINTF("[I2C] Flags reset\r\n");
}
