1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 
19 #include <zephyr.h>
20 #undef irq_enable
21 #undef irq_disable
22 #undef ARRAY_SIZE
23 
24 #include "plic.h"
25 #include "compiler.h"
26 #include "b91_bt.h"
27 #include "b91_bt_init.h"
28 #include "stack/ble/controller/ble_controller.h"
29 
30 
31 /* Module defines */
32 #define BLE_THREAD_STACK_SIZE           CONFIG_B91_BLE_CTRL_THREAD_STACK_SIZE
33 #define BLE_THREAD_PRIORITY             CONFIG_B91_BLE_CTRL_THREAD_PRIORITY
34 #define BLE_THREAD_PERIOD_MS            CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS
35 
36 #define BYTES_TO_UINT16(n, p)           {n = ((u16)(p)[0] + ((u16)(p)[1]<<8));}
37 #define BSTREAM_TO_UINT16(n, p)         {BYTES_TO_UINT16(n, p); p += 2;}
38 
39 
40 static struct b91_ctrl_t
41 {
42 	bool is_initialized;
43 	b91_bt_host_callback_t callbacks;
44 } b91_ctrl;
45 
46 /**
47  * @brief    RF driver interrupt handler
48  */
rf_irq_handler(void)49 _attribute_ram_code_ void rf_irq_handler(void)
50 {
51 	blc_sdk_irq_handler();
52 }
53 
54 /**
55  * @brief    System Timer interrupt handler
56  */
stimer_irq_handler(void)57 _attribute_ram_code_ void stimer_irq_handler(void)
58 {
59 	blc_sdk_irq_handler();
60 }
61 
62 /**
63  * @brief    BLE Controller HCI Tx callback implementation
64  */
b91_bt_hci_tx_handler(void)65 static int b91_bt_hci_tx_handler(void)
66 {
67 	/* check for data available */
68 	if(bltHci_txfifo.wptr == bltHci_txfifo.rptr)
69 	{
70 		return 0;
71 	}
72 
73 	/* Get HCI data */
74 	u8 *p = bltHci_txfifo.p + (bltHci_txfifo.rptr & bltHci_txfifo.mask) * bltHci_txfifo.size;
75 	if(p)
76 	{
77 		u32 len;
78 		BSTREAM_TO_UINT16(len, p);
79 		bltHci_txfifo.rptr++;
80 
81 		/* Send data to the host */
82 		if(b91_ctrl.callbacks.host_read_packet)
83 		{
84 			b91_ctrl.callbacks.host_read_packet(p, len);
85 		}
86 	}
87 
88 	return 0;
89 }
90 
91 /**
92  * @brief    BLE Controller HCI Rx callback implementation
93  */
b91_bt_hci_rx_handler(void)94 static int b91_bt_hci_rx_handler(void)
95 {
96 	/* Check for data available */
97 	if(bltHci_rxfifo.wptr == bltHci_rxfifo.rptr)
98 	{
99 		/* No data to process, send host_send_available message to the host */
100 		if(b91_ctrl.callbacks.host_send_available)
101 		{
102 			b91_ctrl.callbacks.host_send_available();
103 		}
104 
105 		return 0;
106 	}
107 
108 	/* Get HCI data */
109 	u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.rptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
110 	if(p)
111 	{
112 		/* Send data to the controller */
113 		blc_hci_handler(&p[0], 0);
114 		bltHci_rxfifo.rptr++;
115 	}
116 
117 	return 0;
118 }
119 
120 /**
121  * @brief    Telink B91 BLE Controller thread
122  */
b91_bt_controller_thread()123 static void b91_bt_controller_thread()
124 {
125 	while(1)
126 	{
127 		if(b91_ctrl.is_initialized)
128 		{
129 			blc_sdk_main_loop();
130 		}
131 
132 		k_msleep(BLE_THREAD_PERIOD_MS);
133 	}
134 }
135 
136 /**
137  * @brief    BLE Controller IRQs initialization
138  */
b91_bt_irq_init()139 static void b91_bt_irq_init()
140 {
141 	/* Init STimer IRQ */
142 	IRQ_CONNECT(IRQ1_SYSTIMER, 0, stimer_irq_handler, 0, 0);
143 
144 	/* Init RF IRQ */
145 	IRQ_CONNECT(IRQ15_ZB_RT, 0, rf_irq_handler, 0, 0);
146 }
147 
148 /**
149  * @brief    Telink B91 BLE Controller initialization
150  * @return   Status - 0: command succeeded; -1: command failed
151  */
b91_bt_controller_init()152 int b91_bt_controller_init()
153 {
154 	int status;
155 
156 	/* Init IRQs */
157 	b91_bt_irq_init();
158 
159 	/* Init RF driver */
160 	rf_drv_ble_init();
161 
162 	/* Init BLE Controller stack */
163 	status = b91_bt_blc_init(b91_bt_hci_rx_handler, b91_bt_hci_tx_handler);
164 	if(status != INIT_OK)
165 	{
166 		return status;
167 	}
168 
169 	/* Init controller data */
170 	b91_ctrl.is_initialized = TRUE;
171 
172 	return status;
173 }
174 
175 /**
176  * @brief      Host send HCI packet to controller
177  * @param      data the packet point
178  * @param      len the packet length
179  */
b91_bt_host_send_packet(uint8_t type,uint8_t * data,uint16_t len)180 void b91_bt_host_send_packet(uint8_t type, uint8_t *data, uint16_t len)
181 {
182 	u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.wptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
183 	*p++ = type;
184 	memcpy(p, data, len);
185 	bltHci_rxfifo.wptr++;
186 }
187 
188 /**
189  * @brief Register the vhci reference callback
190  */
b91_bt_host_callback_register(const b91_bt_host_callback_t * pcb)191 void b91_bt_host_callback_register(const b91_bt_host_callback_t *pcb)
192 {
193 	b91_ctrl.callbacks.host_read_packet = pcb->host_read_packet;
194 	b91_ctrl.callbacks.host_send_available = pcb->host_send_available;
195 }
196 
197 K_THREAD_DEFINE(ZephyrBleController, BLE_THREAD_STACK_SIZE, b91_bt_controller_thread,
198                 NULL, NULL, NULL, BLE_THREAD_PRIORITY, 0, 0);
199