Example #1
0
/**
 * @brief Function for turning on RX carrier.
*/
void radio_rx_carrier(uint8_t mode, uint8_t channel)
{
    radio_disable();
    NRF_RADIO->SHORTS     = RADIO_SHORTS_READY_START_Msk;
    NRF_RADIO->FREQUENCY  = channel;
    NRF_RADIO->TASKS_RXEN = 1;
}
Example #2
0
/*
 * Start modulated TX carrier. This is done by repeatedly sending a packet with random address and
 * random payload.
 */
static void radio_modulated_tx_carrier(uint8_t txpower, uint8_t mode, uint8_t channel)
{
  radio_disable();
  generate_modulated_rf_packet();
  NRF_RADIO->SHORTS     = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk;;
  NRF_RADIO->TXPOWER    = (txpower << RADIO_TXPOWER_TXPOWER_Pos);
  NRF_RADIO->MODE       = (mode << RADIO_MODE_MODE_Pos);
  NRF_RADIO->FREQUENCY  = channel;
  NRF_RADIO->TASKS_TXEN = 1;
}
Example #3
0
/**
 * @brief Function for turning on the TX carrier test mode.
*/
void radio_tx_carrier(uint8_t txpower, uint8_t mode, uint8_t channel)
{
    radio_disable();
    NRF_RADIO->SHORTS     = RADIO_SHORTS_READY_START_Msk;
    NRF_RADIO->TXPOWER    = (txpower << RADIO_TXPOWER_TXPOWER_Pos);    
    NRF_RADIO->MODE       = (mode << RADIO_MODE_MODE_Pos);
    NRF_RADIO->FREQUENCY  = channel;
    NRF_RADIO->TEST       = (RADIO_TEST_CONST_CARRIER_Enabled << RADIO_TEST_CONST_CARRIER_Pos) \
                            | (RADIO_TEST_PLL_LOCK_Enabled << RADIO_TEST_PLL_LOCK_Pos);
    NRF_RADIO->TASKS_TXEN = 1;
}
void ll_scan_timeout_cb (void)
{
  switch (m_scanner.state)
  {
    case SCANNER_STATE_RECEIVE_SCAN_RSP:
      m_state_receive_scan_rsp_exit ();
      radio_disable ();
      m_state_receive_adv_entry ();
      break;

    default:
      break;
  }
}
Example #5
0
u8 mode_select_display_func(ui_mode_t mode, ui_display_event_t event)
{
    if (event == CONFIG_SHORT_PRESS)
    {
        u16 m = 1;
        u8 i;
        for(i=0; i<3-mode_select_digit; i++)
        {
            m *= 10;
        }
        u8 p = (mode_select_current/m)%10;
        mode_select_current -= p*m;
        p = (p+1)%10;
        mode_select_current += p*m;
    }
    else if (event == CONFIG_LONG_PRESS)
    {
        ++mode_select_digit;
        if (mode_select_digit >= 4)
        {
            /* Save the new config word */
            save_persist_data_16(PDATA_CONFIG_WORD_1L + mode_select_word*2, ~mode_select_current);
            
            ++mode_select_word;
            do_config_word(mode_select_word);
        }        
        if (mode_select_word >= NUM_CONFIG_WORDS)
        {
            /* wait for button release */
            while (!(LED_PIN & (1<<LED_BIT)));
            
            radio_disable();
            
            /* reset */
            void (*rstvec)() = (void (*)())0;
            (*rstvec)();
        }
    }
    output_number(MODE_MODE_SELECT + mode_select_word + 1, 
            mode_select_current, CENTER_NONE, DFLAGS_FLASH_PLACE_0<<mode_select_digit);
    return 1;
}
void ll_scan_rx_cb (bool crc_valid)
{
  /* Received invalid packet */
  if (!crc_valid)
  {
    switch(m_scanner.state)
    {
      case SCANNER_STATE_RECEIVE_ADV:
        m_packets_invalid++;
      
        m_state_receive_adv_exit ();
        radio_disable ();
        m_state_receive_adv_entry ();
        break;

      case SCANNER_STATE_RECEIVE_SCAN_RSP:
        m_packets_invalid++;
      
        m_state_receive_scan_rsp_exit ();
        radio_disable ();
        m_state_receive_adv_entry ();
        break;

      default:
        break;
    }
  }
  
  switch (m_scanner.state)
  {  
    /* Packet received */
    case SCANNER_STATE_RECEIVE_ADV:
      m_packets_valid++;
    
      switch (m_rx_buf[0] & 0x0F)
      {
        /* If active scanning is enabled, these packets should be reponded to with
         * a SCAN_REQ, and we should wait for a SCAN_RSP.
         */
        case PACKET_TYPE_ADV_IND:
          m_state_receive_adv_exit ();

          m_adv_report_generate (m_rx_buf);

          /* If we're doing active scanning, prepare to send SCAN REQ, otherwise
           * loop back around to receive a new advertisement.
           */
          if (m_scanner.params.scan_type == BTLE_SCAN_TYPE_ACTIVE)
          {
            m_state_send_scan_req_entry ();
          }
          else
          {
            m_state_receive_adv_entry ();
          }
          break;
        case PACKET_TYPE_ADV_SCAN_IND:
          m_state_receive_adv_exit ();
          m_adv_report_generate (m_rx_buf);

          /* If we're doing active scanning, prepare to send SCAN REQ, otherwise
           * loop back around to receive a new advertisement.
           */
          if (m_scanner.params.scan_type == BTLE_SCAN_TYPE_ACTIVE)
          {
            m_state_send_scan_req_entry ();
          }
          else
          {
            m_state_receive_adv_entry ();
          }
          break;

        /* These packets do not require response.
         */
        case PACKET_TYPE_ADV_DIRECT_IND:
          m_state_receive_adv_exit ();
          radio_disable();
          m_adv_report_generate (m_rx_buf);
          m_state_receive_adv_entry ();
          break;
        
        case PACKET_TYPE_ADV_NONCONN_IND:
          m_state_receive_adv_exit ();
          radio_disable();
          m_adv_report_generate (m_rx_buf);
          m_state_receive_adv_entry ();
          break;

        /* This should not have happened */
        default:
          m_state_receive_adv_exit ();
          radio_disable();
          m_state_receive_adv_entry();
      }
      break;

    case SCANNER_STATE_RECEIVE_SCAN_RSP:
      m_packets_valid++;

      m_state_receive_scan_rsp_exit ();
      m_adv_report_generate (m_rx_buf);

      m_state_receive_adv_entry ();
      break;

    default:
      break;
  }
}
/**
* @brief Handle trickle timing events
*/
static void trickle_step_callback(void)
{
    TICK_PIN(6);
    /* check if timeslot is about to end */
    if (timeslot_get_remaining_time() < RADIO_SAFETY_TIMING_US)
        return;

    uint64_t time_now = global_time + timer_get_timestamp();
    trickle_time_update(time_now);

    packet_t packet;
    bool has_anything_to_send = false;

    mesh_srv_packet_assemble(&packet, PACKET_DATA_MAX_LEN * PACKET_MAX_CHAIN_LEN,
        &has_anything_to_send);

    if (has_anything_to_send)
    {
        TICK_PIN(PIN_MESH_TX);
        radio_disable();

        uint8_t packet_and_addr_type = PACKET_TYPE_ADV_NONCONN |
            ((packet.sender.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC)?
            0 :
            PACKET_ADDR_TYPE_MASK);

        uint8_t* temp_data_ptr = &packet.data[0];
        uint8_t* tx_data_ptr = &tx_data[0];
        tx_data_ptr[PACKET_TYPE_POS] = packet_and_addr_type;

        /* Code structured for packet chaining, although this is yet
         to be implemented. */
        do
        {
            uint8_t min_len = ((packet.length > PACKET_DATA_MAX_LEN)?
                PACKET_DATA_MAX_LEN :
                packet.length);

            tx_data_ptr[PACKET_PADDING_POS] = 0;
            tx_data_ptr[PACKET_LENGTH_POS] = (min_len + PACKET_ADDR_LEN);
            tx_data_ptr[PACKET_TYPE_POS] = packet_and_addr_type;

            memcpy(&tx_data_ptr[PACKET_ADDR_POS], packet.sender.addr, PACKET_ADDR_LEN);
            memcpy(&tx_data_ptr[PACKET_DATA_POS], &temp_data_ptr[0], min_len);

            radio_event_t tx_event;
            tx_event.access_address = 0;
            rbc_mesh_channel_get(&tx_event.channel);
            tx_event.event_type = RADIO_EVENT_TYPE_TX;
            tx_event.packet_ptr = &tx_data_ptr[0];
            tx_event.start_time = 0;
            tx_event.callback.tx = NULL;

            radio_order(&tx_event);
            TICK_PIN(0);
        } while (0);

        order_search(); /* search for the rest of the timeslot */
    }

    /* order next processing */
    uint64_t next_time;
    uint64_t end_time = timeslot_get_end_time();
    uint32_t error_code = mesh_srv_get_next_processing_time(&next_time);

    if (error_code == NRF_SUCCESS && next_time < global_time + end_time)
    {
        timer_abort(step_timer_index);
        step_timer_index = timer_order_cb(next_time - global_time, trickle_step_callback);
    }
}
Example #8
0
/**
 * @brief Function for stopping Timer 0.
*/
void radio_sweep_end(void)
{
    NRF_TIMER0->TASKS_STOP = 1;
    radio_disable();
}
/**
* @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;
}