Commit a426c8d5 authored by Daniel Friesel's avatar Daniel Friesel
Browse files

Working Nrf24 ping-pong

parent 946db125
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -60,9 +60,16 @@ endif

ifneq ($(findstring nrf24l01,${drivers}), )
	CXX_TARGETS += src/driver/nrf24l01.cc
	ifeq (${arch}, msp430fr5994lp)
	nrf24l01_cs_pin ?= p1_3
	nrf24l01_en_pin ?= p6_2
	nrf24l01_irq_pin ?= p8_3
	endif
	ifeq (${arch}, msp430fr5969lp)
		nrf24l01_en_pin ?= p4_3
		nrf24l01_cs_pin ?= p2_4
		nrf24l01_irq_pin ?= p1_5
	endif
	COMMON_FLAGS += -DDRIVER_NRF24L01
	COMMON_FLAGS += -DNRF24L01_EN_PIN=GPIO::${nrf24l01_en_pin}
	COMMON_FLAGS += -DNRF24L01_CS_PIN=GPIO::${nrf24l01_cs_pin}
+223 −117
Original line number Diff line number Diff line
@@ -60,6 +60,17 @@ private:
   */
   uint8_t writePayload(const void *buf, uint8_t data_len, const uint8_t writeType);

     /**
   * Read the receive payload
   *
   * The size of data read is the fixed payload size, see getPayloadSize()
   *
   * @param buf Where to put the data
   * @param len Maximum number of bytes to read
   * @return Current value of status register
   */
  uint8_t readPayload(void* buf, uint8_t len);

   inline void csnHigh()
   {
      gpio.write(NRF24L01_CS_PIN, 1);
@@ -147,6 +158,16 @@ public:
   */
   void powerUp(void);

   /**
   * Initialize the radio. Open a reading pipe at addr and set channel.
   * 
   * @param addr Address at which the reading pipe will be opened.
   * @param channel that will be used, can be 0-125. Channel bandwidth = 1 MHz starting at 2400 Mhz.
   * @return 0: success, -1: invalid channel, -2 error setting channel, -3: other error.
   * 
   */
   //int init(uint8_t addr, uint8_t channel, rf24_datarate_e datarate = RF24_2MBPS);

   /**
   * Empty the transmit buffer. This is generally not required in standard operation.
   * May be required in specific cases after stopListening() , if operating at 250KBPS data rate.
@@ -314,6 +335,17 @@ public:
   */
   void setAutoAck(uint8_t pipe, bool enable);

   /**
   * Enable custom payloads on the acknowledge packets
   *
   * Ack payloads are a handy way to return data back to senders without
   * manually changing the radio modes on both units.
   *
   * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call
   * enableDynamicPayloads() to enable on all pipes.
   */
   void enableAckPayload(void);

   /**
   * Be sure to call openWritingPipe() first to set the destination
   * of where to write to.
@@ -378,6 +410,24 @@ public:
   */
   bool available(void);

   /**
   * Test whether there are bytes available to be read in the
   * FIFO buffers.
   *
   * @param[out] pipe_num Which pipe has the payload available
   *
   * @code
   * uint8_t pipeNum;
   * if(radio.available(&pipeNum)){
   *   radio.read(&data,sizeof(data));
   *   Serial.print("Got data on pipe");
   *   Serial.println(pipeNum);
   * }
   * @endcode
   * @return True if there is a payload available, false if none is
   */
   bool available(uint8_t *pipe_num);

   /**
   * Read the available payload
   *
@@ -438,6 +488,62 @@ public:
   */
   void closeReadingPipe(uint8_t pipe);

   /**
   * New: Open a pipe for writing via byte array. Old addressing format retained
   * for compatibility.
   *
   * Only one writing pipe can be open at once, but you can change the address
   * you'll write to. Call stopListening() first.
   *
   * Addresses are assigned via a byte array, default is 5 byte address length
s   *
   * @code
   *   uint8_t addresses[][6] = {"1Node","2Node"};
   *   radio.openWritingPipe(addresses[0]);
   * @endcode
   * @code
   *  uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC };
   *  radio.openWritingPipe(address);
   *  address[0] = 0x33;
   *  radio.openReadingPipe(1,address);
   * @endcode
   * @see setAddressWidth
   *
   * @param address The address of the pipe to open. Coordinate these pipe
   * addresses amongst nodes on the network.
   */

   void openWritingPipe(const uint8_t *address);

     /**
   * Test whether there was a carrier on the line for the
   * previous listening period.
   *
   * Useful to check for interference on the current channel.
   *
   * @return true if was carrier, false if not
   */
  bool testCarrier(void);

  /**
   * Test whether a signal (carrier or otherwise) greater than
   * or equal to -64dBm is present on the channel. Valid only
   * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier().
   *
   * Useful to check for interference on the current channel and
   * channel hopping strategies.
   *
   * @code
   * bool goodSignal = radio.testRPD();
   * if(radio.available()){
   *    Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" );
   *    radio.read(0,0);
   * }
   * @endcode
   * @return true if signal => -64dBm, false if not
   */
  bool testRPD(void);

   uint8_t getStatus();
};

