static void intervals_calculate(void)
{

    bool etlm_required = false;
    uint8_t no_of_eid_slots = eddystone_adv_slot_num_of_current_eids(NULL, &etlm_required);

    /*Buffers to hardcode a small shortening of the intervals just in case of any delays
    between all the running timer interrupts (scheduled to main context) + variance in encyrption time
    of eTLMs so that all slots have enough time to advertise before the next advertising interval comes around*/

    const uint8_t etlm_dist_buffer_ms = 25;
    const uint8_t slot_dist_buffer_ms = 25;

    /**@note From internal testing we can see that eTLM encryption takes about ~170 ms on the NRF52.
    Which means that the delay after the timer interrupt fires to advertise and the actual eTLM advertisement is ~170 ms,
    this is a significant limiting factor for the minimum advertising interval.

    Please read the comments above @ref timers_init to see what is the current scheme of
    advertising timing before continuing.

    Thus if there N EIDs configured (N > 0) in the beacon and at least 1 TLM configured, then the TLM frame auto switches
    to eTLM and cycles through the set of EIKs of the EIDs frames and advertises N eTLM frames, all within one slot interval,
    each encrypted with the EIK of one of the EID slots. Hence there must be enough time alotted in 1 slot interval for N*(~170 ms + buffer).
     */

     /*Minimum interval between two eTLM advertisements (2+ EIDs) in one eTLM slot in ms*/
     const uint16_t ETLM_INTERVAL_LIMIT = 225;  /*MUST be > ~170 ms + etlm_dist_buffer_ms */

    /*Minimum interval between two slots in ms.
     If eTLM is required then SLOT_INTERVAL_LIMIT becomes just the first half of the sum,
     else the second half (MIN_NON_CONN_ADV_INTERVAL) since there is no significant real-time encrytion delays*/
    const uint16_t SLOT_INTERVAL_LIMIT = (no_of_eid_slots*ETLM_INTERVAL_LIMIT)*(uint8_t)(etlm_required)
                                          + MIN_NON_CONN_ADV_INTERVAL*((uint8_t)(!etlm_required));

    DEBUG_PRINTF(0,"SLOT_INTERVAL_LIMIT: %d \r\n", SLOT_INTERVAL_LIMIT);
    //See if any slot is configured at all
    uint8_t no_of_currently_configed_slots = eddystone_adv_slot_num_of_configured_slots(m_currently_configured_slots);
    DEBUG_PRINTF(0,"Number of Configured Slots: %d \r\n", no_of_currently_configed_slots);

    //Gets slot 0's advertising interval since only global advertising interval is supported currently
    eddystone_adv_slot_params_t adv_slot_0_params;
    eddystone_adv_slot_params_get(0, &adv_slot_0_params);
    m_intervals.adv_intrvl = adv_slot_0_params.adv_intrvl;

    //Can happen when flash R/W for storing/loading slot configs did not behave as expected
    //which can crash the app_timer_start
    //TODO: might need a better error handling strategy for this...
    if (m_intervals.adv_intrvl == 0)
    {
        m_intervals.adv_intrvl = 1000;
    }

    if (no_of_currently_configed_slots == 0)
    {
        m_intervals.slot_slot_interval = 0;
        m_intervals.etlm_etlm_interval = 0;
    }
    else
    {
        //Slot-Slot Interval
        m_intervals.slot_slot_interval = (m_intervals.adv_intrvl/(no_of_currently_configed_slots)) - slot_dist_buffer_ms;
        if (m_intervals.slot_slot_interval < SLOT_INTERVAL_LIMIT)
        {
            ble_ecs_adv_intrvl_t adjusted_interval = (SLOT_INTERVAL_LIMIT + slot_dist_buffer_ms)*no_of_currently_configed_slots;
            m_intervals.adv_intrvl = adjusted_interval;

            DEBUG_PRINTF(0,"1 - ADV INTERVAL ADJUSTED BY ADV MGR: %d \r\n", adjusted_interval);
            adjusted_interval = BYTES_SWAP_16BIT(adjusted_interval);
            eddystone_adv_slot_adv_intrvl_set(0, &adjusted_interval, true);
            m_intervals.slot_slot_interval = m_intervals.adv_intrvl/no_of_currently_configed_slots - slot_dist_buffer_ms;
            DEBUG_PRINTF(0,"Slot-Slot Interval: %d \r\n", m_intervals.slot_slot_interval );
        }

        //eTLM-eTLM interval
        if (no_of_eid_slots != 0 && etlm_required == true)
        {
            m_intervals.etlm_etlm_interval = (m_intervals.slot_slot_interval/no_of_eid_slots) - etlm_dist_buffer_ms;

            if (m_intervals.etlm_etlm_interval < ETLM_INTERVAL_LIMIT)
            {
                m_intervals.etlm_etlm_interval = ETLM_INTERVAL_LIMIT;
                m_intervals.slot_slot_interval = (m_intervals.etlm_etlm_interval + etlm_dist_buffer_ms)*no_of_eid_slots - slot_dist_buffer_ms;

                ble_ecs_adv_intrvl_t adjusted_interval = (m_intervals.slot_slot_interval + slot_dist_buffer_ms)*no_of_currently_configed_slots;
                m_intervals.adv_intrvl = adjusted_interval;

                DEBUG_PRINTF(0,"2 - ADV INTERVAL ADJUSTED BY ADV MGR: %d \r\n", adjusted_interval);
                adjusted_interval = BYTES_SWAP_16BIT(adjusted_interval);
                eddystone_adv_slot_adv_intrvl_set(0, &adjusted_interval, true);

                DEBUG_PRINTF(0,"eTLM-eTLM Interval: %d \r\n", m_intervals.etlm_etlm_interval );
                DEBUG_PRINTF(0,"Slot-Slot Interval: %d \r\n", m_intervals.slot_slot_interval );
            }
        }
        else
        {
            m_intervals.etlm_etlm_interval = 0;
        }
    }
}
Exemplo n.º 2
0
ret_code_t nrf_ble_escs_init(nrf_ble_escs_t * p_escs, const nrf_ble_escs_init_t * p_escs_init)
{
    uint32_t      err_code;
    ble_uuid_t    ble_uuid;
    ble_uuid128_t ecs_base_uuid = ESCS_BASE_UUID;
    uint8_t       zero_val = 0;

    VERIFY_PARAM_NOT_NULL(p_escs);
    VERIFY_PARAM_NOT_NULL(p_escs_init);

    // Initialize the service structure.
    p_escs->conn_handle       = BLE_CONN_HANDLE_INVALID;
    p_escs->write_evt_handler = p_escs_init->write_evt_handler;
    p_escs->read_evt_handler  = p_escs_init->read_evt_handler;

    // Add a custom base UUID.
    err_code = sd_ble_uuid_vs_add(&ecs_base_uuid, &p_escs->uuid_type);
    VERIFY_SUCCESS(err_code);

    ble_uuid.type = p_escs->uuid_type;
    ble_uuid.uuid = BLE_UUID_ESCS_SERVICE;

    // Add the service.
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &ble_uuid,
                                        &p_escs->service_handle);
    VERIFY_SUCCESS(err_code);

    m_handle_to_uuid_map_idx = 0;

    // Set up initial values for characteristics

    // Eddystone spec requires big endian
    nrf_ble_escs_broadcast_cap_t temp = p_escs_init->p_init_vals->broadcast_cap;
    temp.supp_frame_types = BYTES_SWAP_16BIT(temp.supp_frame_types);

    nrf_ble_escs_adv_interval_t temp_interval = p_escs_init->p_init_vals->adv_interval;
    temp_interval = BYTES_SWAP_16BIT(temp_interval);

    // Adding chracteristics

    err_code = char_add(&BROADCAST_CAP_CHAR_INIT, p_escs,
                        &temp, &p_escs->broadcast_cap_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&ACTIVE_SLOT_CHAR_INIT, p_escs,
                        p_escs->p_active_slot, &p_escs->active_slot_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&ADV_INTERVAL_CHAR_INIT, p_escs,
                        &temp_interval, &p_escs->adv_interval_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&RADIO_TX_PWR_CHAR_INIT, p_escs,
                        &(p_escs_init->p_init_vals->radio_tx_pwr), &p_escs->radio_tx_pwr_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&ADV_TX_PWR_CHAR_INIT, p_escs,
                        &(p_escs_init->p_init_vals->adv_tx_pwr), &p_escs->adv_tx_pwr_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&LOCK_STATE_CHAR_INIT, p_escs,
                        p_escs->p_lock_state, &p_escs->lock_state_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&UNLOCK_CHAR_INIT, p_escs,
                        &zero_val, &p_escs->unlock_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&PUBLIC_ECDH_KEY_CHAR_INIT,  p_escs,
                        &zero_val, &p_escs->pub_ecdh_key_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&EID_ID_KEY_CHAR_INIT, p_escs,
                        &zero_val, &p_escs->eid_id_key_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&RW_ADV_SLOT_CHAR_INIT, p_escs,
                        &zero_val, &p_escs->rw_adv_slot_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&FACTORY_RESET_CHAR_INIT, p_escs,
                        &(p_escs_init->p_init_vals->factory_reset), &p_escs->factory_reset_handles);
    VERIFY_SUCCESS(err_code);

    err_code = char_add(&REMAIN_CONNECTABLE_CHAR_INIT, p_escs,
                        &(p_escs_init->p_init_vals->remain_connectable.r_is_non_connectable_supported),
                        &p_escs->remain_connectable_handles);
    VERIFY_SUCCESS(err_code);

    return NRF_SUCCESS;
}