Skip to content

Commit 293b841

Browse files
committed
add: expose status byte in public API.
Offers intuitive alternatives to `maskIRQ()` and `whatHappened()`. The API is more explicit, but there's less bit-banging and memory allocation involved. The StatusFlags API is implemented in the python wrapper also. All new API is grouped in the docs under the topic "Status flags".
1 parent 0c34c0f commit 293b841

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

RF24.cpp

+56
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212

1313
/****************************************************************************/
1414

15+
int StatusFlags::toString(char* buf) const
16+
{
17+
return sprintf(buf, "rx_dr: %s, tx_ds: %s, tx_df: %s, rx_pipe: %d, tx_full: %s",
18+
rx_dr ? "true" : "false", tx_ds ? "true" : "false",
19+
tx_df ? "true" : "false", rx_pipe, tx_full ? "true" : "false");
20+
}
21+
22+
/****************************************************************************/
23+
1524
void RF24::csn(bool mode)
1625
{
1726
#if defined(RF24_TINY)
@@ -1559,6 +1568,53 @@ void RF24::whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready)
15591568

15601569
/****************************************************************************/
15611570

1571+
StatusFlags RF24::clearStatusFlags()
1572+
{
1573+
write_register(NRF_STATUS, 0x70);
1574+
StatusFlags flags;
1575+
memcpy((void*)(&flags), &status, 1);
1576+
return flags;
1577+
}
1578+
1579+
/****************************************************************************/
1580+
1581+
void RF24::clearStatusFlags(StatusFlags& flags)
1582+
{
1583+
uint8_t out = 0;
1584+
memcpy(&out, &flags, 1);
1585+
write_register(NRF_STATUS, out & 0x70);
1586+
memcpy((void*)(&flags), &status, 1);
1587+
}
1588+
1589+
/****************************************************************************/
1590+
1591+
void RF24::setStatusFlags(StatusFlags flags)
1592+
{
1593+
uint8_t out = 0;
1594+
memcpy(&out, &flags, 1);
1595+
// flip the flags to translate from "human understanding"
1596+
write_register(NRF_CONFIG, ~out & 0x70);
1597+
}
1598+
1599+
/****************************************************************************/
1600+
1601+
void RF24::getStatusFlags(StatusFlags& flags)
1602+
{
1603+
memcpy((void*)(&flags), &status, 1);
1604+
}
1605+
1606+
/****************************************************************************/
1607+
1608+
StatusFlags RF24::update()
1609+
{
1610+
read_register(RF24_NOP, (uint8_t*)nullptr, 0);
1611+
StatusFlags flags;
1612+
memcpy((void*)(&flags), &status, 1);
1613+
return flags;
1614+
}
1615+
1616+
/****************************************************************************/
1617+
15621618
void RF24::openWritingPipe(uint64_t value)
15631619
{
15641620
// Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)

RF24.h

+120
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,54 @@ typedef enum
128128
RF24_FIFO_INVALID,
129129
} rf24_fifo_state_e;
130130

