Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
nRF2401A.h@1:d40d911b763a, 2013-07-08 (annotated)
- Committer:
- persoder
- Date:
- Mon Jul 08 21:08:46 2013 +0000
- Revision:
- 1:d40d911b763a
- Parent:
- 0:3fe71769ad07
This one works...! The trick was not to switch to receive before the hole message is sent. Didn't/missed to include time on air for the (implicitly) added address bits!
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| persoder | 0:3fe71769ad07 | 1 | /** \file |
| persoder | 0:3fe71769ad07 | 2 | * \brief |
| persoder | 0:3fe71769ad07 | 3 | * |
| persoder | 1:d40d911b763a | 4 | * \author Per Söderstam © 2011, 2012 |
| persoder | 0:3fe71769ad07 | 5 | */ |
| persoder | 0:3fe71769ad07 | 6 | |
| persoder | 0:3fe71769ad07 | 7 | #include <mbed.h> |
| persoder | 0:3fe71769ad07 | 8 | #include <inttypes.h> |
| persoder | 0:3fe71769ad07 | 9 | |
| persoder | 1:d40d911b763a | 10 | /** ISR handler prototype for receiving messages. |
| persoder | 1:d40d911b763a | 11 | * A function of this type is registered and called when the DR pin on the |
| persoder | 1:d40d911b763a | 12 | * nRF tranciever signals the reception of a message. The void * argument |
| persoder | 1:d40d911b763a | 13 | * is likewise supplied when registering and is returned at call time. |
| persoder | 1:d40d911b763a | 14 | */ |
| persoder | 1:d40d911b763a | 15 | typedef void (*nRF2401A_rx_handler_t)(void *); |
| persoder | 1:d40d911b763a | 16 | |
| persoder | 0:3fe71769ad07 | 17 | /** |
| persoder | 0:3fe71769ad07 | 18 | * |
| persoder | 0:3fe71769ad07 | 19 | * |
| persoder | 0:3fe71769ad07 | 20 | */ |
| persoder | 0:3fe71769ad07 | 21 | class nRF2401A |
| persoder | 0:3fe71769ad07 | 22 | { |
| persoder | 0:3fe71769ad07 | 23 | public: |
| persoder | 1:d40d911b763a | 24 | /** Class constructor. |
| persoder | 1:d40d911b763a | 25 | * The constructor assigns the specified pinout, attatch the |
| persoder | 1:d40d911b763a | 26 | * DR1 to a pin interrupt and sets up inmutable control packet |
| persoder | 1:d40d911b763a | 27 | * fields. |
| persoder | 1:d40d911b763a | 28 | * \param ce Chip Enable (CE) pin of the nRF2401A. |
| persoder | 1:d40d911b763a | 29 | * \param c2 Chip Select (CS) pin of the nRF2401A. |
| persoder | 1:d40d911b763a | 30 | * \param dr1 Data Ready 1 (DR1) pin of the nRF2401A. |
| persoder | 1:d40d911b763a | 31 | * \param clk1 Clock 1 (CLK1) pin of the nRF2401A. |
| persoder | 1:d40d911b763a | 32 | * \param data Data (DATA) pin of the nRF2401A. |
| persoder | 0:3fe71769ad07 | 33 | */ |
| persoder | 0:3fe71769ad07 | 34 | nRF2401A(PinName ce, |
| persoder | 0:3fe71769ad07 | 35 | PinName cs, |
| persoder | 0:3fe71769ad07 | 36 | PinName dr1, |
| persoder | 0:3fe71769ad07 | 37 | PinName clk1, |
| persoder | 1:d40d911b763a | 38 | PinName data); |
| persoder | 1:d40d911b763a | 39 | |
| persoder | 1:d40d911b763a | 40 | /** Class destructor. |
| persoder | 1:d40d911b763a | 41 | * Pretty much useless in the embedded world... |
| persoder | 1:d40d911b763a | 42 | */ |
| persoder | 1:d40d911b763a | 43 | virtual ~nRF2401A() { return; } |
| persoder | 1:d40d911b763a | 44 | |
| persoder | 1:d40d911b763a | 45 | /** Set the payload length, in bits. |
| persoder | 1:d40d911b763a | 46 | * Set the control packet field for length, in number of bits, of the message payload. |
| persoder | 1:d40d911b763a | 47 | * \param n Number of bits of the message payload. |
| persoder | 1:d40d911b763a | 48 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 49 | */ |
| persoder | 1:d40d911b763a | 50 | nRF2401A& setDataPayloadLength(uint8_t n) |
| persoder | 1:d40d911b763a | 51 | { |
| persoder | 1:d40d911b763a | 52 | _ctrl_packet_buf.channel_1_data_payload_len = n; |
| persoder | 1:d40d911b763a | 53 | return *this; |
| persoder | 0:3fe71769ad07 | 54 | } |
| persoder | 0:3fe71769ad07 | 55 | |
| persoder | 1:d40d911b763a | 56 | /** Set the address of channel 1. |
| persoder | 1:d40d911b763a | 57 | * The channel address is a up to 40 bit number identifying the tranciever. |
| persoder | 1:d40d911b763a | 58 | * \param addr4 Bits 39-32 of the address. |
| persoder | 1:d40d911b763a | 59 | * \param addr4 Bits 31-24 of the address. |
| persoder | 1:d40d911b763a | 60 | * \param addr4 Bits 23-16 of the address. |
| persoder | 1:d40d911b763a | 61 | * \param addr4 Bits 15-8 of the address. |
| persoder | 1:d40d911b763a | 62 | * \param addr4 Bits 7-0 of the address. |
| persoder | 1:d40d911b763a | 63 | * \param n_bits Number of bits used in the address. |
| persoder | 1:d40d911b763a | 64 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 0:3fe71769ad07 | 65 | */ |
| persoder | 0:3fe71769ad07 | 66 | nRF2401A& setAddress(uint8_t addr4, uint8_t addr3, uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t n_bits) |
| persoder | 0:3fe71769ad07 | 67 | { |
| persoder | 0:3fe71769ad07 | 68 | _ctrl_packet_buf.channel_1_address[0] = addr4; |
| persoder | 0:3fe71769ad07 | 69 | _ctrl_packet_buf.channel_1_address[1] = addr3; |
| persoder | 0:3fe71769ad07 | 70 | _ctrl_packet_buf.channel_1_address[2] = addr2; |
| persoder | 0:3fe71769ad07 | 71 | _ctrl_packet_buf.channel_1_address[3] = addr1; |
| persoder | 0:3fe71769ad07 | 72 | _ctrl_packet_buf.channel_1_address[4] = addr0; |
| persoder | 0:3fe71769ad07 | 73 | _ctrl_packet_buf.channel_address_len = n_bits; |
| persoder | 0:3fe71769ad07 | 74 | |
| persoder | 0:3fe71769ad07 | 75 | return *this; |
| persoder | 0:3fe71769ad07 | 76 | } |
| persoder | 0:3fe71769ad07 | 77 | |
| persoder | 1:d40d911b763a | 78 | /** CRC settings. |
| persoder | 1:d40d911b763a | 79 | * Type covering the allowed settings for use of CRC. |
| persoder | 0:3fe71769ad07 | 80 | */ |
| persoder | 1:d40d911b763a | 81 | typedef enum |
| persoder | 1:d40d911b763a | 82 | { |
| persoder | 1:d40d911b763a | 83 | NO_CRC = 0x0, /**< Do not use CRC. */ |
| persoder | 1:d40d911b763a | 84 | CRC_8 = 0x1, /**< Use a 8-bit CRC. */ |
| persoder | 1:d40d911b763a | 85 | CRC_16 = 0x3 /**< Use a 16-bit CRC. */ |
| persoder | 1:d40d911b763a | 86 | } CRC_T; |
| persoder | 1:d40d911b763a | 87 | |
| persoder | 1:d40d911b763a | 88 | /** Set CRC use. |
| persoder | 1:d40d911b763a | 89 | * Set the CRC mode field of the control packet. |
| persoder | 1:d40d911b763a | 90 | * \param mode The CRC mode of choise. |
| persoder | 1:d40d911b763a | 91 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 92 | */ |
| persoder | 1:d40d911b763a | 93 | nRF2401A& setCRCMode(CRC_T mode) |
| persoder | 1:d40d911b763a | 94 | { |
| persoder | 1:d40d911b763a | 95 | _ctrl_packet_buf.crc_config = mode; |
| persoder | 1:d40d911b763a | 96 | return *this; |
| persoder | 1:d40d911b763a | 97 | } |
| persoder | 0:3fe71769ad07 | 98 | |
| persoder | 1:d40d911b763a | 99 | /** Data rate settings. |
| persoder | 1:d40d911b763a | 100 | * Type covering the allowed settings for the tranciever data rate. |
| persoder | 1:d40d911b763a | 101 | */ |
| persoder | 1:d40d911b763a | 102 | typedef enum |
| persoder | 1:d40d911b763a | 103 | { |
| persoder | 1:d40d911b763a | 104 | BIT_RATE_250KBITS = 0x0, /**< */ |
| persoder | 1:d40d911b763a | 105 | BIT_RATE_1MBITS = 0x1 /**< */ |
| persoder | 1:d40d911b763a | 106 | } DATA_RATE_T; |
| persoder | 1:d40d911b763a | 107 | |
| persoder | 1:d40d911b763a | 108 | /** Set tranciever data rate. |
| persoder | 1:d40d911b763a | 109 | * Sets the data rate field to either 250 kbit/s or 1 Mbit/s data transfer rate. |
| persoder | 1:d40d911b763a | 110 | * \param mode The data rate of choise. |
| persoder | 1:d40d911b763a | 111 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 0:3fe71769ad07 | 112 | */ |
| persoder | 1:d40d911b763a | 113 | nRF2401A& setDataRate(DATA_RATE_T data_rate) |
| persoder | 1:d40d911b763a | 114 | { |
| persoder | 1:d40d911b763a | 115 | _ctrl_packet_buf.rf_data_rate = data_rate; |
| persoder | 1:d40d911b763a | 116 | return *this; |
| persoder | 1:d40d911b763a | 117 | } |
| persoder | 1:d40d911b763a | 118 | |
| persoder | 1:d40d911b763a | 119 | /** Set RF channel. |
| persoder | 1:d40d911b763a | 120 | * Sets the control packet field for channel number. Channel numbers are from 0 to 127 |
| persoder | 1:d40d911b763a | 121 | * representing channel frequencies equal to (2400 + channel number) MHz. |
| persoder | 1:d40d911b763a | 122 | * \param ch Channel number, from the range [0, 127]. |
| persoder | 1:d40d911b763a | 123 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 124 | */ |
| persoder | 1:d40d911b763a | 125 | nRF2401A& setChannel(uint8_t ch) |
| persoder | 1:d40d911b763a | 126 | { |
| persoder | 1:d40d911b763a | 127 | _ctrl_packet_buf.rf_channel = ch; |
| persoder | 1:d40d911b763a | 128 | return *this; |
| persoder | 1:d40d911b763a | 129 | } |
| persoder | 1:d40d911b763a | 130 | |
| persoder | 1:d40d911b763a | 131 | /** Send the control packet to the nRF2401A. |
| persoder | 1:d40d911b763a | 132 | * This function transfer the control packet image to the nRF2401A. |
| persoder | 1:d40d911b763a | 133 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 134 | */ |
| persoder | 1:d40d911b763a | 135 | nRF2401A& flushControlPacket(); |
| persoder | 0:3fe71769ad07 | 136 | |
| persoder | 0:3fe71769ad07 | 137 | /** |
| persoder | 0:3fe71769ad07 | 138 | * |
| persoder | 0:3fe71769ad07 | 139 | */ |
| persoder | 1:d40d911b763a | 140 | void activate(bool active = true); |
| persoder | 0:3fe71769ad07 | 141 | |
| persoder | 0:3fe71769ad07 | 142 | /** |
| persoder | 0:3fe71769ad07 | 143 | * |
| persoder | 0:3fe71769ad07 | 144 | */ |
| persoder | 1:d40d911b763a | 145 | typedef uint8_t address_t[5]; |
| persoder | 1:d40d911b763a | 146 | |
| persoder | 1:d40d911b763a | 147 | /** Send a message. |
| persoder | 1:d40d911b763a | 148 | * This routine will transfer the data from the supplied buffer and send |
| persoder | 1:d40d911b763a | 149 | * it to the specified address using the current control packet settings. |
| persoder | 1:d40d911b763a | 150 | * \param addr The address to send to. |
| persoder | 1:d40d911b763a | 151 | * \param addr_len Length of address, in bits. |
| persoder | 1:d40d911b763a | 152 | * \param msg_buf Message body. |
| persoder | 1:d40d911b763a | 153 | * \param msg_len Length of message, in bits. |
| persoder | 1:d40d911b763a | 154 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 155 | */ |
| persoder | 1:d40d911b763a | 156 | nRF2401A& sendMsg(address_t addr, uint8_t addr_len, uint8_t *msg_buf, uint8_t msg_len); |
| persoder | 0:3fe71769ad07 | 157 | |
| persoder | 1:d40d911b763a | 158 | /** Register a receive action callback. |
| persoder | 1:d40d911b763a | 159 | * Attach a callback that will be called when the tranciever intercept a |
| persoder | 1:d40d911b763a | 160 | * message. This callback will be called in the context of an interrupt |
| persoder | 1:d40d911b763a | 161 | * routine and should act accordingly. |
| persoder | 1:d40d911b763a | 162 | * \param handler The callback, of type nRF2401_rx_handler_t. |
| persoder | 1:d40d911b763a | 163 | * \param arg Pointer to data supplied to the handler at call time. |
| persoder | 1:d40d911b763a | 164 | * \return Reference to the invoked object (for chaining operations). |
| persoder | 1:d40d911b763a | 165 | */ |
| persoder | 1:d40d911b763a | 166 | nRF2401A& attachRXHandler(nRF2401A_rx_handler_t handler, void *arg); |
| persoder | 1:d40d911b763a | 167 | |
| persoder | 1:d40d911b763a | 168 | void printControlPacket(Serial& port); |
| persoder | 1:d40d911b763a | 169 | void printDataPacket(Serial& port); |
| persoder | 0:3fe71769ad07 | 170 | |
| persoder | 0:3fe71769ad07 | 171 | private: |
| persoder | 0:3fe71769ad07 | 172 | |
| persoder | 1:d40d911b763a | 173 | DigitalOut _ce; /**< Chip Enable pin. */ |
| persoder | 1:d40d911b763a | 174 | DigitalOut _cs; /**< Chip select pin. */ |
| persoder | 1:d40d911b763a | 175 | DigitalIn _dr1; /**< Data Ready 1 pin. */ |
| persoder | 1:d40d911b763a | 176 | DigitalOut _clk1; /**< Clock 1 pin. */ |
| persoder | 1:d40d911b763a | 177 | DigitalInOut _data; /**< Data pin. */ |
| persoder | 0:3fe71769ad07 | 178 | |
| persoder | 1:d40d911b763a | 179 | /** |
| persoder | 1:d40d911b763a | 180 | * |
| persoder | 1:d40d911b763a | 181 | */ |
| persoder | 1:d40d911b763a | 182 | typedef enum |
| persoder | 1:d40d911b763a | 183 | { |
| persoder | 1:d40d911b763a | 184 | UNDEF, /**< The start state. */ |
| persoder | 1:d40d911b763a | 185 | RX, /**< The tranciever is in receive mode. */ |
| persoder | 1:d40d911b763a | 186 | TX, /**< The tranciever is transmitting. */ |
| persoder | 1:d40d911b763a | 187 | STANDBY /**< The tranciever goes into stanby mode. */ |
| persoder | 1:d40d911b763a | 188 | } STATE_T; |
| persoder | 1:d40d911b763a | 189 | |
| persoder | 1:d40d911b763a | 190 | STATE_T _state; |
| persoder | 1:d40d911b763a | 191 | |
| persoder | 1:d40d911b763a | 192 | /** Contol packet data. |
| persoder | 1:d40d911b763a | 193 | * |
| persoder | 1:d40d911b763a | 194 | */ |
| persoder | 0:3fe71769ad07 | 195 | struct nRF2401A_ctrl_packet_t |
| persoder | 0:3fe71769ad07 | 196 | { |
| persoder | 0:3fe71769ad07 | 197 | uint8_t channel_2_data_payload_len; /**< */ |
| persoder | 0:3fe71769ad07 | 198 | uint8_t channel_1_data_payload_len; /**< */ |
| persoder | 0:3fe71769ad07 | 199 | uint8_t channel_2_address[5]; /**< */ |
| persoder | 0:3fe71769ad07 | 200 | uint8_t channel_1_address[5]; /**< */ |
| persoder | 0:3fe71769ad07 | 201 | |
| persoder | 1:d40d911b763a | 202 | uint8_t crc_config : 2; /**< */ |
| persoder | 0:3fe71769ad07 | 203 | uint8_t channel_address_len : 6; /**< */ |
| persoder | 0:3fe71769ad07 | 204 | |
| persoder | 1:d40d911b763a | 205 | uint8_t rf_power : 2; /**< */ |
| persoder | 1:d40d911b763a | 206 | uint8_t xo_frequency : 3; /**< */ |
| persoder | 0:3fe71769ad07 | 207 | uint8_t rf_data_rate : 1; /**< */ |
| persoder | 1:d40d911b763a | 208 | uint8_t communication_mode : 1; /**< */ |
| persoder | 1:d40d911b763a | 209 | uint8_t enable_dual_channel_mode : 1; /**< */ |
| persoder | 0:3fe71769ad07 | 210 | |
| persoder | 1:d40d911b763a | 211 | uint8_t txr_switch : 1; /**< */ |
| persoder | 0:3fe71769ad07 | 212 | uint8_t rf_channel : 7; /**< */ |
| persoder | 0:3fe71769ad07 | 213 | |
| persoder | 0:3fe71769ad07 | 214 | } _ctrl_packet_buf; /**< */ |
| persoder | 1:d40d911b763a | 215 | |
| persoder | 1:d40d911b763a | 216 | uint8_t *_ctrl_packet; /**< */ |
| persoder | 1:d40d911b763a | 217 | |
| persoder | 1:d40d911b763a | 218 | uint8_t _data_buf[32]; /**< */ |
| persoder | 1:d40d911b763a | 219 | |
| persoder | 1:d40d911b763a | 220 | nRF2401A_rx_handler_t _rx_handler; /**< */ |
| persoder | 1:d40d911b763a | 221 | void *_rx_handler_arg; /**< */ |
| persoder | 1:d40d911b763a | 222 | |
| persoder | 1:d40d911b763a | 223 | /** Receive ISR. |
| persoder | 1:d40d911b763a | 224 | * This handler is attached to the rising flank of the DR1 pin. It |
| persoder | 1:d40d911b763a | 225 | * will thus be called when the nRF2401A receives a packet in ShockBurst |
| persoder | 1:d40d911b763a | 226 | * mode (the mode used). It will in turn call the attached handler. |
| persoder | 1:d40d911b763a | 227 | */ |
| persoder | 1:d40d911b763a | 228 | void dataReadyHandler(void); |
| persoder | 1:d40d911b763a | 229 | |
| persoder | 1:d40d911b763a | 230 | /** |
| persoder | 1:d40d911b763a | 231 | * |
| persoder | 1:d40d911b763a | 232 | */ |
| persoder | 1:d40d911b763a | 233 | InterruptIn _dr1_isr; |
| persoder | 1:d40d911b763a | 234 | |
| persoder | 1:d40d911b763a | 235 | /* |
| persoder | 1:d40d911b763a | 236 | * |
| persoder | 1:d40d911b763a | 237 | */ |
| persoder | 1:d40d911b763a | 238 | typedef enum { RX_MODE = 0x1, TX_MODE = 0x0 } TXR_T; |
| persoder | 1:d40d911b763a | 239 | |
| persoder | 1:d40d911b763a | 240 | /** Write to the data bus. |
| persoder | 1:d40d911b763a | 241 | * Write n_bits bits on the DATA line. |
| persoder | 1:d40d911b763a | 242 | * \param buf Data buffer. |
| persoder | 1:d40d911b763a | 243 | * \param n_bits Number of bits to transfer. |
| persoder | 1:d40d911b763a | 244 | * \param is_ctrl True if the tranfered data is control word, false if data. |
| persoder | 1:d40d911b763a | 245 | */ |
| persoder | 1:d40d911b763a | 246 | void pushCtrl(uint8_t *buf, uint8_t n_bits, bool is_ctrl = true); |
| persoder | 1:d40d911b763a | 247 | |
| persoder | 1:d40d911b763a | 248 | /** Read a message from the tranciever. |
| persoder | 1:d40d911b763a | 249 | * Read until DR1 goes low. |
| persoder | 1:d40d911b763a | 250 | * \param buf Data buffer. |
| persoder | 1:d40d911b763a | 251 | * \return Number of bits read. |
| persoder | 1:d40d911b763a | 252 | */ |
| persoder | 1:d40d911b763a | 253 | int pull(uint8_t *buf); |
| persoder | 1:d40d911b763a | 254 | }; |