xref: /nrf52832-nimble/packages/NimBLE-latest/apps/bleprph/src/phy.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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 "os/mynewt.h"
21*042d53a7SEvalZero #include "bsp/bsp.h"
22*042d53a7SEvalZero #include "hal/hal_gpio.h"
23*042d53a7SEvalZero #include "host/ble_gap.h"
24*042d53a7SEvalZero #include "bleprph.h"
25*042d53a7SEvalZero 
26*042d53a7SEvalZero #if MYNEWT_VAL(BLEPRPH_LE_PHY_SUPPORT)
27*042d53a7SEvalZero 
28*042d53a7SEvalZero static const int button_gpio[4] = MYNEWT_VAL(BLEPRPH_LE_PHY_BUTTON_GPIO);
29*042d53a7SEvalZero static const int led_gpio[3] = MYNEWT_VAL(BLEPRPH_LE_PHY_LED_GPIO);
30*042d53a7SEvalZero 
31*042d53a7SEvalZero #define PHY_TO_PTR(_mask, _opts) (void *)(((_opts) << 16) | ((_mask)))
32*042d53a7SEvalZero #define PTR_TO_PHY_MASK(_ptr) (uint8_t)(((int)_ptr) & 0x0ff)
33*042d53a7SEvalZero #define PTR_TO_PHY_OPTS(_ptr) (uint8_t)(((int)_ptr) >> 16)
34*042d53a7SEvalZero 
35*042d53a7SEvalZero static struct os_event gpio_event;
36*042d53a7SEvalZero 
37*042d53a7SEvalZero static uint16_t conn_handle = CONN_HANDLE_INVALID;
38*042d53a7SEvalZero 
39*042d53a7SEvalZero static void
gpio_irq_handler(void * arg)40*042d53a7SEvalZero gpio_irq_handler(void *arg)
41*042d53a7SEvalZero {
42*042d53a7SEvalZero     gpio_event.ev_arg = arg;
43*042d53a7SEvalZero     os_eventq_put(os_eventq_dflt_get(), &gpio_event);
44*042d53a7SEvalZero }
45*042d53a7SEvalZero 
46*042d53a7SEvalZero static void
gpio_event_handler(struct os_event * ev)47*042d53a7SEvalZero gpio_event_handler(struct os_event *ev)
48*042d53a7SEvalZero {
49*042d53a7SEvalZero     uint8_t phy_mask;
50*042d53a7SEvalZero     uint8_t phy_opts;
51*042d53a7SEvalZero     int sr;
52*042d53a7SEvalZero 
53*042d53a7SEvalZero     OS_ENTER_CRITICAL(sr);
54*042d53a7SEvalZero     phy_mask = PTR_TO_PHY_MASK(ev->ev_arg);
55*042d53a7SEvalZero     phy_opts = PTR_TO_PHY_OPTS(ev->ev_arg);
56*042d53a7SEvalZero     OS_EXIT_CRITICAL(sr);
57*042d53a7SEvalZero 
58*042d53a7SEvalZero     if (conn_handle != CONN_HANDLE_INVALID) {
59*042d53a7SEvalZero         ble_gap_set_prefered_le_phy(conn_handle, phy_mask, phy_mask, phy_opts);
60*042d53a7SEvalZero     }
61*042d53a7SEvalZero }
62*042d53a7SEvalZero 
63*042d53a7SEvalZero static void
setup_button_gpio(int button,uint8_t phy_mask,uint8_t phy_opts)64*042d53a7SEvalZero setup_button_gpio(int button, uint8_t phy_mask, uint8_t phy_opts)
65*042d53a7SEvalZero {
66*042d53a7SEvalZero     if (button < 0) {
67*042d53a7SEvalZero         return;
68*042d53a7SEvalZero     }
69*042d53a7SEvalZero 
70*042d53a7SEvalZero     hal_gpio_irq_init(button, gpio_irq_handler, PHY_TO_PTR(phy_mask, phy_opts),
71*042d53a7SEvalZero                       HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
72*042d53a7SEvalZero     hal_gpio_irq_enable(button);
73*042d53a7SEvalZero }
74*042d53a7SEvalZero 
75*042d53a7SEvalZero void
phy_init(void)76*042d53a7SEvalZero phy_init(void)
77*042d53a7SEvalZero {
78*042d53a7SEvalZero     gpio_event.ev_cb = gpio_event_handler;
79*042d53a7SEvalZero 
80*042d53a7SEvalZero     /*
81*042d53a7SEvalZero      * XXX: we could make this configurable, but for now assume all pins are
82*042d53a7SEvalZero      * valid, buttons gpio pins are pulled-up and LEDs are active-low - this
83*042d53a7SEvalZero      * is valid for nRF52840 PDK.
84*042d53a7SEvalZero      */
85*042d53a7SEvalZero     setup_button_gpio(button_gpio[0], BLE_GAP_LE_PHY_1M_MASK,
86*042d53a7SEvalZero                       BLE_GAP_LE_PHY_CODED_ANY);
87*042d53a7SEvalZero     setup_button_gpio(button_gpio[1], BLE_GAP_LE_PHY_2M_MASK,
88*042d53a7SEvalZero                       BLE_GAP_LE_PHY_CODED_ANY);
89*042d53a7SEvalZero     setup_button_gpio(button_gpio[2], BLE_GAP_LE_PHY_CODED_MASK,
90*042d53a7SEvalZero                       BLE_GAP_LE_PHY_CODED_S2);
91*042d53a7SEvalZero     setup_button_gpio(button_gpio[3], BLE_GAP_LE_PHY_CODED_MASK,
92*042d53a7SEvalZero                       BLE_GAP_LE_PHY_CODED_S8);
93*042d53a7SEvalZero 
94*042d53a7SEvalZero     hal_gpio_init_out(led_gpio[0], 1);
95*042d53a7SEvalZero     hal_gpio_init_out(led_gpio[1], 1);
96*042d53a7SEvalZero     hal_gpio_init_out(led_gpio[2], 1);
97*042d53a7SEvalZero }
98*042d53a7SEvalZero 
99*042d53a7SEvalZero void
phy_conn_changed(uint16_t handle)100*042d53a7SEvalZero phy_conn_changed(uint16_t handle)
101*042d53a7SEvalZero {
102*042d53a7SEvalZero     uint8_t phy = 0;
103*042d53a7SEvalZero 
104*042d53a7SEvalZero     conn_handle = handle;
105*042d53a7SEvalZero 
106*042d53a7SEvalZero     if (handle != CONN_HANDLE_INVALID) {
107*042d53a7SEvalZero         /* XXX: assume symmetric phy for now */
108*042d53a7SEvalZero         ble_gap_read_le_phy(handle, &phy, &phy);
109*042d53a7SEvalZero     }
110*042d53a7SEvalZero 
111*042d53a7SEvalZero     phy_update(phy);
112*042d53a7SEvalZero }
113*042d53a7SEvalZero 
114*042d53a7SEvalZero void
phy_update(uint8_t phy)115*042d53a7SEvalZero phy_update(uint8_t phy)
116*042d53a7SEvalZero {
117*042d53a7SEvalZero     if (conn_handle == CONN_HANDLE_INVALID) {
118*042d53a7SEvalZero         hal_gpio_write(led_gpio[0], 1);
119*042d53a7SEvalZero         hal_gpio_write(led_gpio[1], 1);
120*042d53a7SEvalZero         hal_gpio_write(led_gpio[2], 1);
121*042d53a7SEvalZero     } else {
122*042d53a7SEvalZero         hal_gpio_write(led_gpio[0], !(phy == BLE_GAP_LE_PHY_1M));
123*042d53a7SEvalZero         hal_gpio_write(led_gpio[1], !(phy == BLE_GAP_LE_PHY_2M));
124*042d53a7SEvalZero         hal_gpio_write(led_gpio[2], !(phy == BLE_GAP_LE_PHY_CODED));
125*042d53a7SEvalZero     }
126*042d53a7SEvalZero }
127*042d53a7SEvalZero 
128*042d53a7SEvalZero #endif
129