添加电池曲线app_power_manage.c
📎 原始文档:https://www.kdocs.cn/l/civ13PuFfJbe 添加电池曲线app_power_manage.c
app_power_manage.c 下载【金山文档】添加电池曲线
代码如下:
#include "system/includes.h"
#include "app_power_manage.h"
#include "app_main.h"
#include "app_config.h"
#include "app_action.h"
#include "asm/charge.h"
#include "ui_manage.h"
#include "tone_player.h"
#include "asm/adc_api.h"
#include "btstack/avctp_user.h"
#include "user_cfg.h"
#include "bt.h"
#include "asm/charge.h"
#include "ui/ui_api.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#define LOG_TAG_CONST APP_POWER
#define LOG_TAG "[APP_POWER]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define TCFG_BATTERY_POWER_MANAGE_ENABLE ENABLE_THIS_MOUDLE
// 1、需要在user_cfg_id.h添加保存电量的ID
// #define VM_BAT_PRESENT xx id范围[1 ~ 60]
// 2、充电曲线总宏控制 TCFG_BATTERY_POWER_MANAGE_ENABLE
// 3、替换充放电曲线,需要电池厂提供与实际充放电电流尽量接近的电压百分比曲线
// 放电电压曲线: Battery_discharge_curve[]
// 放电百分比曲线: battery_precent_val[]
// 充电电压曲线:charge_80mA_battery_value[]
// 充电百分比曲线:charge_80mA_battery_precent_value[]
// 电压映射电量函数:Get_the_corresponding_value_of_battery_power
// 用户电量计算函数:usr_vbat_percent_averge_filter
#if TCFG_BATTERY_POWER_MANAGE_ENABLE
u16 get_vbat_level_1(void);
static void vbat_vm_init();
u8 get_vbat_averge_percent(void);
// u16 vbat_value_fifo[SAMPLE_POINT];
u8 battery_precent_lel = 100;
#endif
enum {
VBAT_NORMAL = 0,
VBAT_WARNING,
VBAT_LOWPOWER,
} VBAT_STATUS;
#define VBAT_DETECT_CNT 3 //连续3次检测
static int vbat_slow_timer = 0;
static int vbat_fast_timer = 0;
static int lowpower_timer = 0;
static u8 old_battery_level = 9;
static u16 bat_val = 0;
static u16 avr_bat_val = 0;
static u8 avr_bat_percent_val = 0;
static volatile u8 cur_battery_level = 0;
static u16 battery_full_value = 0;
static u8 tws_sibling_bat_level = 0xff;
static u8 tws_sibling_bat_percent_level = 0xff;
static u8 cur_bat_st = VBAT_NORMAL;
void vbat_check(void *priv);
void sys_enter_soft_poweroff(void *priv);
void clr_wdt(void);
void power_event_to_user(u8 event);
static void vbat_percent_averge_filter(u16 battery_val);
static void usr_vbat_percent_averge_filter(void *p);
u8 get_tws_sibling_bat_level(void)
{
#if TCFG_USER_TWS_ENABLE
/* log_info("***********get_tws_sibling_bat_level: %2x", tws_sibling_bat_percent_level); */
return tws_sibling_bat_level & 0x7f;
#endif
return 0xff;
}
u8 get_tws_sibling_bat_persent(void)
{
#if TCFG_USER_TWS_ENABLE
/* log_info("***********get_tws_sibling_bat_level: %2x", tws_sibling_bat_percent_level); */
return tws_sibling_bat_percent_level;
#endif
return 0xff;
}
void app_power_set_tws_sibling_bat_level(u8 vbat, u8 percent)
{
#if TCFG_USER_TWS_ENABLE
tws_sibling_bat_level = vbat;
tws_sibling_bat_percent_level = percent;
/*
** 发出电量同步事件进行进一步处理
**/
power_event_to_user(POWER_EVENT_SYNC_TWS_VBAT_LEVEL);
log_info("set_sibling_bat_level: %d, %d\n", vbat, percent);
#endif
}
static void set_tws_sibling_bat_level(void *_data, u16 len, bool rx)
{
u8 *data = (u8 *)_data;
if (rx) {
app_power_set_tws_sibling_bat_level(data[0], data[1]);
}
}
#if TCFG_USER_TWS_ENABLE
REGISTER_TWS_FUNC_STUB(vbat_sync_stub) = {
.func_id = TWS_FUNC_ID_VBAT_SYNC,
.func = set_tws_sibling_bat_level,
};
#endif
void tws_sync_bat_level(void)
{
#if (TCFG_USER_TWS_ENABLE && BT_SUPPORT_DISPLAY_BAT)
u8 battery_level = cur_battery_level;
#if CONFIG_DISPLAY_DETAIL_BAT
u8 percent_level = get_vbat_percent();
#else
u8 percent_level = get_self_battery_level() * 10 + 10;
#endif
if (get_charge_online_flag()) {
percent_level |= BIT(7);
}
u8 data[2];
data[0] = battery_level;
data[1] = percent_level;
tws_api_send_data_to_sibling(data, 2, TWS_FUNC_ID_VBAT_SYNC);
log_info("tws_sync_bat_level: %d,%d\n", battery_level, percent_level);
#endif
}
void power_event_to_user(u8 event)
{
struct sys_event e;
e.type = SYS_DEVICE_EVENT;
e.arg = (void *)DEVICE_EVENT_FROM_POWER;
e.u.dev.event = event;
e.u.dev.value = 0;
sys_event_notify(&e);
}
int app_power_event_handler(struct device_event *dev)
{
int ret = false;
#if(TCFG_SYS_LVD_EN == 1)
switch (dev->event) {
case POWER_EVENT_POWER_NORMAL:
ui_update_status(STATUS_EXIT_LOWPOWER);
break;
case POWER_EVENT_POWER_WARNING:
/* ui_update_status(STATUS_LOWPOWER); */
if (lowpower_timer == 0) {
lowpower_timer = sys_timer_add((void *)POWER_EVENT_POWER_WARNING, (void (*)(void *))power_event_to_user, LOW_POWER_WARN_TIME);
}
break;
case POWER_EVENT_POWER_LOW:
r_printf(" POWER_EVENT_POWER_LOW");
vbat_timer_delete();
if (lowpower_timer) {
sys_timer_del(lowpower_timer);
lowpower_timer = 0 ;
}
#if TCFG_APP_BT_EN
#if (RCSP_ADV_EN)
extern u8 adv_tws_both_in_charge_box(u8 type);
adv_tws_both_in_charge_box(1);
#endif
soft_poweroff_mode(1); ///强制关机
sys_enter_soft_poweroff(NULL);
#else
void app_entry_idle() ;
app_entry_idle() ;
#endif
break;
#if TCFG_APP_BT_EN
#if TCFG_USER_TWS_ENABLE
case POWER_EVENT_SYNC_TWS_VBAT_LEVEL:
if (tws_api_get_role() == TWS_ROLE_MASTER) {
user_send_cmd_prepare(USER_CTRL_HFP_CMD_UPDATE_BATTARY, 0, NULL);
}
break;
#endif
case POWER_EVENT_POWER_CHANGE:
/* log_info("POWER_EVENT_POWER_CHANGE\n"); */
#if TCFG_USER_TWS_ENABLE
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
if (tws_api_get_tws_state()&TWS_STA_ESCO_OPEN) {
break;
}
tws_sync_bat_level();
}
#endif
UI_MSG_POST("bat_status:event=%4", dev->event);
user_send_cmd_prepare(USER_CTRL_HFP_CMD_UPDATE_BATTARY, 0, NULL);
#endif
break;
case POWER_EVENT_POWER_CHARGE:
UI_MSG_POST("bat_status:event=%4", dev->event);
if (lowpower_timer) {
sys_timer_del(lowpower_timer);
lowpower_timer = 0 ;
}
break;
default:
break;
}
#endif
return ret;
}
u16 get_vbat_level(void)
{
//return 370; //debug
return (adc_get_voltage(AD_CH_VBAT) * 4 / 10);
}
#if TCFG_BATTERY_POWER_MANAGE_ENABLE
u16 get_vbat_level_1(void)
{
//return 370; //debug
//printf("adc_get_voltage(AD_CH_VBAT) * 4 = %d\n",adc_get_voltage(AD_CH_VBAT)*4);
return (adc_get_voltage(AD_CH_VBAT) * 4 );
}
#endif
__attribute__((weak)) u8 remap_calculate_vbat_percent(u16 bat_val)
{
return 0;
}
u16 get_vbat_value(void)
{
return bat_val;
}
u8 get_vbat_percent(void)
{
#if TCFG_BATTERY_POWER_MANAGE_ENABLE
if (bat_val <= app_var.poweroff_tone_v)
{
return 0;
}
return get_vbat_averge_percent();
#endif
u16 tmp_bat_val;
u16 bat_val = avr_bat_val;//get_vbat_level();
if (battery_full_value == 0) {
#if TCFG_CHARGE_ENABLE
battery_full_value = (get_charge_full_value() - 100) / 10; //防止部分电池充不了这么高电量,充满显示未满的情况
#else
battery_full_value = 420;
#endif
}
if (bat_val <= app_var.poweroff_tone_v) {
return 0;
}
tmp_bat_val = remap_calculate_vbat_percent(bat_val);
if (!tmp_bat_val) {
tmp_bat_val = ((u32)bat_val - app_var.poweroff_tone_v) * 100 / (battery_full_value - app_var.poweroff_tone_v);
if (tmp_bat_val > 100) {
tmp_bat_val = 100;
}
}
return (u8)tmp_bat_val;
}
u8 get_vbat_averge_percent(void)
{
return avr_bat_percent_val;
}
bool get_vbat_need_shutdown(void)
{
if ((bat_val <= LOW_POWER_SHUTDOWN) || adc_check_vbat_lowpower()) {
return TRUE;
}
return FALSE;
}
//将当前电量转换为1~9级发送给手机同步电量
u8 battery_value_to_phone_level(u16 bat_val)
{
u8 battery_level = 0;
u8 vbat_percent = get_vbat_percent();
if (vbat_percent < 5) { //小于5%电量等级为0,显示10%
return 0;
}
battery_level = (vbat_percent - 5) / 10;
return battery_level;
}
//获取自身的电量
u8 get_self_battery_level(void)
{
return cur_battery_level;
}
u8 get_cur_battery_level(void)
{
u8 bat_lev = tws_sibling_bat_level & (~BIT(7));
#if TCFG_USER_TWS_ENABLE
if (bat_lev == 0x7f) {
return cur_battery_level;
}
#if (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_LOWER)
return cur_battery_level < bat_lev ? cur_battery_level : bat_lev;
#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_HIGHER)
return cur_battery_level < bat_lev ? bat_lev : cur_battery_level;
#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_LEFT)
return tws_api_get_local_channel() == 'L' ? cur_battery_level : bat_lev;
#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_RIGHT)
return tws_api_get_local_channel() == 'R' ? cur_battery_level : bat_lev;
#else
return cur_battery_level;
#endif //END CONFIG_DISPLAY_TWS_BAT_TYPE
#else //TCFG_USER_TWS_ENABLE == 0
return cur_battery_level;
#endif
}
void vbat_check_slow(void *priv)
{
if (vbat_fast_timer == 0) {
vbat_fast_timer = usr_timer_add(NULL, vbat_check, 10, 1);
}
if (get_charge_online_flag()) {
sys_timer_modify(vbat_slow_timer, 30 * 1000);
} else {
sys_timer_modify(vbat_slow_timer, 15 * 1000);
}
}
void vbat_check_init(void)
{
#if TCFG_BATTERY_POWER_MANAGE_ENABLE
vbat_vm_init();
usr_vbat_percent_averge_filter(NULL);
usr_timer_add(NULL, usr_vbat_percent_averge_filter, 10, 0);
if (vbat_slow_timer == 0) {
vbat_slow_timer = sys_timer_add(NULL, vbat_check_slow, 10 * 1000);
} else {
sys_timer_modify(vbat_slow_timer, 10 * 1000);
}
#else
if (vbat_slow_timer == 0) {
vbat_slow_timer = sys_timer_add(NULL, vbat_check_slow, 30 * 1000);
} else {
sys_timer_modify(vbat_slow_timer, 30 * 1000);
}
#endif
if (vbat_fast_timer == 0) {
vbat_fast_timer = usr_timer_add(NULL, vbat_check, 10, 1);
}
}
void vbat_timer_delete(void)
{
if (vbat_slow_timer) {
sys_timer_del(vbat_slow_timer);
vbat_slow_timer = 0;
}
if (vbat_fast_timer) {
usr_timer_del(vbat_fast_timer);
vbat_fast_timer = 0;
}
}
#define SAMPLE_POINT 20
#define FILTER_CNT 5
#define abs(x) ((x)>0?(x):-(x))
u16 vbat_fifo[SAMPLE_POINT];
u8 vbat_percent_fifo[SAMPLE_POINT];
static void vbat_averge_filter(u16 val)
{
u8 i = 0, k = 0;
u32 sum = 0;
int val_diff = avr_bat_val - val;
static u8 filter_cnt = 0;
//电量值与平均值超过0.05v,默认为无效数据
if (abs(val_diff) > 5 && (avr_bat_val != 0)) {
filter_cnt++;
if (filter_cnt < FILTER_CNT) {
return;
}
/* printf("filter_cnt >= FILTER_CNT"); */
}
k = SAMPLE_POINT;
filter_cnt = 0;
if (vbat_fifo[0] == 0) {
for (i = 0; i < k; i++) {
vbat_fifo[i] = val;
}
} else {
for (i = 0; i < k - 1; i++) {
vbat_fifo[i] = vbat_fifo[i + 1];
}
vbat_fifo[k - 1] = val;
}
for (i = 0; i < k; i++) {
sum += vbat_fifo[i];
}
avr_bat_val = sum / k;
/* r_printf("b:%d %d", avr_bat_val, val); */
}
#if TCFG_BATTERY_POWER_MANAGE_ENABLE
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if 1//TCFG_BATTERY_POWER_MANAGE_ENABLE
const u16 Battery_discharge_curve[] =
{
4173,
4148,
4136,
4128,
4121,
4115,
4110,
4105,
4100,
4096,
4091,
4087,
4083,
4079,
4075,
4071,
4067,
4063,
4059,
4055,
4051,
4048,
4044,
4041,
4037,
4033,
4030,
4026,
4023,
4019,
4016,
4013,
4009,
4006,
4002,
3999,
3996,
3992,
3989,
3986,
3982,
3979,
3975,
3972,
3969,
3965,
3962,
3958,
3955,
3952,
3949,
3946,
3942,
3939,
3936,
3933,
3930,
3927,
3924,
3921,
3918,
3916,
3913,
3910,
3907,
3904,
3902,
3899,
3896,
3893,
3891,
3888,
3885,
3883,
3880,
3877,
3875,
3872,
3869,
3867,
3864,
3862,
3859,
3857,
3854,
3852,
3849,
3847,
3844,
3842,
3840,
3837,
3835,
3833,
3830,
3828,
3826,
3824,
3821,
3819,
3817,
3815,
3813,
3811,
3809,
3807,
3805,
3803,
3801,
3799,
3797,
3795,
3793,
3791,
3790,
3788,
3786,
3784,
3782,
3781,
3779,
3777,
3776,
3774,
3772,
3771,
3769,
3768,
3766,
3764,
3763,
3761,
3760,
3758,
3757,
3755,
3754,
3752,
3751,
3750,
3748,
3747,
3746,
3744,
3743,
3742,
3740,
3739,
3738,
3737,
3735,
3734,
3733,
3732,
3731,
3730,
3728,
3727,
3726,
3725,
3724,
3723,
3722,
3721,
3720,
3719,
3718,
3717,
3716,
3715,
3715,
3714,
3713,
3712,
3712,
3710,
3709,
3708,
3707,
3706,
3705,
3704,
3703,
3702,
3701,
3701,
3700,
3698,
3697,
3696,
3695,
3694,
3693,
3692,
3691,
3690,
3689,
3687,
3686,
3685,
3684,
3682,
3681,
3680,
3678,
3677,
3676,
3674,
3673,
3671,
3670,
3668,
3666,
3665,
3663,
3661,
3659,
3657,
3655,
3654,
3652,
3650,
3648,
3645,
3643,
3641,
3639,
3637,
3635,
3633,
3631,
3628,
3626,
3624,
3622,
3620,
3618,
3616,
3614,
3612,
3609,
3607,
3604,
3601,
3598,
3595,
3591,
3587,
3582,
3577,
3571,
3563,
3555,
3545,
3534,
3520,
3505,
3488,
3467,
3445,
3418,
3389,
3354,
3313,
3265,
3205,
3125,
3000
};
const u8 battery_precent_val[] = {
0,
0,
0,
1,
1,
1,
2,
2,
3,
3,//10
3,
4,
4,
4,
5,
5,
6,
6,
6,//20
7,
7,
7,
8,
8,
9,
9,
9,
10,
10,//30
10,
11,
11,
12,
12,
12,
13,
13,
13,
14,//40
14,
15,
15,
15,
16,
16,
16,
17,
17,
18,//50
18,
18,
19,
19,
19,
20,
20,
21,
21,
21,//60
22,
22,
22,
23,
23,
24,
24,
24,
25,
25,//70
25,
26,
26,
27,
27,
27,
28,
28,
28,
29,//80
29,
30,
30,
30,
31,
31,
31,
32,
32,
33,//90
33,
33,
34,
34,
34,
35,
35,
36,
36,
36,//100
37,
37,
37,
38,
38,
39,
39,
39,
40,
40,//110
40,
41,
41,
42,
42,
42,
43,
43,
43,
44,//120
44,
45,
45,
45,
46,
46,
46,
47,
47,
48,//130
48,
48,
49,
49,
49,
50,
50,
51,
51,
51,//140
52,
52,
52,
53,
53,
54,
54,
54,
55,
55,//150
55,
56,
56,
57,
57,
57,
58,
58,
58,
59,//160
59,
60,
60,
60,
61,
61,
61,
62,
62,
63,//170
63,
63,
64,
64,
64,
65,
65,
66,
66,
66,//180
67,
67,
67,
68,
68,
69,
69,
69,
70,
70,//190
70,
71,
71,
72,
72,
72,
73,
73,
73,
74,//200
74,
75,
75,
75,//204
76,
76,
76,
77,
77,
78,//210
78,
78,
79,
79,
79,
80,
80,
81,
81,
81,//220
82,
82,
82,
83,
83,
84,
84,
84,
85,
85,//230
85,
86,
86,
87,
87,
87,
88,
88,
88,
89,//240
89,
90,
90,
90,
91,
91,
91,
92,
92,
93,//250
93,
93,
94,
94,
94,
95,
95,
96,
96,
96,//260
97,
97,
97,
98,
98,
99,
99,
99,
100//269
};
const u16 charge_80mA_battery_value[] = {
3359,
3457,
3509,
3548,
3581,
3609,
3633,
3655,
3675,
3692,
3708,
3722,
3734,
3743,
3749,
3752,
3754,
3756,
3758,
3759,
3761,
3763,
3764,
3766,
3768,
3769,
3772,
3774,
3775,
3778,
3780,
3783,
3785,
3788,
3791,
3793,
3796,
3798,
3801,
3804,
3806,
3809,
3811,
3814,
3816,
3819,
3821,
3823,
3826,
3828,
3830,
3832,
3834,
3836,
3838,
3840,
3842,
3843,
3845,
3846,
3848,
3849,
3850,
3851,
3852,
3853,
3854,
3855,
3856,
3857,
3858,
3859,
3859,
3860,
3861,
3862,
3863,
3864,
3864,
3865,
3866,
3866,
3867,
3868,
3869,
3869,
3870,
3871,
3871,
3872,
3873,
3873,
3874,
3875,
3875,
3876,
3877,
3878,
3879,
3879,
3880,
3881,
3882,
3883,
3884,
3884,
3885,
3886,
3887,
3888,
3889,
3890,
3891,
3892,
3893,
3894,
3896,
3897,
3898,
3899,
3900,
3902,
3903,
3904,
3905,
3907,
3908,
3909,
3911,
3912,
3913,
3915,
3916,
3917,
3919,
3920,
3922,
3923,
3924,
3926,
3928,
3929,
3931,
3932,
3934,
3936,
3937,
3939,
3941,
3942,
3944,
3946,
3947,
3949,
3951,
3953,
3954,
3956,
3958,
3960,
3962,
3964,
3965,
3967,
3969,
3971,
3973,
3975,
3977,
3979,
3981,
3983,
3985,
3987,
3989,
3991,
3994,
3996,
3998,
4000,
4002,
4004,
4007,
4009,
4011,
4014,
4016,
4018,
4021,
4023,
4026,
4028,
4031,
4033,
4035,
4038,
4041,
4043,
4046,
4048,
4051,
4054,
4056,
4059,
4062,
4064,
4067,
4070,
4073,
4076,
4079,
4082,
4085,
4087,
4091,
4094,
4097,
4100,
4103,
4107,
4110,
4114,
4117,
4121,
4124,
4128,
4132,
4135,
4139,
4143,
4146,
4150,
4154,
4157,
4161,
4165,
4169,
4172,
4176,
4180,
4184,
4188,
4192,
4196,
4200,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4202,
4202,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4201,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202,
4202
};
const u8 charge_80mA_battery_precent_value[] = {
0,
0,
0,
1,
1,
1,
2,
2,
3,
3,
3,
4,
4,
4,
5,
5,
6,
6,
6,
7,
7,
7,
8,
8,
9,
9,
9,
10,
10,
10,
11,
11,
12,
12,
12,
13,
13,
13,
14,
14,
15,
15,
15,
16,
16,
16,
17,
17,
18,
18,
18,
19,
19,
19,
20,
20,
21,
21,
21,
22,
22,
22,
23,
23,
24,
24,
24,
25,
25,
26,
26,
26,
27,
27,
27,
28,
28,
29,
29,
29,
30,
30,
30,
31,
31,
32,
32,
32,
33,
33,
33,
34,
34,
35,
35,
35,
36,
36,
36,
37,
37,
38,
38,
38,
39,
39,
39,
40,
40,
41,
41,
41,
42,
42,
42,
43,
43,
44,
44,
44,
45,
45,
45,
46,
46,
47,
47,
47,
48,
48,
49,
49,
49,
50,
50,
50,
51,
51,
52,
52,
52,
53,
53,
53,
54,
54,
55,
55,
55,
56,
56,
56,
57,
57,
58,
58,
58,
59,
59,
59,
60,
60,
61,
61,
61,
62,
62,
62,
63,
63,
64,
64,
64,
65,
65,
65,
66,
66,
67,
67,
67,
68,
68,
68,
69,
69,
70,
70,
70,
71,
71,
72,
72,
72,
73,
73,
73,
74,
74,
75,
75,
75,
76,
76,
76,
77,
77,
78,
78,
78,
79,
79,
79,
80,
80,
81,
81,
81,
82,
82,
82,
83,
83,
84,
84,
84,
85,
85,
85,
86,
86,
87,
87,
87,
88,
88,
88,
89,
89,
90,
90,
90,
91,
91,
91,
92,
92,
93,
93,
93,
93,
94,
94,
94,
94,
95,
95,
95,
95,
95,
96,
96,
96,
96,
96,
96,
96,
97,
97,
97,
97,
97,
97,
97,
97,
97,
97,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
98,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100
};
#endif
u8 get_user_battery_precent_val(void)
{
return battery_precent_lel;
}
//获取电池电量对应值
static u16 Get_the_corresponding_value_of_battery_power(u16 in_val)
{
int curr_present_k = -1;
u32 battery_val = in_val;
// 放电曲线映射
int i,k;
k=0;
if(!get_charge_online_flag()) {
int bat_len = sizeof(Battery_discharge_curve)/sizeof(Battery_discharge_curve[0]);
int bat_p_len = sizeof(battery_precent_val)/sizeof(battery_precent_val[0]);
ASSERT(bat_len==bat_p_len, "attery_discharge_curve len error!!!");// 注意数组长度要一致
for(i=0; i<bat_len; i++) {
k++;
if(Battery_discharge_curve[bat_len-i-1] > battery_val) {
break;
}
}
curr_present_k = battery_precent_val[k-1]*10;
} else {// 充电曲线映射
int charge_bat_len = sizeof(charge_80mA_battery_value)/sizeof(charge_80mA_battery_value[0]);
int charge_bat_p_len = sizeof(charge_80mA_battery_precent_value)/sizeof(charge_80mA_battery_precent_value[0]);
ASSERT(charge_bat_len==charge_bat_p_len, "attery_charge_curve len error!!!!");// 注意数组长度要一致
for(i=0; i<charge_bat_len; i++) {
k++;
if(charge_80mA_battery_value[i] > battery_val) {
break;
}
}
curr_present_k = charge_80mA_battery_precent_value[k-1]*10;
}
printf(">>>>>>>>>>>>>>>>>>>>CHARGE:%d k:%d NOW_P:%d",get_charge_online_flag(),k, curr_present_k);
return curr_present_k;
}
//获取电池电量百分比
u8 Get_battery_power_percentage(void)
{
return battery_precent_lel;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
static int last_present_k=-1;
int write_bat_vm(int vm_present){
printf(">>>>>>>>>>>>>>>>>>>>>更改电量VM");
syscfg_write(VM_BAT_PRESENT, &vm_present, sizeof(vm_present));
}
static void vbat_vm_init()
{
#if 1 //读取VM
int vm_present=0;
// 初始化
if(last_present_k == -1) {
int ret = syscfg_read(VM_BAT_PRESENT, &vm_present, sizeof(vm_present));
if( ret>0 ) {
last_present_k = vm_present;
printf("上电VM有值:%d", last_present_k);
} else {
// last_present_k = 500;
// printf("上电VM无值:%d", last_present_k);
// syscfg_write(VM_BAT_PRESENT, &vm_present, sizeof(vm_present));
}
}
#endif
}
static void usr_vbat_percent_averge_filter(void *p)
{
// 20S采样一次
static u32 last_time=0;
if(sys_timer_get_ms()-last_time<20000 && last_time!=0){
return;
}
last_time = sys_timer_get_ms();
int curr_present_k = Get_the_corresponding_value_of_battery_power(get_vbat_level_1());
int a = 50;//当前滤波系数
int b = 1000;
if( curr_present_k>= 970 || curr_present_k<=30) {
a=500;
}
// 恒压充阶段还没完成,不显示到 100 %。
if( curr_present_k==0 || /* curr_present_k==1000 || */ get_charge_full_flag()){
a=1000;
}
// 防止电压回弹
if( get_charge_online_flag() ) {
if(curr_present_k <= last_present_k) { //电量下降忽略本次采样
printf("charge...hold");
a = 0;
}
} else {
if(curr_present_k >= last_present_k) { //电量上升忽略本次采样
printf("discharge...hold");
a = 0;
}
}
// 没有初始化,直接用当前电量
static int last_result = -1;
if(last_present_k == -1){
last_present_k = curr_present_k;
}
if(last_result = -1){
last_result = last_present_k;
}
int result = a*curr_present_k/b + (b-a)*last_present_k/b;
result = constrain(result,0,1000);
if(last_result/10 != result/10) {
printf("vbat change 1% save VM");
int argv[3];
argv[0] = (int)write_bat_vm;
argv[1] = 1;
argv[2] = result;
int ret = os_taskq_post_type("app_core", Q_CALLBACK, 3, argv);
if (ret) {
printf("vbat change post ret:%d \n", ret);
}
}
last_result = result;
last_present_k = result;
printf("curr_present_k = %d result=%d charge=%d",curr_present_k,last_present_k, get_charge_online_flag());
// UI实际拿到的电量值
avr_bat_percent_val = result/10;
return;
}
#endif // TCFG_BATTERY_POWER_MANAGE_ENABLE
static void vbat_percent_averge_filter(u16 battery_val)
{
u8 i = 0, k = SAMPLE_POINT;
u32 sum = 0;
u16 tmp_bat_val;
if (battery_full_value == 0) {
#if TCFG_CHARGE_ENABLE
battery_full_value = (get_charge_full_value() - 100) / 10; //防止部分电池充不了这么高电量,充满显示未满的情况
#else
battery_full_value = 420;
#endif
}
if (battery_val <= app_var.poweroff_tone_v) {
return;
}
tmp_bat_val = remap_calculate_vbat_percent(battery_val);
if (!tmp_bat_val) {
tmp_bat_val = ((u32)battery_val - app_var.poweroff_tone_v) * 100 / (battery_full_value - app_var.poweroff_tone_v);
if (tmp_bat_val > 100) {
tmp_bat_val = 100;
}
}
if (vbat_percent_fifo[0] == 0) {
for (i = 0; i < k; i++) {
vbat_percent_fifo[i] = tmp_bat_val;
}
} else {
for (i = 0; i < k - 1; i++) {
vbat_percent_fifo[i] = vbat_percent_fifo[i + 1];
}
vbat_percent_fifo[k - 1] = tmp_bat_val;
}
for (i = 0; i < k; i++) {
sum += vbat_percent_fifo[i];
}
avr_bat_percent_val = sum / k;
/* r_printf("p:%d %d", avr_bat_percent_val, tmp_bat_val); */
}
void vbat_check(void *priv)
{
static u8 unit_cnt = 0;
static u8 low_warn_cnt = 0;
static u8 low_off_cnt = 0;
static u8 low_voice_cnt = 0;
static u8 low_power_cnt = 0;
static u8 power_normal_cnt = 0;
static u8 charge_online_flag = 0;
static u8 low_voice_first_flag = 1;//进入低电后先提醒一次
if (!bat_val) {
bat_val = get_vbat_level();
} else {
bat_val = (get_vbat_level() + bat_val) / 2; //32s平均电压
}
cur_battery_level = battery_value_to_phone_level(bat_val);
vbat_averge_filter(bat_val); //bat_val计算出平均电压avr_bat_val
#if !TCFG_BATTERY_POWER_MANAGE_ENABLE
vbat_percent_averge_filter(get_vbat_level()); //avr_bat_val计算出平均电量avr_bat_percent_val
#endif
printf("bv:%d, bl:%d , check_vbat:%d, avr_bat_val = %d\n", bat_val, cur_battery_level, adc_check_vbat_lowpower(),avr_bat_val);
unit_cnt++;
/* if (bat_val < LOW_POWER_OFF_VAL) { */
if (adc_check_vbat_lowpower() || (bat_val <= app_var.poweroff_tone_v)) {
low_off_cnt++;
}
/* if (bat_val < LOW_POWER_WARN_VAL) { */
if (bat_val <= app_var.warning_tone_v) {
low_warn_cnt++;
}
/* log_info("unit_cnt:%d\n", unit_cnt); */
if (unit_cnt >= VBAT_DETECT_CNT) {
if (get_charge_online_flag() == 0) {
if (low_off_cnt > (VBAT_DETECT_CNT / 2)) { //低电关机
low_power_cnt++;
low_voice_cnt = 0;
power_normal_cnt = 0;
cur_bat_st = VBAT_LOWPOWER;
if (low_power_cnt > 6) {
log_info("\n*******Low Power,enter softpoweroff********\n");
low_power_cnt = 0;
power_event_to_user(POWER_EVENT_POWER_LOW);
usr_timer_del(vbat_fast_timer);
vbat_fast_timer = 0;
}
} else if (low_warn_cnt > (VBAT_DETECT_CNT / 2)) { //低电提醒
low_voice_cnt ++;
low_power_cnt = 0;
power_normal_cnt = 0;
cur_bat_st = VBAT_WARNING;
if ((low_voice_first_flag && low_voice_cnt > 1) || //第一次进低电10s后报一次
(!low_voice_first_flag && low_voice_cnt >= 5)) {
low_voice_first_flag = 0;
low_voice_cnt = 0;
if (!lowpower_timer) {
log_info("\n**Low Power,Please Charge Soon!!!**\n");
power_event_to_user(POWER_EVENT_POWER_WARNING);
}
}
} else {
power_normal_cnt++;
low_voice_cnt = 0;
low_power_cnt = 0;
if (power_normal_cnt > 2) {
if (cur_bat_st != VBAT_NORMAL) {
log_info("[Noraml power]\n");
cur_bat_st = VBAT_NORMAL;
power_event_to_user(POWER_EVENT_POWER_NORMAL);
}
}
}
} else {
power_event_to_user(POWER_EVENT_POWER_CHARGE);
}
unit_cnt = 0;
low_off_cnt = 0;
low_warn_cnt = 0;
if (cur_bat_st != VBAT_LOWPOWER) {
usr_timer_del(vbat_fast_timer);
vbat_fast_timer = 0;
cur_battery_level = battery_value_to_phone_level(bat_val);
if (cur_battery_level != old_battery_level) {
power_event_to_user(POWER_EVENT_POWER_CHANGE);
} else {
if (charge_online_flag != get_charge_online_flag()) {
//充电变化也要交换,确定是否在充电仓
power_event_to_user(POWER_EVENT_POWER_CHANGE);
}
}
charge_online_flag = get_charge_online_flag();
old_battery_level = cur_battery_level;
}
}
}
bool vbat_is_low_power(void)
{
return (cur_bat_st != VBAT_NORMAL);
}
void check_power_on_voltage(void)
{
#if(TCFG_SYS_LVD_EN == 1)
u16 val = 0;
u8 normal_power_cnt = 0;
u8 low_power_cnt = 0;
while (1) {
clr_wdt();
val = get_vbat_level();
printf("vbat: %d\n", val);
if ((val < app_var.poweroff_tone_v) || adc_check_vbat_lowpower()) {
low_power_cnt++;
normal_power_cnt = 0;
if (low_power_cnt > 10) {
ui_update_status(STATUS_POWERON_LOWPOWER);
log_info("power on low power , enter softpoweroff!\n");
power_set_soft_poweroff();
}
} else {
normal_power_cnt++;
low_power_cnt = 0;
if (normal_power_cnt > 10) {
vbat_check_init();
return;
}
}
}
#endif
}