/* * led_func() - Set LED states * * INPUT * - act: led action * OUTPUT * none */ void led_func(LedAction act) { #ifndef EMULATOR switch(act) { case CLR_GREEN_LED: SET_PIN(GREEN_LED); break; case SET_GREEN_LED: CLEAR_PIN(GREEN_LED); break; case TGL_GREEN_LED: TOGGLE_PIN(GREEN_LED); break; case CLR_RED_LED: SET_PIN(RED_LED); break; case SET_RED_LED: CLEAR_PIN(RED_LED); break; case TGL_RED_LED: TOGGLE_PIN(RED_LED); break; default: /* No action */ break; } #endif }
static bool event_fifo_pop(fifo_t* evt_fifo) { SET_PIN(PIN_SWI0); async_event_t evt; uint32_t error_code = fifo_pop(evt_fifo, &evt); if (error_code == NRF_SUCCESS) { async_event_execute(&evt); CLEAR_PIN(PIN_SWI0); return true; } CLEAR_PIN(PIN_SWI0); return false; }
/** * @brief Handle incoming packets */ static void search_callback(uint8_t* data) { SET_PIN(PIN_RX); uint32_t checksum = (NRF_RADIO->RXCRC & 0x00FFFFFF); /* check if timeslot is about to end */ uint64_t radio_time_left = timeslot_get_remaining_time(); if (radio_time_left > RADIO_SAFETY_TIMING_US) { /* setup next RX */ order_search(); } CLEAR_PIN(PIN_RX); if (data == NULL || !packet_is_data_packet(data)) { return; } async_event_t async_evt; async_evt.type = EVENT_TYPE_PACKET; packet_create_from_data(data, &async_evt.callback.packet); async_evt.callback.packet.rx_crc = checksum; event_handler_push(&async_evt); /** @TODO: add packet chain handling */ }
/* packet processing, executed in APP_LOW */ void tc_packet_handler(uint8_t* data, uint32_t crc, uint64_t timestamp) { // LOGi("_6"); SET_PIN(PIN_RX); mesh_packet_t* p_packet = (mesh_packet_t*) data; // printArray(p_packet, sizeof(mesh_packet_t)); if (p_packet->header.length > MESH_PACKET_OVERHEAD + RBC_MESH_VALUE_MAX_LEN) { // LOGi("_2"); /* invalid packet, ignore */ CLEAR_PIN(PIN_RX); mesh_packet_ref_count_dec(p_packet); /* from rx_cb */ return; } ble_gap_addr_t addr; memcpy(addr.addr, p_packet->addr, BLE_GAP_ADDR_LEN); addr.addr_type = p_packet->header.addr_type; mesh_adv_data_t* p_mesh_adv_data = mesh_packet_adv_data_get(p_packet); if (p_mesh_adv_data != NULL) { // LOGi("_3"); /* filter mesh packets on handle range */ if (p_mesh_adv_data->handle <= RBC_MESH_APP_MAX_HANDLE) { // LOGi("_4"); mesh_app_packet_handle(p_mesh_adv_data, timestamp); } } /* this packet is no longer needed in this context */ mesh_packet_ref_count_dec(p_packet); /* from rx_cb */ if (g_state.queue_saturation) { // LOGi("_5"); order_search(); g_state.queue_saturation = false; } CLEAR_PIN(PIN_RX); }
/** Initialize the pins needed for the communication with D12. **/ void d12_pins_init(void) { INIT_PIN_OUTPUT(A0_PORT, A0_PIN); INIT_PIN_OUTPUT(RD_PORT, RD_PIN); INIT_PIN_OUTPUT(WR_PORT, WR_PIN); INIT_PIN_OUTPUT(SUSPEND_PORT, SUSPEND_PIN); INIT_PIN_INPUT(IRQ_PORT, IRQ_PIN); CLEAR_PIN(IRQ_PORT, IRQ_PIN); }
/** * @brief Timeslot related events callback * Called whenever the softdevice tries to change the original course of actions * related to the timeslots */ void ts_sd_event_handler(void) { uint32_t evt; SET_PIN(6); while (sd_evt_get(&evt) == NRF_SUCCESS) { PIN_OUT(evt, 32); switch (evt) { case NRF_EVT_RADIO_SESSION_IDLE: timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); break; case NRF_EVT_RADIO_SESSION_CLOSED: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); break; case NRF_EVT_RADIO_BLOCKED: /* something in the softdevice is blocking our requests, go into emergency mode, where slots are short, in order to avoid complete lockout */ timeslot_order_earliest(TIMESLOT_SLOT_EMERGENCY_LENGTH, true); break; case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); break; case NRF_EVT_RADIO_CANCELED: timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_STATE); } } CLEAR_PIN(6); }
/** * @brief Timeslot related events callback * Called whenever the softdevice tries to change the original course of actions * related to the timeslots */ void ts_sd_event_handler(uint32_t evt) { SET_PIN(PIN_SD_EVT_HANDLER); switch (evt) { case NRF_EVT_RADIO_SESSION_IDLE: /* the idle event is usually triggered when rbc_mesh_stop is called, but if this isn't the case, we have to restart the TS */ if (g_timeslot_forced_command != TS_FORCED_COMMAND_STOP) { timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); } break; case NRF_EVT_RADIO_SESSION_CLOSED: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); break; case NRF_EVT_RADIO_BLOCKED: /* something in the softdevice is blocking our requests, go into emergency mode, where slots are short, in order to avoid complete lockout */ timeslot_order_earliest(TIMESLOT_SLOT_EMERGENCY_LENGTH, true); break; case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); break; case NRF_EVT_RADIO_CANCELED: timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); break; default: break; } CLEAR_PIN(PIN_SD_EVT_HANDLER); }
/** * @brief Radio signal callback handler taking care of all signals in searching * mode */ static nrf_radio_signal_callback_return_param_t* radio_signal_callback(uint8_t sig) { g_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; g_is_in_callback = true; static uint32_t requested_extend_time = 0; static uint32_t successful_extensions = 0; static uint64_t last_rtc_value = 0; //static uint8_t noise_val = 0x5F; SET_PIN(PIN_SYNC_TIME); static uint64_t time_now = 0; switch (sig) { case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: { NVIC_ClearPendingIRQ(SWI0_IRQn); g_is_in_timeslot = true; event_fifo_flush(); timer_init(); SET_PIN(2); successful_extensions = 0; g_negotiate_timeslot_length = g_timeslot_length; g_timeslot_length = g_next_timeslot_length; g_timeslot_end_timer = timer_order_cb_sync_exec(g_timeslot_length - TIMESLOT_END_SAFETY_MARGIN_US, end_timer_handler); /* attempt to extend our time right away */ timeslot_extend(g_negotiate_timeslot_length); #if USE_SWI_FOR_PROCESSING NVIC_EnableIRQ(SWI0_IRQn); NVIC_SetPriority(SWI0_IRQn, 3); #endif /* sample RTC timer for trickle timing */ uint32_t rtc_time = NRF_RTC0->COUNTER; /*First time the offset should be added*/ if(last_rtc_value == 0) { last_rtc_value = g_start_time_ref; } /* Calculate delta rtc time */ uint64_t delta_rtc_time; if(last_rtc_value > rtc_time) { delta_rtc_time = 0xFFFFFF - last_rtc_value + rtc_time; } else { delta_rtc_time = rtc_time - last_rtc_value; } /* Store last rtc time */ last_rtc_value = rtc_time; /* scale to become us */ time_now += ((delta_rtc_time << 15) / 1000); transport_control_timeslot_begin(time_now); break; } case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /* send to radio control module */ TICK_PIN(PIN_RADIO_SIGNAL); radio_event_handler(); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /* send to timer control module */ TICK_PIN(PIN_TIMER_SIGNAL); timer_event_handler(); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: g_timeslot_length += requested_extend_time; requested_extend_time = 0; ++successful_extensions; g_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; timer_abort(g_timeslot_end_timer); g_timeslot_end_timer = timer_order_cb_sync_exec(g_timeslot_length - TIMESLOT_END_SAFETY_MARGIN_US, end_timer_handler); TICK_PIN(1); if (g_timeslot_length + g_negotiate_timeslot_length < TIMESLOT_MAX_LENGTH) { timeslot_extend(g_negotiate_timeslot_length); } else { /* done extending, check for new trickle event */ transport_control_step(); } break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: g_negotiate_timeslot_length >>= 2; TICK_PIN(1); if (g_negotiate_timeslot_length > 1000) { timeslot_extend(g_negotiate_timeslot_length); } else { /* done extending, check for new trickle event */ transport_control_step(); } break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_STATE); } g_is_in_callback = false; if (g_ret_param.callback_action == NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND) { requested_extend_time = g_ret_param.params.extend.length_us; } else if (g_ret_param.callback_action == NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END) { CLEAR_PIN(2); g_is_in_timeslot = false; event_fifo_flush(); } else { requested_extend_time = 0; } CLEAR_PIN(PIN_SYNC_TIME); return &g_ret_param; }
void LED_INIT() { vAHI_DioSetDirection(0, 1 << 2); vAHI_DioSetDirection(0, 1 << 3); vAHI_DioSetDirection(0, 1 << 16); vAHI_DioSetDirection(0, 1 << 17); CLEAR_PIN(16); CLEAR_PIN(17); }
void LEDS_OFF() { CLEAR_PIN(2); CLEAR_PIN(3); CLEAR_PIN(17); }
/** * @brief Radio signal callback handler taking care of all signals in searching * mode */ static nrf_radio_signal_callback_return_param_t* radio_signal_callback(uint8_t sig) { static uint32_t requested_extend_time = 0; static uint32_t successful_extensions = 0; static uint32_t timeslot_count = 0; if (sig == NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) { g_timeslot_forced_command = TS_FORCED_COMMAND_NONE; } else /* on forced command */ { switch (g_timeslot_forced_command) { case TS_FORCED_COMMAND_STOP: g_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_END; g_is_in_timeslot = false; g_end_timer_triggered = false; CLEAR_PIN(PIN_IN_TS); event_handler_on_ts_end(); timeslot_count = 0; return &g_ret_param; case TS_FORCED_COMMAND_RESTART: timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); g_is_in_timeslot = false; g_end_timer_triggered = false; CLEAR_PIN(PIN_IN_TS); event_handler_on_ts_end(); radio_disable(); return &g_ret_param; default: break; } } g_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; g_is_in_callback = true; SET_PIN(PIN_IN_CB); switch (sig) { case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: { SET_PIN(PIN_IN_TS); g_is_in_timeslot = true; g_end_timer_triggered = false; successful_extensions = 0; if (timeslot_count > 0) { global_time_update(); } mesh_packet_on_ts_begin(); event_handler_on_ts_begin(); timer_on_ts_begin(); tc_on_ts_begin(); g_negotiate_timeslot_length = TIMESLOT_SLOT_EXTEND_LENGTH; g_timeslot_length = g_next_timeslot_length; timer_order_cb_sync_exec(TIMER_INDEX_TS_END, g_timeslot_length - end_timer_margin(), end_timer_handler); /* attempt to extend our time right away */ timeslot_extend(g_negotiate_timeslot_length); /* increase timeslot-count, but skip =0 on rollover */ if (!++timeslot_count) { timeslot_count++; } break; } case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /* send to radio control module */ SET_PIN(PIN_RADIO_SIGNAL); radio_event_handler(); CLEAR_PIN(PIN_RADIO_SIGNAL); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /* send to timer control module */ SET_PIN(PIN_TIMER_SIGNAL); timer_event_handler(); CLEAR_PIN(PIN_TIMER_SIGNAL); break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: g_timeslot_length += requested_extend_time; requested_extend_time = 0; ++successful_extensions; timer_abort(TIMER_INDEX_TS_END); timer_order_cb_sync_exec(TIMER_INDEX_TS_END, g_timeslot_length - end_timer_margin(), end_timer_handler); g_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; TICK_PIN(PIN_EXTENSION_OK); if (g_timeslot_length + g_negotiate_timeslot_length < TIMESLOT_MAX_LENGTH) { timeslot_extend(g_negotiate_timeslot_length); } else { /* done extending, check for new trickle event */ vh_on_timeslot_begin(); } break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: g_negotiate_timeslot_length >>= 1; TICK_PIN(PIN_EXTENSION_FAIL); if (g_negotiate_timeslot_length > 1000) { timeslot_extend(g_negotiate_timeslot_length); } else { /* done extending, check for new trickle event */ vh_on_timeslot_begin(); } break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_STATE); } if (g_end_timer_triggered) { timeslot_order_earliest(TIMESLOT_SLOT_LENGTH, true); g_is_in_timeslot = false; g_end_timer_triggered = false; CLEAR_PIN(PIN_IN_TS); event_handler_on_ts_end(); radio_disable(); timer_on_ts_end(); } else if (g_ret_param.callback_action == NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND) { requested_extend_time = g_ret_param.params.extend.length_us; } else { requested_extend_time = 0; } g_is_in_callback = false; CLEAR_PIN(PIN_IN_CB); return &g_ret_param; }