初版
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".reference_time.data.bss")
|
||||
#pragma data_seg(".reference_time.data")
|
||||
#pragma const_seg(".reference_time.text.const")
|
||||
#pragma code_seg(".reference_time.text")
|
||||
#endif
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file reference_time.c
|
||||
*
|
||||
* \brief 提供音频参考时钟选择的接口函数实体与管理
|
||||
*
|
||||
* Copyright (c) 2011-2022 ZhuHai Jieli Technology Co.,Ltd.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include "reference_time.h"
|
||||
#include "system/includes.h"
|
||||
/* #include "le_audio_stream.h" */
|
||||
|
||||
/*
|
||||
* 关于优先级选择:
|
||||
* 手机的网络时钟优先级最高,无手机网络的情况下选择TWS网络
|
||||
*/
|
||||
static LIST_HEAD(reference_head);
|
||||
static u8 local_network = 0xff;
|
||||
static u8 local_net_addr[6];
|
||||
static u8 local_network_id = 1;
|
||||
extern const int LE_AUDIO_TIME_ENABLE;
|
||||
|
||||
struct reference_clock {
|
||||
u8 id;
|
||||
u8 network;
|
||||
union {
|
||||
u8 net_addr[6];
|
||||
void *le_addr;
|
||||
};
|
||||
struct list_head entry;
|
||||
};
|
||||
|
||||
extern void bt_audio_reference_clock_select(void *addr, u8 network);
|
||||
extern u32 bt_audio_reference_clock_time(u8 network);
|
||||
extern u32 bt_audio_reference_clock_remapping(void *src_addr, u8 src_network, void *dst_addr, u8 dst_network, u32 clock);
|
||||
extern u8 bt_audio_reference_link_exist(void *addr, u8 network);
|
||||
|
||||
//le audio相关函数弱定义
|
||||
__attribute__((weak))
|
||||
int le_audio_stream_clock_select(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
u32 le_audio_stream_current_time(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
int le_audio_stream_get_latch_time(void *le_audio, u32 *time, u16 *us_1_12th, u32 *event)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
void le_audio_stream_latch_time_enable(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
int audio_reference_clock_select(void *addr, u8 network)
|
||||
{
|
||||
struct reference_clock *reference_clock = (struct reference_clock *)zalloc(sizeof(struct reference_clock));
|
||||
struct reference_clock *clk;
|
||||
u8 reset_clock = 1;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
if (network > 2) {
|
||||
local_irq_enable();
|
||||
free(reference_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (list_empty(&reference_head) || network == 0) {
|
||||
reference_clock->network = network;
|
||||
if (LE_AUDIO_TIME_ENABLE && network == 2) {
|
||||
reference_clock->le_addr = addr;
|
||||
} else {
|
||||
if (addr == NULL) {
|
||||
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
|
||||
} else {
|
||||
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 0 && bt_audio_reference_link_exist(clk->net_addr, clk->network)) {
|
||||
reference_clock->network = clk->network;
|
||||
memcpy(reference_clock->net_addr, clk->net_addr, sizeof(reference_clock->net_addr));
|
||||
reset_clock = 0;
|
||||
} else {
|
||||
reference_clock->network = network;
|
||||
if (LE_AUDIO_TIME_ENABLE && network == 2) {
|
||||
reference_clock->le_addr = addr;
|
||||
} else {
|
||||
if (addr == NULL) {
|
||||
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
|
||||
} else {
|
||||
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_add(&reference_clock->entry, &reference_head);
|
||||
reference_clock->id = local_network_id;
|
||||
if (++local_network_id == 0) {
|
||||
local_network_id++;
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
if (reset_clock) {
|
||||
if (LE_AUDIO_TIME_ENABLE && reference_clock->network == 2) {
|
||||
le_audio_stream_clock_select(reference_clock->le_addr);
|
||||
} else {
|
||||
bt_audio_reference_clock_select(reference_clock->net_addr, reference_clock->network);
|
||||
}
|
||||
}
|
||||
|
||||
return reference_clock->id;
|
||||
}
|
||||
|
||||
u32 audio_reference_clock_time(void)
|
||||
{
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (LE_AUDIO_TIME_ENABLE && clk->network == 2) {
|
||||
return le_audio_stream_current_time(clk->le_addr);
|
||||
}
|
||||
return bt_audio_reference_clock_time(clk->network);
|
||||
}
|
||||
|
||||
return bt_audio_reference_clock_time(local_network);
|
||||
}
|
||||
|
||||
u32 audio_reference_network_clock_time(u8 network)
|
||||
{
|
||||
return bt_audio_reference_clock_time(network);
|
||||
}
|
||||
|
||||
u8 audio_reference_network_exist(u8 id)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (clk->id == id) {
|
||||
goto exist_detect;
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
|
||||
exist_detect:
|
||||
local_irq_enable();
|
||||
return bt_audio_reference_link_exist(clk->net_addr, clk->network);
|
||||
}
|
||||
|
||||
int le_audio_get_reference_latch_time(u32 *time, u16 *us_1_12th, u32 *event)
|
||||
{
|
||||
if (!LE_AUDIO_TIME_ENABLE) {
|
||||
return 0;
|
||||
}
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 2) {
|
||||
le_audio_stream_get_latch_time(clk->le_addr, time, us_1_12th, event);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void le_audio_reference_time_latch_enable(void)
|
||||
{
|
||||
if (!LE_AUDIO_TIME_ENABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 2) {
|
||||
le_audio_stream_latch_time_enable(clk->le_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 is_audio_reference_clock_enable(void)
|
||||
{
|
||||
return 0;
|
||||
/*return local_network == 0xff ? 0 : 1;*/
|
||||
}
|
||||
|
||||
u8 audio_reference_clock_network(void *addr)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
|
||||
if (list_empty(&reference_head)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network != 2 && addr) {
|
||||
memcpy(addr, clk->net_addr, 6);
|
||||
}
|
||||
|
||||
return clk->network;
|
||||
}
|
||||
|
||||
u8 audio_reference_clock_match(void *addr, u8 network)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
|
||||
if (list_empty(&reference_head)) {
|
||||
return 0;
|
||||
}
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == network) {
|
||||
if (network == 0) {
|
||||
if (addr && memcmp(clk->net_addr, addr, 6) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 audio_reference_clock_remapping(u8 now_network, u8 dst_network, u32 clock)
|
||||
{
|
||||
void *now_addr = NULL;
|
||||
void *dst_addr = NULL;
|
||||
struct reference_clock *clk;
|
||||
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (!now_addr && clk->network == now_network) {
|
||||
now_addr = clk->net_addr;
|
||||
}
|
||||
if (!dst_addr && clk->network == dst_network) {
|
||||
dst_addr = clk->net_addr;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
return bt_audio_reference_clock_remapping(now_addr, now_network, dst_addr, dst_network, clock);
|
||||
}
|
||||
|
||||
void audio_reference_clock_exit(u8 id)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (clk->id == id) {
|
||||
goto delete;
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
return;
|
||||
delete:
|
||||
list_del(&clk->entry);
|
||||
free(clk);
|
||||
if (!list_empty(&reference_head)) {
|
||||
/*clk = list_first_entry(&reference_head, struct reference_clock, entry);*/
|
||||
/*bt_audio_reference_clock_select(clk->net_addr, clk->network);*/
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
Reference in New Issue
Block a user