KT24-1110_65E-HA-651B/apps/common/charge_box/chgbox_box.c

564 lines
18 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#include "app_config.h"
#include "system/includes.h"
#include "chgbox_box.h"
#include "user_cfg.h"
#include "device/vm.h"
#include "app_task.h"
#include "app_main.h"
#include "chargeIc_manage.h"
#include "chgbox_ctrl.h"
#include "device/chargebox.h"
#include "asm/power/p33.h"
#include "chgbox_det.h"
#if(TCFG_CHARGE_BOX_ENABLE)
#define LOG_TAG_CONST APP_CHGBOX
#define LOG_TAG "[APP_CBOX]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define CHGBOX_THR_NAME "chgbox_n"
OS_MUTEX power_mutex;
//电池参数,电池不同,参数不同
//使用不同的电池要更新此表,不然数据可能会不准确
#define POWER_TOP_LVL 4200
#define POWER_BOOT_LVL 3100
#define POWER_LVL_MAX 11
const u16 voltage_table[2][POWER_LVL_MAX] = {
{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
{POWER_BOOT_LVL, 3600, 3660, 3720, 3780, 3840, 3900, 3950, 4000, 4050, POWER_TOP_LVL},
};
/*------------------------------------------------------------------------------------*/
/**@brief 获取充电仓电量值
@param
@return 0~100
@note 0~100
*/
/*------------------------------------------------------------------------------------*/
u8 get_box_power_lvl()
{
u16 max, min, power;
u8 i;
power = get_vbat_voltage();
if (power <= POWER_BOOT_LVL) {
return 0;
}
if (power >= POWER_TOP_LVL) {
return 100;
}
for (i = 0; i < POWER_LVL_MAX; i++) {
if (power < voltage_table[1][i]) {
break;
}
}
min = voltage_table[1][i - 1];
max = voltage_table[1][i];
return ((u8)(((power - min) * 10 / (max - min)) + voltage_table[0][i - 1]));
}
//通信的时候不能进入低功耗
static volatile u8 is_comm_active = 0;
static u8 comm_idle_query(void)
{
return (!is_comm_active);
}
REGISTER_LP_TARGET(comm_lp_target) = {
.name = "chgbox_comm",
.is_idle = comm_idle_query,
};
/*------------------------------------------------------------------------------------*/
/**@brief 进入发送数据关处理
@param
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void enter_hook(void)
{
//进入发送数据前,先关闭升压输出
os_mutex_pend(&power_mutex, 0);
if (sys_info.charge) {
chargeIc_pwr_ctrl(0);
}
chargebox_api_open_port(EAR_L);
chargebox_api_open_port(EAR_R);
is_comm_active = 1;
}
/*------------------------------------------------------------------------------------*/
/**@brief 发送数据后恢复处理
@param
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void exit_hook(void)
{
//退出发送数据后,是否需要打开升压输出
if (sys_info.charge && (sys_info.temperature_limit == 0)) {
chargebox_check_output_short();
chargebox_api_shutdown_port(EAR_L);
chargebox_api_shutdown_port(EAR_R);
if (sys_info.current_limit == 0) {
chargeIc_pwr_ctrl(1);
}
} else {
chargebox_api_close_port(EAR_L);
chargebox_api_close_port(EAR_R);
}
is_comm_active = 0;
os_mutex_post(&power_mutex);
}
/*------------------------------------------------------------------------------------*/
/**@brief 发消息到通信处理线程
@param msg:
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_send_mag(int msg)
{
//有数据需要发送,自动关机计时器复位
sys_info.life_cnt = 0;
os_taskq_post_msg(CHGBOX_THR_NAME, 1, msg);
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓事件发送函数
@param event:
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_event_to_user(u8 event)
{
struct sys_event e;
e.type = SYS_DEVICE_EVENT;
e.arg = (void *)DEVICE_EVENT_FROM_CHARGEBOX;
e.u.dev.event = event;
sys_event_notify(&e);
}
/*------------------------------------------------------------------------------------*/
/**@brief 耳机在线检测
@param ret_l:
ret_r:
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_api_check_online(bool ret_l, bool ret_r)
{
if (ret_l == TRUE) {
if (ear_info.online[EAR_L] == 0) {
//发事件,耳机入舱
app_chargebox_event_to_user(CHGBOX_EVENT_EAR_L_ONLINE);
}
ear_info.online[EAR_L] = TCFG_EAR_OFFLINE_MAX;
} else {
if (ear_info.online[EAR_L]) {
ear_info.online[EAR_L]--;
if (ear_info.online[EAR_L] == 0) {
ear_info.power[EAR_L] = 0xff;
//发事件,耳机离舱
app_chargebox_event_to_user(CHGBOX_EVENT_EAR_L_OFFLINE);
}
}
}
if (ret_r == TRUE) {
if (ear_info.online[EAR_R] == 0) {
//发事件,耳机入舱
app_chargebox_event_to_user(CHGBOX_EVENT_EAR_R_ONLINE);
}
ear_info.online[EAR_R] = TCFG_EAR_OFFLINE_MAX;
} else {
if (ear_info.online[EAR_R]) {
ear_info.online[EAR_R]--;
if (ear_info.online[EAR_R] == 0) {
ear_info.power[EAR_R] = 0xff;
//发事件,耳机离舱
app_chargebox_event_to_user(CHGBOX_EVENT_EAR_R_OFFLINE);
}
}
}
if ((ear_info.online[EAR_L] == 0) && (ear_info.online[EAR_R] == 0)) {
chargebox_api_reset();
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 发送 耳机关机 指令
@param
@return TRUE: FALSE:
@note
*/
/*------------------------------------------------------------------------------------*/
u8 app_chargebox_api_send_shutdown(void)
{
u8 ret0, ret1;
enter_hook();
ret0 = chargebox_send_shut_down(EAR_L);
ret1 = chargebox_send_shut_down(EAR_R);
exit_hook();
if ((ret0 == TRUE) && (ret1 == TRUE)) {
log_debug("send shutdown ok!\n");
return TRUE;
} else {
log_error("shut down, L:%d,R:%d\n", ret0, ret1);
}
return FALSE;
}
/*------------------------------------------------------------------------------------*/
/**@brief 发送合盖指令
@param
@return
@note 线
*/
/*------------------------------------------------------------------------------------*/
u8 app_chargebox_api_send_close_cid(void)
{
u8 online_cnt = 0;;
u8 ret0, ret1;
if (ear_info.online[EAR_L]) {
online_cnt += 1;
}
if (ear_info.online[EAR_R]) {
online_cnt += 1;
}
enter_hook();
ret0 = chargebox_send_close_cid(EAR_L, online_cnt);
ret1 = chargebox_send_close_cid(EAR_R, online_cnt);
exit_hook();
app_chargebox_api_check_online(ret0, ret1);
if ((ret0 == TRUE) && (ret1 == TRUE)) {
log_debug("send close CID ok\n");
return TRUE;
} else {
log_error("LID close, L:%d,R:%d\n", ret0, ret1);
}
return FALSE;
}
//存放左、右、公共地址
static u8 adv_addr_tmp_buf[3][6];
/*------------------------------------------------------------------------------------*/
/**@brief 记录左/右耳机地址
@param lr:1-- 0--
inbuf:buf指针
@return
@note buf
*/
/*------------------------------------------------------------------------------------*/
void get_lr_adr_cb(u8 lr, u8 *inbuf)
{
if (lr) {
memcpy(&adv_addr_tmp_buf[1][0], inbuf, 6);
} else {
memcpy(&adv_addr_tmp_buf[0][0], inbuf, 6);
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 修改广播地址回调
@param
@return
@note 广广buf
*/
/*------------------------------------------------------------------------------------*/
void exchange_addr_succ_cb(void)
{
u8 i;
for (i = 0; i < 6; i++) {
adv_addr_tmp_buf[2][i] = adv_addr_tmp_buf[0][i] + adv_addr_tmp_buf[1][i];
}
sys_info.chg_addr_ok = 1;
}
/*------------------------------------------------------------------------------------*/
/**@brief 获取广播地址
@param
@return NULL:广
@note
*/
/*------------------------------------------------------------------------------------*/
u8 *get_chargebox_adv_addr(void)
{
if (sys_info.chg_addr_ok) {
return &adv_addr_tmp_buf[2][0];
} else {
return NULL;
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 从vm读取广播地址
@param
@return TRUE: 0:
@note
*/
/*------------------------------------------------------------------------------------*/
u8 chgbox_addr_read_from_vm(void)
{
if (6 == syscfg_read(CFG_CHGBOX_ADDR, &adv_addr_tmp_buf[2][0], 6)) {
sys_info.chg_addr_ok = 1;
log_info("Read adv addr OK:");
put_buf(&adv_addr_tmp_buf[2][0], 6);
return TRUE;
} else {
sys_info.chg_addr_ok = 0;
log_error("Read adv addr error\n");
return FALSE;
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓获取两耳机地址扫描
@param
@return 1: 0:
@note 广chg_addr_ok==0广(线)
*/
/*------------------------------------------------------------------------------------*/
u8 chgbox_addr_save_to_vm(void)
{
if (6 == syscfg_write(CFG_CHGBOX_ADDR, &adv_addr_tmp_buf[2][0], 6)) {
log_info("Write adv addr OK!\n");
return TRUE;
} else {
log_error("Write adv addr error!\n");
return FALSE;
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓获取两耳机地址扫描
@param
@return 1: 0:
@note 广chg_addr_ok==0广(线)
*/
/*------------------------------------------------------------------------------------*/
u8 chgbox_adv_addr_scan(void)
{
//注意部分耳机要收到open_power指令后才跑蓝牙流程,才能拿到地址
static u8 caa_cnt = 0;
if (!sys_info.chg_addr_ok) {
if (ear_info.online[EAR_L] && ear_info.online[EAR_R] && sys_info.chgbox_status == CHG_STATUS_COMM) {
caa_cnt++;
if (caa_cnt < 8) {
//0~4是直接返回1不做操作留给外面的200Ms操作发open_power指令
if (caa_cnt == 5) { //交换地址(配对)
log_debug("ss-0\n");
app_chargebox_send_mag(CHGBOX_MSG_SEND_PAIR);
}
if (caa_cnt > 4) {
log_debug("ss-1\n");
return 0;//发配对指令后不发其他命令,避免干扰
}
} else {
caa_cnt = 0; //如果拿不到地址(chg_addr_ok==0)清0循环
}
}
}
log_debug("ss-2\n");
return 1;
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓交换地址app
@param
@return
@note 线
*/
/*------------------------------------------------------------------------------------*/
u8 app_chargebox_api_exchange_addr(void)
{
u8 ret = FALSE;
if (ear_info.online[EAR_L] && ear_info.online[EAR_R]) {
enter_hook();
ret = chargebox_exchange_addr(get_lr_adr_cb, exchange_addr_succ_cb);
exit_hook();
}
if (ret) {
//交换地址成功后记录地址
chgbox_addr_save_to_vm();
}
return ret;
}
/*------------------------------------------------------------------------------------*/
/**@brief 私有命令例子
* @param
* @return
* @note 10xC00xFE
* 232
* 3lr_buf lr_len
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_api_send_cmd_demo(void)
{
extern u8 lr_buf[2][32];
extern u8 lr_len[2];
u8 buf[3];
buf[0] = CMD_USER;
buf[1] = 0x12;
buf[2] = 0x34;
enter_hook();
if (chargebox_api_write_read(EAR_L, buf, 3, 4) == TRUE) {
//耳机有回复数据
log_dump(lr_buf[EAR_L], lr_len[EAR_L]);
}
if (chargebox_api_write_read(EAR_R, buf, 3, 4) == TRUE) {
//耳机有回复数据
log_dump(lr_buf[EAR_R], lr_len[EAR_R]);
}
exit_hook();
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓发送电量命令获取电量
@param flag:1 0
@return
@note A耳机的电量 B耳机B耳机的电量B是否在线 ()
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_api_send_power(u8 flag)
{
u8 power;
u8 ret0, ret1, is_charge = 0;
power = get_box_power_lvl();//获取仓的电量
if (sys_info.status[USB_DET] == STATUS_ONLINE) {
is_charge = 1;
}
enter_hook();
if (flag == 0) {
ret0 = chargebox_send_power_open(EAR_L, power, is_charge, ear_info.power[EAR_R]);
ret1 = chargebox_send_power_open(EAR_R, power, is_charge, ear_info.power[EAR_L]);
} else {
ret0 = chargebox_send_power_close(EAR_L, power, is_charge, ear_info.power[EAR_R]);
ret1 = chargebox_send_power_close(EAR_R, power, is_charge, ear_info.power[EAR_L]);
}
exit_hook();
app_chargebox_api_check_online(ret0, ret1);
if (ret0 == TRUE) {
ear_info.power[EAR_L] = chargebox_get_power(EAR_L);
log_info("Ear_L:%d_%d", ear_info.power[EAR_L]&BIT(7) ? 1 : 0, ear_info.power[EAR_L] & (~BIT(7)));
} else {
/* log_error("Can't got L\n"); */
}
if (ret1 == TRUE) {
ear_info.power[EAR_R] = chargebox_get_power(EAR_R);
log_info("Ear_R:%d_%d", ear_info.power[EAR_R]&BIT(7) ? 1 : 0, ear_info.power[EAR_R] & (~BIT(7)));
} else {
/* log_error("Can't got R\n"); */
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓通信线程
@param priv:
@return
@note 线
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_task_handler(void *priv)
{
int msg[32];
log_info("data thread running! \n");
while (1) {
if (os_task_pend("taskq", msg, ARRAY_SIZE(msg)) != OS_TASKQ) {
continue;
}
switch (msg[1]) {
case CHGBOX_MSG_SEND_POWER_OPEN:
app_chargebox_api_send_power(0);
break;
case CHGBOX_MSG_SEND_POWER_CLOSE:
app_chargebox_api_send_power(1);
break;
case CHGBOX_MSG_SEND_CLOSE_LID:
app_chargebox_api_send_close_cid();
break;
case CHGBOX_MSG_SEND_SHUTDOWN:
app_chargebox_api_send_shutdown();
break;
case CHGBOX_MSG_SEND_PAIR:
log_info("CHANGE ear ADDR\n");
if (app_chargebox_api_exchange_addr() == TRUE) {
sys_info.pair_succ = 1;
} else {
log_error("pair_fail\n");
}
break;
default:
log_info("default msg: %d\n", msg[1]);
break;
}
}
}
CHARGEBOX_PLATFORM_DATA_BEGIN(chargebox_data)
.L_port = TCFG_CHARGEBOX_L_PORT,
.R_port = TCFG_CHARGEBOX_R_PORT,
CHARGEBOX_PLATFORM_DATA_END()
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓提前初始化内容
@param priv:
@return
@note
*/
/*------------------------------------------------------------------------------------*/
void app_chargebox_timer_handle(void *priv)
{
static u8 ms200_cnt = 0;
static u8 ms500_cnt = 0;
ms200_cnt++;
if (ms200_cnt >= 2) {
ms200_cnt = 0;
app_chargebox_event_to_user(CHGBOX_EVENT_200MS);
}
ms500_cnt++;
if (ms500_cnt >= 5) {
ms500_cnt = 0;
app_chargebox_event_to_user(CHGBOX_EVENT_500MS);
}
}
/*------------------------------------------------------------------------------------*/
/**@brief 充电仓提前初始化内容
@param
@return
@note 广线timer
*/
/*------------------------------------------------------------------------------------*/
int chargebox_advanced_init(void)
{
chgbox_addr_read_from_vm();
chargebox_api_init(&chargebox_data);
task_create(app_chargebox_task_handler, NULL, CHGBOX_THR_NAME);
os_mutex_create(&power_mutex);
sys_timer_add(NULL, app_chargebox_timer_handle, 100);//推事件处理
return 0;
}
__initcall(chargebox_advanced_init);
#endif