/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */

/** @file
 *
 * @defgroup ble_sdk_app_hids_mouse_main main.c
 * @{
 * @ingroup ble_sdk_app_hids_mouse
 * @brief HID Mouse Sample Application main file.
 *
 * This file contains is the source code for a sample application using the HID, Battery and Device
 * Information Service for implementing a simple mouse functionality. This application uses the
 * @ref app_scheduler.
 *
 * Also it would accept pairing requests from any peer device. This implementation of the
 * application will not know whether a connected central is a known device or not.
 */


/*******************************************************************************
********************************************************************************
                    include
********************************************************************************
*******************************************************************************/
#include "prj_config.h"
#include "m_global.h"

#include "app_scheduler.h"
#include "app_timer.h"
#include "nrf_delay.h"
#include "nrf_drv_rng.h"
#include "nrf_fstorage.h"
#include "nrf_fstorage_sd.h"
#include "nrf_gpio.h"
#include "nrf_log_ctrl.h"
#ifdef TWI_SW_MASTER_USE
	#include "twi_master.h"
#endif

// SD
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"

// application
#include "appl_ble.h"
#include "codebook.h"
#include "drv_doorlock.h"
#include "imgate_flash.h"
#include "m_doorlock.h"
#include "pstorage_platform.h"
#include "rtc.h"

// common
#include "app_error.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"



/*******************************************************************************
********************************************************************************
                    definitions
********************************************************************************
*******************************************************************************/
#define VARIABLE_MAC_ADDRESS_BIT_MASK	0x80

#define APP_TIMER_OP_QUEUE_SIZE			40		// old : 25, Size of timer operation queues.

//#define SCHED_MAX_EVENT_DATA_SIZE		MAX(MAX(APP_TIMER_SCHED_EVENT_DATA_SIZE,BLE_STACK_HANDLER_SCHED_EVT_SIZE),sizeof(m_doorlock_data_t))
#define SCHED_MAX_EVENT_DATA_SIZE		MAX(APP_TIMER_SCHED_EVENT_DATA_SIZE, sizeof(m_doorlock_data_t))
#define SCHED_QUEUE_SIZE					45		// old : 30, Maximum number of events in the scheduler queue.


APP_TIMER_DEF(m_system_timer_id);       
#define SYSTEM_INTERVAL						APP_TIMER_TICKS(1000)	// 1 sec

#define RTC_CLOCK_LIMIT						30
#define RTC_DEFAULT_OPTION					1				// old : 0	// 0 : XTAL, 1 - RC, 2- SYNTH


/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */
//NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL);



/*******************************************************************************
********************************************************************************
                    variables
********************************************************************************
*******************************************************************************/
uint8_t m_main_test_mode = 0;
uint8_t m_nfc_test_TxControlReg = 0;
uint32_t m_nfc_test_sampling_delay = 0;
uint8_t m_nfc_test_mode = 0;					// bit 0 : 0- tx_off /1 -  tx_on , BIT[1] : TX Delay Mode, BIT[2] : No Algorith
uint32_t m_nfc_test_interval = 0;
uint8_t m_log_save_control = 0;
uint8_t m_rtc_option;

uint8_t resetType = 0;							// reset type

volatile uint8_t m_queue_start_index;		// Index of queue entry at the start of the queue
volatile uint8_t m_queue_end_index;			// Index of queue entry at the end of the queue

extern global_t m_global;
extern ram_global_t *mp_ram_global;

extern ble_gap_addr_t m_MAC_Address[2];
extern char DEVICE_NAME[13];
extern uint8_t m_codebook_status[MAX_CODEBOOK_NUM];
extern uint16_t m_treepass_alarm_counter;
extern uint32_t g_curr_sec;
extern volatile doorlock_main_state_t m_main_state;



/*******************************************************************************
********************************************************************************
                    fuctions
********************************************************************************
*******************************************************************************/

#if 0		// mtkim add
// wdt
nrfx_wdt_channel_id m_channel_id;

void configWdt(void)
{
	uint32_t err_code = NRF_SUCCESS;

	nrfx_wdt_config_t config = NRFX_WDT_DEAFULT_CONFIG;
	err_code = nrfx_wdt_init(&config, NULL);
	APP_ERROR_CHECK(err_code);
	err_code = nrfx_wdt_channel_alloc(&m_channel_id);
	APP_ERROR_CHECK(err_code);
	nrfx_wdt_enable();
}
#endif


static void system_timeout_handler(void * p_context)
{
	UNUSED_PARAMETER(p_context);

	g_curr_sec++;

	if (mp_ram_global->nMissingPasswordCount)
	{
		mp_ram_global->nMissingPasswordElaspedSec++;
		CheckMissingPasswordModeTO();
	};

	if (mp_ram_global->nLowVoltageAuthReaminedSecs)
	{
		mp_ram_global->nLowVoltageAuthReaminedSecs--;
	};

	if (m_main_state == S810_TRESPASS)
	{
		m_treepass_alarm_counter++;
//		NRF_LOG_RAW_INFO("TREPASS : %u\r\n", m_treepass_alarm_counter);

		if (m_treepass_alarm_counter == 60*1)
		{
//			NRF_LOG_RAW_INFO("TREPASS STOP\r\n");
			// Alarm Stop
			send_event_to_main_handler(doorlock_packet_type_trepass_alarm_stop_req);
		}
		else if (m_treepass_alarm_counter >= 60*6)
		{
//			NRF_LOG_RAW_INFO("TREPASS START\r\n");
			m_treepass_alarm_counter = 0;
			// Restart Alarm
			send_event_to_main_handler(doorlock_packet_type_trepass_alarm_start_req);
		};
	}

	RTC_CAL_TIMER_INCRESE();
}

