Attempting to moved micro enhanced shockburst into a class so that functionality can be used.

Dependencies:   mbed

Fork of nRF51822_esb by Joshua Noble

Committer:
joshuajnoble
Date:
Mon Mar 23 04:09:41 2015 +0000
Revision:
0:a01a54c0dc90
Child:
1:5d49c7b9f405
trying esb

Who changed what in which revision?

UserRevisionLine numberNew contents of line
joshuajnoble 0:a01a54c0dc90 1 /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
joshuajnoble 0:a01a54c0dc90 2 *
joshuajnoble 0:a01a54c0dc90 3 * The information contained herein is property of Nordic Semiconductor ASA.
joshuajnoble 0:a01a54c0dc90 4 * Terms and conditions of usage are described in detail in NORDIC
joshuajnoble 0:a01a54c0dc90 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
joshuajnoble 0:a01a54c0dc90 6 *
joshuajnoble 0:a01a54c0dc90 7 * Licensees are granted free, non-transferable use of the information. NO
joshuajnoble 0:a01a54c0dc90 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
joshuajnoble 0:a01a54c0dc90 9 * the file.
joshuajnoble 0:a01a54c0dc90 10 *
joshuajnoble 0:a01a54c0dc90 11 */
joshuajnoble 0:a01a54c0dc90 12
joshuajnoble 0:a01a54c0dc90 13 #include "micro_esb.h"
joshuajnoble 0:a01a54c0dc90 14 #include "uesb_error_codes.h"
joshuajnoble 0:a01a54c0dc90 15 //#include "nrf_gpio.h"
joshuajnoble 0:a01a54c0dc90 16 #include <string.h>
joshuajnoble 0:a01a54c0dc90 17
joshuajnoble 0:a01a54c0dc90 18
joshuajnoble 0:a01a54c0dc90 19 static uesb_event_handler_t m_event_handler;
joshuajnoble 0:a01a54c0dc90 20
joshuajnoble 0:a01a54c0dc90 21 // RF parameters
joshuajnoble 0:a01a54c0dc90 22 static uesb_config_t m_config_local;
joshuajnoble 0:a01a54c0dc90 23
joshuajnoble 0:a01a54c0dc90 24 // TX FIFO
joshuajnoble 0:a01a54c0dc90 25 static uesb_payload_t m_tx_fifo_payload[UESB_CORE_TX_FIFO_SIZE];
joshuajnoble 0:a01a54c0dc90 26 static uesb_payload_tx_fifo_t m_tx_fifo;
joshuajnoble 0:a01a54c0dc90 27
joshuajnoble 0:a01a54c0dc90 28 // RX FIFO
joshuajnoble 0:a01a54c0dc90 29 static uesb_payload_t m_rx_fifo_payload[UESB_CORE_RX_FIFO_SIZE];
joshuajnoble 0:a01a54c0dc90 30 static uesb_payload_rx_fifo_t m_rx_fifo;
joshuajnoble 0:a01a54c0dc90 31
joshuajnoble 0:a01a54c0dc90 32 static uint8_t m_tx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2];
joshuajnoble 0:a01a54c0dc90 33 static uint8_t m_rx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2];
joshuajnoble 0:a01a54c0dc90 34
joshuajnoble 0:a01a54c0dc90 35 // Run time variables
joshuajnoble 0:a01a54c0dc90 36 static volatile uint32_t m_interrupt_flags = 0;
joshuajnoble 0:a01a54c0dc90 37 static uint32_t m_pid = 0;
joshuajnoble 0:a01a54c0dc90 38 static volatile uint32_t m_retransmits_remaining;
joshuajnoble 0:a01a54c0dc90 39 static volatile uint32_t m_last_tx_attempts;
joshuajnoble 0:a01a54c0dc90 40 static volatile uint8_t m_last_rx_packet_pid = 0xFF;
joshuajnoble 0:a01a54c0dc90 41 static volatile uint32_t m_last_rx_packet_crc = 0xFFFFFFFF;
joshuajnoble 0:a01a54c0dc90 42 static volatile uint32_t m_wait_for_ack_timeout_us;
joshuajnoble 0:a01a54c0dc90 43
joshuajnoble 0:a01a54c0dc90 44 static uesb_payload_t *current_payload;
joshuajnoble 0:a01a54c0dc90 45
joshuajnoble 0:a01a54c0dc90 46 static uesb_mainstate_t m_uesb_mainstate = UESB_STATE_UNINITIALIZED;
joshuajnoble 0:a01a54c0dc90 47
joshuajnoble 0:a01a54c0dc90 48 // Constant parameters
joshuajnoble 0:a01a54c0dc90 49 #define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS 48 // Smallest reliable value - 43
joshuajnoble 0:a01a54c0dc90 50 #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS 64 // Smallest reliable value - 59
joshuajnoble 0:a01a54c0dc90 51 #define RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS 250
joshuajnoble 0:a01a54c0dc90 52
joshuajnoble 0:a01a54c0dc90 53 // Macros
joshuajnoble 0:a01a54c0dc90 54 #define DISABLE_RF_IRQ NVIC_DisableIRQ(RADIO_IRQn)
joshuajnoble 0:a01a54c0dc90 55 #define ENABLE_RF_IRQ NVIC_EnableIRQ(RADIO_IRQn)
joshuajnoble 0:a01a54c0dc90 56
joshuajnoble 0:a01a54c0dc90 57 #define RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \
joshuajnoble 0:a01a54c0dc90 58 RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk )
joshuajnoble 0:a01a54c0dc90 59
joshuajnoble 0:a01a54c0dc90 60 // These function pointers are changed dynamically, depending on protocol configuration and state
joshuajnoble 0:a01a54c0dc90 61 static void (*on_radio_disabled)(void) = 0;
joshuajnoble 0:a01a54c0dc90 62 static void (*on_radio_end)(void) = 0;
joshuajnoble 0:a01a54c0dc90 63 static void (*update_rf_payload_format)(uint32_t payload_length) = 0;
joshuajnoble 0:a01a54c0dc90 64
joshuajnoble 0:a01a54c0dc90 65 // The following functions are assigned to the function pointers above
joshuajnoble 0:a01a54c0dc90 66 static void on_radio_disabled_esb_dpl_tx_noack(void);
joshuajnoble 0:a01a54c0dc90 67 static void on_radio_disabled_esb_dpl_tx(void);
joshuajnoble 0:a01a54c0dc90 68 static void on_radio_disabled_esb_dpl_tx_wait_for_ack(void);
joshuajnoble 0:a01a54c0dc90 69 static void on_radio_disabled_esb_dpl_rx(void);
joshuajnoble 0:a01a54c0dc90 70 static void on_radio_disabled_esb_dpl_rx_ack(void);
joshuajnoble 0:a01a54c0dc90 71
joshuajnoble 0:a01a54c0dc90 72 static void on_radio_end_sb_tx(void);
joshuajnoble 0:a01a54c0dc90 73 static void on_radio_end_sb_rx(void);
joshuajnoble 0:a01a54c0dc90 74
joshuajnoble 0:a01a54c0dc90 75 static void update_rf_payload_format_esb_dpl(uint32_t payload_length)
joshuajnoble 0:a01a54c0dc90 76 {
joshuajnoble 0:a01a54c0dc90 77 #if(UESB_CORE_MAX_PAYLOAD_LENGTH <= 32)
joshuajnoble 0:a01a54c0dc90 78 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
joshuajnoble 0:a01a54c0dc90 79 #else
joshuajnoble 0:a01a54c0dc90 80 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (8 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
joshuajnoble 0:a01a54c0dc90 81 #endif
joshuajnoble 0:a01a54c0dc90 82 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
joshuajnoble 0:a01a54c0dc90 83 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
joshuajnoble 0:a01a54c0dc90 84 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
joshuajnoble 0:a01a54c0dc90 85 (0 << RADIO_PCNF1_STATLEN_Pos) |
joshuajnoble 0:a01a54c0dc90 86 (UESB_CORE_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos);
joshuajnoble 0:a01a54c0dc90 87 }
joshuajnoble 0:a01a54c0dc90 88
joshuajnoble 0:a01a54c0dc90 89 static void update_rf_payload_format_esb(uint32_t payload_length)
joshuajnoble 0:a01a54c0dc90 90 {
joshuajnoble 0:a01a54c0dc90 91 NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (1 << RADIO_PCNF0_S1LEN_Pos);
joshuajnoble 0:a01a54c0dc90 92 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
joshuajnoble 0:a01a54c0dc90 93 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
joshuajnoble 0:a01a54c0dc90 94 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
joshuajnoble 0:a01a54c0dc90 95 (payload_length << RADIO_PCNF1_STATLEN_Pos) |
joshuajnoble 0:a01a54c0dc90 96 (payload_length << RADIO_PCNF1_MAXLEN_Pos);
joshuajnoble 0:a01a54c0dc90 97 }
joshuajnoble 0:a01a54c0dc90 98
joshuajnoble 0:a01a54c0dc90 99 static void update_rf_payload_format_sb(uint32_t payload_length)
joshuajnoble 0:a01a54c0dc90 100 {
joshuajnoble 0:a01a54c0dc90 101 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (0 << RADIO_PCNF0_S1LEN_Pos);
joshuajnoble 0:a01a54c0dc90 102 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
joshuajnoble 0:a01a54c0dc90 103 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
joshuajnoble 0:a01a54c0dc90 104 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
joshuajnoble 0:a01a54c0dc90 105 (payload_length << RADIO_PCNF1_STATLEN_Pos) |
joshuajnoble 0:a01a54c0dc90 106 (payload_length << RADIO_PCNF1_MAXLEN_Pos);
joshuajnoble 0:a01a54c0dc90 107 }
joshuajnoble 0:a01a54c0dc90 108
joshuajnoble 0:a01a54c0dc90 109 // Function that swaps the bits within each byte in a uint32. Used to convert from nRF24L type addressing to nRF51 type addressing
joshuajnoble 0:a01a54c0dc90 110 static uint32_t bytewise_bit_swap(uint32_t inp)
joshuajnoble 0:a01a54c0dc90 111 {
joshuajnoble 0:a01a54c0dc90 112 inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4;
joshuajnoble 0:a01a54c0dc90 113 inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2;
joshuajnoble 0:a01a54c0dc90 114 return (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1;
joshuajnoble 0:a01a54c0dc90 115 }
joshuajnoble 0:a01a54c0dc90 116
joshuajnoble 0:a01a54c0dc90 117 static void update_radio_parameters()
joshuajnoble 0:a01a54c0dc90 118 {
joshuajnoble 0:a01a54c0dc90 119 // Protocol
joshuajnoble 0:a01a54c0dc90 120 switch(m_config_local.protocol)
joshuajnoble 0:a01a54c0dc90 121 {
joshuajnoble 0:a01a54c0dc90 122 case UESB_PROTOCOL_ESB_DPL:
joshuajnoble 0:a01a54c0dc90 123 update_rf_payload_format = update_rf_payload_format_esb_dpl;
joshuajnoble 0:a01a54c0dc90 124 break;
joshuajnoble 0:a01a54c0dc90 125 case UESB_PROTOCOL_ESB:
joshuajnoble 0:a01a54c0dc90 126 update_rf_payload_format = update_rf_payload_format_esb;
joshuajnoble 0:a01a54c0dc90 127 break;
joshuajnoble 0:a01a54c0dc90 128 case UESB_PROTOCOL_SB:
joshuajnoble 0:a01a54c0dc90 129 update_rf_payload_format = update_rf_payload_format_sb;
joshuajnoble 0:a01a54c0dc90 130 on_radio_end = (m_config_local.mode == UESB_MODE_PTX ? on_radio_end_sb_tx : on_radio_end_sb_rx);
joshuajnoble 0:a01a54c0dc90 131 break;
joshuajnoble 0:a01a54c0dc90 132 }
joshuajnoble 0:a01a54c0dc90 133 // TX power
joshuajnoble 0:a01a54c0dc90 134 NRF_RADIO->TXPOWER = m_config_local.tx_output_power << RADIO_TXPOWER_TXPOWER_Pos;
joshuajnoble 0:a01a54c0dc90 135
joshuajnoble 0:a01a54c0dc90 136 // RF bitrate
joshuajnoble 0:a01a54c0dc90 137 NRF_RADIO->MODE = m_config_local.bitrate << RADIO_MODE_MODE_Pos;
joshuajnoble 0:a01a54c0dc90 138 switch(m_config_local.bitrate)
joshuajnoble 0:a01a54c0dc90 139 {
joshuajnoble 0:a01a54c0dc90 140 case UESB_BITRATE_2MBPS:
joshuajnoble 0:a01a54c0dc90 141 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS;
joshuajnoble 0:a01a54c0dc90 142 break;
joshuajnoble 0:a01a54c0dc90 143 case UESB_BITRATE_1MBPS:
joshuajnoble 0:a01a54c0dc90 144 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS;
joshuajnoble 0:a01a54c0dc90 145 break;
joshuajnoble 0:a01a54c0dc90 146 case UESB_BITRATE_250KBPS:
joshuajnoble 0:a01a54c0dc90 147 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS;
joshuajnoble 0:a01a54c0dc90 148 break;
joshuajnoble 0:a01a54c0dc90 149 }
joshuajnoble 0:a01a54c0dc90 150
joshuajnoble 0:a01a54c0dc90 151 // CRC configuration
joshuajnoble 0:a01a54c0dc90 152 NRF_RADIO->CRCCNF = m_config_local.crc << RADIO_CRCCNF_LEN_Pos;
joshuajnoble 0:a01a54c0dc90 153 if(m_config_local.crc == RADIO_CRCCNF_LEN_Two)
joshuajnoble 0:a01a54c0dc90 154 {
joshuajnoble 0:a01a54c0dc90 155 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
joshuajnoble 0:a01a54c0dc90 156 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
joshuajnoble 0:a01a54c0dc90 157 }
joshuajnoble 0:a01a54c0dc90 158 else if(m_config_local.crc == RADIO_CRCCNF_LEN_One)
joshuajnoble 0:a01a54c0dc90 159 {
joshuajnoble 0:a01a54c0dc90 160 NRF_RADIO->CRCINIT = 0xFFUL; // Initial value
joshuajnoble 0:a01a54c0dc90 161 NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1
joshuajnoble 0:a01a54c0dc90 162 }
joshuajnoble 0:a01a54c0dc90 163
joshuajnoble 0:a01a54c0dc90 164 // Packet format
joshuajnoble 0:a01a54c0dc90 165 update_rf_payload_format(m_config_local.payload_length);
joshuajnoble 0:a01a54c0dc90 166
joshuajnoble 0:a01a54c0dc90 167 // Radio address config
joshuajnoble 0:a01a54c0dc90 168 NRF_RADIO->PREFIX0 = bytewise_bit_swap(m_config_local.rx_address_p3 << 24 | m_config_local.rx_address_p2 << 16 | m_config_local.rx_address_p1[0] << 8 | m_config_local.rx_address_p0[0]);
joshuajnoble 0:a01a54c0dc90 169 NRF_RADIO->PREFIX1 = bytewise_bit_swap(m_config_local.rx_address_p7 << 24 | m_config_local.rx_address_p6 << 16 | m_config_local.rx_address_p5 << 8 | m_config_local.rx_address_p4);
joshuajnoble 0:a01a54c0dc90 170 NRF_RADIO->BASE0 = bytewise_bit_swap(m_config_local.rx_address_p0[1] << 24 | m_config_local.rx_address_p0[2] << 16 | m_config_local.rx_address_p0[3] << 8 | m_config_local.rx_address_p0[4]);
joshuajnoble 0:a01a54c0dc90 171 NRF_RADIO->BASE1 = bytewise_bit_swap(m_config_local.rx_address_p1[1] << 24 | m_config_local.rx_address_p1[2] << 16 | m_config_local.rx_address_p1[3] << 8 | m_config_local.rx_address_p1[4]);
joshuajnoble 0:a01a54c0dc90 172 }
joshuajnoble 0:a01a54c0dc90 173
joshuajnoble 0:a01a54c0dc90 174 static void initialize_fifos()
joshuajnoble 0:a01a54c0dc90 175 {
joshuajnoble 0:a01a54c0dc90 176 m_tx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 177 m_tx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 178 m_tx_fifo.count = 0;
joshuajnoble 0:a01a54c0dc90 179 for(int i = 0; i < UESB_CORE_TX_FIFO_SIZE; i++)
joshuajnoble 0:a01a54c0dc90 180 {
joshuajnoble 0:a01a54c0dc90 181 m_tx_fifo.payload_ptr[i] = &m_tx_fifo_payload[i];
joshuajnoble 0:a01a54c0dc90 182 }
joshuajnoble 0:a01a54c0dc90 183
joshuajnoble 0:a01a54c0dc90 184 m_rx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 185 m_rx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 186 m_rx_fifo.count = 0;
joshuajnoble 0:a01a54c0dc90 187 for(int i = 0; i < UESB_CORE_RX_FIFO_SIZE; i++)
joshuajnoble 0:a01a54c0dc90 188 {
joshuajnoble 0:a01a54c0dc90 189 m_rx_fifo.payload_ptr[i] = &m_rx_fifo_payload[i];
joshuajnoble 0:a01a54c0dc90 190 }
joshuajnoble 0:a01a54c0dc90 191 }
joshuajnoble 0:a01a54c0dc90 192
joshuajnoble 0:a01a54c0dc90 193 static void tx_fifo_remove_last()
joshuajnoble 0:a01a54c0dc90 194 {
joshuajnoble 0:a01a54c0dc90 195 if(m_tx_fifo.count > 0)
joshuajnoble 0:a01a54c0dc90 196 {
joshuajnoble 0:a01a54c0dc90 197 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 198 m_tx_fifo.count--;
joshuajnoble 0:a01a54c0dc90 199 m_tx_fifo.exit_point++;
joshuajnoble 0:a01a54c0dc90 200 if(m_tx_fifo.exit_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 201 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 202 }
joshuajnoble 0:a01a54c0dc90 203 }
joshuajnoble 0:a01a54c0dc90 204
joshuajnoble 0:a01a54c0dc90 205 static bool rx_fifo_push_rfbuf(uint8_t pipe)
joshuajnoble 0:a01a54c0dc90 206 {
joshuajnoble 0:a01a54c0dc90 207 if(m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE)
joshuajnoble 0:a01a54c0dc90 208 {
joshuajnoble 0:a01a54c0dc90 209 if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL)
joshuajnoble 0:a01a54c0dc90 210 {
joshuajnoble 0:a01a54c0dc90 211 if(m_rx_payload_buffer[0] > UESB_CORE_MAX_PAYLOAD_LENGTH) return false;
joshuajnoble 0:a01a54c0dc90 212 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_rx_payload_buffer[0];
joshuajnoble 0:a01a54c0dc90 213 }
joshuajnoble 0:a01a54c0dc90 214 else
joshuajnoble 0:a01a54c0dc90 215 {
joshuajnoble 0:a01a54c0dc90 216 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_config_local.payload_length;
joshuajnoble 0:a01a54c0dc90 217 }
joshuajnoble 0:a01a54c0dc90 218 if(m_config_local.protocol == UESB_PROTOCOL_SB)
joshuajnoble 0:a01a54c0dc90 219 {
joshuajnoble 0:a01a54c0dc90 220 memcpy(m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[0], m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length);
joshuajnoble 0:a01a54c0dc90 221 }
joshuajnoble 0:a01a54c0dc90 222 else
joshuajnoble 0:a01a54c0dc90 223 {
joshuajnoble 0:a01a54c0dc90 224 memcpy(m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[2], m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length);
joshuajnoble 0:a01a54c0dc90 225 }
joshuajnoble 0:a01a54c0dc90 226 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->pipe = pipe;
joshuajnoble 0:a01a54c0dc90 227 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE;
joshuajnoble 0:a01a54c0dc90 228 if(++m_rx_fifo.entry_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 229 m_rx_fifo.count++;
joshuajnoble 0:a01a54c0dc90 230 return true;
joshuajnoble 0:a01a54c0dc90 231 }
joshuajnoble 0:a01a54c0dc90 232 return false;
joshuajnoble 0:a01a54c0dc90 233 }
joshuajnoble 0:a01a54c0dc90 234
joshuajnoble 0:a01a54c0dc90 235 static void sys_timer_init()
joshuajnoble 0:a01a54c0dc90 236 {
joshuajnoble 0:a01a54c0dc90 237 // Configure the system timer with a 1 MHz base frequency
joshuajnoble 0:a01a54c0dc90 238 UESB_SYS_TIMER->PRESCALER = 4;
joshuajnoble 0:a01a54c0dc90 239 UESB_SYS_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
joshuajnoble 0:a01a54c0dc90 240 UESB_SYS_TIMER->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk;
joshuajnoble 0:a01a54c0dc90 241 }
joshuajnoble 0:a01a54c0dc90 242
joshuajnoble 0:a01a54c0dc90 243 static void ppi_init()
joshuajnoble 0:a01a54c0dc90 244 {
joshuajnoble 0:a01a54c0dc90 245 NRF_PPI->CH[UESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY;
joshuajnoble 0:a01a54c0dc90 246 NRF_PPI->CH[UESB_PPI_TIMER_START].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_START;
joshuajnoble 0:a01a54c0dc90 247 NRF_PPI->CH[UESB_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
joshuajnoble 0:a01a54c0dc90 248 NRF_PPI->CH[UESB_PPI_TIMER_STOP].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_STOP;
joshuajnoble 0:a01a54c0dc90 249 NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[0];
joshuajnoble 0:a01a54c0dc90 250 NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE;
joshuajnoble 0:a01a54c0dc90 251 NRF_PPI->CH[UESB_PPI_TX_START].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[1];
joshuajnoble 0:a01a54c0dc90 252 NRF_PPI->CH[UESB_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
joshuajnoble 0:a01a54c0dc90 253 }
joshuajnoble 0:a01a54c0dc90 254
joshuajnoble 0:a01a54c0dc90 255 uint32_t uesb_init(uesb_config_t *parameters)
joshuajnoble 0:a01a54c0dc90 256 {
joshuajnoble 0:a01a54c0dc90 257 if(m_uesb_mainstate != UESB_STATE_UNINITIALIZED) return UESB_ERROR_ALREADY_INITIALIZED;
joshuajnoble 0:a01a54c0dc90 258 m_event_handler = parameters->event_handler;
joshuajnoble 0:a01a54c0dc90 259 memcpy(&m_config_local, parameters, sizeof(uesb_config_t));
joshuajnoble 0:a01a54c0dc90 260
joshuajnoble 0:a01a54c0dc90 261 m_interrupt_flags = 0;
joshuajnoble 0:a01a54c0dc90 262 m_pid = 0;
joshuajnoble 0:a01a54c0dc90 263 m_last_rx_packet_pid = 0xFF;
joshuajnoble 0:a01a54c0dc90 264 m_last_rx_packet_crc = 0xFFFFFFFF;
joshuajnoble 0:a01a54c0dc90 265
joshuajnoble 0:a01a54c0dc90 266 update_radio_parameters();
joshuajnoble 0:a01a54c0dc90 267
joshuajnoble 0:a01a54c0dc90 268 initialize_fifos();
joshuajnoble 0:a01a54c0dc90 269
joshuajnoble 0:a01a54c0dc90 270 sys_timer_init();
joshuajnoble 0:a01a54c0dc90 271
joshuajnoble 0:a01a54c0dc90 272 ppi_init();
joshuajnoble 0:a01a54c0dc90 273
joshuajnoble 0:a01a54c0dc90 274 NVIC_SetPriority(RADIO_IRQn, m_config_local.radio_irq_priority & 0x03);
joshuajnoble 0:a01a54c0dc90 275
joshuajnoble 0:a01a54c0dc90 276 //m_uesb_initialized = true;
joshuajnoble 0:a01a54c0dc90 277 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 278
joshuajnoble 0:a01a54c0dc90 279 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 280 }
joshuajnoble 0:a01a54c0dc90 281
joshuajnoble 0:a01a54c0dc90 282 uint32_t uesb_disable(void)
joshuajnoble 0:a01a54c0dc90 283 {
joshuajnoble 0:a01a54c0dc90 284 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 285 NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_TIMER_STOP) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TX_START);
joshuajnoble 0:a01a54c0dc90 286 m_uesb_mainstate = UESB_STATE_UNINITIALIZED;
joshuajnoble 0:a01a54c0dc90 287 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 288 }
joshuajnoble 0:a01a54c0dc90 289
joshuajnoble 0:a01a54c0dc90 290 static void start_tx_transaction()
joshuajnoble 0:a01a54c0dc90 291 {
joshuajnoble 0:a01a54c0dc90 292 bool ack;
joshuajnoble 0:a01a54c0dc90 293 m_last_tx_attempts = 1;
joshuajnoble 0:a01a54c0dc90 294 // Prepare the payload
joshuajnoble 0:a01a54c0dc90 295 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point];
joshuajnoble 0:a01a54c0dc90 296 m_pid = (m_pid + 1) % 4;
joshuajnoble 0:a01a54c0dc90 297 switch(m_config_local.protocol)
joshuajnoble 0:a01a54c0dc90 298 {
joshuajnoble 0:a01a54c0dc90 299 case UESB_PROTOCOL_SB:
joshuajnoble 0:a01a54c0dc90 300 update_rf_payload_format(current_payload->length);
joshuajnoble 0:a01a54c0dc90 301 memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length);
joshuajnoble 0:a01a54c0dc90 302 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk;
joshuajnoble 0:a01a54c0dc90 303 NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
joshuajnoble 0:a01a54c0dc90 304 on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack;
joshuajnoble 0:a01a54c0dc90 305 m_uesb_mainstate = UESB_STATE_PTX_TX;
joshuajnoble 0:a01a54c0dc90 306 break;
joshuajnoble 0:a01a54c0dc90 307
joshuajnoble 0:a01a54c0dc90 308 case UESB_PROTOCOL_ESB:
joshuajnoble 0:a01a54c0dc90 309 update_rf_payload_format(current_payload->length);
joshuajnoble 0:a01a54c0dc90 310 m_tx_payload_buffer[0] = 0xCC | m_pid;
joshuajnoble 0:a01a54c0dc90 311 m_tx_payload_buffer[1] = 0;
joshuajnoble 0:a01a54c0dc90 312 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length);
joshuajnoble 0:a01a54c0dc90 313
joshuajnoble 0:a01a54c0dc90 314 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk;
joshuajnoble 0:a01a54c0dc90 315 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
joshuajnoble 0:a01a54c0dc90 316
joshuajnoble 0:a01a54c0dc90 317 // Configure the retransmit counter
joshuajnoble 0:a01a54c0dc90 318 m_retransmits_remaining = m_config_local.retransmit_count;
joshuajnoble 0:a01a54c0dc90 319 on_radio_disabled = on_radio_disabled_esb_dpl_tx;
joshuajnoble 0:a01a54c0dc90 320 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK;
joshuajnoble 0:a01a54c0dc90 321 break;
joshuajnoble 0:a01a54c0dc90 322
joshuajnoble 0:a01a54c0dc90 323 case UESB_PROTOCOL_ESB_DPL:
joshuajnoble 0:a01a54c0dc90 324 ack = current_payload->noack == 0 || m_config_local.dynamic_ack_enabled == 0;
joshuajnoble 0:a01a54c0dc90 325 m_tx_payload_buffer[0] = current_payload->length;
joshuajnoble 0:a01a54c0dc90 326 m_tx_payload_buffer[1] = m_pid << 1 | ((current_payload->noack == 0 && m_config_local.dynamic_ack_enabled) ? 0x01 : 0x00);
joshuajnoble 0:a01a54c0dc90 327 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length);
joshuajnoble 0:a01a54c0dc90 328 if(ack)
joshuajnoble 0:a01a54c0dc90 329 {
joshuajnoble 0:a01a54c0dc90 330 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk;
joshuajnoble 0:a01a54c0dc90 331 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
joshuajnoble 0:a01a54c0dc90 332
joshuajnoble 0:a01a54c0dc90 333 // Configure the retransmit counter
joshuajnoble 0:a01a54c0dc90 334 m_retransmits_remaining = m_config_local.retransmit_count;
joshuajnoble 0:a01a54c0dc90 335 on_radio_disabled = on_radio_disabled_esb_dpl_tx;
joshuajnoble 0:a01a54c0dc90 336 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK;
joshuajnoble 0:a01a54c0dc90 337 }
joshuajnoble 0:a01a54c0dc90 338 else
joshuajnoble 0:a01a54c0dc90 339 {
joshuajnoble 0:a01a54c0dc90 340 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON;
joshuajnoble 0:a01a54c0dc90 341 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
joshuajnoble 0:a01a54c0dc90 342 on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack;
joshuajnoble 0:a01a54c0dc90 343 m_uesb_mainstate = UESB_STATE_PTX_TX;
joshuajnoble 0:a01a54c0dc90 344 }
joshuajnoble 0:a01a54c0dc90 345 break;
joshuajnoble 0:a01a54c0dc90 346 }
joshuajnoble 0:a01a54c0dc90 347
joshuajnoble 0:a01a54c0dc90 348 NRF_RADIO->TXADDRESS = current_payload->pipe;
joshuajnoble 0:a01a54c0dc90 349 NRF_RADIO->RXADDRESSES = 1 << current_payload->pipe;
joshuajnoble 0:a01a54c0dc90 350
joshuajnoble 0:a01a54c0dc90 351 NRF_RADIO->FREQUENCY = m_config_local.rf_channel;
joshuajnoble 0:a01a54c0dc90 352
joshuajnoble 0:a01a54c0dc90 353 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 354
joshuajnoble 0:a01a54c0dc90 355 NVIC_ClearPendingIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 356 NVIC_EnableIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 357
joshuajnoble 0:a01a54c0dc90 358 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 359 DEBUG_PIN_SET(DEBUGPIN4);
joshuajnoble 0:a01a54c0dc90 360 NRF_RADIO->TASKS_TXEN = 1;
joshuajnoble 0:a01a54c0dc90 361 }
joshuajnoble 0:a01a54c0dc90 362
joshuajnoble 0:a01a54c0dc90 363 static uint32_t write_tx_payload(uesb_payload_t *payload, bool noack) // ~50us @ 61 bytes SB
joshuajnoble 0:a01a54c0dc90 364 {
joshuajnoble 0:a01a54c0dc90 365 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED;
joshuajnoble 0:a01a54c0dc90 366 if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL;
joshuajnoble 0:a01a54c0dc90 367
joshuajnoble 0:a01a54c0dc90 368 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 369 if(noack && m_config_local.dynamic_ack_enabled) payload->noack = 1;
joshuajnoble 0:a01a54c0dc90 370 else payload->noack = 0;
joshuajnoble 0:a01a54c0dc90 371 memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t));
joshuajnoble 0:a01a54c0dc90 372 m_tx_fifo.entry_point++;
joshuajnoble 0:a01a54c0dc90 373 if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 374 m_tx_fifo.count++;
joshuajnoble 0:a01a54c0dc90 375 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 376
joshuajnoble 0:a01a54c0dc90 377 if(m_config_local.tx_mode == UESB_TXMODE_AUTO && m_uesb_mainstate == UESB_STATE_IDLE)
joshuajnoble 0:a01a54c0dc90 378 {
joshuajnoble 0:a01a54c0dc90 379 start_tx_transaction();
joshuajnoble 0:a01a54c0dc90 380 }
joshuajnoble 0:a01a54c0dc90 381
joshuajnoble 0:a01a54c0dc90 382 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 383 }
joshuajnoble 0:a01a54c0dc90 384
joshuajnoble 0:a01a54c0dc90 385 uint32_t uesb_write_tx_payload(uesb_payload_t *payload)
joshuajnoble 0:a01a54c0dc90 386 {
joshuajnoble 0:a01a54c0dc90 387 return write_tx_payload(payload, false);
joshuajnoble 0:a01a54c0dc90 388 }
joshuajnoble 0:a01a54c0dc90 389
joshuajnoble 0:a01a54c0dc90 390 uint32_t uesb_write_tx_payload_noack(uesb_payload_t *payload)
joshuajnoble 0:a01a54c0dc90 391 {
joshuajnoble 0:a01a54c0dc90 392 if(m_config_local.dynamic_ack_enabled == 0) return UESB_ERROR_DYN_ACK_NOT_ENABLED;
joshuajnoble 0:a01a54c0dc90 393 return write_tx_payload(payload, true);
joshuajnoble 0:a01a54c0dc90 394 }
joshuajnoble 0:a01a54c0dc90 395
joshuajnoble 0:a01a54c0dc90 396 uint32_t uesb_write_ack_payload(uesb_payload_t *payload)
joshuajnoble 0:a01a54c0dc90 397 {
joshuajnoble 0:a01a54c0dc90 398 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED;
joshuajnoble 0:a01a54c0dc90 399 if((m_uesb_mainstate != UESB_STATE_PRX) &&
joshuajnoble 0:a01a54c0dc90 400 (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK) &&
joshuajnoble 0:a01a54c0dc90 401 (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK_PAYLOAD))
joshuajnoble 0:a01a54c0dc90 402 {
joshuajnoble 0:a01a54c0dc90 403 return UESB_ERROR_NOT_IN_RX_MODE;
joshuajnoble 0:a01a54c0dc90 404 }
joshuajnoble 0:a01a54c0dc90 405 if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL;
joshuajnoble 0:a01a54c0dc90 406
joshuajnoble 0:a01a54c0dc90 407 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 408 memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t));
joshuajnoble 0:a01a54c0dc90 409 m_tx_fifo.entry_point++;
joshuajnoble 0:a01a54c0dc90 410 if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 411 m_tx_fifo.count++;
joshuajnoble 0:a01a54c0dc90 412 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 413
joshuajnoble 0:a01a54c0dc90 414 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 415 }
joshuajnoble 0:a01a54c0dc90 416
joshuajnoble 0:a01a54c0dc90 417 uint32_t uesb_read_rx_payload(uesb_payload_t *payload)
joshuajnoble 0:a01a54c0dc90 418 {
joshuajnoble 0:a01a54c0dc90 419 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED;
joshuajnoble 0:a01a54c0dc90 420 if(m_rx_fifo.count == 0) return UESB_ERROR_RX_FIFO_EMPTY;
joshuajnoble 0:a01a54c0dc90 421
joshuajnoble 0:a01a54c0dc90 422 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 423 payload->length = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->length;
joshuajnoble 0:a01a54c0dc90 424 payload->pipe = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->pipe;
joshuajnoble 0:a01a54c0dc90 425 payload->rssi = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->rssi;
joshuajnoble 0:a01a54c0dc90 426 memcpy(payload->data, m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->data, payload->length);
joshuajnoble 0:a01a54c0dc90 427 if(++m_rx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 428 m_rx_fifo.count--;
joshuajnoble 0:a01a54c0dc90 429 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 430
joshuajnoble 0:a01a54c0dc90 431 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 432 }
joshuajnoble 0:a01a54c0dc90 433
joshuajnoble 0:a01a54c0dc90 434 uint32_t uesb_start_tx()
joshuajnoble 0:a01a54c0dc90 435 {
joshuajnoble 0:a01a54c0dc90 436 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 437 if(m_tx_fifo.count == 0) return UESB_ERROR_TX_FIFO_EMPTY;
joshuajnoble 0:a01a54c0dc90 438 start_tx_transaction();
joshuajnoble 0:a01a54c0dc90 439 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 440 }
joshuajnoble 0:a01a54c0dc90 441
joshuajnoble 0:a01a54c0dc90 442 uint32_t uesb_start_rx(void)
joshuajnoble 0:a01a54c0dc90 443 {
joshuajnoble 0:a01a54c0dc90 444 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 445
joshuajnoble 0:a01a54c0dc90 446 NRF_RADIO->INTENCLR = 0xFFFFFFFF;
joshuajnoble 0:a01a54c0dc90 447 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 448 on_radio_disabled = on_radio_disabled_esb_dpl_rx;
joshuajnoble 0:a01a54c0dc90 449 switch(m_config_local.protocol)
joshuajnoble 0:a01a54c0dc90 450 {
joshuajnoble 0:a01a54c0dc90 451 case UESB_PROTOCOL_SB:
joshuajnoble 0:a01a54c0dc90 452 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk;
joshuajnoble 0:a01a54c0dc90 453 NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
joshuajnoble 0:a01a54c0dc90 454 m_uesb_mainstate = UESB_STATE_PRX;
joshuajnoble 0:a01a54c0dc90 455 break;
joshuajnoble 0:a01a54c0dc90 456 case UESB_PROTOCOL_ESB:
joshuajnoble 0:a01a54c0dc90 457 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk;
joshuajnoble 0:a01a54c0dc90 458 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
joshuajnoble 0:a01a54c0dc90 459 m_uesb_mainstate = UESB_STATE_PRX;
joshuajnoble 0:a01a54c0dc90 460 break;
joshuajnoble 0:a01a54c0dc90 461 case UESB_PROTOCOL_ESB_DPL:
joshuajnoble 0:a01a54c0dc90 462 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk;
joshuajnoble 0:a01a54c0dc90 463 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
joshuajnoble 0:a01a54c0dc90 464 m_uesb_mainstate = UESB_STATE_PRX;
joshuajnoble 0:a01a54c0dc90 465 break;
joshuajnoble 0:a01a54c0dc90 466 }
joshuajnoble 0:a01a54c0dc90 467
joshuajnoble 0:a01a54c0dc90 468 NRF_RADIO->RXADDRESSES = m_config_local.rx_pipes_enabled;
joshuajnoble 0:a01a54c0dc90 469
joshuajnoble 0:a01a54c0dc90 470 NRF_RADIO->FREQUENCY = m_config_local.rf_channel;
joshuajnoble 0:a01a54c0dc90 471
joshuajnoble 0:a01a54c0dc90 472 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 473
joshuajnoble 0:a01a54c0dc90 474 NVIC_ClearPendingIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 475 NVIC_EnableIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 476
joshuajnoble 0:a01a54c0dc90 477 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 478 NRF_RADIO->TASKS_RXEN = 1;
joshuajnoble 0:a01a54c0dc90 479 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 480 }
joshuajnoble 0:a01a54c0dc90 481
joshuajnoble 0:a01a54c0dc90 482 uint32_t uesb_stop_rx(void)
joshuajnoble 0:a01a54c0dc90 483 {
joshuajnoble 0:a01a54c0dc90 484 if((m_uesb_mainstate == UESB_STATE_PRX) || (m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD))
joshuajnoble 0:a01a54c0dc90 485 {
joshuajnoble 0:a01a54c0dc90 486 NRF_RADIO->SHORTS = 0;
joshuajnoble 0:a01a54c0dc90 487 NRF_RADIO->INTENCLR = 0xFFFFFFFF;
joshuajnoble 0:a01a54c0dc90 488 on_radio_disabled = NULL;
joshuajnoble 0:a01a54c0dc90 489 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 490 NRF_RADIO->TASKS_DISABLE = 1;
joshuajnoble 0:a01a54c0dc90 491 while(NRF_RADIO->EVENTS_DISABLED == 0);
joshuajnoble 0:a01a54c0dc90 492 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 493 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 494 }
joshuajnoble 0:a01a54c0dc90 495 return UESB_ERROR_NOT_IN_RX_MODE;
joshuajnoble 0:a01a54c0dc90 496 }
joshuajnoble 0:a01a54c0dc90 497
joshuajnoble 0:a01a54c0dc90 498 uint32_t uesb_get_tx_attempts(uint32_t *attempts)
joshuajnoble 0:a01a54c0dc90 499 {
joshuajnoble 0:a01a54c0dc90 500 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED;
joshuajnoble 0:a01a54c0dc90 501 *attempts = m_last_tx_attempts;
joshuajnoble 0:a01a54c0dc90 502 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 503 }
joshuajnoble 0:a01a54c0dc90 504
joshuajnoble 0:a01a54c0dc90 505 uint32_t uesb_flush_tx(void)
joshuajnoble 0:a01a54c0dc90 506 {
joshuajnoble 0:a01a54c0dc90 507 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 508 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 509 m_tx_fifo.count = 0;
joshuajnoble 0:a01a54c0dc90 510 m_tx_fifo.entry_point = m_tx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 511 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 512 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 513 }
joshuajnoble 0:a01a54c0dc90 514
joshuajnoble 0:a01a54c0dc90 515 uint32_t uesb_flush_rx(void)
joshuajnoble 0:a01a54c0dc90 516 {
joshuajnoble 0:a01a54c0dc90 517 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 518 m_rx_fifo.count = 0;
joshuajnoble 0:a01a54c0dc90 519 m_rx_fifo.entry_point = 0;
joshuajnoble 0:a01a54c0dc90 520 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 521 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 522 }
joshuajnoble 0:a01a54c0dc90 523
joshuajnoble 0:a01a54c0dc90 524 uint32_t uesb_get_clear_interrupts(uint32_t *interrupts)
joshuajnoble 0:a01a54c0dc90 525 {
joshuajnoble 0:a01a54c0dc90 526 DISABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 527 *interrupts = m_interrupt_flags;
joshuajnoble 0:a01a54c0dc90 528 m_interrupt_flags = 0;
joshuajnoble 0:a01a54c0dc90 529 ENABLE_RF_IRQ;
joshuajnoble 0:a01a54c0dc90 530 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 531 }
joshuajnoble 0:a01a54c0dc90 532
joshuajnoble 0:a01a54c0dc90 533 uint32_t uesb_set_address(uesb_address_type_t address, const uint8_t *data_ptr)
joshuajnoble 0:a01a54c0dc90 534 {
joshuajnoble 0:a01a54c0dc90 535 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 536 switch(address)
joshuajnoble 0:a01a54c0dc90 537 {
joshuajnoble 0:a01a54c0dc90 538 case UESB_ADDRESS_PIPE0:
joshuajnoble 0:a01a54c0dc90 539 memcpy(m_config_local.rx_address_p0, data_ptr, m_config_local.rf_addr_length);
joshuajnoble 0:a01a54c0dc90 540 break;
joshuajnoble 0:a01a54c0dc90 541 case UESB_ADDRESS_PIPE1:
joshuajnoble 0:a01a54c0dc90 542 memcpy(m_config_local.rx_address_p1, data_ptr, m_config_local.rf_addr_length);
joshuajnoble 0:a01a54c0dc90 543 break;
joshuajnoble 0:a01a54c0dc90 544 case UESB_ADDRESS_PIPE2:
joshuajnoble 0:a01a54c0dc90 545 m_config_local.rx_address_p2 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 546 break;
joshuajnoble 0:a01a54c0dc90 547 case UESB_ADDRESS_PIPE3:
joshuajnoble 0:a01a54c0dc90 548 m_config_local.rx_address_p3 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 549 break;
joshuajnoble 0:a01a54c0dc90 550 case UESB_ADDRESS_PIPE4:
joshuajnoble 0:a01a54c0dc90 551 m_config_local.rx_address_p4 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 552 break;
joshuajnoble 0:a01a54c0dc90 553 case UESB_ADDRESS_PIPE5:
joshuajnoble 0:a01a54c0dc90 554 m_config_local.rx_address_p5 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 555 break;
joshuajnoble 0:a01a54c0dc90 556 case UESB_ADDRESS_PIPE6:
joshuajnoble 0:a01a54c0dc90 557 m_config_local.rx_address_p6 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 558 break;
joshuajnoble 0:a01a54c0dc90 559 case UESB_ADDRESS_PIPE7:
joshuajnoble 0:a01a54c0dc90 560 m_config_local.rx_address_p7 = *data_ptr;
joshuajnoble 0:a01a54c0dc90 561 break;
joshuajnoble 0:a01a54c0dc90 562 default:
joshuajnoble 0:a01a54c0dc90 563 return UESB_ERROR_INVALID_PARAMETERS;
joshuajnoble 0:a01a54c0dc90 564 }
joshuajnoble 0:a01a54c0dc90 565 update_radio_parameters();
joshuajnoble 0:a01a54c0dc90 566 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 567 }
joshuajnoble 0:a01a54c0dc90 568
joshuajnoble 0:a01a54c0dc90 569 uint32_t uesb_set_rf_channel(uint32_t channel)
joshuajnoble 0:a01a54c0dc90 570 {
joshuajnoble 0:a01a54c0dc90 571 if(channel > 125) return UESB_ERROR_INVALID_PARAMETERS;
joshuajnoble 0:a01a54c0dc90 572 m_config_local.rf_channel = channel;
joshuajnoble 0:a01a54c0dc90 573 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 574 }
joshuajnoble 0:a01a54c0dc90 575
joshuajnoble 0:a01a54c0dc90 576 uint32_t uesb_set_tx_power(uesb_tx_power_t tx_output_power)
joshuajnoble 0:a01a54c0dc90 577 {
joshuajnoble 0:a01a54c0dc90 578 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE;
joshuajnoble 0:a01a54c0dc90 579 if ( m_config_local.tx_output_power == tx_output_power ) return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 580 m_config_local.tx_output_power = tx_output_power;
joshuajnoble 0:a01a54c0dc90 581 update_radio_parameters();
joshuajnoble 0:a01a54c0dc90 582 return UESB_SUCCESS;
joshuajnoble 0:a01a54c0dc90 583 }
joshuajnoble 0:a01a54c0dc90 584
joshuajnoble 0:a01a54c0dc90 585 void RADIO_IRQHandler()
joshuajnoble 0:a01a54c0dc90 586 {
joshuajnoble 0:a01a54c0dc90 587 if(NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk))
joshuajnoble 0:a01a54c0dc90 588 {
joshuajnoble 0:a01a54c0dc90 589 NRF_RADIO->EVENTS_READY = 0;
joshuajnoble 0:a01a54c0dc90 590
joshuajnoble 0:a01a54c0dc90 591 DEBUG_PIN_SET(DEBUGPIN1);
joshuajnoble 0:a01a54c0dc90 592 }
joshuajnoble 0:a01a54c0dc90 593
joshuajnoble 0:a01a54c0dc90 594 if(NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk))
joshuajnoble 0:a01a54c0dc90 595 {
joshuajnoble 0:a01a54c0dc90 596 NRF_RADIO->EVENTS_END = 0;
joshuajnoble 0:a01a54c0dc90 597
joshuajnoble 0:a01a54c0dc90 598 DEBUG_PIN_SET(DEBUGPIN2);
joshuajnoble 0:a01a54c0dc90 599
joshuajnoble 0:a01a54c0dc90 600 // Call the correct on_radio_end function, depending on the current protocol state
joshuajnoble 0:a01a54c0dc90 601 if(on_radio_end)
joshuajnoble 0:a01a54c0dc90 602 {
joshuajnoble 0:a01a54c0dc90 603 on_radio_end();
joshuajnoble 0:a01a54c0dc90 604 }
joshuajnoble 0:a01a54c0dc90 605 }
joshuajnoble 0:a01a54c0dc90 606
joshuajnoble 0:a01a54c0dc90 607 if(NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk))
joshuajnoble 0:a01a54c0dc90 608 {
joshuajnoble 0:a01a54c0dc90 609 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 610
joshuajnoble 0:a01a54c0dc90 611 DEBUG_PIN_SET(DEBUGPIN3);
joshuajnoble 0:a01a54c0dc90 612
joshuajnoble 0:a01a54c0dc90 613 // Call the correct on_radio_disable function, depending on the current protocol state
joshuajnoble 0:a01a54c0dc90 614 if(on_radio_disabled)
joshuajnoble 0:a01a54c0dc90 615 {
joshuajnoble 0:a01a54c0dc90 616 on_radio_disabled();
joshuajnoble 0:a01a54c0dc90 617 }
joshuajnoble 0:a01a54c0dc90 618 }
joshuajnoble 0:a01a54c0dc90 619
joshuajnoble 0:a01a54c0dc90 620 DEBUG_PIN_CLR(DEBUGPIN1);
joshuajnoble 0:a01a54c0dc90 621 DEBUG_PIN_CLR(DEBUGPIN2);
joshuajnoble 0:a01a54c0dc90 622 DEBUG_PIN_CLR(DEBUGPIN3);
joshuajnoble 0:a01a54c0dc90 623 DEBUG_PIN_CLR(DEBUGPIN4);
joshuajnoble 0:a01a54c0dc90 624 }
joshuajnoble 0:a01a54c0dc90 625
joshuajnoble 0:a01a54c0dc90 626 static void on_radio_disabled_esb_dpl_tx_noack()
joshuajnoble 0:a01a54c0dc90 627 {
joshuajnoble 0:a01a54c0dc90 628 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK;
joshuajnoble 0:a01a54c0dc90 629 tx_fifo_remove_last();
joshuajnoble 0:a01a54c0dc90 630
joshuajnoble 0:a01a54c0dc90 631 if(m_tx_fifo.count == 0)
joshuajnoble 0:a01a54c0dc90 632 {
joshuajnoble 0:a01a54c0dc90 633 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 634 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 635 }
joshuajnoble 0:a01a54c0dc90 636 else
joshuajnoble 0:a01a54c0dc90 637 {
joshuajnoble 0:a01a54c0dc90 638 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 639 start_tx_transaction();
joshuajnoble 0:a01a54c0dc90 640 }
joshuajnoble 0:a01a54c0dc90 641 }
joshuajnoble 0:a01a54c0dc90 642
joshuajnoble 0:a01a54c0dc90 643 static void on_radio_disabled_esb_dpl_tx()
joshuajnoble 0:a01a54c0dc90 644 {
joshuajnoble 0:a01a54c0dc90 645 // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays disabled after the RX window
joshuajnoble 0:a01a54c0dc90 646 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON;
joshuajnoble 0:a01a54c0dc90 647
joshuajnoble 0:a01a54c0dc90 648 // Make sure the timer is started the next time the radio is ready,
joshuajnoble 0:a01a54c0dc90 649 // and that it will disable the radio automatically if no packet is received by the time defined in m_wait_for_ack_timeout_us
joshuajnoble 0:a01a54c0dc90 650 UESB_SYS_TIMER->CC[0] = m_wait_for_ack_timeout_us;
joshuajnoble 0:a01a54c0dc90 651 UESB_SYS_TIMER->CC[1] = m_config_local.retransmit_delay - 130;
joshuajnoble 0:a01a54c0dc90 652 UESB_SYS_TIMER->TASKS_CLEAR = 1;
joshuajnoble 0:a01a54c0dc90 653 UESB_SYS_TIMER->EVENTS_COMPARE[0] = 0;
joshuajnoble 0:a01a54c0dc90 654 UESB_SYS_TIMER->EVENTS_COMPARE[1] = 0;
joshuajnoble 0:a01a54c0dc90 655 NRF_PPI->CHENSET = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP);
joshuajnoble 0:a01a54c0dc90 656 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START);
joshuajnoble 0:a01a54c0dc90 657 NRF_RADIO->EVENTS_END = 0;
joshuajnoble 0:a01a54c0dc90 658 if(m_config_local.protocol == UESB_PROTOCOL_ESB)
joshuajnoble 0:a01a54c0dc90 659 {
joshuajnoble 0:a01a54c0dc90 660 update_rf_payload_format(0);
joshuajnoble 0:a01a54c0dc90 661 }
joshuajnoble 0:a01a54c0dc90 662 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 663 on_radio_disabled = on_radio_disabled_esb_dpl_tx_wait_for_ack;
joshuajnoble 0:a01a54c0dc90 664 m_uesb_mainstate = UESB_STATE_PTX_RX_ACK;
joshuajnoble 0:a01a54c0dc90 665 }
joshuajnoble 0:a01a54c0dc90 666
joshuajnoble 0:a01a54c0dc90 667 static void on_radio_disabled_esb_dpl_tx_wait_for_ack()
joshuajnoble 0:a01a54c0dc90 668 {
joshuajnoble 0:a01a54c0dc90 669 // This marks the completion of a TX_RX sequence (TX with ACK)
joshuajnoble 0:a01a54c0dc90 670
joshuajnoble 0:a01a54c0dc90 671 // Make sure the timer will not deactivate the radio if a packet is received
joshuajnoble 0:a01a54c0dc90 672 NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP);
joshuajnoble 0:a01a54c0dc90 673
joshuajnoble 0:a01a54c0dc90 674 // If the radio has received a packet and the CRC status is OK
joshuajnoble 0:a01a54c0dc90 675 if(NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0)
joshuajnoble 0:a01a54c0dc90 676 {
joshuajnoble 0:a01a54c0dc90 677 UESB_SYS_TIMER->TASKS_STOP = 1;
joshuajnoble 0:a01a54c0dc90 678 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START);
joshuajnoble 0:a01a54c0dc90 679 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK;
joshuajnoble 0:a01a54c0dc90 680 m_last_tx_attempts = m_config_local.retransmit_count - m_retransmits_remaining + 1;
joshuajnoble 0:a01a54c0dc90 681 tx_fifo_remove_last();
joshuajnoble 0:a01a54c0dc90 682 if(m_rx_payload_buffer[0] > 0)
joshuajnoble 0:a01a54c0dc90 683 {
joshuajnoble 0:a01a54c0dc90 684 if(rx_fifo_push_rfbuf((uint8_t)NRF_RADIO->TXADDRESS))
joshuajnoble 0:a01a54c0dc90 685 {
joshuajnoble 0:a01a54c0dc90 686 m_interrupt_flags |= UESB_INT_RX_DR_MSK;
joshuajnoble 0:a01a54c0dc90 687 }
joshuajnoble 0:a01a54c0dc90 688 }
joshuajnoble 0:a01a54c0dc90 689
joshuajnoble 0:a01a54c0dc90 690 if((m_tx_fifo.count == 0) || (m_config_local.tx_mode == UESB_TXMODE_MANUAL))
joshuajnoble 0:a01a54c0dc90 691 {
joshuajnoble 0:a01a54c0dc90 692 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 693 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 694 }
joshuajnoble 0:a01a54c0dc90 695 else
joshuajnoble 0:a01a54c0dc90 696 {
joshuajnoble 0:a01a54c0dc90 697 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 698 start_tx_transaction();
joshuajnoble 0:a01a54c0dc90 699 }
joshuajnoble 0:a01a54c0dc90 700 }
joshuajnoble 0:a01a54c0dc90 701 else
joshuajnoble 0:a01a54c0dc90 702 {
joshuajnoble 0:a01a54c0dc90 703 if(m_retransmits_remaining-- == 0)
joshuajnoble 0:a01a54c0dc90 704 {
joshuajnoble 0:a01a54c0dc90 705 UESB_SYS_TIMER->TASKS_STOP = 1;
joshuajnoble 0:a01a54c0dc90 706 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START);
joshuajnoble 0:a01a54c0dc90 707 // All retransmits are expended, and the TX operation is suspended
joshuajnoble 0:a01a54c0dc90 708 m_last_tx_attempts = m_config_local.retransmit_count + 1;
joshuajnoble 0:a01a54c0dc90 709 m_interrupt_flags |= UESB_INT_TX_FAILED_MSK;
joshuajnoble 0:a01a54c0dc90 710
joshuajnoble 0:a01a54c0dc90 711 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 712 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 713 }
joshuajnoble 0:a01a54c0dc90 714 else
joshuajnoble 0:a01a54c0dc90 715 {
joshuajnoble 0:a01a54c0dc90 716 // We still have more retransmits left, and we should enter TX mode again as soon as the system timer reaches CC[1]
joshuajnoble 0:a01a54c0dc90 717 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk;
joshuajnoble 0:a01a54c0dc90 718 update_rf_payload_format(current_payload->length);
joshuajnoble 0:a01a54c0dc90 719 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 720 on_radio_disabled = on_radio_disabled_esb_dpl_tx;
joshuajnoble 0:a01a54c0dc90 721 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK;
joshuajnoble 0:a01a54c0dc90 722 UESB_SYS_TIMER->TASKS_START = 1;
joshuajnoble 0:a01a54c0dc90 723 NRF_PPI->CHENSET = (1 << UESB_PPI_TX_START);
joshuajnoble 0:a01a54c0dc90 724 if(UESB_SYS_TIMER->EVENTS_COMPARE[1])
joshuajnoble 0:a01a54c0dc90 725 {
joshuajnoble 0:a01a54c0dc90 726 NRF_RADIO->TASKS_TXEN = 1;
joshuajnoble 0:a01a54c0dc90 727 }
joshuajnoble 0:a01a54c0dc90 728 }
joshuajnoble 0:a01a54c0dc90 729 }
joshuajnoble 0:a01a54c0dc90 730 }
joshuajnoble 0:a01a54c0dc90 731
joshuajnoble 0:a01a54c0dc90 732 static void on_radio_disabled_esb_dpl_rx(void)
joshuajnoble 0:a01a54c0dc90 733 {
joshuajnoble 0:a01a54c0dc90 734 bool send_ack = false;
joshuajnoble 0:a01a54c0dc90 735 bool set_rx_interrupt = false;
joshuajnoble 0:a01a54c0dc90 736 if(NRF_RADIO->CRCSTATUS != 0 && m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE)
joshuajnoble 0:a01a54c0dc90 737 {
joshuajnoble 0:a01a54c0dc90 738 send_ack = true;
joshuajnoble 0:a01a54c0dc90 739 }
joshuajnoble 0:a01a54c0dc90 740 if(send_ack)
joshuajnoble 0:a01a54c0dc90 741 {
joshuajnoble 0:a01a54c0dc90 742 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk;
joshuajnoble 0:a01a54c0dc90 743
joshuajnoble 0:a01a54c0dc90 744 // For a packet to be considered new (and not a retransmit) the PID or the CRC has to be different
joshuajnoble 0:a01a54c0dc90 745 if(NRF_RADIO->RXCRC != m_last_rx_packet_crc || (m_rx_payload_buffer[1] >> 1) != m_last_rx_packet_pid)
joshuajnoble 0:a01a54c0dc90 746 {
joshuajnoble 0:a01a54c0dc90 747 if((m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD) && (m_tx_fifo.count > 0))
joshuajnoble 0:a01a54c0dc90 748 {
joshuajnoble 0:a01a54c0dc90 749 // It is assumed that the last ACK payload was recieved.
joshuajnoble 0:a01a54c0dc90 750 if(++m_tx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_tx_fifo.exit_point = 0;
joshuajnoble 0:a01a54c0dc90 751 m_tx_fifo.count--;
joshuajnoble 0:a01a54c0dc90 752
joshuajnoble 0:a01a54c0dc90 753 // ACK payloads also require TX_DS (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf').
joshuajnoble 0:a01a54c0dc90 754 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK;
joshuajnoble 0:a01a54c0dc90 755 }
joshuajnoble 0:a01a54c0dc90 756
joshuajnoble 0:a01a54c0dc90 757 set_rx_interrupt = true;
joshuajnoble 0:a01a54c0dc90 758 m_last_rx_packet_pid = m_rx_payload_buffer[1] >> 1;
joshuajnoble 0:a01a54c0dc90 759 m_last_rx_packet_crc = NRF_RADIO->RXCRC;
joshuajnoble 0:a01a54c0dc90 760 }
joshuajnoble 0:a01a54c0dc90 761
joshuajnoble 0:a01a54c0dc90 762 if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL)
joshuajnoble 0:a01a54c0dc90 763 {
joshuajnoble 0:a01a54c0dc90 764 if(m_tx_fifo.count > 0)
joshuajnoble 0:a01a54c0dc90 765 {
joshuajnoble 0:a01a54c0dc90 766 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point];
joshuajnoble 0:a01a54c0dc90 767
joshuajnoble 0:a01a54c0dc90 768 update_rf_payload_format(current_payload->length);
joshuajnoble 0:a01a54c0dc90 769 m_tx_payload_buffer[0] = current_payload->length;
joshuajnoble 0:a01a54c0dc90 770 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length);
joshuajnoble 0:a01a54c0dc90 771
joshuajnoble 0:a01a54c0dc90 772 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK_PAYLOAD;
joshuajnoble 0:a01a54c0dc90 773 }
joshuajnoble 0:a01a54c0dc90 774 else
joshuajnoble 0:a01a54c0dc90 775 {
joshuajnoble 0:a01a54c0dc90 776 update_rf_payload_format(0);
joshuajnoble 0:a01a54c0dc90 777 m_tx_payload_buffer[0] = 0;
joshuajnoble 0:a01a54c0dc90 778
joshuajnoble 0:a01a54c0dc90 779 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK;
joshuajnoble 0:a01a54c0dc90 780 }
joshuajnoble 0:a01a54c0dc90 781
joshuajnoble 0:a01a54c0dc90 782 m_tx_payload_buffer[1] = m_rx_payload_buffer[1];
joshuajnoble 0:a01a54c0dc90 783 }
joshuajnoble 0:a01a54c0dc90 784 else if(m_config_local.protocol == UESB_PROTOCOL_ESB)
joshuajnoble 0:a01a54c0dc90 785 {
joshuajnoble 0:a01a54c0dc90 786 m_tx_payload_buffer[0] = m_rx_payload_buffer[0];
joshuajnoble 0:a01a54c0dc90 787 m_tx_payload_buffer[1] = 0;
joshuajnoble 0:a01a54c0dc90 788
joshuajnoble 0:a01a54c0dc90 789 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK;
joshuajnoble 0:a01a54c0dc90 790 }
joshuajnoble 0:a01a54c0dc90 791
joshuajnoble 0:a01a54c0dc90 792 NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH;
joshuajnoble 0:a01a54c0dc90 793 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 794
joshuajnoble 0:a01a54c0dc90 795 on_radio_disabled = on_radio_disabled_esb_dpl_rx_ack;
joshuajnoble 0:a01a54c0dc90 796 }
joshuajnoble 0:a01a54c0dc90 797 else
joshuajnoble 0:a01a54c0dc90 798 {
joshuajnoble 0:a01a54c0dc90 799 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON;
joshuajnoble 0:a01a54c0dc90 800 update_rf_payload_format(m_config_local.payload_length);
joshuajnoble 0:a01a54c0dc90 801 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 802 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 803 NRF_RADIO->TASKS_DISABLE = 1;
joshuajnoble 0:a01a54c0dc90 804 while(NRF_RADIO->EVENTS_DISABLED == 0);
joshuajnoble 0:a01a54c0dc90 805 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 806 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk;
joshuajnoble 0:a01a54c0dc90 807 NRF_RADIO->TASKS_RXEN = 1;
joshuajnoble 0:a01a54c0dc90 808 }
joshuajnoble 0:a01a54c0dc90 809 if(set_rx_interrupt)
joshuajnoble 0:a01a54c0dc90 810 {
joshuajnoble 0:a01a54c0dc90 811 rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH);
joshuajnoble 0:a01a54c0dc90 812 m_interrupt_flags |= UESB_INT_RX_DR_MSK;
joshuajnoble 0:a01a54c0dc90 813 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 814 }
joshuajnoble 0:a01a54c0dc90 815 }
joshuajnoble 0:a01a54c0dc90 816
joshuajnoble 0:a01a54c0dc90 817 static void on_radio_disabled_esb_dpl_rx_ack(void)
joshuajnoble 0:a01a54c0dc90 818 {
joshuajnoble 0:a01a54c0dc90 819 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk;
joshuajnoble 0:a01a54c0dc90 820 update_rf_payload_format(m_config_local.payload_length);
joshuajnoble 0:a01a54c0dc90 821 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
joshuajnoble 0:a01a54c0dc90 822 on_radio_disabled = on_radio_disabled_esb_dpl_rx;
joshuajnoble 0:a01a54c0dc90 823
joshuajnoble 0:a01a54c0dc90 824 if(m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK)
joshuajnoble 0:a01a54c0dc90 825 {
joshuajnoble 0:a01a54c0dc90 826 // In the case of UESB_STATE_PRX_SEND_ACK_PAYLOAD the state will be updated when the next packet is received.
joshuajnoble 0:a01a54c0dc90 827 m_uesb_mainstate = UESB_STATE_PRX;
joshuajnoble 0:a01a54c0dc90 828 }
joshuajnoble 0:a01a54c0dc90 829 }
joshuajnoble 0:a01a54c0dc90 830
joshuajnoble 0:a01a54c0dc90 831 static void on_radio_end_sb_tx(void)
joshuajnoble 0:a01a54c0dc90 832 {
joshuajnoble 0:a01a54c0dc90 833 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK;
joshuajnoble 0:a01a54c0dc90 834 tx_fifo_remove_last();
joshuajnoble 0:a01a54c0dc90 835 if(m_config_local.tx_mode == UESB_TXMODE_MANUAL || m_tx_fifo.count == 0)
joshuajnoble 0:a01a54c0dc90 836 {
joshuajnoble 0:a01a54c0dc90 837 // No more packets to send. Disable the radio and set the state to idle.
joshuajnoble 0:a01a54c0dc90 838 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 839 NRF_RADIO->TASKS_DISABLE = 1;
joshuajnoble 0:a01a54c0dc90 840 while(!NRF_RADIO->EVENTS_DISABLED);
joshuajnoble 0:a01a54c0dc90 841 NRF_RADIO->EVENTS_DISABLED = 0;
joshuajnoble 0:a01a54c0dc90 842 m_uesb_mainstate = UESB_STATE_IDLE;
joshuajnoble 0:a01a54c0dc90 843 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 844 }
joshuajnoble 0:a01a54c0dc90 845 else
joshuajnoble 0:a01a54c0dc90 846 {
joshuajnoble 0:a01a54c0dc90 847 // Send another packet automatically without disabling the radio first.
joshuajnoble 0:a01a54c0dc90 848 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point];
joshuajnoble 0:a01a54c0dc90 849
joshuajnoble 0:a01a54c0dc90 850 update_rf_payload_format(current_payload->length);
joshuajnoble 0:a01a54c0dc90 851 memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length);
joshuajnoble 0:a01a54c0dc90 852
joshuajnoble 0:a01a54c0dc90 853 NRF_RADIO->TXADDRESS = current_payload->pipe;
joshuajnoble 0:a01a54c0dc90 854
joshuajnoble 0:a01a54c0dc90 855 NVIC_ClearPendingIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 856 NVIC_EnableIRQ(RADIO_IRQn);
joshuajnoble 0:a01a54c0dc90 857
joshuajnoble 0:a01a54c0dc90 858 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = 0;
joshuajnoble 0:a01a54c0dc90 859 NRF_RADIO->TASKS_START = 1;
joshuajnoble 0:a01a54c0dc90 860
joshuajnoble 0:a01a54c0dc90 861 }
joshuajnoble 0:a01a54c0dc90 862 }
joshuajnoble 0:a01a54c0dc90 863
joshuajnoble 0:a01a54c0dc90 864 static void on_radio_end_sb_rx(void)
joshuajnoble 0:a01a54c0dc90 865 {
joshuajnoble 0:a01a54c0dc90 866 if(NRF_RADIO->CRCSTATUS != 0 && rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH))
joshuajnoble 0:a01a54c0dc90 867 {
joshuajnoble 0:a01a54c0dc90 868 m_interrupt_flags |= UESB_INT_RX_DR_MSK;
joshuajnoble 0:a01a54c0dc90 869 if(m_event_handler != 0) m_event_handler();
joshuajnoble 0:a01a54c0dc90 870 }
joshuajnoble 0:a01a54c0dc90 871 }