function processInquiryForRegister(reg, cb) { var iq = registersNeeded[reg]; reg = +reg; // was string key, now convert back to number // if a register is "full" we can simply overwrite, otherwise we must read+merge // NOTE: high bits in RF_CH/PX_PW_Pn are *reserved*, i.e. technically need merging if (!iq.arr.length || iq.arr[0]==='RF_CH' || iq.arr[0].indexOf('RX_PW_P')===0) { var val = vals[iq.solo || iq.arr[0]], buf = (Buffer.isBuffer(val)) ? val : [val]; nrf.execCommand(['W_REGISTER', reg], buf, cb); } else nrf.execCommand(['R_REGISTER', reg], 1, function (e,d) { if (e) return cb(e); var val = d[0], settlingNeeded = 0; if (iq.solo) val = vals[iq.solo]; // TODO: refactor so as not to fetch in the first place! iq.arr.forEach(function (mnem) { var m = maskForMnemonic(mnem); if (mnem === 'PWR_UP') { var rising = !(d[0] & m.mask) && vals[mnem]; if (rising) settlingNeeded = Math.max(settlingNeeded, nrf._T.pd2stby); } else if (mnem === 'PRIM_RX') { var changing = !(d[0] & m.mask) !== !vals[mnem]; if (changing) settlingNeeded = Math.max(settlingNeeded, nrf._T.stby2a); } val &= ~m.mask; // clear current value val |= (vals[mnem] << m.rightmostBit) & m.mask; }); if (val !== d[0] || reg === _statusReg) nrf.execCommand(['W_REGISTER', reg], [val], function () { if (settlingNeeded) nrf.blockMicroseconds(settlingNeeded); // see p.24 cb.apply(this, arguments); }); else cb(null); // don't bother writing if value hasn't changed (unless status, which clears bits) }); }
nrf.sendPayload = function (data, opts, cb) { if (!cb) cb = _nop; if (data.length > 32) throw Error("Maximum packet size exceeded. Smaller writes, Dash!"); nrf._prevSender = null; // help PxX setup again if user sends data directly var cmd; if ('asAckTo' in opts) { cmd = ['W_ACK_PAYLOAD',opts.asAckTo]; } else if (opts.ack) { cmd = 'W_TX_PAYLOAD'; } else { cmd = 'W_TX_PD_NOACK'; } nrf.execCommand(cmd, data, function (e) { if (e) return cb(e); if (!opts.ceHigh) nrf.pulseCE('pece2csn'); // TODO: if _sendOpts.asAckTo we won't get MAX_RT interrupt — how to prevent a blocked TX FIFO? (see p.33) nrf.once('interrupt', function (d) { if (d.MAX_RT) nrf.execCommand('FLUSH_TX', function (e) { // see p.56 finish(new Error("Packet timeout, transmit queue flushed.")); }); else if (!d.TX_DS) console.warn("Unexpected IRQ during transmit phase!"); else finish(); function finish(e) { // clear our interrupts, leaving RX_DR nrf.setStates({TX_DS:true,MAX_RT:true,RX_DR:false}, function () { cb(e||null); }); } }); }); };
if (opts.width === 'auto') nrf.execCommand('R_RX_PL_WID', 1, function (e,d) { if (e) return finish(e); var width = d[0]; if (width > 32) nrf.execCommand('FLUSH_RX', function (e,d) { finish(new Error("Invalid dynamic payload size, receive queue flushed.")); // per R_RX_PL_WID details, p.51 }); else read(width); }); else read(opts.width);
nrf.once('interrupt', function (d) { if (d.MAX_RT) nrf.execCommand('FLUSH_TX', function (e) { // see p.56 finish(new Error("Packet timeout, transmit queue flushed.")); }); else if (!d.TX_DS) console.warn("Unexpected IRQ during transmit phase!"); else finish(); function finish(e) { // clear our interrupts, leaving RX_DR nrf.setStates({TX_DS:true,MAX_RT:true,RX_DR:false}, function () { cb(e||null); }); } });
function processInquiryForRegister(reg, cb) { // TODO: execCommand always reads register 0x07 but we're not optimizing for that // TODO: we could probably also eliminate re-fetch of 0x07 during IRQ processing var iq = registersNeeded[reg]; reg = +reg; nrf.execCommand(['R_REGISTER',reg], iq.len, function (e,d) { if (e) return cb(e); iq.arr.forEach(function (mnem) { var m = maskForMnemonic(mnem); states[mnem] = (d[0] & m.mask) >> m.rightmostBit; }); if (iq.solo) states[iq.solo] = d; cb(); }); }
nrf.readPayload = function (opts, cb) { if (!cb) cb = _nop; if (opts.width === 'auto') nrf.execCommand('R_RX_PL_WID', 1, function (e,d) { if (e) return finish(e); var width = d[0]; if (width > 32) nrf.execCommand('FLUSH_RX', function (e,d) { finish(new Error("Invalid dynamic payload size, receive queue flushed.")); // per R_RX_PL_WID details, p.51 }); else read(width); }); else read(opts.width); function read(width) { nrf.execCommand('R_RX_PAYLOAD', width, finish); } function finish(e,d) { // see footnote c, p.62 if (opts.leaveStatus) cb(e,d); else nrf.setStates({RX_DR:true,TX_DS:false,MAX_RT:false}, function (e2) { cb(e||e2,d); }); } };
} else nrf.execCommand(['R_REGISTER', reg], 1, function (e,d) { if (e) return cb(e); var val = d[0], settlingNeeded = 0; if (iq.solo) val = vals[iq.solo]; // TODO: refactor so as not to fetch in the first place! iq.arr.forEach(function (mnem) { var m = maskForMnemonic(mnem); if (mnem === 'PWR_UP') { var rising = !(d[0] & m.mask) && vals[mnem]; if (rising) settlingNeeded = Math.max(settlingNeeded, nrf._T.pd2stby); } else if (mnem === 'PRIM_RX') { var changing = !(d[0] & m.mask) !== !vals[mnem]; if (changing) settlingNeeded = Math.max(settlingNeeded, nrf._T.stby2a); } val &= ~m.mask; // clear current value val |= (vals[mnem] << m.rightmostBit) & m.mask; }); if (val !== d[0] || reg === _statusReg) nrf.execCommand(['W_REGISTER', reg], [val], function () { if (settlingNeeded) nrf.blockMicroseconds(settlingNeeded); // see p.24 cb.apply(this, arguments); }); else cb(null); // don't bother writing if value hasn't changed (unless status, which clears bits) });
function read(width) { nrf.execCommand('R_RX_PAYLOAD', width, finish); }