/** @addtogroup radio_file RADIO peripheral API * * @brief Access functions for the 2.4 GHz Radio * * @ingroup peripheral_apis * LGPL License Terms @ref lgpl_license * @author @htmlonly © @endhtmlonly 2016 * Maxim Sloyko * */ /* * This file is part of the libopencm3 project. * * Copyright (C) 2017-2018 Unicore MX project * Copyright (C) 2021 Eduard Drusa * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ #include #include /**@{*/ /** @brief Set radio transmission power. * * @details Note, not all supported power levels are BLE compliant. * * @param[in] txpower enum radio_txpower * */ void radio_set_txpower(enum radio_txpower txpower) { RADIO_TXPOWER = txpower; } /** @brief Set bit transmission order to LSB first. */ void radio_set_lsbfirst(void) { RADIO_PCNF1 &= ~RADIO_PCNF1_ENDIAN_BIG; } /** @brief Set bit transmission order to MSB first. */ void radio_set_msbfirst(void) { RADIO_PCNF1 |= RADIO_PCNF1_ENDIAN_BIG; } /** @brief Enable on the air data whitening * * @details the in-memory data will remain unwhitened. * */ void radio_enable_whitening(void) { RADIO_PCNF1 |= RADIO_PCNF1_WHITEEN; } /** @brief Disable on the air data whitening. */ void radio_disable_whitening(void) { RADIO_PCNF1 &= ~RADIO_PCNF1_WHITEEN; } /** @brief Set CRC length in number of bytes. * * @param[in] crc_len uint8_t CRC length in number of bytes (1-3), 0 = CRC disabled. */ void radio_set_crclen(uint8_t crc_len) { uint32_t reg_crc = RADIO_CRCCNF; reg_crc &= ~RADIO_CRCCNF_LEN_MASK; RADIO_CRCCNF = reg_crc | RADIO_CRCCNF_LEN_MASKED(crc_len); } /** @brief Disable CRC calculation. */ void radio_disable_crc(void) { RADIO_CRCCNF &= ~RADIO_CRCCNF_LEN_MASK; } /** @brief Enable the peripheral. */ void radio_enable(void) { RADIO_POWER = RADIO_POWER_ENABLED; } /** @brief Disable the peripheral. */ void radio_disable(void) { RADIO_POWER = RADIO_POWER_DISABLED; } /** @brief Set Base Address length. * * @param[in] ba_len uint8_t Base Address length in number of bytes (2-4). */ void radio_set_balen(uint8_t ba_len) { uint32_t reg_pcnf1 = RADIO_PCNF1; reg_pcnf1 &= ~RADIO_PCNF1_BALEN_MASK; RADIO_PCNF1 = reg_pcnf1 | RADIO_PCNF1_BALEN_MASKED(ba_len); } /** @brief Set maximum transmission length in number of bytes. * * @param[in] maxlen uint8_t maximum transmission length. */ void radio_set_maxlen(uint8_t maxlen) { uint32_t reg_pcnf1 = RADIO_PCNF1; reg_pcnf1 &= ~RADIO_PCNF1_MAXLEN_MASK; RADIO_PCNF1 = reg_pcnf1 | RADIO_PCNF1_MAXLEN_MASKED(maxlen); } /** @brief Exclude access address from CRC calculation. * * @param[in] is_skip_addr bool If true, CRC will be calculated over PDU only, * if false, it will also include the Access Address. */ void radio_set_crc_skipaddr(bool is_skip_addr) { if (is_skip_addr) { RADIO_CRCCNF |= RADIO_CRCCNF_SKIPADDR; } else { RADIO_CRCCNF &= ~RADIO_CRCCNF_SKIPADDR; } } /** @brief Configure the radio to be used in BLE mode. * * @details This needs to be called before the radio can be used in BLE mode. * It will set som BLE standard parameters, like Inter-Frame Spacing time, * LSB first, enable whitening, properly configure CRC (for advertising) and address length. */ void radio_configure_ble(void) { #ifdef NRF51 radio_set_mode(RADIO_MODE_BLE_1MBIT); #endif RADIO_TIFS = RADIO_BLE_TIFS; radio_set_lsbfirst(); radio_enable_whitening(); radio_set_crclen(RADIO_BLE_CRCLEN); RADIO_CRCPOLY = RADIO_BLE_CRCPOLY; RADIO_CRCINIT = RADIO_BLE_CRCINIT; radio_set_crc_skipaddr(true); radio_set_balen(3); } /** @brief Configure the packet. * * @details See the data sheet for details. */ void radio_configure_packet(uint8_t lf_len_bits, uint8_t s0_len_bytes, uint8_t s1_len_bits) { RADIO_PCNF0 = RADIO_PCNF0_LFLEN_MASKED(lf_len_bits) | RADIO_PCNF0_S0LEN_MASKED(s0_len_bytes) | RADIO_PCNF0_S1LEN_MASKED(s1_len_bits); } /** @brief Set radio frequency. * * @param[in] freq uint8_t Frequency offset from 2.4GHz in MHz, for example "29" will * tune the radio to 2429MHz */ void radio_set_frequency(uint8_t freq) { RADIO_FREQUENCY = freq; } /** @brief Set Data Whitening Initialization Vector. * * @param[in] iv uint8_t Initialization Vector. For BLE, this is channel index. */ void radio_set_datawhiteiv(uint8_t iv) { RADIO_DATAWHITEIV = iv; } /* @brief Set Address (base and prefix) * * @details Note that bases are shared between addresses 1-7, * so changing one of them will change others too. * * @param[in] addr_index uint8_t address index (0-7) * @param[in] base uint32_t base part of the address. If balen < 4, appropriate number * of LSBs will be thrown away. * @param[in] prefix uint8_t Address prefix. */ void radio_set_addr(uint8_t addr_index, uint32_t base, uint8_t prefix) { if (addr_index == 0) { RADIO_BASE0 = base; } else { RADIO_BASE1 = base; } uint32_t reg_prefix = RADIO_PREFIX_AP(addr_index); reg_prefix &= ~RADIO_PREFIX_AP_MASK(addr_index); RADIO_PREFIX_AP_SET(addr_index, reg_prefix | RADIO_PREFIX_AP_MASKED(addr_index, prefix)); } /* @brief Set TX address index * * @details The address needs to be previously configured with radio_set_addr() * * @param[in] address_index uint8_t address index (0-7) */ void radio_set_tx_address(uint8_t addr_index) { RADIO_TXADDRESS = addr_index; } /* @brief Set pointer for RX/TX data * * @param[in] packet_ptr uint8_t* packet buffer address. */ void radio_set_packet_ptr(uint8_t *packet_ptr) { RADIO_PACKETPTR = (uint32_t)packet_ptr; } /* @brief Enable radio Transmitter */ void radio_enable_tx(void) { PERIPH_TRIGGER_TASK(RADIO_TASK_TXEN); } /* @brief Enable radio Receiver */ void radio_enable_rx(void) { PERIPH_TRIGGER_TASK(RADIO_TASK_RXEN); } /**@}*/