demo工程暂存 优化菜单界面UI和功能
This commit is contained in:
701
MCU/examples/application/btdm_audio/Src/app_at.c
Normal file
701
MCU/examples/application/btdm_audio/Src/app_at.c
Normal file
@ -0,0 +1,701 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fr30xx.h"
|
||||
|
||||
#include "co_util.h"
|
||||
|
||||
#include "bt_types.h"
|
||||
#include "me_api.h"
|
||||
#include "hfg_api.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
#include "app_at.h"
|
||||
#include "app_task.h"
|
||||
#include "app_ble.h"
|
||||
#include "app_bt.h"
|
||||
#include "app_audio.h"
|
||||
#include "btdm_mem.h"
|
||||
#include "fdb_app.h"
|
||||
#include "user_bt.h"
|
||||
#include "dsp_mem.h"
|
||||
#include "heap.h"
|
||||
|
||||
#define AT_RECV_MAX_LEN 32
|
||||
|
||||
static uint8_t app_at_recv_char;
|
||||
static uint8_t at_recv_buffer[AT_RECV_MAX_LEN];
|
||||
static uint8_t at_recv_index = 0;
|
||||
static uint8_t at_recv_state = 0;
|
||||
|
||||
void btdm_host_send_vendor_cmd(uint8_t type, uint8_t length, void *data);
|
||||
|
||||
void btdm_host_vendor_cmd_cmp_evt(uint8_t status, uint8_t len, uint8_t const *param)
|
||||
{
|
||||
printf("status: 0x%02x.\r\n", status);
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
printf("%02x ", param[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
static void app_at_recv_cmd_A(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
switch(sub_cmd)
|
||||
{
|
||||
// case 'A':
|
||||
// {
|
||||
// mac_addr_t addr;
|
||||
// addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
// addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||||
// addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||||
// addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||||
// addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||||
// addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||||
// gap_start_conn(&addr, ascii_strn2val((const char *)&data[12], 16, 2), 64, 64, 0, 500);
|
||||
// }
|
||||
// break;
|
||||
// case 'B':
|
||||
// {
|
||||
// gap_stop_conn();
|
||||
// }
|
||||
// break;
|
||||
case 'A':
|
||||
{
|
||||
uint8_t addr = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
btdm_host_send_vendor_cmd(0x00, 1, &addr);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'B':
|
||||
{
|
||||
uint8_t buffer[2];
|
||||
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
buffer[1] = ascii_strn2val((const char *)&data[3], 16, 2);
|
||||
btdm_host_send_vendor_cmd(0x01, 2, (void *)&buffer[0]);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'C':
|
||||
{
|
||||
uint32_t addr = ascii_strn2val((const char *)&data[0], 16, 8);
|
||||
btdm_host_send_vendor_cmd(0x02, 4, (void *)&addr);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'D':
|
||||
{
|
||||
uint32_t buffer[2];
|
||||
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 8);
|
||||
buffer[1] = ascii_strn2val((const char *)&data[9], 16, 8);
|
||||
btdm_host_send_vendor_cmd(0x03, 8, (void *)&buffer[0]);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'G':
|
||||
printf("hello world!\r\n");
|
||||
break;
|
||||
case 'H':
|
||||
printf("VAL: 0x%08x.\r\n", *(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8));
|
||||
break;
|
||||
case 'I':
|
||||
*(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8) = ascii_strn2val((const char *)&data[9], 16, 8);
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'J':
|
||||
printf("OOL VAL: 0x%02x.\r\n", ool_read(ascii_strn2val((const char *)&data[0], 16, 2)));
|
||||
break;
|
||||
case 'K':
|
||||
ool_write(ascii_strn2val((const char *)&data[0], 16, 2), ascii_strn2val((const char *)&data[3], 16, 2));
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'L':
|
||||
printf("VAL: 0x%02x.\r\n", *(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)));
|
||||
break;
|
||||
case 'M':
|
||||
*(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)) = ascii_strn2val((const char *)&data[9], 16, 2);
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
// case 'P':
|
||||
// co_printf("VAL: 0x%02x.\r\n", *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)));
|
||||
// break;
|
||||
// case 'Q':
|
||||
// *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)) = ascii_strn2val((const char *)&data[3], 16, 2);
|
||||
// co_printf("OK\r\n");
|
||||
// break;
|
||||
// case 'S':
|
||||
// co_printf("VAL: 0x%02x.\r\n", frspim_rd(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1));
|
||||
// break;
|
||||
// case 'T':
|
||||
// frspim_wr(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1, ascii_strn2val((const char *)&data[3], 16, 2));
|
||||
// co_printf("OK\r\n");
|
||||
// break;
|
||||
case 'U':
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)(ascii_strn2val((const char *)&data[0], 16, 8) & (~3));
|
||||
uint8_t count = ascii_strn2val((const char *)&data[9], 16, 2);
|
||||
uint32_t *start = (uint32_t *)((uint32_t)ptr & (~0x0f));
|
||||
for(uint8_t i=0; i<count;) {
|
||||
if(((uint32_t)start & 0x0c) == 0) {
|
||||
printf("0x%08x: ", (uint32_t)start);
|
||||
}
|
||||
if(start < ptr) {
|
||||
printf(" ");
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
printf("%08x", *start);
|
||||
}
|
||||
if(((uint32_t)start & 0x0c) == 0x0c) {
|
||||
printf("\r\n");
|
||||
}
|
||||
else {
|
||||
printf(" ");
|
||||
}
|
||||
start++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
flash_erase(QSPI0, ascii_strn2val((const char *)&data[0], 16, 8), ascii_strn2val((const char *)&data[9], 16, 8));
|
||||
break;
|
||||
case 'W':
|
||||
{
|
||||
uint32_t curr_free, min_free;
|
||||
dsp_mem_get_usage(&curr_free, &min_free);
|
||||
printf("DSP MEM: %d, %d\r\n", curr_free, min_free);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
{
|
||||
void system_reset(void);
|
||||
system_reset();
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
heap_dump_used_mem(ascii_strn2val((const char *)&data[0], 16, 2));
|
||||
break;
|
||||
case 'Z':
|
||||
printf("MEM usage\r\n \
|
||||
\tHEAP_TYPE_SRAM_BLOCK: %d, %d\r\n \
|
||||
\tHEAP_TYPE_DRAM_BLOCK: %d, %d\r\n \
|
||||
\tHEAP_TYPE_BTDM_BLOCK: %d, %d\r\n \
|
||||
\tTOTAL USAGE: %d\r\n", \
|
||||
heap_get_mem_usage(HEAP_TYPE_SRAM_BLOCK), heap_get_mem_usage_single(HEAP_TYPE_SRAM_BLOCK), \
|
||||
heap_get_mem_usage(HEAP_TYPE_DRAM_BLOCK), heap_get_mem_usage_single(HEAP_TYPE_DRAM_BLOCK), \
|
||||
heap_get_mem_usage(HEAP_TYPE_BTDM_BLOCK), heap_get_mem_usage_single(HEAP_TYPE_BTDM_BLOCK), \
|
||||
heap_get_max_mem_usage());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void user_hci_callback(const BtEvent *event)
|
||||
{
|
||||
printf("event type = %d\r\n",event->eType);
|
||||
if(event->eType == BTEVENT_COMMAND_COMPLETE){
|
||||
btdm_free(event->p.meToken);
|
||||
}
|
||||
}
|
||||
static void app_at_recv_cmd_B(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
struct gap_ble_addr peer_addr;
|
||||
BD_ADDR addr;
|
||||
HfgResponse *rsp;
|
||||
BtStatus status;
|
||||
MeCommandToken *token;
|
||||
uint16_t page_timeout = 0x400;
|
||||
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
// AT#BA00
|
||||
//app_ble_start_advertising(ascii_strn2val((const char *)&data[0], 16, 2));
|
||||
break;
|
||||
case 'B':
|
||||
// AT#BB01
|
||||
//app_ble_stop_advertising(ascii_strn2val((const char *)&data[0], 16, 2));
|
||||
break;
|
||||
case 'C':
|
||||
app_ble_scan_start();
|
||||
break;
|
||||
case 'D':
|
||||
app_ble_scan_stop();
|
||||
break;
|
||||
case 'E':
|
||||
// AT#BE0123456789ab_01
|
||||
peer_addr.addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
peer_addr.addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||||
peer_addr.addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||||
peer_addr.addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||||
peer_addr.addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||||
peer_addr.addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||||
peer_addr.addr_type = ascii_strn2val((const char *)&data[13], 16, 2);
|
||||
app_ble_conn_start(&peer_addr);
|
||||
break;
|
||||
case 'F':
|
||||
app_ble_conn_stop();
|
||||
break;
|
||||
#if BTDM_STACK_ENABLE_BT == 1
|
||||
case 'H':
|
||||
ME_Inquiry(BT_IAC_GIAC, 5, 5);
|
||||
break;
|
||||
case 'I':
|
||||
ME_CancelInquiry();
|
||||
break;
|
||||
case 'J':
|
||||
{
|
||||
BtStatus status;
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
|
||||
status = HFG_CreateServiceLink(&hfg_channel[0], &addr);
|
||||
|
||||
if (status == BT_STATUS_PENDING) {
|
||||
printf("Opening Channel...\r\n");
|
||||
} else {
|
||||
printf("Could not open channel, status: %d\r\n", status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'K':
|
||||
status = BT_STATUS_NO_RESOURCES;
|
||||
rsp = (HfgResponse *)btdm_malloc(sizeof(HfgResponse));
|
||||
if(rsp != NULL){
|
||||
status = HFG_CreateCodecConnection(&hfg_channel[0], 1, rsp);
|
||||
}
|
||||
if(status != BT_STATUS_PENDING){
|
||||
btdm_free((void *)rsp);
|
||||
}
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'L':
|
||||
flashdb_del(FDB_KEY_BT_LINKKEY);
|
||||
|
||||
break;
|
||||
case 'M':
|
||||
token = btdm_malloc(sizeof(MeCommandToken));
|
||||
token->p.general.in.hciCommand = 0x0c18;//HCC_WRITE_PAGE_TIMEOUT;
|
||||
token->p.general.in.parmLen = 2;
|
||||
token->p.general.in.parms = (uint8_t *)&page_timeout;
|
||||
token->callback = user_hci_callback; //token is freed at this callback
|
||||
status = ME_SendHciCommandAsync(token);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'N':
|
||||
{
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
user_bt_env.connect_times = 3;
|
||||
status = bt_connect(&addr);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'O':
|
||||
// {
|
||||
// uint8_t battery_level[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
||||
// struct gatt_send_event ntf[6];
|
||||
// uint8_t i=0;
|
||||
// for(i=0;i<6;i++){
|
||||
// ntf[i].conidx = 0;
|
||||
// ntf[i].svc_id = svc_id;
|
||||
// ntf[i].att_idx = 2;
|
||||
// ntf[i].data_len = 15;
|
||||
// ntf[i].p_data = &battery_level[0];
|
||||
// gatt_notification(&ntf[i]);
|
||||
// }
|
||||
// }
|
||||
break;
|
||||
case 'P':
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
bt_disconnect(&addr,false);
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
bt_disconnect(&addr,true);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
// ME_SetLocalDeviceName((const uint8_t *)"FR30xx_m", sizeof("FR30xx_m"));
|
||||
//app_btdm_init();
|
||||
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
BtAccessModeInfo access_mode_nc = {
|
||||
.inqInterval = 0x800,
|
||||
.inqWindow = 0x12,
|
||||
.pageInterval = 0x800,
|
||||
.pageWindow = 0x12,
|
||||
};
|
||||
status = bt_enter_pairing(BAM_GENERAL_ACCESSIBLE, &access_mode_nc);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
{
|
||||
status = bt_exit_pairing();
|
||||
printf("status = %d\r\n",status);
|
||||
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
{
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
bt_exit_pairing();
|
||||
bt_connect(&addr);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
printf("OK\r\n");
|
||||
}
|
||||
|
||||
uint8_t voltage_str[] = "AT+IPHONEACCEV=1,1,6";
|
||||
uint8_t cmps_str[] = "AT+CPMS=?";
|
||||
uint8_t clk_str[] = "AT+CCLK=?";
|
||||
//bt hf&pbap related cmd
|
||||
static void app_at_recv_cmd_C(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
BtStatus status;
|
||||
BD_ADDR addr;
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
status = bt_answer_call(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'B':
|
||||
status = bt_hang_up(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'C':
|
||||
status = bt_redial(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'D':
|
||||
{
|
||||
uint8_t number[] = "10086";
|
||||
status = bt_dial_number(user_bt_env.last_active_index,number,sizeof(number));
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
status = bt_list_current_calls(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'F':
|
||||
status = bt_transfer_sco(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'G':
|
||||
{
|
||||
uint8_t dtmf = data[0];
|
||||
status = bt_send_dtmf(user_bt_env.last_active_index,dtmf);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
{
|
||||
//vol---[0x00,0x0f]
|
||||
uint8_t vol = ascii_strn2val((const char*)&data[0],16,2);
|
||||
status = bt_report_spk_volume(user_bt_env.last_active_index,vol);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
{
|
||||
status = bt_send_hf_cmd(user_bt_env.last_active_index,voltage_str);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
{
|
||||
uint8_t enabled = ascii_strn2val((const char*)&data[0],16,2);
|
||||
status = bt_enable_voice_recognition(user_bt_env.last_active_index, enabled);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'K':
|
||||
printf("voice recog enabled : %d\r\n",bt_is_voice_rec_active(user_bt_env.last_active_index));
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
// addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
// addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
// addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
// addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
// addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
// addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
if(user_bt_get_state(user_bt_env.last_active_index) >= BT_STATE_CONNECTED){
|
||||
printf("pbap client %d\r\n",pbap_client[user_bt_env.last_active_index].cApp.connState);
|
||||
status = PBAP_ClientConnect(&pbap_client[user_bt_env.last_active_index],&user_bt_env.dev[user_bt_env.last_active_index].remote_bd);
|
||||
if(status == BT_STATUS_PENDING){
|
||||
user_bt_env.dev[user_bt_env.last_active_index].pbap_client = &pbap_client[user_bt_env.last_active_index];
|
||||
}
|
||||
}
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'M':
|
||||
status = PBAP_ClientDisconnect(&pbap_client[user_bt_env.last_active_index]);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'N':
|
||||
{
|
||||
uint8_t pbName[64];
|
||||
PbapPullPbParms parms;
|
||||
|
||||
memcpy(pbName,PB_LOCAL_MCH_NAME,sizeof(PB_LOCAL_MCH_NAME));
|
||||
parms.pbName = pbName;
|
||||
memset(parms.filter.byte,0,PBAP_FILTER_SIZE);
|
||||
parms.filter.byte[0] = 0x84;
|
||||
parms.listStartOffset = 0;
|
||||
parms.maxListCount = 4; //0---search missed call and total pb size
|
||||
parms.format= VCARD_FORMAT_30;
|
||||
status = PBAP_PullPhonebook(&pbap_client[0], &parms);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
{
|
||||
PbapPullVcardListingParms parms;
|
||||
uint8_t search_val[12]; //= "13262651013";
|
||||
memcpy(search_val,&data[0],11);
|
||||
uint8_t folder[] = "telecom/pb";
|
||||
parms.folderName = folder;
|
||||
parms.order = VCARD_SORT_ORDER_INDEXED;
|
||||
parms.listStartOffset = 0x00;
|
||||
parms.maxListCount = 4;
|
||||
parms.searchAttribute = VCARD_SEARCH_ATTRIB_NUMBER;
|
||||
parms.searchValue = search_val;
|
||||
status = PBAP_PullVcardListing(&pbap_client[0], &parms);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
{
|
||||
uint8_t pbName[64];
|
||||
PbapPullPbParms parms;
|
||||
|
||||
memcpy(pbName,PB_LOCAL_STORE_NAME,sizeof(PB_LOCAL_STORE_NAME));
|
||||
parms.pbName = pbName;
|
||||
memset(parms.filter.byte,0,PBAP_FILTER_SIZE);
|
||||
parms.filter.byte[0] = 0x07;//0x84;
|
||||
parms.listStartOffset = 0;
|
||||
parms.maxListCount = 20; //0---search missed call and total pb size
|
||||
parms.format= VCARD_FORMAT_30;
|
||||
status = PBAP_PullPhonebook(&pbap_client[0], &parms);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
{
|
||||
uint8_t mute_str[] = "AT+CMUT=1";
|
||||
status = bt_send_hf_cmd(user_bt_env.last_active_index,mute_str);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'Y':
|
||||
{
|
||||
|
||||
status = bt_send_hf_cmd(user_bt_env.last_active_index,clk_str);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
case 'Z':
|
||||
{
|
||||
uint8_t mute_str[] = "AT+CCLK?";
|
||||
status = bt_send_hf_cmd(user_bt_env.last_active_index,mute_str);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("OK\r\n");
|
||||
}
|
||||
|
||||
///bt media related cmd
|
||||
static void app_at_recv_cmd_E(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
BD_ADDR addr;
|
||||
BtStatus status;
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_PLAY, TRUE);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'B':
|
||||
status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_PAUSE, TRUE);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'C':
|
||||
status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_FORWARD, TRUE);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'D':
|
||||
{
|
||||
status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_BACKWARD, TRUE);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
{
|
||||
uint8_t vol = ascii_strn2val((const char*)&data[0],16,2);
|
||||
status = bt_set_media_volume(user_bt_env.last_active_index,vol);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
{
|
||||
status = bt_get_media_info(user_bt_env.last_active_index,0x41);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
{
|
||||
status = bt_get_playstatus(user_bt_env.last_active_index);
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
status = spp_connect(&spp_dev[0],&addr);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'I':
|
||||
status = spp_disconnect(&spp_dev[0]);
|
||||
printf("status = %d\r\n",status);
|
||||
break;
|
||||
case 'J':
|
||||
{
|
||||
uint8_t test_data[] = {'1','2','3','4'};
|
||||
status = spp_send(&spp_dev[0],test_data,sizeof(test_data));
|
||||
printf("status = %d\r\n",status);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("OK\r\n");
|
||||
}
|
||||
|
||||
static void app_at_recv_cmd_D(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
flash_erase(QSPI0, ascii_strn2val((const char*)&data[0],16,8), 0x1000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("OK\r\n");
|
||||
}
|
||||
|
||||
void app_at_cmd_recv_handler(uint8_t *data, uint16_t length)
|
||||
{
|
||||
switch(data[0])
|
||||
{
|
||||
case 'A':
|
||||
app_at_recv_cmd_A(data[1], &data[2]);
|
||||
break;
|
||||
case 'B':
|
||||
app_at_recv_cmd_B(data[1], &data[2]);
|
||||
break;
|
||||
case 'C':
|
||||
app_at_recv_cmd_C(data[1], &data[2]);
|
||||
break;
|
||||
case 'D':
|
||||
app_at_recv_cmd_D(data[1], &data[2]);
|
||||
break;
|
||||
case 'E':
|
||||
app_at_recv_cmd_E(data[1], &data[2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void app_at_recv_c(uint8_t c)
|
||||
{
|
||||
switch(at_recv_state)
|
||||
{
|
||||
case 0:
|
||||
if(c == 'A')
|
||||
{
|
||||
at_recv_state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(c == 'T')
|
||||
at_recv_state++;
|
||||
else
|
||||
at_recv_state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if(c == '#')
|
||||
at_recv_state++;
|
||||
else
|
||||
at_recv_state = 0;
|
||||
break;
|
||||
case 3:
|
||||
at_recv_buffer[at_recv_index++] = c;
|
||||
if((c == '\n')
|
||||
||(at_recv_index >= AT_RECV_MAX_LEN))
|
||||
{
|
||||
struct app_task_event *event;
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_AT_CMD, at_recv_index, false);
|
||||
if(event) {
|
||||
memcpy(event->param, at_recv_buffer, at_recv_index);
|
||||
app_task_event_post(event, false);
|
||||
}
|
||||
at_recv_state = 0;
|
||||
at_recv_index = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void app_at_rx_done(struct __UART_HandleTypeDef *handle)
|
||||
{
|
||||
app_at_recv_c(app_at_recv_char);
|
||||
if (handle) {
|
||||
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void app_at_init(struct __UART_HandleTypeDef *handle)
|
||||
{
|
||||
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||||
}
|
14
MCU/examples/application/btdm_audio/Src/app_at.h
Normal file
14
MCU/examples/application/btdm_audio/Src/app_at.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _APP_AT_H
|
||||
#define _APP_AT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver_uart.h"
|
||||
|
||||
void app_at_cmd_recv_handler(uint8_t *data, uint16_t length);
|
||||
|
||||
void app_at_rx_done(struct __UART_HandleTypeDef *handle);
|
||||
|
||||
void app_at_init(struct __UART_HandleTypeDef *handle);
|
||||
|
||||
#endif // _APP_AT_H
|
148
MCU/examples/application/btdm_audio/Src/app_audio.c
Normal file
148
MCU/examples/application/btdm_audio/Src/app_audio.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "app_config.h"
|
||||
#include "app_audio.h"
|
||||
|
||||
#include "audio_scene.h"
|
||||
#include "co_list.h"
|
||||
|
||||
#define APP_AUDIO_DATA_READY_THD 6
|
||||
#define APP_AUDIO_DATA_BUFFER_MAX 12
|
||||
|
||||
enum app_audio_mode_t {
|
||||
APP_AUDIO_MODE_IDLE,
|
||||
APP_AUDIO_MODE_A2DP_SINK,
|
||||
APP_AUDIO_MODE_A2DP_SOURCE,
|
||||
APP_AUDIO_MODE_SCO,
|
||||
APP_AUDIO_MODE_TONE,
|
||||
APP_AUDIO_MODE_VOICE_RECOGNIZE,
|
||||
};
|
||||
|
||||
static enum app_audio_mode_t audio_mode = APP_AUDIO_MODE_IDLE;
|
||||
static uint32_t audio_data_counter = 0;
|
||||
static audio_scene_t *audio_scene;
|
||||
|
||||
static void audio_pa_disable(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void audio_pa_enable(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void app_audio_stop(void)
|
||||
{
|
||||
switch(audio_mode) {
|
||||
case APP_AUDIO_MODE_A2DP_SINK:
|
||||
app_audio_a2dp_sink_stop();
|
||||
break;
|
||||
case APP_AUDIO_MODE_SCO:
|
||||
app_audio_sco_stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void app_audio_a2dp_sink_start(audio_type_t audio_type, uint32_t sample_rate)
|
||||
{
|
||||
audio_scene_param_a2dp_sink_t param;
|
||||
|
||||
if (audio_mode == APP_AUDIO_MODE_A2DP_SINK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio_mode != APP_AUDIO_MODE_IDLE) {
|
||||
app_audio_stop();
|
||||
}
|
||||
|
||||
param.sample_rate = sample_rate;
|
||||
param.channels = 2;
|
||||
param.audio_type = audio_type;
|
||||
param.hw_type = AUDIO_HW_TYPE_CODEC;
|
||||
param.hw_base_addr = I2S0_BASE;
|
||||
|
||||
assert(audio_mode == APP_AUDIO_MODE_IDLE);
|
||||
|
||||
audio_scene = audio_scene_create(AUDIO_SCENE_TYPE_A2DP_SINK, ¶m);
|
||||
assert(audio_scene != NULL);
|
||||
audio_mode = APP_AUDIO_MODE_A2DP_SINK;
|
||||
}
|
||||
|
||||
void app_audio_a2dp_sink_stop(void)
|
||||
{
|
||||
if (audio_mode == APP_AUDIO_MODE_A2DP_SINK) {
|
||||
audio_scene_destroy(audio_scene);
|
||||
audio_mode = APP_AUDIO_MODE_IDLE;
|
||||
audio_pa_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void app_audio_a2dp_sink_play(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (audio_mode == APP_AUDIO_MODE_A2DP_SINK) {
|
||||
if (audio_scene_dac_is_ready(audio_scene)) {
|
||||
audio_pa_enable();
|
||||
}
|
||||
audio_scene_recv_raw_data(audio_scene, true, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
void app_audio_sco_start(audio_type_t audio_type,audio_sence_report_encoded_frame report_enc_cb, void *report_enc_arg)
|
||||
{
|
||||
audio_scene_param_sco_t param;
|
||||
|
||||
if (audio_mode == APP_AUDIO_MODE_SCO) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio_mode != APP_AUDIO_MODE_IDLE) {
|
||||
app_audio_stop();
|
||||
}
|
||||
|
||||
if (audio_type == AUDIO_TYPE_MSBC) {
|
||||
printf("SCO: msbc.\r\n");
|
||||
param.sample_rate = 16000;
|
||||
}
|
||||
else {
|
||||
printf("SCO: cvsd.\r\n");
|
||||
param.sample_rate = 8000;
|
||||
}
|
||||
param.audio_type = audio_type;
|
||||
param.hw_type = AUDIO_HW_TYPE_CODEC;
|
||||
param.hw_base_addr = I2S0_BASE;
|
||||
param.report_enc_cb = report_enc_cb;
|
||||
param.report_enc_arg = report_enc_arg;
|
||||
|
||||
assert(audio_mode == APP_AUDIO_MODE_IDLE);
|
||||
|
||||
audio_scene = audio_scene_create(AUDIO_SCENE_TYPE_SCO, ¶m);
|
||||
audio_mode = APP_AUDIO_MODE_SCO;
|
||||
assert(audio_scene != NULL);
|
||||
}
|
||||
|
||||
void app_audio_sco_stop(void)
|
||||
{
|
||||
if (audio_mode == APP_AUDIO_MODE_SCO) {
|
||||
audio_scene_destroy(audio_scene);
|
||||
audio_mode = APP_AUDIO_MODE_IDLE;
|
||||
audio_pa_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void app_audio_sco_recv(bool valid, uint8_t audio_type, uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (audio_mode == APP_AUDIO_MODE_SCO) {
|
||||
if (audio_scene_dac_is_ready(audio_scene)) {
|
||||
audio_pa_enable();
|
||||
}
|
||||
if (audio_type == AUDIO_TYPE_MSBC) {
|
||||
audio_scene_recv_raw_data(audio_scene, valid, buffer+2, length-3);
|
||||
}
|
||||
else {
|
||||
audio_scene_recv_raw_data(audio_scene, valid, buffer, length);
|
||||
}
|
||||
}
|
||||
}
|
21
MCU/examples/application/btdm_audio/Src/app_audio.h
Normal file
21
MCU/examples/application/btdm_audio/Src/app_audio.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _APP_AUDIO_H
|
||||
#define _APP_AUDIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "audio_common.h"
|
||||
#include "audio_scene.h"
|
||||
|
||||
void app_audio_a2dp_sink_start(audio_type_t audio_type, uint32_t sample_rate);
|
||||
void app_audio_a2dp_sink_stop(void);
|
||||
void app_audio_a2dp_sink_play(uint8_t *buffer, uint32_t length);
|
||||
|
||||
void app_audio_sco_start(audio_type_t audio_type, audio_sence_report_encoded_frame report_enc_cb, void *report_enc_arg);
|
||||
void app_audio_sco_stop(void);
|
||||
void app_audio_sco_recv(bool valid, uint8_t audio_type, uint8_t *buffer, uint32_t length);
|
||||
|
||||
void app_audio_voice_recognize_start(void);
|
||||
void app_audio_voice_recognize_stop(void);
|
||||
|
||||
#endif // _APP_AUDIO_H
|
390
MCU/examples/application/btdm_audio/Src/app_ble.c
Normal file
390
MCU/examples/application/btdm_audio/Src/app_ble.c
Normal file
@ -0,0 +1,390 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "co_log.h"
|
||||
|
||||
#include "gap_api.h"
|
||||
#include "gatt_api.h"
|
||||
#include "gaf_api.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "timers.h"
|
||||
//#include "user_bt.h"
|
||||
#include "hid_service.h"
|
||||
#include "simple_gatt_service.h"
|
||||
#include "ANCS_AMS_client.h"
|
||||
#include "AMS_client.h"
|
||||
|
||||
#define APP_BLE_ADV_CHN_MAX 2
|
||||
|
||||
|
||||
static TimerHandle_t ble_sec_req_timer = NULL;
|
||||
static void app_ble_start_advertising(uint8_t adv_chn);
|
||||
|
||||
char local_device_name[] = "30xx_ble";
|
||||
static adv_handle adv[APP_BLE_ADV_CHN_MAX];
|
||||
static uint16_t mtu_connected[8];
|
||||
|
||||
extern const uint8_t ble_static_addr[];
|
||||
|
||||
uint8_t slave_link_conidx;
|
||||
static uint8_t adv_data[] = {
|
||||
|
||||
#if 0
|
||||
/* gatt service information */
|
||||
0x03, //length of this AD
|
||||
GAP_ADVTYPE_16BIT_MORE, //16bit service uuid AD type
|
||||
//0xff, 0xf0, //value.service uuid:0xFFF0
|
||||
LO_UINT16(0XFF72),
|
||||
HI_UINT16(0XFF72),
|
||||
#endif
|
||||
|
||||
/* local device name information */
|
||||
0x0A, //length of this AD
|
||||
GAP_ADVTYPE_LOCAL_NAME_COMPLETE, //complete name AD type
|
||||
'3','0','x','x','_',' ','b','l','e', //value.local device name
|
||||
|
||||
// 0x09, // addr mac
|
||||
// GAP_ADVTYPE_MANUFACTURER_SPECIFIC,
|
||||
// LO_UINT16(0x1671),
|
||||
// HI_UINT16(0x1671),
|
||||
// 0xc2,0x12,0x12,0x12,0x00,0x13,
|
||||
|
||||
// 0x03, // length of this data
|
||||
// GAP_ADVTYPE_APPEARANCE,
|
||||
// LO_UINT16(0x03c0),
|
||||
// HI_UINT16(0x03c0),
|
||||
|
||||
|
||||
#if 0
|
||||
// appearance
|
||||
0x03, // length of this data
|
||||
GAP_ADVTYPE_APPEARANCE,
|
||||
LO_UINT16(GAP_APPEARE_HID_KEYBOARD),
|
||||
HI_UINT16(GAP_APPEARE_HID_KEYBOARD),
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Advertising scan response data, max size is 31 bytes
|
||||
*/
|
||||
static uint8_t adv_scan_rsp_data[] = {
|
||||
|
||||
#if 1
|
||||
0x03, // length of this data
|
||||
GAP_ADVTYPE_16BIT_COMPLETE,
|
||||
LO_UINT16(HID_SERV_UUID),
|
||||
HI_UINT16(HID_SERV_UUID),
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Tx power level <20><><EFBFBD>书<EFBFBD><E4B9A6>
|
||||
0x02, // length of this data
|
||||
GAP_ADVTYPE_POWER_LEVEL,
|
||||
0, // 0dBm
|
||||
#endif
|
||||
};
|
||||
|
||||
static uint8_t client_id;
|
||||
|
||||
uint16_t app_ble_get_mtu(uint8_t conidx)
|
||||
{
|
||||
return mtu_connected[conidx];
|
||||
}
|
||||
|
||||
void app_ble_set_mtu(uint8_t conidx, uint16_t mtu)
|
||||
{
|
||||
mtu_connected[conidx] = mtu;
|
||||
}
|
||||
|
||||
static void ble_sec_req_timer_cb(TimerHandle_t pxTimer)
|
||||
{
|
||||
gap_security_req(0);
|
||||
}
|
||||
|
||||
static uint16_t gap_callback(struct gap_event *event)
|
||||
{
|
||||
printf("gap_callback: type = %d\r\n", event->type);
|
||||
|
||||
switch(event->type) {
|
||||
case GATT_EVT_PROFILE_ADDED:
|
||||
{
|
||||
printf("gap_callback: GATT_EVT_PROFILE_ADDED: 0x%02X\r\n", event->param.profile_added_status);
|
||||
|
||||
/* service profile has been added successfully, then the advertising can be started */
|
||||
app_ble_start_advertising(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_PARAM:
|
||||
printf("adv param set: 0x%02X\r\n", event->param.adv_set_param.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_ADV_DATA:
|
||||
printf("adv data set: 0x%02X\r\n", event->param.adv_set_adv_data.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_SCAN_RSP:
|
||||
printf("adv scan rsp data set: 0x%02X\r\n", event->param.adv_set_scan_rsp.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_START:
|
||||
printf("adv start :0x%02X\r\n", event->param.adv_start.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_END:
|
||||
printf("adv end: 0x%02X\r\n", event->param.adv_end.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_SLAVE_CONNECT:
|
||||
{
|
||||
//gap_get_link_version(event->param.connect.conidx);
|
||||
//gap_get_link_rssi(event->param.connect.conidx);
|
||||
//gap_get_link_features(event->param.connect.conidx);
|
||||
printf("slave connect[%d], connect num: %d\r\n", event->param.connect.conidx, gap_get_connect_num());
|
||||
// gatt_mtu_exchange_req(service_id, event->param.connect.conidx, 247);
|
||||
if(ble_sec_req_timer == NULL){
|
||||
ble_sec_req_timer = xTimerCreate("ble_sec_req_timer", 1000, pdFALSE, 0, ble_sec_req_timer_cb );
|
||||
}
|
||||
xTimerStart(ble_sec_req_timer,portMAX_DELAY);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_DISCONNECT:
|
||||
{
|
||||
printf("gap_callback: GAP_EVT_DISCONNECT, conidx:%d, reason:0x%02X\r\n", event->param.disconnect.conidx,
|
||||
event->param.disconnect.reason);
|
||||
app_ble_start_advertising(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GATT_EVT_MTU:
|
||||
printf("gap_callback: conidx: %d, GATT_EVT_MTU: %d\r\n", event->param.mtu_ind.conidx, event->param.mtu_ind.mtu);
|
||||
app_ble_set_mtu(event->param.mtu_ind.conidx, event->param.mtu_ind.mtu);
|
||||
//gap_security_req(event->param.connect.conidx);
|
||||
break;
|
||||
case GAP_EVT_SMP_ENCRYPT_SUCCESS:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_SMP_ENCRYPT_SUCCESS\r\n", event->param.mtu_ind.conidx);
|
||||
break;
|
||||
|
||||
case GAP_EVT_SMP_BOND_SUCCESS:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_SMP_BOND_SUCCESS\r\n", event->param.mtu_ind.conidx);
|
||||
#if BLE_PROFILE_ENABLE_ANCS
|
||||
gatt_discovery_all_peer_svc(ANCS_AMS_client_id,event->param.connect.conidx);
|
||||
#endif
|
||||
|
||||
#if (BLE_PROFILE_ENABLE_HID)
|
||||
hid_service_enable(event->param.connect.conidx);
|
||||
#endif
|
||||
|
||||
// user_bt_env.connect_times = 3;
|
||||
// bt_connect(&event->param.bond.peer_id_addr.addr.addr);
|
||||
break;
|
||||
|
||||
case GAP_EVT_NAME_REQ:
|
||||
{
|
||||
|
||||
gap_name_req_rsp(event->param.name_req.conidx,
|
||||
event->param.name_req.token,
|
||||
sizeof(local_device_name),
|
||||
(uint8_t *)local_device_name);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_APPEARANCE_REQ:
|
||||
{
|
||||
gap_appearance_req_rsp(event->param.appearance_req.conidx,
|
||||
event->param.appearance_req.token,
|
||||
GAP_APPEARE_HID_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_PARAM_REQ:
|
||||
{
|
||||
struct gap_link_param_update_rsp rsp;
|
||||
rsp.accept = true;
|
||||
rsp.conidx = event->param.link_param_update_req.conidx;
|
||||
rsp.ce_len_max = 2;
|
||||
rsp.ce_len_min = 2;
|
||||
gap_param_update_rsp(&rsp);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_PARAM_UPDATE:
|
||||
{
|
||||
printf("conn param update,conidx:%d, con_int:%d, latency:%d, timeout%d\r\n", event->param.link_param_update.conidx,
|
||||
event->param.link_param_update.con_interval,
|
||||
event->param.link_param_update.con_latency,
|
||||
event->param.link_param_update.sup_to);
|
||||
//gap_security_req(event->param.connect.conidx);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_RSSI:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_RSSI: %d\r\n", event->param.gap_link_rssi.conidx, event->param.gap_link_rssi.link_rssi);
|
||||
break;
|
||||
|
||||
case GAP_EVT_PHY_IND:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_PHY_IND: %d\r\n", event->param.gap_phy_ind.conidx, event->param.gap_phy_ind.tx_phy);
|
||||
break;
|
||||
|
||||
case GAP_EVT_PHY_REJECT:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_PHY_REJECT, status: %d\r\n", event->param.gap_phy_update_reject.conidx, event->param.gap_phy_update_reject.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_VER:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_VER\r\n", event->param.gap_link_ver.conidx);
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_FEATURE:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_FEATURE:%d\r\n", event->param.gap_link_feature.conidx, event->param.gap_link_feature.features[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t gatt_callback(struct gatt_msg *p_msg)
|
||||
{
|
||||
switch(p_msg->msg_evt) {
|
||||
case GATT_OP_PEER_SVC_DISC_END:
|
||||
switch(p_msg->param.gatt_op_cmp.operation) {
|
||||
case GATT_OP_PEER_SVC_DISC_END:
|
||||
// LOG_INFO(NULL, "GATT_OP_PEER_SVC_DISC_END: ");
|
||||
// uint16_t length = p_msg->param.gatt_op_cmp.arg_len;
|
||||
// uint8_t *buffer = p_msg->param.gatt_op_cmp.arg;
|
||||
// for(uint8_t i=0; i<length; i++) {
|
||||
// LOG_INFO(NULL, "%02x ", buffer[i]);
|
||||
// }
|
||||
// LOG_INFO(NULL, "\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void app_ble_init(void)
|
||||
{
|
||||
struct gap_security_param smp_param;
|
||||
|
||||
gap_set_cb_func(gap_callback);
|
||||
|
||||
smp_param.mitm = false;
|
||||
smp_param.secure_connection = true;
|
||||
smp_param.bond = true;
|
||||
smp_param.rsp_mode = ENABLE_AUTO_RSP;
|
||||
smp_param.oob_used = GAP_OOB_AUTH_DATA_NOT_PRESENT;
|
||||
smp_param.io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
|
||||
smp_param.rsp_mode = ENABLE_AUTO_RSP;
|
||||
gap_security_param_init(&smp_param);
|
||||
|
||||
sp_gatt_add_service();
|
||||
|
||||
#if BLE_PROFILE_ENABLE_ANCS
|
||||
ANCS_AMS_gatt_add_client();
|
||||
#endif
|
||||
|
||||
#if BLE_PROFILE_ENABLE_HID
|
||||
hid_gatt_add_service();
|
||||
#endif
|
||||
|
||||
// gaf_cfg();
|
||||
}
|
||||
|
||||
void app_ble_start_advertising(uint8_t adv_chn)
|
||||
{
|
||||
if (adv_chn < APP_BLE_ADV_CHN_MAX) {
|
||||
if (adv[adv_chn] == NULL) {
|
||||
struct gap_adv_param adv_param;
|
||||
|
||||
adv_param.adv_mode = GAP_ADV_MODE_UNDIRECT;
|
||||
adv_param.disc_mode = GAP_ADV_DISC_MODE_GEN_DISC;
|
||||
adv_param.filt_policy = GAP_ADV_FILTER_SCAN_ANY_CON_ANY;
|
||||
adv_param.adv_chnl_map = GAP_ADV_CHAN_ALL;
|
||||
adv_param.phy_mode = GAP_PHY_TYPE_LE_1M;
|
||||
adv_param.own_addr_type = GAP_ADDR_TYPE_STATIC; // GAPM_GEN_RSLV_ADDR GAPM_STATIC_ADDR
|
||||
|
||||
adv_param.adv_intv_min = 1600;
|
||||
adv_param.adv_intv_max = 1600;
|
||||
adv[adv_chn] = gap_adv_create();
|
||||
gap_adv_set_param(adv[adv_chn], &adv_param);
|
||||
|
||||
adv_data[17] = ble_static_addr[5];
|
||||
adv_data[18] = ble_static_addr[4];
|
||||
adv_data[19] = ble_static_addr[3];
|
||||
adv_data[20] = ble_static_addr[2];
|
||||
adv_data[21] = ble_static_addr[1];
|
||||
adv_data[22] = ble_static_addr[0];
|
||||
|
||||
gap_adv_set_adv_data(adv[adv_chn], adv_data, sizeof(adv_data));
|
||||
gap_adv_set_scan_rsp(adv[adv_chn], adv_scan_rsp_data, sizeof(adv_scan_rsp_data));
|
||||
}
|
||||
gap_adv_start(adv[adv_chn], 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void app_ble_stop_advertising(uint8_t adv_chn)
|
||||
{
|
||||
if ((adv_chn < APP_BLE_ADV_CHN_MAX)
|
||||
&& (adv[adv_chn] != NULL)) {
|
||||
gap_adv_stop(adv[adv_chn]);
|
||||
}
|
||||
}
|
||||
|
||||
void app_ble_scan_start(void)
|
||||
{
|
||||
struct gap_scan_param param;
|
||||
|
||||
param.scan_type = GAP_SCAN_TYPE_GEN_DISC;
|
||||
param.own_addr_type = GAP_ADDR_TYPE_STATIC;
|
||||
param.phy_mode = GAP_PHY_TYPE_LE_1M;
|
||||
|
||||
param.dup_filt_pol = true;
|
||||
param.scan_intv = 32;
|
||||
param.scan_window = 20;
|
||||
param.duration = 0;
|
||||
|
||||
gap_scan_start(¶m);
|
||||
}
|
||||
|
||||
void app_ble_scan_stop(void)
|
||||
{
|
||||
gap_scan_stop();
|
||||
}
|
||||
|
||||
void app_ble_conn_start(struct gap_ble_addr *addr)
|
||||
{
|
||||
struct gap_conn_param conn_param;
|
||||
conn_param.peer_addr.addr_type = addr->addr_type;
|
||||
conn_param.peer_addr.addr.addr[0] = addr->addr.addr[0];
|
||||
conn_param.peer_addr.addr.addr[1] = addr->addr.addr[1];
|
||||
conn_param.peer_addr.addr.addr[2] = addr->addr.addr[2];
|
||||
conn_param.peer_addr.addr.addr[3] = addr->addr.addr[3];
|
||||
conn_param.peer_addr.addr.addr[4] = addr->addr.addr[4];
|
||||
conn_param.peer_addr.addr.addr[5] = addr->addr.addr[5];
|
||||
conn_param.own_addr_type = GAP_ADDR_TYPE_STATIC;
|
||||
conn_param.phy_mode = GAP_PHY_TYPE_LE_1M;
|
||||
conn_param.scan_intv = 32;
|
||||
conn_param.scan_window = 32;
|
||||
conn_param.conn_intv_min = 24;
|
||||
conn_param.conn_intv_max = 24;
|
||||
conn_param.supervision_to = 500;
|
||||
conn_param.slave_latency = 0;
|
||||
conn_param.ce_len_max = 2;
|
||||
conn_param.ce_len_min = 2;
|
||||
gap_conn_start(&conn_param);
|
||||
}
|
||||
|
||||
void app_ble_conn_stop(void)
|
||||
{
|
||||
gap_conn_stop();
|
||||
}
|
19
MCU/examples/application/btdm_audio/Src/app_ble.h
Normal file
19
MCU/examples/application/btdm_audio/Src/app_ble.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _APP_BLE_H
|
||||
#define _APP_BLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gap_api.h"
|
||||
|
||||
void app_ble_init(void);
|
||||
|
||||
void app_ble_advertising_start(uint8_t adv_chn);
|
||||
void app_ble_advertising_stop(uint8_t adv_chn);
|
||||
|
||||
void app_ble_scan_start(void);
|
||||
void app_ble_scan_stop(void);
|
||||
|
||||
void app_ble_conn_start(struct gap_ble_addr *addr);
|
||||
void app_ble_conn_stop(void);
|
||||
|
||||
#endif // _APP_BLE_H
|
1284
MCU/examples/application/btdm_audio/Src/app_bt.c
Normal file
1284
MCU/examples/application/btdm_audio/Src/app_bt.c
Normal file
File diff suppressed because it is too large
Load Diff
32
MCU/examples/application/btdm_audio/Src/app_bt.h
Normal file
32
MCU/examples/application/btdm_audio/Src/app_bt.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef _APP_BT_H
|
||||
#define _APP_BT_H
|
||||
|
||||
#include "app_btdm.h"
|
||||
|
||||
#include "hf_api.h"
|
||||
#include "me_api.h"
|
||||
#include "a2dp_api.h"
|
||||
#include "hfg_api.h"
|
||||
#include "avrcp_api.h"
|
||||
#include "hid_api.h"
|
||||
#include "spp_api.h"
|
||||
#include "pbap_api.h"
|
||||
|
||||
extern HfChannel *hf_channel;
|
||||
extern HfgChannel *hfg_channel;
|
||||
extern A2dpStream *Stream;
|
||||
extern AvrcpChannel *rcpCtChannel;
|
||||
extern AvrcpChannel *rcpTgChannel;
|
||||
extern PbapClientSession *pbap_client;
|
||||
extern SppDev *spp_dev;
|
||||
|
||||
uint8_t bt_get_free_hf_channel(void);
|
||||
uint8_t bt_get_free_hfg_channel(void);
|
||||
uint8_t bt_get_free_a2dp_stream(void);
|
||||
uint8_t bt_get_free_avrcp_channel(void);
|
||||
|
||||
void app_bt_send_sco_data(void *channel, uint8_t seq, uint8_t *data, uint16_t length);
|
||||
|
||||
void app_bt_init(app_btdm_callback_t cb);
|
||||
|
||||
#endif // _APP_BT_H
|
233
MCU/examples/application/btdm_audio/Src/app_btdm.c
Normal file
233
MCU/examples/application/btdm_audio/Src/app_btdm.c
Normal file
@ -0,0 +1,233 @@
|
||||
#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;
|
||||
}
|
67
MCU/examples/application/btdm_audio/Src/app_btdm.h
Normal file
67
MCU/examples/application/btdm_audio/Src/app_btdm.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef _APP_BTDM_H
|
||||
#define _APP_BTDM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum {
|
||||
APP_BTDM_EVT_BLE_CONNECTED,
|
||||
APP_BTDM_EVT_BLE_DISCONNECTED,
|
||||
|
||||
APP_BTDM_EVT_BT_CONNECTED,
|
||||
APP_BTDM_EVT_BT_DISCONNECTED,
|
||||
APP_BTDM_EVT_HF_INCOMING,
|
||||
APP_BTDM_EVT_HF_CALL_ACTIVE,
|
||||
APP_BTDM_EVT_HF_CALL_REMOVE,
|
||||
APP_BTDM_EVT_A2DP_STREAM_STARTED,
|
||||
APP_BTDM_EVT_A2DP_STREAM_STOPPED,
|
||||
APP_BTDM_EVT_A2DP_STREAM_DATA,
|
||||
APP_BTDM_EVT_AVRCP_VOL_CHANGE,
|
||||
APP_BTDM_EVT_AVRCP_NEXT,
|
||||
APP_BTDM_EVT_AVRCP_PREV,
|
||||
APP_BTDM_EVT_AVRCP_PAUSE,
|
||||
APP_BTDM_EVT_AVRCP_FAST_FORWARD,
|
||||
APP_BTDM_EVT_AVRCP_FAST_BACKWARD,
|
||||
APP_BTDM_EVT_SCO_CREATED,
|
||||
APP_BTDM_EVT_SCO_REMOVED,
|
||||
APP_BTDM_EVT_SCO_DATA,
|
||||
};
|
||||
|
||||
enum {
|
||||
APP_BTDM_CODEC_SBC,
|
||||
APP_BTDM_CODEC_AAC,
|
||||
APP_BTDM_CODEC_mSBC,
|
||||
APP_BTDM_CODEC_PCM,
|
||||
APP_BTDM_CODEC_UNKNOWN,
|
||||
};
|
||||
|
||||
struct app_btdm_event_t {
|
||||
uint8_t event;
|
||||
union {
|
||||
struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
} a2dp_data;
|
||||
struct {
|
||||
uint8_t codec_type;
|
||||
uint32_t sample_rate;
|
||||
} a2dp_codec;
|
||||
struct {
|
||||
bool valid;
|
||||
uint8_t codec_type;
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
} sco_data;
|
||||
struct {
|
||||
void *hf_channel;
|
||||
uint8_t codec_type;
|
||||
} sco_codec;
|
||||
} param;
|
||||
};
|
||||
|
||||
typedef void (*app_btdm_callback_t)(struct app_btdm_event_t *e);
|
||||
|
||||
void app_btdm_start(void);
|
||||
void app_btdm_init(void);
|
||||
const uint8_t *app_get_bt_addr(void);
|
||||
#endif // _APP_BTDM_H
|
133
MCU/examples/application/btdm_audio/Src/app_rpmsg.c
Normal file
133
MCU/examples/application/btdm_audio/Src/app_rpmsg.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "fr30xx.h"
|
||||
|
||||
/* FreeRTOS kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "rpmsg.h"
|
||||
#include "rpmsg_lite.h"
|
||||
#include "rpmsg_queue.h"
|
||||
#include "rpmsg_ns.h"
|
||||
|
||||
#include "dsp.h"
|
||||
|
||||
#include "app_config.h"
|
||||
#include "app_task.h"
|
||||
#include "app_rpmsg.h"
|
||||
|
||||
#define DSP_BOOT_FROM_EXT_FLASH 1 // 1: flash, 0: sd card
|
||||
|
||||
/* Remote rpmsg instance */
|
||||
static struct rpmsg_lite_instance *remote_rpmsg;
|
||||
static TaskHandle_t rpmsg_task_handle;
|
||||
|
||||
static void rpmsg_recv(struct rpmsg_lite_instance *rpmsg, struct rpmsg_msg_t *msg)
|
||||
{
|
||||
// printf("rpmsg_recv: msg_type = %d.\r\n", msg->msg_type);
|
||||
|
||||
switch (msg->msg_type) {
|
||||
case RPMSG_MSG_TYPE_SYNC_INVOKE:
|
||||
if (msg->p.sync_func.func_id == RPMSG_SYNC_FUNC_SUM) {
|
||||
uint32_t address = (uint32_t)msg->p.sync_func.param;
|
||||
struct rpmsg_sync_msg_sum_t *param = msg->p.sync_func.param;
|
||||
if (address >= DSP_DRAM_BASE_ADDR) {
|
||||
address = DSP_DRAM_2_MCU_SRAM(address);
|
||||
}
|
||||
param = (void *)address;
|
||||
rpmsg_send_sync_ret(rpmsg, 0, param->x + param->y);
|
||||
}
|
||||
else {
|
||||
rpmsg_send_sync_ret(rpmsg, 0xffffffff, 0);
|
||||
}
|
||||
break;
|
||||
case RPMSG_MSG_TYPE_ASYNC_MSG:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsg_task(void *arg)
|
||||
{
|
||||
struct app_task_event *event;
|
||||
struct rpmsg_msg_t *msg;
|
||||
uint32_t msg_len;
|
||||
uint32_t src_addr;
|
||||
uint32_t length;
|
||||
|
||||
dsp_prepare();
|
||||
|
||||
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
extern uint8_t DSP_CODE_ROM_BASE, DSP_CODE_ROM_END;
|
||||
src_addr = (uint32_t)&DSP_CODE_ROM_BASE;
|
||||
length = (uint32_t)&DSP_CODE_ROM_END - (uint32_t)&DSP_CODE_ROM_BASE;
|
||||
#elif defined(__GNUC__) || defined(__ICCARM__)
|
||||
extern const uint8_t dsp_code_rom_buffer[];
|
||||
src_addr = (uint32_t)&dsp_code_rom_buffer[0];
|
||||
length = 0;
|
||||
#endif
|
||||
if (dsp_load_code_from_internal_flash(src_addr, length) == false) {
|
||||
|
||||
printf("DSP image load failed.\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
printf("DSP is released.\r\n");
|
||||
__SYSTEM_LIBRARY_ROM_CLK_ENABLE();
|
||||
remote_rpmsg = rpmsg_remote_init(rpmsg_recv);
|
||||
dsp_run(0x78400660);
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_DSP);
|
||||
rpmsg_wait_master_ready(remote_rpmsg);
|
||||
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_DSP);
|
||||
|
||||
printf("DSP is ready.\r\n");
|
||||
|
||||
/* notice APP that rpmsg is ready. */
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_RPMSG_INITED, 0, true);
|
||||
app_task_event_post(event, false);
|
||||
|
||||
while (1) {
|
||||
src_addr = rpmsg_recv_msg(remote_rpmsg, &msg, &msg_len);
|
||||
rpmsg_recv(remote_rpmsg, msg);
|
||||
rpmsg_lite_release_rx_buffer(remote_rpmsg, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void app_rpmsg_init(void)
|
||||
{
|
||||
/* create rpmsg task. */
|
||||
xTaskCreate(rpmsg_task, "RPMSG_TASK", RPMSG_TASK_STACK_SIZE, NULL, RPMSG_TASK_PRIORITY, &rpmsg_task_handle);
|
||||
}
|
||||
|
||||
void app_rpmsg_recover(void)
|
||||
{
|
||||
dsp_prepare();
|
||||
|
||||
uint32_t src_addr;
|
||||
uint32_t length;
|
||||
#if DSP_CODE_LOAD_MODE == DSP_CODE_LOAD_MODE_XIP_RO
|
||||
#if DSP_ROM_CODE_XIP == 1
|
||||
extern uint8_t DSP_CODE_FLASH_BASE, DSP_CODE_FLASH_END;
|
||||
src_addr = (uint32_t)&DSP_CODE_FLASH_BASE;
|
||||
length = (uint32_t)&DSP_CODE_FLASH_END - (uint32_t)&DSP_CODE_FLASH_BASE;
|
||||
#else
|
||||
extern uint8_t DSP_CODE_ROM_BASE, DSP_CODE_ROM_END;
|
||||
src_addr = (uint32_t)&DSP_CODE_ROM_BASE;
|
||||
length = (uint32_t)&DSP_CODE_ROM_END - (uint32_t)&DSP_CODE_ROM_BASE;
|
||||
#endif
|
||||
dsp_load_rw_from_internal_flash(src_addr, length);
|
||||
#elif DSP_CODE_LOAD_MODE == DSP_CODE_LOAD_MODE_FIX_ADDRESS
|
||||
src_addr = (uint32_t)((DSP_CODE_FIX_ADDRESS + 0x10) | FLASH_DAC_BASE);
|
||||
length = *(volatile uint32_t *)((DSP_CODE_FIX_ADDRESS + 0x08) | FLASH_DAC_BASE);
|
||||
dsp_load_rw_from_internal_flash(src_addr, length);
|
||||
#else
|
||||
#error "choose correct DSP code load mode"
|
||||
#endif
|
||||
|
||||
#if DSP_ROM_CODE_XIP == 0
|
||||
__SYSTEM_LIBRARY_ROM_CLK_ENABLE();
|
||||
#endif
|
||||
dsp_run(0x78400660);
|
||||
|
||||
rpmsg_remote_recover();
|
||||
}
|
7
MCU/examples/application/btdm_audio/Src/app_rpmsg.h
Normal file
7
MCU/examples/application/btdm_audio/Src/app_rpmsg.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _APP_RPMSG_H
|
||||
#define _APP_RPMSG_H
|
||||
|
||||
void app_rpmsg_init(void);
|
||||
void app_rpmsg_recover(void);
|
||||
|
||||
#endif // _APP_RPMSG_H
|
110
MCU/examples/application/btdm_audio/Src/app_task.c
Normal file
110
MCU/examples/application/btdm_audio/Src/app_task.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "app_at.h"
|
||||
#include "app_task.h"
|
||||
#include "app_bt.h"
|
||||
#include "app_ble.h"
|
||||
#include "app_rpmsg.h"
|
||||
#include "app_config.h"
|
||||
|
||||
static struct co_list event_list;
|
||||
|
||||
extern TaskHandle_t app_task_handle;
|
||||
|
||||
void hci_controller_read(void);
|
||||
void hci_host_read(void);
|
||||
|
||||
static void app_task_event_handler(void)
|
||||
{
|
||||
struct app_task_event *event = NULL;
|
||||
|
||||
vTaskSuspendAll();
|
||||
event = (struct app_task_event *)co_list_pop_front(&event_list);
|
||||
xTaskResumeAll();
|
||||
|
||||
if(event) {
|
||||
switch(event->event_type) {
|
||||
case APP_TASK_EVENT_AT_CMD:
|
||||
app_at_cmd_recv_handler(event->param, event->param_len);
|
||||
break;
|
||||
case APP_TASK_EVENT_RPMSG_INITED:
|
||||
app_btdm_init();
|
||||
break;
|
||||
case APP_TASK_EVENT_HOST_INITED:
|
||||
app_btdm_start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vPortFree((void *)event);
|
||||
}
|
||||
}
|
||||
|
||||
void app_task_event_post(struct app_task_event *event, bool high)
|
||||
{
|
||||
uint32_t old_basepri;
|
||||
|
||||
if(xPortIsInsideInterrupt()) {
|
||||
old_basepri = taskENTER_CRITICAL_FROM_ISR();
|
||||
if(high) {
|
||||
co_list_push_front(&event_list, &event->hdr);
|
||||
}
|
||||
else {
|
||||
co_list_push_back(&event_list, &event->hdr);
|
||||
}
|
||||
taskEXIT_CRITICAL_FROM_ISR(old_basepri);
|
||||
vTaskNotifyGiveFromISR(app_task_handle, NULL);
|
||||
}
|
||||
else {
|
||||
taskENTER_CRITICAL();
|
||||
if(high) {
|
||||
co_list_push_front(&event_list, &event->hdr);
|
||||
}
|
||||
else {
|
||||
co_list_push_back(&event_list, &event->hdr);
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
xTaskNotifyGive(app_task_handle);
|
||||
}
|
||||
}
|
||||
|
||||
struct app_task_event *app_task_event_alloc(uint8_t event_type, uint32_t param_len, bool block)
|
||||
{
|
||||
struct app_task_event *event = NULL;
|
||||
|
||||
while(event == NULL) {
|
||||
event = pvPortMalloc(sizeof(struct app_task_event) + param_len);
|
||||
if (event == NULL) {
|
||||
if (block) {
|
||||
vTaskDelay(10);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event->event_type = event_type;
|
||||
event->param_len = param_len;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void app_task(void *arg)
|
||||
{
|
||||
co_list_init(&event_list);
|
||||
|
||||
app_rpmsg_init();
|
||||
|
||||
while(1) {
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
app_task_event_handler();
|
||||
}
|
||||
}
|
||||
|
||||
void app_task_init(void)
|
||||
{
|
||||
xTaskCreate(app_task, "app", APP_TASK_STACK_SIZE, NULL, APP_TASK_PRIORITY, &app_task_handle);
|
||||
}
|
30
MCU/examples/application/btdm_audio/Src/app_task.h
Normal file
30
MCU/examples/application/btdm_audio/Src/app_task.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef _APP_TASK_H
|
||||
#define _APP_TASK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "co_list.h"
|
||||
|
||||
#define APP_TASK_EVENT_AT_CMD 0x00
|
||||
#define APP_TASK_EVENT_RPMSG_INITED 0x01
|
||||
#define APP_TASK_EVENT_HOST_INITED 0x02
|
||||
#define APP_TASK_EVENT_LVGL_INITED 0x03
|
||||
#define APP_TASK_EVENT_DELAY_CONNECT 0x04
|
||||
|
||||
struct app_task_event {
|
||||
struct co_list_hdr hdr;
|
||||
|
||||
uint8_t event_type;
|
||||
|
||||
uint16_t param_len;
|
||||
uint8_t param[];
|
||||
};
|
||||
|
||||
void app_task_event_post(struct app_task_event *event, bool high);
|
||||
|
||||
struct app_task_event *app_task_event_alloc(uint8_t event_type, uint32_t param_len, bool block);
|
||||
|
||||
void app_task_init(void);
|
||||
|
||||
#endif // _APP_TASK_H
|
451
MCU/examples/application/btdm_audio/Src/diskio.c
Normal file
451
MCU/examples/application/btdm_audio/Src/diskio.c
Normal file
@ -0,0 +1,451 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* If a working storage control module is available, it should be */
|
||||
/* attached to the FatFs via a glue function rather than modifying it. */
|
||||
/* This is an example of glue functions to attach various exsisting */
|
||||
/* storage control modules to the FatFs module with a defined API. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "fr30xx.h"
|
||||
|
||||
#include "ff.h" /* Obtains integer types */
|
||||
#include "diskio.h" /* Declarations of disk functions */
|
||||
|
||||
/* Definitions of physical drive number for each drive */
|
||||
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
|
||||
#define DEV_MMC 1 /* Example: Map MMC to physical drive 1 */
|
||||
#define DEV_SPI_FLASH 2 /* Example: Map SPI Flash to physical drive 2 */
|
||||
#define DEV_NAND_FLASH 3 /* Example: Map Nand Flash to physical drive 3 */
|
||||
#define DEV_SD_CARD 4 /* Example: Map SD Card to physical drive 4 */
|
||||
|
||||
#define RAM_SECTOR_SIZE 512
|
||||
#define RAM_SECTOR_COUNT (16*48)
|
||||
#define RAM_BLOCK_SIZE 4096
|
||||
#define RAM_DISK_SIZE (RAM_SECTOR_SIZE * RAM_SECTOR_COUNT)
|
||||
|
||||
#define SD_CARD_SECTOR_SIZE 512
|
||||
#define SD_CARD_BLOCK_SIZE 4096
|
||||
|
||||
#define SPI_FLASH_SECTOR_SIZE 512
|
||||
#define SPI_FLASH_BLOCK_SIZE 4096
|
||||
#define SPI_FLASH_SECTOR_COUNT (2*1024*4)
|
||||
|
||||
__ALIGNED(4) static uint8_t ram_disk_space[RAM_DISK_SIZE];
|
||||
static uint8_t spi_flash_poll[4096];
|
||||
extern SD_HandleTypeDef sdio_handle;
|
||||
|
||||
static DSTATUS RAM_disk_status(void)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS MMC_disk_status(void)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS SPI_flash_status(void)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS SD_Card_status(void)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS RAM_disk_initialize(void)
|
||||
{
|
||||
// memset(ram_disk_space, 0, RAM_DISK_SIZE);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS MMC_disk_initialize(void)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS SPI_flash_initialize(void)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS SD_Card_initialize(void)
|
||||
{
|
||||
// uint32_t EER;
|
||||
//
|
||||
// EER = SDCard_Init(&SDIO);
|
||||
// if (EER != INT_NO_ERR) {
|
||||
// return RES_ERROR;
|
||||
// }
|
||||
// EER = SDCard_BusWidth_Select(&SDIO, SDIO_BUS_WIDTH_4BIT);
|
||||
// if (EER != INT_NO_ERR) {
|
||||
// return RES_ERROR;
|
||||
// }
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS RAM_disk_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS SPI_flash_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS MMC_disk_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS SD_Card_read(BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
SDCard_ReadBolcks(&sdio_handle, (uint32_t *)buff, sector, count);
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static DSTATUS RAM_disk_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS MMC_disk_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS SPI_flash_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
static DSTATUS SD_Card_write(const BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
SDCard_WriteBolcks(&sdio_handle, (uint32_t *)buff, sector, count);
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
DSTATUS stat;
|
||||
|
||||
switch (pdrv) {
|
||||
case DEV_RAM :
|
||||
stat = RAM_disk_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_MMC :
|
||||
stat = MMC_disk_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_SPI_FLASH :
|
||||
stat = SPI_flash_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_SD_CARD :
|
||||
stat = SD_Card_status();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
}
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
DSTATUS stat;
|
||||
|
||||
switch (pdrv) {
|
||||
case DEV_RAM :
|
||||
stat = RAM_disk_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_MMC :
|
||||
stat = MMC_disk_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_SPI_FLASH :
|
||||
stat = SPI_flash_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
|
||||
case DEV_SD_CARD :
|
||||
stat = SD_Card_initialize();
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return stat;
|
||||
}
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
LBA_t sector, /* Start sector in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
|
||||
switch (pdrv) {
|
||||
case DEV_RAM :
|
||||
// translate the arguments here
|
||||
|
||||
res = RAM_disk_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_MMC :
|
||||
// translate the arguments here
|
||||
|
||||
res = MMC_disk_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SPI_FLASH :
|
||||
// translate the arguments here
|
||||
|
||||
res = SPI_flash_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SD_CARD :
|
||||
// translate the arguments here
|
||||
|
||||
res = SD_Card_read(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#if FF_FS_READONLY == 0
|
||||
|
||||
DRESULT disk_write (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
LBA_t sector, /* Start sector in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
|
||||
switch (pdrv) {
|
||||
case DEV_RAM :
|
||||
// translate the arguments here
|
||||
|
||||
res = RAM_disk_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_MMC :
|
||||
// translate the arguments here
|
||||
|
||||
res = MMC_disk_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SPI_FLASH :
|
||||
// translate the arguments here
|
||||
|
||||
res = SPI_flash_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SD_CARD :
|
||||
// translate the arguments here
|
||||
|
||||
res = SD_Card_write(buff, sector, count);
|
||||
|
||||
// translate the reslut code here
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_ioctl (
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
DRESULT res = RES_PARERR;
|
||||
|
||||
switch (pdrv) {
|
||||
case DEV_RAM :
|
||||
|
||||
// Process of the command for the RAM drive
|
||||
switch(cmd)
|
||||
{
|
||||
case CTRL_SYNC:
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_SIZE:
|
||||
*(WORD*)buff = RAM_SECTOR_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*(WORD*)buff = RAM_BLOCK_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_COUNT:
|
||||
*(DWORD*)buff = RAM_SECTOR_COUNT;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case CTRL_TRIM:
|
||||
res = RES_OK;
|
||||
break;
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_MMC :
|
||||
|
||||
// Process of the command for the MMC/SD card
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SPI_FLASH :
|
||||
|
||||
// Process of the command for the MMC/SD card
|
||||
switch(cmd)
|
||||
{
|
||||
case CTRL_SYNC:
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_SIZE:
|
||||
*(WORD*)buff = SPI_FLASH_SECTOR_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*(WORD*)buff = SPI_FLASH_BLOCK_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_COUNT:
|
||||
*(DWORD*)buff = SPI_FLASH_SECTOR_COUNT;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case CTRL_TRIM:
|
||||
res = RES_OK;
|
||||
break;
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
case DEV_SD_CARD :
|
||||
|
||||
// Process of the command for the RAM drive
|
||||
switch(cmd)
|
||||
{
|
||||
case CTRL_SYNC:
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_SIZE:
|
||||
*(WORD*)buff = SD_CARD_SECTOR_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*(WORD*)buff = SD_CARD_BLOCK_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_COUNT:
|
||||
*(DWORD*)buff = SDCard_Get_Block_count(&sdio_handle);
|
||||
res = RES_OK;
|
||||
break;
|
||||
case CTRL_TRIM:
|
||||
res = RES_OK;
|
||||
break;
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
374
MCU/examples/application/btdm_audio/Src/main.c
Normal file
374
MCU/examples/application/btdm_audio/Src/main.c
Normal file
@ -0,0 +1,374 @@
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "fr30xx.h"
|
||||
|
||||
/* FreeRTOS kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "fdb_app.h"
|
||||
#include "host.h"
|
||||
#include "ff.h"
|
||||
|
||||
#include "app_task.h"
|
||||
#include "app_at.h"
|
||||
#include "audio_scene.h"
|
||||
|
||||
/* hardware handlers */
|
||||
static UART_HandleTypeDef Uart3_handle;
|
||||
SD_HandleTypeDef sdio_handle;
|
||||
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
/* FreeRTOS running status monitor task */
|
||||
static TaskHandle_t monitor_task_handle;
|
||||
volatile unsigned int CPU_RunTime;
|
||||
static uint8_t CPU_RunInfo[2048];
|
||||
#endif
|
||||
|
||||
/* file system */
|
||||
static FATFS fs;
|
||||
|
||||
/* APP task */
|
||||
TaskHandle_t app_task_handle;
|
||||
|
||||
void controller_start(void);
|
||||
void host_start(void);
|
||||
|
||||
#if defined(__ARMCC_VERSION) || defined(__CC_ARM)
|
||||
int fputc(int c, FILE *fp)
|
||||
{
|
||||
uart_transmit(&Uart3_handle, (void *)&c, 1);
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ICCARM__
|
||||
int putchar(int c)
|
||||
{
|
||||
uart_transmit(&Uart3_handle, (void *)&c, 1);
|
||||
while(!(Uart3_handle.UARTx->USR.TFE));
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
static void monitor_task(void *arg)
|
||||
{
|
||||
while(1) {
|
||||
vTaskDelay(10000);
|
||||
|
||||
memset(CPU_RunInfo,0,2048);
|
||||
vTaskList((char *)&CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
printf("name state priority stack seq\r\n");
|
||||
printf("%s", CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
|
||||
memset(CPU_RunInfo,0,400);
|
||||
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
|
||||
printf("name counter usage\r\n");
|
||||
printf("%s", CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
||||
{
|
||||
( void ) pcTaskName;
|
||||
( void ) pxTask;
|
||||
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
void vApplicationTickHook(void)
|
||||
{
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
CPU_RunTime++;
|
||||
#endif
|
||||
}
|
||||
|
||||
__RAM_CODE bool user_deep_sleep_check(void)
|
||||
{
|
||||
return host_before_sleep_check();
|
||||
}
|
||||
|
||||
__RAM_CODE void user_entry_before_sleep(void)
|
||||
{
|
||||
ool_write(PMU_REG_PMU_GATE_M, ool_read(PMU_REG_PMU_GATE_M) | 0x40);
|
||||
}
|
||||
|
||||
__RAM_CODE void user_entry_after_sleep(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio_config;
|
||||
|
||||
/* configure all interrupt priority to 2 */
|
||||
*(volatile uint32_t *)0xE000E400 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E404 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E408 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E40C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E410 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E414 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E418 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E41C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E420 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E424 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E428 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E42C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E430 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E434 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E438 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E43C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E440 = 0x40404040;
|
||||
|
||||
host_hci_reinit();
|
||||
ool_write(PMU_REG_PMU_GATE_M, ool_read(PMU_REG_PMU_GATE_M) & (~0x40));
|
||||
NVIC_SetPriority(UART0_IRQn, 2);
|
||||
NVIC_EnableIRQ(UART0_IRQn);
|
||||
NVIC_SetPriority(PMU_IRQn, 4);
|
||||
NVIC_EnableIRQ(PMU_IRQn);
|
||||
|
||||
/* configure PA0 and PA1 to UART0 function */
|
||||
__SYSTEM_GPIOA_CLK_ENABLE();
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_5;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||||
gpio_init(GPIOB, &gpio_config);
|
||||
|
||||
/* UART0: used for Log and AT command */
|
||||
__SYSTEM_UART2_CLK_ENABLE();
|
||||
Uart3_handle.UARTx = UART3;
|
||||
Uart3_handle.Init.BaudRate = 921600;
|
||||
Uart3_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||||
Uart3_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
Uart3_handle.Init.Parity = UART_PARITY_NONE;
|
||||
Uart3_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||||
Uart3_handle.TxCpltCallback = NULL;
|
||||
Uart3_handle.RxCpltCallback = app_at_rx_done;
|
||||
uart_init(&Uart3_handle);
|
||||
|
||||
app_rpmsg_recover();
|
||||
|
||||
}
|
||||
|
||||
__RAM_CODE void hw_clock_init(void)
|
||||
{
|
||||
System_ClkConfig_t sys_clk_cfg;
|
||||
|
||||
sys_clk_cfg.AUPLL_CFG.PLL_N = 8;
|
||||
sys_clk_cfg.AUPLL_CFG.PLL_M = 15204;
|
||||
sys_clk_cfg.AUPLL_CFG.PowerEn = 1;
|
||||
sys_clk_cfg.SPLL_CFG.PLL_N = 8;
|
||||
sys_clk_cfg.SPLL_CFG.PLL_M = 0;
|
||||
sys_clk_cfg.SPLL_CFG.PowerEn = 1;
|
||||
sys_clk_cfg.MCU_Clock_Source = MCU_CLK_SEL_SPLL_CLK;
|
||||
sys_clk_cfg.SOC_DIV = 1;
|
||||
sys_clk_cfg.MCU_DIV = 1;
|
||||
sys_clk_cfg.APB0_DIV = 1;
|
||||
sys_clk_cfg.APB1_DIV = 1;
|
||||
sys_clk_cfg.APB2_DIV = 1;
|
||||
sys_clk_cfg.APB3_DIV = 1;
|
||||
System_AUPLL_config(&sys_clk_cfg.AUPLL_CFG, 1000);
|
||||
System_SPLL_config(&sys_clk_cfg.SPLL_CFG, 1000);
|
||||
System_MCU_clock_Config(&sys_clk_cfg);
|
||||
|
||||
__SYSTEM_SPI_MASTER0_X8_CLK_SELECT_AUPLL();
|
||||
__SYSTEM_SPI_MASTER1_X8_CLK_SELECT_AUPLL();
|
||||
__SYSTEM_I2C_CLK_SELECT_SPLL();
|
||||
__SYSTEM_BLEND_CLK_SELECT_SPLL();
|
||||
__SYSTEM_UART_CLK_SELECT_SPLL();
|
||||
}
|
||||
|
||||
__RAM_CODE __attribute__((noinline)) static void rise_qspi_clock(void)
|
||||
{
|
||||
__SYSTEM_QSPI0_CLK_SELECT_AUPLL();
|
||||
__QSPI_DELAY_CS_START_SET(QSPI0, 4);
|
||||
__QSPI_DELAY_CS_END_SET(QSPI0, 4);
|
||||
__QSPI_DELAY_CS_DESSERT_SET(QSPI0, 8);
|
||||
__QSPI_READ_CAPTURE_DELAY_SET(QSPI0, 0); // FLASH_ID_PUYA_P25Q32: 4 when div is 2
|
||||
// FLASH_ID_XMC_XM25LU32: 3 when div is 2
|
||||
// FLASH_ID_GIANTEC_GT25Q16A: 1 when div is 4
|
||||
// FLASH_ID_GIANTEC_GT25Q16A: 4 when div is 2
|
||||
system_delay_us(1000);
|
||||
}
|
||||
|
||||
__RAM_CODE void hw_xip_flash_init(bool wake_up)
|
||||
{
|
||||
// init internal flash
|
||||
__SYSTEM_PFC_CLK_ENABLE();
|
||||
__SYSTEM_QSPI0_CLK_ENABLE();
|
||||
__SYSTEM_APB_CLK_ENABLE();
|
||||
__SYSTEM_APB1_CLK_ENABLE();
|
||||
system_cache_enable(true);
|
||||
flash_enable_quad(QSPI0);
|
||||
SYSTEM->QspiPadConfig.QSPI_FuncMux = 0x00000500;
|
||||
flash_init_controller(QSPI0, FLASH_RD_TYPE_QUAD, FLASH_WR_TYPE_SINGLE);
|
||||
if (wake_up == false) {
|
||||
flash_set_IO_DRV(QSPI0, 3);
|
||||
}
|
||||
flash_set_baudrate(QSPI0, QSPI_BAUDRATE_DIV_4);
|
||||
rise_qspi_clock();
|
||||
}
|
||||
|
||||
int main( void )
|
||||
{
|
||||
GPIO_InitTypeDef gpio_config;
|
||||
UART_HandleTypeDef dsp_uart_handle;
|
||||
uint32_t error;
|
||||
uint32_t rand_num;
|
||||
size_t size;
|
||||
|
||||
system_delay_us(1000000);
|
||||
|
||||
/* configure all interrupt priority to 2 */
|
||||
*(volatile uint32_t *)0xE000E400 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E404 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E408 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E40C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E410 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E414 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E418 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E41C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E420 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E424 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E428 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E42C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E430 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E434 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E438 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E43C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E440 = 0x40404040;
|
||||
|
||||
pmu_init();
|
||||
ool_write(0xc3, 0x27);
|
||||
|
||||
// system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_DISABLE);
|
||||
|
||||
/* initial system clock and XIP flash */
|
||||
hw_clock_init();
|
||||
hw_xip_flash_init(false);
|
||||
|
||||
__SYSTEM_GPIOA_CLK_ENABLE();
|
||||
/* configure PA6 to PA_EN function */
|
||||
gpio_config.Pin = GPIO_PIN_6;
|
||||
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_0;
|
||||
gpio_init(GPIOA, &gpio_config);
|
||||
gpio_write_pin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
|
||||
|
||||
/* initialize uart for DSP UART */
|
||||
/* ========================================================== */
|
||||
/* ========= Uart LOG configuration ========= */
|
||||
/* ========================================================== */
|
||||
/* configure PA4 and PA5 to UART1 function */
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_5;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||||
gpio_init(GPIOA, &gpio_config);
|
||||
|
||||
/* UART1: used for Log and AT command */
|
||||
__SYSTEM_UART1_CLK_ENABLE();
|
||||
dsp_uart_handle.UARTx = UART1;
|
||||
dsp_uart_handle.Init.BaudRate = 3000000;
|
||||
dsp_uart_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||||
dsp_uart_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
dsp_uart_handle.Init.Parity = UART_PARITY_NONE;
|
||||
dsp_uart_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||||
dsp_uart_handle.Init.AUTO_FLOW = false;
|
||||
dsp_uart_handle.TxCpltCallback = NULL;
|
||||
dsp_uart_handle.RxCpltCallback = NULL;
|
||||
uart_init(&dsp_uart_handle);
|
||||
|
||||
/* configure PB4 and PB5 to UART3 function */
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_5;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||||
gpio_init(GPIOB, &gpio_config);
|
||||
|
||||
/* UART3: used for Log and AT command */
|
||||
__SYSTEM_UART3_CLK_ENABLE();
|
||||
Uart3_handle.UARTx = UART3;
|
||||
Uart3_handle.Init.BaudRate = 921600;
|
||||
Uart3_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||||
Uart3_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
Uart3_handle.Init.Parity = UART_PARITY_NONE;
|
||||
Uart3_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||||
Uart3_handle.TxCpltCallback = NULL;
|
||||
Uart3_handle.RxCpltCallback = app_at_rx_done;
|
||||
uart_init(&Uart3_handle);
|
||||
NVIC_EnableIRQ(UART3_IRQn);
|
||||
NVIC_SetPriority(UART3_IRQn, 4);
|
||||
|
||||
/* ========================================================== */
|
||||
/* ========= I2S interface configuration ======== */
|
||||
/* ========================================================== */
|
||||
/* configure PB0~PB3 to I2S0 function */
|
||||
gpio_config.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_B;
|
||||
gpio_init(GPIOB, &gpio_config);
|
||||
|
||||
/* init flashdb to store user data */
|
||||
flashdb_init();
|
||||
|
||||
/* get random seed*/
|
||||
size = flashdb_get(FDB_KEY_USER_RANDOM_SEED, (void *)&rand_num, 4);
|
||||
printf("flashdb get random seed :%d\r\n",size);
|
||||
if(size == 0){
|
||||
__SYSTEM_TRNG_CLK_ENABLE();
|
||||
trng_init();
|
||||
trng_read_rand_num((uint8_t *)&rand_num,4);
|
||||
flashdb_set(FDB_KEY_USER_RANDOM_SEED,(uint8_t *)&rand_num,4);
|
||||
__SYSTEM_TRNG_CLK_DISABLE();
|
||||
}
|
||||
printf("flash db get rand num: %x\r\n",rand_num);
|
||||
/* Create tasks */
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
xTaskCreate(monitor_task, "monitor", MONITOR_TASK_STACK_SIZE, NULL, MONITOR_TASK_PRIORITY, &monitor_task_handle);
|
||||
#endif
|
||||
|
||||
app_task_init();
|
||||
audio_scene_init(AUDIO_SCENE_TASK_STACK_SIZE, AUDIO_SCENE_TASK_PRIORITY);
|
||||
|
||||
/* initialize AT command */
|
||||
app_at_init(&Uart3_handle);
|
||||
|
||||
printf("FR5090: BTDM test.\r\n");
|
||||
|
||||
/* Start the scheduler itself. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart3_irq(void)
|
||||
{
|
||||
uart_IRQHandler(&Uart3_handle);
|
||||
}
|
||||
|
||||
void PMU_GPIO_PMU_IRQHandler(void)
|
||||
{
|
||||
uint16_t data = ool_read16(PMU_REG_PIN_DATA);
|
||||
uint16_t result = ool_read16(PMU_REG_PIN_XOR_RESULT);
|
||||
|
||||
/* update last value with latest data */
|
||||
ool_write16(PMU_REG_PIN_LAST_V, data);
|
||||
/* clear last XOR result */
|
||||
ool_write16(PMU_REG_PIN_XOR_CLR, result);
|
||||
|
||||
if (data & PMU_PIN_9) {
|
||||
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX);
|
||||
}
|
||||
else {
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX);
|
||||
}
|
||||
}
|
1167
MCU/examples/application/btdm_audio/Src/user_bt.c
Normal file
1167
MCU/examples/application/btdm_audio/Src/user_bt.c
Normal file
File diff suppressed because it is too large
Load Diff
223
MCU/examples/application/btdm_audio/Src/user_bt.h
Normal file
223
MCU/examples/application/btdm_audio/Src/user_bt.h
Normal file
@ -0,0 +1,223 @@
|
||||
#ifndef __USER_BT_H
|
||||
#define __USER_BT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "app_bt.h"
|
||||
#include "bt_types.h"
|
||||
#include "btconfig.h"
|
||||
#include "co_list.h"
|
||||
|
||||
///enable_profiles
|
||||
#define ENABLE_PROFILE_HF BIT0
|
||||
#define ENABLE_PROFILE_A2DP BIT1 //if a2dp is enabled, avrcp is enabled automatically
|
||||
#define ENABLE_PROFILE_HID BIT2
|
||||
#define ENABLE_PROFILE_PBAP BIT3
|
||||
#define ENABLE_PROFILE_SPP BIT4
|
||||
#define ENABLE_PROFILE_HFG BIT5
|
||||
#define ENABLE_PROFILE_MAP BIT6
|
||||
#define ENABLE_PROFILE_ALL 0xff
|
||||
|
||||
//conn flags
|
||||
#define LINK_STATUS_HF_CONNECTED (1<<0)
|
||||
#define LINK_STATUS_AV_CONNECTED (1<<1)
|
||||
#define LINK_STATUS_AVC_CONNECTED (1<<2)
|
||||
#define LINK_STATUS_MEDIA_PLAYING (1<<3)
|
||||
#define LINK_STATUS_SCO_CONNECTED (1<<4)
|
||||
#define LINK_STATUS_HID_CONNECTED (1<<5)
|
||||
#define LINK_STATUS_PBAP_CONNECTED (1<<6)
|
||||
#define LINK_STATUS_SPP_CONNECTED (1<<7)
|
||||
#define LINK_STATUS_HFG_CONNECTED (1<<8)
|
||||
|
||||
|
||||
enum bt_state_t{
|
||||
BT_STATE_IDLE, //IDLE
|
||||
BT_STATE_CONNECTING, //CONNECTING, connect is ongoing
|
||||
BT_STATE_DISCONNECTING, //disconnecting
|
||||
BT_STATE_CONNECTED, //CONNECTED, connected,no call and music
|
||||
BT_STATE_HFP_INCOMMING, //INCOMMING CALL
|
||||
BT_STATE_HFP_OUTGOING, //OUTGOING CALL
|
||||
BT_STATE_HFP_CALLACTIVE, //CALL IS ACTIVE
|
||||
BT_STATE_MEDIA_PLAYING, //MUSIC PLAYING
|
||||
BT_STATE_MAX,
|
||||
};
|
||||
|
||||
//enum bt_state_t{
|
||||
// BT_STATE_IDLE, //IDLE
|
||||
// BT_STATE_PAIRING, //PAIRING
|
||||
// BT_STATE_CONNECTED, //CONNECTED, connected,no call and music
|
||||
// BT_STATE_BOTH_CONNECTED, //used in connecting with two device
|
||||
// BT_STATE_MAX,
|
||||
//};
|
||||
|
||||
enum bt_link_state_t{
|
||||
BT_LINK_STATE_IDLE,
|
||||
BT_LINK_STATE_CONNECTING,
|
||||
BT_LINK_STATE_DISCONNECTING,
|
||||
BT_LINK_STATE_ACL_CONNECTED,
|
||||
BT_LINK_STATE_PROFILE_CONNECTED,
|
||||
};
|
||||
|
||||
enum app_bt_access_state_t{
|
||||
ACCESS_IDLE = 0x00,
|
||||
ACCESS_PAIRING,
|
||||
};
|
||||
|
||||
enum bt_connect_action_t{
|
||||
BT_ACTION_NULL,
|
||||
BT_ACTION_CONNECT,
|
||||
BT_ACTION_DISCONNECT,
|
||||
BT_ACTION_ACCESS,
|
||||
};
|
||||
|
||||
enum bt_connect_event_t{
|
||||
BT_EVENT_CON_IND,
|
||||
BT_EVENT_CON_CNF,
|
||||
BT_EVENT_PROFILE_CONNECT,
|
||||
BT_EVENT_DISCONNECT,
|
||||
BT_EVENT_ACC_CHG,
|
||||
};
|
||||
|
||||
enum bt_profile_event_t{
|
||||
BT_PROFILE_HF_CONN_REQ,
|
||||
BT_PROFILE_HF_CONN,
|
||||
BT_PROFILE_HF_DISCONN,
|
||||
BT_PROFILE_HF_AUDIO_CONN,
|
||||
BT_PROFILE_HF_AUDIO_DISCONN,
|
||||
|
||||
BT_PROFILE_HF_CALL, //5
|
||||
BT_PROFILE_HF_CALLSETUP,
|
||||
BT_PROFILE_HF_SPK_VOL,
|
||||
BT_PROFILE_HF_CURRENT_CALL,
|
||||
BT_PROFILE_HF_AT_RESULT,
|
||||
BT_PROFILE_HF_MAX, //10
|
||||
|
||||
BT_PROFILE_A2DP_CONN,
|
||||
BT_PROFILE_A2DP_DISCONN,
|
||||
BT_PROFILE_A2DP_PLAYING,
|
||||
BT_PROFILE_A2DP_SUSPEND,
|
||||
BT_PROFILE_A2DP_OPEN_IND,
|
||||
BT_PROFILE_A2DP_MAX,
|
||||
|
||||
BT_PROFILE_AVRCP_CONN,
|
||||
BT_PROFILE_AVRCP_DISCONN,
|
||||
BT_PROFILE_AVRCP_MEDIA_STATUS,
|
||||
BT_PROFILE_AVRCP_MEDIA_INFO,
|
||||
BT_PROFILE_AVRCP_MEDIA_POS,
|
||||
BT_PROFILE_AVRCP_MAX,
|
||||
|
||||
BT_PROFILE_PBAP_CONN,
|
||||
BT_PROFILE_PBAP_DISCONN,
|
||||
BT_PROFILE_PBAP_DATA_IND,
|
||||
BT_PROFILE_PBAP_COMP,
|
||||
BT_PROFILE_PBAP_MAX,
|
||||
};
|
||||
|
||||
struct bt_connect_param_t{
|
||||
uint16_t page_timeout; //unit: 625us
|
||||
uint8_t connect_times;
|
||||
// uint8_t connect_interval; //unit: 1s , interval shall larger than page_timeout
|
||||
};
|
||||
|
||||
struct bt_connect_elt_t{
|
||||
struct co_list_hdr hdr;
|
||||
BD_ADDR addr;
|
||||
uint8_t action;
|
||||
// struct bt_connect_param_t param;
|
||||
};
|
||||
|
||||
/* Device context */
|
||||
typedef struct app_device_t {
|
||||
BD_ADDR remote_bd;
|
||||
uint16_t conFlags;//avrcp,a2dp,hfp conn status
|
||||
uint8_t prf_all_connected;
|
||||
uint8_t responder;
|
||||
uint8_t state;
|
||||
|
||||
uint8_t mode;//active or sniff
|
||||
|
||||
HfCallSetupState setup_state;
|
||||
HfCallActiveState active;
|
||||
HfCallHeldState call_held;
|
||||
|
||||
BtRemoteDevice *remDev;
|
||||
HfChannel *hf_chan;
|
||||
HfgChannel *hfg_chan;
|
||||
AvrcpChannel *rcp_chan;
|
||||
A2dpStream *pstream;
|
||||
HidChannel *hid_chan;
|
||||
PbapClientSession *pbap_client;
|
||||
} APP_DEVICE;
|
||||
|
||||
struct user_bt_env_t {
|
||||
uint8_t enable_profiles;
|
||||
uint8_t last_active_index;
|
||||
uint8_t access_state;
|
||||
uint16_t page_timeout; //unit: 625us
|
||||
uint8_t connect_times;
|
||||
BD_ADDR last_dev_addr;
|
||||
uint8_t cur_action;
|
||||
uint8_t action_cnt;
|
||||
struct co_list op_list;
|
||||
// struct bt_connect_param_t connect_param;
|
||||
void (*bt_disconnect_cb)(BD_ADDR *addr, uint8_t errcode);
|
||||
void (*bt_connect_cb)(uint8_t type, BD_ADDR *addr, uint8_t errcode);
|
||||
void (*bt_access_change_cb)(uint8_t mode);
|
||||
APP_DEVICE dev[NUM_BT_DEVICES];
|
||||
};
|
||||
|
||||
extern struct user_bt_env_t user_bt_env;
|
||||
|
||||
|
||||
BtStatus bt_connect(BD_ADDR *addr);
|
||||
|
||||
BtStatus bt_disconnect(BD_ADDR *addr, uint8_t force_disconnect);
|
||||
|
||||
BtStatus bt_poweroff(void);
|
||||
|
||||
void bt_connect_act_cmp(uint8_t evt,uint8_t error,BtRemoteDevice *rem_dev);
|
||||
|
||||
void bt_update_conn_status(uint8_t event, void *chan, const void *param);
|
||||
|
||||
uint8_t user_bt_get_state(uint8_t dev_index);
|
||||
|
||||
void user_bt_init(void);
|
||||
|
||||
|
||||
BtStatus bt_answer_call(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_dial_number(uint8_t dev_index, uint8_t *number, uint16_t len);
|
||||
|
||||
BtStatus bt_redial(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_call_hold(uint8_t dev_index, HfHoldAction action, uint8_t index);
|
||||
|
||||
BtStatus bt_hang_up(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_list_current_calls(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_transfer_sco(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_send_dtmf(uint8_t dev_index, uint8_t dtmf);
|
||||
|
||||
BtStatus bt_report_mic_volume(uint8_t dev_index, uint8_t vol);
|
||||
|
||||
BtStatus bt_report_spk_volume(uint8_t dev_index, uint8_t vol);
|
||||
|
||||
BtStatus bt_send_hf_cmd(uint8_t dev_index, const uint8_t *at_str);
|
||||
|
||||
BtStatus bt_enable_voice_recognition(uint8_t dev_index, uint8_t enabled);
|
||||
|
||||
uint8_t bt_is_voice_rec_active(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_get_media_info(uint8_t dev_index,AvrcpMediaAttrIdMask mediaMask);
|
||||
|
||||
BtStatus bt_get_playstatus(uint8_t dev_index);
|
||||
|
||||
BtStatus bt_set_media_volume(uint8_t dev_index, uint8_t volume);
|
||||
|
||||
BtStatus bt_enter_pairing(uint8_t access, BtAccessModeInfo *info);
|
||||
|
||||
BtStatus bt_exit_pairing(void);
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user