/**
 * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 *
 * @defgroup ble_sdk_app_template_main main.c
 * @{
 * @ingroup ble_sdk_app_template
 * @brief Template project main file.
 *
 * This file contains a template for creating a new application. It has the code necessary to wakeup
 * from button, advertise, get a connection restart advertising on disconnect and if no new
 * connection created go back to system-off mode.
 * It can easily be used as a starting point for creating a new application, the comments identified
 * with 'YOUR_JOB' indicates where and how you can customize.
 */

#include <nrfx.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "nrf_nvmc.h"

#include "app_error.h"
#include "app_timer.h"
#include "ble.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_conn_state.h"
#include "ble_cus.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "bsp_btn_ble.h"
#include "fds.h"
#include "nordic_common.h"
#include "nrf.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_gpiote.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_sdh_soc.h"
#include "nrf_soc.h"
#include "peer_manager.h"
#include "peer_manager_handler.h"
#include "sensorsim.h"
#include <ble_dis.h>

#include "nrf_fstorage.h"

#include "nrf_fstorage_sd.h"

// BEGIN Block Added for DFU
#include "C:\Nordic\SDK\nRF5SDK17009d13099\nRF5_SDK_17.0.0_9d13099\components\libraries\bootloader\nrf_bootloader_info.h"
#include "ble_dfu.h"
#include "nrf_dfu_ble_svci_bond_sharing.h"
#include "nrf_svci_async_function.h"
#include "nrf_svci_async_handler.h"
// END Block Added for DFU


//UART


#include "nrf_libuarte_async.h"
#include "nrf_drv_clock.h"
#include <bsp.h>
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"
#include "nrf_delay.h"



//UART




//---------------------------------------- Device Information ---------------------------------------------------------------------------------
#define DEVICE_NAME "Muqarrrab"                /**< Name of device. Will be included in the advertising data. */
#define MANUFACTURER_NAME "Rahman" /**< Manufacturer. Will be passed to Device Information Service. */
#define MODEL_NUMBER "Muqarrab"
#define SERIAL_NUMBER "1"  ///3P0-2603218-plus  //3P0-2603218-pro
#define HARDWARE_NUMBER "1"
#define FIRMWARE_NUMBER "1"
//---------------------------------------------------------------------------------------------------------------------------------------------

#define APP_ADV_INTERVAL 32     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
#define APP_ADV_DURATION 0      /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_BLE_CONN_CFG_TAG 1  /**< A tag identifying the SoftDevice BLE configuration. */

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.1 seconds). */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(45, UNIT_1_25_MS) /**< Maximum acceptable connection interval (0.2 second). */
#define SLAVE_LATENCY 0                                   /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)  /**< Connection supervisory timeout (4 seconds). */

#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3                       /**< Number of attempts before giving up the connection parameter negotiation. */

#define SEC_PARAM_BOND 1                               /**< Perform bonding. */
#define SEC_PARAM_MITM 0                               /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC 0                               /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS 0                           /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
#define SEC_PARAM_OOB 0                                /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE 7                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE 16                      /**< Maximum encryption key size. */

#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

//---------------------------------------- Pins Assignmnets ---------------------------------------------------------------------------------
#define State_LED NRF_GPIO_PIN_MAP(0, 15)
#define Function_LED NRF_GPIO_PIN_MAP(0, 10)


#define Lock_Pin NRF_GPIO_PIN_MAP(0, 2)
#define UnLock_Pin NRF_GPIO_PIN_MAP(0, 4)
#define Trunk_Pin NRF_GPIO_PIN_MAP(1, 9)
#define Engin_Kill_Pin NRF_GPIO_PIN_MAP(0, 26)
#define Indicator_Pin NRF_GPIO_PIN_MAP(0, 29)

#define ACC_Pin NRF_GPIO_PIN_MAP(0, 20)
#define On_Off_Pin NRF_GPIO_PIN_MAP(1, 11)
#define Start_Pin NRF_GPIO_PIN_MAP(1, 12)
#define Power_Output NRF_GPIO_PIN_MAP(1, 7)

#define N_Door_Feedback NRF_GPIO_PIN_MAP(1, 13)
#define P_Door_Feedback NRF_GPIO_PIN_MAP(1, 15)

#define Power_Feedback NRF_GPIO_PIN_MAP(1, 14)
//---------------------------------------------------------------------------------------------------------------------------------------------

//UART
NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

static uint8_t text[] = "UART example started5.\r\nLoopback:\r\n";
static uint8_t text_size = sizeof(text);
static volatile bool m_loopback_phase;

static uint8_t command[]="123456789012345123456534623465351235412344123412341234";

unsigned char received_data[200];
int count_data=0;

bool data_completed=false;


typedef struct {
    uint8_t * p_data;
    uint32_t length;
} buffer_t;

NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);



//UART


NRF_BLE_GATT_DEF(m_gatt);           /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr);             /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */

BLE_CUS_DEF(m_cus);

APP_TIMER_DEF(Blink_LED);
APP_TIMER_DEF(Delay_Event);
APP_TIMER_DEF(Flash);
APP_TIMER_DEF(Push_Power_Pulse);
APP_TIMER_DEF(Disconnect_Commands);
APP_TIMER_DEF(Engin_Kill_Timer);
APP_TIMER_DEF(Engin_Kill_Flash);
APP_TIMER_DEF(Regular_Check_Timer);
APP_TIMER_DEF(Proximity_Stop_Timer);

ble_cus_t *p_cus;

/**@brief Timeout handler for the single shot timer.
 */

static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */

/* YOUR_JOB: Declare all services structure your application is using
 *  BLE_XYZ_DEF(m_xyz);
 */