131+
/**
132+
* @}
133+
* @defgroup StatusFlags Status flags
134+
* @{
135+
*/
136+
137+
/**
138+
* @brief A bit-field struct to represent the radio's STATUS byte.
139+
*/
140+
struct StatusFlags
141+
{
142+
// starting with bit 0 at the top...
143+
/// Signifies that the TX FIFO is fully occupied.
144+
const bool tx_full : 1;
145+
/// @brief Represents the pipe number that received the first available payload in the RX FIFO.
146+
/// @remark This data shall be considered invalid if the @ref StatusFlags::rx_dr flag is `false`.
147+
const uint8_t rx_pipe : 3;
148+
/// Represents an event where TX Data Failed to send.
149+
bool tx_df : 1;
150+
/// Represents an event where TX Data Sent successfully.
151+
bool tx_ds : 1;
152+
/// Represents an event where RX Data is Ready to `RF24::read()`.
153+
bool rx_dr : 1;
154+
155+
/**
156+
* @brief Convert this struct to a human understandable string.
157+
*
158+
* ```cpp
159+
* char buf[69] = {0};
160+
* StatusFlags flags;
161+
* flags.toString(buf);
162+
* ```
163+
*
164+
* Afterward, printing the string in `buf` should read something similar to:
165+
*
166+
* > rx_dr: false, tx_ds: false, tx_df: false, rx_pipe: 7, tx_full: false
167+
*
168+
* @param[out] buf The string buffer into which the StatusFlags description is stored.
169+
* This buffer needs to be at least 69 bytes long.
170+
* @returns The amount of bytes altered in the given `buf` parameter.
171+
*/
172+
int toString(char* buf) const;
173+
174+
/// An explicit default initializer for compatibility with C++11 (or newer) standards.
175+
/// @see Details about `StatusFlags::toString()` show an example output of default values.
176+
StatusFlags() : tx_full(false), rx_pipe(7), tx_df(false), tx_ds(false), rx_dr(false) {};
177+
};
178+
131179
/**
132180
* @}
133181
* @brief Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver
@@ -1162,6 +1210,78 @@ class RF24
11621210
*/
11631211
void whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready);
11641212

