Commit 6bdbdadd authored by Daniel Friesel's avatar Daniel Friesel
Browse files

RF24: Add functions required for reading

parent defe3e47
Loading
Loading
Loading
Loading
+157 −2
Original line number Diff line number Diff line
@@ -22,8 +22,42 @@ private:
	uint8_t addr_width;				  /**< The address width to use - 3,4 or 5 bytes. */
	uint32_t txRxDelay;				  /**< Var for adjusting delays depending on datarate */

	/**
   * Write a single byte to a register
   *
   * @param reg Which register. Use constants from nRF24L01.h
   * @param value The new value to write
   * @return Current value of status register
   */
	uint8_t writeRegister(uint8_t reg, uint8_t value);

	/**
   * Write a chunk of data to a register
   *
   * @param reg Which register. Use constants from nRF24L01.h
   * @param buf Where to get the data
   * @param len How many bytes of data to transfer
   * @return Current value of status register
   */
	uint8_t writeRegister(uint8_t reg, const uint8_t *buf, uint8_t len);

	/**
   * Read single byte from a register
   *
   * @param reg Which register. Use constants from nRF24L01.h
   * @return Current value of register @p reg
   */
	uint8_t readRegister(uint8_t reg);

	/**
   * Write the transmit payload
   *
   * The size of data written is the fixed payload size, see getPayloadSize()
   *
   * @param buf Where to get the data
   * @param len Number of bytes to be sent
   * @return Current value of status register
   */
	uint8_t writePayload(const void *buf, uint8_t data_len, const uint8_t writeType);

	inline void csnHigh()
@@ -46,7 +80,7 @@ private:
	}

public:
	Nrf24l01() : payload_size(32), dynamic_payloads_enabled(false), addr_width(5) {}
	Nrf24l01() : payload_size(32), dynamic_payloads_enabled(false), addr_width(5) { pipe0_reading_address[0] = 0; }

	/**
		 * Power Amplifier level.
@@ -231,9 +265,130 @@ public:
   * are enabled.  See the datasheet for details.
   */
	void toggleFeatures(void);

	/**
   * Be sure to call openWritingPipe() first to set the destination
   * of where to write to.
   *
   * This blocks until the message is successfully acknowledged by
   * the receiver or the timeout/retransmit maxima are reached.  In
   * the current configuration, the max delay here is 60-70ms.
   *
   * The maximum size of data written is the fixed payload size, see
   * getPayloadSize().  However, you can write less, and the remainder
   * will just be filled with zeroes.
   *
   * TX/RX/RT interrupt flags will be cleared every time write is called
   *
   * @param buf Pointer to the data to be sent
   * @param len Number of bytes to be sent
   *
   * @code
   * radio.stopListening();
   * radio.write(&data,sizeof(data));
   * @endcode
   * @return True if the payload was delivered successfully false if not
   */
	uint8_t write(const void *buf, uint8_t len, bool blocking);

	/**
   * Start listening on the pipes opened for reading.
   *
   * 1. Be sure to call openReadingPipe() first.
   * 2. Do not call write() while in this mode, without first calling stopListening().
   * 3. Call available() to check for incoming traffic, and read() to get it.
   *
   * @code
   * Open reading pipe 1 using address CCCECCCECC
   *
   * byte address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC };
   * radio.openReadingPipe(1,address);
   * radio.startListening();
   * @endcode
   */
	void startListening(void);

	/**
   * Stop listening for incoming messages, and switch to transmit mode.
   *
   * Do this before calling write().
   * @code
   * radio.stopListening();
   * radio.write(&data,sizeof(data));
   * @endcode
   */
	void stopListening(void);

	/**
   * Check whether there are bytes available to be read
   * @code
   * if(radio.available()){
   *   radio.read(&data,sizeof(data));
   * }
   * @endcode
   * @return True if there is a payload available, false if none is
   */
	bool available(void);

	/**
   * Read the available payload
   *
   * The size of data read is the fixed payload size, see getPayloadSize()
   *
   * @note I specifically chose 'void*' as a data type to make it easier
   * for beginners to use.  No casting needed.
   *
   * @note No longer boolean. Use available to determine if packets are
   * available. Interrupt flags are now cleared during reads instead of
   * when calling available().
   *
   * @param buf Pointer to a buffer where the data should be written
   * @param len Maximum number of bytes to read into the buffer
   *
   * @code
   * if(radio.available()){
   *   radio.read(&data,sizeof(data));
   * }
   * @endcode
   * @return No return value. Use available().
   */
	void read(void *buf, uint8_t len);

	/**
   * Open a pipe for reading
   *
   * Up to 6 pipes can be open for reading at once.  Open all the required
   * reading pipes, and then call startListening().
   *
   * @see openWritingPipe
   * @see setAddressWidth
   *
   * @note Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically
   * only store a single byte, borrowing up to 4 additional bytes from pipe #1 per the
   * assigned address width.
   * @warning Pipes 1-5 should share the same address, except the first byte.
   * Only the first byte in the array should be unique, e.g.
   * @code
   *   uint8_t addresses[][6] = {"1Node","2Node"};
   *   openReadingPipe(1,addresses[0]);
   *   openReadingPipe(2,addresses[1]);
   * @endcode
   *
   * @warning Pipe 0 is also used by the writing pipe.  So if you open
   * pipe 0 for reading, and then startListening(), it will overwrite the
   * writing pipe.  Ergo, do an openWritingPipe() again before write().
   *
   * @param number Which pipe# to open, 0-5.
   * @param address The 24, 32 or 40 bit address of the pipe to open.
   */
	void openReadingPipe(uint8_t number, const uint8_t *address);

	/**
   * Close a pipe after it has been previously opened.
   * Can be safely called without having previously opened a pipe.
   * @param pipe Which pipe # to close, 0-5.
   */
	void closeReadingPipe(uint8_t pipe);

	uint8_t getStatus();
};