// YOUR_JOB: Use UUIDs for service(s) used in your application.
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */
    {
        {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
        // YOUR_JOB: Use UUIDs for service(s) used in your application.
        {CUSTOM_SERVICE_UUID, BLE_UUID_TYPE_VENDOR_BEGIN} /**< Universally unique service identifiers. */

};

/////////////////////////////////////////////////////////////////// Timers  ////////////////////////////////////////////////////////////

static uint32_t lock_delay = 800;
static uint32_t unlock_delay = 800;
static uint32_t trunk_delay = 800;

/////////////////////////////////////////////////////////////////// Timers Part Ends  ///////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// Keys Part Start  ////////////////////////////////////////////////////////////

uint8_t masterkey1 = 10;
uint8_t masterkey2 = 10;
uint8_t regularkey1 = 10;
uint8_t regularkey2 = 10;

int feedback = 0;
int masterokforeg = 0;
int regchange = 0;
int regchgc = 0;
int masterchange = 0;
int masterchgc = 0;
uint8_t masterkeyinput;
uint8_t regularkeyinput;
uint8_t keycheck;
int regularchk = 0;
int masterchk = 0;

/////////////////////////////////////////////////////////////////// Keys Part End  ////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////// Regular checks End   //////////////////////////////////////////////////////////

int adv_off = 0;
int wrong_counter_reg = 0;
int wrong_counter_master = 0;
int no_of_tries = 10;

int indicator_counter_1 = 0;
int indicator_counter_2 = 0;

int notify_check = 0;
uint8_t notify_value = 0;

////////////////////////////////////////////////////////////////// Regular checks ///////////////////////////////////////////////////////////

int regular_chk = 0;
int master_chk = 0;

int Disconnect_Lock = 1;
int verified_lock = 0;

int Smart_key_State = 0;
int Car_Type = 1;

int push_state_chk = 0;
int push_state_counter = 0;
int push_state_change = 0;

int indicator_speed = 0;
int indicator_counter = 0;

int verified_engine_kill = 0;
int Engin_Kill_Setting = 0;
int Engin_Kill_Time = 1;
int toggle_flash = 0;
int indicator_toggle = 0;
int i_counter = 0;

int regular_key_expire = 0;
int share_check = 0;

int prox_stop_value = 0;
int prox_stop_timer = 5000;
int prox_toggle = 0;
int prox_counter = 1;

int Door_Status = 3;   //3 for Lock 4 for unlock
int feedback_wire = 2; //1 for Unlock 2 for Lock
int door_update = 2;   //1 for Unlock 2 for Lock
int Lock_Wires = 2;    //2
int stop_delay = 0;

////////////////////////////////////////////////////////////////// Regular checks End///////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////// Characters input ///////////////////////////////////////////////////////////

uint8_t lock_engine_test = 0;
uint8_t lock_engine = 0;

uint8_t self_start_test = 0;
uint8_t self_start = 0;

int start_on_check = 0;
int start_check = 0;
int start_timer = 750;

uint8_t timer_test = 0;
uint8_t timer = 0x13;

int push_power_on = 0;

uint8_t setting_test = 0;
uint8_t setting = 0x01;
uint8_t test_bit = 0;

///////////////////////////////////////////////////////////////   Connection Checks   //////////////////////////////////////////////////////////////
int connection_state = 0;
int toggle = 0;
int pins_chk = 0;
int blink_time = 2000;

uint8_t retain_on = 0; //////// 1st bit For Engine Kill
                       //////// 2nd bit For Smart Key

uint8_t retain_test_bit = 0;

/**@brief   Sleep until an event is received. */
static void power_manage(void) {
  (void)sd_app_evt_wait();
}

/////////////////////////////////////////////////////////////////////////////// SNV ////////////////////////////////////////////////////

bool write_to_flash = false;
int memory_option = 0;

char read_data[] = "1010101";
char __attribute__((aligned)) save_data[] = "1010000";

char __attribute__((aligned)) device_keys[] = "1010101";

const uint8_t memory_page=0x67;
const uint32_t flash_start_address = 0x67000;
const uint32_t flash_end_address = 0x6ffff;

static void fstorage_evt_handler(nrf_fstorage_evt_t *p_evt);

NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
    {
        /* Set a handler for fstorage events. */
        .evt_handler = fstorage_evt_handler,

        /* These below are the boundaries of the flash space assigned to this instance of fstorage.
     * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
     * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
     * last page of flash available to write data. */
        .start_addr = flash_start_address,
        .end_addr = flash_end_address,
};

static void print_flash_info(nrf_fstorage_t *p_fstorage) {
  NRF_LOG_INFO("========| flash info |========");
  NRF_LOG_INFO("erase unit: \t%d bytes", p_fstorage->p_flash_info->erase_unit);
  NRF_LOG_INFO("program unit: \t%d bytes", p_fstorage->p_flash_info->program_unit);
  NRF_LOG_INFO("==============================");
}

void wait_for_flash_ready(nrf_fstorage_t const *p_fstorage) {
  /* While fstorage is busy, sleep and wait for an event. */
  while (nrf_fstorage_is_busy(p_fstorage)) {
    power_manage();
  }
}

void write_in_flash(uint8_t place) {
  ret_code_t rc;
  if (place == 1) {

    save_data[0] = 0x10;
    save_data[1] = 0x20;
    save_data[2] = 0x30;
    save_data[3] = 0x40;
    save_data[4] = 0x50;
    save_data[5] = 0x60;
    save_data[6] = 0x70;
    
    sd_flash_page_erase(memory_page);
    rc = nrf_fstorage_write(&fstorage, flash_start_address + 16, save_data, sizeof(save_data), NULL);
    APP_ERROR_CHECK(rc);
    wait_for_flash_ready(&fstorage);

    device_keys[0] = 0x0A;
    device_keys[1] = 0x0A;
    device_keys[2] = 0x0A;
    device_keys[3] = 0x0A;
    device_keys[4] = 0x13;
    device_keys[5] = 0x01;
    device_keys[6] = 0x00;

    rc = nrf_fstorage_write(&fstorage, flash_start_address + 32, device_keys, sizeof(save_data), NULL);
    APP_ERROR_CHECK(rc);
    wait_for_flash_ready(&fstorage);
  } else if (place == 2) {
    save_data[0] = 0x10;
    save_data[1] = 0x20;
    save_data[2] = 0x30;
    save_data[3] = 0x40;
    save_data[4] = 0x50;
    save_data[5] = 0x60;
    save_data[6] = 0x70;

    sd_flash_page_erase(memory_page);
    rc = nrf_fstorage_write(&fstorage, flash_start_address + 16, save_data, sizeof(save_data), NULL);
    APP_ERROR_CHECK(rc);
    wait_for_flash_ready(&fstorage);

    rc = nrf_fstorage_write(&fstorage, flash_start_address + 32, device_keys, sizeof(save_data), NULL);
    APP_ERROR_CHECK(rc);
    wait_for_flash_ready(&fstorage);
  }

  NRF_LOG_INFO("Memory Write Completed");
}
void read_in_flash(uint8_t place) {
  ret_code_t rc;

  if (place == 1) {
    rc = nrf_fstorage_read(&fstorage, flash_start_address + 16, read_data, sizeof(save_data));
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);

    //NRF_LOG_INFO("Reading from flash hex:");
    //for (uint8_t i = 0; i < sizeof(read_data); i++) {
    //  NRF_LOG_RAW_INFO("%02x:", read_data[i]);
    //}

    if (read_data[0] == 0x10 && read_data[1] == 0x20 && read_data[2] == 0x30 && read_data[3] == 0x40 && read_data[4] == 0x50 && read_data[5] == 0x60) {
      NRF_LOG_INFO("Memory is Not Blank");
      rc = nrf_fstorage_read(&fstorage, flash_start_address + 32, device_keys, sizeof(save_data));
      APP_ERROR_CHECK(rc);

      wait_for_flash_ready(&fstorage);

      //NRF_LOG_INFO("Reading from flash hex:");
      //for (uint8_t i = 0; i < sizeof(read_data); i++) {
      //  NRF_LOG_RAW_INFO("%02x:", device_keys[i]);
      //}

    } else {
      NRF_LOG_INFO("Memory is Blank");
      write_in_flash(1);
    }
  } else if (place == 2) {
    place = place * 16;
    rc = nrf_fstorage_read(&fstorage, flash_start_address + 32, device_keys, sizeof(save_data));
    APP_ERROR_CHECK(rc);

    wait_for_flash_ready(&fstorage);

    //NRF_LOG_INFO("Reading from flash hex:");
    //for (uint8_t i = 0; i < sizeof(read_data); i++) {
    //  NRF_LOG_RAW_INFO("%02x:", device_keys[i]);
    //}
  }
  masterkey1 = device_keys[0];
  masterkey2 = device_keys[1];
  regularkey1 = device_keys[2];
  regularkey2 = device_keys[3];
  timer = device_keys[4];
  setting = device_keys[5];
  retain_on = device_keys[6];

  /////////////////////////////////////////////////////////////////////////////////// Timers
  timer_test = timer & 0xF0;

  if (timer_test == 0x10) {
    Engin_Kill_Time = 1;
  } else if (timer_test == 0x20) {
    Engin_Kill_Time = 2;
  } else if (timer_test == 0x30) {
    Engin_Kill_Time = 3;
  } else if (timer_test == 0x40) {
    Engin_Kill_Time = 4;
  } else if (timer_test == 0x50) {
    Engin_Kill_Time = 5;
  } else if (timer_test == 0x60) {
    Engin_Kill_Time = 6;
  } else if (timer_test == 0x70) {
    Engin_Kill_Time = 7;
  } else if (timer_test == 0x80) {
    Engin_Kill_Time = 8;
  } else if (timer_test == 0x90) {
    Engin_Kill_Time = 9;
  } else if (timer_test == 0xA0) {
    Engin_Kill_Time = 10;
  } else {
    Engin_Kill_Time = 1;
  }

  timer_test = timer & 0x0F;
  if (timer_test == 1) {
    start_timer = 250;
  } else if (timer_test == 2) {
    start_timer = 500;
  } else if (timer_test == 3) {
    start_timer = 750;
  } else if (timer_test == 4) {
    start_timer = 1000;
  } else if (timer_test == 5) {
    start_timer = 1250;
  } else if (timer_test == 6) {
    start_timer = 1500;
  } else if (timer_test == 7) {
    start_timer = 1750;
  } else if (timer_test == 8) {
    start_timer = 2000;
  } else if (timer_test == 9) {
    start_timer = 2250;
  } else if (timer_test == 10) {
    start_timer = 2500;
  } else {
    start_timer = 750;
  }
  /////////////////////////////////////////////////////////////////////////////////// Timers End

  /////////////////////////////////////////////////////////////////////////////////// Settings

  test_bit = setting & 0x01;
  if (test_bit == 1) {
    Disconnect_Lock = 1;
  } else {
    Disconnect_Lock = 0;
  }
  test_bit = setting & 0x02;
  if (test_bit == 2) {
    Engin_Kill_Setting = 1;
    nrf_gpio_pin_set(Engin_Kill_Pin);
    lock_engine = lock_engine & 0x0F;
    lock_engine = lock_engine | 0x30;
    ble_cus_custom_value_update(p_cus, lock_engine, 4);
  }
  test_bit = setting & 0x04;
  if (test_bit == 4) {
    Smart_key_State = 1;
  } else {
    Smart_key_State = 0;
  }
  test_bit = setting & 0x08;
  if (test_bit == 8) {
    Car_Type = 2;
  } else {
    Car_Type = 1;
  }
  test_bit = setting & 0x40;
  if (test_bit == 0x40) {
    Lock_Wires = 1;
  } else {
    Lock_Wires = 2;
  }
  test_bit = setting & 0x80;
  if (test_bit == 0x80) {
    feedback_wire = 1;
  } else {
    feedback_wire = 2;
  }
  /////////////////////////////////////////////////////////////////////////////////// Settings End

  retain_test_bit = retain_on & 0x01;
  if (Engin_Kill_Setting == 1 || retain_test_bit == 1) {
    nrf_gpio_pin_set(Engin_Kill_Pin);
    lock_engine = lock_engine & 0x0F;
    lock_engine = lock_engine | 0x30;
    ble_cus_custom_value_update(p_cus, lock_engine, 4);
  }

  retain_test_bit = retain_on & 0x02;
  if (Car_Type == 2 && retain_test_bit == 2 && Smart_key_State == 1) {
    nrf_gpio_pin_set(ACC_Pin);
    nrf_gpio_pin_set(Power_Output);
    self_start = self_start & 0xF0;
    self_start = self_start | 0x05;
    ble_cus_custom_value_update(p_cus, self_start, 5);
  }

  ble_cus_custom_value_update(p_cus, timer, 6);
  ble_cus_custom_value_update(p_cus, setting, 7);

  //NRF_LOG_INFO("\nMaster Key: %02x%02x",masterkey1,masterkey2);
  //NRF_LOG_INFO("Regular Key: %02x%02x",regularkey1,regularkey2);

  NRF_LOG_INFO("Memory Read Completed");
}
/////////////////////////////////////////////////////////////////////////////// SNV End //////////////////////////////////////////////////////

void Reset() {
  nrf_gpio_pin_clear(Indicator_Pin);
  nrf_gpio_pin_clear(Function_LED);
  nrf_gpio_pin_clear(Lock_Pin);
  nrf_gpio_pin_clear(UnLock_Pin);
  nrf_gpio_pin_clear(Trunk_Pin);
  
  if(connection_state==1)
  {
    nrf_gpio_pin_set(State_LED);
  }
  
}

/////////////////////////////////////////////////////////////////////////////// Charcteristics Initialize
void Charcteristics_Init(ble_cus_t *d_cus) {
  p_cus = d_cus;

  ble_cus_custom_value_update(p_cus, 0, 1);
  ble_cus_custom_value_update(p_cus, 0, 2);
  ble_cus_custom_value_update(p_cus, 0, 3);
  ble_cus_custom_value_update(p_cus, 0, 4);
  ble_cus_custom_value_update(p_cus, 0, 5);
  ble_cus_custom_value_update(p_cus, 0x13, 6);
  ble_cus_custom_value_update(p_cus, 0x01, 7);
  ble_cus_custom_value_update(p_cus, 0, 8);
  ble_cus_custom_value_update(p_cus, 0, 9);
  ble_cus_custom_value_update(p_cus, 0, 10);
}

