#include #include #include "app_timer.h" #include "ble_advdata.h" #include "bsp.h" #include "nordic_common.h" #include "nrf_delay.h" #include "nrf_drv_rtc.h" #include "nrf_gpio.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_soc.h" #include "rtc.h" // P0.03 // #define LED_PIN 3 #define LED_PIN NRF_GPIO_PIN_MAP(1, 11) // Environmental sensing. #define SERVICE_UUID 0x181a #define DEAD_BEEF 0xDEADBEEF #define NAME "Parasite" #define NAME_LEN 8 #define SERVICE_DATA_LEN 8 static uint8_t service_data[SERVICE_DATA_LEN]; #define APP_BLE_CONN_CFG_TAG 1 // Seconds between RTC 2 events. #define COMPARE_COUNTERTIME (1UL) // RTC0 is used by softdevice, so we need to pick another instance. const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2); static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */ static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */ #define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; static ble_gap_adv_data_t m_adv_data = { .adv_data = {.p_data = m_enc_advdata, .len = BLE_GAP_ADV_SET_DATA_SIZE_MAX}, .scan_rsp_data = {.p_data = NULL, .len = 0 }}; void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) { app_error_handler(DEAD_BEEF, line_num, p_file_name); } static void advertising_init(void) { uint32_t err_code; ble_advdata_t advdata; // Build and set advertising data. memset(&advdata, 0, sizeof(advdata)); uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; ble_advdata_service_data_t advdata_service_data; advdata_service_data.service_uuid = SERVICE_UUID; advdata_service_data.data.p_data = service_data; advdata_service_data.data.size = SERVICE_DATA_LEN; advdata.name_type = BLE_ADVDATA_FULL_NAME; advdata.flags = flags; advdata.p_service_data_array = &advdata_service_data; advdata.service_data_count = 1; // Initialize advertising parameters (used when starting advertising). memset(&m_adv_params, 0, sizeof(m_adv_params)); m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; m_adv_params.p_peer_addr = NULL; // Undirected advertisement. m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; m_adv_params.interval = NON_CONNECTABLE_ADV_INTERVAL; m_adv_params.duration = 0; // Never time out. ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)NAME, NAME_LEN); err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len); APP_ERROR_CHECK(err_code); err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params); APP_ERROR_CHECK(err_code); } static void advertising_start(void) { ret_code_t err_code; err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG); APP_ERROR_CHECK(err_code); NRF_LOG_INFO("Advertising started\n.") } static void advertising_stop(void) { ret_code_t err_code; err_code = sd_ble_gap_adv_stop(m_adv_handle); APP_ERROR_CHECK(err_code); } 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); } static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("Log inited"); } static void leds_init(void) { nrf_gpio_cfg_output(LED_PIN); nrf_gpio_pin_toggle(LED_PIN); nrf_delay_ms(500); nrf_gpio_pin_toggle(LED_PIN); nrf_delay_ms(500); NRF_LOG_INFO("Leds inited"); } static void timers_init(void) { ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(err_code); } static void power_management_init(void) { ret_code_t err_code; err_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(err_code); } static void idle_state_handle(void) { if (NRF_LOG_PROCESS() == false) { nrf_pwr_mgmt_run(); } } #define FPU_EXCEPTION_MASK 0x0000009F static void power_manage(void) { __set_FPSCR(__get_FPSCR() & ~(FPU_EXCEPTION_MASK)); (void)__get_FPSCR(); NVIC_ClearPendingIRQ(FPU_IRQn); nrf_pwr_mgmt_run(); } static void rtc_callback() { NRF_LOG_INFO("rtc callback running...\n"); NRF_LOG_FLUSH(); nrf_gpio_pin_set(LED_PIN); advertising_start(); nrf_delay_ms(500); advertising_stop(); nrf_gpio_pin_clear(LED_PIN); } int main(void) { // Initialize. log_init(); leds_init(); power_management_init(); ble_stack_init(); advertising_init(); prst_rtc_set_callback(rtc_callback); prst_rtc_init(); // Enter main loop. for (;;) { power_manage(); } }