Nrf5 improvements (#938)

* Fix NRF5_ESB_readMessage, allways enable radio

* NRF5: fixes and improvements

- Compiles with arduino core for nRF52 (primo)
  MY_RADIO_NRF5_ESB stays unsupported with primo!

- Split ACK negation flag into
    MY_NRF5_ESB_REVERSE_ACK_TX
    MY_NRF5_ESB_REVERSE_ACK_RX

- MY_RADIO_NRF5_ESB changes to act more than NRF24

- MY_RADIO_NRF5_ESB better support for powerdown/standby

- Moved initialization from MyMainNRF5 to hwInit()
This commit is contained in:
d00616
2017-09-30 22:55:55 +02:00
committed by Henrik Ekblad
parent 9ee837199e
commit 1b1cf8ff9c
9 changed files with 159 additions and 126 deletions
+1 -5
View File
@@ -23,14 +23,10 @@
#ifndef __NRF_RADIO_H__
#define __NRF_RADIO_H__
#if !defined(ARDUINO)
#if !defined(ARDUINO_ARCH_NRF5)
#error "NRF5 Radio is not supported for this platform."
#endif
#if defined(NRF5_SOFTDEVICE)
#warning "NRF5 SoftDevice cannot be used with NRF5 Radio."
#endif
#include <nrf.h>
#include <stdint.h>
#include <stdio.h>
+76 -36
View File
@@ -70,6 +70,12 @@ static bool NRF5_ESB_initialize()
// Power on radio unit
NRF_RADIO->POWER = 1;
// Disable shorts
NRF_RADIO->SHORTS = 0;
// Disable radio
NRF_RADIO->TASKS_DISABLE = 1;
// Enable radio interrupt
NVIC_SetPriority(RADIO_IRQn, 1);
NVIC_ClearPendingIRQ(RADIO_IRQn);
@@ -80,10 +86,16 @@ static bool NRF5_ESB_initialize()
NVIC_ClearPendingIRQ(NRF5_RADIO_TIMER_IRQN);
NVIC_EnableIRQ(NRF5_RADIO_TIMER_IRQN);
// Clear events
NRF_RADIO->EVENTS_END = 0;
NRF_RADIO->EVENTS_READY = 0;
// Clear all events
NRF_RADIO->EVENTS_ADDRESS = 0;
NRF_RADIO->EVENTS_BCMATCH = 0;
NRF_RADIO->EVENTS_DEVMATCH = 0;
NRF_RADIO->EVENTS_DEVMISS = 0;
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->EVENTS_END = 0;
NRF_RADIO->EVENTS_PAYLOAD = 0;
NRF_RADIO->EVENTS_READY = 0;
NRF_RADIO->EVENTS_RSSIEND = 0;
// Disable all interrupts
NRF_RADIO->INTENCLR = (uint32_t)~0;
@@ -161,9 +173,16 @@ static bool NRF5_ESB_initialize()
TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk;
// Reset timer
NRF5_RADIO_TIMER->TASKS_CLEAR = 1;
// Reset compare events
NRF5_RADIO_TIMER->EVENTS_COMPARE[0] = 0;
NRF5_RADIO_TIMER->EVENTS_COMPARE[1] = 0;
#ifdef NRF51
for (uint8_t i=0; i<4; i++) {
#else
for (uint8_t i=0; i<6; i++) {
#endif
NRF5_RADIO_TIMER->EVENTS_COMPARE[i] = 0;
}
// Enable interrupt
NRF5_RADIO_TIMER->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
NRF5_RADIO_TIMER->INTENSET = TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos;
@@ -179,6 +198,12 @@ static bool NRF5_ESB_initialize()
// Set internal variables
radio_disabled = true;
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
intcntr_bcmatch=0;
intcntr_ready=0;
intcntr_end=0;
#endif
return true;
}
@@ -209,19 +234,24 @@ static void NRF5_ESB_powerDown()
static void NRF5_ESB_powerUp()
{
// Not needed
NRF5_ESB_initialize();
}
static void NRF5_ESB_sleep()
{
NRF5_RADIO_DEBUG(PSTR("NRF5:SLP\n"));
NRF5_ESB_powerDown();
// Disable shorts
NRF_RADIO->SHORTS = 0;
// Disable radio
NRF_RADIO->TASKS_DISABLE = 1;
}
static void NRF5_ESB_standBy()
{
NRF5_RADIO_DEBUG(PSTR("NRF5:SBY\n"));
NRF5_ESB_initialize();
NRF5_ESB_startListening();
}
static bool NRF5_ESB_sanityCheck()
@@ -274,27 +304,27 @@ static bool NRF5_ESB_isDataAvailable()
static uint8_t NRF5_ESB_readMessage(void *data)
{
uint8_t ret = 0;
// get content from rx buffer
NRF5_ESB_Packet *buffer = rx_circular_buffer.getBack();
// Nothing to read?
if (buffer == NULL) {
return 0;
}
if (buffer != NULL) {
// copy content
memcpy(data, buffer->data, buffer->len);
ret = buffer->len;
rssi_rx = 0-buffer->rssi;
// copy content
memcpy(data, buffer->data, buffer->len);
uint8_t ret = buffer->len;
rssi_rx = 0-buffer->rssi;
// Debug message
// Debug message
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
NRF5_RADIO_DEBUG(PSTR("NRF5:RX:LEN=%" PRIu8 ",NOACK=%" PRIu8 ",PID=%" PRIu8 ",RSSI=%" PRIi16 ",RX=%"
PRIu32 "\n"),
buffer->len, buffer->noack, buffer->pid, rssi_rx, buffer->rxmatch);
NRF5_RADIO_DEBUG(PSTR("NRF5:RX:LEN=%" PRIu8 ",NOACK=%" PRIu8 ",PID=%" PRIu8 ",RSSI=%" PRIi16 ",RX=%"
PRIu32 "\n"),
buffer->len, buffer->noack, buffer->pid, rssi_rx, buffer->rxmatch);
#endif
// release buffer
rx_circular_buffer.popBack();
// release buffer
rx_circular_buffer.popBack();
}
// Check if radio was disabled by buffer end
if (radio_disabled == true) {
@@ -399,7 +429,7 @@ static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len
// build metadata
tx_buffer.len = len;
#ifndef MY_NRF5_ESB_REVERSE_ACK
#ifndef MY_NRF5_ESB_REVERSE_ACK_TX
tx_buffer.noack = noACK || recipient==BROADCAST_ADDRESS;
#else
// reverse the noack bit
@@ -408,13 +438,13 @@ static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len
tx_buffer.pid++;
// Calculate number of retries
tx_retries = ((recipient == BROADCAST_ADDRESS)?(NRF5_ESB_BC):(NRF5_ESB_ARC));
if (recipient == BROADCAST_ADDRESS) {
tx_retries = NRF5_ESB_BC_ARC;
} else {
tx_retries = ((noACK == false)?(NRF5_ESB_ARC_ACK):(NRF5_ESB_ARC_NOACK));
}
int8_t tx_retries_start = tx_retries;
// This line disables sending a broadcast packet multiple times
// ack_received = (recipient == BROADCAST_ADDRESS);
// This line force to send an boradcast packet multiple times like NRF24
ack_received = tx_buffer.noack;
ack_received = false;
// configure TX address
NRF_RADIO->PREFIX1 = (NRF_RADIO->PREFIX1 & NRF5_ESB_TX_ADDR_MSK) |
@@ -442,9 +472,6 @@ static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len
#endif
}
// Enable listening on Node and BC address
NRF_RADIO->RXADDRESSES = (1 << NRF5_ESB_NODE_ADDR) | (1 << NRF5_ESB_BC_ADDR);
// Calculate RSSI
if (rssi_tx == INVALID_RSSI) {
// calculate pseudo-RSSI based on retransmission counter (ARC)
@@ -452,12 +479,17 @@ static bool NRF5_ESB_sendMessage(uint8_t recipient, const void *buf, uint8_t len
// Arbitrary definition: ARC 0 == -29, ARC 15 = -104
rssi_tx = (-29 - (8 * (tx_retries_start - tx_retries)));
}
// Enable listening on Node and BC address
NRF_RADIO->RXADDRESSES = (1 << NRF5_ESB_NODE_ADDR) | (1 << NRF5_ESB_BC_ADDR);
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
NRF5_RADIO_DEBUG(PSTR("NRF5:SND:END=%" PRIu8 ",ACK=%" PRIu8 ",RTRY=%" PRIi8 ",RSSI=%" PRIi16
",WAKE=%" PRIu32 "\n"),
events_end_tx, ack_received, tx_retries_start - tx_retries, rssi_tx, wakeups);
#endif
return ack_received;
};
@@ -486,7 +518,7 @@ static uint8_t reverse_byte(uint8_t address)
return address;
}
// Calculate time to transmit an byte in us as bit shift -> 2^X
// Calculate time to transmit an byte in µs as bit shift -> 2^X
static inline uint8_t NRF5_ESB_byte_time()
{
if ((MY_NRF5_ESB_MODE == NRF5_1MBPS) or
@@ -510,14 +542,16 @@ extern "C" {
*/
if (NRF_RADIO->EVENTS_BCMATCH == 1) {
NRF_RESET_EVENT(NRF_RADIO->EVENTS_BCMATCH);
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
intcntr_bcmatch++;
#endif
// Disable bitcounter
NRF_RADIO->TASKS_BCSTOP = 1;
// In RX mode -> prepare ACK or RX
if (NRF_RADIO->STATE == RADIO_STATE_STATE_Rx) {
// ACK only for node address and unset noack bit
#ifndef MY_NRF5_ESB_REVERSE_ACK
#ifndef MY_NRF5_ESB_REVERSE_ACK_RX
if ((NRF_RADIO->RXMATCH != NRF5_ESB_NODE_ADDR) || (rx_buffer->noack)) {
#else
if ((NRF_RADIO->RXMATCH != NRF5_ESB_NODE_ADDR) || (!rx_buffer->noack)) {
@@ -561,6 +595,9 @@ extern "C" {
*/
if (NRF_RADIO->EVENTS_READY == 1) {
NRF_RESET_EVENT(NRF_RADIO->EVENTS_READY);
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
intcntr_ready++;
#endif
// Fetch a new buffer
rx_buffer = rx_circular_buffer.getFront();
@@ -591,6 +628,9 @@ extern "C" {
*/
if (NRF_RADIO->EVENTS_END == 1) {
NRF_RESET_EVENT(NRF_RADIO->EVENTS_END);
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
intcntr_end++;
#endif
// Enable ACK bitcounter for next packet
NRF_RADIO->BCC = NRF5_ESB_BITCOUNTER;
@@ -619,7 +659,7 @@ extern "C" {
// Prepare ACK package
ack_buffer.pid++;
ack_buffer.len=1; // data[0] is set some lines before
#ifndef MY_NRF5_ESB_REVERSE_ACK
#ifndef MY_NRF5_ESB_REVERSE_ACK_TX
ack_buffer.noack = 1;
#else
ack_buffer.noack = 0;
+17 -3
View File
@@ -25,6 +25,11 @@
#include "Radio.h"
#include <Arduino.h>
// Check SoftDevice presence
#if defined(SOFTDEVICE_PRESENT) && !defined(FORCE_RADIO_ESB_WITH_SD)
#error "NRF5 SoftDevice cannot be used with NRF5 Radio."
#endif
// Check maximum messae length
#if MAX_MESSAGE_LENGTH > (32)
#error "Unsupported message length. (MAX_MESSAGE_LENGTH)"
@@ -49,11 +54,14 @@
// auto retry delay in us, don't set this value < 1500us@250kbit
#define NRF5_ESB_ARD (1500)
// auto retry count
#define NRF5_ESB_ARC (15)
// auto retry count with noACK is false
#define NRF5_ESB_ARC_ACK (15)
// auto retry count with noACK is true
#define NRF5_ESB_ARC_NOACK (15)
// How often broadcast messages are send
#define NRF5_ESB_BC (1)
#define NRF5_ESB_BC_ARC (15)
// Node address index
#define NRF5_ESB_NODE_ADDR (0)
@@ -154,4 +162,10 @@ typedef struct nrf5_radio_packet_s {
#endif
} NRF5_ESB_Packet;
#ifdef MY_DEBUG_VERBOSE_NRF5_ESB
static uint32_t intcntr_bcmatch;
static uint32_t intcntr_ready;
static uint32_t intcntr_end;
#endif
#endif // __NRF5_H__
+6
View File
@@ -32,7 +32,13 @@ void nrf5_pinMode(uint32_t ulPin, uint32_t ulMode)
return;
}
#ifdef ARDUINO_ARCH_NRF52
// Arduino: https://github.com/arduino-org/arduino-core-nrf52
ulPin = g_APinDescription[ulPin].ulPin;
#else
// Sandeep Mistry: https://github.com/sandeepmistry/arduino-nRF5
ulPin = g_ADigitalPinMap[ulPin];
#endif
// Set pin mode according to chapter '22.6.3 I/O Pin Configuration'
switch (ulMode) {