/////////////////////////////////////////////////////////////////////////////// Charcteristics Functions
void Charcteristics_1(uint8_t test) {
  masterkeyinput = test;
  //////////////////     Check Master Key     ///////////////////////
  if (masterchk == 1) {
    if (masterkeyinput == masterkey1) {
      masterchk = 2;
      feedback = 13;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    } else {
      /*
                wrong_counter_master=wrong_counter_master+1;
                if(wrong_counter_master==no_of_tries)
                {
                  State_LED=0;
                  adv_off = 1;
                  GAPRole_TerminateConnection();
                  uint8 new_adv_enabled_status = FALSE;
                  GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &new_adv_enabled_status);
                  osal_start_timerEx(simpleBLEPeripheral_TaskID, Delay_Event, 300000);
                }
*/
      masterchk = 0;
      feedback = 0;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  } else if (masterchk == 2) {
    if (masterkeyinput == masterkey2) {
      if (keycheck == 4) {
        master_chk = 1;
        regular_chk = 1;
        verified_engine_kill = 1;
        verified_lock = 1;
        share_check = 0;
      } else {
        masterchk = 3;
        masterokforeg = 1;
        regchgc = 1;
      }
      NRF_LOG_INFO("Master Key Matched");
      wrong_counter_master = 0;
      feedback = 14;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    } else {
      /*
            wrong_counter_master=wrong_counter_master+1;
            if(wrong_counter_master==no_of_tries)
            {
              State_LED=0;
              adv_off = 1;
              GAPRole_TerminateConnection();
              uint8 new_adv_enabled_status = FALSE;
              GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &new_adv_enabled_status);
              osal_start_timerEx(simpleBLEPeripheral_TaskID, Delay_Event, 300000);
            }
  */
      masterchk = 0;
      feedback = 0;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  }
  //////////////////     Change Master Key     ///////////////////////
  else if (masterokforeg == 1 && masterchange == 1 && masterchk == 3) {
    if (masterchgc == 1) {
      masterchgc = 2;
      masterkey1 = masterkeyinput;

      feedback = 17;
      ble_cus_custom_value_update(p_cus, feedback, 3);

    } else if (masterchgc == 2) {
      masterkey2 = masterkeyinput;

      write_to_flash = true;
      memory_option = 2;
      device_keys[0] = masterkey1;
      device_keys[1] = masterkey2;

      masterchk = 3;
      masterokforeg = 0;
      regchange = 0;
      NRF_LOG_INFO("Master Key Changed");
      feedback = 18;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  }
}
void Charcteristics_2(uint8_t test) {
  regularkeyinput = test;
  //////////////////     Check Regular Key     ///////////////////////
  if (regularchk == 1) {
    if (regularkeyinput == regularkey1) {
      regularchk = 2;
      feedback = 11;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    } else {

      /*wrong_counter_reg=wrong_counter_reg+1;
                        if(wrong_counter_reg==no_of_tries)
                        {
                          State_LED=0;
                          adv_off = 1;
                          GAPRole_TerminateConnection();
                          uint8 new_adv_enabled_status = FALSE;
                          GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &new_adv_enabled_status);
                          osal_start_timerEx(simpleBLEPeripheral_TaskID, Delay_Event, 300000);
                        }
                        */
      regularchk = 0;
      feedback = 0;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  } else if (regularchk == 2) {
    if (regularkeyinput == regularkey2) {
      NRF_LOG_INFO("Regular Key Matched");
      regularchk = 0;
      feedback = 12;
      ble_cus_custom_value_update(p_cus, feedback, 3);
      ///////// Regular Checks

      wrong_counter_reg = 0;
      regular_chk = 1;
      verified_engine_kill = 1;
      verified_lock = 1;
      share_check = 1;
    } else {
      /*
                    wrong_counter_reg=wrong_counter_reg+1;
                    if(wrong_counter_reg==no_of_tries)
                    {
                      State_LED=0;
                      adv_off = 1;
                      GAPRole_TerminateConnection();
                      uint8 new_adv_enabled_status = FALSE;
                      GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &new_adv_enabled_status);
                      osal_start_timerEx(simpleBLEPeripheral_TaskID, Delay_Event, 300000);
                    }
        */
      regularchk = 0;
      feedback = 0;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  }
  //////////////////     Change Regular Key     ///////////////////////
  if (masterokforeg == 1 && regchange == 1) {
    if (regchgc == 1) {
      regchgc = 2;
      regularkey1 = regularkeyinput;

      feedback = 15;
      ble_cus_custom_value_update(p_cus, feedback, 3);

    } else if (regchgc == 2) {
      regularkey2 = regularkeyinput;

      write_to_flash = true;
      memory_option = 2;
      device_keys[2] = regularkey1;
      device_keys[3] = regularkey2;

      NRF_LOG_INFO("Regular Key Changed");

      masterokforeg = 0;
      regchange = 0;
      feedback = 16;
      ble_cus_custom_value_update(p_cus, feedback, 3);
    }
  }
}
void Charcteristics_3(uint8_t test) {
  keycheck = test;
  //////////////////     Check Regular Key     ///////////////////////
  if (keycheck == 1) {
    feedback = 0;
    regularchk = 1;
    masterokforeg = 0;
  }
  //////////////////     Change Regular Key     ///////////////////////
  else if (keycheck == 2) {
    regchgc = 0;
    feedback = 0;
    regchange = 1;
    masterchk = 1;
  }
  //////////////////     Change Master Key     ///////////////////////
  else if (keycheck == 3) {
    feedback = 0;
    masterchange = 1;
    masterchk = 1;
    masterchgc = 1;
  }
  //////////////////     Check Master Key     ///////////////////////
  else if (keycheck == 4) {
    feedback = 0;
    masterchk = 1;
    masterokforeg = 0;
  }
}
void Charcteristics_4(uint8_t test) {
  lock_engine_test = test;
  ret_code_t err_code;
  if (regular_chk == 1) {
    //////////////////     Lock     ///////////////////////
    if (lock_engine_test == 1) {
      if (Lock_Wires == 1) {
        if (Door_Status == 4) {
          door_update = feedback_wire;
          nrf_gpio_pin_set(Lock_Pin);
          nrf_gpio_pin_set(Indicator_Pin);
          nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);

          err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
          APP_ERROR_CHECK(err_code);

        } else if (Door_Status == 3) {
          lock_engine = lock_engine & 0xF0;
          lock_engine = lock_engine | 0x03;
          ble_cus_custom_value_update(p_cus, lock_engine, 4);
        }
      } else if (Lock_Wires == 2) {
        nrf_gpio_pin_set(Lock_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);

        lock_engine = lock_engine & 0xF0;
        lock_engine = lock_engine | 0x03;
        ble_cus_custom_value_update(p_cus, lock_engine, 4);

        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
        APP_ERROR_CHECK(err_code);
      }
    }
    //////////////////     UnLock   ///////////////////////
    else if (lock_engine_test == 2) {
      if (Lock_Wires == 1) {
        if (Door_Status == 3) {
          door_update = feedback_wire;
          indicator_counter_1 = 1;
          nrf_gpio_pin_set(Lock_Pin);
          nrf_gpio_pin_set(Indicator_Pin);
          nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
          err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
        } else if (Door_Status == 4) {
          lock_engine = lock_engine & 0xF0;
          lock_engine = lock_engine | 0x04;
          ble_cus_custom_value_update(p_cus, lock_engine, 4);
        }
      } else if (Lock_Wires == 2) {
        indicator_counter_1 = 1;
        nrf_gpio_pin_set(UnLock_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);

        lock_engine = lock_engine & 0xF0;
        lock_engine = lock_engine | 0x04;
        ble_cus_custom_value_update(p_cus, lock_engine, 4);
        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
        APP_ERROR_CHECK(err_code);

      }
    }
    //////////////////     Trunk   ///////////////////////
    else if (lock_engine_test == 5) {
      nrf_gpio_pin_set(Trunk_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(trunk_delay), NULL);
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    }
    //////////////////     Engine Kill On   ///////////////////////
    else if (lock_engine_test == 10) {

      nrf_gpio_pin_set(Engin_Kill_Pin);
      lock_engine = lock_engine & 0x0F;
      lock_engine = lock_engine | 0x30;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
      retain_test_bit = retain_on & 0x01;
      if (retain_test_bit == 0) {
        retain_on = retain_on + 1;

        write_to_flash = true;
        memory_option = 2;
        device_keys[6] = retain_on;
      }
      if (Car_Type == 1) {
        stop_delay = 1;
        nrf_gpio_pin_clear(Indicator_Pin);
        nrf_gpio_pin_clear(Function_LED);
        nrf_gpio_pin_clear(On_Off_Pin);

        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);

        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);

        start_on_check = 0;
        self_start = self_start & 0xF0;
        self_start = self_start | 0x08;
        ble_cus_custom_value_update(p_cus, lock_engine, 4);
      }
      if (Car_Type == 2) {
        nrf_gpio_pin_clear(ACC_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);

        indicator_counter_1 = 1;

        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
        self_start = self_start & 0xF0;
        self_start = self_start | 0x06;
        ble_cus_custom_value_update(p_cus, self_start, 5);
        if (Car_Type == 2) {
          retain_test_bit = retain_on & 0x02;
          if (retain_test_bit == 2) {
            retain_on = retain_on - 2;

            write_to_flash = true;
            memory_option = 2;
            device_keys[6] = retain_on;
          }
        }
      }
    }
    //////////////////     Engine Kill OFF   ///////////////////////
    else if (lock_engine_test == 20) {
      nrf_gpio_pin_clear(Engin_Kill_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      indicator_counter_1 = 1;
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);

      lock_engine = lock_engine & 0x0F;
      lock_engine = lock_engine | 0x40;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
      retain_test_bit = retain_on & 0x01;
      if (retain_test_bit == 1) {
        retain_on = retain_on - 1;
        write_to_flash = true;
        memory_option = 2;
        device_keys[6] = retain_on;
      }
    }
  }
  ble_cus_custom_value_update(p_cus, lock_engine, 4);
}
void Charcteristics_5(uint8_t test) {
  self_start_test = test;
  ret_code_t err_code;

 // if (regular_chk == 1) 
 {
    //////////////////     ACC ON    ///////////////////////
    if (self_start_test == 10) {
      nrf_gpio_pin_set(ACC_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      self_start = self_start & 0xF0;
      self_start = self_start | 0x05;
      ble_cus_custom_value_update(p_cus, self_start, 5);
      if (Car_Type == 2) {
        nrf_gpio_pin_set(Power_Output);
        retain_test_bit = retain_on & 0x02;
        if (retain_test_bit == 0) {
          retain_on = retain_on + 2;
          write_to_flash = true;
          memory_option = 2;
          device_keys[6] = retain_on;
        }
      }
    }
    //////////////////     ACC OFF   ///////////////////////
    else if (self_start_test == 15) {
      nrf_gpio_pin_clear(ACC_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      indicator_counter_1 = 1;
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      self_start = self_start & 0xF0;
      self_start = self_start | 0x06;
      ble_cus_custom_value_update(p_cus, self_start, 5);
      if (Car_Type == 2) {
        nrf_gpio_pin_clear(Power_Output);
        retain_test_bit = retain_on & 0x02;
        if (retain_test_bit == 2) {
          retain_on = retain_on - 2;
          write_to_flash = true;
          memory_option = 2;
          device_keys[6] = retain_on;
        }
      }
    }
    //////////////////     Power On   ///////////////////////
    else if (self_start_test == 20) {
      nrf_gpio_pin_set(Power_Output);
      nrf_gpio_pin_set(On_Off_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);

      indicator_counter_2 = 1;
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      self_start = self_start & 0xF0;
      self_start = self_start | 0x07;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    }
    //////////////////     Power OFF   ///////////////////////
    else if (self_start_test == 25) {
      nrf_gpio_pin_clear(Power_Output);
      stop_delay = 1;
      prox_stop_value = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);

      nrf_gpio_pin_clear(On_Off_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);

      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      start_on_check = 0;
      self_start = self_start & 0xF0;
      self_start = self_start | 0x08;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    }
    //////////////////     Start     ///////////////////////
    else if (self_start_test == 30) {
      if (start_on_check == 0) {
        nrf_gpio_pin_set(Power_Output);
        stop_delay = 2;
        nrf_gpio_pin_set(ACC_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      }
      self_start = self_start & 0xF0;
      self_start = self_start | 0x09;
      ble_cus_custom_value_update(p_cus, self_start, 5);

    }
    //////////////////     Proximity Stop     ///////////////////////
    else if (self_start_test == 35) {

      prox_stop_value = 5;
      prox_toggle = 0;
      prox_counter = 1;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
      err_code = app_timer_start(Proximity_Stop_Timer, APP_TIMER_TICKS(200), NULL);

    } else if (self_start_test == 36) {
      prox_stop_value = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
    }
    //////////////////     Push Start     ///////////////////////
    else if (self_start_test == 40) {

      if (nrf_gpio_pin_read(Power_Feedback) != 0) {
        nrf_gpio_pin_set(On_Off_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);
        push_power_on = 1;
        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
        self_start = self_start & 0x0F;
        self_start = self_start | 0x00;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      }

      else if (nrf_gpio_pin_read(Power_Feedback) == 0) {
        self_start = self_start & 0x0F;
        self_start = self_start | 0x30;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      }

    } else if (self_start_test == 50) {
      prox_stop_value = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      if (nrf_gpio_pin_read(Power_Feedback) != 0) {
        nrf_gpio_pin_set(Indicator_Pin);
        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
        self_start = self_start & 0x0F;
        self_start = self_start | 0x20;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      } else if (nrf_gpio_pin_read(Power_Feedback) == 0) {
        push_state_chk = 1;
        push_state_counter = 1;
        nrf_gpio_pin_set(Start_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);
        err_code = app_timer_start(Flash, APP_TIMER_TICKS(500), NULL);
      }
    } else if (self_start_test == 51) {
      prox_stop_value = 10;
      prox_toggle = 0;
      prox_counter = 1;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
      err_code = app_timer_start(Proximity_Stop_Timer, APP_TIMER_TICKS(200), NULL);
    } else if (self_start_test == 52) {
      prox_stop_value = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
    }
  }
  ble_cus_custom_value_update(p_cus, self_start, 5);
}
void Charcteristics_6(uint8_t test) {
  timer_test = test;
  ret_code_t err_code;
  //  if(regular_chk==1)
  {
    //////////////////     Self Timer     ///////////////////////

    if (timer_test == 0) {
      start_timer = 250;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x01;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 1) {
      start_timer = 500;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x02;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 2) {
      start_timer = 750;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x03;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 3) {
      start_timer = 1000;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x04;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 4) {
      start_timer = 1250;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x05;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 5) {
      start_timer = 1500;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x06;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 6) {
      start_timer = 1750;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x07;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 7) {
      start_timer = 2000;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x08;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 8) {
      start_timer = 2250;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x09;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 9) {
      start_timer = 2500;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0xF0;
      timer = timer | 0x0A;
      ble_cus_custom_value_update(p_cus, timer, 6);
    }
    //////////////////     Engine Kill Timer     ///////////////////////

    else if (timer_test == 10) {
      Engin_Kill_Time = 1;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x10;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 11) {
      Engin_Kill_Time = 2;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x20;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 12) {
      Engin_Kill_Time = 3;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x30;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 13) {
      Engin_Kill_Time = 4;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x40;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 14) {
      Engin_Kill_Time = 5;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x50;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 15) {
      Engin_Kill_Time = 6;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x60;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 16) {
      Engin_Kill_Time = 7;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x70;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 17) {
      Engin_Kill_Time = 8;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x80;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 18) {
      Engin_Kill_Time = 9;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0x90;
      ble_cus_custom_value_update(p_cus, timer, 6);
    } else if (timer_test == 19) {
      Engin_Kill_Time = 10;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      timer = timer & 0x0F;
      timer = timer | 0xA0;
      ble_cus_custom_value_update(p_cus, timer, 6);
    }

    write_to_flash = true;
    memory_option = 2;
    device_keys[4] = timer;
  }

  ble_cus_custom_value_update(p_cus, timer, 6);
}
void Charcteristics_7(uint8_t test) {
  setting_test = test;
  ret_code_t err_code;
  //  if(regular_chk==1)
  {
    //////////////////     Auto Lock On Disconnect     ///////////////////////

    if (setting_test == 65) {
      Disconnect_Lock = 1;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x01;
      if (test_bit == 0) {
        setting = setting + 1;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 75) {
      Disconnect_Lock = 0;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x01;
      if (test_bit == 1) {
        setting = setting - 1;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    //////////////////     Auto-Engine Kill On Disconnect     ///////////////////////

    else if (setting_test == 66) {
      Engin_Kill_Setting = 1;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x02;
      if (test_bit == 0) {
        setting = setting + 2;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 76) {
      Engin_Kill_Setting = 0;
      //     nrf_gpio_pin_set(Indicator_Pin);
      //     err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x02;
      if (test_bit == 2) {
        setting = setting - 2;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    //////////////////     Retain ACC On Disconnect     ///////////////////////

    else if (setting_test == 67) {
      Smart_key_State = 1;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x04;
      if (test_bit == 0) {
        setting = setting + 4;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 77) {
      Smart_key_State = 0;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x04;
      if (test_bit == 4) {
        setting = setting - 4;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    ///////////////////////////     Car Type     ///////////////////////////////////////

    else if (setting_test == 68) {
      Car_Type = 2;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);

      test_bit = setting & 0x08;
      if (test_bit == 0) {
        setting = setting + 8;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
      nrf_gpio_pin_clear(ACC_Pin);
      nrf_gpio_pin_clear(On_Off_Pin);
      nrf_gpio_pin_clear(State_LED);
      start_on_check = 0;
      self_start = self_start & 0xF0;
      self_start = self_start | 0x06;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    } else if (setting_test == 78) {
      Car_Type = 1;
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x08;
      if (test_bit == 8) {
        setting = setting - 8;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
      nrf_gpio_pin_clear(ACC_Pin);
      nrf_gpio_pin_clear(On_Off_Pin);
      nrf_gpio_pin_clear(State_LED);
      start_on_check = 0;
      self_start = self_start & 0xF0;
      self_start = self_start | 0x06;
      ble_cus_custom_value_update(p_cus, self_start, 5);

      ///// Engine Kill Timer Off
      Engin_Kill_Setting = 0;
      test_bit = setting & 0x02;
      if (test_bit == 2) {
        setting = setting - 2;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);

      ///// Engine Kill Off
      nrf_gpio_pin_clear(Engin_Kill_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      lock_engine = lock_engine & 0x0F;
      lock_engine = lock_engine | 0x40;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
      retain_test_bit = retain_on & 0x01;
      if (retain_test_bit == 1) {
        retain_on = retain_on - 1;

        write_to_flash = true;
        memory_option = 2;
        device_keys[6] = retain_on;
      }
    }

    //////////////////     Proximity Setting(Lock/Unlock)     ///////////////////////

    else if (setting_test == 69) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x10;
      if (test_bit == 0) {
        setting = setting + 16;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 79) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x10;
      if (test_bit == 16) {
        setting = setting - 16;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    //////////////////     Proximity Setting(Start/Stop)     ///////////////////////

    else if (setting_test == 70) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x20;
      if (test_bit == 0) {
        setting = setting + 32;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 80) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      test_bit = setting & 0x20;
      if (test_bit == 32) {
        setting = setting - 32;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    //////////////////     Lock Setting (1 or 2 Wires)     ///////////////////////

    else if (setting_test == 71) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      Lock_Wires = 1;
      test_bit = setting & 0x40;
      if (test_bit == 0) {
        setting = setting + 64;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 81) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      Lock_Wires = 2;
      test_bit = setting & 0x40;
      if (test_bit == 64) {
        setting = setting - 64;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    //////////////////     FeedBack Wire (UnLock/Lock)     ///////////////////////

    else if (setting_test == 72) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      feedback_wire = 1;
      Lock_Wires = 1;
      test_bit = setting & 0x40;
      if (test_bit == 0) {
        setting = setting + 64;
      }
      test_bit = setting & 0x80;
      if (test_bit == 0) {
        setting = setting + 128;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    } else if (setting_test == 82) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      feedback_wire = 2;
      Lock_Wires = 1;
      test_bit = setting & 0x40;
      if (test_bit == 0) {
        setting = setting + 64;
      }
      test_bit = setting & 0x80;
      if (test_bit == 128) {
        setting = setting - 128;
      }
      ble_cus_custom_value_update(p_cus, setting, 7);
    }

    write_to_flash = true;
    memory_option = 2;
    device_keys[5] = setting;
  }
  ble_cus_custom_value_update(p_cus, setting, 7);
}
void Charcteristics_8(uint8_t test) {
}
void Charcteristics_9(uint8_t test) {
  ret_code_t err_code;
  err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  APP_ERROR_CHECK(err_code);
  sd_ble_gap_adv_stop(m_advertising.adv_handle);
}
void Charcteristics_10(uint8_t test) {
  write_to_flash = true;
  memory_option = 3;
}

//UART

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
    ret_code_t ret;

    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:

            if((unsigned char)*(p_evt->data.rxtx.p_data)!=0)
            {
                  received_data[count_data]=(unsigned char)*(p_evt->data.rxtx.p_data);
                  count_data=count_data+1;
                  if((unsigned char)*(p_evt->data.rxtx.p_data)==35)
                      data_completed=true;
            }

            m_loopback_phase = true;
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            if (m_loopback_phase)
            {
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                if (!nrf_queue_is_empty(&m_buf_queue))
                {
                    buffer_t buf;
                    ret = nrf_queue_pop(&m_buf_queue, &buf);
                    APP_ERROR_CHECK(ret);
                    UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
                }
            }

            data_completed=true;
            printf("Tx Called\n");

            break;
        default:
            break;
    }
}


//UART


/////////////////////////////////////////////////////////////////////////////// Charcteristics Functions
static void Blink_LED_handler(void *p_context) {
  ret_code_t err_code;
  if (connection_state == 0) {
    if (toggle == 0) {
      toggle = 1;

      nrf_gpio_pin_set(State_LED);
      err_code = app_timer_start(Blink_LED, APP_TIMER_TICKS(blink_time), NULL);
      APP_ERROR_CHECK(err_code);
    } else {
      toggle = 0;
      nrf_gpio_pin_clear(State_LED);
      err_code = app_timer_start(Blink_LED, APP_TIMER_TICKS(blink_time), NULL);
      APP_ERROR_CHECK(err_code);
    }
  }
}

static void Delay_Event_handler(void *p_context) {
  ret_code_t err_code;
  //   NRF_LOG_INFO("Timer Called");

  if (adv_off == 1) {
    wrong_counter_reg = 0;
    wrong_counter_master = 0;
    adv_off = 0;
    //      uint8 new_adv_enabled_status=TRUE;
    //    GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &new_adv_enabled_status );
    //  return (events ^ Delay_Event);
  }
  if (stop_delay == 1) {
    nrf_gpio_pin_clear(ACC_Pin);
    stop_delay = 0;
  }

  if (stop_delay == 2) {
    nrf_gpio_pin_set(On_Off_Pin);
    nrf_gpio_pin_clear(Indicator_Pin);
    nrf_gpio_pin_clear(Function_LED);
    stop_delay = 3;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
    return;
  }
  if (stop_delay == 3) {
    nrf_gpio_pin_set(Start_Pin);
    start_on_check = 1;
    start_check = 1;
    stop_delay = 0;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(200), NULL);
    return;
  }

  if (start_check == 1) {
    indicator_counter_2 = 0;
    indicator_counter_1 = 0;
    start_check = 2;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(start_timer - 200), NULL);
  } else if (start_check == 2) {
    start_check = 0;
    nrf_gpio_pin_clear(Start_Pin);
  }

  if (Car_Type == 2 && push_state_chk == 1) {
    notify_value = 3;
    ble_cus_custom_value_update(p_cus, notify_value, 8);

    if (nrf_gpio_pin_read(Power_Feedback) == 0) {
      push_state_counter = push_state_counter + 1;
      if (push_state_counter == 2) {
        nrf_gpio_pin_set(Start_Pin);
        err_code = app_timer_start(Flash, APP_TIMER_TICKS(500), NULL);
        self_start = self_start & 0x0F;
        self_start = self_start | 0x40;
        ble_cus_custom_value_update(p_cus, self_start, 5);

      } else if (push_state_counter == 3) {
        nrf_gpio_pin_set(Start_Pin);
        err_code = app_timer_start(Flash, APP_TIMER_TICKS(500), NULL);
        self_start = self_start & 0x0F;
        self_start = self_start | 0x50;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      } else if (push_state_counter == 4) {
        self_start = self_start & 0x0F;
        self_start = self_start | 0x60;
        ble_cus_custom_value_update(p_cus, self_start, 5);
        push_state_counter = 0;
        push_state_chk = 0;
      }
    } else if (nrf_gpio_pin_read(Power_Feedback) != 0) {
      push_state_counter = 0;
      push_state_chk = 0;
      self_start = self_start & 0x0F;
      self_start = self_start | 0x20;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    }
  }
  if (door_update == 2) {
    if (nrf_gpio_pin_read(P_Door_Feedback) == 0 || nrf_gpio_pin_read(N_Door_Feedback) == 0) {
      Door_Status = 3;
      lock_engine = lock_engine & 0xF0;
      lock_engine = lock_engine | 0x03;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    } else {
      Door_Status = 4;
      lock_engine = lock_engine & 0xF0;
      lock_engine = lock_engine | 0x04;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    }
    door_update = 0;
    notify_value = 5;
    ble_cus_custom_value_update(p_cus, notify_value, 8);
  } else if (door_update == 1) {
    if (nrf_gpio_pin_read(P_Door_Feedback) == 0 || nrf_gpio_pin_read(N_Door_Feedback) == 0) {
      Door_Status = 4;
      lock_engine = lock_engine & 0xF0;
      lock_engine = lock_engine | 0x04;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    } else {
      Door_Status = 3;
      lock_engine = lock_engine & 0xF0;
      lock_engine = lock_engine | 0x03;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    }
    door_update = 0;
    notify_value = 5;
    ble_cus_custom_value_update(p_cus, notify_value, 8);
  }
  Reset(); //Reset Pins
  if (Car_Type == 2 && push_power_on == 2) {
    err_code = app_timer_start(Push_Power_Pulse, APP_TIMER_TICKS(2000), NULL);
  }

  else if (Car_Type == 2 && push_power_on == 1) {
    err_code = app_timer_start(Push_Power_Pulse, APP_TIMER_TICKS(1500), NULL);
  }

  if (indicator_counter_1 == 1)
    err_code = app_timer_start(Flash, APP_TIMER_TICKS(300), NULL);

  if (indicator_counter_2 == 1 || indicator_counter_2 == 2)
    err_code = app_timer_start(Flash, APP_TIMER_TICKS(150), NULL);
}

static void Flash_handler(void *p_context) {
  ret_code_t err_code;

  if (Car_Type == 2 && push_state_chk == 1) {
    nrf_gpio_pin_clear(Start_Pin);
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(200), NULL);
    return;
  }

  if (indicator_counter_1 == 1) {
    nrf_gpio_pin_set(Indicator_Pin);
    nrf_gpio_pin_set(Function_LED);
    nrf_gpio_pin_clear(State_LED);
    indicator_counter_1 = 0;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
  }

  if (indicator_counter_2 == 1 || indicator_counter_2 == 2) {
    nrf_gpio_pin_set(Indicator_Pin);
    nrf_gpio_pin_set(Function_LED);
    nrf_gpio_pin_clear(State_LED);
    indicator_counter_2 = indicator_counter_2 + 1;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(150), NULL);
  }

  if (indicator_counter_2 == 3) {
    nrf_gpio_pin_set(Indicator_Pin);
    nrf_gpio_pin_set(Function_LED);
    nrf_gpio_pin_clear(State_LED);
    indicator_counter_2 = 0;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(150), NULL);
  }
}
static void Push_Power_Pulse_handler(void *p_context) {
  ret_code_t err_code;
  if (Car_Type == 2 && push_power_on == 1) {
    push_power_on = 2;
    nrf_gpio_pin_set(Start_Pin);
    nrf_gpio_pin_set(Indicator_Pin);
    nrf_gpio_pin_set(Function_LED);
    nrf_gpio_pin_clear(State_LED);
    start_check = 2;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
  } else if (Car_Type == 2 && push_power_on == 2) {
    push_power_on = 0;
    nrf_gpio_pin_clear(On_Off_Pin);
    notify_value = 3;
    ble_cus_custom_value_update(p_cus, notify_value, 8);
    if (nrf_gpio_pin_read(Power_Feedback) == 0) {
      self_start = self_start & 0x0F;
      self_start = self_start | 0x10;
      ble_cus_custom_value_update(p_cus, self_start, 5);

    } else {
      uint8_t b = 0;
      b = self_start & 0x0F;
      if (b == 0x05) {
        self_start = self_start & 0x0F;
        self_start = self_start | 0x70;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      } else if (b == 0x06) {
        self_start = self_start & 0x0F;
        self_start = self_start | 0x80;
        ble_cus_custom_value_update(p_cus, self_start, 5);
      }
    }
  }
}

static void Disconnect_Commands_handler(void *p_context) {
  ret_code_t err_code;

  if (connection_state == 0) {
    NRF_LOG_INFO("Disconnect Commands Called");

    //State_LED=0;
    notify_check = 1;
    regular_chk = 0;
    master_chk = 0;

    if (Engin_Kill_Setting == 1 && verified_engine_kill == 1) {
      verified_engine_kill = 0;
      if (Engin_Kill_Time == 1)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(10000), NULL);
      if (Engin_Kill_Time == 2)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(20000), NULL);
      if (Engin_Kill_Time == 3)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(30000), NULL);
      if (Engin_Kill_Time == 4)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(40000), NULL);
      if (Engin_Kill_Time == 5)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(50000), NULL);
      if (Engin_Kill_Time == 6)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(60000), NULL);
      if (Engin_Kill_Time == 7)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(70000), NULL);
      if (Engin_Kill_Time == 8)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(80000), NULL);
      if (Engin_Kill_Time == 9)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(90000), NULL);
      if (Engin_Kill_Time == 10)
        err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(100000), NULL);

      toggle_flash = 0;
      i_counter = 0;
      indicator_toggle = 1;
      indicator_speed = Engin_Kill_Time;
      indicator_counter = 10 / indicator_speed;
      err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS(200), NULL);
    }

    err_code = app_timer_start(Blink_LED, APP_TIMER_TICKS(blink_time), NULL);
    APP_ERROR_CHECK(err_code);

    //      osal_start_timerEx( simpleBLEPeripheral_TaskID, Blink_LED, blink_time);

    if (Disconnect_Lock == 1 && verified_lock == 1) {
      verified_lock = 0;
      if (Lock_Wires == 1) {
        if (Door_Status == 4) {
          door_update = feedback_wire;
          nrf_gpio_pin_set(Lock_Pin);
          nrf_gpio_pin_set(Indicator_Pin);
          nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
          err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
        }
      } else if (Lock_Wires == 2) {
        nrf_gpio_pin_set(Lock_Pin);
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
        err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(lock_delay), NULL);
      }
      lock_engine = lock_engine & 0xF0;
      lock_engine = lock_engine | 0x03;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
    }
    if (Car_Type == 2 && Smart_key_State == 0) {
      nrf_gpio_pin_clear(ACC_Pin);
      nrf_gpio_pin_clear(Power_Output);
      self_start = self_start & 0xF0;
      self_start = self_start | 0x06;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    }
  }
}
static void Engin_Kill_Timer_handler(void *p_context) {
  ret_code_t err_code;

  if ((Engin_Kill_Setting == 1 || regular_key_expire == 1) && regular_chk == 0) {
    indicator_toggle = 0;
    if (Car_Type == 1) {
      nrf_gpio_pin_set(Engin_Kill_Pin);
      lock_engine = lock_engine & 0x0F;
      lock_engine = lock_engine | 0x30;
      ble_cus_custom_value_update(p_cus, lock_engine, 4);
      retain_test_bit = retain_on & 0x01;
      if (retain_test_bit == 0) {
        retain_on = retain_on + 1;
        write_to_flash = true;
        memory_option = 2;
        device_keys[6] = retain_on;
      }
    }
    if (Car_Type == 2) {
      nrf_gpio_pin_clear(ACC_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);
      indicator_counter_1 = 1;
      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
      self_start = self_start & 0xF0;
      self_start = self_start | 0x06;
      ble_cus_custom_value_update(p_cus, self_start, 5);
      if (Car_Type == 2) {
        retain_test_bit = retain_on & 0x02;
        if (retain_test_bit == 2) {
          retain_on = retain_on - 2;
          write_to_flash = true;
          memory_option = 2;
          device_keys[6] = retain_on;
        }
      }
    }
  }
}
static void Engin_Kill_Flash_handler(void *p_context) {
  ret_code_t err_code;
  if (indicator_toggle == 1 && (Engin_Kill_Setting == 1 || regular_key_expire == 1) && regular_chk == 0) {

    if (toggle_flash == 0) {
      toggle_flash = 1;
      if (i_counter <= indicator_counter) {
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
        nrf_gpio_pin_clear(State_LED);
        i_counter = i_counter + 1;
        err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS(300), NULL);
        if (i_counter == indicator_counter) {
          indicator_speed = indicator_speed - 1;
          indicator_counter = 10 / indicator_speed;
          i_counter = 0;

        } else if (indicator_speed == 0 && indicator_toggle == 1) {
          nrf_gpio_pin_set(Indicator_Pin);
          nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
          err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS(300), NULL);
        }
      }
    } else {
      toggle_flash = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
      if (indicator_speed >= 1)
        err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS((indicator_speed * 1000) - 300), NULL);
      else
        err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS(700), NULL);
    }
  }
}
static void Regular_Check_Timer_handler(void *p_context) {
  ret_code_t err_code;
  if (connection_state == 1 || share_check == 1) {
    if (master_chk == 1) {
      return;
    } else if (regular_chk == 1) {
      regular_chk = 0;
      notify_value = 2;
      ble_cus_custom_value_update(p_cus, notify_value, 8);
      err_code = app_timer_start(Regular_Check_Timer, APP_TIMER_TICKS(300000), NULL);

    } else {
      share_check = 0;
      regular_chk = 0;
      regular_key_expire = 1;
      err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
      APP_ERROR_CHECK(err_code);
      err_code = app_timer_start(Engin_Kill_Timer, APP_TIMER_TICKS(100000), NULL);

      toggle_flash = 0;
      i_counter = 0;
      indicator_toggle = 1;
      indicator_speed = 10;
      indicator_counter = 10 / indicator_speed;
      err_code = app_timer_start(Engin_Kill_Flash, APP_TIMER_TICKS(200), NULL);
    }

  } else {
    regular_chk = 0;
    err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
  }
}
static void Proximity_Stop_Timer_handler(void *p_context) {
  ret_code_t err_code;

  if ((prox_stop_value == 5 || prox_stop_value == 10) && prox_counter <= 14) {
    prox_counter = prox_counter + 1;
    if (prox_toggle == 0) {
      prox_toggle = 1;
      if (prox_counter > 4) {
        nrf_gpio_pin_set(Indicator_Pin);
        nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);
      }
      err_code = app_timer_start(Proximity_Stop_Timer, APP_TIMER_TICKS(250), NULL);
    } else {
      prox_toggle = 0;
      nrf_gpio_pin_clear(Indicator_Pin);
      nrf_gpio_pin_clear(Function_LED);
      err_code = app_timer_start(Proximity_Stop_Timer, APP_TIMER_TICKS(450), NULL);
    }
  }

  if (prox_stop_value == 5 && prox_counter == 15) {
    notify_value = 4;
    ble_cus_custom_value_update(p_cus, notify_value, 8);
    prox_stop_value = 0;
    stop_delay = 1;
    nrf_gpio_pin_clear(Power_Output);
    nrf_gpio_pin_clear(On_Off_Pin);
    nrf_gpio_pin_set(Indicator_Pin);

    indicator_counter_1 = 1;
    err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(300), NULL);
    start_on_check = 0;
    self_start = self_start & 0xF0;
    self_start = self_start | 0x08;
    ble_cus_custom_value_update(p_cus, self_start, 5);
  }
  if (prox_stop_value == 10 && prox_counter == 15) {
    prox_stop_value = 0;
    if (nrf_gpio_pin_read(Power_Feedback) != 0) {
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
          nrf_gpio_pin_clear(State_LED);

      err_code = app_timer_start(Delay_Event, APP_TIMER_TICKS(500), NULL);
      self_start = self_start & 0x0F;
      self_start = self_start | 0x20;
      ble_cus_custom_value_update(p_cus, self_start, 5);
    } else if (nrf_gpio_pin_read(Power_Feedback) == 0) {
      push_state_chk = 1;
      push_state_counter = 1;
      nrf_gpio_pin_set(Start_Pin);
      nrf_gpio_pin_set(Indicator_Pin);
      nrf_gpio_pin_set(Function_LED);
      nrf_gpio_pin_clear(State_LED);

      err_code = app_timer_start(Flash, APP_TIMER_TICKS(500), NULL);
    }
  }
}

