Created a non-blocking write and an example for how to use it.

This commit is contained in:
maniacbug 2011-07-06 20:49:59 -07:00
parent bb37e88094
commit d3fff68a7c
3 changed files with 102 additions and 31 deletions

View File

@ -356,17 +356,8 @@ boolean RF24::write( const void* buf, uint8_t len )
{
boolean result = false;
// 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);
// Begin the write
startWrite(buf,len);
// ------------
// 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 status;
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
{
status = read_register(OBSERVE_TX,&observe_tx,1);
@ -420,6 +411,22 @@ boolean RF24::write( const void* buf, uint8_t len )
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_fail = status & _BV(MAX_RT);
rx_ready = status & _BV(RX_DR);
//print_status(status);
}
/******************************************************************/

18
RF24.h
View File

@ -252,9 +252,6 @@ public:
* getPayloadSize(). However, you can write less, and the remainder
* 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 len Number of bytes to be sent
* @return True if the payload was delivered successfully false if not
@ -403,6 +400,21 @@ public:
*/
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
*

View File

@ -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
* transmit/receive modes. Here, a payload is set to the transmitter within
* the Ack packet of each transmission. Note that the payload is set BEFORE
* the sender's message arrives.
* This is an example of how to user interrupts to interact with the radio.
* It builds on the pingpair_pl example, and uses ack payloads.
*/
#include <SPI.h>
@ -58,6 +56,13 @@ const char* role_friendly_name[] = { "invalid", "Sender", "Receiver"};
// The role of the current running sketch
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)
{
//
@ -81,9 +86,15 @@ void setup(void)
Serial.begin(57600);
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]);
//
// Attach interrupt handler to interrupt #0 (using pin 2)
//
attachInterrupt(0, check_radio, FALLING);
//
// Setup and configure rf radio
//
@ -93,6 +104,9 @@ void setup(void)
// We will be using the Ack Payload feature, so please enable it
radio.enableAckPayload();
// Pick a high channel
radio.setChannel(110);
//
// Open pipes to other nodes for communication
//
@ -123,9 +137,10 @@ void setup(void)
radio.printDetails();
}
static uint32_t message_count = 0;
void loop(void)
{
static uint32_t message_count = 0;
//
// Sender role. Repeatedly send the current time
@ -133,17 +148,10 @@ void loop(void)
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();
printf("Now sending %lu...",time);
radio.write( &time, sizeof(unsigned long) );
if ( radio.isAckPayloadAvailable() )
{
radio.read(&message_count,sizeof(message_count));
printf("Ack: [%lu] ",message_count);
}
printf("OK\n\r");
radio.startWrite( &time, sizeof(unsigned long) );
// Try again soon
delay(2000);
@ -176,5 +184,47 @@ void loop(void)
++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