Library for the nRF2401A Transceiver

Dependents:   nRF2401A_Hello_World nRF2401A_Wireless_Accelerometer_joypad nRF2401A_Gameduino_Invaders

Committer:
TheChrisyd
Date:
Sun Mar 09 11:57:33 2014 +0000
Revision:
9:7245524e37e4
Parent:
7:22f69cf045d9
Update after feedback, parameters set to defaults, removed references ti this and added error checking to the functions instead, moved defines and updated documentation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TheChrisyd 3:7ae3a5e53a1f 1 /**
TheChrisyd 3:7ae3a5e53a1f 2 *@section DESCRIPTION
TheChrisyd 3:7ae3a5e53a1f 3 * mbed nRF2401A Library
TheChrisyd 3:7ae3a5e53a1f 4 *@section LICENSE
TheChrisyd 0:17cb4be1e37f 5 * Copyright (c) 2011, Per Söderstam
TheChrisyd 0:17cb4be1e37f 6 *
TheChrisyd 0:17cb4be1e37f 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
TheChrisyd 0:17cb4be1e37f 8 * of this software and associated documentation files (the "Software"), to deal
TheChrisyd 0:17cb4be1e37f 9 * in the Software without restriction, including without limitation the rights
TheChrisyd 0:17cb4be1e37f 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
TheChrisyd 0:17cb4be1e37f 11 * copies of the Software, and to permit persons to whom the Software is
TheChrisyd 0:17cb4be1e37f 12 * furnished to do so, subject to the following conditions:
TheChrisyd 0:17cb4be1e37f 13 *
TheChrisyd 0:17cb4be1e37f 14 * The above copyright notice and this permission notice shall be included in
TheChrisyd 0:17cb4be1e37f 15 * all copies or substantial portions of the Software.
TheChrisyd 0:17cb4be1e37f 16 *
TheChrisyd 0:17cb4be1e37f 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
TheChrisyd 0:17cb4be1e37f 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
TheChrisyd 0:17cb4be1e37f 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
TheChrisyd 0:17cb4be1e37f 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
TheChrisyd 0:17cb4be1e37f 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
TheChrisyd 0:17cb4be1e37f 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
TheChrisyd 0:17cb4be1e37f 23 * THE SOFTWARE.
TheChrisyd 3:7ae3a5e53a1f 24 * @file "nRF2401A.cpp"
TheChrisyd 0:17cb4be1e37f 25 */
TheChrisyd 0:17cb4be1e37f 26
TheChrisyd 0:17cb4be1e37f 27 #include "nRF2401A.h"
TheChrisyd 0:17cb4be1e37f 28
TheChrisyd 9:7245524e37e4 29 #define Ts 1 /**< Setup time from data to rising clock edge on write (accualy 500 ns). */
TheChrisyd 9:7245524e37e4 30 #define Th 1 /**< Hold time from rising clock to data toggle/falling clock (accualy 500 ns). */
TheChrisyd 9:7245524e37e4 31 #define Tcs2data 5 /**< Min delay from CS assert to data, in us. */
TheChrisyd 9:7245524e37e4 32 #define Tce2data 5 /**< Min delay from CE assert to data, in us. */
TheChrisyd 9:7245524e37e4 33 #define Td 1 /**< Minimum delay between edges (actually 50 ns). */
TheChrisyd 9:7245524e37e4 34 #define Tpd2cfgm 3 /**< Minimum delay from power up of tranciever to configuration. */
TheChrisyd 9:7245524e37e4 35 #define Tsby2txSB 195 /**< Minimum delay from tx initation to air, in us. */
TheChrisyd 9:7245524e37e4 36 #define Tsby2rx 202 /**< Minimum delay from stanby to rx mode, in us. */
TheChrisyd 9:7245524e37e4 37 #define Thmin 5 /**< */
TheChrisyd 9:7245524e37e4 38 #define Tclk2data 1 /**< */
TheChrisyd 9:7245524e37e4 39 #define MAXIMUM_ADDR_LENGTH 40 /**< */
TheChrisyd 9:7245524e37e4 40
TheChrisyd 0:17cb4be1e37f 41
TheChrisyd 0:17cb4be1e37f 42 nRF2401A::nRF2401A(PinName ce,
TheChrisyd 0:17cb4be1e37f 43 PinName cs,
TheChrisyd 0:17cb4be1e37f 44 PinName dr1,
TheChrisyd 0:17cb4be1e37f 45 PinName clk1,
TheChrisyd 0:17cb4be1e37f 46 PinName data)
TheChrisyd 9:7245524e37e4 47 :
TheChrisyd 9:7245524e37e4 48 _ce(DigitalOut(ce)),
TheChrisyd 0:17cb4be1e37f 49 _cs(DigitalOut(cs)),
TheChrisyd 0:17cb4be1e37f 50 _dr1(DigitalIn(dr1)),
TheChrisyd 0:17cb4be1e37f 51 _clk1(DigitalOut(clk1)),
TheChrisyd 0:17cb4be1e37f 52 _data(DigitalInOut(data)),
TheChrisyd 7:22f69cf045d9 53 _state(nRF2401A::STANDBY),
TheChrisyd 0:17cb4be1e37f 54 _rx_handler((nRF2401A_rx_handler_t) 0),
TheChrisyd 0:17cb4be1e37f 55 _rx_handler_arg((void *) 0),
TheChrisyd 5:18ce8a56b248 56 _dr1_isr(InterruptIn(dr1)) {
TheChrisyd 9:7245524e37e4 57
TheChrisyd 0:17cb4be1e37f 58 // init member variables
TheChrisyd 0:17cb4be1e37f 59 _data.output();
TheChrisyd 9:7245524e37e4 60 // set defaults
TheChrisyd 9:7245524e37e4 61 _ctrl_packet_buf.crc_config = NO_CRC;
TheChrisyd 9:7245524e37e4 62 _ctrl_packet_buf.rf_data_rate = BIT_RATE_250KBITS;
TheChrisyd 9:7245524e37e4 63 _ctrl_packet_buf.rf_channel = 0x02;
TheChrisyd 9:7245524e37e4 64 _ctrl_packet_buf.channel_1_data_payload_len = 0x20;
TheChrisyd 0:17cb4be1e37f 65 // setup...
TheChrisyd 0:17cb4be1e37f 66 _ctrl_packet = (uint8_t *) &_ctrl_packet_buf;
TheChrisyd 0:17cb4be1e37f 67 _dr1_isr.rise(this, &nRF2401A::dataReadyHandler);
TheChrisyd 1:8c57f88ff574 68 // ...tranceiver in standby...
TheChrisyd 0:17cb4be1e37f 69 _ce = 0;
TheChrisyd 0:17cb4be1e37f 70 _cs = 0;
TheChrisyd 0:17cb4be1e37f 71 // ...and clear receive buffer
TheChrisyd 0:17cb4be1e37f 72 for (int i = 0; i < 16; i++)
TheChrisyd 0:17cb4be1e37f 73 _data_buf[i] = 0x0;
TheChrisyd 0:17cb4be1e37f 74 // ...set imutable control fields...
TheChrisyd 0:17cb4be1e37f 75 _ctrl_packet_buf.enable_dual_channel_mode = 0x0; // single channel receive
TheChrisyd 0:17cb4be1e37f 76 _ctrl_packet_buf.communication_mode = 0x1; // ShockBurst mode
TheChrisyd 0:17cb4be1e37f 77 _ctrl_packet_buf.xo_frequency = 0x3; // 16 MHz crystal
TheChrisyd 0:17cb4be1e37f 78 _ctrl_packet_buf.rf_power = 0x3; // 0 dBm (1 mW) output power
TheChrisyd 0:17cb4be1e37f 79 // ...start in RX mode
TheChrisyd 0:17cb4be1e37f 80 _ctrl_packet_buf.txr_switch = nRF2401A::RX_MODE;
TheChrisyd 7:22f69cf045d9 81 _state = nRF2401A::RX ;
TheChrisyd 1:8c57f88ff574 82 // assure minimum wake up time while assuming tranceiver powers up with uP
TheChrisyd 0:17cb4be1e37f 83 wait_ms(Tpd2cfgm);
TheChrisyd 0:17cb4be1e37f 84
TheChrisyd 0:17cb4be1e37f 85 return;
TheChrisyd 0:17cb4be1e37f 86 }
TheChrisyd 0:17cb4be1e37f 87
TheChrisyd 9:7245524e37e4 88 /* Public functions */
TheChrisyd 7:22f69cf045d9 89
TheChrisyd 9:7245524e37e4 90 /* Print control packet
TheChrisyd 9:7245524e37e4 91 * Print the control packet to a serial port
TheChrisyd 9:7245524e37e4 92 * @param arg Pointer to the port to transmit on
TheChrisyd 9:7245524e37e4 93 * @return bool for correct parameters supplied
TheChrisyd 9:7245524e37e4 94 */
TheChrisyd 9:7245524e37e4 95 bool nRF2401A::printControlPacket(Serial& port)
TheChrisyd 0:17cb4be1e37f 96 {
TheChrisyd 9:7245524e37e4 97 bool ok = false;
TheChrisyd 9:7245524e37e4 98 if (port != NULL)
TheChrisyd 9:7245524e37e4 99 {
TheChrisyd 9:7245524e37e4 100 for(int i = 0; i < sizeof(_ctrl_packet_buf); i++)
TheChrisyd 9:7245524e37e4 101 {
TheChrisyd 9:7245524e37e4 102 port.printf("%02x ", _ctrl_packet[i]);
TheChrisyd 9:7245524e37e4 103 }
TheChrisyd 9:7245524e37e4 104 port.printf("\n\r");
TheChrisyd 9:7245524e37e4 105 ok = true;
TheChrisyd 9:7245524e37e4 106 }
TheChrisyd 9:7245524e37e4 107 return ok;
TheChrisyd 0:17cb4be1e37f 108 }
TheChrisyd 0:17cb4be1e37f 109
TheChrisyd 9:7245524e37e4 110 /* Print data packet
TheChrisyd 9:7245524e37e4 111 * Print the data packet to a serial port
TheChrisyd 9:7245524e37e4 112 * @param arg Pointer to the port to transmit on
TheChrisyd 9:7245524e37e4 113 * @return bool for correct parameters supplied
TheChrisyd 9:7245524e37e4 114 */
TheChrisyd 9:7245524e37e4 115 bool nRF2401A::printDataPacket(Serial& port)
TheChrisyd 0:17cb4be1e37f 116 {
TheChrisyd 9:7245524e37e4 117 bool ok = false;
TheChrisyd 9:7245524e37e4 118 if (port != NULL)
TheChrisyd 9:7245524e37e4 119 {
TheChrisyd 9:7245524e37e4 120 for(int i = 0; i < sizeof(_data_buf); i++)
TheChrisyd 9:7245524e37e4 121 {
TheChrisyd 9:7245524e37e4 122 port.printf("%02x ", _data_buf[i]);
TheChrisyd 9:7245524e37e4 123 }
TheChrisyd 9:7245524e37e4 124 port.printf("\r");
TheChrisyd 9:7245524e37e4 125 ok = true;
TheChrisyd 9:7245524e37e4 126 }
TheChrisyd 9:7245524e37e4 127 return ok;
TheChrisyd 0:17cb4be1e37f 128 }
TheChrisyd 0:17cb4be1e37f 129
TheChrisyd 9:7245524e37e4 130 /* Send the control packet to the nRF2401A.
TheChrisyd 9:7245524e37e4 131 * This function transfer the control packet image to the nRF2401A.
TheChrisyd 9:7245524e37e4 132 * @return bool for successfull flushing of the packet
TheChrisyd 9:7245524e37e4 133 */
TheChrisyd 9:7245524e37e4 134 bool nRF2401A::flushControlPacket() {
TheChrisyd 9:7245524e37e4 135 bool flush = false;
TheChrisyd 7:22f69cf045d9 136 switch (_state) {
TheChrisyd 7:22f69cf045d9 137 case nRF2401A::RX:
TheChrisyd 7:22f69cf045d9 138 pushCtrl(_ctrl_packet, 15 << 3 );
TheChrisyd 7:22f69cf045d9 139 _state = nRF2401A::RX;
TheChrisyd 7:22f69cf045d9 140 _ce = 1;
TheChrisyd 7:22f69cf045d9 141 _cs = 0;
TheChrisyd 9:7245524e37e4 142 flush = true;
TheChrisyd 7:22f69cf045d9 143 break;
TheChrisyd 7:22f69cf045d9 144 case nRF2401A::STANDBY:
TheChrisyd 7:22f69cf045d9 145 pushCtrl(_ctrl_packet, 15 << 3 );
TheChrisyd 7:22f69cf045d9 146 _state = nRF2401A::STANDBY;
TheChrisyd 7:22f69cf045d9 147 _ce = 0;
TheChrisyd 7:22f69cf045d9 148 _cs = 0;
TheChrisyd 9:7245524e37e4 149 flush = true;
TheChrisyd 7:22f69cf045d9 150 break;
TheChrisyd 7:22f69cf045d9 151 case nRF2401A::TX:
TheChrisyd 7:22f69cf045d9 152 default:
TheChrisyd 7:22f69cf045d9 153 _ce = 0;
TheChrisyd 7:22f69cf045d9 154 _cs = 0;
TheChrisyd 7:22f69cf045d9 155 }
TheChrisyd 9:7245524e37e4 156 return flush;
TheChrisyd 7:22f69cf045d9 157 }
TheChrisyd 7:22f69cf045d9 158
TheChrisyd 9:7245524e37e4 159 /* Register a receive action callback.
TheChrisyd 9:7245524e37e4 160 * Attach a callback that will be called when the tranceiver intercept a
TheChrisyd 9:7245524e37e4 161 * message. This callback will be called in the context of an interrupt
TheChrisyd 9:7245524e37e4 162 * routine and should act accordingly.
TheChrisyd 9:7245524e37e4 163 * @param handler The callback, of type nRF2401_rx_handler_t.
TheChrisyd 9:7245524e37e4 164 * @param arg Pointer to data supplied to the handler at call time.
TheChrisyd 9:7245524e37e4 165 * @return Reference to the invoked object (for chaining operations).
TheChrisyd 9:7245524e37e4 166 */
TheChrisyd 9:7245524e37e4 167 bool nRF2401A::attachRXHandler(nRF2401A_rx_handler_t handler, void *arg)
TheChrisyd 4:e8523ef6e472 168 {
TheChrisyd 9:7245524e37e4 169 bool ok = false;
TheChrisyd 9:7245524e37e4 170 if (handler != NULL)
TheChrisyd 9:7245524e37e4 171 {
TheChrisyd 9:7245524e37e4 172 _rx_handler = handler;
TheChrisyd 9:7245524e37e4 173 _rx_handler_arg = arg;
TheChrisyd 9:7245524e37e4 174 ok = true;
TheChrisyd 9:7245524e37e4 175 }
TheChrisyd 9:7245524e37e4 176 return ok;
TheChrisyd 0:17cb4be1e37f 177 }
TheChrisyd 0:17cb4be1e37f 178
TheChrisyd 9:7245524e37e4 179 /* Set the payload length, in bits.
TheChrisyd 9:7245524e37e4 180 * Set the control packet field for length, in number of bits, of the message payload.
TheChrisyd 9:7245524e37e4 181 * @param n Number of bits of the message payload.
TheChrisyd 9:7245524e37e4 182 * @return void
TheChrisyd 9:7245524e37e4 183 */
TheChrisyd 9:7245524e37e4 184 void nRF2401A::setDataPayloadLength(uint8_t n)
TheChrisyd 9:7245524e37e4 185 {
TheChrisyd 9:7245524e37e4 186 _ctrl_packet_buf.channel_1_data_payload_len = n;
TheChrisyd 9:7245524e37e4 187 }
TheChrisyd 9:7245524e37e4 188
TheChrisyd 9:7245524e37e4 189 /* Set the address of channel 1.
TheChrisyd 9:7245524e37e4 190 * The channel address is a up to 40 bit number identifying the tranceiver.
TheChrisyd 9:7245524e37e4 191 * @param addr4 Bits 39-32 of the address.
TheChrisyd 9:7245524e37e4 192 * @param addr4 Bits 31-24 of the address.
TheChrisyd 9:7245524e37e4 193 * @param addr4 Bits 23-16 of the address.
TheChrisyd 9:7245524e37e4 194 * @param addr4 Bits 15-8 of the address.
TheChrisyd 9:7245524e37e4 195 * @param addr4 Bits 7-0 of the address.
TheChrisyd 9:7245524e37e4 196 * @param n_bits Number of bits used in the address.
TheChrisyd 9:7245524e37e4 197 * @return bool for correct settings supplied
TheChrisyd 9:7245524e37e4 198 */
TheChrisyd 9:7245524e37e4 199 bool nRF2401A::setAddress(uint8_t addr4, uint8_t addr3, uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t n_bits)
TheChrisyd 9:7245524e37e4 200 {
TheChrisyd 9:7245524e37e4 201 bool ok = false;
TheChrisyd 9:7245524e37e4 202 if (n_bits <= MAXIMUM_ADDR_LENGTH)
TheChrisyd 5:18ce8a56b248 203 {
TheChrisyd 9:7245524e37e4 204 _ctrl_packet_buf.channel_1_address[0] = addr4;
TheChrisyd 9:7245524e37e4 205 _ctrl_packet_buf.channel_1_address[1] = addr3;
TheChrisyd 9:7245524e37e4 206 _ctrl_packet_buf.channel_1_address[2] = addr2;
TheChrisyd 9:7245524e37e4 207 _ctrl_packet_buf.channel_1_address[3] = addr1;
TheChrisyd 9:7245524e37e4 208 _ctrl_packet_buf.channel_1_address[4] = addr0;
TheChrisyd 9:7245524e37e4 209 _ctrl_packet_buf.channel_address_len = n_bits;
TheChrisyd 9:7245524e37e4 210 ok = true;
TheChrisyd 5:18ce8a56b248 211 }
TheChrisyd 9:7245524e37e4 212 return ok;
TheChrisyd 5:18ce8a56b248 213 }
TheChrisyd 5:18ce8a56b248 214
TheChrisyd 9:7245524e37e4 215 /* Set CRC use.
TheChrisyd 9:7245524e37e4 216 * Set the CRC mode field of the control packet. Defaults to no CRC.
TheChrisyd 9:7245524e37e4 217 * @param mode The CRC mode of choise.
TheChrisyd 9:7245524e37e4 218 * @return bool for correct parameter supplied
TheChrisyd 9:7245524e37e4 219 */
TheChrisyd 9:7245524e37e4 220 bool nRF2401A::setCRCMode(CRC_T mode)
TheChrisyd 9:7245524e37e4 221 {
TheChrisyd 9:7245524e37e4 222 bool ok = false;
TheChrisyd 9:7245524e37e4 223 if (mode < INVALID_CRC)
TheChrisyd 9:7245524e37e4 224 {
TheChrisyd 9:7245524e37e4 225 _ctrl_packet_buf.crc_config = mode;
TheChrisyd 9:7245524e37e4 226 ok = true;
TheChrisyd 9:7245524e37e4 227 }
TheChrisyd 9:7245524e37e4 228 return ok;
TheChrisyd 5:18ce8a56b248 229 }
TheChrisyd 5:18ce8a56b248 230
TheChrisyd 9:7245524e37e4 231 /* Set RF power use.
TheChrisyd 9:7245524e37e4 232 * Set the RF power field of the control packet. Defaults to full power.
TheChrisyd 9:7245524e37e4 233 * @param power The RF power of choise.
TheChrisyd 9:7245524e37e4 234 * @return bool for correct parameter supplied
TheChrisyd 9:7245524e37e4 235 */
TheChrisyd 9:7245524e37e4 236 bool nRF2401A::setRFpower(RF_POWER_T power)
TheChrisyd 9:7245524e37e4 237 {
TheChrisyd 9:7245524e37e4 238 bool ok = false;
TheChrisyd 9:7245524e37e4 239 if (power < INVALID_POWER)
TheChrisyd 9:7245524e37e4 240 {
TheChrisyd 9:7245524e37e4 241 _ctrl_packet_buf.rf_power = power;
TheChrisyd 9:7245524e37e4 242 ok = true;
TheChrisyd 9:7245524e37e4 243 }
TheChrisyd 9:7245524e37e4 244 return ok;
TheChrisyd 9:7245524e37e4 245 }
TheChrisyd 9:7245524e37e4 246
TheChrisyd 9:7245524e37e4 247 /* Set tranceiver data rate.
TheChrisyd 9:7245524e37e4 248 * Sets the data rate field to either 250 kbit/s or 1 Mbit/s data transfer rate.
TheChrisyd 9:7245524e37e4 249 * Defaults to 250 kbit/s.
TheChrisyd 9:7245524e37e4 250 * @param mode The data rate of choise.
TheChrisyd 9:7245524e37e4 251 * @return bool for correct parameter supplied
TheChrisyd 9:7245524e37e4 252 */
TheChrisyd 9:7245524e37e4 253 bool nRF2401A::setDataRate(DATA_RATE_T data_rate)
TheChrisyd 9:7245524e37e4 254 {
TheChrisyd 9:7245524e37e4 255 bool ok = false;
TheChrisyd 9:7245524e37e4 256 if ( data_rate < INVALID_RATE)
TheChrisyd 9:7245524e37e4 257 {
TheChrisyd 9:7245524e37e4 258 _ctrl_packet_buf.rf_data_rate = data_rate;
TheChrisyd 9:7245524e37e4 259 ok = true;
TheChrisyd 9:7245524e37e4 260 }
TheChrisyd 9:7245524e37e4 261 return ok;
TheChrisyd 9:7245524e37e4 262 }
TheChrisyd 9:7245524e37e4 263
TheChrisyd 9:7245524e37e4 264 /** Set RF channel.
TheChrisyd 9:7245524e37e4 265 * Sets the control packet field for channel number. Channel numbers are from 0 to 127
TheChrisyd 9:7245524e37e4 266 * representing channel frequencies equal to (2400 + channel number) MHz. Defaults to channel 1.
TheChrisyd 9:7245524e37e4 267 * @param ch Channel number, from the range [0, 127].
TheChrisyd 9:7245524e37e4 268 * @return boolean to confirm valid parameters have been supplied
TheChrisyd 9:7245524e37e4 269 */
TheChrisyd 9:7245524e37e4 270 bool nRF2401A::setChannel(uint8_t ch)
TheChrisyd 9:7245524e37e4 271 {
TheChrisyd 9:7245524e37e4 272 bool result = false;
TheChrisyd 9:7245524e37e4 273 if (ch < 128)
TheChrisyd 9:7245524e37e4 274 {
TheChrisyd 9:7245524e37e4 275 _ctrl_packet_buf.rf_channel = ch;
TheChrisyd 9:7245524e37e4 276 result = true;
TheChrisyd 9:7245524e37e4 277 }
TheChrisyd 9:7245524e37e4 278 return result;
TheChrisyd 9:7245524e37e4 279 }
TheChrisyd 0:17cb4be1e37f 280
TheChrisyd 9:7245524e37e4 281 /* Read a message.
TheChrisyd 9:7245524e37e4 282 * This routine will transfer the data from the receive buffer to the buffer
TheChrisyd 9:7245524e37e4 283 * supplied. It will transfer a number of Bytes equal to the specified length.
TheChrisyd 9:7245524e37e4 284 * @param msg_buf Message buffer.
TheChrisyd 9:7245524e37e4 285 * @param msg_len Length of message, in bytes.
TheChrisyd 9:7245524e37e4 286 * @return boolean to confirm if valid parameters have been supplied
TheChrisyd 9:7245524e37e4 287 */
TheChrisyd 9:7245524e37e4 288 bool nRF2401A::readMsg( uint8_t *msg_buf, uint8_t msg_len ) {
TheChrisyd 9:7245524e37e4 289 bool result = false;
TheChrisyd 9:7245524e37e4 290 if ((msg_buf != NULL) && (msg_len <= DATA_BUFFER_SIZE))
TheChrisyd 9:7245524e37e4 291 {
TheChrisyd 9:7245524e37e4 292 for(int i = 0; i < msg_len; i++)
TheChrisyd 9:7245524e37e4 293 {
TheChrisyd 9:7245524e37e4 294 msg_buf[i] = _data_buf[i];
TheChrisyd 9:7245524e37e4 295 }
TheChrisyd 9:7245524e37e4 296 result = true;
TheChrisyd 9:7245524e37e4 297 }
TheChrisyd 9:7245524e37e4 298 return result;
TheChrisyd 9:7245524e37e4 299 }
TheChrisyd 9:7245524e37e4 300
TheChrisyd 9:7245524e37e4 301 /* Read a byte from message.
TheChrisyd 9:7245524e37e4 302 * This routine will transfer the data from the receive buffer to the buffer
TheChrisyd 9:7245524e37e4 303 * supplied. It will transfer one Bytes at index buf_index.
TheChrisyd 9:7245524e37e4 304 * @param msg_buf Message body.
TheChrisyd 9:7245524e37e4 305 * @param buf_index index of byte to be read.
TheChrisyd 9:7245524e37e4 306 * @return one Byte of the message buffer
TheChrisyd 9:7245524e37e4 307 */
TheChrisyd 9:7245524e37e4 308 uint8_t nRF2401A::readMsg_byte( uint8_t buf_index ) {
TheChrisyd 9:7245524e37e4 309 return _data_buf[buf_index];
TheChrisyd 9:7245524e37e4 310 }
TheChrisyd 0:17cb4be1e37f 311
TheChrisyd 9:7245524e37e4 312 /** Send a message.
TheChrisyd 9:7245524e37e4 313 * This routine will transfer the data from the supplied buffer and send
TheChrisyd 9:7245524e37e4 314 * it to the specified address using the current control packet settings.
TheChrisyd 9:7245524e37e4 315 * @param addr The address to send to.
TheChrisyd 9:7245524e37e4 316 * @param addr_len Length of address, in bits.
TheChrisyd 9:7245524e37e4 317 * @param msg_buf Message body.
TheChrisyd 9:7245524e37e4 318 * @param msg_len Length of message, in bits.
TheChrisyd 9:7245524e37e4 319 * @return Reference to the invoked object (for chaining operations).
TheChrisyd 9:7245524e37e4 320 */
TheChrisyd 9:7245524e37e4 321 bool nRF2401A::sendMsg(nRF2401A::address_t addr, uint8_t addr_len, uint8_t *msg_buf, uint8_t msg_len) {
TheChrisyd 9:7245524e37e4 322 bool sent = false;
TheChrisyd 9:7245524e37e4 323 if ((msg_buf != NULL) && (addr_len <= MAXIMUM_ADDR_LENGTH))
TheChrisyd 9:7245524e37e4 324 {
TheChrisyd 9:7245524e37e4 325 // point to start of address byte in address
TheChrisyd 9:7245524e37e4 326 uint8_t *aligned_addr = &addr[sizeof(address_t) - (addr_len / 8)];
TheChrisyd 9:7245524e37e4 327 // wait for tx completion
TheChrisyd 9:7245524e37e4 328 int Toa = (_ctrl_packet_buf.rf_data_rate == nRF2401A::BIT_RATE_1MBITS ? 1 : 4) * (addr_len + msg_len + 1 + 16);
TheChrisyd 9:7245524e37e4 329
TheChrisyd 9:7245524e37e4 330 switch (_state) {
TheChrisyd 9:7245524e37e4 331 case nRF2401A::STANDBY:
TheChrisyd 9:7245524e37e4 332 //come out of standby into RX mode
TheChrisyd 9:7245524e37e4 333 standby_mode(true);
TheChrisyd 9:7245524e37e4 334 case nRF2401A::TX:
TheChrisyd 9:7245524e37e4 335 //wait while in tx mode
TheChrisyd 9:7245524e37e4 336 while (_state == nRF2401A::TX ) {
TheChrisyd 9:7245524e37e4 337 }
TheChrisyd 9:7245524e37e4 338 case nRF2401A::RX:
TheChrisyd 9:7245524e37e4 339 // switch to transmit
TheChrisyd 9:7245524e37e4 340 transmit_mode();
TheChrisyd 9:7245524e37e4 341 // push out the bits
TheChrisyd 9:7245524e37e4 342 _data = nRF2401A::TX_MODE;
TheChrisyd 0:17cb4be1e37f 343 wait_us(Ts);
TheChrisyd 0:17cb4be1e37f 344 _clk1 = 1;
TheChrisyd 0:17cb4be1e37f 345 wait_us(Th);
TheChrisyd 0:17cb4be1e37f 346 _clk1 = 0;
TheChrisyd 9:7245524e37e4 347 // wait Td
TheChrisyd 9:7245524e37e4 348 wait_us(Td);
TheChrisyd 9:7245524e37e4 349 // deassert CS/CE and done...
TheChrisyd 9:7245524e37e4 350 _cs = 0;
TheChrisyd 9:7245524e37e4 351 _ce = 0;
TheChrisyd 9:7245524e37e4 352
TheChrisyd 9:7245524e37e4 353 // zero control and data lines
TheChrisyd 0:17cb4be1e37f 354 _clk1 = 0;
TheChrisyd 9:7245524e37e4 355 _data = 0;
TheChrisyd 9:7245524e37e4 356 // wait Td
TheChrisyd 9:7245524e37e4 357 wait_us(Td);
TheChrisyd 9:7245524e37e4 358 // assert CE and wait Tcs2data
TheChrisyd 9:7245524e37e4 359 _ce = 1;
TheChrisyd 9:7245524e37e4 360 wait_us(Tce2data);
TheChrisyd 9:7245524e37e4 361 // push out the address bits
TheChrisyd 9:7245524e37e4 362 for (int i = 0; i < addr_len; i++) {
TheChrisyd 9:7245524e37e4 363 _data = ((0x80 >> (i % 8)) & aligned_addr[i / 8]) ? 0x1 : 0x0;
TheChrisyd 9:7245524e37e4 364 wait_us(Ts);
TheChrisyd 9:7245524e37e4 365 _clk1 = 1;
TheChrisyd 9:7245524e37e4 366 wait_us(Th);
TheChrisyd 9:7245524e37e4 367 _clk1 = 0;
TheChrisyd 9:7245524e37e4 368 }
TheChrisyd 9:7245524e37e4 369 // push out the message bits
TheChrisyd 9:7245524e37e4 370 for (int i = 0; i < msg_len; i++) {
TheChrisyd 9:7245524e37e4 371 _data = ((0x80 >> (i % 8)) & msg_buf[i / 8]) ? 0x1 : 0x0;
TheChrisyd 9:7245524e37e4 372 wait_us(Ts);
TheChrisyd 9:7245524e37e4 373 _clk1 = 1;
TheChrisyd 9:7245524e37e4 374 wait_us(Th);
TheChrisyd 9:7245524e37e4 375 _clk1 = 0;
TheChrisyd 9:7245524e37e4 376 }
TheChrisyd 9:7245524e37e4 377 // reset data
TheChrisyd 9:7245524e37e4 378 _data = 0;
TheChrisyd 9:7245524e37e4 379 // deassert CE will initiate transmission
TheChrisyd 9:7245524e37e4 380 _ce = 0;
TheChrisyd 9:7245524e37e4 381 wait_us(Tsby2txSB + Toa);
TheChrisyd 0:17cb4be1e37f 382
TheChrisyd 9:7245524e37e4 383 // switch back to receive
TheChrisyd 9:7245524e37e4 384 receive_mode();
TheChrisyd 9:7245524e37e4 385 sent = true;
TheChrisyd 9:7245524e37e4 386 break;
TheChrisyd 9:7245524e37e4 387 }
TheChrisyd 7:22f69cf045d9 388 }
TheChrisyd 9:7245524e37e4 389 return sent;
TheChrisyd 7:22f69cf045d9 390 }
TheChrisyd 7:22f69cf045d9 391
TheChrisyd 7:22f69cf045d9 392
TheChrisyd 9:7245524e37e4 393 /* Put the tranceiver into, or bring out of standby.
TheChrisyd 9:7245524e37e4 394 * Tx mode 10.5mA, RX mode 18mA, Standby 400nA.
TheChrisyd 9:7245524e37e4 395 * @param active set standby state
TheChrisyd 9:7245524e37e4 396 */
TheChrisyd 9:7245524e37e4 397 nRF2401A::STATE_T nRF2401A::standby_mode(bool active) {
TheChrisyd 7:22f69cf045d9 398 switch (_state) {
TheChrisyd 7:22f69cf045d9 399 case nRF2401A::TX:
TheChrisyd 7:22f69cf045d9 400 //wait while in tx mode
TheChrisyd 7:22f69cf045d9 401 while (_state == nRF2401A::TX ) {
TheChrisyd 7:22f69cf045d9 402 }
TheChrisyd 7:22f69cf045d9 403 case nRF2401A::RX:
TheChrisyd 7:22f69cf045d9 404 if (!active) {
TheChrisyd 7:22f69cf045d9 405 _state = nRF2401A::STANDBY;
TheChrisyd 7:22f69cf045d9 406 _ce = 0;
TheChrisyd 7:22f69cf045d9 407 _cs = 0;
TheChrisyd 9:7245524e37e4 408 wait_us(Tsby2rx);
TheChrisyd 7:22f69cf045d9 409 }
TheChrisyd 0:17cb4be1e37f 410 break;
TheChrisyd 0:17cb4be1e37f 411 case nRF2401A::STANDBY:
TheChrisyd 7:22f69cf045d9 412 if (active) {
TheChrisyd 7:22f69cf045d9 413 _state = nRF2401A::RX;
TheChrisyd 7:22f69cf045d9 414 _ce = 1;
TheChrisyd 7:22f69cf045d9 415 _cs = 0;
TheChrisyd 7:22f69cf045d9 416 }
TheChrisyd 0:17cb4be1e37f 417 break;
TheChrisyd 0:17cb4be1e37f 418 }
TheChrisyd 9:7245524e37e4 419 return _state;
TheChrisyd 7:22f69cf045d9 420 }
TheChrisyd 0:17cb4be1e37f 421
TheChrisyd 9:7245524e37e4 422 /* Private functions */
TheChrisyd 7:22f69cf045d9 423
TheChrisyd 9:7245524e37e4 424 /* transmit_mode
TheChrisyd 9:7245524e37e4 425 *
TheChrisyd 9:7245524e37e4 426 * put the transceiver into transmit mode
TheChrisyd 9:7245524e37e4 427 */
TheChrisyd 7:22f69cf045d9 428 void nRF2401A::transmit_mode( void ) {
TheChrisyd 7:22f69cf045d9 429 _ce = 0;
TheChrisyd 7:22f69cf045d9 430 _cs = 0;
TheChrisyd 7:22f69cf045d9 431 wait_us(Td);
TheChrisyd 7:22f69cf045d9 432 // assert CS/CE and wait Tcs2data
TheChrisyd 7:22f69cf045d9 433 _ce = 0;
TheChrisyd 7:22f69cf045d9 434 _cs = 1;
TheChrisyd 7:22f69cf045d9 435 wait_us(Tcs2data);
TheChrisyd 7:22f69cf045d9 436 _state = nRF2401A::TX;
TheChrisyd 7:22f69cf045d9 437 }
TheChrisyd 7:22f69cf045d9 438
TheChrisyd 9:7245524e37e4 439 /* receive_mode
TheChrisyd 9:7245524e37e4 440 *
TheChrisyd 9:7245524e37e4 441 * put the transceiver into receive mode
TheChrisyd 9:7245524e37e4 442 */
TheChrisyd 7:22f69cf045d9 443 void nRF2401A::receive_mode( void ) {
TheChrisyd 7:22f69cf045d9 444 wait_us(Td);
TheChrisyd 7:22f69cf045d9 445 // assert CS/CE and wait Tcs2data
TheChrisyd 7:22f69cf045d9 446 _cs = 1;
TheChrisyd 7:22f69cf045d9 447 wait_us(Tcs2data);
TheChrisyd 7:22f69cf045d9 448 // push out the bits
TheChrisyd 7:22f69cf045d9 449 _data = nRF2401A::RX_MODE;
TheChrisyd 7:22f69cf045d9 450 wait_us(Ts);
TheChrisyd 7:22f69cf045d9 451 _clk1 = 1;
TheChrisyd 7:22f69cf045d9 452 wait_us(Th);
TheChrisyd 7:22f69cf045d9 453 _clk1 = 0;
TheChrisyd 7:22f69cf045d9 454 // wait Td
TheChrisyd 7:22f69cf045d9 455 wait_us(Td);
TheChrisyd 7:22f69cf045d9 456 _data = 0;
TheChrisyd 7:22f69cf045d9 457 // deassert CS/CE and done...
TheChrisyd 7:22f69cf045d9 458 _cs = 0;
TheChrisyd 7:22f69cf045d9 459 // wait Td to avoid simultaineous control high
TheChrisyd 7:22f69cf045d9 460 wait_us(Td);
TheChrisyd 7:22f69cf045d9 461 _ce = 1;
TheChrisyd 7:22f69cf045d9 462 // done
TheChrisyd 7:22f69cf045d9 463 _state = nRF2401A::RX;
TheChrisyd 7:22f69cf045d9 464 }
TheChrisyd 7:22f69cf045d9 465
TheChrisyd 9:7245524e37e4 466 /* dataReadyHandler
TheChrisyd 9:7245524e37e4 467 *
TheChrisyd 9:7245524e37e4 468 * handle the incoming data and call callback
TheChrisyd 9:7245524e37e4 469 */
TheChrisyd 7:22f69cf045d9 470 void nRF2401A::dataReadyHandler(void) {
TheChrisyd 7:22f69cf045d9 471 switch (_state) {
TheChrisyd 7:22f69cf045d9 472 case nRF2401A::RX:
TheChrisyd 7:22f69cf045d9 473 pull(_data_buf);
TheChrisyd 7:22f69cf045d9 474 if (_rx_handler != (nRF2401A_rx_handler_t) 0)
TheChrisyd 7:22f69cf045d9 475 _rx_handler(_rx_handler_arg);
TheChrisyd 7:22f69cf045d9 476 break;
TheChrisyd 7:22f69cf045d9 477 default:
TheChrisyd 7:22f69cf045d9 478 // todo: error msg
TheChrisyd 7:22f69cf045d9 479 break;
TheChrisyd 7:22f69cf045d9 480 }
TheChrisyd 7:22f69cf045d9 481 return;
TheChrisyd 7:22f69cf045d9 482 }
TheChrisyd 7:22f69cf045d9 483
TheChrisyd 9:7245524e37e4 484 /* pull
TheChrisyd 9:7245524e37e4 485 *
TheChrisyd 9:7245524e37e4 486 * Pull the data from the transceiver
TheChrisyd 9:7245524e37e4 487 */
TheChrisyd 7:22f69cf045d9 488 int nRF2401A::pull(uint8_t *buf) {
TheChrisyd 7:22f69cf045d9 489 int n = 0;
TheChrisyd 7:22f69cf045d9 490
TheChrisyd 7:22f69cf045d9 491 // read from data pin
TheChrisyd 7:22f69cf045d9 492 _data.input();
TheChrisyd 7:22f69cf045d9 493 // init signals, go to standby
TheChrisyd 7:22f69cf045d9 494 _ce = 1;
TheChrisyd 7:22f69cf045d9 495 _cs = 0;
TheChrisyd 7:22f69cf045d9 496 _clk1 = 0;
TheChrisyd 7:22f69cf045d9 497 // ensure time from DR
TheChrisyd 7:22f69cf045d9 498 wait_us(Td);
TheChrisyd 7:22f69cf045d9 499
TheChrisyd 7:22f69cf045d9 500 while (_dr1 == 1) {
TheChrisyd 7:22f69cf045d9 501 _clk1 = 1;
TheChrisyd 7:22f69cf045d9 502 wait_us(Thmin);
TheChrisyd 7:22f69cf045d9 503 if(_data.read())
TheChrisyd 7:22f69cf045d9 504 buf[n / 8] |= (0x80 >> (n % 8));
TheChrisyd 7:22f69cf045d9 505 else
TheChrisyd 7:22f69cf045d9 506 buf[n / 8] &= ~(0x80 >> (n % 8));
TheChrisyd 7:22f69cf045d9 507 n++;
TheChrisyd 7:22f69cf045d9 508 _clk1 = 0;
TheChrisyd 7:22f69cf045d9 509 wait_us(Thmin);
TheChrisyd 7:22f69cf045d9 510 }
TheChrisyd 7:22f69cf045d9 511 // return to active
TheChrisyd 7:22f69cf045d9 512 _ce = 1;
TheChrisyd 7:22f69cf045d9 513 // reset data pin direction
TheChrisyd 7:22f69cf045d9 514 _data.output();
TheChrisyd 7:22f69cf045d9 515
TheChrisyd 7:22f69cf045d9 516 return n;
TheChrisyd 0:17cb4be1e37f 517 }
TheChrisyd 0:17cb4be1e37f 518
TheChrisyd 9:7245524e37e4 519 /* pushCtrl
TheChrisyd 9:7245524e37e4 520 *
TheChrisyd 9:7245524e37e4 521 * Push the data to the transceiver
TheChrisyd 9:7245524e37e4 522 */
TheChrisyd 0:17cb4be1e37f 523 void nRF2401A::pushCtrl(uint8_t *buf, uint8_t n_bits, bool is_ctrl) {
TheChrisyd 0:17cb4be1e37f 524
TheChrisyd 0:17cb4be1e37f 525 DigitalOut &ctrl_pin = is_ctrl ? _cs : _ce;
TheChrisyd 0:17cb4be1e37f 526
TheChrisyd 0:17cb4be1e37f 527 // set data to output
TheChrisyd 0:17cb4be1e37f 528 _data.output();
TheChrisyd 0:17cb4be1e37f 529 // zero control and data lines
TheChrisyd 0:17cb4be1e37f 530 _cs = 0;
TheChrisyd 0:17cb4be1e37f 531 _ce = 0;
TheChrisyd 0:17cb4be1e37f 532 _clk1 = 0;
TheChrisyd 0:17cb4be1e37f 533 _data = 0;
TheChrisyd 0:17cb4be1e37f 534 // wait Td
TheChrisyd 0:17cb4be1e37f 535 wait_us(Td);
TheChrisyd 0:17cb4be1e37f 536 // assert CS/CE and wait Tcs2data
TheChrisyd 0:17cb4be1e37f 537 ctrl_pin = 1;
TheChrisyd 0:17cb4be1e37f 538 wait_us(Tcs2data);
TheChrisyd 0:17cb4be1e37f 539 // push out the bits
TheChrisyd 0:17cb4be1e37f 540 for (int i = 0; i < n_bits; i++) {
TheChrisyd 0:17cb4be1e37f 541 _data = ((0x80 >> (i % 8)) & buf[i / 8]) ? 0x1 : 0x0;
TheChrisyd 0:17cb4be1e37f 542 wait_us(Ts);
TheChrisyd 0:17cb4be1e37f 543 _clk1 = 1;
TheChrisyd 0:17cb4be1e37f 544 wait_us(Th);
TheChrisyd 0:17cb4be1e37f 545 _clk1 = 0;
TheChrisyd 0:17cb4be1e37f 546 }
TheChrisyd 0:17cb4be1e37f 547 _data = 0;
TheChrisyd 0:17cb4be1e37f 548 // wait Td
TheChrisyd 0:17cb4be1e37f 549 wait_us(Td);
TheChrisyd 0:17cb4be1e37f 550 // deassert CS/CE and done...
TheChrisyd 0:17cb4be1e37f 551 ctrl_pin = 0;
TheChrisyd 0:17cb4be1e37f 552
TheChrisyd 0:17cb4be1e37f 553 return;
TheChrisyd 0:17cb4be1e37f 554 }