static void advertising_config_get(ble_adv_modes_config_t *p_config) {
  memset(p_config, 0, sizeof(ble_adv_modes_config_t));

  p_config->ble_adv_fast_enabled = true;
  p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
  p_config->ble_adv_fast_timeout = APP_ADV_DURATION;
}

static void disconnect(uint16_t conn_handle, void *p_context) {
  UNUSED_PARAMETER(p_context);

  ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  if (err_code != NRF_SUCCESS) {
    NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
  } else {
    NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
  }
}


// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
 *
 * @param[in]   event   Event from the Buttonless Secure DFU service.
 */

static void ble_dfu_buttonless_evt_handler(ble_dfu_buttonless_evt_type_t event) {
  switch (event) {
  case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE: {
    NRF_LOG_INFO("Device is preparing to enter bootloader mode.");

    // Prevent device from advertising on disconnect.
    ble_adv_modes_config_t config;
    advertising_config_get(&config);
    config.ble_adv_on_disconnect_disabled = true;
    ble_advertising_modes_config_set(&m_advertising, &config);

    // Disconnect all other bonded devices that currently are connected.
    // This is required to receive a service changed indication
    // on bootup after a successful (or aborted) Device Firmware Update.
    uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
    NRF_LOG_INFO("Disconnected %d links.", conn_count);
    break;
  }

  case BLE_DFU_EVT_BOOTLOADER_ENTER:
    // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
    //           by delaying reset by reporting false in app_shutdown_handler
    NRF_LOG_INFO("Device will enter bootloader mode.");
    break;

  case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
    NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
    // YOUR_JOB: Take corrective measures to resolve the issue
    //           like calling APP_ERROR_CHECK to reset the device.
    break;

  case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
    NRF_LOG_ERROR("Request to send a response to client failed.");
    // YOUR_JOB: Take corrective measures to resolve the issue
    //           like calling APP_ERROR_CHECK to reset the device.
    APP_ERROR_CHECK(false);
    break;

  default:
    NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
    break;
  }
}

