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 <string.h>
22*042d53a7SEvalZero #include <assert.h>
23*042d53a7SEvalZero #include "syscfg/syscfg.h"
24*042d53a7SEvalZero #include "os/os.h"
25*042d53a7SEvalZero #include "ble/xcvr.h"
26*042d53a7SEvalZero #include "nimble/ble.h"
27*042d53a7SEvalZero #include "nimble/nimble_opt.h"
28*042d53a7SEvalZero #include "controller/ble_phy.h"
29*042d53a7SEvalZero #include "controller/ble_ll.h"
30*042d53a7SEvalZero
31*042d53a7SEvalZero /* BLE PHY data structure */
32*042d53a7SEvalZero struct ble_phy_obj
33*042d53a7SEvalZero {
34*042d53a7SEvalZero uint8_t phy_stats_initialized;
35*042d53a7SEvalZero int8_t phy_txpwr_dbm;
36*042d53a7SEvalZero uint8_t phy_chan;
37*042d53a7SEvalZero uint8_t phy_state;
38*042d53a7SEvalZero uint8_t phy_transition;
39*042d53a7SEvalZero uint8_t phy_rx_started;
40*042d53a7SEvalZero uint8_t phy_encrypted;
41*042d53a7SEvalZero uint8_t phy_privacy;
42*042d53a7SEvalZero uint8_t phy_tx_pyld_len;
43*042d53a7SEvalZero uint32_t phy_aar_scratch;
44*042d53a7SEvalZero uint32_t phy_access_address;
45*042d53a7SEvalZero struct ble_mbuf_hdr rxhdr;
46*042d53a7SEvalZero void *txend_arg;
47*042d53a7SEvalZero uint8_t *rxdptr;
48*042d53a7SEvalZero ble_phy_tx_end_func txend_cb;
49*042d53a7SEvalZero };
50*042d53a7SEvalZero struct ble_phy_obj g_ble_phy_data;
51*042d53a7SEvalZero
52*042d53a7SEvalZero /* Statistics */
53*042d53a7SEvalZero struct ble_phy_statistics
54*042d53a7SEvalZero {
55*042d53a7SEvalZero uint32_t tx_good;
56*042d53a7SEvalZero uint32_t tx_fail;
57*042d53a7SEvalZero uint32_t tx_late;
58*042d53a7SEvalZero uint32_t tx_bytes;
59*042d53a7SEvalZero uint32_t rx_starts;
60*042d53a7SEvalZero uint32_t rx_aborts;
61*042d53a7SEvalZero uint32_t rx_valid;
62*042d53a7SEvalZero uint32_t rx_crc_err;
63*042d53a7SEvalZero uint32_t phy_isrs;
64*042d53a7SEvalZero uint32_t radio_state_errs;
65*042d53a7SEvalZero uint32_t no_bufs;
66*042d53a7SEvalZero };
67*042d53a7SEvalZero
68*042d53a7SEvalZero struct ble_phy_statistics g_ble_phy_stats;
69*042d53a7SEvalZero
70*042d53a7SEvalZero static uint8_t g_ble_phy_tx_buf[BLE_PHY_MAX_PDU_LEN];
71*042d53a7SEvalZero
72*042d53a7SEvalZero /* XCVR object to emulate transceiver */
73*042d53a7SEvalZero struct xcvr_data
74*042d53a7SEvalZero {
75*042d53a7SEvalZero uint32_t irq_status;
76*042d53a7SEvalZero };
77*042d53a7SEvalZero static struct xcvr_data g_xcvr_data;
78*042d53a7SEvalZero
79*042d53a7SEvalZero #define BLE_XCVR_IRQ_F_RX_START (0x00000001)
80*042d53a7SEvalZero #define BLE_XCVR_IRQ_F_RX_END (0x00000002)
81*042d53a7SEvalZero #define BLE_XCVR_IRQ_F_TX_START (0x00000004)
82*042d53a7SEvalZero #define BLE_XCVR_IRQ_F_TX_END (0x00000008)
83*042d53a7SEvalZero #define BLE_XCVR_IRQ_F_BYTE_CNTR (0x00000010)
84*042d53a7SEvalZero
85*042d53a7SEvalZero /* "Rail" power level if outside supported range */
86*042d53a7SEvalZero #define BLE_XCVR_TX_PWR_MAX_DBM (30)
87*042d53a7SEvalZero #define BLE_XCVR_TX_PWR_MIN_DBM (-20)
88*042d53a7SEvalZero
89*042d53a7SEvalZero /* Statistics */
90*042d53a7SEvalZero STATS_SECT_START(ble_phy_stats)
91*042d53a7SEvalZero STATS_SECT_ENTRY(phy_isrs)
92*042d53a7SEvalZero STATS_SECT_ENTRY(tx_good)
93*042d53a7SEvalZero STATS_SECT_ENTRY(tx_fail)
94*042d53a7SEvalZero STATS_SECT_ENTRY(tx_late)
95*042d53a7SEvalZero STATS_SECT_ENTRY(tx_bytes)
96*042d53a7SEvalZero STATS_SECT_ENTRY(rx_starts)
97*042d53a7SEvalZero STATS_SECT_ENTRY(rx_aborts)
98*042d53a7SEvalZero STATS_SECT_ENTRY(rx_valid)
99*042d53a7SEvalZero STATS_SECT_ENTRY(rx_crc_err)
100*042d53a7SEvalZero STATS_SECT_ENTRY(rx_late)
101*042d53a7SEvalZero STATS_SECT_ENTRY(no_bufs)
102*042d53a7SEvalZero STATS_SECT_ENTRY(radio_state_errs)
103*042d53a7SEvalZero STATS_SECT_ENTRY(rx_hw_err)
104*042d53a7SEvalZero STATS_SECT_ENTRY(tx_hw_err)
105*042d53a7SEvalZero STATS_SECT_END
106*042d53a7SEvalZero STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
107*042d53a7SEvalZero
108*042d53a7SEvalZero STATS_NAME_START(ble_phy_stats)
STATS_NAME(ble_phy_stats,phy_isrs)109*042d53a7SEvalZero STATS_NAME(ble_phy_stats, phy_isrs)
110*042d53a7SEvalZero STATS_NAME(ble_phy_stats, tx_good)
111*042d53a7SEvalZero STATS_NAME(ble_phy_stats, tx_fail)
112*042d53a7SEvalZero STATS_NAME(ble_phy_stats, tx_late)
113*042d53a7SEvalZero STATS_NAME(ble_phy_stats, tx_bytes)
114*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_starts)
115*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_aborts)
116*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_valid)
117*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_crc_err)
118*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_late)
119*042d53a7SEvalZero STATS_NAME(ble_phy_stats, no_bufs)
120*042d53a7SEvalZero STATS_NAME(ble_phy_stats, radio_state_errs)
121*042d53a7SEvalZero STATS_NAME(ble_phy_stats, rx_hw_err)
122*042d53a7SEvalZero STATS_NAME(ble_phy_stats, tx_hw_err)
123*042d53a7SEvalZero STATS_NAME_END(ble_phy_stats)
124*042d53a7SEvalZero
125*042d53a7SEvalZero /* XXX: TODO:
126*042d53a7SEvalZero
127*042d53a7SEvalZero * 1) Test the following to make sure it works: suppose an event is already
128*042d53a7SEvalZero * set to 1 and the interrupt is not enabled. What happens if you enable the
129*042d53a7SEvalZero * interrupt with the event bit already set to 1
130*042d53a7SEvalZero * 2) how to deal with interrupts?
131*042d53a7SEvalZero */
132*042d53a7SEvalZero static uint32_t
133*042d53a7SEvalZero ble_xcvr_get_irq_status(void)
134*042d53a7SEvalZero {
135*042d53a7SEvalZero return g_xcvr_data.irq_status;
136*042d53a7SEvalZero }
137*042d53a7SEvalZero
138*042d53a7SEvalZero static void
ble_xcvr_clear_irq(uint32_t mask)139*042d53a7SEvalZero ble_xcvr_clear_irq(uint32_t mask)
140*042d53a7SEvalZero {
141*042d53a7SEvalZero g_xcvr_data.irq_status &= ~mask;
142*042d53a7SEvalZero }
143*042d53a7SEvalZero
144*042d53a7SEvalZero /**
145*042d53a7SEvalZero * Copies the data from the phy receive buffer into a mbuf chain.
146*042d53a7SEvalZero *
147*042d53a7SEvalZero * @param dptr Pointer to receive buffer
148*042d53a7SEvalZero * @param rxpdu Pointer to already allocated mbuf chain
149*042d53a7SEvalZero *
150*042d53a7SEvalZero * NOTE: the packet header already has the total mbuf length in it. The
151*042d53a7SEvalZero * lengths of the individual mbufs are not set prior to calling.
152*042d53a7SEvalZero *
153*042d53a7SEvalZero */
154*042d53a7SEvalZero void
ble_phy_rxpdu_copy(uint8_t * dptr,struct os_mbuf * rxpdu)155*042d53a7SEvalZero ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
156*042d53a7SEvalZero {
157*042d53a7SEvalZero uint16_t rem_bytes;
158*042d53a7SEvalZero uint16_t mb_bytes;
159*042d53a7SEvalZero uint16_t copylen;
160*042d53a7SEvalZero uint32_t *dst;
161*042d53a7SEvalZero uint32_t *src;
162*042d53a7SEvalZero struct os_mbuf *m;
163*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
164*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
165*042d53a7SEvalZero
166*042d53a7SEvalZero /* Better be aligned */
167*042d53a7SEvalZero assert(((uint32_t)dptr & 3) == 0);
168*042d53a7SEvalZero
169*042d53a7SEvalZero pkthdr = OS_MBUF_PKTHDR(rxpdu);
170*042d53a7SEvalZero rem_bytes = pkthdr->omp_len;
171*042d53a7SEvalZero
172*042d53a7SEvalZero /* Fill in the mbuf pkthdr first. */
173*042d53a7SEvalZero dst = (uint32_t *)(rxpdu->om_data);
174*042d53a7SEvalZero src = (uint32_t *)dptr;
175*042d53a7SEvalZero
176*042d53a7SEvalZero mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
177*042d53a7SEvalZero copylen = min(mb_bytes, rem_bytes);
178*042d53a7SEvalZero copylen &= 0xFFFC;
179*042d53a7SEvalZero rem_bytes -= copylen;
180*042d53a7SEvalZero mb_bytes -= copylen;
181*042d53a7SEvalZero rxpdu->om_len = copylen;
182*042d53a7SEvalZero while (copylen > 0) {
183*042d53a7SEvalZero *dst = *src;
184*042d53a7SEvalZero ++dst;
185*042d53a7SEvalZero ++src;
186*042d53a7SEvalZero copylen -= 4;
187*042d53a7SEvalZero }
188*042d53a7SEvalZero
189*042d53a7SEvalZero /* Copy remaining bytes */
190*042d53a7SEvalZero m = rxpdu;
191*042d53a7SEvalZero while (rem_bytes > 0) {
192*042d53a7SEvalZero /* If there are enough bytes in the mbuf, copy them and leave */
193*042d53a7SEvalZero if (rem_bytes <= mb_bytes) {
194*042d53a7SEvalZero memcpy(m->om_data + m->om_len, src, rem_bytes);
195*042d53a7SEvalZero m->om_len += rem_bytes;
196*042d53a7SEvalZero break;
197*042d53a7SEvalZero }
198*042d53a7SEvalZero
199*042d53a7SEvalZero m = SLIST_NEXT(m, om_next);
200*042d53a7SEvalZero assert(m != NULL);
201*042d53a7SEvalZero
202*042d53a7SEvalZero mb_bytes = m->om_omp->omp_databuf_len;
203*042d53a7SEvalZero copylen = min(mb_bytes, rem_bytes);
204*042d53a7SEvalZero copylen &= 0xFFFC;
205*042d53a7SEvalZero rem_bytes -= copylen;
206*042d53a7SEvalZero mb_bytes -= copylen;
207*042d53a7SEvalZero m->om_len = copylen;
208*042d53a7SEvalZero dst = (uint32_t *)m->om_data;
209*042d53a7SEvalZero while (copylen > 0) {
210*042d53a7SEvalZero *dst = *src;
211*042d53a7SEvalZero ++dst;
212*042d53a7SEvalZero ++src;
213*042d53a7SEvalZero copylen -= 4;
214*042d53a7SEvalZero }
215*042d53a7SEvalZero }
216*042d53a7SEvalZero
217*042d53a7SEvalZero /* Copy ble header */
218*042d53a7SEvalZero ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
219*042d53a7SEvalZero memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
220*042d53a7SEvalZero }
221*042d53a7SEvalZero
222*042d53a7SEvalZero void
ble_phy_isr(void)223*042d53a7SEvalZero ble_phy_isr(void)
224*042d53a7SEvalZero {
225*042d53a7SEvalZero int rc;
226*042d53a7SEvalZero uint8_t transition;
227*042d53a7SEvalZero uint32_t irq_en;
228*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
229*042d53a7SEvalZero
230*042d53a7SEvalZero /* Check for disabled event. This only happens for transmits now */
231*042d53a7SEvalZero irq_en = ble_xcvr_get_irq_status();
232*042d53a7SEvalZero if (irq_en & BLE_XCVR_IRQ_F_TX_END) {
233*042d53a7SEvalZero
234*042d53a7SEvalZero /* Better be in TX state! */
235*042d53a7SEvalZero assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
236*042d53a7SEvalZero ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);
237*042d53a7SEvalZero
238*042d53a7SEvalZero transition = g_ble_phy_data.phy_transition;
239*042d53a7SEvalZero if (transition == BLE_PHY_TRANSITION_TX_RX) {
240*042d53a7SEvalZero /* Disable the phy */
241*042d53a7SEvalZero /* XXX: count no bufs? */
242*042d53a7SEvalZero ble_phy_disable();
243*042d53a7SEvalZero } else {
244*042d53a7SEvalZero /* Better not be going from rx to tx! */
245*042d53a7SEvalZero assert(transition == BLE_PHY_TRANSITION_NONE);
246*042d53a7SEvalZero }
247*042d53a7SEvalZero }
248*042d53a7SEvalZero
249*042d53a7SEvalZero /* We get this if we have started to receive a frame */
250*042d53a7SEvalZero if (irq_en & BLE_XCVR_IRQ_F_RX_START) {
251*042d53a7SEvalZero
252*042d53a7SEvalZero ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_START);
253*042d53a7SEvalZero
254*042d53a7SEvalZero /* Call Link Layer receive start function */
255*042d53a7SEvalZero rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
256*042d53a7SEvalZero &g_ble_phy_data.rxhdr);
257*042d53a7SEvalZero if (rc >= 0) {
258*042d53a7SEvalZero /* XXX: set rx end enable isr */
259*042d53a7SEvalZero } else {
260*042d53a7SEvalZero /* Disable PHY */
261*042d53a7SEvalZero ble_phy_disable();
262*042d53a7SEvalZero irq_en = 0;
263*042d53a7SEvalZero ++g_ble_phy_stats.rx_aborts;
264*042d53a7SEvalZero }
265*042d53a7SEvalZero
266*042d53a7SEvalZero /* Count rx starts */
267*042d53a7SEvalZero ++g_ble_phy_stats.rx_starts;
268*042d53a7SEvalZero }
269*042d53a7SEvalZero
270*042d53a7SEvalZero /* Receive packet end (we dont enable this for transmit) */
271*042d53a7SEvalZero if (irq_en & BLE_XCVR_IRQ_F_RX_END) {
272*042d53a7SEvalZero
273*042d53a7SEvalZero ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_END);
274*042d53a7SEvalZero
275*042d53a7SEvalZero /* Construct BLE header before handing up */
276*042d53a7SEvalZero ble_hdr = &g_ble_phy_data.rxhdr;
277*042d53a7SEvalZero ble_hdr->rxinfo.flags = 0;
278*042d53a7SEvalZero ble_hdr->rxinfo.rssi = -77; /* XXX: dummy rssi */
279*042d53a7SEvalZero ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
280*042d53a7SEvalZero ble_hdr->rxinfo.phy = BLE_PHY_1M;
281*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
282*042d53a7SEvalZero ble_hdr->rxinfo.aux_data = NULL;
283*042d53a7SEvalZero #endif
284*042d53a7SEvalZero
285*042d53a7SEvalZero /* Count PHY valid packets */
286*042d53a7SEvalZero ++g_ble_phy_stats.rx_valid;
287*042d53a7SEvalZero ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
288*042d53a7SEvalZero
289*042d53a7SEvalZero /* Call Link Layer receive payload function */
290*042d53a7SEvalZero rc = ble_ll_rx_end(g_ble_phy_data.rxdptr, ble_hdr);
291*042d53a7SEvalZero if (rc < 0) {
292*042d53a7SEvalZero /* Disable the PHY. */
293*042d53a7SEvalZero ble_phy_disable();
294*042d53a7SEvalZero }
295*042d53a7SEvalZero }
296*042d53a7SEvalZero
297*042d53a7SEvalZero /* Count # of interrupts */
298*042d53a7SEvalZero ++g_ble_phy_stats.phy_isrs;
299*042d53a7SEvalZero }
300*042d53a7SEvalZero
301*042d53a7SEvalZero /**
302*042d53a7SEvalZero * ble phy init
303*042d53a7SEvalZero *
304*042d53a7SEvalZero * Initialize the PHY. This is expected to be called once.
305*042d53a7SEvalZero *
306*042d53a7SEvalZero * @return int 0: success; PHY error code otherwise
307*042d53a7SEvalZero */
308*042d53a7SEvalZero int
ble_phy_init(void)309*042d53a7SEvalZero ble_phy_init(void)
310*042d53a7SEvalZero {
311*042d53a7SEvalZero /* Set phy channel to an invalid channel so first set channel works */
312*042d53a7SEvalZero g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
313*042d53a7SEvalZero g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
314*042d53a7SEvalZero
315*042d53a7SEvalZero /* XXX: emulate ISR? */
316*042d53a7SEvalZero
317*042d53a7SEvalZero return 0;
318*042d53a7SEvalZero }
319*042d53a7SEvalZero
320*042d53a7SEvalZero int
ble_phy_rx(void)321*042d53a7SEvalZero ble_phy_rx(void)
322*042d53a7SEvalZero {
323*042d53a7SEvalZero /* Check radio state */
324*042d53a7SEvalZero if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
325*042d53a7SEvalZero ble_phy_disable();
326*042d53a7SEvalZero ++g_ble_phy_stats.radio_state_errs;
327*042d53a7SEvalZero return BLE_PHY_ERR_RADIO_STATE;
328*042d53a7SEvalZero }
329*042d53a7SEvalZero
330*042d53a7SEvalZero g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
331*042d53a7SEvalZero
332*042d53a7SEvalZero return 0;
333*042d53a7SEvalZero }
334*042d53a7SEvalZero
335*042d53a7SEvalZero void
ble_phy_restart_rx(void)336*042d53a7SEvalZero ble_phy_restart_rx(void)
337*042d53a7SEvalZero {
338*042d53a7SEvalZero }
339*042d53a7SEvalZero
340*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
341*042d53a7SEvalZero /**
342*042d53a7SEvalZero * Called to enable encryption at the PHY. Note that this state will persist
343*042d53a7SEvalZero * in the PHY; in other words, if you call this function you have to call
344*042d53a7SEvalZero * disable so that future PHY transmits/receives will not be encrypted.
345*042d53a7SEvalZero *
346*042d53a7SEvalZero * @param pkt_counter
347*042d53a7SEvalZero * @param iv
348*042d53a7SEvalZero * @param key
349*042d53a7SEvalZero * @param is_master
350*042d53a7SEvalZero */
351*042d53a7SEvalZero void
ble_phy_encrypt_enable(uint64_t pkt_counter,uint8_t * iv,uint8_t * key,uint8_t is_master)352*042d53a7SEvalZero ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
353*042d53a7SEvalZero uint8_t is_master)
354*042d53a7SEvalZero {
355*042d53a7SEvalZero }
356*042d53a7SEvalZero
357*042d53a7SEvalZero void
ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter,int dir)358*042d53a7SEvalZero ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
359*042d53a7SEvalZero {
360*042d53a7SEvalZero }
361*042d53a7SEvalZero
362*042d53a7SEvalZero void
ble_phy_encrypt_disable(void)363*042d53a7SEvalZero ble_phy_encrypt_disable(void)
364*042d53a7SEvalZero {
365*042d53a7SEvalZero }
366*042d53a7SEvalZero #endif
367*042d53a7SEvalZero
368*042d53a7SEvalZero void
ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb,void * arg)369*042d53a7SEvalZero ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
370*042d53a7SEvalZero {
371*042d53a7SEvalZero /* Set transmit end callback and arg */
372*042d53a7SEvalZero g_ble_phy_data.txend_cb = txend_cb;
373*042d53a7SEvalZero g_ble_phy_data.txend_arg = arg;
374*042d53a7SEvalZero }
375*042d53a7SEvalZero
376*042d53a7SEvalZero /**
377*042d53a7SEvalZero * Called to set the start time of a transmission.
378*042d53a7SEvalZero *
379*042d53a7SEvalZero * This function is called to set the start time when we are not going from
380*042d53a7SEvalZero * rx to tx automatically.
381*042d53a7SEvalZero *
382*042d53a7SEvalZero * NOTE: care must be taken when calling this function. The channel should
383*042d53a7SEvalZero * already be set.
384*042d53a7SEvalZero *
385*042d53a7SEvalZero * @param cputime
386*042d53a7SEvalZero * @param rem_usecs
387*042d53a7SEvalZero *
388*042d53a7SEvalZero * @return int
389*042d53a7SEvalZero */
390*042d53a7SEvalZero int
ble_phy_tx_set_start_time(uint32_t cputime,uint8_t rem_usecs)391*042d53a7SEvalZero ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
392*042d53a7SEvalZero {
393*042d53a7SEvalZero return 0;
394*042d53a7SEvalZero }
395*042d53a7SEvalZero
396*042d53a7SEvalZero /**
397*042d53a7SEvalZero * Called to set the start time of a reception
398*042d53a7SEvalZero *
399*042d53a7SEvalZero * This function acts a bit differently than transmit. If we are late getting
400*042d53a7SEvalZero * here we will still attempt to receive.
401*042d53a7SEvalZero *
402*042d53a7SEvalZero * NOTE: care must be taken when calling this function. The channel should
403*042d53a7SEvalZero * already be set.
404*042d53a7SEvalZero *
405*042d53a7SEvalZero * @param cputime
406*042d53a7SEvalZero * @param rem_usecs
407*042d53a7SEvalZero *
408*042d53a7SEvalZero * @return int
409*042d53a7SEvalZero */
410*042d53a7SEvalZero int
ble_phy_rx_set_start_time(uint32_t cputime,uint8_t rem_usecs)411*042d53a7SEvalZero ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
412*042d53a7SEvalZero {
413*042d53a7SEvalZero return 0;
414*042d53a7SEvalZero }
415*042d53a7SEvalZero
416*042d53a7SEvalZero
417*042d53a7SEvalZero int
ble_phy_tx(ble_phy_tx_pducb_t pducb,void * pducb_arg,uint8_t end_trans)418*042d53a7SEvalZero ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
419*042d53a7SEvalZero {
420*042d53a7SEvalZero uint8_t hdr_byte;
421*042d53a7SEvalZero int rc;
422*042d53a7SEvalZero
423*042d53a7SEvalZero if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
424*042d53a7SEvalZero ble_phy_disable();
425*042d53a7SEvalZero ++g_ble_phy_stats.radio_state_errs;
426*042d53a7SEvalZero return BLE_PHY_ERR_RADIO_STATE;
427*042d53a7SEvalZero }
428*042d53a7SEvalZero
429*042d53a7SEvalZero /* Select tx address */
430*042d53a7SEvalZero if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
431*042d53a7SEvalZero /* XXX: fix this */
432*042d53a7SEvalZero assert(0);
433*042d53a7SEvalZero } else {
434*042d53a7SEvalZero }
435*042d53a7SEvalZero
436*042d53a7SEvalZero /* Set the PHY transition */
437*042d53a7SEvalZero g_ble_phy_data.phy_transition = end_trans;
438*042d53a7SEvalZero
439*042d53a7SEvalZero /* Set phy state to transmitting and count packet statistics */
440*042d53a7SEvalZero g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
441*042d53a7SEvalZero ++g_ble_phy_stats.tx_good;
442*042d53a7SEvalZero g_ble_phy_stats.tx_bytes += pducb(g_ble_phy_tx_buf, pducb_arg, &hdr_byte) +
443*042d53a7SEvalZero BLE_LL_PDU_HDR_LEN;
444*042d53a7SEvalZero rc = BLE_ERR_SUCCESS;
445*042d53a7SEvalZero
446*042d53a7SEvalZero return rc;
447*042d53a7SEvalZero }
448*042d53a7SEvalZero
449*042d53a7SEvalZero /**
450*042d53a7SEvalZero * ble phy txpwr set
451*042d53a7SEvalZero *
452*042d53a7SEvalZero * Set the transmit output power (in dBm).
453*042d53a7SEvalZero *
454*042d53a7SEvalZero * NOTE: If the output power specified is within the BLE limits but outside
455*042d53a7SEvalZero * the chip limits, we "rail" the power level so we dont exceed the min/max
456*042d53a7SEvalZero * chip values.
457*042d53a7SEvalZero *
458*042d53a7SEvalZero * @param dbm Power output in dBm.
459*042d53a7SEvalZero *
460*042d53a7SEvalZero * @return int 0: success; anything else is an error
461*042d53a7SEvalZero */
462*042d53a7SEvalZero int
ble_phy_txpwr_set(int dbm)463*042d53a7SEvalZero ble_phy_txpwr_set(int dbm)
464*042d53a7SEvalZero {
465*042d53a7SEvalZero /* Check valid range */
466*042d53a7SEvalZero assert(dbm <= BLE_PHY_MAX_PWR_DBM);
467*042d53a7SEvalZero
468*042d53a7SEvalZero /* "Rail" power level if outside supported range */
469*042d53a7SEvalZero if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
470*042d53a7SEvalZero dbm = BLE_XCVR_TX_PWR_MAX_DBM;
471*042d53a7SEvalZero } else {
472*042d53a7SEvalZero if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
473*042d53a7SEvalZero dbm = BLE_XCVR_TX_PWR_MIN_DBM;
474*042d53a7SEvalZero }
475*042d53a7SEvalZero }
476*042d53a7SEvalZero
477*042d53a7SEvalZero g_ble_phy_data.phy_txpwr_dbm = dbm;
478*042d53a7SEvalZero
479*042d53a7SEvalZero return 0;
480*042d53a7SEvalZero }
481*042d53a7SEvalZero
482*042d53a7SEvalZero /**
483*042d53a7SEvalZero * ble phy txpwr round
484*042d53a7SEvalZero *
485*042d53a7SEvalZero * Get the rounded transmit output power (in dBm).
486*042d53a7SEvalZero *
487*042d53a7SEvalZero * @param dbm Power output in dBm.
488*042d53a7SEvalZero *
489*042d53a7SEvalZero * @return int Rounded power in dBm
490*042d53a7SEvalZero */
ble_phy_txpower_round(int dbm)491*042d53a7SEvalZero int ble_phy_txpower_round(int dbm)
492*042d53a7SEvalZero {
493*042d53a7SEvalZero /* "Rail" power level if outside supported range */
494*042d53a7SEvalZero if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
495*042d53a7SEvalZero dbm = BLE_XCVR_TX_PWR_MAX_DBM;
496*042d53a7SEvalZero } else {
497*042d53a7SEvalZero if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
498*042d53a7SEvalZero dbm = BLE_XCVR_TX_PWR_MIN_DBM;
499*042d53a7SEvalZero }
500*042d53a7SEvalZero }
501*042d53a7SEvalZero
502*042d53a7SEvalZero return dbm;
503*042d53a7SEvalZero }
504*042d53a7SEvalZero
505*042d53a7SEvalZero /**
506*042d53a7SEvalZero * ble phy txpwr get
507*042d53a7SEvalZero *
508*042d53a7SEvalZero * Get the transmit power.
509*042d53a7SEvalZero *
510*042d53a7SEvalZero * @return int The current PHY transmit power, in dBm
511*042d53a7SEvalZero */
512*042d53a7SEvalZero int
ble_phy_txpwr_get(void)513*042d53a7SEvalZero ble_phy_txpwr_get(void)
514*042d53a7SEvalZero {
515*042d53a7SEvalZero return g_ble_phy_data.phy_txpwr_dbm;
516*042d53a7SEvalZero }
517*042d53a7SEvalZero
518*042d53a7SEvalZero /**
519*042d53a7SEvalZero * ble phy setchan
520*042d53a7SEvalZero *
521*042d53a7SEvalZero * Sets the logical frequency of the transceiver. The input parameter is the
522*042d53a7SEvalZero * BLE channel index (0 to 39, inclusive). The NRF52 frequency register
523*042d53a7SEvalZero * works like this: logical frequency = 2400 + FREQ (MHz).
524*042d53a7SEvalZero *
525*042d53a7SEvalZero * Thus, to get a logical frequency of 2402 MHz, you would program the
526*042d53a7SEvalZero * FREQUENCY register to 2.
527*042d53a7SEvalZero *
528*042d53a7SEvalZero * @param chan This is the Data Channel Index or Advertising Channel index
529*042d53a7SEvalZero *
530*042d53a7SEvalZero * @return int 0: success; PHY error code otherwise
531*042d53a7SEvalZero */
532*042d53a7SEvalZero int
ble_phy_setchan(uint8_t chan,uint32_t access_addr,uint32_t crcinit)533*042d53a7SEvalZero ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
534*042d53a7SEvalZero {
535*042d53a7SEvalZero assert(chan < BLE_PHY_NUM_CHANS);
536*042d53a7SEvalZero
537*042d53a7SEvalZero /* Check for valid channel range */
538*042d53a7SEvalZero if (chan >= BLE_PHY_NUM_CHANS) {
539*042d53a7SEvalZero return BLE_PHY_ERR_INV_PARAM;
540*042d53a7SEvalZero }
541*042d53a7SEvalZero
542*042d53a7SEvalZero g_ble_phy_data.phy_access_address = access_addr;
543*042d53a7SEvalZero
544*042d53a7SEvalZero g_ble_phy_data.phy_chan = chan;
545*042d53a7SEvalZero
546*042d53a7SEvalZero return 0;
547*042d53a7SEvalZero }
548*042d53a7SEvalZero
549*042d53a7SEvalZero /**
550*042d53a7SEvalZero * Disable the PHY. This will do the following:
551*042d53a7SEvalZero * -> Turn off all phy interrupts.
552*042d53a7SEvalZero * -> Disable internal shortcuts.
553*042d53a7SEvalZero * -> Disable the radio.
554*042d53a7SEvalZero * -> Sets phy state to idle.
555*042d53a7SEvalZero */
556*042d53a7SEvalZero void
ble_phy_disable(void)557*042d53a7SEvalZero ble_phy_disable(void)
558*042d53a7SEvalZero {
559*042d53a7SEvalZero g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
560*042d53a7SEvalZero }
561*042d53a7SEvalZero
562*042d53a7SEvalZero /* Gets the current access address */
ble_phy_access_addr_get(void)563*042d53a7SEvalZero uint32_t ble_phy_access_addr_get(void)
564*042d53a7SEvalZero {
565*042d53a7SEvalZero return g_ble_phy_data.phy_access_address;
566*042d53a7SEvalZero }
567*042d53a7SEvalZero
568*042d53a7SEvalZero /**
569*042d53a7SEvalZero * Return the phy state
570*042d53a7SEvalZero *
571*042d53a7SEvalZero * @return int The current PHY state.
572*042d53a7SEvalZero */
573*042d53a7SEvalZero int
ble_phy_state_get(void)574*042d53a7SEvalZero ble_phy_state_get(void)
575*042d53a7SEvalZero {
576*042d53a7SEvalZero return g_ble_phy_data.phy_state;
577*042d53a7SEvalZero }
578*042d53a7SEvalZero
579*042d53a7SEvalZero /**
580*042d53a7SEvalZero * Called to see if a reception has started
581*042d53a7SEvalZero *
582*042d53a7SEvalZero * @return int
583*042d53a7SEvalZero */
584*042d53a7SEvalZero int
ble_phy_rx_started(void)585*042d53a7SEvalZero ble_phy_rx_started(void)
586*042d53a7SEvalZero {
587*042d53a7SEvalZero return g_ble_phy_data.phy_rx_started;
588*042d53a7SEvalZero }
589*042d53a7SEvalZero
590*042d53a7SEvalZero /**
591*042d53a7SEvalZero * Called to return the maximum data pdu payload length supported by the
592*042d53a7SEvalZero * phy. For this chip, if encryption is enabled, the maximum payload is 27
593*042d53a7SEvalZero * bytes.
594*042d53a7SEvalZero *
595*042d53a7SEvalZero * @return uint8_t Maximum data channel PDU payload size supported
596*042d53a7SEvalZero */
597*042d53a7SEvalZero uint8_t
ble_phy_max_data_pdu_pyld(void)598*042d53a7SEvalZero ble_phy_max_data_pdu_pyld(void)
599*042d53a7SEvalZero {
600*042d53a7SEvalZero return BLE_LL_DATA_PDU_MAX_PYLD;
601*042d53a7SEvalZero }
602*042d53a7SEvalZero
603*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
604*042d53a7SEvalZero void
ble_phy_resolv_list_enable(void)605*042d53a7SEvalZero ble_phy_resolv_list_enable(void)
606*042d53a7SEvalZero {
607*042d53a7SEvalZero g_ble_phy_data.phy_privacy = 1;
608*042d53a7SEvalZero }
609*042d53a7SEvalZero
610*042d53a7SEvalZero void
ble_phy_resolv_list_disable(void)611*042d53a7SEvalZero ble_phy_resolv_list_disable(void)
612*042d53a7SEvalZero {
613*042d53a7SEvalZero g_ble_phy_data.phy_privacy = 0;
614*042d53a7SEvalZero }
615*042d53a7SEvalZero
616*042d53a7SEvalZero /**
617*042d53a7SEvalZero * Return the transceiver state
618*042d53a7SEvalZero *
619*042d53a7SEvalZero * @return int transceiver state.
620*042d53a7SEvalZero */
621*042d53a7SEvalZero uint8_t
ble_phy_xcvr_state_get(void)622*042d53a7SEvalZero ble_phy_xcvr_state_get(void)
623*042d53a7SEvalZero {
624*042d53a7SEvalZero return g_ble_phy_data.phy_state;
625*042d53a7SEvalZero }
626*042d53a7SEvalZero
627*042d53a7SEvalZero #endif
628*042d53a7SEvalZero
629*042d53a7SEvalZero void
ble_phy_wfr_enable(int txrx,uint8_t tx_phy_mode,uint32_t wfr_usecs)630*042d53a7SEvalZero ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
631*042d53a7SEvalZero {
632*042d53a7SEvalZero }
633