Appiko
radio_trigger.c
1 /*
2  * radio_trigger.c : Module to send trigger wireless-ly using 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 "radio_trigger.h"
20 #include "hal_radio.h"
21 #include "nrf52810.h"
22 
23 #if ISR_MANAGER == 1
24 #include "isr_manager.h"
25 #include "nrf52810_bitfields.h"
26 #include "log.h"
27 #endif
28 
33 #define TIMER_USED TIMER_USED_RADIO_TRIGGER
34 #define TIMER_ID CONCAT_2(NRF_TIMER,TIMER_USED)
35 
36 #define TIMER_IRQN TIMER_IRQN_a(TIMER_USED)
37 #define TIMER_IRQ_Handler TIMER_IRQ_Handler_a(TIMER_USED)
38 
39 #define TIMER_IRQN_a(n) TIMER_IRQN_b(n)
40 #define TIMER_IRQN_b(n) TIMER##n##_IRQn
41 
42 #define TIMER_IRQ_Handler_a(n) TIMER_IRQ_Handler_b(n)
43 #define TIMER_IRQ_Handler_b(n) TIMER##n##_IRQHandler
44 
46 #define TIMER_1MHz_PRESCALAR 4
47 
48 #define TIMER_INTEN_OFFSET 16
49 
50 #define TIMER_CHANNEL_COMMON_STARTUP TIMER_CHANNEL_USED_RADIO_TRIGGER_0
51 
52 #define TIMER_CHANNEL_RX_ON TIMER_CHANNEL_USED_RADIO_TRIGGER_1
53 
54 #define TIMER_CHANNEL_TX_ON TIMER_CHANNEL_USED_RADIO_TRIGGER_1
55 #define TIMER_CHANNEL_TX_FREQ TIMER_CHANNEL_USED_RADIO_TRIGGER_2
56 
57 #define XTAL_STARTUP_TIME 450
58 
59 #define MS_TO_US_CONV(n) (n * 1000)
60 
61 //static uint32_t radio_rx_on_ticks = 0;
62 
63 //static uint32_t radio_tx_on_ticks = 0;
64 
65 static uint32_t radio_tx_freq_ticks = 0;
66 
67 static radio_trigger_dir_t radio_dir = RADIO_TRIGGER_Tx;
68 
69 volatile bool is_radio_free = true;
70 
71 void (* p_radio_rx_handler) (void * p_data, uint32_t len);
72 void (* p_radio_tx_handler) (void * p_data, uint32_t len);
73 
74 hal_radio_config_t radio_config;
75 
76 app_irq_priority_t radio_trig_irq_priority;
77 
78 void radio_trigger_init (radio_trigger_init_t* radio_trig_init)
79 {
80  p_radio_rx_handler = radio_trig_init->radio_trigger_rx_callback;
81  p_radio_tx_handler = radio_trig_init->radio_trigger_tx_callback;
82  radio_trig_irq_priority = radio_trig_init->irq_priority;
83  radio_dir = radio_trig_init->comm_direction;
84  {
85  radio_config.freq = radio_trig_init->comm_freq;
86  radio_config.irq_priority = radio_trig_init->irq_priority;
87  radio_config.rx_done_handler = p_radio_rx_handler;
88  }
89 
90  TIMER_ID->MODE = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk;
91 
92  TIMER_ID->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
93 
94  TIMER_ID->PRESCALER = TIMER_1MHz_PRESCALAR;
95  TIMER_ID->CC[TIMER_CHANNEL_COMMON_STARTUP] = XTAL_STARTUP_TIME;
96  if(radio_trig_init->comm_direction == RADIO_TRIGGER_Tx)
97  {
98  TIMER_ID->INTENSET =
99  (1 << (TIMER_CHANNEL_COMMON_STARTUP + TIMER_INTEN_OFFSET)) |
100  (1 << (TIMER_CHANNEL_TX_ON + TIMER_INTEN_OFFSET)) |
101  (1 << (TIMER_CHANNEL_TX_FREQ + TIMER_INTEN_OFFSET)) ;
102  TIMER_ID->CC[TIMER_CHANNEL_TX_ON] =
103  (MS_TO_US_CONV(radio_trig_init->tx_on_time_ms) + XTAL_STARTUP_TIME);
104  TIMER_ID->CC[TIMER_CHANNEL_TX_FREQ] = radio_trig_init->tx_on_freq_us+ XTAL_STARTUP_TIME;
105  radio_tx_freq_ticks = radio_trig_init->tx_on_freq_us;
106  }
107  else
108  {
109  TIMER_ID->CC[TIMER_CHANNEL_RX_ON] = MS_TO_US_CONV(radio_trig_init->rx_on_time_ms) + XTAL_STARTUP_TIME;
110  TIMER_ID->INTENSET =
111  (1 << (TIMER_CHANNEL_COMMON_STARTUP + TIMER_INTEN_OFFSET)) |
112  (1 << (TIMER_CHANNEL_RX_ON + TIMER_INTEN_OFFSET));
113  }
114 
115 
116  NVIC_SetPriority (TIMER_IRQN, radio_trig_init->irq_priority);
117  NVIC_EnableIRQ (TIMER_IRQN);
118 
119 }
120 
121 void radio_trigger_yell ()
122 {
123  is_radio_free = false;
124  TIMER_ID->CC[TIMER_CHANNEL_TX_FREQ] = radio_tx_freq_ticks + XTAL_STARTUP_TIME;
125 
126  TIMER_ID->TASKS_START = 1;
127  hal_radio_init (&radio_config);
128  NVIC_SetPriority (TIMER_IRQN, radio_trig_irq_priority);
129  NVIC_EnableIRQ (TIMER_IRQN);
130 }
131 
132 void radio_trigger_listen ()
133 {
134  is_radio_free = false;
135  TIMER_ID->TASKS_START = 1;
136  hal_radio_init (&radio_config);
137  NVIC_SetPriority (TIMER_IRQN, radio_trig_irq_priority);
138  NVIC_EnableIRQ (TIMER_IRQN);
139 }
140 
141 void radio_trigger_shut ()
142 {
143  TIMER_ID->TASKS_STOP = 1;
144  TIMER_ID->TASKS_SHUTDOWN = 1;
145  NVIC_DisableIRQ (TIMER_IRQN);
146  hal_radio_deinit ();
147  is_radio_free = true;
148 }
149 
150 #if ISR_MANAGER == true
151 void radio_trigger_timer_Handler ()
152 #else
153 void TIMER_IRQ_Handler ()
154 #endif
155 {
156  if(radio_dir == RADIO_TRIGGER_Tx)
157  {
158  if(TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_COMMON_STARTUP] == true)
159  {
160 #if ISR_MANAGER == false
161  TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_COMMON_STARTUP] = false;
162 #endif
163  log_printf("%s\n", __func__);
165  }
166 
167  if(TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_TX_FREQ] == true)
168  {
169 #if ISR_MANAGER == false
170  TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_TX_FREQ] = false;
171 #endif
173  TIMER_ID->CC[TIMER_CHANNEL_TX_FREQ] += radio_tx_freq_ticks;
174  log_printf("CC[%d] : %d\n", TIMER_CHANNEL_TX_FREQ, TIMER_ID->CC[TIMER_CHANNEL_TX_FREQ]);
175  }
176 
177  if(TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_TX_ON])
178  {
179 #if ISR_MANAGER == false
180  TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_TX_ON] = false;
181 #endif
182  TIMER_ID->TASKS_CLEAR = 1;
183  TIMER_ID->TASKS_STOP = 1;
184  TIMER_ID->TASKS_SHUTDOWN = 1;
185  (void) TIMER_ID->TASKS_SHUTDOWN;
186  hal_radio_deinit ();
187  is_radio_free = true;
188  }
189  }
190  else
191  {
192  if(TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_COMMON_STARTUP] == true)
193  {
194 #if ISR_MANAGER == false
195  TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_COMMON_STARTUP] = false;
196 #endif
198  }
199 
200  if(TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_RX_ON])
201  {
202 #if ISR_MANAGER == false
203  TIMER_ID->EVENTS_COMPARE[TIMER_CHANNEL_RX_ON] = false;
204 #endif
205  TIMER_ID->TASKS_CLEAR = 1;
206  TIMER_ID->TASKS_STOP = 1;
207  TIMER_ID->TASKS_SHUTDOWN = 1;
208  (void) TIMER_ID->TASKS_SHUTDOWN;
209  hal_radio_deinit ();
210  is_radio_free = true;
211  }
212  }
213 }
214 
215 void radio_trigger_memorize_data (void * data, uint32_t len)
216 {
217  hal_radio_set_tx_payload_data (data, len);
218 }
219 
220 bool is_radio_trigger_availabel ()
221 {
222  return is_radio_free;
223 }
void hal_radio_deinit()
Function to de-initiate the radio peripheral.
Definition: hal_radio.c:167
void hal_radio_start_rx()
Function to start data reception.
Definition: hal_radio.c:156
app_irq_priority_t
Priority levels that the application can use based on whether the SoftDevice (SD) is used.
Definition: nrf_util.h:63
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
app_irq_priority_t irq_priority
Definition: hal_radio.h:44