1 //
2 // BTstack Port for the Microchip PIC32 Harmony Platfrom
3 //
4
5 #include "btstack_port.h"
6
7 #include "system_config.h"
8
9 #include "btstack_chipset_csr.h"
10 #include "btstack_debug.h"
11 #include "btstack_event.h"
12 #include "btstack_run_loop.h"
13 #include "btstack_run_loop_embedded.h"
14 #include "btstack_uart_slip_wrapper.h"
15 #include "hci.h"
16 #include "hci_dump.h"
17 #include "hci_transport.h"
18
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdlib.h>
23
24 #include "driver/tmr/drv_tmr.h"
25 #include "peripheral/usart/plib_usart.h"
26 #include "system/ports/sys_ports.h"
27
28 //
29 int btstack_main(int argc, const char * argv[]);
30
31
32 /// HAL Tick ///
33 #include "hal_tick.h"
34
35 #define APP_TMR_ALARM_PERIOD 48825
36 #define APP_LED_PORT PORT_CHANNEL_A
37 #define APP_LED_PIN PORTS_BIT_POS_4
38
39 static void dummy_handler(void);
40 static void (*tick_handler)(void);
41 static int hal_uart_needed_during_sleep = 1;
42
dummy_handler(void)43 static void dummy_handler(void){};
44 static DRV_HANDLE handleTmr;
45 static bool ledIsOn;
46
sys_tick_handler(uintptr_t context,uint32_t alarmCount)47 static void sys_tick_handler ( uintptr_t context, uint32_t alarmCount ){
48 if (!ledIsOn) {
49 ledIsOn = true;
50 SYS_PORTS_PinSet(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN);
51 }
52 else
53 {
54 ledIsOn = false;
55 SYS_PORTS_PinClear(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN);
56 }
57
58 (*tick_handler)();
59 }
60
hal_tick_init(void)61 void hal_tick_init(void){
62 ledIsOn = false;
63 handleTmr = DRV_TMR_Open(APP_TMR_DRV_INDEX, DRV_IO_INTENT_EXCLUSIVE);
64 if( DRV_HANDLE_INVALID == handleTmr ){
65 log_error("Timer init failed");
66 return;
67 }
68 DRV_TMR_Alarm16BitRegister(handleTmr, APP_TMR_ALARM_PERIOD, true, (uintptr_t)NULL, sys_tick_handler);
69 DRV_TMR_Start(handleTmr);
70 SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, APP_LED_PORT, APP_LED_PIN);
71 }
72
hal_tick_get_tick_period_in_ms(void)73 int hal_tick_get_tick_period_in_ms(void){
74 return 250;
75 }
76
hal_tick_set_handler(void (* handler)(void))77 void hal_tick_set_handler(void (*handler)(void)){
78 if (handler == NULL){
79 tick_handler = &dummy_handler;
80 return;
81 }
82 tick_handler = handler;
83 }
84
msleep(uint32_t delay)85 static void msleep(uint32_t delay) {
86 uint32_t wake = btstack_run_loop_embedded_get_ticks() + delay / hal_tick_get_tick_period_in_ms();
87 while (wake > btstack_run_loop_embedded_get_ticks()){
88 SYS_Tasks();
89 };
90 }
91
92 /// HAL CPU ///
93 #include "hal_cpu.h"
94
hal_cpu_disable_irqs(void)95 void hal_cpu_disable_irqs(void){
96 // TODO implement
97 }
98
hal_cpu_enable_irqs(void)99 void hal_cpu_enable_irqs(void){
100 // TODO implement
101 }
102
hal_cpu_enable_irqs_and_sleep(void)103 void hal_cpu_enable_irqs_and_sleep(void){
104 // TODO implement
105 }
106
107
108 /// HAL UART DMA ///
109 #include "hal_uart_dma.h"
110
111 // handlers
112 static void (*rx_done_handler)(void) = dummy_handler;
113 static void (*tx_done_handler)(void) = dummy_handler;
114 static void (*cts_irq_handler)(void) = dummy_handler;
115
116 // rx state
117 static uint16_t bytes_to_read = 0;
118 static uint8_t * rx_buffer_ptr = 0;
119
120 // tx state
121 static uint16_t bytes_to_write = 0;
122 static uint8_t * tx_buffer_ptr = 0;
123
124
125 // reset Bluetooth using n_shutdown
bluetooth_power_cycle(void)126 static void bluetooth_power_cycle(void){
127 printf("Bluetooth power cycle: Reset ON\n");
128 SYS_PORTS_PinClear(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT);
129 msleep(250);
130 printf("Bluetooth power cycle: Reset OFF\n");
131 SYS_PORTS_PinSet(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT);
132 }
133
hal_uart_dma_init(void)134 void hal_uart_dma_init(void){
135
136 bytes_to_write = 0;
137 bytes_to_read = 0;
138
139 /* PPS Input Remapping */
140 PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2RX, INPUT_PIN_RPF4 );
141 PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2CTS, INPUT_PIN_RPB2 );
142
143 /* PPS Output Remapping */
144 PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2RTS, OUTPUT_PIN_RPG9 );
145 PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2TX, OUTPUT_PIN_RPF5 );
146
147 /* Initialize USART */
148 PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), BT_USART_BAUD);
149 PLIB_USART_HandshakeModeSelect(BT_USART_ID, USART_HANDSHAKE_MODE_FLOW_CONTROL);
150 PLIB_USART_OperationModeSelect(BT_USART_ID, USART_ENABLE_TX_RX_CTS_RTS_USED);
151 PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8N1);
152
153 // BCSP on CSR requires even parity
154 // PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8E1);
155
156 PLIB_USART_TransmitterEnable(BT_USART_ID);
157 // PLIB_USART_TransmitterInterruptModeSelect(bluetooth_uart_id, USART_TRANSMIT_FIFO_IDLE);
158
159 // allow overrun mode: not needed for H4. CSR with BCSP/H5 does not enable RTS/CTS
160 PLIB_USART_RunInOverflowEnable(BT_USART_ID);
161
162 PLIB_USART_ReceiverEnable(BT_USART_ID);
163 // PLIB_USART_ReceiverInterruptModeSelect(bluetooth_uart_id, USART_RECEIVE_FIFO_ONE_CHAR);
164
165 PLIB_USART_Enable(BT_USART_ID);
166
167 // enable _RESET
168 SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, BT_RESET_PORT, BT_RESET_BIT);
169
170 bluetooth_power_cycle();
171
172 // After reset, CTS is high and we need to wait until CTS is low again
173
174 // HACK: CTS doesn't seem to work right now
175 msleep(250);
176 }
177
hal_uart_dma_set_block_received(void (* the_block_handler)(void))178 void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
179 rx_done_handler = the_block_handler;
180 }
181
hal_uart_dma_set_block_sent(void (* the_block_handler)(void))182 void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
183 tx_done_handler = the_block_handler;
184 }
185
hal_uart_dma_set_csr_irq_handler(void (* the_irq_handler)(void))186 void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
187 // not needed for regular H4 module (but needed for TI's eHCILL)
188 }
hal_uart_dma_set_sleep(uint8_t sleep)189 void hal_uart_dma_set_sleep(uint8_t sleep){
190 // not needed for regualr h4 module (but needed for eHCILL or h5)
191 UNUSED(sleep);
192 }
193
hal_uart_dma_set_baud(uint32_t baud)194 int hal_uart_dma_set_baud(uint32_t baud){
195 // PLIB_USART_Disable(BT_USART_ID);
196 // PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), baud);
197 // PLIB_USART_Enable(BT_USART_ID);
198 return 0;
199 }
200
hal_uart_dma_send_block(const uint8_t * data,uint16_t size)201 void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
202 tx_buffer_ptr = (uint8_t *) data;
203 bytes_to_write = size;}
204
205
hal_uart_dma_receive_block(uint8_t * data,uint16_t size)206 void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
207 // printf("hal_uart_dma_receive_block req size %u\n", size);
208 rx_buffer_ptr = data;
209 bytes_to_read = size;
210 }
211
212 ///
213 static hci_transport_config_uart_t config = {
214 HCI_TRANSPORT_CONFIG_UART,
215 115200,
216 0, // main baudrate
217 1, // flow control
218 NULL,
219 };
220
221 static btstack_packet_callback_registration_t hci_event_callback_registration;
222
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)223 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
224 if (packet_type != HCI_EVENT_PACKET) return;
225 if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
226 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
227 printf("BTstack up and running.\n");
228 }
229
BTSTACK_Initialize(void)230 void BTSTACK_Initialize ( void )
231 {
232 printf("\n\nBTstack_Initialize()\n");
233
234 btstack_memory_init();
235 btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
236
237 // hci_dump_open(NULL, HCI_DUMP_STDOUT);
238
239 // setup uart driver
240 const btstack_uart_block_t * uart_block_driver = btstack_uart_block_embedded_instance();
241 const btstack_uart_t * uart_slip_driver = btstack_uart_slip_wrapper_instance(uart_block_driver);
242
243 const hci_transport_t * transport = hci_transport_h5_instance(uart_slip_driver);
244 hci_init(transport, &config);
245 hci_set_chipset(btstack_chipset_csr_instance());
246
247 // inform about BTstack state
248 hci_event_callback_registration.callback = &packet_handler;
249 hci_add_event_handler(&hci_event_callback_registration);
250
251 btstack_main(0, NULL);
252 }
253
254
BTSTACK_Tasks(void)255 void BTSTACK_Tasks(void){
256
257 while (bytes_to_read && PLIB_USART_ReceiverDataIsAvailable(BT_USART_ID)) {
258 *rx_buffer_ptr++ = PLIB_USART_ReceiverByteReceive(BT_USART_ID);
259 bytes_to_read--;
260 if (bytes_to_read == 0){
261 (*rx_done_handler)();
262 }
263 }
264
265 if(PLIB_USART_ReceiverOverrunHasOccurred(BT_USART_ID))
266 {
267 // printf("RX Overrun!\n");
268 PLIB_USART_ReceiverOverrunErrorClear(BT_USART_ID);
269 }
270
271 while (bytes_to_write && !PLIB_USART_TransmitterBufferIsFull(BT_USART_ID)){
272 PLIB_USART_TransmitterByteSend(BT_USART_ID, *tx_buffer_ptr++);
273 bytes_to_write--;
274 if (bytes_to_write == 0){
275 (*tx_done_handler)();
276 }
277 }
278
279 // BTstack Run Loop
280 btstack_run_loop_embedded_execute_once();
281 }
282
283