1 /*
2  * Copyright (c) 2017 Oticon A/S
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * RADIO Bitcounter functionality
8  * We treat it as a sub-peripheral
9  *
10  * Notes:
11  *   * If the bitcounter is started in a CodedPhy packet during FEC1, FEC2 has a different
12  *     coding rate, and the BCC value gets it into the FEC2, the bitcounter model behavior
13  *     will not be correct (it will keep counting at the bit rate of the FEC1)
14  *     (It is unclear how the real RADIO HW handles this)
15  */
16 #include "bs_types.h"
17 #include "bs_tracing.h"
18 #include "NHW_common_types.h"
19 #include "NHW_config.h"
20 #include "NHW_peri_types.h"
21 #include "NHW_RADIO.h"
22 #include "NHW_RADIO_signals.h"
23 #include "nsi_hw_scheduler.h"
24 #include "nsi_tasks.h"
25 #include "nsi_hws_models_if.h"
26 
27 static bs_time_t Timer_RADIO_bitcounter = TIME_NEVER;
28 
29 static bs_time_t Time_BitCounterStarted = TIME_NEVER;
30 static bool bit_counter_running = false;
31 
32 extern NRF_RADIO_Type NRF_RADIO_regs;
33 
nrf_radio_bitcounter_timer_triggered(void)34 static void nrf_radio_bitcounter_timer_triggered(void) {
35   nhw_RADIO_signal_EVENTS_BCMATCH(0);
36   Timer_RADIO_bitcounter = TIME_NEVER;
37   nsi_hws_find_next_event();
38   //Note that we leave the bit counter running, so a new BCC can be programmed to make it trigger later
39 }
40 
41 NSI_HW_EVENT(Timer_RADIO_bitcounter, nrf_radio_bitcounter_timer_triggered, 50);
42 
nhw_RADIO_TASK_BCSTART(void)43 void nhw_RADIO_TASK_BCSTART(void) {
44   /* Note that we do not validate that the end of the address has been received */
45 
46   if (bit_counter_running) {
47     bs_trace_warning_line_time("NRF_RADIO: BCSTART received while the bitcounter was already running."
48         "New BCSTART is just ignored\n");
49     return;
50   }
51   bit_counter_running = true;
52   Time_BitCounterStarted = nsi_hws_get_time();
53   Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nhw_radio_get_bpus();
54   nsi_hws_find_next_event();
55 }
56 
nhw_radio_stop_bit_counter(void)57 void nhw_radio_stop_bit_counter(void) {
58   if (!bit_counter_running){
59     return;
60   }
61   bit_counter_running = false;
62   if (Timer_RADIO_bitcounter != TIME_NEVER) {
63     Timer_RADIO_bitcounter = TIME_NEVER;
64     nsi_hws_find_next_event();
65   }
66 }
67 
nhw_RADIO_TASK_BCSTOP(void)68 void nhw_RADIO_TASK_BCSTOP(void) {
69   nhw_radio_stop_bit_counter();
70 }
71 
nhw_RADIO_regw_sideeffects_BCC(void)72 void nhw_RADIO_regw_sideeffects_BCC(void) {
73   if (!bit_counter_running){
74     return;
75   }
76   Timer_RADIO_bitcounter = Time_BitCounterStarted + NRF_RADIO_regs.BCC/nhw_radio_get_bpus();
77   if (Timer_RADIO_bitcounter < nsi_hws_get_time()) {
78     bs_trace_warning_line_time("NRF_RADIO: Reprogrammed bitcounter with a BCC which has already"
79         "passed (%"PRItime") => we ignore it\n",
80         Timer_RADIO_bitcounter);
81     Timer_RADIO_bitcounter = TIME_NEVER;
82   }
83   nsi_hws_find_next_event();
84 }
85