static void fstorage_evt_handler(nrf_fstorage_evt_t *p_evt) {
  if (p_evt->result != NRF_SUCCESS) {
    NRF_LOG_INFO("Event received: ERROR while executing an fstorage operation.");
    return;
  }

  switch (p_evt->id) {
  case NRF_FSTORAGE_EVT_WRITE_RESULT: {
    NRF_LOG_INFO("Event received: wrote %d bytes at address 0x%x.",
        p_evt->len, p_evt->addr);
  } break;

  case NRF_FSTORAGE_EVT_ERASE_RESULT: {
    NRF_LOG_INFO("Event received: erased %d page from address 0x%x.",
        p_evt->len, p_evt->addr);
  } break;

  default:
    break;
  }
}

static void advertising_start(bool erase_bonds);

/**@brief Callback function for asserts in the SoftDevice.
 *
 * @details This function will be called in case of an assert in the SoftDevice.
 *
 * @warning This handler is an example only and does not fit a final product. You need to analyze
 *          how your product is supposed to react in case of Assert.
 * @warning On assert from the SoftDevice, the system can only recover on reset.
 *
 * @param[in] line_num   Line number of the failing ASSERT call.
 * @param[in] file_name  File name of the failing ASSERT call.
 */
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) {
  app_error_handler(DEAD_BEEF, line_num, p_file_name);
}

