Specialized interface code for the nRF24L01P wireless transceiver.

Dependents:   WalkingRobot PcRadioBridge FzeroXcontroller WalkingRobot ... more

Committer:
pclary
Date:
Thu Jan 17 18:33:18 2013 +0000
Revision:
4:7953b5fa8aae
Parent:
3:245faa365852
Removed unnecessary 1ms pause in receive interrupt.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pclary 0:fb0cf6209cd3 1 #include "Radio.h"
pclary 0:fb0cf6209cd3 2 #include "nRF24L01P_defs.h"
pclary 0:fb0cf6209cd3 3
pclary 0:fb0cf6209cd3 4
pclary 0:fb0cf6209cd3 5
pclary 0:fb0cf6209cd3 6 Radio::Radio(PinName mosi, PinName miso, PinName sck, PinName csn, PinName ce, PinName irq)
pclary 0:fb0cf6209cd3 7 : _spi(mosi, miso, sck), _csn(csn), _ce(ce), _irq(irq)
pclary 0:fb0cf6209cd3 8 {
pclary 0:fb0cf6209cd3 9 // Disable nRF24L01+
pclary 0:fb0cf6209cd3 10 _ce = 0;
pclary 0:fb0cf6209cd3 11
pclary 0:fb0cf6209cd3 12 // Disable chip select
pclary 0:fb0cf6209cd3 13 _csn = 1;
pclary 0:fb0cf6209cd3 14
pclary 0:fb0cf6209cd3 15 // Set up SPI
pclary 0:fb0cf6209cd3 16 _spi.frequency(SPI_FREQUENCY);
pclary 0:fb0cf6209cd3 17 _spi.format(8, 0);
pclary 0:fb0cf6209cd3 18
pclary 0:fb0cf6209cd3 19 // Set to use controller channel 0
pclary 0:fb0cf6209cd3 20 controller = 0;
pclary 0:fb0cf6209cd3 21
pclary 0:fb0cf6209cd3 22 // Set up IRQ
pclary 0:fb0cf6209cd3 23 _irq.fall(this, &Radio::receive);
pclary 0:fb0cf6209cd3 24 }
pclary 0:fb0cf6209cd3 25
pclary 0:fb0cf6209cd3 26
pclary 0:fb0cf6209cd3 27
pclary 0:fb0cf6209cd3 28 void Radio::reset()
pclary 0:fb0cf6209cd3 29 {
pclary 0:fb0cf6209cd3 30 // Wait for power on reset
pclary 0:fb0cf6209cd3 31 wait_us(TIMING_Tpor);
pclary 0:fb0cf6209cd3 32
pclary 0:fb0cf6209cd3 33 // Put into standby
pclary 0:fb0cf6209cd3 34 _ce = 0;
pclary 0:fb0cf6209cd3 35
pclary 0:fb0cf6209cd3 36 // Configure registers
pclary 0:fb0cf6209cd3 37 setRegister(CONFIG, CONFIG_MASK_TX_DS | CONFIG_MASK_MAX_RT | CONFIG_EN_CRC | CONFIG_PWR_UP | CONFIG_PRIM_RX);
pclary 0:fb0cf6209cd3 38 setRegister(EN_AA, 0x00);
pclary 0:fb0cf6209cd3 39 setRegister(EN_RXADDR, ERX_P0 | ERX_P1);
pclary 0:fb0cf6209cd3 40 setRegister(SETUP_AW, SETUP_AW_3BYTES);
pclary 0:fb0cf6209cd3 41 setRegister(SETUP_RETR, 0x00);
pclary 0:fb0cf6209cd3 42 setRegister(RF_CH, RF_CHANNEL);
pclary 0:fb0cf6209cd3 43 setRegister(RF_SETUP, RF_SETUP_RF_DR_HIGH | RF_SETUP_RF_PWR_0);
pclary 0:fb0cf6209cd3 44 setRegister(STATUS, STATUS_RX_DR | STATUS_TX_DS | STATUS_MAX_RT);
pclary 0:fb0cf6209cd3 45 setRegister(RX_PW_P0, 4);
pclary 0:fb0cf6209cd3 46 setRegister(RX_PW_P1, 4);
pclary 0:fb0cf6209cd3 47 setRegister(DYNPD, 0x00);
pclary 0:fb0cf6209cd3 48 setRegister(FEATURE, 0x00);
pclary 0:fb0cf6209cd3 49
pclary 0:fb0cf6209cd3 50 // Set addresses
pclary 0:fb0cf6209cd3 51 _csn = 0;
pclary 0:fb0cf6209cd3 52 _spi.write(W_REGISTER | RX_ADDR_P0);
pclary 0:fb0cf6209cd3 53 _spi.write(CTRL_BASE_ADDRESS_1 + (controller & 0xf));
pclary 0:fb0cf6209cd3 54 _spi.write(CTRL_BASE_ADDRESS_2);
pclary 0:fb0cf6209cd3 55 _spi.write(CTRL_BASE_ADDRESS_3);
pclary 0:fb0cf6209cd3 56 _csn = 1;
pclary 0:fb0cf6209cd3 57 _csn = 0;
pclary 0:fb0cf6209cd3 58 _spi.write(W_REGISTER | RX_ADDR_P1);
pclary 0:fb0cf6209cd3 59 _spi.write(ROBOT_ADDRESS_1);
pclary 0:fb0cf6209cd3 60 _spi.write(ROBOT_ADDRESS_2);
pclary 0:fb0cf6209cd3 61 _spi.write(ROBOT_ADDRESS_3);
pclary 0:fb0cf6209cd3 62 _csn = 1;
pclary 0:fb0cf6209cd3 63 _csn = 0;
pclary 0:fb0cf6209cd3 64 _spi.write(W_REGISTER | TX_ADDR);
pclary 0:fb0cf6209cd3 65 _spi.write(ROBOT_ADDRESS_1);
pclary 0:fb0cf6209cd3 66 _spi.write(ROBOT_ADDRESS_2);
pclary 0:fb0cf6209cd3 67 _spi.write(ROBOT_ADDRESS_3);
pclary 0:fb0cf6209cd3 68 _csn = 1;
pclary 0:fb0cf6209cd3 69
pclary 0:fb0cf6209cd3 70 // Put into PRX
pclary 0:fb0cf6209cd3 71 _ce = 1;
pclary 0:fb0cf6209cd3 72 wait_us(TIMING_Tstby2a);
pclary 0:fb0cf6209cd3 73
pclary 0:fb0cf6209cd3 74 // Flush FIFOs
pclary 0:fb0cf6209cd3 75 _csn = 0;
pclary 0:fb0cf6209cd3 76 _spi.write(FLUSH_TX);
pclary 0:fb0cf6209cd3 77 _csn = 1;
pclary 0:fb0cf6209cd3 78 _csn = 0;
pclary 0:fb0cf6209cd3 79 _spi.write(FLUSH_RX);
pclary 0:fb0cf6209cd3 80 _csn = 1;
pclary 0:fb0cf6209cd3 81 }
pclary 0:fb0cf6209cd3 82
pclary 0:fb0cf6209cd3 83
pclary 0:fb0cf6209cd3 84
pclary 0:fb0cf6209cd3 85 void Radio::transmit(uint32_t data)
pclary 0:fb0cf6209cd3 86 {
pclary 0:fb0cf6209cd3 87 // Put into standby
pclary 0:fb0cf6209cd3 88 _ce = 0;
pclary 0:fb0cf6209cd3 89
pclary 0:fb0cf6209cd3 90 // Configure for PTX
pclary 0:fb0cf6209cd3 91 int config = getRegister(CONFIG);
pclary 0:fb0cf6209cd3 92 config &= ~CONFIG_PRIM_RX;
pclary 0:fb0cf6209cd3 93 setRegister(CONFIG, config);
pclary 0:fb0cf6209cd3 94
pclary 0:fb0cf6209cd3 95 // Write packet data
pclary 0:fb0cf6209cd3 96 _csn = 0;
pclary 0:fb0cf6209cd3 97 _spi.write(W_TX_PAYLOAD);
pclary 0:fb0cf6209cd3 98 _spi.write( (data>>0) & 0xff );
pclary 0:fb0cf6209cd3 99 _spi.write( (data>>8) & 0xff );
pclary 0:fb0cf6209cd3 100 _spi.write( (data>>16) & 0xff );
pclary 0:fb0cf6209cd3 101 _spi.write( (data>>24) & 0xff );
pclary 0:fb0cf6209cd3 102 _csn = 1;
pclary 0:fb0cf6209cd3 103
pclary 0:fb0cf6209cd3 104 // Put into PTX
pclary 0:fb0cf6209cd3 105 _ce = 1;
pclary 0:fb0cf6209cd3 106 wait_us(TIMING_Tstby2a);
pclary 0:fb0cf6209cd3 107 _ce = 0;
pclary 0:fb0cf6209cd3 108
pclary 0:fb0cf6209cd3 109 // Wait for message transmission and put into PRX
pclary 0:fb0cf6209cd3 110 wait_us(TIMING_Toa);
pclary 0:fb0cf6209cd3 111 config = getRegister(CONFIG);
pclary 0:fb0cf6209cd3 112 config |= CONFIG_PRIM_RX;
pclary 0:fb0cf6209cd3 113 setRegister(CONFIG, config);
pclary 0:fb0cf6209cd3 114 setRegister(STATUS, STATUS_TX_DS);
pclary 0:fb0cf6209cd3 115 _ce = 1;
pclary 0:fb0cf6209cd3 116 }
pclary 0:fb0cf6209cd3 117
pclary 0:fb0cf6209cd3 118
pclary 0:fb0cf6209cd3 119
pclary 0:fb0cf6209cd3 120 void Radio::receive()
pclary 0:fb0cf6209cd3 121 {
pclary 0:fb0cf6209cd3 122 uint32_t data = 0;
pclary 0:fb0cf6209cd3 123 int pipe;
pclary 0:fb0cf6209cd3 124
pclary 2:24a6ae7c3f69 125 while (!(getRegister(FIFO_STATUS) & FIFO_STATUS_RX_EMPTY))
pclary 2:24a6ae7c3f69 126 {
pclary 2:24a6ae7c3f69 127 // Check data pipe
pclary 4:7953b5fa8aae 128 //wait_us(1000);
pclary 2:24a6ae7c3f69 129 pipe = getStatus() & STATUS_RN_P_MASK;
pclary 2:24a6ae7c3f69 130
pclary 2:24a6ae7c3f69 131 // Read data
pclary 2:24a6ae7c3f69 132 _csn = 0;
pclary 2:24a6ae7c3f69 133 _spi.write(R_RX_PAYLOAD);
pclary 2:24a6ae7c3f69 134 data |= _spi.write(NOP)<<0;
pclary 2:24a6ae7c3f69 135 data |= _spi.write(NOP)<<8;
pclary 2:24a6ae7c3f69 136 data |= _spi.write(NOP)<<16;
pclary 2:24a6ae7c3f69 137 data |= _spi.write(NOP)<<24;
pclary 2:24a6ae7c3f69 138 _csn = 1;
pclary 2:24a6ae7c3f69 139
pclary 2:24a6ae7c3f69 140 // Sort into recieve buffer
pclary 2:24a6ae7c3f69 141 switch(pipe)
pclary 2:24a6ae7c3f69 142 {
pclary 2:24a6ae7c3f69 143 case STATUS_RN_P_NO_P0:
pclary 2:24a6ae7c3f69 144 rx_controller = data;
pclary 3:245faa365852 145 clearTimeout.attach(this, &Radio::clear, 0.5f);
pclary 2:24a6ae7c3f69 146 break;
pclary 2:24a6ae7c3f69 147
pclary 2:24a6ae7c3f69 148 case STATUS_RN_P_NO_P1:
pclary 2:24a6ae7c3f69 149 rx_robot[rx_robot_pos++ % RX_BUFFER_SIZE] = data;
pclary 2:24a6ae7c3f69 150 break;
pclary 2:24a6ae7c3f69 151
pclary 2:24a6ae7c3f69 152 default:
pclary 2:24a6ae7c3f69 153 break;
pclary 2:24a6ae7c3f69 154 }
pclary 2:24a6ae7c3f69 155 }
pclary 2:24a6ae7c3f69 156
pclary 0:fb0cf6209cd3 157 // Reset IRQ pin
pclary 0:fb0cf6209cd3 158 setRegister(STATUS, STATUS_RX_DR);
pclary 0:fb0cf6209cd3 159 }
pclary 0:fb0cf6209cd3 160
pclary 0:fb0cf6209cd3 161
pclary 0:fb0cf6209cd3 162
pclary 3:245faa365852 163 void Radio::clear()
pclary 3:245faa365852 164 {
pclary 3:245faa365852 165 rx_controller = 0;
pclary 3:245faa365852 166 }
pclary 3:245faa365852 167
pclary 3:245faa365852 168
pclary 3:245faa365852 169
pclary 0:fb0cf6209cd3 170 int Radio::getRegister(int address)
pclary 0:fb0cf6209cd3 171 {
pclary 0:fb0cf6209cd3 172 _csn = 0;
pclary 0:fb0cf6209cd3 173 int rc = R_REGISTER | (address & REGISTER_ADDRESS_MASK);
pclary 0:fb0cf6209cd3 174 _spi.write(rc);
pclary 0:fb0cf6209cd3 175 int data = _spi.write(NOP);
pclary 0:fb0cf6209cd3 176 _csn = 1;
pclary 0:fb0cf6209cd3 177 return data;
pclary 0:fb0cf6209cd3 178 }
pclary 0:fb0cf6209cd3 179
pclary 0:fb0cf6209cd3 180
pclary 0:fb0cf6209cd3 181
pclary 0:fb0cf6209cd3 182 int Radio::getStatus()
pclary 0:fb0cf6209cd3 183 {
pclary 0:fb0cf6209cd3 184 _csn = 0;
pclary 0:fb0cf6209cd3 185 int status = _spi.write(NOP);
pclary 0:fb0cf6209cd3 186 _csn = 1;
pclary 0:fb0cf6209cd3 187 return status;
pclary 0:fb0cf6209cd3 188 }
pclary 0:fb0cf6209cd3 189
pclary 0:fb0cf6209cd3 190
pclary 0:fb0cf6209cd3 191 void Radio::setRegister(int address, int data)
pclary 0:fb0cf6209cd3 192 {
pclary 0:fb0cf6209cd3 193 bool enabled = false;
pclary 0:fb0cf6209cd3 194 if (_ce == 1)
pclary 0:fb0cf6209cd3 195 {
pclary 0:fb0cf6209cd3 196 enabled = true;
pclary 0:fb0cf6209cd3 197 _ce = 0;
pclary 0:fb0cf6209cd3 198 }
pclary 0:fb0cf6209cd3 199
pclary 0:fb0cf6209cd3 200 _csn = 0;
pclary 0:fb0cf6209cd3 201 int rc = W_REGISTER | (address & REGISTER_ADDRESS_MASK);
pclary 0:fb0cf6209cd3 202 _spi.write(rc);
pclary 0:fb0cf6209cd3 203 _spi.write(data & 0xff);
pclary 0:fb0cf6209cd3 204 _csn = 1;
pclary 0:fb0cf6209cd3 205
pclary 0:fb0cf6209cd3 206 if (enabled)
pclary 0:fb0cf6209cd3 207 {
pclary 0:fb0cf6209cd3 208 _ce = 1;
pclary 0:fb0cf6209cd3 209 wait_us(TIMING_Tpece2csn);
pclary 0:fb0cf6209cd3 210 }
pclary 0:fb0cf6209cd3 211
pclary 0:fb0cf6209cd3 212 }
pclary 1:32635715529f 213
pclary 1:32635715529f 214
pclary 1:32635715529f 215
pclary 1:32635715529f 216 /************************************************************************/
pclary 1:32635715529f 217
pclary 1:32635715529f 218
pclary 1:32635715529f 219
pclary 1:32635715529f 220 RadioController::RadioController(PinName mosi, PinName miso, PinName sck, PinName csn, PinName ce)
pclary 1:32635715529f 221 : _spi(mosi, miso, sck), _csn(csn), _ce(ce)
pclary 1:32635715529f 222 {
pclary 1:32635715529f 223 // Disable nRF24L01+
pclary 1:32635715529f 224 _ce = 0;
pclary 1:32635715529f 225
pclary 1:32635715529f 226 // Disable chip select
pclary 1:32635715529f 227 _csn = 1;
pclary 1:32635715529f 228
pclary 1:32635715529f 229 // Set up SPI
pclary 1:32635715529f 230 _spi.frequency(SPI_FREQUENCY);
pclary 1:32635715529f 231 _spi.format(8, 0);
pclary 1:32635715529f 232
pclary 1:32635715529f 233 // Set to use controller channel 0
pclary 1:32635715529f 234 controller = 0;
pclary 1:32635715529f 235 }
pclary 1:32635715529f 236
pclary 1:32635715529f 237
pclary 1:32635715529f 238
pclary 1:32635715529f 239 void RadioController::reset()
pclary 1:32635715529f 240 {
pclary 1:32635715529f 241 // Wait for power on reset
pclary 1:32635715529f 242 wait_us(TIMING_Tpor);
pclary 1:32635715529f 243
pclary 1:32635715529f 244 // Put into standby
pclary 1:32635715529f 245 _ce = 0;
pclary 1:32635715529f 246
pclary 1:32635715529f 247 // Configure registers
pclary 1:32635715529f 248 setRegister(CONFIG, CONFIG_MASK_RX_DR | CONFIG_MASK_TX_DS | CONFIG_MASK_MAX_RT | CONFIG_EN_CRC | CONFIG_PWR_UP);
pclary 1:32635715529f 249 setRegister(EN_AA, 0x00);
pclary 1:32635715529f 250 setRegister(EN_RXADDR, 0x00);
pclary 1:32635715529f 251 setRegister(SETUP_AW, SETUP_AW_3BYTES);
pclary 1:32635715529f 252 setRegister(SETUP_RETR, 0x00);
pclary 1:32635715529f 253 setRegister(RF_CH, RF_CHANNEL);
pclary 1:32635715529f 254 setRegister(RF_SETUP, RF_SETUP_RF_DR_HIGH | RF_SETUP_RF_PWR_0);
pclary 1:32635715529f 255 setRegister(STATUS, STATUS_RX_DR | STATUS_TX_DS | STATUS_MAX_RT);
pclary 1:32635715529f 256 setRegister(DYNPD, 0x00);
pclary 1:32635715529f 257 setRegister(FEATURE, 0x00);
pclary 1:32635715529f 258
pclary 1:32635715529f 259 // Set transmit address
pclary 1:32635715529f 260 _csn = 0;
pclary 1:32635715529f 261 _spi.write(W_REGISTER | TX_ADDR);
pclary 1:32635715529f 262 _spi.write(CTRL_BASE_ADDRESS_1 + (controller & 0xf));
pclary 1:32635715529f 263 _spi.write(CTRL_BASE_ADDRESS_2);
pclary 1:32635715529f 264 _spi.write(CTRL_BASE_ADDRESS_3);
pclary 1:32635715529f 265 _csn = 1;
pclary 1:32635715529f 266
pclary 1:32635715529f 267 // Flush TX FIFO
pclary 1:32635715529f 268 _csn = 0;
pclary 1:32635715529f 269 _spi.write(FLUSH_TX);
pclary 1:32635715529f 270 _csn = 1;
pclary 1:32635715529f 271 }
pclary 1:32635715529f 272
pclary 1:32635715529f 273
pclary 1:32635715529f 274
pclary 1:32635715529f 275 void RadioController::transmit(uint32_t data)
pclary 1:32635715529f 276 {
pclary 1:32635715529f 277 // Write packet data
pclary 1:32635715529f 278 _csn = 0;
pclary 1:32635715529f 279 _spi.write(W_TX_PAYLOAD);
pclary 1:32635715529f 280 _spi.write( (data>>0) & 0xff );
pclary 1:32635715529f 281 _spi.write( (data>>8) & 0xff );
pclary 1:32635715529f 282 _spi.write( (data>>16) & 0xff );
pclary 1:32635715529f 283 _spi.write( (data>>24) & 0xff );
pclary 1:32635715529f 284 _csn = 1;
pclary 1:32635715529f 285
pclary 1:32635715529f 286 // Put into PTX and transmit packet
pclary 1:32635715529f 287 _ce = 1;
pclary 1:32635715529f 288 wait_us(TIMING_Tstby2a);
pclary 1:32635715529f 289
pclary 1:32635715529f 290 // Go back into standby
pclary 1:32635715529f 291 _ce = 0;
pclary 1:32635715529f 292 }
pclary 1:32635715529f 293
pclary 1:32635715529f 294
pclary 1:32635715529f 295
pclary 1:32635715529f 296 void RadioController::setRegister(int address, int data)
pclary 1:32635715529f 297 {
pclary 1:32635715529f 298 bool enabled = false;
pclary 1:32635715529f 299 if (_ce == 1)
pclary 1:32635715529f 300 {
pclary 1:32635715529f 301 enabled = true;
pclary 1:32635715529f 302 _ce = 0;
pclary 1:32635715529f 303 }
pclary 1:32635715529f 304
pclary 1:32635715529f 305 _csn = 0;
pclary 1:32635715529f 306 int rc = W_REGISTER | (address & REGISTER_ADDRESS_MASK);
pclary 1:32635715529f 307 _spi.write(rc);
pclary 1:32635715529f 308 _spi.write(data & 0xff);
pclary 1:32635715529f 309 _csn = 1;
pclary 1:32635715529f 310
pclary 1:32635715529f 311 if (enabled)
pclary 1:32635715529f 312 {
pclary 1:32635715529f 313 _ce = 1;
pclary 1:32635715529f 314 wait_us(TIMING_Tpece2csn);
pclary 1:32635715529f 315 }
pclary 1:32635715529f 316
pclary 1:32635715529f 317 }