Appiko
hal_radio.c
1 /*
2  * hal_radio.c : Basic driver for Radio peripheral
3  * Copyright (C) 2019 Appiko
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #include <stddef.h>
20 #include "string.h"
21 
22 #include "hal_radio.h"
23 #include "nrf.h"
24 
25 #if ISR_MANAGER == 1
26 #include "isr_manager.h"
27 #endif
28 
29 
31 #define SHORT_READY_START \
32  (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos)
33 
34 #define SHORT_END_DIS \
35  (RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos)
36 
37 #define SHORT_DIS_TXEN \
38  (RADIO_SHORTS_DISABLED_TXEN_Enabled << RADIO_SHORTS_DISABLED_TXEN_Pos)
39 
40 #define SHORT_DIS_RXEN \
41  (RADIO_SHORTS_DISABLED_RXEN_Enabled << RADIO_SHORTS_DISABLED_RXEN_Pos)
42 
43 
45 #define MAX_PAYLOAD_BYTES 255
46 
48 #define ADDR 0x8E89BE35
49 
51 #define LEN_OFFSET 0
52 
54 #define DATA_OFFSET 1
55 
59 typedef struct
60 {
62  uint8_t payload_len;
64  uint8_t p_payload[MAX_PAYLOAD_BYTES - 1];
65 }payload_t;
66 
68 static payload_t payload_buff;
69 
71 void (* pb_tx_done_handler) (void * buff, uint32_t len);
73 void (* pb_rx_done_handler) (void * buff, uint32_t len);
74 
75 void hal_radio_init (hal_radio_config_t * radio_init_config)
76 {
77  if(radio_init_config->tx_done_handler != NULL)
78  {
79  pb_tx_done_handler = radio_init_config->tx_done_handler;
80  }
81  if(radio_init_config->rx_done_handler != NULL)
82  {
83  pb_rx_done_handler = radio_init_config->rx_done_handler;
84  }
85 
87  if(NRF_CLOCK->HFCLKSTAT !=
88  ((CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos) |
89  (CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos)))
90  {
91  NRF_CLOCK->TASKS_HFCLKSTART = 1;
92  }
93 
94  //Power on Radio
95  NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled;
96 
97  //Set mode to BLE 2Mbps
98  NRF_RADIO->MODE = (RADIO_MODE_MODE_Ble_2Mbit << RADIO_MODE_MODE_Pos)&RADIO_MODE_MODE_Msk;
99 
100  //Configure payload package
101  NRF_RADIO->PCNF0 = ((0UL << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk)
102  | ((8UL << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk)
103  | ((0UL << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk);
104 
105  NRF_RADIO->PCNF1 = ((RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk)
106  | ((MAX_PAYLOAD_BYTES << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)
107  | ((RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk)
108  | ((3UL << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk);
109 
110  //Configure Address
111  NRF_RADIO->CRCCNF = ((RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) & RADIO_CRCCNF_LEN_Msk)
112  | ((RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) & RADIO_CRCCNF_SKIPADDR_Msk);
113 
114  NRF_RADIO->CRCPOLY = 0x100065B;
115 
116 
117  //Configure freq
118  NRF_RADIO->DATAWHITEIV = 0x8888;
119  NRF_RADIO->FREQUENCY = radio_init_config->freq;
120 
121 
122 
123  NRF_RADIO->BASE0 = (ADDR << 8) & 0xFFFFFF00;
124  NRF_RADIO->PREFIX0 = (ADDR >> 24) & 0xFF;
125  NRF_RADIO->CRCINIT = 0x012345;
126 
127  NRF_RADIO->TXADDRESS =((0<<RADIO_TXADDRESS_TXADDRESS_Pos)&RADIO_TXADDRESS_TXADDRESS_Msk);
128  NRF_RADIO->TXPOWER = 4;
129 
130  NRF_RADIO->RXADDRESSES = ((RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos)
131  & RADIO_RXADDRESSES_ADDR0_Msk);
132 
133  //enable related interrupts and shorts
134  NRF_RADIO->INTENSET |= ((RADIO_INTENSET_CRCERROR_Enabled
135  << RADIO_INTENSET_CRCERROR_Pos) & RADIO_INTENSET_CRCERROR_Msk)
136  | ((RADIO_INTENSET_END_Enabled << RADIO_INTENSET_END_Pos) & RADIO_INTENSET_END_Msk)
137  | ((RADIO_INTENSET_CRCOK_Enabled << RADIO_INTENSET_CRCOK_Pos) & RADIO_INTENSET_CRCOK_Msk);
138  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
139  NRF_RADIO->PACKETPTR = (uint32_t) &payload_buff;
140  NVIC_SetPriority (RADIO_IRQn, radio_init_config->irq_priority);
141  NVIC_EnableIRQ (RADIO_IRQn);
142 }
143 
144 void hal_radio_set_tx_payload_data (void * p_payload, uint32_t len)
145 {
146  payload_buff.payload_len = len + 1;
147  memcpy (payload_buff.p_payload, p_payload, len);
148 }
149 
151 {
152  NRF_RADIO->TASKS_TXEN = 1;
153 
154 }
155 
157 {
158  NRF_RADIO->TASKS_RXEN = 1;
159 }
160 
162 {
163  NRF_RADIO->TASKS_DISABLE = 1;
164  NRF_RADIO->TASKS_STOP = 1;
165 }
166 
168 {
169  NVIC_DisableIRQ (RADIO_IRQn);
170  NRF_RADIO->INTENCLR = 0xFFFFFFFF;
171  NRF_RADIO->TASKS_DISABLE = 1;
172  NRF_RADIO->POWER = (RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos) &
173  RADIO_POWER_POWER_Msk;
174 }
175 
177 {
178  return (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) ? true : false;
179 }
180 
181 
182 #if ISR_MANAGER == 1
183 void hal_radio_Handler ()
184 #else
185 void RADIO_IRQHandler ()
186 #endif
187 {
188  if(NRF_RADIO->EVENTS_CRCOK == 1)
189  {
190 #if ISR_MANAGER == false
191  NRF_RADIO->EVENTS_CRCOK = 0;
192 #endif
193  if(pb_rx_done_handler != NULL)
194  {
195  pb_rx_done_handler (payload_buff.p_payload, payload_buff.payload_len - 1);
196  }
197  }
198  if(NRF_RADIO->EVENTS_CRCERROR == 1)
199  {
200 #if ISR_MANAGER == false
201  NRF_RADIO->EVENTS_CRCERROR = 0;
202 #endif
203 
204  }
205  if(NRF_RADIO->EVENTS_END == 1)
206  {
207 #if ISR_MANAGER == false
208  NRF_RADIO->EVENTS_END = 0;
209 #endif
210  if(pb_tx_done_handler != NULL)
211  {
212  pb_tx_done_handler (payload_buff.p_payload, payload_buff.payload_len - 1);
213  }
214  }
215 }
bool hal_radio_is_on()
Function to check status of radio peripheral.
Definition: hal_radio.c:176
void hal_radio_deinit()
Function to de-initiate the radio peripheral.
Definition: hal_radio.c:167
Structure to store payload.
Definition: hal_radio.c:59
void hal_radio_start_rx()
Function to start data reception.
Definition: hal_radio.c:156
uint8_t payload_len
Definition: hal_radio.c:62
void hal_radio_set_tx_payload_data(void *p_payload, uint32_t len)
Function to Set the payload data for transmission.
Definition: hal_radio.c:144
void hal_radio_init(hal_radio_config_t *radio_init_config)
Function to Initiate Radio peripheral.
Definition: hal_radio.c:75
void hal_radio_start_tx()
Function to start data transmission.
Definition: hal_radio.c:150
void(* rx_done_handler)(void *p_buff, uint32_t len)
Definition: hal_radio.h:48
Structure used to store the data required for radio configuration.
Definition: hal_radio.h:39
void(* tx_done_handler)(void *p_buff, uint32_t len)
Definition: hal_radio.h:46
uint8_t p_payload[MAX_PAYLOAD_BYTES - 1]
Definition: hal_radio.c:64
void hal_radio_stop()
Function to stop radio peripheral.
Definition: hal_radio.c:161
app_irq_priority_t irq_priority
Definition: hal_radio.h:44