+32 −9
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
	counter.stop(); \
	kout << endl << index << " :: " << dec << counter.value << "/" << counter.overflow << endl;

char buf[32];

void loop(void)
{
	gpio.led_toggle(1);
@@ -33,17 +35,22 @@ void loop(void)
	}
	kout << endl;

#ifdef MULTIPASS_ARCH_msp430fr5969lp
	kout << "write: ";
	nrf24l01.setRetries(0, 0);
	nrf24l01.setDynamicPayloads(false);
	nrf24l01.setDynamicAck(false);
	TIMEIT("blocking write(3)", nrf24l01.write("foo", 3, true, true));
	TIMEIT("blocking write(10)", nrf24l01.write("123456789", 10, true, true));
	TIMEIT("blocking write(20)", nrf24l01.write("123456789123456789", 20, true, true));
	//TIMEIT("blocking write(30)", nrf24l01.write("123456789123456789123456789", 30, true, true));
	nrf24l01.startListening();
	arch.delay_ms(10);
	//kout << nrf24l01.write("foo", 3, true, true) << " ";
	//kout << nrf24l01.write("123456789", 10, true, true) << " ";
	kout << nrf24l01.write("123456789123456789", 20, true, true) << endl;
#else
	kout << "carrier " << nrf24l01.testCarrier() << " / RPD " << nrf24l01.testRPD();
	if (nrf24l01.available()) {
		nrf24l01.read(buf, 32);
		kout << " / data = " << buf << endl;
	} else {
		kout << " / no data" << endl;
	}
	nrf24l01.stopListening();
	nrf24l01.startListening();
#endif
}

int main(void)
@@ -56,6 +63,22 @@ int main(void)
	nrf24l01.setup();
	kout << " OK" << endl;

	kout << "nrf24l01 configure ...";
    unsigned char addr[5] = {0, 'D', 'E', 'R', 'F'};
	//nrf24l01.setAutoAck(1);
	//nrf24l01.enableAckPayload();
	nrf24l01.setDynamicPayloads(true);
	nrf24l01.setPALevel(Nrf24l01::RF24_PA_MAX);
	nrf24l01.setChannel(25);
	nrf24l01.setDataRate(Nrf24l01::RF24_2MBPS);
#ifdef MULTIPASS_ARCH_msp430fr5994lp
	nrf24l01.openReadingPipe(1, addr);
	nrf24l01.startListening();
#else
	nrf24l01.openWritingPipe((const uint8_t*)addr);
#endif
	kout << " OK" << endl;

	gpio.led_on(0);
	arch.idle_loop();

+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ build/system.hex: build/system.elf
program: build/system.hex
	${QUIET}LD_LIBRARY_PATH=${MSP430_FLASHER_DIR} \
	${MSP430_FLASHER_DIR}/MSP430Flasher \
	-i ${DEBUG_PORT} \
	-i /dev/${DEBUG_PORT} \
	-w build/system.hex -v -g -z '[VCC]'

arch_clean:
+175 −24
Original line number Diff line number Diff line
@@ -77,7 +77,41 @@ void Nrf24l01::setup()
	// PTX should use only 22uA of power
	writeRegister(NRF_CONFIG, (readRegister(NRF_CONFIG)) & ~(1 << PRIM_RX));
}
/*
int Nrf24l01::init(uint8_t addr, uint8_t channel, rf24_datarate_e datarate){
    
  if(channel > 125){
   return -1; 
  }
  
  unsigned char node_addr[5] = {addr, 'x', 'S', 'D', 'P'};
  
  setAutoAck(1);
  enableAckPayload();
  maskIRQ(true, true, false);
  enableDynamicPayloads();  
  setPALevel(RF24_PA_MAX);
  setChannel(channel);
  setDataRate(datarate);
  openWritingPipe((const uint8_t*)GATEWAY_NAME); // GATEWAY_NAME is defined in the MSP430FR5969 RF24_arch_config.h
  currentWritingPipe = 0;
  openReadingPipe(1, node_addr);
#ifdef CONFIG_Apps_SolarDoorplate_PacketHandler
  node_addr[0] = CONFIG_PACKETHANDLER_BROADCAST_ID;
  openReadingPipe(2, node_addr);
#endif  
  if(getChannel() != channel){
   return -2; 
  }
  
  if(getDataRate() != datarate){
   return -3; 
  }
  
  return 0;
  
}
*/
//Power up now. Radio will not power down unless instructed by MCU for config changes etc.
void Nrf24l01::powerUp(void)
{
@@ -172,6 +206,25 @@ void Nrf24l01::toggleFeatures(void)
	endTransaction();
}

