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.
nRFBareRadio.cpp
00001 #include "nRFBareRadio.h" 00002 00003 /* 00004 #ifdef TARGET_NRF52 00005 #define RADIO_RECEIVE_EVENT EVENTS_CRCOK 00006 #else 00007 #define RADIO_RECEIVE_EVENT EVENTS_END 00008 #endif*/ 00009 00010 RadioConfig::RadioConfig() { 00011 frequency = 2; 00012 rate = RADIO_RATE_2M; 00013 tx_power = RADIO_TX_0dBm; 00014 data_length = 32; // compatible to nRF24 (range 1-32) 00015 address_length = 5; // compatible to nRF24 (range 3-5) 00016 use_whitening = RADIO_NO_WHITENING; // compatible to nRF24 (no change) 00017 endianness = RADIO_BIGENDIAN; // compatible to nRF24 (no change) 00018 crc_poly = 0x1021; // compatible to nRF24 (no change) 00019 crc_init = 0xFFFF; // compatible to nRF24 (no change) 00020 } 00021 00022 00023 00024 // Partially based on a version by Manuel Caballero 00025 // https://os.mbed.com/users/mcm/ 00026 00027 BareRadio::BareRadio() { 00028 data_len = 32; 00029 for (int i=0; i<data_len; i++) packet[i] = 0; 00030 ConfigClock(); 00031 } 00032 00033 int BareRadio::ConfigClock() { 00034 int i; 00035 00036 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; // flag 00037 NRF_CLOCK->TASKS_HFCLKSTART = 1; // start task 00038 00039 for (i=0; i<10000; i++) { 00040 if (NRF_CLOCK->EVENTS_HFCLKSTARTED) return 1; 00041 wait_us(10); 00042 } 00043 return 0; // could not configure timer in 100ms 00044 } 00045 00046 void BareRadio::Setup(int mode, RadioAddress address, RadioConfig& config) { 00047 // According to datasheet, power off and on causes a reset on all registers 00048 NRF_RADIO->POWER = ( RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos ); // POWER OFF 00049 wait_us(10); 00050 NRF_RADIO->POWER = ( RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos ); // POWER ON 00051 00052 // calculate the BASE0 length based on the total address length 00053 // total address length must be in the range [3,5] 00054 int BASE0_len = config.address_length - 1; 00055 if (BASE0_len < 2) BASE0_len = 2; 00056 if (BASE0_len > 4) BASE0_len = 4; 00057 00058 data_len = config.data_length; 00059 00060 // Configure data rate (0=1M, 1=2M, 2=250K, 3=BLE1M) 00061 NRF_RADIO->MODE = ( config.rate << RADIO_MODE_MODE_Pos ); 00062 00063 // Configure packet: NO S0,S1 or Length fields & 8-bit preamble. 00064 // Compatible to nRF24 without dynamic payload 00065 NRF_RADIO->PCNF0 = ( 0 << RADIO_PCNF0_LFLEN_Pos ) | 00066 ( 0 << RADIO_PCNF0_S0LEN_Pos ) | 00067 ( 0 << RADIO_PCNF0_S1LEN_Pos ) 00068 #ifdef TARGET_NRF52 00069 | ( RADIO_PCNF0_S1INCL_Automatic << RADIO_PCNF0_S1INCL_Pos ) 00070 | ( RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos ) 00071 #endif 00072 ; 00073 00074 // Configure static payload length 00075 NRF_RADIO->PCNF1 = ( config.data_length << RADIO_PCNF1_MAXLEN_Pos) | // this is to truncate the packet 00076 ( config.data_length << RADIO_PCNF1_STATLEN_Pos) | // this is to configure the radio 00077 ( BASE0_len << RADIO_PCNF1_BALEN_Pos) | 00078 ( config.endianness << RADIO_PCNF1_ENDIAN_Pos) | 00079 ( config.use_whitening << RADIO_PCNF1_WHITEEN_Pos); 00080 00081 // Whitening value 00082 NRF_RADIO->DATAWHITEIV = ( ( 0x55 & RADIO_DATAWHITEIV_DATAWHITEIV_Msk ) << RADIO_DATAWHITEIV_DATAWHITEIV_Pos ); 00083 00084 // Configure address Prefix0 and Base0 00085 unsigned int addr[5] = {address.A0, address.A1, address.A2, address.A3, address.A4}; 00086 unsigned int base_address = 0; 00087 int i = 0; 00088 while (i<BASE0_len) { 00089 base_address |= (addr[i] << (i*8)); 00090 i++; 00091 } 00092 NRF_RADIO->BASE0 = base_address; 00093 NRF_RADIO->PREFIX0 = ( ( addr[i] & RADIO_PREFIX0_AP0_Msk ) << RADIO_PREFIX0_AP0_Pos ); 00094 00095 // Initialize CRC ( two bytes ) 00096 // Includes address field for nRF24 compatibility 00097 NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos) | 00098 (RADIO_CRCCNF_SKIPADDR_Include << RADIO_CRCCNF_SKIPADDR_Pos); 00099 00100 NRF_RADIO->CRCPOLY = ( config.crc_poly << RADIO_CRCPOLY_CRCPOLY_Pos ); 00101 NRF_RADIO->CRCINIT = ( config.crc_init << RADIO_CRCINIT_CRCINIT_Pos ); 00102 00103 #ifdef TARGET_NRF52 00104 // Enable fast rampup, new in nRF52 00105 NRF_RADIO->MODECNF0 = ( RADIO_MODECNF0_DTX_B0 << RADIO_MODECNF0_DTX_Pos ) | 00106 ( RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos ); 00107 #endif 00108 00109 NRF_RADIO->FREQUENCY = ( ( config.frequency & RADIO_FREQUENCY_FREQUENCY_Msk ) << RADIO_FREQUENCY_FREQUENCY_Pos ); // Frequency = 2400 + FREQUENCY (MHz). 00110 00111 00112 // Configure address of the packet and logic address to use 00113 NRF_RADIO->PACKETPTR = (unsigned int)&packet[0]; // Almost the same as (unsigned int)packet, 00114 // but sizeof() will return normal pointer size 00115 00116 // Transmit to address 0 00117 NRF_RADIO->TXADDRESS = ( 0 << RADIO_TXADDRESS_TXADDRESS_Pos); 00118 00119 // Output Power: 0dBm @2400MHz 00120 NRF_RADIO->TXPOWER = ( config.tx_power << RADIO_TXPOWER_TXPOWER_Pos ); 00121 00122 // TX 00123 if (mode == RADIO_MODE_TX) { 00124 00125 // Disable receiving address 00126 NRF_RADIO->RXADDRESSES = ( RADIO_RXADDRESSES_ADDR0_Disabled << RADIO_RXADDRESSES_ADDR0_Pos ); 00127 00128 // Configure shortcuts. 00129 NRF_RADIO->SHORTS = ( RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos ) | 00130 ( RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos ); 00131 } 00132 00133 // RX 00134 if (mode == RADIO_MODE_RX) { 00135 // Use logical address 0 (BASE0 + PREFIX0 byte 0) 00136 NRF_RADIO->RXADDRESSES = ( RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos ); 00137 00138 // Configure shortcuts. 00139 NRF_RADIO->SHORTS = ( RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos ) | 00140 ( RADIO_SHORTS_END_START_Enabled << RADIO_SHORTS_END_START_Pos ); 00141 00142 NRF_RADIO->TASKS_RXEN = 1; // Enable receiver 00143 } 00144 } 00145 00146 00147 void BareRadio::Transmit(char * data) { 00148 Transmit((unsigned char *)data); 00149 } 00150 void BareRadio::Transmit(unsigned char * data) { 00151 // data must be an array of (unsigned) char at least data_len elements wide 00152 for (int i=0; i<data_len; i++) packet[i] = data[i]; 00153 00154 // Transmits one packet 00155 NRF_RADIO->TASKS_TXEN = 1; // Enable transmitter 00156 while ( ( NRF_RADIO->EVENTS_DISABLED ) == 0 ); // Wait until transmission complete 00157 NRF_RADIO->EVENTS_DISABLED = 0; // Clear flag 00158 // Time on air: 150 us 00159 00160 } 00161 00162 int BareRadio::Receive(char * data) { 00163 return Receive((unsigned char *) data); 00164 } 00165 int BareRadio::Receive(unsigned char * data) { 00166 // returns true if a packet has arrived and data was replaced 00167 if ( NRF_RADIO->EVENTS_END == 1 ) { 00168 NRF_RADIO->EVENTS_END = 0; 00169 if (NRF_RADIO->CRCSTATUS) { 00170 for (int i=0; i<data_len; i++) data[i] = packet[i]; 00171 return 1; 00172 } 00173 } 00174 return 0; 00175 00176 }
Generated on Thu Jul 14 2022 10:13:26 by
1.7.2