/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module.
 */
static void timers_init(void)
{
	uint32_t err_code __attribute__((unused));

	// Initialize timer module, making it use the scheduler.
	err_code = app_timer_init();
	DL_APP_ERROR_CHECK(err_code);

	// Create system timer & start
	err_code = app_timer_create(&m_system_timer_id, APP_TIMER_MODE_REPEATED, system_timeout_handler);
	DL_APP_ERROR_CHECK(err_code);

	err_code = app_timer_start(m_system_timer_id, SYSTEM_INTERVAL, NULL);
	DL_APP_ERROR_CHECK(err_code);
}

/**@brief Function for dispatching a system event to interested modules.
 *
 * @details This function is called from the System event interrupt handler after a system
 *          event has been received.
 *
 * @param[in]   sys_evt   System stack event.
 */
void sys_evt_dispatch(uint32_t sys_evt, void * p_context)
{
	UNUSED_PARAMETER(p_context);			// mtkim add

	// Dispatch the system event to the fstorage module, where it will be
	// dispatched to the Flash Data Storage (FDS) module.
////	fs_sys_event_handler(sys_evt);
	nrf_fstorage_sys_evt_handler(sys_evt);

	// Dispatch to the Advertising module last, since it will check if there are any
	// pending flash operations in fstorage. Let fstorage process system events first,
	// so that it can report correctly to the Advertising module.
////	ble_advertising_on_sys_evt(sys_evt);
}


/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(uint8_t clock_option)
{
#if 0		// old
    uint32_t err_code __attribute__((unused));

    nrf_clock_lf_cfg_t clock_lf_cfg_xtal = NRF_CLOCK_LFCLKSRC_XTAL;
    nrf_clock_lf_cfg_t clock_lf_cfg_rc = NRF_CLOCK_LFCLKSRC_RC;
    nrf_clock_lf_cfg_t clock_lf_cfg_synth = NRF_CLOCK_LFCLKSRC_SYNTH;

    switch (clock_option)
    {
    case 1:
        SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg_rc, NULL);
//        NRF_LOG_RAW_INFO("2) 32768 Clock RC\r\n");
        break;

    case 2:
        SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg_synth, NULL);
//        NRF_LOG_RAW_INFO("2) 32768 Clock SYNTH\r\n");
        break;

    default:
        SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg_xtal, NULL);
//        NRF_LOG_RAW_INFO("2) 32768 Clock XTAL\r\n");
        break;
    };

    ble_enable_params_t ble_enable_params;
    err_code = softdevice_enable_get_default_config(NRF_SDH_BLE_CENTRAL_LINK_COUNT,
                                                    NRF_SDH_BLE_PERIPHERAL_LINK_COUNT,
                                                    &ble_enable_params);
    DL_APP_ERROR_CHECK(err_code);

    // Check the ram settings against the used number of links
    CHECK_RAM_START_ADDR(NRF_SDH_BLE_CENTRAL_LINK_COUNT, NRF_SDH_BLE_PERIPHERAL_LINK_COUNT);

    // Enable BLE stack.
#if (NRF_SD_BLE_API_VERSION == 3)
    ble_enable_params.gatt_enable_params.att_mtu = NRF_BLE_MAX_MTU_SIZE;
#endif
    err_code = softdevice_enable(&ble_enable_params);
    DL_APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    DL_APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for system events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    DL_APP_ERROR_CHECK(err_code);

#define VARIABLE_MAC_ADDRESS_BIT_MASK 0x80
    sd_ble_gap_address_get(&m_MAC_Address[0]);
    sd_ble_gap_address_get(&m_MAC_Address[1]);
    if(m_MAC_Address[1].addr[4] & VARIABLE_MAC_ADDRESS_BIT_MASK) 
        m_MAC_Address[1].addr[4] &= ~VARIABLE_MAC_ADDRESS_BIT_MASK;
    else
        m_MAC_Address[1].addr[4] |= VARIABLE_MAC_ADDRESS_BIT_MASK;

#else
	uint32_t err_code __attribute__((unused));
	uint32_t ram_start = 0;

	// boot address set
//	NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR);
//	err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR);
//	DL_APP_ERROR_CHECK(err_code);

	// clock set in sdk_config.h -> inner RC use
	err_code = nrf_sdh_enable_request();
	DL_APP_ERROR_CHECK(err_code);

	// configure the BLE stack using the default settings.
	// Fetch the start address of the application RAM.
	err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
	DL_APP_ERROR_CHECK(err_code);

	// Enable BLE stack
	err_code = nrf_sdh_ble_enable(&ram_start);
	DL_APP_ERROR_CHECK(err_code);

	// register a handler for BLE events.
	NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_dispatch, NULL);
	NRF_SDH_SOC_OBSERVER(m_soc_observer, APP_SOC_OBSERVER_PRIO, sys_evt_dispatch, NULL);	// no need ??


	// MAC address set
	sd_ble_gap_addr_get(&m_MAC_Address[0]);
	sd_ble_gap_addr_get(&m_MAC_Address[1]);

	if(m_MAC_Address[1].addr[4] & VARIABLE_MAC_ADDRESS_BIT_MASK) 
		m_MAC_Address[1].addr[4] &= ~VARIABLE_MAC_ADDRESS_BIT_MASK;
	else
		m_MAC_Address[1].addr[4] |= VARIABLE_MAC_ADDRESS_BIT_MASK;