void Nrf24l01::enableAckPayload(void)
{
	//
	// enable ack payload and dynamic payload features
	//

	//toggle_features();
	writeRegister(FEATURE, readRegister(FEATURE) | (1 << EN_ACK_PAY) | (1 << EN_DPL));

	//IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE)));

	//
	// Enable dynamic payload on pipes 0 & 1
	//

	writeRegister(DYNPD, readRegister(DYNPD) | (1 << DPL_P1) | (1 << DPL_P0));
	dynamic_payloads_enabled = true;
}

void Nrf24l01::setChannel(uint8_t channel)
{
	writeRegister(RF_CH, rf24_min(channel, 125));
@@ -182,16 +235,17 @@ uint8_t Nrf24l01::write(const void *buf, uint8_t len, bool await_ack, bool block
	writePayload(buf, len, await_ack ? W_TX_PAYLOAD : W_TX_PAYLOAD_NO_ACK);

	gpio.write(NRF24L01_EN_PIN, 1);
	arch.delay_us(10);
	gpio.write(NRF24L01_EN_PIN, 0);

	if (!blocking)
	{
		arch.delay_us(10);
		gpio.write(NRF24L01_EN_PIN, 0);
		return 0;
	}

	while (!(getStatus() & ((1 << TX_DS) | (1 << MAX_RT))))
		;
	gpio.write(NRF24L01_EN_PIN, 1);
	uint8_t status = writeRegister(NRF_STATUS, ((1 << TX_DS) | (1 << MAX_RT)));

	if (status & (1 << MAX_RT))
@@ -241,6 +295,41 @@ void Nrf24l01::stopListening(void)
	writeRegister(EN_RXADDR, readRegister(EN_RXADDR) | (1 << child_pipe_enable[0])); // Enable RX on pipe0
}

bool Nrf24l01::available(void)
{
	return available(NULL);
}

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

bool Nrf24l01::available(uint8_t *pipe_num)
{
	if (!(readRegister(FIFO_STATUS) & (1 << RX_EMPTY)))
	{

		// If the caller wants the pipe number, include that
		if (pipe_num)
		{
			uint8_t status = getStatus();
			*pipe_num = (status >> RX_P_NO) & 0b111;
		}
		return 1;
	}
	return 0;
}

bool Nrf24l01::testCarrier(void)
{
	return (readRegister(CD) & 1);
}

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

bool Nrf24l01::testRPD(void)
{
	return (readRegister(RPD) & 1);
}

void Nrf24l01::openReadingPipe(uint8_t child, const uint8_t *address)
{
	// If this is pipe 0, cache the address.  This is needed because
@@ -281,6 +370,29 @@ void Nrf24l01::closeReadingPipe(uint8_t pipe)
	writeRegister(EN_RXADDR, readRegister(EN_RXADDR) & ~(1 << child_pipe_enable[pipe]));
}

/****************************************************************************/
void Nrf24l01::openWritingPipe(const uint8_t *address)
{
	// Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
	// expects it LSB first too, so we're good.

	writeRegister(RX_ADDR_P0, address, addr_width);
	writeRegister(TX_ADDR, address, addr_width);

	//const uint8_t max_payload_size = 32;
	//write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size));
	writeRegister(RX_PW_P0, payload_size);
}

void Nrf24l01::setAddressWidth(uint8_t a_width)
{
	if (a_width -= 2)
	{
		writeRegister(SETUP_AW, a_width % 4);
		addr_width = (a_width % 4) + 2;
	}
}

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

@@ -338,6 +450,45 @@ uint8_t Nrf24l01::writeRegister(uint8_t reg, uint8_t value)
	return rxbuf[0];
}

uint8_t Nrf24l01::readPayload(void *buf, uint8_t data_len)
{
	uint8_t status;
	uint8_t *current = reinterpret_cast<uint8_t *>(buf);

	if (data_len > payload_size)
		data_len = payload_size;
	uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;

	beginTransaction();
	txbuf[0] = R_RX_PAYLOAD;
	spi.xmit(1, txbuf, 1, rxbuf);
	status = rxbuf[0];
	txbuf[0] = 0xf;
	;
	while (data_len--)
	{
		spi.xmit(1, txbuf, 1, rxbuf);
		*current++ = rxbuf[0];
	}
	while (blank_len--)
	{
		spi.xmit(1, txbuf, 1, rxbuf);
	}
	endTransaction();

	return status;
}

void Nrf24l01::read(void *buf, uint8_t len)
{

	// Fetch the payload
	readPayload(buf, len);

	//Clear the two possible interrupt flags with one command
	writeRegister(NRF_STATUS, (1 << RX_DR) | (1 << MAX_RT) | (1 << TX_DS));
}

void Nrf24l01::setDynamicPayloads(const bool enabled)
{
	if (enabled)