/**@brief Function for handling Peer Manager events.
 *
 * @param[in] p_evt  Peer Manager event.
 */
static void pm_evt_handler(pm_evt_t const *p_evt) {
  pm_handler_on_pm_evt(p_evt);
  pm_handler_flash_clean(p_evt);

  switch (p_evt->evt_id) {
  case PM_EVT_PEERS_DELETE_SUCCEEDED:
    advertising_start(false);
    break;

  case PM_EVT_CONN_SEC_CONFIG_REQ: {
    // Allow pairing request from an already bonded peer.
    pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
    pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
  } break;

  default:
    break;
  }
}

/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module. This creates and starts application timers.
 */
static void timers_init(void) {
  // Initialize timer module.
  ret_code_t err_code = app_timer_init();
  APP_ERROR_CHECK(err_code);

  err_code = app_timer_create(&Delay_Event,
      APP_TIMER_MODE_SINGLE_SHOT,
      Delay_Event_handler);
  APP_ERROR_CHECK(err_code);

  err_code = app_timer_create(&Flash,
      APP_TIMER_MODE_SINGLE_SHOT,
      Flash_handler);
  APP_ERROR_CHECK(err_code);

  err_code = app_timer_create(&Push_Power_Pulse,
      APP_TIMER_MODE_SINGLE_SHOT,
      Push_Power_Pulse_handler);
  APP_ERROR_CHECK(err_code);

  err_code = app_timer_create(&Blink_LED,
      APP_TIMER_MODE_SINGLE_SHOT,
      Blink_LED_handler);
  APP_ERROR_CHECK(err_code);

  err_code = app_timer_create(&Disconnect_Commands,
      APP_TIMER_MODE_SINGLE_SHOT,
      Disconnect_Commands_handler);
  APP_ERROR_CHECK(err_code);
  err_code = app_timer_create(&Engin_Kill_Timer,
      APP_TIMER_MODE_SINGLE_SHOT,
      Engin_Kill_Timer_handler);
  APP_ERROR_CHECK(err_code);
  err_code = app_timer_create(&Engin_Kill_Flash,
      APP_TIMER_MODE_SINGLE_SHOT,
      Engin_Kill_Flash_handler);
  APP_ERROR_CHECK(err_code);
  err_code = app_timer_create(&Regular_Check_Timer,
      APP_TIMER_MODE_SINGLE_SHOT,
      Regular_Check_Timer_handler);
  APP_ERROR_CHECK(err_code);
  err_code = app_timer_create(&Proximity_Stop_Timer,
      APP_TIMER_MODE_SINGLE_SHOT,
      Proximity_Stop_Timer_handler);
  APP_ERROR_CHECK(err_code);

  // Create timers.

  /* YOUR_JOB: Create any timers to be used by the application.
                 Below is an example of how to create a timer.
                 For every new timer needed, increase the value of the macro APP_TIMER_MAX_TIMERS by
                 one.
       ret_code_t err_code;
       err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);
       APP_ERROR_CHECK(err_code); */
}

