KDocs 研发资料库
  • 屏融合应用方案入口汇总
  • JL701N穿戴客述问题FAQ
  • JL701N穿戴类补丁list
  • 手表软件调试
  • JL701手表硬件设计注意事项 总结
  • 手表烧录_升级工具说明
  • 手表量产相关
  • 生产烧录KEY及代码和升级代码
  • AC695N系列手表SDK开发指南
  • JL7012A手表-SDK入门指南V1.0
  • 穿戴手表JL701N-入门到进阶开发指导
  • 彩屏充电仓JL701N LVGL入门到进阶指导文档
  • AC695N手表软硬件问题整理
  • JL701N手表软硬件问题整理
  • 701n手表SDK共性问题汇总
  • UI效果参考demo文档
  • 屏幕触摸驱动相关参考
  • 穿戴类支付宝支付流程
  • AC701N_PMU_介绍
  • 经典蓝牙相关接口说明
  • music应用详细设计说明书
  • music_player接口设计说明文档
  • PO声测试以及处理方法
  • DAC性能测试指南
  • 杰理串口升级规范
  • AC696N串口升级说明
  • AC695N系列手表UI开发指南
  • AC695N添加升级UI说明文档.
  • UI布局工具使用说明
  • UI接口设计说明书
  • UI工具快速使用说明
  • 701N_UI编辑工具用户手册
  • UI工程源文件升级工具使用说明
  • 701N屏幕驱动配置说明
  • JL701N 2D图形硬件加速接口使用说明
  • JL701_watch常用例子参考
  • JL_WATCH_SDK UI相关工具使用文档
  • 智能手表音频 设计调试手册 V1.2
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 701手表 PCBA产测工具使用说明书 V1.0
  • 杰理定频问题排查2021.1.26
  • BQB5.4 20231007
  • 各类概率性死机调试解决指南
  • 不开机问题处理汇总(仅供参考)
  • 蓝牙搜索不到问题处理汇总(仅供参考)
  • 样机发烫(仅供参考)
  • 蓝牙音乐卡顿问题处理汇总(仅供参考)
  • 充电问题处理汇总(仅供参考)
  • 触摸问题处理汇总(仅供参考)
  • 功耗调试指导
  • JL701N穿戴客述问题FAQ
  • 701N 开发板新屏幕驱动修改
  • AC701 nandflash A8图片显示问题
  • 支付宝乘车码接入资料
  • 多国语言及字库使用指南
  • 查看C程序Flash 和RAM 资源占用说明文档
  • 701N_SDK3.0.1_OPUS_OGG 编解码
  • 蓝牙在线调eq说明
  • BR EDR BLE 蓝牙性能测试配置方法_
  • BLE-HID
  • BLE-HID 调试文档
  • 【问题】701v301外置flash播放wts提示音
  • 本地录音开启及调试
  • 死机分析
  • 表盘传输APP层的压缩算法
  • 功能模版:JL701_V301_UI资源使用FAT文件系统demo
  • JL7013+4G CAT1 参考设计原理图
  • 吾爱4G模组+JL701接口说明
  • (电脑一拖多)手表升级dongle工具使用补充说明
  • 蓝牙接口使用说明
  • ble 开发流程
  • 彩屏仓功耗优化
  • 彩屏仓补丁list
  • 更新字库步骤
  • 支付宝硬件接入资料

添加电池曲线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
}