diff --git a/ports/stm32/modstm.c b/ports/stm32/modstm.c index 3f4f33979afd5..be7fc6d85c948 100644 --- a/ports/stm32/modstm.c +++ b/ports/stm32/modstm.c @@ -50,6 +50,9 @@ STATIC const mp_rom_map_elem_t stm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_rfcore_status), MP_ROM_PTR(&rfcore_status_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_fw_version), MP_ROM_PTR(&rfcore_fw_version_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_sys_hci), MP_ROM_PTR(&rfcore_sys_hci_obj) }, + #if MICROPY_HW_STM32WB_TRANSPARENT_MODE + { MP_ROM_QSTR(MP_QSTR_rfcore_transparent), MP_ROM_PTR(&rfcore_transparent_obj) }, + #endif #endif }; diff --git a/ports/stm32/mpbthciport.c b/ports/stm32/mpbthciport.c index 369c91e30386c..35076e72390c8 100644 --- a/ports/stm32/mpbthciport.c +++ b/ports/stm32/mpbthciport.c @@ -181,6 +181,84 @@ int mp_bluetooth_hci_uart_readchar(void) { } } +#if MICROPY_HW_STM32WB_TRANSPARENT_MODE +#include "py/stream.h" + +STATIC int rfcore_transparent_msg_cb(void *env, const uint8_t *buf, size_t len) { + mp_hal_stdout_tx_strn((const char*)buf, len); + return 0; +} + +#define STATE_IDLE 0 +#define STATE_NEED_LEN 1 +#define STATE_IN_PAYLOAD 2 + +#define HCI_KIND_BT_CMD (0x01) // +#define HCI_KIND_BT_ACL (0x02) // +#define HCI_KIND_BT_EVENT (0x04) // +#define HCI_KIND_VENDOR_RESPONSE (0x11) +#define HCI_KIND_VENDOR_EVENT (0x12) + +STATIC mp_obj_t rfcore_transparent(void) { + rfcore_ble_init(); + + mp_hal_set_interrupt_char(-1); + + uint8_t buf[1024]; + size_t rx = 0; + size_t len = 0; + int state = 0; + int cmd_type = 0; + + while (true) { + if (state == STATE_IN_PAYLOAD && len == 0) { + rfcore_ble_hci_cmd(rx, buf); + // mp_hal_stdout_tx_strn((const char*)buf, rx); + rx = 0; + len = 0; + state = STATE_IDLE; + } + + if (mp_hal_stdio_poll(MP_STREAM_POLL_RD) & MP_STREAM_POLL_RD) { + uint8_t c = mp_hal_stdin_rx_chr(); + + if (state == STATE_IDLE && (c == HCI_KIND_BT_CMD || c == HCI_KIND_BT_ACL || c == HCI_KIND_BT_EVENT || c == HCI_KIND_VENDOR_RESPONSE || c == HCI_KIND_VENDOR_EVENT)) { + cmd_type = c; + state = STATE_NEED_LEN; + buf[rx++] = c; + len = 0; + } else if (state == STATE_NEED_LEN) { + buf[rx++] = c; + if (cmd_type == HCI_KIND_BT_ACL && rx == 4) { + len = c; + } + if (cmd_type == HCI_KIND_BT_ACL && rx == 5) { + len += ((size_t)c) << 8; + state = STATE_IN_PAYLOAD; + } + if (cmd_type == HCI_KIND_BT_EVENT && rx == 3) { + len = c; + state = STATE_IN_PAYLOAD; + } + if (cmd_type == HCI_KIND_BT_CMD && rx == 4) { + len = c; + state = STATE_IN_PAYLOAD; + } + } else if (state == STATE_IN_PAYLOAD) { + buf[rx++] = c; + --len; + } + } + + rfcore_ble_check_msg(rfcore_transparent_msg_cb, NULL); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(rfcore_transparent_obj, rfcore_transparent); +#endif // MICROPY_HW_STM32WB_TRANSPARENT_MODE + + #else /******************************************************************************/ diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c index 67b63679a72a6..024c7a2c1f57e 100644 --- a/ports/stm32/rfcore.c +++ b/ports/stm32/rfcore.c @@ -45,6 +45,8 @@ #if MICROPY_BLUETOOTH_NIMBLE // For mp_bluetooth_nimble_hci_uart_wfi #include "nimble/nimble_npl.h" +// For mp_bluetooth_nimble_ble_state +#include "modbluetooth_nimble.h" #else #error "STM32WB must use NimBLE." #endif @@ -261,7 +263,6 @@ void ipcc_init(uint32_t irq_pri) { // Enable receive IRQ on the BLE channel. LL_C1_IPCC_EnableIT_RXO(IPCC); LL_C1_IPCC_DisableReceiveChannel(IPCC, LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6); - LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE); NVIC_SetPriority(IPCC_C1_RX_IRQn, irq_pri); HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn); @@ -447,7 +448,7 @@ STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_h // Clear receive channel (allows RF core to send more data to us). LL_C1_IPCC_ClearFlag_CHx(IPCC, ch); - if (ch == IPCC_CH_BLE) { + if (ch == IPCC_CH_BLE && (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF)) { // Renable IRQs for BLE now that we've cleared the flag. LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE); } @@ -585,6 +586,10 @@ static const struct { void rfcore_ble_init(void) { DEBUG_printf("rfcore_ble_init\n"); + if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { + LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE); + } + // Clear any outstanding messages from ipcc_init. tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL); @@ -642,7 +647,9 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) { break; } #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE - mp_bluetooth_nimble_hci_uart_wfi(); + if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { + mp_bluetooth_nimble_hci_uart_wfi(); + } #endif } diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h index fe29ac612ccc6..0988deb479aef 100644 --- a/ports/stm32/rfcore.h +++ b/ports/stm32/rfcore.h @@ -34,6 +34,9 @@ void rfcore_ble_init(void); void rfcore_ble_hci_cmd(size_t len, const uint8_t *src); void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env); void rfcore_ble_set_txpower(uint8_t level); +#if MICROPY_HW_STM32WB_TRANSPARENT_MODE +void rfcore_ble_disable_ble_rx_interrupt(void); +#endif void rfcore_start_flash_erase(void); void rfcore_end_flash_erase(void); @@ -41,5 +44,7 @@ void rfcore_end_flash_erase(void); MP_DECLARE_CONST_FUN_OBJ_0(rfcore_status_obj); MP_DECLARE_CONST_FUN_OBJ_1(rfcore_fw_version_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj); - +#if MICROPY_HW_STM32WB_TRANSPARENT_MODE +MP_DECLARE_CONST_FUN_OBJ_0(rfcore_transparent_obj); +#endif #endif // MICROPY_INCLUDED_STM32_RFCORE_H