/**@brief Function for the GAP initialization.
 *
 * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
 *          device including the device name, appearance, and the preferred connection parameters.
 */
static void gap_params_init(void) {
  ret_code_t err_code;
  ble_gap_conn_params_t gap_conn_params;
  ble_gap_conn_sec_mode_t sec_mode;
  security_req_t level;

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

  err_code = sd_ble_gap_device_name_set(&sec_mode,
      (const uint8_t *)DEVICE_NAME,
      strlen(DEVICE_NAME));
  APP_ERROR_CHECK(err_code);

  /* YOUR_JOB: Use an appearance value matching the application's use case.
       err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_);
       APP_ERROR_CHECK(err_code); */

  memset(&gap_conn_params, 0, sizeof(gap_conn_params));

  gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
  gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
  gap_conn_params.slave_latency = SLAVE_LATENCY;
  gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;

  err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
  APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the GATT module.
 */
static void gatt_init(void) {
  ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling Queued Write Module errors.
 *
 * @details A pointer to this function will be passed to each service which may need to inform the
 *          application about an error.
 *
 * @param[in]   nrf_error   Error code containing information about what went wrong.
 */
static void nrf_qwr_error_handler(uint32_t nrf_error) {
  APP_ERROR_HANDLER(nrf_error);
}

/**@brief Function for handling the YYY Service events.
 * YOUR_JOB implement a service handler function depending on the event the service you are using can generate
 *
 * @details This function will be called for all YY Service events which are passed to
 *          the application.
 *
 * @param[in]   p_yy_service   YY Service structure.
 * @param[in]   p_evt          Event received from the YY Service.
 *
 *
static void on_yys_evt(ble_yy_service_t     * p_yy_service,
                       ble_yy_service_evt_t * p_evt)
{
    switch (p_evt->evt_type)
    {
        case BLE_YY_NAME_EVT_WRITE:
            APPL_LOG("[APPL]: charact written with value %s. ", p_evt->params.char_xx.value.p_str);
            break;

        default:
            // No implementation needed.
            break;
    }
}
*/

/**@brief Function for initializing services that will be used by the application.
 */
static void services_init(void) {

  /* YOUR_JOB: Add code to initialize the services used by the application.*/
  ret_code_t err_code;
  ble_cus_init_t cus_init;
  ble_dis_init_t dis_init;
  nrf_ble_qwr_init_t qwr_init = {0};
  //   ble_dfu_buttonless_init_t dfus_init = {0};

  // Initialize CUS Service init structure to zero.
  memset(&cus_init, 0, sizeof(cus_init));

  // Initialize Queued Write Module.
  qwr_init.error_handler = nrf_qwr_error_handler;

  err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
  APP_ERROR_CHECK(err_code);

  // Initialize Device Information Service.
  memset(&dis_init, 0, sizeof(dis_init));

  ble_gap_addr_t ble_addr;
  sd_ble_gap_addr_get(&ble_addr);

  uint64_t MANUFACTURER_ID;
  uint32_t ORG_UNIQUE_ID;

  MANUFACTURER_ID = ble_addr.addr[2];
  MANUFACTURER_ID = (MANUFACTURER_ID * 0x100) + ble_addr.addr[1];
  MANUFACTURER_ID = (MANUFACTURER_ID * 0x100) + ble_addr.addr[0];

  ORG_UNIQUE_ID = ble_addr.addr[5];
  ORG_UNIQUE_ID = (ORG_UNIQUE_ID * 0x100) + ble_addr.addr[4];
  ORG_UNIQUE_ID = (ORG_UNIQUE_ID * 0x100) + ble_addr.addr[3];

  ble_dis_sys_id_t system_id;
  system_id.manufacturer_id = MANUFACTURER_ID;
  system_id.organizationally_unique_id = ORG_UNIQUE_ID;
  dis_init.p_sys_id = &system_id;
  dis_init.dis_char_rd_sec = SEC_OPEN;

  ble_srv_ascii_to_utf8(&dis_init.model_num_str, (char *)MODEL_NUMBER);
  ble_srv_ascii_to_utf8(&dis_init.serial_num_str, (char *)SERIAL_NUMBER);
  ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, (char *)FIRMWARE_NUMBER);
  ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, (char *)HARDWARE_NUMBER);
  ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);

  err_code = ble_dis_init(&dis_init);
  APP_ERROR_CHECK(err_code);

  ble_gatts_attr_md_t cccd_md;
  memset(&cccd_md, 0, sizeof(cccd_md));

  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

  BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cus_init.custom_value_char_attr_md.read_perm);
  BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&cus_init.custom_value_char_attr_md.write_perm);

  err_code = ble_cus_init(&m_cus, &cus_init);
  APP_ERROR_CHECK(err_code);

  // BEGIN Block Added for DFU
  // ONLY ADD THIS BLOCK TO THE EXISTING FUNCTION
  // Initialize the DFU service
  ble_dfu_buttonless_init_t dfus_init =
      {
          .evt_handler = ble_dfu_buttonless_evt_handler};
  err_code = ble_dfu_buttonless_init(&dfus_init);
  APP_ERROR_CHECK(err_code);



  /*
    /* YOUR_JOB: Add code to initialize the services used by the application.
       ble_xxs_init_t                     xxs_init;
       ble_yys_init_t                     yys_init;

       // Initialize XXX Service.
       memset(&xxs_init, 0, sizeof(xxs_init));

       xxs_init.evt_handler                = NULL;
       xxs_init.is_xxx_notify_supported    = true;
       xxs_init.ble_xx_initial_value.level = 100;

       err_code = ble_bas_init(&m_xxs, &xxs_init);
       APP_ERROR_CHECK(err_code);

       // Initialize YYY Service.
       memset(&yys_init, 0, sizeof(yys_init));
       yys_init.evt_handler                  = on_yys_evt;
       yys_init.ble_yy_initial_value.counter = 0;

       err_code = ble_yy_service_init(&yys_init, &yy_init);
       APP_ERROR_CHECK(err_code);
     */
}

/**@brief Function for handling the Connection Parameters Module.
 *
 * @details This function will be called for all events in the Connection Parameters Module which
 *          are passed to the application.
 *          @note All this function does is to disconnect. This could have been done by simply
 *                setting the disconnect_on_fail config parameter, but instead we use the event
 *                handler mechanism to demonstrate its use.
 *
 * @param[in] p_evt  Event received from the Connection Parameters Module.
 */
static void on_conn_params_evt(ble_conn_params_evt_t *p_evt) {
  ret_code_t err_code;

  if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
    err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
    APP_ERROR_CHECK(err_code);
  }
}

/**@brief Function for handling a Connection Parameters error.
 *
 * @param[in] nrf_error  Error code containing information about what went wrong.
 */
static void conn_params_error_handler(uint32_t nrf_error) {
  APP_ERROR_HANDLER(nrf_error);
}

/**@brief Function for initializing the Connection Parameters module.
 */
static void conn_params_init(void) {
  ret_code_t err_code;
  ble_conn_params_init_t cp_init;

  memset(&cp_init, 0, sizeof(cp_init));

  cp_init.p_conn_params = NULL;
  cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
  cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
  cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
  cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
  cp_init.disconnect_on_fail = false;
  cp_init.evt_handler = on_conn_params_evt;
  cp_init.error_handler = conn_params_error_handler;

  err_code = ble_conn_params_init(&cp_init);
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for starting timers.
 */
static void application_timers_start(void) {
  /* YOUR_JOB: Start your timers. below is an example of how to start a timer.
       ret_code_t err_code;
       err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL, NULL);
       APP_ERROR_CHECK(err_code); */
}

/**@brief Function for putting the chip into sleep mode.
 *
 * @note This function will not return.
 */
static void sleep_mode_enter(void) {
  ret_code_t err_code;

  err_code = bsp_indication_set(BSP_INDICATE_IDLE);
  APP_ERROR_CHECK(err_code);

  // Prepare wakeup buttons.
  err_code = bsp_btn_ble_sleep_mode_prepare();
  APP_ERROR_CHECK(err_code);

  // Go to system-off mode (this function will not return; wakeup will cause a reset).
  err_code = sd_power_system_off();
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling advertising events.
 *
 * @details This function will be called for advertising events which are passed to the application.
 *
 * @param[in] ble_adv_evt  Advertising event.
 */
static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
  ret_code_t err_code;

  switch (ble_adv_evt) {
  case BLE_ADV_EVT_FAST:
    NRF_LOG_INFO("Fast advertising.");
    err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
    APP_ERROR_CHECK(err_code);
    break;

  case BLE_ADV_EVT_IDLE:
    sleep_mode_enter();
    break;

  default:
    break;
  }
}

/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) {
  ret_code_t err_code = NRF_SUCCESS;

  switch (p_ble_evt->header.evt_id) {
  case BLE_GAP_EVT_DISCONNECTED:
    NRF_LOG_INFO("Disconnected.");
    // LED indication will be changed when advertising starts.
    regular_chk = 0;
    masterokforeg = 0;
    connection_state = 0;
    err_code = app_timer_start(Disconnect_Commands, APP_TIMER_TICKS(3000), NULL);
    APP_ERROR_CHECK(err_code);
    break;

  case BLE_GAP_EVT_CONNECTED:
    NRF_LOG_INFO("Connected.");
    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);
    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
    APP_ERROR_CHECK(err_code);
    //      pins_chk=1;
    connection_state = 1;
    NRF_LOG_INFO("Connected LED Set");

    nrf_gpio_pin_set(State_LED);
    //      osal_start_timerEx( simpleBLEPeripheral_TaskID, Regular_Check_Timer ,300000);

    //   Charcteristics_10(5);

    break;

  case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
    NRF_LOG_DEBUG("PHY update request.");
    ble_gap_phys_t const phys =
        {
            .rx_phys = BLE_GAP_PHY_AUTO,
            .tx_phys = BLE_GAP_PHY_AUTO,
        };
    err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
    APP_ERROR_CHECK(err_code);
  } break;

  case BLE_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    NRF_LOG_DEBUG("GATT Client Timeout.");
    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
        BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
    break;

  case BLE_GATTS_EVT_TIMEOUT:
    // Disconnect on GATT Server timeout event.
    NRF_LOG_DEBUG("GATT Server Timeout.");
    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
        BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
    break;

  default:
    // No implementation needed.
    break;
  }
}

