Пример #1
0
/**@brief Set scan parameters and start scanning
 *
 * @note The HCI spec specifies interval in units of 0.625 ms.
 * 	Here we use us directly.
 *
 * @param [in] scan_type: should be LL_SCAN_ACTIVE or LL_SCAN_PASSIVE
 * 		(only the latter implemented at this time)
 * @param [in] interval: the scan Interval in us
 * @param [in] window: the scan Window in us
 * @param [in] adv_report_cb: the function to call for advertising report events
 *
 * @return -EINVAL if window > interval or interval > 10.24 s
 * @return -EINVAL if scan_type != LL_SCAN_PASSIVE
 */
int16_t ll_scan_start(uint8_t scan_type, uint32_t interval, uint32_t window,
						adv_report_cb_t adv_report_cb)
{
	int16_t err_code;

	if(window > interval || interval > LL_SCAN_INTERVAL_MAX)
		return -EINVAL;

	switch(scan_type) {
		case LL_SCAN_PASSIVE:
			/* Setup callback function */
			ll_adv_report_cb = adv_report_cb;
			break;

		case LL_SCAN_ACTIVE:
		/* Not implemented */
		default:
			return -EINVAL;
	}

	radio_set_callbacks(ll_on_radio_rx, NULL);

	/* Setup timer and save window length */
	t_scan_window = window;
	err_code = timer_start(t_ll_interval, interval);
	if (err_code < 0)
		return err_code;

	current_state = LL_STATE_SCANNING;
	t_ll_interval_cb();

	DBG("interval %uus, window %uus", interval, window);

	return 0;
}
Пример #2
0
int16_t ll_advertise_start(ll_pdu_t type, uint32_t interval, uint8_t chmap)
{
	int16_t err_code;

	if (current_state != LL_STATE_STANDBY)
		return -ENOREADY;

	if (!chmap || (chmap & !LL_ADV_CH_ALL))
		return -EINVAL;

	if (interval % LL_ADV_INTERVAL_QUANTUM)
		return -EINVAL;

	if (interval < LL_ADV_INTERVAL_MIN_NONCONN
					|| interval > LL_ADV_INTERVAL_MAX)
			return -EINVAL;

	adv_ch_map = chmap;

	switch (type) {
	case LL_PDU_ADV_IND:
	case LL_PDU_ADV_SCAN_IND:
		rx = true;
		break;

	case LL_PDU_ADV_NONCONN_IND:
		rx = false;
		break;

	case LL_PDU_ADV_DIRECT_IND:
		/* TODO: Not implemented */
	default:
		/* Invalid PDU */
		return -EINVAL;
	}

	pdu_adv.type = type;
	t_adv_pdu_interval = TIMER_MILLIS(10); /* <= 10ms Sec 4.4.2.6 */

	radio_set_callbacks(rx ? ll_on_radio_rx : NULL,
						rx ? ll_on_radio_tx : NULL);

	DBG("PDU interval %u ms, event interval %u ms",
				t_adv_pdu_interval / 1000, interval / 1000);

	err_code = timer_start(t_ll_interval, interval);
	if (err_code < 0)
		return err_code;

	current_state = LL_STATE_ADVERTISING;

	t_ll_interval_cb();

	return 0;
}
Пример #3
0
int16_t radio_init(void)
{
    if (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0UL) {
        NRF_CLOCK->TASKS_HFCLKSTART = 1UL;
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0UL);
    }

    /* nRF51 Series Reference Manual v2.1, section 6.1.1, page 18
     * PCN-083 rev.1.1
     *
     * Fine tune BLE deviation parameters.
     */
    if ((NRF_FICR->OVERRIDEEN & FICR_OVERRIDEEN_BLE_1MBIT_Msk)
            == (FICR_OVERRIDEEN_BLE_1MBIT_Override
                << FICR_OVERRIDEEN_BLE_1MBIT_Pos)) {
        NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0];
        NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1];
        NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2];
        NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3];
        NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4] | 0x80000000;
    }

    /* nRF51 Series Reference Manual v2.1, section 16.2.7, page 86 */
    NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos;

    /* Link Layer specification section 4.1, Core 4.1, page 2524
     * nRF51 Series Reference Manual v2.1, section 16.2.7, page 92
     *
     * Set the inter frame space (T_IFS) to 150 us.
     */
    NRF_RADIO->TIFS = 150;

    /* nRF51 Series Reference Manual v2.1, section 16.2.9, page 88
     *
     * Enable data whitening, set the maximum payload length and set the
     * access address size (3 + 1 octets).
     */
    NRF_RADIO->PCNF1 =
        (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
        (MAX_PAYLOAD_LEN << RADIO_PCNF1_MAXLEN_Pos) |
        (3UL << RADIO_PCNF1_BALEN_Pos);

    /* nRF51 Series Reference Manual v2.1, section 16.1.4, page 74
     * nRF51 Series Reference Manual v2.1, section 16.2.14-15, pages 89-90
     *
     * Preset the address to use when receive and transmit packets (logical
     * address 0, which is assembled by base address BASE0 and prefix byte
     * PREFIX0.AP0.
     */
    NRF_RADIO->RXADDRESSES = 1UL;
    NRF_RADIO->TXADDRESS = 0UL;

    /* nRF51 Series Reference Manual v2.1, section 16.1.7, page 76
     * nRF51 Series Reference Manual v2.1, sections 16.1.16-17, page 90
     *
     * Configure the CRC length (3 octets), polynominal and set it to
     * ignore the access address when calculate the CRC.
     */
    NRF_RADIO->CRCCNF =
        (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
        (RADIO_CRCCNF_SKIP_ADDR_Skip << RADIO_CRCCNF_SKIP_ADDR_Pos);
    NRF_RADIO->CRCPOLY = 0x100065B;

    /* nRF51 Series Reference Manual v2.1, section 16.1.2, page 74
     * nRF51 Series Reference Manual v2.1, sections 16.1.8, page 87
     * Link Layer specification section 2.3, Core 4.1, page 2504
     * Link Layer specification section 2.4, Core 4.1, page 2511
     *
     * Configure the header size. The nRF51822 has 3 fields before the
     * payload field: S0, LENGTH and S1. These fields can be used to store
     * the PDU header.
     */
    NRF_RADIO->PCNF0 = (1UL << RADIO_PCNF0_S0LEN_Pos)
                       | (8UL << RADIO_PCNF0_LFLEN_Pos)
                       | (0UL << RADIO_PCNF0_S1LEN_Pos);

    /* nRF51 Series Reference Manual v2.1, section 16.1.8, page 76
     * nRF51 Series Reference Manual v2.1, section 16.1.10-11, pages 78-80
     * nRF51 Series Reference Manual v2.1, section 16.2.1, page 85
     *
     * Enable READY_START short: when the READY event happens, initialize
     * the START task.
     *
     * Enable END_DISABLE short: when the END event happens, initialize the
     * DISABLE task.
     */
    NRF_RADIO->SHORTS = BASE_SHORTS;

    /* Trigger RADIO interruption when an END event happens */
    NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;

    NVIC_SetPriority(RADIO_IRQn, IRQ_PRIORITY_HIGH);
    NVIC_ClearPendingIRQ(RADIO_IRQn);
    NVIC_EnableIRQ(RADIO_IRQn);

    radio_set_callbacks(NULL, NULL);
    radio_set_tx_power(RADIO_POWER_0_DBM);
    radio_set_out_buffer(NULL);

    NRF_RADIO->PACKETPTR = (uint32_t) inbuf;
    memset(inbuf, 0, sizeof(inbuf));

    status = STATUS_INITIALIZED;

    return 0;
}