#include "app_config.h" #include "app_task.h" #include "app_btdm.h" #include "app_audio.h" #include "app_ble.h" #include "app_bt.h" #include "user_bt.h" #include "co_list.h" #include "controller.h" #include "host.h" #include "btdm_mem.h" #include "fdb_app.h" #define SCO_DATA_BUFFER_COUNT 4 typedef int32_t app_btdm_ret_t; struct sco_data_t { struct co_list_hdr hdr; void *arg; uint16_t length; uint8_t data[]; }; uint8_t bt_addr[] = {0x12, 0x00, 0x12, 0x12, 0x12, 0x12}; uint8_t ble_public_addr[] = {0x13, 0x00, 0x88, 0x12, 0x12, 0x12}; uint8_t ble_static_addr[] = {0x13, 0x66, 0x88, 0x12, 0x12, 0xc2}; static uint8_t sco_data_buffering = 0; static struct co_list sco_data_list; static void encoded_sco_frame_cb(void *arg, uint8_t *data, uint16_t length) { static uint16_t seq = 0; if (sco_data_buffering) { struct sco_data_t *sco_data; sco_data = (void *)btdm_malloc(sizeof(struct sco_data_t) + length); sco_data->arg = arg; sco_data->length = length; memcpy((void *)&sco_data->data[0], data, length); co_list_push_back(&sco_data_list, &sco_data->hdr); sco_data_buffering--; if (sco_data_buffering == 0) { sco_data = (void *)co_list_pop_front(&sco_data_list); while (sco_data) { //fputc('D', NULL); app_bt_send_sco_data(sco_data->arg, seq++, sco_data->data, sco_data->length); btdm_free((void *)sco_data); sco_data = (void *)co_list_pop_front(&sco_data_list); } } } else { //fputc('D', NULL); app_bt_send_sco_data(arg, seq++, data, length); } } static void btdm_callback(struct app_btdm_event_t *event) { switch(event->event) { case APP_BTDM_EVT_A2DP_STREAM_STARTED: if (event->param.a2dp_codec.codec_type == APP_BTDM_CODEC_SBC) { app_audio_a2dp_sink_start(AUDIO_TYPE_SBC, event->param.a2dp_codec.sample_rate); } else if (event->param.a2dp_codec.codec_type == APP_BTDM_CODEC_AAC) { app_audio_a2dp_sink_start(AUDIO_TYPE_AAC, event->param.a2dp_codec.sample_rate); } system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_A2DP_ONGOING); break; case APP_BTDM_EVT_A2DP_STREAM_STOPPED: app_audio_a2dp_sink_stop(); system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_A2DP_ONGOING); break; case APP_BTDM_EVT_A2DP_STREAM_DATA: app_audio_a2dp_sink_play(event->param.a2dp_data.buffer, event->param.a2dp_data.length); break; case APP_BTDM_EVT_SCO_CREATED: sco_data_buffering = SCO_DATA_BUFFER_COUNT; { struct sco_data_t *sco_data; sco_data = (void *)co_list_pop_front(&sco_data_list); while (sco_data) { btdm_free((void *)sco_data); sco_data = (void *)co_list_pop_front(&sco_data_list); } } if (event->param.sco_codec.codec_type == APP_BTDM_CODEC_mSBC) { app_audio_sco_start(AUDIO_TYPE_MSBC, encoded_sco_frame_cb, event->param.sco_codec.hf_channel); } else { app_audio_sco_start(AUDIO_TYPE_PCM, encoded_sco_frame_cb, event->param.sco_codec.hf_channel); } system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_SCO_ONGOING); break; case APP_BTDM_EVT_SCO_REMOVED: app_audio_sco_stop(); system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_SCO_ONGOING); break; case APP_BTDM_EVT_SCO_DATA: { uint8_t audio_codec_type; if (event->param.sco_data.codec_type == APP_BTDM_CODEC_mSBC) { audio_codec_type = AUDIO_TYPE_MSBC; } else { audio_codec_type = AUDIO_TYPE_PCM; } app_audio_sco_recv(event->param.sco_data.valid, audio_codec_type, event->param.sco_data.buffer, event->param.sco_data.length); } break; default: break; } } void app_btdm_start(void) { app_ble_init(); #if BTDM_STACK_ENABLE_BT == 1 app_bt_init(btdm_callback); user_bt_init(); #endif } void host_ready_cb(void) { struct app_task_event *event; /* notify application BTDM stack is ready. */ event = app_task_event_alloc(APP_TASK_EVENT_HOST_INITED, 0, true); app_task_event_post(event, false); } void app_btdm_init(void) { /*get bt addr*/ #if BT_ADDR_RANDOM_ENABLE | BLE_ADDR_RANDOM_ENABLE uint8_t rand_num[4]; if(flashdb_get(FDB_KEY_USER_RANDOM_SEED, (void *)&rand_num[0], 4) != 0){ #if BT_ADDR_RANDOM_ENABLE memcpy((void *)&bt_addr[0],rand_num,4); #endif #if BLE_ADDR_RANDOM_ENABLE memcpy((void *)&ble_static_addr[0],rand_num,4); #endif } #endif /* prepare for BTDM stack */ #if defined(__CC_ARM) || defined(__ARMCC_VERSION) extern uint8_t CONTROLLER_CODE_OTA_BASE; uint32_t controller_code_base_addr = (uint32_t)&CONTROLLER_CODE_OTA_BASE; controller_start(BTDM_STACK_HCI_BAUDRATE, ble_public_addr, bt_addr, controller_code_base_addr); #elif defined(__GNUC__) || defined(__ICCARM__) extern const uint8_t controller_code_buffer[]; controller_start(BTDM_STACK_HCI_BAUDRATE, ble_public_addr, bt_addr, (uint32_t)&controller_code_buffer[0]); #else #error "not supported platform" #endif #if BTDM_STACK_ENABLE_BT == 1 host_btdm_start(BTDM_STACK_HCI_BAUDRATE, HOST_TASK_STACK_SIZE, HOST_TASK_PRIORITY, ble_static_addr); #else host_ble_start(BTDM_STACK_HCI_BAUDRATE, HOST_TASK_STACK_SIZE, HOST_TASK_PRIORITY, ble_static_addr); #endif /* init MCU->BT pin, configure PMU_PIN_8 output BBG_EN signal */ ool_write(PMU_REG_DIAG_CTRL, 0x82); ool_write(PMU_REG_PIN_IOMUX_H, 0x03); /* disable PMU pin input as default setting */ ool_write16(PMU_REG_PIN_INPUT_EN, 0x0002); /* PP1 is connected to ARST of 1010, this pin is low in sleep mode */ ool_write16(PMU_REG_PIN_PULL_EN, 0x3ffd); ool_write16(PMU_REG_PIN_PULL_SEL, 0x3fff); /* init BT->MCU pin, system should not enter sleep mode when this pin is low level */ system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX); pmu_gpio_int_init(PMU_PIN_9, PMU_GPIO_PULL_UP, 0); pmu_enable_isr(PMU_GPIO_PMU_INT_MSK_BIT); NVIC_SetPriority(PMU_IRQn, 4); NVIC_EnableIRQ(PMU_IRQn); } app_btdm_ret_t app_btdm_ble_adv_start(uint16_t dur) { return -1; } app_btdm_ret_t app_btdm_ble_adv_stop(void) { return -1; } app_btdm_ret_t app_btdm_ble_disconnect(void) { return -1; } app_btdm_ret_t app_btdm_bt_access_mode_set(uint8_t mode) { return -1; } app_btdm_ret_t app_btdm_bt_scan_start(uint16_t dur) { return -1; } app_btdm_ret_t app_btdm_bt_scan_stop(void) { return -1; } app_btdm_ret_t app_btdm_bt_connect(uint8_t *peer_addr) { return -1; } app_btdm_ret_t app_btdm_bt_disconnect(void) { return -1; } app_btdm_ret_t app_btdm_bt_profile_enable(uint16_t profiles) { return -1; } const uint8_t *app_get_bt_addr(void) { return bt_addr; }