+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,9 @@ void loop(void)
	kout << "status: " << hex << nrf24l01.getStatus() << endl;
	kout << "write: ";
	kout << nrf24l01.write("foo", 3, true) << endl;
	nrf24l01.startListening();
	arch.delay_ms(10);
	nrf24l01.stopListening();
}

int main(void)
+101 −0
Original line number Diff line number Diff line
@@ -18,6 +18,16 @@
#error makeflag nrf24l01_cs_pin required
#endif

static const uint8_t child_pipe[] =
	{
		RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5};
static const uint8_t child_payload_size[] =
	{
		RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5};
static const uint8_t child_pipe_enable[] =
	{
		ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5};

void Nrf24l01::setup()
{
	spi.setup();
@@ -181,6 +191,85 @@ uint8_t Nrf24l01::write(const void *buf, uint8_t len, bool blocking)
	return 1;
}

void Nrf24l01::startListening(void)
{
	writeRegister(NRF_CONFIG, readRegister(NRF_CONFIG) | (1 << PRIM_RX));
	writeRegister(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT));
	gpio.write(NRF24L01_EN_PIN, 1);

	// Restore the pipe0 adddress, if exists
	if (pipe0_reading_address[0] > 0)
	{
		writeRegister(RX_ADDR_P0, pipe0_reading_address, addr_width);
	}
	else
	{
		closeReadingPipe(0);
	}

	if (readRegister(FEATURE) & (1 << EN_ACK_PAY))
	{
		flushTx();
	}
}

void Nrf24l01::stopListening(void)
{
	gpio.write(NRF24L01_EN_PIN, 0);

	arch.delay_us(txRxDelay);

	if (readRegister(FEATURE) & (1 << EN_ACK_PAY))
	{
		arch.delay_us(txRxDelay); //200
		flushTx();
	}
	//flush_rx();
	writeRegister(NRF_CONFIG, (readRegister(NRF_CONFIG)) & ~(1 << PRIM_RX));

	writeRegister(EN_RXADDR, readRegister(EN_RXADDR) | (1 << child_pipe_enable[0])); // Enable RX on pipe0
}

void Nrf24l01::openReadingPipe(uint8_t child, const uint8_t *address)
{
	// If this is pipe 0, cache the address.  This is needed because
	// openWritingPipe() will overwrite the pipe 0 address, so
	// startListening() will have to restore it.
	if (child == 0)
	{
		pipe0_reading_address[0] = address[0];
		pipe0_reading_address[1] = address[1];
		pipe0_reading_address[2] = address[2];
		pipe0_reading_address[3] = address[3];
		pipe0_reading_address[4] = address[4];
	}
	if (child <= 6)
	{
		// For pipes 2-5, only write the LSB
		if (child < 2)
		{
			writeRegister(child_pipe[child], address, addr_width);
		}
		else
		{
			writeRegister(child_pipe[child], address, 1);
		}
		writeRegister(child_payload_size[child], payload_size);

		// Note it would be more efficient to set all of the bits for all open
		// pipes at once.  However, I thought it would make the calling code
		// more simple to do it this way.
		writeRegister(EN_RXADDR, readRegister(EN_RXADDR) | (1 << child_pipe_enable[child]));
	}
}

/****************************************************************************/

void Nrf24l01::closeReadingPipe(uint8_t pipe)
{
	writeRegister(EN_RXADDR, readRegister(EN_RXADDR) & ~(1 << child_pipe_enable[pipe]));
}

void Nrf24l01::maskIRQ(bool tx, bool fail, bool rx)
{

@@ -214,6 +303,18 @@ uint8_t Nrf24l01::readRegister(uint8_t reg)
	return rxbuf[1];
}

uint8_t Nrf24l01::writeRegister(uint8_t reg, const uint8_t *buf, uint8_t len)
{
	txbuf[0] = W_REGISTER | (REGISTER_MASK & reg);

	beginTransaction();
	spi.xmit(1, txbuf, 1, rxbuf);
	spi.xmit(len, (unsigned char *)buf, 0, NULL);
	endTransaction();

	return rxbuf[0];
}

uint8_t Nrf24l01::writeRegister(uint8_t reg, uint8_t value)
{
	txbuf[0] = W_REGISTER | (REGISTER_MASK & reg);