Created a non-blocking write and an example for how to use it.
This commit is contained in:
parent
bb37e88094
commit
d3fff68a7c
33
RF24.cpp
33
RF24.cpp
|
@ -356,17 +356,8 @@ boolean RF24::write( const void* buf, uint8_t len )
|
||||||
{
|
{
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
// Transmitter power-up
|
// Begin the write
|
||||||
write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
|
startWrite(buf,len);
|
||||||
delay(2);
|
|
||||||
|
|
||||||
// Send the payload
|
|
||||||
write_payload( buf, len );
|
|
||||||
|
|
||||||
// Allons!
|
|
||||||
ce(HIGH);
|
|
||||||
delayMicroseconds(15);
|
|
||||||
ce(LOW);
|
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
// At this point we could return from a non-blocking write, and then call
|
// At this point we could return from a non-blocking write, and then call
|
||||||
|
@ -379,7 +370,7 @@ boolean RF24::write( const void* buf, uint8_t len )
|
||||||
uint8_t observe_tx;
|
uint8_t observe_tx;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint32_t sent_at = millis();
|
uint32_t sent_at = millis();
|
||||||
const uint32_t timeout = 100; //ms to wait for timeout
|
const uint32_t timeout = 500; //ms to wait for timeout
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
status = read_register(OBSERVE_TX,&observe_tx,1);
|
status = read_register(OBSERVE_TX,&observe_tx,1);
|
||||||
|
@ -420,6 +411,22 @@ boolean RF24::write( const void* buf, uint8_t len )
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
void RF24::startWrite( const void* buf, uint8_t len )
|
||||||
|
{
|
||||||
|
// Transmitter power-up
|
||||||
|
write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
|
||||||
|
delay(2);
|
||||||
|
|
||||||
|
// Send the payload
|
||||||
|
write_payload( buf, len );
|
||||||
|
|
||||||
|
// Allons!
|
||||||
|
ce(HIGH);
|
||||||
|
delayMicroseconds(15);
|
||||||
|
ce(LOW);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
||||||
|
@ -507,6 +514,8 @@ void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready)
|
||||||
tx_ok = status & _BV(TX_DS);
|
tx_ok = status & _BV(TX_DS);
|
||||||
tx_fail = status & _BV(MAX_RT);
|
tx_fail = status & _BV(MAX_RT);
|
||||||
rx_ready = status & _BV(RX_DR);
|
rx_ready = status & _BV(RX_DR);
|
||||||
|
|
||||||
|
//print_status(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
18
RF24.h
18
RF24.h
|
@ -252,9 +252,6 @@ public:
|
||||||
* getPayloadSize(). However, you can write less, and the remainder
|
* getPayloadSize(). However, you can write less, and the remainder
|
||||||
* will just be filled with zeroes.
|
* will just be filled with zeroes.
|
||||||
*
|
*
|
||||||
* @todo Write a non-blocking write to support users who want to
|
|
||||||
* check on progress separately or use an interrupt.
|
|
||||||
*
|
|
||||||
* @param buf Pointer to the data to be sent
|
* @param buf Pointer to the data to be sent
|
||||||
* @param len Number of bytes to be sent
|
* @param len Number of bytes to be sent
|
||||||
* @return True if the payload was delivered successfully false if not
|
* @return True if the payload was delivered successfully false if not
|
||||||
|
@ -403,6 +400,21 @@ public:
|
||||||
*/
|
*/
|
||||||
boolean available(uint8_t* pipe_num);
|
boolean available(uint8_t* pipe_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-blocking write to the open writing pipe
|
||||||
|
*
|
||||||
|
* Just like write(), but it returns immediately. To find out what happened
|
||||||
|
* to the send, catch the IRQ and then call whatHappened().
|
||||||
|
*
|
||||||
|
* @see write()
|
||||||
|
* @see whatHappened()
|
||||||
|
*
|
||||||
|
* @param buf Pointer to the data to be sent
|
||||||
|
* @param len Number of bytes to be sent
|
||||||
|
* @return True if the payload was delivered successfully false if not
|
||||||
|
*/
|
||||||
|
void startWrite( const void* buf, uint8_t len );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable custom payloads on the acknowledge packets
|
* Enable custom payloads on the acknowledge packets
|
||||||
*
|
*
|
||||||
|
|
|
@ -7,12 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example of using Ack Payloads
|
* Example of using interrupts
|
||||||
*
|
*
|
||||||
* This is an example of how to do two-way communication without changing
|
* This is an example of how to user interrupts to interact with the radio.
|
||||||
* transmit/receive modes. Here, a payload is set to the transmitter within
|
* It builds on the pingpair_pl example, and uses ack payloads.
|
||||||
* the Ack packet of each transmission. Note that the payload is set BEFORE
|
|
||||||
* the sender's message arrives.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
@ -58,6 +56,13 @@ const char* role_friendly_name[] = { "invalid", "Sender", "Receiver"};
|
||||||
// The role of the current running sketch
|
// The role of the current running sketch
|
||||||
role_e role;
|
role_e role;
|
||||||
|
|
||||||
|
// Message buffer to allow interrupt handler to print messages
|
||||||
|
bool message_ready;
|
||||||
|
char message[100];
|
||||||
|
|
||||||
|
// Interrupt handler, check the radio because we got an IRQ
|
||||||
|
void check_radio(void);
|
||||||
|
|
||||||
void setup(void)
|
void setup(void)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -81,9 +86,15 @@ void setup(void)
|
||||||
|
|
||||||
Serial.begin(57600);
|
Serial.begin(57600);
|
||||||
printf_begin();
|
printf_begin();
|
||||||
printf("\n\rRF24/examples/pingpair_pl/\n\r");
|
printf("\n\rRF24/examples/pingpair_irq/\n\r");
|
||||||
printf("ROLE: %s\n\r",role_friendly_name[role]);
|
printf("ROLE: %s\n\r",role_friendly_name[role]);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Attach interrupt handler to interrupt #0 (using pin 2)
|
||||||
|
//
|
||||||
|
|
||||||
|
attachInterrupt(0, check_radio, FALLING);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup and configure rf radio
|
// Setup and configure rf radio
|
||||||
//
|
//
|
||||||
|
@ -93,6 +104,9 @@ void setup(void)
|
||||||
// We will be using the Ack Payload feature, so please enable it
|
// We will be using the Ack Payload feature, so please enable it
|
||||||
radio.enableAckPayload();
|
radio.enableAckPayload();
|
||||||
|
|
||||||
|
// Pick a high channel
|
||||||
|
radio.setChannel(110);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Open pipes to other nodes for communication
|
// Open pipes to other nodes for communication
|
||||||
//
|
//
|
||||||
|
@ -123,9 +137,10 @@ void setup(void)
|
||||||
radio.printDetails();
|
radio.printDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t message_count = 0;
|
||||||
|
|
||||||
void loop(void)
|
void loop(void)
|
||||||
{
|
{
|
||||||
static uint32_t message_count = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sender role. Repeatedly send the current time
|
// Sender role. Repeatedly send the current time
|
||||||
|
@ -133,17 +148,10 @@ void loop(void)
|
||||||
|
|
||||||
if (role == role_sender)
|
if (role == role_sender)
|
||||||
{
|
{
|
||||||
// Take the time, and send it. This will block until complete
|
// Take the time, and send it.
|
||||||
unsigned long time = millis();
|
unsigned long time = millis();
|
||||||
printf("Now sending %lu...",time);
|
printf("Now sending %lu...",time);
|
||||||
radio.write( &time, sizeof(unsigned long) );
|
radio.startWrite( &time, sizeof(unsigned long) );
|
||||||
|
|
||||||
if ( radio.isAckPayloadAvailable() )
|
|
||||||
{
|
|
||||||
radio.read(&message_count,sizeof(message_count));
|
|
||||||
printf("Ack: [%lu] ",message_count);
|
|
||||||
}
|
|
||||||
printf("OK\n\r");
|
|
||||||
|
|
||||||
// Try again soon
|
// Try again soon
|
||||||
delay(2000);
|
delay(2000);
|
||||||
|
@ -176,5 +184,47 @@ void loop(void)
|
||||||
++message_count;
|
++message_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Message handler. Display messages from the interrupt
|
||||||
|
//
|
||||||
|
if ( message_ready )
|
||||||
|
{
|
||||||
|
message_ready = false;
|
||||||
|
Serial.println(message);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_radio(void)
|
||||||
|
{
|
||||||
|
// What happened?
|
||||||
|
bool tx,fail,rx;
|
||||||
|
radio.whatHappened(tx,fail,rx);
|
||||||
|
|
||||||
|
char *messageptr = message;
|
||||||
|
message_ready = true;
|
||||||
|
sprintf(message,"Unknown");
|
||||||
|
|
||||||
|
if ( tx )
|
||||||
|
{
|
||||||
|
radio.powerDown();
|
||||||
|
sprintf(messageptr,"Send:OK ");
|
||||||
|
messageptr += strlen(messageptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fail )
|
||||||
|
{
|
||||||
|
radio.powerDown();
|
||||||
|
sprintf(messageptr,"Send:Failed ");
|
||||||
|
messageptr += strlen(messageptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rx )
|
||||||
|
{
|
||||||
|
radio.read(&message_count,sizeof(message_count));
|
||||||
|
sprintf(messageptr,"Ack:%lu ",message_count);
|
||||||
|
messageptr += strlen(messageptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
||||||
|
|
Loading…
Reference in New Issue