nRFBareRadio is a library to use the Radio peripheral in a nRF51 or nRF52 Nordic microcontroller in "bare" mode transmitting raw packets, instead of the usual BLE protocols.

Committer:
fbcosentino
Date:
Fri May 17 13:36:56 2019 +0000
Revision:
0:123cac2364c4
nRFBareRadio is a library to use the Radio peripheral in a ; nRF51 or nRF52 Nordic microcontroller in "bare" mode transmitting; raw packets, instead of the usual BLE protocols.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fbcosentino 0:123cac2364c4 1 #include "nRFBareRadio.h"
fbcosentino 0:123cac2364c4 2
fbcosentino 0:123cac2364c4 3 /*
fbcosentino 0:123cac2364c4 4 #ifdef TARGET_NRF52
fbcosentino 0:123cac2364c4 5 #define RADIO_RECEIVE_EVENT EVENTS_CRCOK
fbcosentino 0:123cac2364c4 6 #else
fbcosentino 0:123cac2364c4 7 #define RADIO_RECEIVE_EVENT EVENTS_END
fbcosentino 0:123cac2364c4 8 #endif*/
fbcosentino 0:123cac2364c4 9
fbcosentino 0:123cac2364c4 10 RadioConfig::RadioConfig() {
fbcosentino 0:123cac2364c4 11 frequency = 2;
fbcosentino 0:123cac2364c4 12 rate = RADIO_RATE_2M;
fbcosentino 0:123cac2364c4 13 tx_power = RADIO_TX_0dBm;
fbcosentino 0:123cac2364c4 14 data_length = 32; // compatible to nRF24 (range 1-32)
fbcosentino 0:123cac2364c4 15 address_length = 5; // compatible to nRF24 (range 3-5)
fbcosentino 0:123cac2364c4 16 use_whitening = RADIO_NO_WHITENING; // compatible to nRF24 (no change)
fbcosentino 0:123cac2364c4 17 endianness = RADIO_BIGENDIAN; // compatible to nRF24 (no change)
fbcosentino 0:123cac2364c4 18 crc_poly = 0x1021; // compatible to nRF24 (no change)
fbcosentino 0:123cac2364c4 19 crc_init = 0xFFFF; // compatible to nRF24 (no change)
fbcosentino 0:123cac2364c4 20 }
fbcosentino 0:123cac2364c4 21
fbcosentino 0:123cac2364c4 22
fbcosentino 0:123cac2364c4 23
fbcosentino 0:123cac2364c4 24 // Partially based on a version by Manuel Caballero
fbcosentino 0:123cac2364c4 25 // https://os.mbed.com/users/mcm/
fbcosentino 0:123cac2364c4 26
fbcosentino 0:123cac2364c4 27 BareRadio::BareRadio() {
fbcosentino 0:123cac2364c4 28 data_len = 32;
fbcosentino 0:123cac2364c4 29 for (int i=0; i<data_len; i++) packet[i] = 0;
fbcosentino 0:123cac2364c4 30 ConfigClock();
fbcosentino 0:123cac2364c4 31 }
fbcosentino 0:123cac2364c4 32
fbcosentino 0:123cac2364c4 33 int BareRadio::ConfigClock() {
fbcosentino 0:123cac2364c4 34 int i;
fbcosentino 0:123cac2364c4 35
fbcosentino 0:123cac2364c4 36 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; // flag
fbcosentino 0:123cac2364c4 37 NRF_CLOCK->TASKS_HFCLKSTART = 1; // start task
fbcosentino 0:123cac2364c4 38
fbcosentino 0:123cac2364c4 39 for (i=0; i<10000; i++) {
fbcosentino 0:123cac2364c4 40 if (NRF_CLOCK->EVENTS_HFCLKSTARTED) return 1;
fbcosentino 0:123cac2364c4 41 wait_us(10);
fbcosentino 0:123cac2364c4 42 }
fbcosentino 0:123cac2364c4 43 return 0; // could not configure timer in 100ms
fbcosentino 0:123cac2364c4 44 }
fbcosentino 0:123cac2364c4 45
fbcosentino 0:123cac2364c4 46 void BareRadio::Setup(int mode, RadioAddress address, RadioConfig& config) {
fbcosentino 0:123cac2364c4 47 // According to datasheet, power off and on causes a reset on all registers
fbcosentino 0:123cac2364c4 48 NRF_RADIO->POWER = ( RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos ); // POWER OFF
fbcosentino 0:123cac2364c4 49 wait_us(10);
fbcosentino 0:123cac2364c4 50 NRF_RADIO->POWER = ( RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos ); // POWER ON
fbcosentino 0:123cac2364c4 51
fbcosentino 0:123cac2364c4 52 // calculate the BASE0 length based on the total address length
fbcosentino 0:123cac2364c4 53 // total address length must be in the range [3,5]
fbcosentino 0:123cac2364c4 54 int BASE0_len = config.address_length - 1;
fbcosentino 0:123cac2364c4 55 if (BASE0_len < 2) BASE0_len = 2;
fbcosentino 0:123cac2364c4 56 if (BASE0_len > 4) BASE0_len = 4;
fbcosentino 0:123cac2364c4 57
fbcosentino 0:123cac2364c4 58 data_len = config.data_length;
fbcosentino 0:123cac2364c4 59
fbcosentino 0:123cac2364c4 60 // Configure data rate (0=1M, 1=2M, 2=250K, 3=BLE1M)
fbcosentino 0:123cac2364c4 61 NRF_RADIO->MODE = ( config.rate << RADIO_MODE_MODE_Pos );
fbcosentino 0:123cac2364c4 62
fbcosentino 0:123cac2364c4 63 // Configure packet: NO S0,S1 or Length fields & 8-bit preamble.
fbcosentino 0:123cac2364c4 64 // Compatible to nRF24 without dynamic payload
fbcosentino 0:123cac2364c4 65 NRF_RADIO->PCNF0 = ( 0 << RADIO_PCNF0_LFLEN_Pos ) |
fbcosentino 0:123cac2364c4 66 ( 0 << RADIO_PCNF0_S0LEN_Pos ) |
fbcosentino 0:123cac2364c4 67 ( 0 << RADIO_PCNF0_S1LEN_Pos )
fbcosentino 0:123cac2364c4 68 #ifdef TARGET_NRF52
fbcosentino 0:123cac2364c4 69 | ( RADIO_PCNF0_S1INCL_Automatic << RADIO_PCNF0_S1INCL_Pos )
fbcosentino 0:123cac2364c4 70 | ( RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos )
fbcosentino 0:123cac2364c4 71 #endif
fbcosentino 0:123cac2364c4 72 ;
fbcosentino 0:123cac2364c4 73
fbcosentino 0:123cac2364c4 74 // Configure static payload length
fbcosentino 0:123cac2364c4 75 NRF_RADIO->PCNF1 = ( config.data_length << RADIO_PCNF1_MAXLEN_Pos) | // this is to truncate the packet
fbcosentino 0:123cac2364c4 76 ( config.data_length << RADIO_PCNF1_STATLEN_Pos) | // this is to configure the radio
fbcosentino 0:123cac2364c4 77 ( BASE0_len << RADIO_PCNF1_BALEN_Pos) |
fbcosentino 0:123cac2364c4 78 ( config.endianness << RADIO_PCNF1_ENDIAN_Pos) |
fbcosentino 0:123cac2364c4 79 ( config.use_whitening << RADIO_PCNF1_WHITEEN_Pos);
fbcosentino 0:123cac2364c4 80
fbcosentino 0:123cac2364c4 81 // Whitening value
fbcosentino 0:123cac2364c4 82 NRF_RADIO->DATAWHITEIV = ( ( 0x55 & RADIO_DATAWHITEIV_DATAWHITEIV_Msk ) << RADIO_DATAWHITEIV_DATAWHITEIV_Pos );
fbcosentino 0:123cac2364c4 83
fbcosentino 0:123cac2364c4 84 // Configure address Prefix0 and Base0
fbcosentino 0:123cac2364c4 85 unsigned int addr[5] = {address.A0, address.A1, address.A2, address.A3, address.A4};
fbcosentino 0:123cac2364c4 86 unsigned int base_address = 0;
fbcosentino 0:123cac2364c4 87 int i = 0;
fbcosentino 0:123cac2364c4 88 while (i<BASE0_len) {
fbcosentino 0:123cac2364c4 89 base_address |= (addr[i] << (i*8));
fbcosentino 0:123cac2364c4 90 i++;
fbcosentino 0:123cac2364c4 91 }
fbcosentino 0:123cac2364c4 92 NRF_RADIO->BASE0 = base_address;
fbcosentino 0:123cac2364c4 93 NRF_RADIO->PREFIX0 = ( ( addr[i] & RADIO_PREFIX0_AP0_Msk ) << RADIO_PREFIX0_AP0_Pos );
fbcosentino 0:123cac2364c4 94
fbcosentino 0:123cac2364c4 95 // Initialize CRC ( two bytes )
fbcosentino 0:123cac2364c4 96 // Includes address field for nRF24 compatibility
fbcosentino 0:123cac2364c4 97 NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos) |
fbcosentino 0:123cac2364c4 98 (RADIO_CRCCNF_SKIPADDR_Include << RADIO_CRCCNF_SKIPADDR_Pos);
fbcosentino 0:123cac2364c4 99
fbcosentino 0:123cac2364c4 100 NRF_RADIO->CRCPOLY = ( config.crc_poly << RADIO_CRCPOLY_CRCPOLY_Pos );
fbcosentino 0:123cac2364c4 101 NRF_RADIO->CRCINIT = ( config.crc_init << RADIO_CRCINIT_CRCINIT_Pos );
fbcosentino 0:123cac2364c4 102
fbcosentino 0:123cac2364c4 103 #ifdef TARGET_NRF52
fbcosentino 0:123cac2364c4 104 // Enable fast rampup, new in nRF52
fbcosentino 0:123cac2364c4 105 NRF_RADIO->MODECNF0 = ( RADIO_MODECNF0_DTX_B0 << RADIO_MODECNF0_DTX_Pos ) |
fbcosentino 0:123cac2364c4 106 ( RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos );
fbcosentino 0:123cac2364c4 107 #endif
fbcosentino 0:123cac2364c4 108
fbcosentino 0:123cac2364c4 109 NRF_RADIO->FREQUENCY = ( ( config.frequency & RADIO_FREQUENCY_FREQUENCY_Msk ) << RADIO_FREQUENCY_FREQUENCY_Pos ); // Frequency = 2400 + FREQUENCY (MHz).
fbcosentino 0:123cac2364c4 110
fbcosentino 0:123cac2364c4 111
fbcosentino 0:123cac2364c4 112 // Configure address of the packet and logic address to use
fbcosentino 0:123cac2364c4 113 NRF_RADIO->PACKETPTR = (unsigned int)&packet[0]; // Almost the same as (unsigned int)packet,
fbcosentino 0:123cac2364c4 114 // but sizeof() will return normal pointer size
fbcosentino 0:123cac2364c4 115
fbcosentino 0:123cac2364c4 116 // Transmit to address 0
fbcosentino 0:123cac2364c4 117 NRF_RADIO->TXADDRESS = ( 0 << RADIO_TXADDRESS_TXADDRESS_Pos);
fbcosentino 0:123cac2364c4 118
fbcosentino 0:123cac2364c4 119 // Output Power: 0dBm @2400MHz
fbcosentino 0:123cac2364c4 120 NRF_RADIO->TXPOWER = ( config.tx_power << RADIO_TXPOWER_TXPOWER_Pos );
fbcosentino 0:123cac2364c4 121
fbcosentino 0:123cac2364c4 122 // TX
fbcosentino 0:123cac2364c4 123 if (mode == RADIO_MODE_TX) {
fbcosentino 0:123cac2364c4 124
fbcosentino 0:123cac2364c4 125 // Disable receiving address
fbcosentino 0:123cac2364c4 126 NRF_RADIO->RXADDRESSES = ( RADIO_RXADDRESSES_ADDR0_Disabled << RADIO_RXADDRESSES_ADDR0_Pos );
fbcosentino 0:123cac2364c4 127
fbcosentino 0:123cac2364c4 128 // Configure shortcuts.
fbcosentino 0:123cac2364c4 129 NRF_RADIO->SHORTS = ( RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos ) |
fbcosentino 0:123cac2364c4 130 ( RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos );
fbcosentino 0:123cac2364c4 131 }
fbcosentino 0:123cac2364c4 132
fbcosentino 0:123cac2364c4 133 // RX
fbcosentino 0:123cac2364c4 134 if (mode == RADIO_MODE_RX) {
fbcosentino 0:123cac2364c4 135 // Use logical address 0 (BASE0 + PREFIX0 byte 0)
fbcosentino 0:123cac2364c4 136 NRF_RADIO->RXADDRESSES = ( RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos );
fbcosentino 0:123cac2364c4 137
fbcosentino 0:123cac2364c4 138 // Configure shortcuts.
fbcosentino 0:123cac2364c4 139 NRF_RADIO->SHORTS = ( RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos ) |
fbcosentino 0:123cac2364c4 140 ( RADIO_SHORTS_END_START_Enabled << RADIO_SHORTS_END_START_Pos );
fbcosentino 0:123cac2364c4 141
fbcosentino 0:123cac2364c4 142 NRF_RADIO->TASKS_RXEN = 1; // Enable receiver
fbcosentino 0:123cac2364c4 143 }
fbcosentino 0:123cac2364c4 144 }
fbcosentino 0:123cac2364c4 145
fbcosentino 0:123cac2364c4 146
fbcosentino 0:123cac2364c4 147 void BareRadio::Transmit(char * data) {
fbcosentino 0:123cac2364c4 148 Transmit((unsigned char *)data);
fbcosentino 0:123cac2364c4 149 }
fbcosentino 0:123cac2364c4 150 void BareRadio::Transmit(unsigned char * data) {
fbcosentino 0:123cac2364c4 151 // data must be an array of (unsigned) char at least data_len elements wide
fbcosentino 0:123cac2364c4 152 for (int i=0; i<data_len; i++) packet[i] = data[i];
fbcosentino 0:123cac2364c4 153
fbcosentino 0:123cac2364c4 154 // Transmits one packet
fbcosentino 0:123cac2364c4 155 NRF_RADIO->TASKS_TXEN = 1; // Enable transmitter
fbcosentino 0:123cac2364c4 156 while ( ( NRF_RADIO->EVENTS_DISABLED ) == 0 ); // Wait until transmission complete
fbcosentino 0:123cac2364c4 157 NRF_RADIO->EVENTS_DISABLED = 0; // Clear flag
fbcosentino 0:123cac2364c4 158 // Time on air: 150 us
fbcosentino 0:123cac2364c4 159
fbcosentino 0:123cac2364c4 160 }
fbcosentino 0:123cac2364c4 161
fbcosentino 0:123cac2364c4 162 int BareRadio::Receive(char * data) {
fbcosentino 0:123cac2364c4 163 return Receive((unsigned char *) data);
fbcosentino 0:123cac2364c4 164 }
fbcosentino 0:123cac2364c4 165 int BareRadio::Receive(unsigned char * data) {
fbcosentino 0:123cac2364c4 166 // returns true if a packet has arrived and data was replaced
fbcosentino 0:123cac2364c4 167 if ( NRF_RADIO->EVENTS_END == 1 ) {
fbcosentino 0:123cac2364c4 168 NRF_RADIO->EVENTS_END = 0;
fbcosentino 0:123cac2364c4 169 if (NRF_RADIO->CRCSTATUS) {
fbcosentino 0:123cac2364c4 170 for (int i=0; i<data_len; i++) data[i] = packet[i];
fbcosentino 0:123cac2364c4 171 return 1;
fbcosentino 0:123cac2364c4 172 }
fbcosentino 0:123cac2364c4 173 }
fbcosentino 0:123cac2364c4 174 return 0;
fbcosentino 0:123cac2364c4 175
fbcosentino 0:123cac2364c4 176 }