Per Söderstam / Mbed 2 deprecated driver_nRF2401A

Dependencies:   mbed

Committer:
persoder
Date:
Mon Jul 08 21:08:46 2013 +0000
Revision:
1:d40d911b763a
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?

UserRevisionLine numberNew contents of line
persoder 1:d40d911b763a 1 /** \file
persoder 1:d40d911b763a 2 * \brief
persoder 1:d40d911b763a 3 *
persoder 1:d40d911b763a 4 * \author Per Söderstam © 2011
persoder 1:d40d911b763a 5 */
persoder 1:d40d911b763a 6
persoder 1:d40d911b763a 7 #include "nRF2401A.h"
persoder 1:d40d911b763a 8
persoder 1:d40d911b763a 9 const int Ts = 1; /**< Setup time from data to rising clock edge on write (accualy 500 ns). */
persoder 1:d40d911b763a 10 const int Th = 1; /**< Hold time from rising clock to data toggle/falling clock (accualy 500 ns). */
persoder 1:d40d911b763a 11 const int Tcs2data = 5; /**< Min delay from CS assert to data, in us. */
persoder 1:d40d911b763a 12 const int Tce2data = 5; /**< Min delay from CE assert to data, in us. */
persoder 1:d40d911b763a 13 const int Td = 1; /**< Minimum delay between edges (actually 50 ns). */
persoder 1:d40d911b763a 14 const int Tpd2cfgm = 3; /**< Minimum delay from power up of tranciever to configuration. */
persoder 1:d40d911b763a 15 const int Tsby2txSB = 195; /**< Minimum delay from tx initation to air, in us. */
persoder 1:d40d911b763a 16 const int Thmin = 5; /**< */
persoder 1:d40d911b763a 17 const int Tclk2data = 1; /**< */
persoder 1:d40d911b763a 18
persoder 1:d40d911b763a 19 nRF2401A::nRF2401A(PinName ce,
persoder 1:d40d911b763a 20 PinName cs,
persoder 1:d40d911b763a 21 PinName dr1,
persoder 1:d40d911b763a 22 PinName clk1,
persoder 1:d40d911b763a 23 PinName data)
persoder 1:d40d911b763a 24 : _ce(DigitalOut(ce)),
persoder 1:d40d911b763a 25 _cs(DigitalOut(cs)),
persoder 1:d40d911b763a 26 _dr1(DigitalIn(dr1)),
persoder 1:d40d911b763a 27 _clk1(DigitalOut(clk1)),
persoder 1:d40d911b763a 28 _data(DigitalInOut(data)),
persoder 1:d40d911b763a 29 _state(nRF2401A::UNDEF),
persoder 1:d40d911b763a 30 _rx_handler((nRF2401A_rx_handler_t) 0),
persoder 1:d40d911b763a 31 _rx_handler_arg((void *) 0),
persoder 1:d40d911b763a 32 _dr1_isr(InterruptIn(dr1)) {
persoder 1:d40d911b763a 33
persoder 1:d40d911b763a 34 // init member variables
persoder 1:d40d911b763a 35 _data.output();
persoder 1:d40d911b763a 36 // setup...
persoder 1:d40d911b763a 37 _ctrl_packet = (uint8_t *) &_ctrl_packet_buf;
persoder 1:d40d911b763a 38 _dr1_isr.rise(this, &nRF2401A::dataReadyHandler);
persoder 1:d40d911b763a 39 // ...tranciever in standby...
persoder 1:d40d911b763a 40 _ce = 0;
persoder 1:d40d911b763a 41 _cs = 0;
persoder 1:d40d911b763a 42 // ...and clear receive buffer
persoder 1:d40d911b763a 43 for (int i = 0; i < 16; i++)
persoder 1:d40d911b763a 44 _data_buf[i] = 0x0;
persoder 1:d40d911b763a 45 // ...set imutable control fields...
persoder 1:d40d911b763a 46 _ctrl_packet_buf.enable_dual_channel_mode = 0x0; // single channel receive
persoder 1:d40d911b763a 47 _ctrl_packet_buf.communication_mode = 0x1; // ShockBurst mode
persoder 1:d40d911b763a 48 _ctrl_packet_buf.xo_frequency = 0x3; // 16 MHz crystal
persoder 1:d40d911b763a 49 _ctrl_packet_buf.rf_power = 0x3; // 0 dBm (1 mW) output power
persoder 1:d40d911b763a 50 // ...start in RX mode
persoder 1:d40d911b763a 51 _ctrl_packet_buf.txr_switch = nRF2401A::RX_MODE;
persoder 1:d40d911b763a 52 // assure minimum wake up time while assuming tranciever powers up with uP
persoder 1:d40d911b763a 53 wait_ms(Tpd2cfgm);
persoder 1:d40d911b763a 54
persoder 1:d40d911b763a 55 return;
persoder 1:d40d911b763a 56 }
persoder 1:d40d911b763a 57
persoder 1:d40d911b763a 58 void nRF2401A::printControlPacket(Serial& port)
persoder 1:d40d911b763a 59 {
persoder 1:d40d911b763a 60 for(int i = 0; i < sizeof(_ctrl_packet_buf); i++)
persoder 1:d40d911b763a 61 port.printf("%02x ", _ctrl_packet[i]);
persoder 1:d40d911b763a 62 port.printf("\n\r");
persoder 1:d40d911b763a 63 return;
persoder 1:d40d911b763a 64 }
persoder 1:d40d911b763a 65
persoder 1:d40d911b763a 66 void nRF2401A::printDataPacket(Serial& port)
persoder 1:d40d911b763a 67 {
persoder 1:d40d911b763a 68 for(int i = 0; i < sizeof(_data_buf); i++)
persoder 1:d40d911b763a 69 port.printf("%02x ", _data_buf[i]);
persoder 1:d40d911b763a 70 port.printf("\r");
persoder 1:d40d911b763a 71 return;
persoder 1:d40d911b763a 72 }
persoder 1:d40d911b763a 73
persoder 1:d40d911b763a 74 nRF2401A& nRF2401A::attachRXHandler(nRF2401A_rx_handler_t handler, void *arg) {
persoder 1:d40d911b763a 75
persoder 1:d40d911b763a 76 _rx_handler = handler;
persoder 1:d40d911b763a 77 _rx_handler_arg = arg;
persoder 1:d40d911b763a 78
persoder 1:d40d911b763a 79 return *this;
persoder 1:d40d911b763a 80 }
persoder 1:d40d911b763a 81
persoder 1:d40d911b763a 82 nRF2401A& nRF2401A::sendMsg(nRF2401A::address_t addr, uint8_t addr_len, uint8_t *msg_buf, uint8_t msg_len) {
persoder 1:d40d911b763a 83
persoder 1:d40d911b763a 84 // point to start of address byte in address
persoder 1:d40d911b763a 85 uint8_t *aligned_addr = &addr[sizeof(address_t) - (addr_len / 8)];
persoder 1:d40d911b763a 86 // wait for tx completion
persoder 1:d40d911b763a 87 int Toa = (_ctrl_packet_buf.rf_data_rate == nRF2401A::BIT_RATE_1MBITS ? 1 : 4) * (addr_len + msg_len + 1 + 16);
persoder 1:d40d911b763a 88
persoder 1:d40d911b763a 89 switch (_state) {
persoder 1:d40d911b763a 90 case nRF2401A::RX:
persoder 1:d40d911b763a 91 // switch to transmit
persoder 1:d40d911b763a 92 _ce = 0;
persoder 1:d40d911b763a 93 _cs = 0;
persoder 1:d40d911b763a 94 wait_us(Td);
persoder 1:d40d911b763a 95 // assert CS/CE and wait Tcs2data
persoder 1:d40d911b763a 96 _ce = 0;
persoder 1:d40d911b763a 97 _cs = 1;
persoder 1:d40d911b763a 98 wait_us(Tcs2data);
persoder 1:d40d911b763a 99 // push out the bits
persoder 1:d40d911b763a 100 _data = nRF2401A::TX_MODE;
persoder 1:d40d911b763a 101 wait_us(Ts);
persoder 1:d40d911b763a 102 _clk1 = 1;
persoder 1:d40d911b763a 103 wait_us(Th);
persoder 1:d40d911b763a 104 _clk1 = 0;
persoder 1:d40d911b763a 105 // wait Td
persoder 1:d40d911b763a 106 wait_us(Td);
persoder 1:d40d911b763a 107 // deassert CS/CE and done...
persoder 1:d40d911b763a 108 _cs = 0;
persoder 1:d40d911b763a 109 _ce = 0;
persoder 1:d40d911b763a 110
persoder 1:d40d911b763a 111 // zero control and data lines
persoder 1:d40d911b763a 112 _clk1 = 0;
persoder 1:d40d911b763a 113 _data = 0;
persoder 1:d40d911b763a 114 // wait Td
persoder 1:d40d911b763a 115 wait_us(Td);
persoder 1:d40d911b763a 116 // assert CE and wait Tcs2data
persoder 1:d40d911b763a 117 _ce = 1;
persoder 1:d40d911b763a 118 wait_us(Tce2data);
persoder 1:d40d911b763a 119 // push out the address bits
persoder 1:d40d911b763a 120 for (int i = 0; i < addr_len; i++) {
persoder 1:d40d911b763a 121 _data = ((0x80 >> (i % 8)) & aligned_addr[i / 8]) ? 0x1 : 0x0;
persoder 1:d40d911b763a 122 wait_us(Ts);
persoder 1:d40d911b763a 123 _clk1 = 1;
persoder 1:d40d911b763a 124 wait_us(Th);
persoder 1:d40d911b763a 125 _clk1 = 0;
persoder 1:d40d911b763a 126 }
persoder 1:d40d911b763a 127 // push out the message bits
persoder 1:d40d911b763a 128 for (int i = 0; i < msg_len; i++) {
persoder 1:d40d911b763a 129 _data = ((0x80 >> (i % 8)) & msg_buf[i / 8]) ? 0x1 : 0x0;
persoder 1:d40d911b763a 130 wait_us(Ts);
persoder 1:d40d911b763a 131 _clk1 = 1;
persoder 1:d40d911b763a 132 wait_us(Th);
persoder 1:d40d911b763a 133 _clk1 = 0;
persoder 1:d40d911b763a 134 }
persoder 1:d40d911b763a 135 // reset data
persoder 1:d40d911b763a 136 _data = 0;
persoder 1:d40d911b763a 137 // deassert CE will initiate transmission
persoder 1:d40d911b763a 138 _ce = 0;
persoder 1:d40d911b763a 139 wait_us(Tsby2txSB + Toa);
persoder 1:d40d911b763a 140
persoder 1:d40d911b763a 141 // switch back to receive
persoder 1:d40d911b763a 142 wait_us(Td);
persoder 1:d40d911b763a 143 // assert CS/CE and wait Tcs2data
persoder 1:d40d911b763a 144 _cs = 1;
persoder 1:d40d911b763a 145 wait_us(Tcs2data);
persoder 1:d40d911b763a 146 // push out the bits
persoder 1:d40d911b763a 147 _data = nRF2401A::RX_MODE;
persoder 1:d40d911b763a 148 wait_us(Ts);
persoder 1:d40d911b763a 149 _clk1 = 1;
persoder 1:d40d911b763a 150 wait_us(Th);
persoder 1:d40d911b763a 151 _clk1 = 0;
persoder 1:d40d911b763a 152 // wait Td
persoder 1:d40d911b763a 153 wait_us(Td);
persoder 1:d40d911b763a 154 _data = 0;
persoder 1:d40d911b763a 155 // deassert CS/CE and done...
persoder 1:d40d911b763a 156 _cs = 0;
persoder 1:d40d911b763a 157 // wait Td to avoid simultaineous control high
persoder 1:d40d911b763a 158 wait_us(Td);
persoder 1:d40d911b763a 159 _ce = 1;
persoder 1:d40d911b763a 160 // done
persoder 1:d40d911b763a 161 break;
persoder 1:d40d911b763a 162 case nRF2401A::STANDBY:
persoder 1:d40d911b763a 163 case nRF2401A::TX:
persoder 1:d40d911b763a 164 case nRF2401A::UNDEF:
persoder 1:d40d911b763a 165 default:
persoder 1:d40d911b763a 166 // can only send in RX mode
persoder 1:d40d911b763a 167 break;
persoder 1:d40d911b763a 168 }
persoder 1:d40d911b763a 169
persoder 1:d40d911b763a 170 return *this;
persoder 1:d40d911b763a 171 }
persoder 1:d40d911b763a 172
persoder 1:d40d911b763a 173 void nRF2401A::pushCtrl(uint8_t *buf, uint8_t n_bits, bool is_ctrl) {
persoder 1:d40d911b763a 174
persoder 1:d40d911b763a 175 DigitalOut &ctrl_pin = is_ctrl ? _cs : _ce;
persoder 1:d40d911b763a 176
persoder 1:d40d911b763a 177 // set data to output
persoder 1:d40d911b763a 178 _data.output();
persoder 1:d40d911b763a 179 // zero control and data lines
persoder 1:d40d911b763a 180 _cs = 0;
persoder 1:d40d911b763a 181 _ce = 0;
persoder 1:d40d911b763a 182 _clk1 = 0;
persoder 1:d40d911b763a 183 _data = 0;
persoder 1:d40d911b763a 184 // wait Td
persoder 1:d40d911b763a 185 wait_us(Td);
persoder 1:d40d911b763a 186 // assert CS/CE and wait Tcs2data
persoder 1:d40d911b763a 187 ctrl_pin = 1;
persoder 1:d40d911b763a 188 wait_us(Tcs2data);
persoder 1:d40d911b763a 189 // push out the bits
persoder 1:d40d911b763a 190 for (int i = 0; i < n_bits; i++) {
persoder 1:d40d911b763a 191 _data = ((0x80 >> (i % 8)) & buf[i / 8]) ? 0x1 : 0x0;
persoder 1:d40d911b763a 192 wait_us(Ts);
persoder 1:d40d911b763a 193 _clk1 = 1;
persoder 1:d40d911b763a 194 wait_us(Th);
persoder 1:d40d911b763a 195 _clk1 = 0;
persoder 1:d40d911b763a 196 }
persoder 1:d40d911b763a 197 _data = 0;
persoder 1:d40d911b763a 198 // wait Td
persoder 1:d40d911b763a 199 wait_us(Td);
persoder 1:d40d911b763a 200 // deassert CS/CE and done...
persoder 1:d40d911b763a 201 ctrl_pin = 0;
persoder 1:d40d911b763a 202
persoder 1:d40d911b763a 203 return;
persoder 1:d40d911b763a 204 }
persoder 1:d40d911b763a 205
persoder 1:d40d911b763a 206 int nRF2401A::pull(uint8_t *buf) {
persoder 1:d40d911b763a 207 int n = 0;
persoder 1:d40d911b763a 208
persoder 1:d40d911b763a 209 // read from data pin
persoder 1:d40d911b763a 210 _data.input();
persoder 1:d40d911b763a 211 // init signals, go to standby
persoder 1:d40d911b763a 212 _ce = 1;
persoder 1:d40d911b763a 213 _cs = 0;
persoder 1:d40d911b763a 214 _clk1 = 0;
persoder 1:d40d911b763a 215 // ensure time from DR
persoder 1:d40d911b763a 216 wait_us(Td);
persoder 1:d40d911b763a 217
persoder 1:d40d911b763a 218 while (_dr1 == 1) {
persoder 1:d40d911b763a 219 _clk1 = 1;
persoder 1:d40d911b763a 220 wait_us(Thmin);
persoder 1:d40d911b763a 221 if(_data.read())
persoder 1:d40d911b763a 222 buf[n / 8] |= (0x80 >> (n % 8));
persoder 1:d40d911b763a 223 else
persoder 1:d40d911b763a 224 buf[n / 8] &= ~(0x80 >> (n % 8));
persoder 1:d40d911b763a 225 n++;
persoder 1:d40d911b763a 226 _clk1 = 0;
persoder 1:d40d911b763a 227 wait_us(Thmin);
persoder 1:d40d911b763a 228 }
persoder 1:d40d911b763a 229 // return to active
persoder 1:d40d911b763a 230 _ce = 1;
persoder 1:d40d911b763a 231 // reset data pin direction
persoder 1:d40d911b763a 232 _data.output();
persoder 1:d40d911b763a 233
persoder 1:d40d911b763a 234 return n;
persoder 1:d40d911b763a 235 }
persoder 1:d40d911b763a 236
persoder 1:d40d911b763a 237 void nRF2401A::activate(bool active) {
persoder 1:d40d911b763a 238 switch (_state) {
persoder 1:d40d911b763a 239 case nRF2401A::RX:
persoder 1:d40d911b763a 240 if (!active) {
persoder 1:d40d911b763a 241 _state = nRF2401A::STANDBY;
persoder 1:d40d911b763a 242 _ce = 0;
persoder 1:d40d911b763a 243 _cs = 0;
persoder 1:d40d911b763a 244 }
persoder 1:d40d911b763a 245 break;
persoder 1:d40d911b763a 246 case nRF2401A::STANDBY:
persoder 1:d40d911b763a 247 if (active) {
persoder 1:d40d911b763a 248 _state = nRF2401A::RX;
persoder 1:d40d911b763a 249 _ce = 1;
persoder 1:d40d911b763a 250 _cs = 0;
persoder 1:d40d911b763a 251 }
persoder 1:d40d911b763a 252 break;
persoder 1:d40d911b763a 253 case nRF2401A::TX:
persoder 1:d40d911b763a 254 case nRF2401A::UNDEF:
persoder 1:d40d911b763a 255 default:
persoder 1:d40d911b763a 256 break;
persoder 1:d40d911b763a 257 }
persoder 1:d40d911b763a 258
persoder 1:d40d911b763a 259 return;
persoder 1:d40d911b763a 260 }
persoder 1:d40d911b763a 261
persoder 1:d40d911b763a 262 void nRF2401A::dataReadyHandler(void) {
persoder 1:d40d911b763a 263 switch (_state) {
persoder 1:d40d911b763a 264 case nRF2401A::RX:
persoder 1:d40d911b763a 265 pull(_data_buf);
persoder 1:d40d911b763a 266 if (_rx_handler != (nRF2401A_rx_handler_t) 0)
persoder 1:d40d911b763a 267 _rx_handler(_rx_handler_arg);
persoder 1:d40d911b763a 268 break;
persoder 1:d40d911b763a 269 default:
persoder 1:d40d911b763a 270 // todo: error msg
persoder 1:d40d911b763a 271 break;
persoder 1:d40d911b763a 272 }
persoder 1:d40d911b763a 273 return;
persoder 1:d40d911b763a 274 }
persoder 1:d40d911b763a 275
persoder 1:d40d911b763a 276 nRF2401A& nRF2401A::flushControlPacket() {
persoder 1:d40d911b763a 277 switch (_state) {
persoder 1:d40d911b763a 278 case nRF2401A::UNDEF:
persoder 1:d40d911b763a 279 case nRF2401A::RX:
persoder 1:d40d911b763a 280 pushCtrl(_ctrl_packet, 15 << 3 );
persoder 1:d40d911b763a 281 _state = nRF2401A::RX;
persoder 1:d40d911b763a 282 _ce = 1;
persoder 1:d40d911b763a 283 _cs = 0;
persoder 1:d40d911b763a 284 break;
persoder 1:d40d911b763a 285 case nRF2401A::STANDBY:
persoder 1:d40d911b763a 286 pushCtrl(_ctrl_packet, 15 << 3 );
persoder 1:d40d911b763a 287 _state = nRF2401A::STANDBY;
persoder 1:d40d911b763a 288 _ce = 0;
persoder 1:d40d911b763a 289 _cs = 0;
persoder 1:d40d911b763a 290 break;
persoder 1:d40d911b763a 291 case nRF2401A::TX:
persoder 1:d40d911b763a 292 default:
persoder 1:d40d911b763a 293 _ce = 0;
persoder 1:d40d911b763a 294 _cs = 0;
persoder 1:d40d911b763a 295 }
persoder 1:d40d911b763a 296
persoder 1:d40d911b763a 297 return *this;
persoder 1:d40d911b763a 298 }