#endif
}


/**@brief Function for the Event Scheduler initialization.
 */
static void scheduler_init(void)
{
    APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}

/**@brief Function for the Power manager.
 */
static void power_manage(void)
{
#ifdef SOFTDEVICE_PRESENT			// 1
	uint32_t err_code = sd_app_evt_wait();
	DL_APP_ERROR_CHECK(err_code);
#else
	__WFE();
//	__SEV();
//	__WFE();
#endif
}

static void io_default_setting(void)
{
#if(HW_REV==1)

    uint8_t default_out_low_pin[] = {IO_NFC_NRSTPD_PIN, 
                                     IO_SPI_MOSI,IO_SPI_MISO,IO_SPI_SCK,IO_NFC_NSS};
    uint8_t default_out_high_pin[] = {IO_KEY_I2C_EN_PIN, IO_COMM_NSS,
                                     IO_LED_N1,IO_LED_N2,IO_LED_N3,IO_LED_N4,IO_LED_N5,IO_LED_N6,IO_LED_N7,IO_LED_N8,IO_LED_N9,IO_LED_N0,IO_LED_STAR,IO_LED_SHARP};
    uint8_t default_input[] = {IO_NFC_SENSE_PIN, IO_NFC_IRQ_PIN, IO_KEY_IRQ_PIN, IO_MASTER_RX};

#elif (HW_REV==2)||(HW_REV==5)

    uint8_t default_out_low_pin[] = {IO_NFC_NRSTPD_PIN, IO_SENSE_EN, IO_MOT_F, IO_MOT_R,
                                     IO_SPI_MOSI,IO_SPI_MISO,IO_SPI_SCK,IO_NFC_NSS};
    uint8_t default_out_high_pin[] = {IO_LED_N9, IO_LED_N10, IO_LED_N11, IO_LED_N12, IO_LED_N13, IO_KEYPAD_EN};
    uint8_t default_input[] = {IO_SW_1,IO_SW_2, IO_TACT_SW_PIN};

#elif(HW_REV==3)||(HW_REV==4)||(HW_REV==6)

    uint8_t default_out_low_pin[] = {IO_NFC_NRSTPD_PIN, IO_LED_FUNCTION,
                                     IO_SPI_MOSI,IO_SPI_MISO,IO_SPI_SCK,IO_NFC_NSS};
    uint8_t default_out_high_pin[] = {IO_COMM_NSS, IO_LED_N9, IO_LED_N10, IO_LED_N11, IO_LED_N12, IO_LED_BATT, IO_KEYPAD_EN};
    uint8_t default_input[] = {IO_NFC_SENSE_PIN, IO_NFC_IRQ_PIN, IO_KEY_IRQ_PIN};

#elif (HW_REV==7)

    uint8_t default_out_low_pin[] = {IO_NFC_NRSTPD_PIN, IO_SENSE_EN, IO_MOT_F, IO_MOT_R,
                                     IO_SPI_MOSI,IO_SPI_MISO,IO_SPI_SCK,IO_NFC_NSS};
    uint8_t default_out_high_pin[] = {IO_LED_N9, IO_LED_N10, IO_LED_N11, IO_LED_N12, IO_LED_N13, IO_KEYPAD_EN};
    uint8_t default_input[] = {IO_SW_1,IO_SW_2, IO_TACT_SW_PIN};

#elif (HW_REV==8)

    uint8_t default_out_low_pin[] = {IO_NFC_NRSTPD_PIN,
                                     IO_SPI_MOSI,IO_SPI_MISO,IO_SPI_SCK,IO_NFC_NSS};
    uint8_t default_out_high_pin[] = {IO_LED_N9, IO_LED_N10, IO_LED_N11, IO_LED_N12, IO_KEYPAD_EN};
    uint8_t default_input[] = {32};

#else
  #error "HW_REV NOT DEFINED!!"
#endif
    if(sizeof(default_out_low_pin))
    {
        for(uint8_t i=0; i<sizeof(default_out_low_pin); i++)
        {
            nrf_gpio_cfg_output(default_out_low_pin[i]);
            nrf_gpio_pin_clear(default_out_low_pin[i]);
        };
    };

    if(sizeof(default_out_high_pin))
    {
        for(uint8_t i=0; i<sizeof(default_out_high_pin); i++)
        {
            nrf_gpio_cfg_output(default_out_high_pin[i]);
            nrf_gpio_pin_set(default_out_high_pin[i]);
        };
    };

    if(sizeof(default_input))
    {
        for(uint8_t i=0; i<sizeof(default_input); i++)
        {
            nrf_gpio_cfg_default(default_input[i]);
        };
    };


	// extra IO setting - mtkim add
#ifdef LOW_CURRENT_P0RT_SET
#if (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8000) || (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8007)
	// all output high
	if(mp_ram_global->dfu_progress == 0)
	{
		// disconnect when CTL DFU
		nrf_gpio_cfg_output(IO_PIN_30);
		nrf_gpio_pin_set(IO_PIN_30);
	}

	nrf_gpio_cfg_output(IO_PIN_7);
	nrf_gpio_pin_set(IO_PIN_7);
#if (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8007)
	nrf_gpio_cfg_output(IO_PIN_12);
	nrf_gpio_pin_set(IO_PIN_12);
#endif
	nrf_gpio_cfg_output(IO_PIN_16);
	nrf_gpio_pin_set(IO_PIN_16);
	nrf_gpio_cfg_output(IO_PIN_19);
	nrf_gpio_pin_set(IO_PIN_19);
	nrf_gpio_cfg_output(IO_PIN_20);
	nrf_gpio_pin_set(IO_PIN_20);
	nrf_gpio_cfg_output(IO_PIN_25);
	nrf_gpio_pin_set(IO_PIN_25);
#endif
#endif


#if (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8008)
	nrf_gpio_cfg_output(13);			// door open LED
	nrf_gpio_pin_set(13);
	nrf_gpio_cfg_output(16);			// nfc LED
	nrf_gpio_pin_set(16);
	nrf_gpio_cfg_output(19);
	nrf_gpio_pin_set(IO_PIN_19);

#elif (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8030)
	nrf_gpio_input_disconnect(0);
	nrf_gpio_input_disconnect(21);
	nrf_gpio_input_disconnect(24);
	nrf_gpio_input_disconnect(26);

	nrf_gpio_input_disconnect(15);
	nrf_gpio_input_disconnect(16);
#endif
}