1213+
/**
1214+
* Clear all of the StatusFlags that caused an interrupt event.
1215+
*
1216+
* @remark This function is similar to `whatHappened()` because it also returns the
1217+
* StatusFlags that caused the interrupt event. However, this function returns
1218+
* a 1-byte bit-field struct (@ref StatusFlags) instead of bit-banging 3 1-byte booleans
1219+
* passed by reference.
1220+
*
1221+
* @note When used in an ISR (Interrupt Service routine), there is a chance that the
1222+
* @ref StatusFlags::rx_pipe information is inaccurate. See available(uint8_t*) (or the
1223+
* datasheet) for more detail.
1224+
*
1225+
* @ingroup StatusFlags
1226+
*/
1227+
StatusFlags clearStatusFlags();
1228+
1229+
/**
1230+
* Clear the specified flags.
1231+
*
1232+
* If any of the following flags are `true`, then the flag will be reset:
1233+
*
1234+
* - @ref StatusFlags::rx_dr
1235+
* - @ref StatusFlags::tx_ds
1236+
* - @ref StatusFlags::tx_df
1237+
*
1238+
* @ingroup StatusFlags
1239+
*/
1240+
void clearStatusFlags(StatusFlags& flags);
1241+
1242+
/**
1243+
* Set which flags shall be reflected on the radio's IRQ pin.
1244+
*
1245+
* This is similar to maskIRQ(), but with a more intuitive API.
1246+
*
1247+
* @param flags The configuration of the StatusFlags to influence the radio's IRQ pin.
1248+
*
1249+
* If any of the following `flags` are `true`, then the flag's corresponding event will
1250+
* trigger the IRQ pin active HIGH:
1251+
*
1252+
* - @ref StatusFlags::rx_dr
1253+
* - @ref StatusFlags::tx_ds
1254+
* - @ref StatusFlags::tx_df
1255+
*
1256+
* @ingroup StatusFlags
1257+
*/
1258+
void setStatusFlags(StatusFlags flags);
1259+
1260+
/**
1261+
* Get the latest STATUS byte returned from the last SPI transaction.
1262+
*
1263+
* @note This does not actually perform any SPI transaction with the radio.
1264+
* Use `RF24::update()` instead to get a fresh copy of the StatusFlags at
1265+
* the slight cost of performance.
1266+
*
1267+
* @param[out] flags The reference data into which the StatusFlags data is stored.
1268+
*
1269+
* In the python wrapper, this function takes no argument and instead
1270+
* returns an instance of StatusFlags.
1271+
*
1272+
* @ingroup StatusFlags
1273+
*/
1274+
void getStatusFlags(StatusFlags& flags);
1275+
1276+
/**
1277+
* Get an updated STATUS byte from the radio.
1278+
*
1279+
* @returns The StatusFlags fetched directly from the radio.
1280+
*
1281+
* @ingroup StatusFlags
1282+
*/
1283+
StatusFlags update();
1284+
11651285
/**
11661286
* Non-blocking write to the open writing pipe used for buffered writes
11671287
*

cspell.config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ words:
225225
- Quigg
226226
- raspi
227227
- REALPATH
228+
- repr
228229
- rpmbuild
229230
- RXADDR
230231
- rxbuff

pyRF24/pyRF24.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,31 @@ bp::tuple whatHappened_wrap(RF24& ref)
113113
return bp::make_tuple(tx_ok, tx_fail, tx_ready);
114114
}
115115

116+
StatusFlags getStatusFlags_wrap(RF24& ref)
117+
{
118+
StatusFlags flags;
119+
ref.getStatusFlags(flags);
120+
return flags;
121+
}
122+
bool get_rx_dr(const StatusFlags& ref) { return ref.rx_dr; }
123+
void set_rx_dr(StatusFlags& ref, bool value) { ref.rx_dr = value; }
124+
bool get_tx_ds(const StatusFlags& ref) { return ref.tx_ds; }
125+
void set_tx_ds(StatusFlags& ref, bool value) { ref.tx_ds = value; }
126+
bool get_tx_df(const StatusFlags& ref) { return ref.tx_df; }
127+
void set_tx_df(StatusFlags& ref, bool value) { ref.tx_df = value; }
128+
bool tx_full_wrap(const StatusFlags& ref) { return ref.tx_full; }
129+
uint8_t rx_pipe_wrap(const StatusFlags& ref) { return ref.rx_pipe; }
130+
std::string reprStatusFlags(StatusFlags& self)
131+
{
132+
char* buf = new char[69];
133+
self.toString(buf);
134+
std::string result = "<StatusFlags ";
135+
result += buf;
136+
result += ">";
137+
delete[] buf;
138+
return result;
139+
}
140+
116141
bp::tuple available_wrap(RF24& ref)
117142
{
118143
bool result;
@@ -287,6 +312,14 @@ BOOST_PYTHON_MODULE(RF24)
287312
.value("RF24_FIFO_INVALID", RF24_FIFO_INVALID)
288313
.export_values();
289314

315+
bp::class_<StatusFlags>("StatusFlags", bp::init<>())
316+
.add_property("rx_dr", &get_rx_dr, &set_rx_dr)
317+
.add_property("tx_ds", &get_tx_ds, &set_tx_ds)
318+
.add_property("tx_df", &get_tx_df, &set_tx_df)
319+
.add_property("tx_full", &tx_full_wrap)
320+
.add_property("rx_pipe", &rx_pipe_wrap)
321+
.def("__repr__", &reprStatusFlags);
322+
290323
// ******************** RF24 class **************************
291324
bp::class_<RF24>("RF24", bp::init<uint16_t, uint16_t>((bp::arg("_cepin"), bp::arg("_cspin"))))
292325
#if defined(RF24_LINUX) && !defined(MRAA)
@@ -348,6 +381,11 @@ BOOST_PYTHON_MODULE(RF24)
348381
.def("setRadiation", &RF24::setRadiation)
349382
.def("txStandBy", (bool(::RF24::*)(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1(bp::args("timeout", "startTx")))
350383
.def("whatHappened", &whatHappened_wrap)
384+
.def("setStatusFlags", &RF24::setStatusFlags, (bp::arg("flags")))
385+
.def("clearStatusFlags", (StatusFlags(::RF24::*)(void))(&RF24::clearStatusFlags))
386+
.def("clearStatusFlags", (void(::RF24::*)(StatusFlags&))(&RF24::clearStatusFlags), (bp::arg("flags")))
387+
.def("getStatusFlags", &getStatusFlags_wrap)
388+
.def("update", &RF24::update)
351389
.def("startConstCarrier", &RF24::startConstCarrier, (bp::arg("level"), bp::arg("channel")))
352390
.def("stopConstCarrier", &RF24::stopConstCarrier)
353391
.def("write", &write_wrap1, (bp::arg("buf")))

0 commit comments

Comments
 (0)