#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; }