291 lines
9.8 KiB
C
291 lines
9.8 KiB
C
#include "charger_port.h"
|
|
#include "adc.h"
|
|
#include "adc_porting.h"
|
|
#include "charger_api.h"
|
|
#include "cmsis_os2.h"
|
|
#include "common_pm.h"
|
|
#include "gpio.h"
|
|
#include "pinctrl.h"
|
|
#include "pm.h"
|
|
#include "power_display_service.h"
|
|
#include "sys_config.h"
|
|
#include "tcxo.h"
|
|
|
|
#define ENABLE_PRINT_INFO 0
|
|
#if ENABLE_PRINT_INFO
|
|
#define static_print_info(...) sys_chrg_log_i(__VA_ARGS__) // 一般信息打印宏控制
|
|
#define static_print_warn(...) sys_chrg_log_w(__VA_ARGS__) // 警告信息打印一般常开
|
|
#define static_print_error(...) sys_chrg_log_e(__VA_ARGS__) // 错误信息打印一般常开
|
|
#else
|
|
#define static_print_info(...)
|
|
#define static_print_warn(...)
|
|
#define static_print_error(...)
|
|
#endif
|
|
|
|
#ifndef ARRAY_SIZE
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
#endif
|
|
|
|
#define CHARGER_STATUS_PORT_ADC_CHANNEL ADC_CHANNEL_0
|
|
#define CHARGER_PORT_ADC_CHANNEL ADC_CHANNEL_2
|
|
#define CHARGER_ADC_CLOCK ADC_CLOCK_500KHZ
|
|
#define CHARGING_TIME_INDEX_OFTIME 30
|
|
#define TESTADC_DISACRD_DELAY_MS 5
|
|
#define adc_trans_sytick_to_voltage_without_auto_scan(x) ((float)(((float)(x) * 18) / 40960))
|
|
#define CHARGER_TASK_TIMER_PERIOD (1000 * 30)
|
|
#define ADC_SAMPLE_COUNT 10
|
|
#define ADC_DISCARD_COUNT 10
|
|
|
|
typedef struct
|
|
{
|
|
signed int (*func_event_handler)(void *param);
|
|
void *param;
|
|
void (*func_event_debug)(char *str, ...);
|
|
void *payload;
|
|
} charger_driver_event_info_t;
|
|
|
|
// signed int charger_duty_task(void *arg);
|
|
|
|
static bool g_adc_init_flag = false;
|
|
static float g_average_value = 0.0;
|
|
static float g_status_value = 0.0;
|
|
static const float g_charger_max_power = 350;
|
|
static const float g_charger_average_current = 250;
|
|
static osTimerId_t g_charger_handle = NULL;
|
|
static float g_charging_time_curve_voltage = 4.4;
|
|
static uint16_t g_power = 0;
|
|
static uint32_t g_charging_time_count = 0;
|
|
|
|
#pragma pack(4)
|
|
struct battery_curve
|
|
{
|
|
float voltage;
|
|
uint16_t power_percent;
|
|
};
|
|
#pragma pack()
|
|
|
|
// 放电曲线
|
|
static struct battery_curve g_dischargeCurve[] = {
|
|
{4.2580, 100}, {4.2465, 99}, {4.2384, 98}, {4.2276, 97}, {4.2170, 96},
|
|
{4.2091, 95}, {4.1984, 94}, {4.1903, 93}, {4.1797, 92}, {4.1692, 91},
|
|
{4.1587, 90}, {4.1508, 89}, {4.1400, 88}, {4.1295, 87}, {4.1216, 86},
|
|
{4.1113, 85}, {4.1007, 84}, {4.0928, 83}, {4.0826, 82}, {4.0720, 81},
|
|
{4.0645, 80}, {4.0538, 79}, {4.0433, 78}, {4.0356, 77}, {4.0251, 76},
|
|
{4.0177, 75}, {4.0087, 74}, {4.0003, 73}, {3.9943, 72}, {3.9869, 71},
|
|
{3.9788, 70}, {3.9665, 69}, {3.9515, 68}, {3.9362, 67}, {3.9256, 66},
|
|
{3.9131, 65}, {3.9030, 64}, {3.8965, 63}, {3.8888, 62}, {3.8820, 61},
|
|
{3.8770, 60}, {3.8710, 59}, {3.8650, 58}, {3.8599, 57}, {3.8533, 56},
|
|
{3.8467, 55}, {3.8418, 54}, {3.8350, 53}, {3.8290, 52}, {3.8239, 51},
|
|
{3.8173, 50}, {3.8117, 49}, {3.8070, 48}, {3.8012, 47}, {3.7954, 46},
|
|
{3.7913, 45}, {3.7855, 44}, {3.7805, 43}, {3.7764, 42}, {3.7715, 41},
|
|
{3.7665, 40}, {3.7624, 39}, {3.7575, 38}, {3.7534, 37}, {3.7498, 36},
|
|
{3.7452, 35}, {3.7406, 34}, {3.7373, 33}, {3.7327, 32}, {3.7281, 31},
|
|
{3.7253, 30}, {3.7211, 29}, {3.7179, 28}, {3.7137, 27}, {3.7097, 26},
|
|
{3.7057, 25}, {3.7026, 24}, {3.6989, 23}, {3.6952, 22}, {3.6921, 21},
|
|
{3.6882, 20}, {3.6843, 19}, {3.6812, 18}, {3.6771, 17}, {3.6738, 16},
|
|
{3.6690, 15}, {3.6642, 14}, {3.6603, 13}, {3.6548, 12}, {3.6492, 11},
|
|
{3.6446, 10}, {3.6382, 9}, {3.6324, 8}, {3.6288, 7}, {3.6253, 6},
|
|
{3.6222, 5}, {3.6198, 4}, {3.6159, 3}, {3.6108, 2}, {3.6053, 1},
|
|
{3.5000, 0},
|
|
};
|
|
|
|
static float find_power_in_discharge_curve(float voltage)
|
|
{
|
|
if (voltage <= 0) {
|
|
return 0;
|
|
}
|
|
const int size = ARRAY_SIZE(g_dischargeCurve);
|
|
int i;
|
|
|
|
for(i = 0; i < (size-1); i++){
|
|
if(g_dischargeCurve[i].voltage <= voltage)
|
|
break;
|
|
}
|
|
|
|
return (g_dischargeCurve[i].power_percent*100);
|
|
|
|
}
|
|
|
|
uint16_t get_power_value(void) { return g_power; }
|
|
|
|
float get_status_value(void) { return g_status_value; }
|
|
|
|
// static void charger_task_callback(uintptr_t data)
|
|
// {
|
|
// uint32_t ret = 0;
|
|
// static charger_driver_event_info_t g_msg_data = {
|
|
// .func_event_handler = charger_duty_task,
|
|
// .param = NULL,
|
|
// .func_event_debug = NULL,
|
|
// .payload = NULL,
|
|
// };
|
|
// static unsigned int g_msg_size = sizeof(charger_driver_event_info_t);
|
|
// ret = osal_msg_queue_write_copy(tjd_task_driver_event_get_queue_id(), &g_msg_data, g_msg_size, 0);
|
|
// if (ret != 0) {
|
|
// static_print_error("msg send failed! err=0x%x", ret);
|
|
// }
|
|
// }
|
|
|
|
uint32_t charger_host_peripheral_init(void)
|
|
{
|
|
uint32_t ret = 0;
|
|
if (g_adc_init_flag) {
|
|
static_print_info("charger host peripheral already init");
|
|
return CHARGER_SUCC;
|
|
}
|
|
g_adc_init_flag = true;
|
|
// g_charger_handle = osTimerNew((osTimerFunc_t)charger_task_callback, osTimerPeriodic, 0, NULL);
|
|
// if (g_charger_handle == NULL) {
|
|
// static_print_error("create charger timer failed");
|
|
// return CHARGER_FAIL;
|
|
// }
|
|
return CHARGER_SUCC;
|
|
}
|
|
|
|
uint32_t charger_host_peripheral_deinit(void)
|
|
{
|
|
uint32_t ret = 0;
|
|
if (!g_adc_init_flag) {
|
|
static_print_info("charger host peripheral not init");
|
|
return CHARGER_SUCC;
|
|
}
|
|
g_adc_init_flag = false;
|
|
|
|
return CHARGER_SUCC;
|
|
}
|
|
|
|
static float adc_stick_transfer_voltage(uint16_t stick) { return adc_trans_sytick_to_voltage_without_auto_scan(stick); }
|
|
|
|
static bool adc_get_sample_result(float *voltage, uint8_t channel)
|
|
{
|
|
uint32_t sample_number = ADC_SAMPLE_COUNT;
|
|
uint32_t discard_number = ADC_DISCARD_COUNT;
|
|
uint32_t stick = 0;
|
|
uint32_t sample_zero_count = 0;
|
|
const power_display_svr_api_t *display_api = power_display_svr_get_api();
|
|
|
|
/* after channel is enabled, sample result is error in previous samplings, need to be discarded */
|
|
for (uint32_t i = 0; i < discard_number; i++) {
|
|
uint32_t irq_sts = osal_irq_lock();
|
|
uapi_adc_manual_sample(ADC_CHANNEL_NONE);
|
|
uapi_tcxo_delay_ms((uint64_t)TESTADC_DISACRD_DELAY_MS);
|
|
osal_irq_restore(irq_sts);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < sample_number; i++) {
|
|
uint32_t irq_sts = osal_irq_lock();
|
|
uint32_t sample_result = (uint32_t)uapi_adc_manual_sample(ADC_CHANNEL_NONE);
|
|
uapi_tcxo_delay_ms((uint64_t)TESTADC_DISACRD_DELAY_MS);
|
|
// osal_printk("sample_result = %u.\r\n", sample_result);
|
|
if (sample_result == 0) {
|
|
sample_zero_count++;
|
|
}
|
|
stick += sample_result;
|
|
osal_irq_restore(irq_sts);
|
|
}
|
|
sample_number -= sample_zero_count;
|
|
if (sample_number > 0) {
|
|
stick = (stick / sample_number);
|
|
} else {
|
|
*voltage = 0;
|
|
return false;
|
|
}
|
|
|
|
float val = adc_stick_transfer_voltage((uint16_t)stick);
|
|
*voltage = val * 12.2 / 2.2;
|
|
/* 补偿数值 */
|
|
if (display_api->get_screen_state() == SCREEN_OFF) {
|
|
*voltage = *voltage + 0.02;
|
|
} else {
|
|
*voltage = *voltage + 0.04 ;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static uint32_t adc_manual_sample(float *voltage, adc_channel_t channel)
|
|
{
|
|
uapi_pm_add_sleep_veto(PM_ID_CHARGER);
|
|
uapi_adc_init(CHARGER_ADC_CLOCK);
|
|
|
|
uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, true);
|
|
uint32_t ret = uapi_adc_open_channel(channel);
|
|
if (ret != CHARGER_SUCC) {
|
|
uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, false);
|
|
uapi_adc_deinit();
|
|
uapi_pm_remove_sleep_veto(PM_ID_CHARGER);
|
|
static_print_error("uapi_adc_open_channel failed : %d\r\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
if (!adc_get_sample_result(voltage, channel)) {
|
|
static_print_info("adc get sample result failed.");
|
|
*voltage = 0;
|
|
}
|
|
|
|
uapi_adc_close_channel(channel);
|
|
uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, false);
|
|
uapi_pm_remove_sleep_veto(PM_ID_CHARGER);
|
|
uapi_adc_deinit();
|
|
|
|
return CHARGER_SUCC;
|
|
}
|
|
|
|
uint32_t charger_status_sample(void) { return adc_manual_sample(&g_status_value, CHARGER_STATUS_PORT_ADC_CHANNEL); }
|
|
|
|
// signed int charger_duty_task(void *arg)
|
|
// {
|
|
// if (!tjd_driver_charger_get_ops()->get_chargng_status()) {
|
|
// osTimerStop(g_charger_handle);
|
|
// return 0;
|
|
// }
|
|
// const uint32_t size = ARRAY_SIZE(g_chargingTimeCurve);
|
|
// const uint32_t time = g_charging_time_count * CHARGER_TASK_TIMER_PERIOD;
|
|
// const uint32_t index = time / CHARGING_TIME_INDEX_OFTIME;
|
|
// double power = 0;
|
|
// if (index < size) {
|
|
// power = g_chargingTimeCurve[index].power / g_charger_max_power;
|
|
// } else {
|
|
// power = g_chargingTimeCurve[size - 1].power / g_charger_max_power;
|
|
// }
|
|
|
|
// ++g_charging_time_count;
|
|
// return 0;
|
|
// }
|
|
|
|
uint32_t charger_sample(void)
|
|
{
|
|
uint32_t ret = adc_manual_sample(&g_average_value, CHARGER_PORT_ADC_CHANNEL);
|
|
if (ret != CHARGER_SUCC) {
|
|
return ret;
|
|
}
|
|
|
|
uint16_t power = find_power_in_discharge_curve(g_average_value);
|
|
uint16_t percent = sql_setting_get_battery_percent();
|
|
if (tjd_service_charger_get_charger_status())
|
|
{
|
|
percent += g_charger_average_current * 10/3600/g_charger_max_power*10000; //CHARGER_SCAN_TIME = 10s
|
|
if(percent > 10000)
|
|
{
|
|
percent = 10000;
|
|
}
|
|
}else{
|
|
if(percent > power)
|
|
{
|
|
percent = (percent+power)/2;
|
|
}else if((percent < 500)&&(power > 3000))
|
|
{
|
|
//适用于异常重启/死机重启
|
|
percent = power;
|
|
}
|
|
}
|
|
|
|
sql_setting_set_battery_percent(percent);
|
|
g_power = min(power, percent);
|
|
|
|
static_print_info("power = %d percent = %d", power, percent);
|
|
static_print_info("g_power [%d] g_average_value[%f]", g_power, g_average_value);
|
|
|
|
return CHARGER_SUCC;
|
|
}
|