void INPUT_PIN_CHECK(uint32_t pin)
{
#if (HW_REV==2)||(HW_REV==5)
    uint32_t prev_pin_state = 0;
    uint32_t current_pin_state = 0;

    nrf_gpio_cfg_output(IO_KEYPAD_EN);
    nrf_gpio_pin_set(IO_KEYPAD_EN);
    
    nrf_delay_ms(100);

    prev_pin_state = nrf_gpio_pin_read(pin);
//    NRF_LOG_RAW_INFO("PIN(%d), STATE(%d)\r\n", pin, prev_pin_state);
    while(1) {
//        NRF_LOG_RAW_INFOESS();
        current_pin_state = nrf_gpio_pin_read(pin);
        if(prev_pin_state!= current_pin_state) {
//            NRF_LOG_RAW_INFO("PIN(%d), STATE(%d)\r\n", pin, current_pin_state);
            prev_pin_state = current_pin_state;
        }
    }
#endif
}

void INPUT_PIN_CHECK2(void)
{
#if (HW_REV==2)||(HW_REV==5)

    uint32_t prev_pin_state = 0;
    uint32_t current_pin_state = NRF_GPIO->IN;

    nrf_gpio_cfg_output(IO_KEYPAD_EN);
    nrf_gpio_pin_set(IO_KEYPAD_EN);
    
    nrf_gpio_cfg_input(IO_SW_1, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(IO_SW_2, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(IO_SW_3, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(IO_KEY_IRQ_PIN, NRF_GPIO_PIN_NOPULL);

    nrf_gpio_pin_set(IO_MOT_F);
    nrf_delay_ms(2000);
    nrf_gpio_pin_clear(IO_MOT_F);
    nrf_gpio_pin_set(IO_MOT_R);
    nrf_delay_ms(2000);
    nrf_gpio_pin_clear(IO_MOT_R);

    prev_pin_state = NRF_GPIO->IN;
//    NRF_LOG_RAW_INFO("STATE(0x%08X)\r\n", prev_pin_state);
    while(1) {
//        NRF_LOG_RAW_INFOESS();
        current_pin_state = NRF_GPIO->IN;
        if(prev_pin_state!= current_pin_state) 
        {
//            NRF_LOG_RAW_INFO("STATE(0x%08X)\r\n", current_pin_state);
            prev_pin_state = current_pin_state;
            nrf_delay_ms(100);
        }
    }
#endif
}

void watchdog_init()
{
#if 0
    // Using the watchdog to do a hard reset    
    NRF_WDT->CONFIG = (WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos);
    NRF_WDT->CRV = 32768 * (10+1);// 11sec (battery timer expire every 10 secs)
    NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos;
    NRF_WDT->TASKS_START = 1;
#ifdef DEBUG_PRINT
    NRF_LOG_RAW_INFO("\t %s()\r\n", M_FUNCTION);
#endif

#else		// mtkim
 	// watchdog only during wakeup -> watchdog always run
//	NRF_WDT->CONFIG = (WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos);
	NRF_WDT->CONFIG = (WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos) | (WDT_CONFIG_HALT_Run << WDT_CONFIG_HALT_Pos);

	NRF_WDT->CRV = 32768 * 5;							// 5sec
	NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos;
	NRF_WDT->TASKS_START = 1;
#endif
}

void watchdog_reset(void)
{
    // Using the watchdog to do a hard reset    
    NRF_WDT->RR[0] = WDT_RR_RR_Reload;  //Reload watchdog register 0
}

uint32_t CheckRTC(void)
{
    uint32_t tries = 1000;
    uint32_t count = 0;
    uint32_t previous, current;
    nrf_gpio_cfg_input(IO_CKOUT, NRF_GPIO_PIN_NOPULL);

    previous = nrf_gpio_pin_read(IO_CKOUT);

    while (tries--)
    {
        current = nrf_gpio_pin_read(IO_CKOUT);
        if (previous != current)
        {
            count++;
            previous  = current;
        };
    };

#ifdef _MSG_RTC
    NRF_LOG_RAW_INFO("RTC clock out count : %d\r\n", count);
#endif

    return count;
}

#if 0
void ErrorNoti(void)
{
// 2 BD type available
#if (HW_REV==3)||(HW_REV==4)||(HW_REV==6)
	uint8_t count=2;

	while(count--)
	{
		// 1
		nrf_delay_ms(100);
		nrf_gpio_pin_clear(IO_LED_N12);
		nrf_delay_ms(100);
		nrf_gpio_pin_set(IO_LED_N12);

		// 4
		nrf_delay_ms(100);
		nrf_gpio_pin_clear(IO_LED_N11);
		nrf_delay_ms(100);
		nrf_gpio_pin_set(IO_LED_N11);

		// 7
		nrf_delay_ms(100);
		nrf_gpio_pin_clear(IO_LED_N10);
		nrf_delay_ms(100);
		nrf_gpio_pin_set(IO_LED_N10);

		// *
		nrf_delay_ms(100);
		nrf_gpio_pin_clear(IO_LED_N9);
		nrf_delay_ms(100);
		nrf_gpio_pin_set(IO_LED_N9);
	}
#endif
}

#else
#if (DOORLOCK_TYPE==DOORLOCK_TYPE_IG8030)
	// 1, 4 display
	const uint8_t LED_PORT[] = {IO_LED_N9, IO_LED_N13};
#elif (HW_REV==1)
	// 1, 2 display : IG5000
	const uint8_t LED_PORT[] = {IO_LED_N1, IO_LED_N2};
#elif (HW_REV==2)||(HW_REV==5)||(HW_REV==7)
	// 1, 2 display : IG7020 / IG7000 / IG7001 / IG7040
	const uint8_t LED_PORT[] = {IO_LED_N11, IO_LED_N10};
#elif (HW_REV==3)||(HW_REV==4)||(HW_REV==6)
	// 1, 4 display : IG6000 / IG8000 / IG8807 / IG8008 / IG 5001
	const uint8_t LED_PORT[] = {IO_LED_N12, IO_LED_N11};
#elif (HW_REV==8)
	// 0, 9 display : IG7030
	const uint8_t LED_PORT[] = {IO_LED_N11, IO_LED_N9};
#else
	#define HW_NOTI_NOT_DEFINED
#endif

void ErrorNoti(uint8_t level)
{
	#ifndef HW_NOTI_NOT_DEFINED
		uint8_t count = 3;

		while(count--)
		{
			nrf_gpio_pin_set(LED_PORT[level]);
			nrf_delay_ms(200);
			nrf_gpio_pin_clear(LED_PORT[level]);
			nrf_delay_ms(200);
		}
	#else
		NRF_LOG_RAW_INFO("no HW init error notification : HW type not defined !!!\r\n");
	#endif
}
#endif



// reset reason
#define RESET_POWER						0x01			// power on reset
#define RESET_DOG							0x02			// watchdog reset
#define RESET_SREQ						0x04			// soft reset
#define RESET_LOCKUP						0x08			// cpu lockup reset
#define RESET_OFF							0x10			// gpio reset when system off mode
#define RESET_LPCOMP						0x20			// lpcomp reset when system off mode
#define RESET_DIF							0x40			// degub interface reset when system off mode
#define RESET_NFC							0x80			// not available in nrf51


/*
Note: Unless cleared, the RESETREAS register will be cumulative. A field is cleared by writing '1' to it. If none of the reset sources are flagged, this indicates
that the chip was reset from the on-chip reset generator, which will indicate a power-on-reset or a brown out reset.
*/
static void resetCheck(void)
{
#ifdef MSG_DEVICE_INFO
	NRF_LOG_RAW_INFO("\r\n");
	NRF_LOG_RAW_INFO("\r\n");
#endif

	if(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)
	{
		resetType |= RESET_POWER;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_POWER ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_DOG_Msk)
	{
		resetType |= RESET_DOG;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_DOG_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_DOG ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_SREQ_Msk)
	{
		resetType |= RESET_SREQ;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_SREQ_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_SREQ ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_LOCKUP_Msk)
	{
		resetType |= RESET_LOCKUP;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_LOCKUP_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_LOCKUP ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_OFF_Msk)
	{
		resetType |= RESET_OFF;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_OFF_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_OFF ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_LPCOMP_Msk)
	{
		resetType |= RESET_LPCOMP;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_LPCOMP_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_LPCOMP ***\r\n");
#endif
	}
	if(NRF_POWER->RESETREAS & POWER_RESETREAS_DIF_Msk)
	{
		resetType |= RESET_DIF;
		NRF_POWER->RESETREAS |= POWER_RESETREAS_DIF_Msk;
#ifdef MSG_DEVICE_INFO
		NRF_LOG_RAW_INFO("*** reset : RESET_DIF ***\r\n");
#endif
	}
}



#ifdef MSG_DEVICE_INFO
void displayDeviceInfo1(void)
{
//	NRF_LOG_INIT(NULL);
	NRF_LOG_RAW_INFO("*** system start ***\r\n"); 
#ifdef FEATURE_MULTI_FAMILY
	NRF_LOG_RAW_INFO("* target : %s-MF\r\n", (uint32_t)DOOR_LOCK_DEST);	 
#else
	NRF_LOG_RAW_INFO("* target : %s-HOME\r\n", (uint32_t)DOOR_LOCK_DEST);	 
#endif
	NRF_LOG_RAW_INFO("* doorlock type : %d\r\n", DOORLOCK_TYPE);
	NRF_LOG_RAW_INFO("* HW version : %d\r\n", HW_REV);
	NRF_LOG_RAW_INFO("* FW version : %d.%02d\r\n", FW_MAJOR, FW_MINOR);
	NRF_LOG_RAW_INFO("* build date : %s %s\r\n", (uint32_t)__DATE__, (uint32_t)__TIME__);
	NRF_LOG_FLUSH();
	NRF_LOG_RAW_INFO("* ram - global paramter addr : 0x%08X, size : 0x%04X\r\n", RAM_GLOBAL_ADDRESS, sizeof(ram_global_t));
	NRF_LOG_RAW_INFO("* flash - global paramter addr : 0x%08X, size : 0x%04X\r\n", FLASH_GLOBAL1_ADDR, sizeof(global_t));
	NRF_LOG_RAW_INFO("* flash - cbook header addr : 0x%08X\r\n", FLASH_CBOOK_HEAD_ADDR);
	NRF_LOG_RAW_INFO("* flash - cbook addr : 0x%08X\r\n", FLASH_CBOOK_ADDR);
#ifdef DUAL_FLASH_USE
	NRF_LOG_RAW_INFO("* flash - global paramter backup addr : 0x%08X\r\n", FLASH_GLOBAL1_BACKUP_ADDR);
#endif
	NRF_LOG_RAW_INFO("* flash - log addr : 0x%08X, cnt : %d\r\n", FLASH_LOG_ADDR, MAX_LOGS);
	NRF_LOG_RAW_INFO("* flash - bootloader addr : 0x%08X\r\n", BOOTLOADER_ADDRESS);
	NRF_LOG_FLUSH();

#ifdef RTC_BACKUP_USE
	NRF_LOG_RAW_INFO("* backup time : %04u.%02u.%02u %02u:%02u:%02u\r\n",			\
							mp_ram_global->rtcBackupTime.year, mp_ram_global->rtcBackupTime.month, mp_ram_global->rtcBackupTime.day,		\
							mp_ram_global->rtcBackupTime.hours, mp_ram_global->rtcBackupTime.minutes, mp_ram_global->rtcBackupTime.seconds);
#endif
}

void displayDeviceInfo2(void)
{
	uint32_t err_code __attribute__((unused));
	bool IsReset;
	ble_date_time_t bdt;

	err_code = drv_rtc_date_time_read(&bdt, &IsReset);
	NRF_LOG_RAW_INFO("* RTC time    : %04u.%02u.%02u %02u:%02u:%02u\r\n",			\
							bdt.year, bdt.month, bdt.day, bdt.hours, bdt.minutes, bdt.seconds);

	print_mac_addr(m_MAC_Address[0]);
	print_mac_addr(m_MAC_Address[1]);
	NRF_LOG_RAW_INFO("* device name : %s\r\n", (uint32_t)DEVICE_NAME);
	NRF_LOG_RAW_INFO("\r\n");
#ifdef OP_MODE_CHANGE_SUPPORT
	uint8_t *puicr = (uint8_t *)(DEVICE_ID_STORAGE_ADDR + 0x10);
	NRF_LOG_RAW_INFO("* mode change use : %d\r\n", puicr[22]);
#endif
}

void displayDeviceInfo3(void)
{
#ifdef OTP_V3_USE
	NRF_LOG_RAW_INFO("* pincode V3 use : %d\r\n", m_global.dotp_seq_v3_enable);
#endif
#ifdef FEATURE_DOOR_STATE_SENSOR
	NRF_LOG_RAW_INFO("* trepass use : %d\r\n", m_global.trepassUse);
#endif
#ifdef PERMANENT_PIN_USE
	NRF_LOG_RAW_INFO("* permanent Pin use : %d\r\n", m_global.permanentPinUse);
#endif
}
#endif


#ifdef FEATURE_TEST_MODE
void setTestMode(void)
{
	uint8_t * pParam = (uint8_t*)DEVICE_ID_STORAGE_ADDR+0x10;
	m_main_test_mode = pParam[20];
//		NRF_LOG_RAW_INFO("Test Mode Param : 0x%X\r\n", m_main_test_mode);
}
#endif


void setUserArea(void)
{
	uint8_t * pParam = (uint8_t*)DEVICE_ID_STORAGE_ADDR+0x10;

	m_nfc_test_mode = pParam[24];
	m_nfc_test_TxControlReg = (pParam[25] == 0xFF) ? NFC_TX_CONTROL_VALUE : pParam[25];
//		NRF_LOG_RAW_INFO("Nfc Test Mode : 0x%02x, Tx Control Reg: 0x%02x\r\n", m_nfc_test_mode, m_nfc_test_TxControlReg);

	m_nfc_test_interval = (pParam[26] == 0xFF) ? NFC_POLLING_INTERVAL_MS : (pParam[26]*10);
	m_nfc_test_sampling_delay = (pParam[27] == 0xFF) ? 0 : pParam[27]*10;
//		NRF_LOG_RAW_INFO("m_nfc_test_interval : %u (msec), m_nfc_test_sampling_delay : %u (usec)\r\n", m_nfc_test_interval, m_nfc_test_sampling_delay);

	m_log_save_control = (pParam[18] == 0xFF) ? 0 : pParam[18];
//		NRF_LOG_RAW_INFO("m_log_save_control : 0x%02X\r\n", m_log_save_control);

	m_rtc_option = (pParam[21] == 0xFF) ? RTC_DEFAULT_OPTION : pParam[21];
//		NRF_LOG_RAW_INFO("m_rtc_option : 0x%02X\r\n", m_rtc_option);
}


#ifdef FEATURE_PRODUCTION_LOCK
void setProductionLock(void)
{
	// Check if read-back mechanism is turned ON.
	if((uint32_t)((NRF_UICR->RBPCONF & UICR_RBPCONF_PALL_Msk) >> UICR_RBPCONF_PALL_Pos) != UICR_RBPCONF_PALL_Enabled)
	{
		NRF_NVMC->CONFIG=1;
		NRF_UICR->RBPCONF=0;
#ifdef DEBUG_PRINT
		NRF_LOG_RAW_INFO("NRF LOCKING\r\n");
#endif
	}
	else
	{
#ifdef DEBUG_PRINT
		NRF_LOG_RAW_INFO("NRF LOCKED\r\n");
#endif
	}
}
#endif

void selectRtcSrc(void)
{
#ifdef MSG_RTC
	NRF_LOG_RAW_INFO("@%s-1 option : %d\r\n", M_FUNCTION, m_rtc_option);
#endif
	switch (m_rtc_option)
	{
		case 1:							// RC
		case 2:							// SYNC
			initRTC(false);
		break;

		default:							// XTAL
			if(CheckRTC() < RTC_CLOCK_LIMIT)
			{
//				ble_stack_init_post();
				m_rtc_option = 2;
				initRTC(false);
			}
		break;
	}

#ifdef MSG_RTC
	NRF_LOG_RAW_INFO("@%s-2 RTC clock count : %d, option : %d\r\n", M_FUNCTION, CheckRTC(), m_rtc_option);
#endif
}



static uint8_t app_sched_queue_empty2(void)
{
	uint8_t temp = m_queue_start_index;

	return m_queue_end_index == temp;
}


static void initLedOn(void) __attribute__((unused));
static void initLedOn(void)
{
#if (DOORLOCK_TYPE == DOORLOCK_TYPE_IG8008)
	nrf_gpio_cfg_output(19);					// dual close
	nrf_gpio_pin_clear(19);
	nrf_gpio_cfg_output(29);					// low battery		
	nrf_gpio_pin_clear(29);
	nrf_gpio_cfg_output(16);					// nfc
	nrf_gpio_pin_clear(16);
	nrf_gpio_cfg_output(13);					// door open
	nrf_gpio_pin_clear(13);
#endif
}


/**@brief Function for application main entry.
 */
int main(void)
{
#if 0
	uint32_t err_code __attribute__((unused));
	bool bhwErrorOccurred __attribute__((unused)) = false;

	nrf_delay_ms(200);						// stability delay : old-500mS
	NRF_LOG_INIT(NULL);
	resetCheck();								// reset reason check : mtkim add

#ifdef MSG_DEVICE_INFO
	displayDeviceInfo1();					// device info output
#endif

#ifdef FEATURE_TEST_MODE
	setTestMode();
#endif

	setUserArea();

#ifdef FEATURE_PRODUCTION_LOCK
	setProductionLock();
#endif

	io_default_setting();
//	INPUT_PIN_CHECK2();
	RAM_Global_Init();

	initFlash();




#ifndef TWI_SW_MASTER_USE
	twi_config();
#else
	/*
	* @return
	 * @retval true TWI bus is clear for transfers.
	 * @retval false TWI bus is stuck.	--> ???
	 */
//	if(!twi_master_init())		// why not ???
	if(twi_master_init())
	{
		#ifdef HALT_ON_I2C_FAILURE
			NRF_LOG_RAW_INFO("I2C init fail !!!\r\n");
			bhwErrorOccurred = true;
			ErrorNoti(0);
		#endif
	}
#endif

#ifndef INTERNAL_RTC_USE
	initRTC(true);
	if(CheckRTC() < RTC_CLOCK_LIMIT)
	{
		#ifdef HALT_ON_RTC_FAILURE
			NRF_LOG_RAW_INFO("RTC init fail !!!\r\n");
			bhwErrorOccurred = true;
			ErrorNoti(1);
		#endif
	}
#else
	m_rtc_option = 1;			// internal RC use
#endif


#if 0	// defined(HALT_ON_I2C_FAILURE) || defined(HALT_ON_RTC_FAILURE)
	if(bhwErrorOccurred)
	{
		NRF_LOG_RAW_INFO("SYSTEM HALT for HW init error !!!\r\n");
		for(;;);
	}
#endif


	// RTC SET
	selectRtcSrc();
	ble_stack_init(m_rtc_option);
	timers_init();
	radio_notification_init();
	device_name_init();

#ifdef RTC_BACKUP_USE
    rtc_timer_init();
#endif

#ifdef MSG_DEVICE_INFO
	displayDeviceInfo2();
#endif

	scheduler_init();

	nrf_drv_rng_init(NULL);

	gap_params_init(false);
////	advertising_init();
	services_init();
	conn_params_init();

	// 2019-01-23 (yeyun) Soft Reset À» ¸ÕÀú Clear ÇÑ´Ù.
	if(IsSoftReset())
	{
		ClearSoftResetFlag();
	}

#ifdef FEATURE_CRYSTAL_TEST
    sd_clock_hfclk_request();
#endif

#ifdef DEBUG_PRINT_GLOBAL
    NRF_LOG_RAW_INFO("\t\t CODEBOOK(%d) - ", get_active_codebook_count());
    dump_8_array(NULL, m_codebook_status, MAX_CODEBOOK_NUM);
#endif


// test
#ifdef SCAN_TEST_USE
	while(1)
	{
//		scanSensitivity();
		scanRawData();
		nrf_delay_ms(50);

	}
#endif

	m_doorlock_init();

#ifdef MSG_DEVICE_INFO
	displayDeviceInfo3();
	NRF_LOG_RAW_INFO("\r\n");
#endif


#ifndef FEATURE_CRYSTAL_TEST
#ifdef WATCHDOG_ENABLE
	watchdog_init();
	watchdog_reset();
#endif
#endif


	// Enter main loop.
	for(;;)
	{
		app_sched_execute();

#ifdef DOORLOCK_RELEASE
		if(app_sched_queue_empty2())
#else
		if(app_sched_queue_empty2() && (NRF_LOG_PROCESS() == false))
#endif
		{
			power_manage();
#ifdef WATCHDOG_ENABLE
			watchdog_reset();
#endif
		}
	}





#else
	uint32_t err_code __attribute__((unused));
	bool bhwErrorOccurred __attribute__((unused)) = false;

	nrf_delay_ms(200);						// stability delay : old-500mS
	err_code = NRF_LOG_INIT(NULL);
	DL_APP_ERROR_CHECK(err_code);
	NRF_LOG_DEFAULT_BACKENDS_INIT();

	resetCheck();								// reset reason check : mtkim add

	// RTC SET
//	selectRtcSrc();
	ble_stack_init(1);


	while(1)
	{
		NRF_LOG_INFO("test\r\n");
	};



#ifdef MSG_DEVICE_INFO
	displayDeviceInfo1();					// device info output
#endif

#ifdef FEATURE_TEST_MODE
	setTestMode();
#endif

	setUserArea();

#ifdef FEATURE_PRODUCTION_LOCK
	setProductionLock();
#endif

	io_default_setting();
//	INPUT_PIN_CHECK2();
	RAM_Global_Init();

	initFlash();




#ifndef TWI_SW_MASTER_USE
	twi_config();
#else
	/*
	* @return
	 * @retval true TWI bus is clear for transfers.
	 * @retval false TWI bus is stuck.	--> ???
	 */
//	if(!twi_master_init())		// why not ???
	if(twi_master_init())
	{
		#ifdef HALT_ON_I2C_FAILURE
			NRF_LOG_RAW_INFO("I2C init fail !!!\r\n");
			bhwErrorOccurred = true;
			ErrorNoti(0);
		#endif
	}
#endif

#ifndef INTERNAL_RTC_USE
	initRTC(true);
	if(CheckRTC() < RTC_CLOCK_LIMIT)
	{
		#ifdef HALT_ON_RTC_FAILURE
			NRF_LOG_RAW_INFO("RTC init fail !!!\r\n");
			bhwErrorOccurred = true;
			ErrorNoti(1);
		#endif
	}
#else
	m_rtc_option = 1;			// internal RC use
#endif


#if 0	// defined(HALT_ON_I2C_FAILURE) || defined(HALT_ON_RTC_FAILURE)
	if(bhwErrorOccurred)
	{
		NRF_LOG_RAW_INFO("SYSTEM HALT for HW init error !!!\r\n");
		for(;;);
	}
#endif


	// RTC SET
	selectRtcSrc();
	ble_stack_init(m_rtc_option);
	timers_init();
	radio_notification_init();
	device_name_init();

#ifdef RTC_BACKUP_USE
    rtc_timer_init();
#endif

#ifdef MSG_DEVICE_INFO
	displayDeviceInfo2();
#endif

	scheduler_init();

	nrf_drv_rng_init(NULL);

	gap_params_init(false);
////	advertising_init();
	services_init();
	conn_params_init();

	// 2019-01-23 (yeyun) Soft Reset À» ¸ÕÀú Clear ÇÑ´Ù.
	if(IsSoftReset())
	{
		ClearSoftResetFlag();
	}

#ifdef FEATURE_CRYSTAL_TEST
    sd_clock_hfclk_request();
#endif

#ifdef DEBUG_PRINT_GLOBAL
    NRF_LOG_RAW_INFO("\t\t CODEBOOK(%d) - ", get_active_codebook_count());
    dump_8_array(NULL, m_codebook_status, MAX_CODEBOOK_NUM);
#endif


// test
#ifdef SCAN_TEST_USE
	while(1)
	{
//		scanSensitivity();
		scanRawData();
		nrf_delay_ms(50);

	}
#endif

	m_doorlock_init();

#ifdef MSG_DEVICE_INFO
	displayDeviceInfo3();
	NRF_LOG_RAW_INFO("\r\n");
#endif


#ifndef FEATURE_CRYSTAL_TEST
#ifdef WATCHDOG_ENABLE
	watchdog_init();
	watchdog_reset();
#endif
#endif


	// Enter main loop.
	for(;;)
	{
		app_sched_execute();

#ifdef DOORLOCK_RELEASE
		if(app_sched_queue_empty2())
#else
		if(app_sched_queue_empty2() && (NRF_LOG_PROCESS() == false))
#endif
		{
			power_manage();
#ifdef WATCHDOG_ENABLE
			watchdog_reset();
#endif
		}
	}

#endif



}



/**
 * @}
 */
