xref: /nrf52832-nimble/packages/NimBLE-latest/apps/bleprph/src/phy.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include "os/mynewt.h"
21 #include "bsp/bsp.h"
22 #include "hal/hal_gpio.h"
23 #include "host/ble_gap.h"
24 #include "bleprph.h"
25 
26 #if MYNEWT_VAL(BLEPRPH_LE_PHY_SUPPORT)
27 
28 static const int button_gpio[4] = MYNEWT_VAL(BLEPRPH_LE_PHY_BUTTON_GPIO);
29 static const int led_gpio[3] = MYNEWT_VAL(BLEPRPH_LE_PHY_LED_GPIO);
30 
31 #define PHY_TO_PTR(_mask, _opts) (void *)(((_opts) << 16) | ((_mask)))
32 #define PTR_TO_PHY_MASK(_ptr) (uint8_t)(((int)_ptr) & 0x0ff)
33 #define PTR_TO_PHY_OPTS(_ptr) (uint8_t)(((int)_ptr) >> 16)
34 
35 static struct os_event gpio_event;
36 
37 static uint16_t conn_handle = CONN_HANDLE_INVALID;
38 
39 static void
gpio_irq_handler(void * arg)40 gpio_irq_handler(void *arg)
41 {
42     gpio_event.ev_arg = arg;
43     os_eventq_put(os_eventq_dflt_get(), &gpio_event);
44 }
45 
46 static void
gpio_event_handler(struct os_event * ev)47 gpio_event_handler(struct os_event *ev)
48 {
49     uint8_t phy_mask;
50     uint8_t phy_opts;
51     int sr;
52 
53     OS_ENTER_CRITICAL(sr);
54     phy_mask = PTR_TO_PHY_MASK(ev->ev_arg);
55     phy_opts = PTR_TO_PHY_OPTS(ev->ev_arg);
56     OS_EXIT_CRITICAL(sr);
57 
58     if (conn_handle != CONN_HANDLE_INVALID) {
59         ble_gap_set_prefered_le_phy(conn_handle, phy_mask, phy_mask, phy_opts);
60     }
61 }
62 
63 static void
setup_button_gpio(int button,uint8_t phy_mask,uint8_t phy_opts)64 setup_button_gpio(int button, uint8_t phy_mask, uint8_t phy_opts)
65 {
66     if (button < 0) {
67         return;
68     }
69 
70     hal_gpio_irq_init(button, gpio_irq_handler, PHY_TO_PTR(phy_mask, phy_opts),
71                       HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
72     hal_gpio_irq_enable(button);
73 }
74 
75 void
phy_init(void)76 phy_init(void)
77 {
78     gpio_event.ev_cb = gpio_event_handler;
79 
80     /*
81      * XXX: we could make this configurable, but for now assume all pins are
82      * valid, buttons gpio pins are pulled-up and LEDs are active-low - this
83      * is valid for nRF52840 PDK.
84      */
85     setup_button_gpio(button_gpio[0], BLE_GAP_LE_PHY_1M_MASK,
86                       BLE_GAP_LE_PHY_CODED_ANY);
87     setup_button_gpio(button_gpio[1], BLE_GAP_LE_PHY_2M_MASK,
88                       BLE_GAP_LE_PHY_CODED_ANY);
89     setup_button_gpio(button_gpio[2], BLE_GAP_LE_PHY_CODED_MASK,
90                       BLE_GAP_LE_PHY_CODED_S2);
91     setup_button_gpio(button_gpio[3], BLE_GAP_LE_PHY_CODED_MASK,
92                       BLE_GAP_LE_PHY_CODED_S8);
93 
94     hal_gpio_init_out(led_gpio[0], 1);
95     hal_gpio_init_out(led_gpio[1], 1);
96     hal_gpio_init_out(led_gpio[2], 1);
97 }
98 
99 void
phy_conn_changed(uint16_t handle)100 phy_conn_changed(uint16_t handle)
101 {
102     uint8_t phy = 0;
103 
104     conn_handle = handle;
105 
106     if (handle != CONN_HANDLE_INVALID) {
107         /* XXX: assume symmetric phy for now */
108         ble_gap_read_le_phy(handle, &phy, &phy);
109     }
110 
111     phy_update(phy);
112 }
113 
114 void
phy_update(uint8_t phy)115 phy_update(uint8_t phy)
116 {
117     if (conn_handle == CONN_HANDLE_INVALID) {
118         hal_gpio_write(led_gpio[0], 1);
119         hal_gpio_write(led_gpio[1], 1);
120         hal_gpio_write(led_gpio[2], 1);
121     } else {
122         hal_gpio_write(led_gpio[0], !(phy == BLE_GAP_LE_PHY_1M));
123         hal_gpio_write(led_gpio[1], !(phy == BLE_GAP_LE_PHY_2M));
124         hal_gpio_write(led_gpio[2], !(phy == BLE_GAP_LE_PHY_CODED));
125     }
126 }
127 
128 #endif
129