/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(void) {
  ret_code_t err_code;

  err_code = nrf_sdh_enable_request();
  APP_ERROR_CHECK(err_code);

  // Configure the BLE stack using the default settings.
  // Fetch the start address of the application RAM.
  uint32_t ram_start = 0;
  err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
  APP_ERROR_CHECK(err_code);

  // Enable BLE stack.
  err_code = nrf_sdh_ble_enable(&ram_start);
  APP_ERROR_CHECK(err_code);

  // Register a handler for BLE events.
  NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}

/**@brief Function for the Peer Manager initialization.
 */
static void peer_manager_init(void) {
  ble_gap_sec_params_t sec_param;
  ret_code_t err_code;

  err_code = pm_init();
  APP_ERROR_CHECK(err_code);

  memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

  // Security parameters to be used for all security procedures.
  sec_param.bond = SEC_PARAM_BOND;
  sec_param.mitm = SEC_PARAM_MITM;
  sec_param.lesc = SEC_PARAM_LESC;
  sec_param.keypress = SEC_PARAM_KEYPRESS;
  sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
  sec_param.oob = SEC_PARAM_OOB;
  sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
  sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
  sec_param.kdist_own.enc = 1;
  sec_param.kdist_own.id = 1;
  sec_param.kdist_peer.enc = 1;
  sec_param.kdist_peer.id = 1;

  err_code = pm_sec_params_set(&sec_param);
  APP_ERROR_CHECK(err_code);

  err_code = pm_register(pm_evt_handler);
  APP_ERROR_CHECK(err_code);
}

/**@brief Clear bond information from persistent storage.
 */
static void delete_bonds(void) {
  ret_code_t err_code;

  NRF_LOG_INFO("Erase bonds!");

  err_code = pm_peers_delete();
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling events from the BSP module.
 *
 * @param[in]   event   Event generated when button is pressed.
 */
static void bsp_event_handler(bsp_event_t event) {
  ret_code_t err_code;

  switch (event) {
  case BSP_EVENT_SLEEP:
    sleep_mode_enter();
    break; // BSP_EVENT_SLEEP

  case BSP_EVENT_DISCONNECT:
    err_code = sd_ble_gap_disconnect(m_conn_handle,
        BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_ERROR_INVALID_STATE) {
      APP_ERROR_CHECK(err_code);
    }
    break; // BSP_EVENT_DISCONNECT

  case BSP_EVENT_WHITELIST_OFF:
    if (m_conn_handle == BLE_CONN_HANDLE_INVALID) {
      err_code = ble_advertising_restart_without_whitelist(&m_advertising);
      if (err_code != NRF_ERROR_INVALID_STATE) {
        APP_ERROR_CHECK(err_code);
      }
    }
    break; // BSP_EVENT_KEY_0

  default:
    break;
  }
}

/**@brief Function for initializing the Advertising functionality.
 */
static void advertising_init(void) {
  ret_code_t err_code;
  ble_advertising_init_t init;

  memset(&init, 0, sizeof(init));

  init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
  init.advdata.include_appearance = true;
  init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
  init.srdata.uuids_complete.p_uuids = m_adv_uuids;

  init.config.ble_adv_fast_enabled = true;
  init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
  init.config.ble_adv_fast_timeout = APP_ADV_DURATION; //

  init.evt_handler = on_adv_evt;

  err_code = ble_advertising_init(&m_advertising, &init);
  APP_ERROR_CHECK(err_code);

  ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

/**@brief Function for initializing buttons and leds.
 *
 * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
 */
static void buttons_leds_init(bool *p_erase_bonds) {
  ret_code_t err_code;
  bsp_event_t startup_event;

  err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
  APP_ERROR_CHECK(err_code);

  err_code = bsp_btn_ble_init(NULL, &startup_event);
  APP_ERROR_CHECK(err_code);

  *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}

/**@brief Function for initializing the nrf log module.
 */
static void log_init(void) {
  ret_code_t err_code = NRF_LOG_INIT(NULL);
  APP_ERROR_CHECK(err_code);

  NRF_LOG_DEFAULT_BACKENDS_INIT();
}

/**@brief Function for initializing power management.
 */
static void power_management_init(void) {
  ret_code_t err_code;
  err_code = nrf_pwr_mgmt_init();
  APP_ERROR_CHECK(err_code);
}
/**@brief Handler for shutdown preparation.
 *
 * @details During shutdown procedures, this function will be called at a 1 second interval
 *          untill the function returns true. When the function returns true, it means that the
 *          app is ready to reset to DFU mode.
 *
 * @param[in]   event   Power manager event.
 *
 * @retval  True if shutdown is allowed by this power manager handler, otherwise false.
 */
static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event) {
  switch (event) {
  case NRF_PWR_MGMT_EVT_PREPARE_DFU:
    NRF_LOG_INFO("Power management wants to reset to DFU mode.");
    // YOUR_JOB: Get ready to reset into DFU mode
    //
    // If you aren't finished with any ongoing tasks, return "false" to
    // signal to the system that reset is impossible at this stage.
    //
    // Here is an example using a variable to delay resetting the device.
    //
    // if (!m_ready_for_reset)
    // {
    //      return false;
    // }
    // else
    //{
    //
    //    // Device ready to enter
    //    uint32_t err_code;
    //    err_code = sd_softdevice_disable();
    //    APP_ERROR_CHECK(err_code);
    //    err_code = app_timer_stop_all();
    //    APP_ERROR_CHECK(err_code);
    //}
    break;

  default:
    // YOUR_JOB: Implement any of the other events available from the power management module:
    //      -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
    //      -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
    //      -NRF_PWR_MGMT_EVT_PREPARE_RESET
    return true;
  }

  NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
  return true;
}

/**@brief Function for handling the idle state (main loop).
 *
 * @details If there is no pending log operation, then sleep until next the next event occurs.
 */
static void idle_state_handle(void) {
  if (NRF_LOG_PROCESS() == false) {
    nrf_pwr_mgmt_run();
  }
}

/**@brief Function for starting advertising.
 */
static void advertising_start(bool erase_bonds) {
  if (erase_bonds == true) {
    delete_bonds();
    // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
  } else {
    ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);

    APP_ERROR_CHECK(err_code);
  }
}

static void gpio_output_voltage_setup(void) {
  // Configure UICR_REGOUT0 register only if it is set to default value.
  if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) ==
      (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos)) {
    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
    }

    NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                        (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);

    NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
    }

    // System reset is needed to update UICR registers.
    NVIC_SystemReset();
  }
}

/**
 * @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output,
 * and configures GPIOTE to give an interrupt on pin change.
 */
static void gpio_init(void) {
  ret_code_t err_code;

  nrf_gpio_cfg_output(Lock_Pin);
  nrf_gpio_cfg_output(UnLock_Pin);
  nrf_gpio_cfg_output(Trunk_Pin);

  nrf_gpio_cfg_output(ACC_Pin);
  nrf_gpio_cfg_output(On_Off_Pin);
  nrf_gpio_cfg_output(Start_Pin);

  nrf_gpio_cfg_output(Indicator_Pin);
  nrf_gpio_cfg_output(Function_LED);

  nrf_gpio_cfg_output(Power_Output);

  nrf_gpio_cfg_output(Engin_Kill_Pin);
  nrf_gpio_cfg_output(State_LED);

  nrf_gpio_cfg_input(N_Door_Feedback, NRF_GPIO_PIN_PULLUP);
  nrf_gpio_cfg_input(P_Door_Feedback, NRF_GPIO_PIN_PULLUP);
  nrf_gpio_cfg_input(Power_Feedback, NRF_GPIO_PIN_PULLUP);

  err_code = nrf_drv_gpiote_init();
  APP_ERROR_CHECK(err_code);

  nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);

  nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
  in_config.pull = NRF_GPIO_PIN_PULLUP;
}

/**@brief Function starting the internal LFCLK oscillator.
 *
 * @details This is needed by RTC1 which is used by the Application Timer
 *          (When SoftDevice is enabled the LFCLK is always running and this is not needed).
 */
static void lfclk_request(void) {
  ret_code_t err_code = nrf_drv_clock_init();
  APP_ERROR_CHECK(err_code);
  nrf_drv_clock_lfclk_request(NULL);
}

/**@brief Function for application main entry.
 */
int main(void) {
  bool erase_bonds;
  // Initialize.
  log_init();

  lfclk_request();
  gpio_init();
  timers_init();
  buttons_leds_init(&erase_bonds);
  power_management_init();

  gpio_output_voltage_setup();
  ble_stack_init();
  gap_params_init();
  gatt_init();
  services_init();
  advertising_init();
  conn_params_init();
  peer_manager_init();

  // Start execution.
  NRF_LOG_INFO("MoboKey Device Started");
  application_timers_start();

  advertising_start(erase_bonds);

  uint32_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, 8);
  APP_ERROR_CHECK(err_code);

  regular_chk = 0;
  masterokforeg = 0;
  connection_state = 0;
  err_code = app_timer_start(Blink_LED, APP_TIMER_TICKS(blink_time), NULL);
  APP_ERROR_CHECK(err_code);

  ret_code_t rc;

  nrf_fstorage_api_t *p_fs_api;
  p_fs_api = &nrf_fstorage_sd;

  rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
  APP_ERROR_CHECK(rc);


 /* 

    err_code = NRF_LOG_INIT(app_timer_cnt_get);
    APP_ERROR_CHECK(err_code);


    NRF_LOG_DEFAULT_BACKENDS_INIT();


    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = TX_PIN_NUMBER,
            .rx_pin     = RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_9600,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 100,
            .int_prio   = APP_IRQ_PRIORITY_LOW
    };

    err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte);

*/


  read_in_flash(1);

  // Enter main loop.
  for (;;) {
    if (write_to_flash == true) {
      write_to_flash = false;
      if (memory_option == 2) {
        write_in_flash(memory_option);
      } 
    }
    idle_state_handle();

        NRF_LOG_FLUSH();

        if(data_completed==true)
        {
          printf("\n");
          printf("Received Msg : %s\n",received_data);
          data_completed=false;
          count_data=0;

          for (int i=0;i<200;i++)
          {
            received_data[i]=0;
          }
        }

  }
}
/**
 * @}
 */