1*042d53a7SEvalZero /*
2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file
4*042d53a7SEvalZero * distributed with this work for additional information
5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file
6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at
9*042d53a7SEvalZero *
10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero * software distributed under the License is distributed on an
14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero * KIND, either express or implied. See the License for the
16*042d53a7SEvalZero * specific language governing permissions and limitations
17*042d53a7SEvalZero * under the License.
18*042d53a7SEvalZero */
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include <stdint.h>
21*042d53a7SEvalZero #include <stddef.h>
22*042d53a7SEvalZero #include <assert.h>
23*042d53a7SEvalZero #include <stddef.h>
24*042d53a7SEvalZero #include "syscfg/syscfg.h"
25*042d53a7SEvalZero #include "os/os_cputime.h"
26*042d53a7SEvalZero #include "controller/ble_phy.h"
27*042d53a7SEvalZero #include "controller/ble_ll.h"
28*042d53a7SEvalZero #include "controller/ble_ll_xcvr.h"
29*042d53a7SEvalZero
30*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
31*042d53a7SEvalZero int
ble_ll_xcvr_rfclk_state(void)32*042d53a7SEvalZero ble_ll_xcvr_rfclk_state(void)
33*042d53a7SEvalZero {
34*042d53a7SEvalZero uint32_t expiry;
35*042d53a7SEvalZero
36*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
37*042d53a7SEvalZero expiry = g_ble_ll_data.ll_rfclk_start_time;
38*042d53a7SEvalZero if ((int32_t)(os_cputime_get32() - expiry) >
39*042d53a7SEvalZero g_ble_ll_data.ll_xtal_ticks) {
40*042d53a7SEvalZero g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_SETTLED;
41*042d53a7SEvalZero }
42*042d53a7SEvalZero }
43*042d53a7SEvalZero return g_ble_ll_data.ll_rfclk_state;
44*042d53a7SEvalZero }
45*042d53a7SEvalZero
46*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_enable(void)47*042d53a7SEvalZero ble_ll_xcvr_rfclk_enable(void)
48*042d53a7SEvalZero {
49*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
50*042d53a7SEvalZero g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_ON;
51*042d53a7SEvalZero ble_phy_rfclk_enable();
52*042d53a7SEvalZero }
53*042d53a7SEvalZero }
54*042d53a7SEvalZero
55*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_disable(void)56*042d53a7SEvalZero ble_ll_xcvr_rfclk_disable(void)
57*042d53a7SEvalZero {
58*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_state != BLE_RFCLK_STATE_OFF) {
59*042d53a7SEvalZero ble_phy_rfclk_disable();
60*042d53a7SEvalZero g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_OFF;
61*042d53a7SEvalZero }
62*042d53a7SEvalZero }
63*042d53a7SEvalZero
64*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_stop(void)65*042d53a7SEvalZero ble_ll_xcvr_rfclk_stop(void)
66*042d53a7SEvalZero {
67*042d53a7SEvalZero os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
68*042d53a7SEvalZero ble_ll_xcvr_rfclk_disable();
69*042d53a7SEvalZero }
70*042d53a7SEvalZero
71*042d53a7SEvalZero uint32_t
ble_ll_xcvr_rfclk_time_till_settled(void)72*042d53a7SEvalZero ble_ll_xcvr_rfclk_time_till_settled(void)
73*042d53a7SEvalZero {
74*042d53a7SEvalZero int32_t dt;
75*042d53a7SEvalZero uint32_t rc;
76*042d53a7SEvalZero
77*042d53a7SEvalZero rc = 0;
78*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
79*042d53a7SEvalZero dt = (int32_t)(os_cputime_get32() - g_ble_ll_data.ll_rfclk_start_time);
80*042d53a7SEvalZero BLE_LL_ASSERT(dt >= 0);
81*042d53a7SEvalZero if (dt < g_ble_ll_data.ll_xtal_ticks) {
82*042d53a7SEvalZero rc = g_ble_ll_data.ll_xtal_ticks - (uint32_t)dt;
83*042d53a7SEvalZero }
84*042d53a7SEvalZero }
85*042d53a7SEvalZero
86*042d53a7SEvalZero return rc;
87*042d53a7SEvalZero }
88*042d53a7SEvalZero
89*042d53a7SEvalZero /**
90*042d53a7SEvalZero * Called when the timer to turn on the RF CLOCK expires. This function checks
91*042d53a7SEvalZero * the state of the clock. If the clock is off, the clock is turned on.
92*042d53a7SEvalZero * Otherwise, we just exit.
93*042d53a7SEvalZero *
94*042d53a7SEvalZero * Context: Interrupt
95*042d53a7SEvalZero *
96*042d53a7SEvalZero * @param arg
97*042d53a7SEvalZero */
98*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_timer_exp(void * arg)99*042d53a7SEvalZero ble_ll_xcvr_rfclk_timer_exp(void *arg)
100*042d53a7SEvalZero {
101*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
102*042d53a7SEvalZero ble_ll_xcvr_rfclk_start_now(os_cputime_get32());
103*042d53a7SEvalZero }
104*042d53a7SEvalZero }
105*042d53a7SEvalZero
106*042d53a7SEvalZero /**
107*042d53a7SEvalZero * This API is used to turn on the rfclock without setting the cputime timer to
108*042d53a7SEvalZero * start the clock at some later point.
109*042d53a7SEvalZero *
110*042d53a7SEvalZero * NOTE: presumes that the state of the rf clock was checked prior to calling.
111*042d53a7SEvalZero *
112*042d53a7SEvalZero * @param now
113*042d53a7SEvalZero */
114*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_start_now(uint32_t now)115*042d53a7SEvalZero ble_ll_xcvr_rfclk_start_now(uint32_t now)
116*042d53a7SEvalZero {
117*042d53a7SEvalZero ble_ll_xcvr_rfclk_enable();
118*042d53a7SEvalZero g_ble_ll_data.ll_rfclk_start_time = now;
119*042d53a7SEvalZero }
120*042d53a7SEvalZero
121*042d53a7SEvalZero /**
122*042d53a7SEvalZero * Starts the timer that will turn the rf clock on. The 'cputime' is
123*042d53a7SEvalZero * the time at which the clock needs to be settled.
124*042d53a7SEvalZero *
125*042d53a7SEvalZero * @param cputime Time at which rfclock should be on and settled.
126*042d53a7SEvalZero */
127*042d53a7SEvalZero void
ble_ll_xcvr_rfclk_timer_start(uint32_t cputime)128*042d53a7SEvalZero ble_ll_xcvr_rfclk_timer_start(uint32_t cputime)
129*042d53a7SEvalZero {
130*042d53a7SEvalZero /*
131*042d53a7SEvalZero * If we are currently in an advertising event or a connection event,
132*042d53a7SEvalZero * no need to start the cputime timer
133*042d53a7SEvalZero */
134*042d53a7SEvalZero if ((g_ble_ll_data.ll_state == BLE_LL_STATE_ADV) ||
135*042d53a7SEvalZero (g_ble_ll_data.ll_state == BLE_LL_STATE_CONNECTION)) {
136*042d53a7SEvalZero return;
137*042d53a7SEvalZero }
138*042d53a7SEvalZero
139*042d53a7SEvalZero /* Account for the settling time */
140*042d53a7SEvalZero cputime -= g_ble_ll_data.ll_xtal_ticks;
141*042d53a7SEvalZero
142*042d53a7SEvalZero /*
143*042d53a7SEvalZero * If the timer is on the list, we need to see if its expiry is before
144*042d53a7SEvalZero * 'cputime'. If the expiry is before, no need to do anything. If it
145*042d53a7SEvalZero * is after, we need to stop the timer and start at new time.
146*042d53a7SEvalZero */
147*042d53a7SEvalZero if (g_ble_ll_data.ll_rfclk_timer.link.tqe_prev != NULL) {
148*042d53a7SEvalZero if ((int32_t)(cputime - g_ble_ll_data.ll_rfclk_timer.expiry) >= 0) {
149*042d53a7SEvalZero return;
150*042d53a7SEvalZero }
151*042d53a7SEvalZero os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
152*042d53a7SEvalZero }
153*042d53a7SEvalZero os_cputime_timer_start(&g_ble_ll_data.ll_rfclk_timer, cputime);
154*042d53a7SEvalZero }
155*042d53a7SEvalZero #endif
156