137 lines
3.9 KiB
C
137 lines
3.9 KiB
C
|
|
#include "basic_include.h"
|
|||
|
|
#include "dev/adc/hgadc_v0.h"
|
|||
|
|
#ifdef PIN_FROM_PARAM
|
|||
|
|
#include "pin_param.h"
|
|||
|
|
#endif
|
|||
|
|
#include "lib/lmac/lmac.h"
|
|||
|
|
|
|||
|
|
struct bat_det_priv {
|
|||
|
|
struct os_work work;
|
|||
|
|
struct hgadc_v0 *adc_dev;
|
|||
|
|
uint32_t bat_det_io;
|
|||
|
|
float vol;
|
|||
|
|
uint32_t _update_fme_adc_val;
|
|||
|
|
uint8_t level;
|
|||
|
|
uint8_t get_value;
|
|||
|
|
uint32_t adc_raw;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct bat_det_priv *g_bat_det_priv_data = NULL;
|
|||
|
|
|
|||
|
|
static int32 bat_detect_work(struct os_work *work)
|
|||
|
|
{
|
|||
|
|
#if WIFI_FEM_CHIP
|
|||
|
|
void * ops = NULL;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv *)work;
|
|||
|
|
|
|||
|
|
uint32_t adc_value = 0;
|
|||
|
|
|
|||
|
|
adc_get_value((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io, &adc_value);
|
|||
|
|
|
|||
|
|
bat_det_priv_data->adc_raw = adc_value;
|
|||
|
|
bat_det_priv_data->get_value = 1;
|
|||
|
|
|
|||
|
|
bat_det_priv_data->vol = (float)adc_value * 3 / 2048 * 2;
|
|||
|
|
|
|||
|
|
bat_det_priv_data->_update_fme_adc_val = adc_value * 3 * 2 / 5;
|
|||
|
|
if (bat_det_priv_data->_update_fme_adc_val > 2047) {
|
|||
|
|
bat_det_priv_data->_update_fme_adc_val = 2047;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
os_printf("---- battery adc:%d vol:%.2fV _update_fme_adc_val:%.2fV adc_val:%d----\n", adc_value, (float)adc_value * 3 / 2048 * 2, (float)bat_det_priv_data->_update_fme_adc_val * 5 / 2048, bat_det_priv_data->_update_fme_adc_val);
|
|||
|
|
|
|||
|
|
// bat_det_priv_data->vol = 4;
|
|||
|
|
#if WIFI_FEM_CHIP
|
|||
|
|
lmac_update_fem_voltage(ops, (uint32_t)(5 * (1 << 10)));
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
os_run_work_delay(&bat_det_priv_data->work, 5000);
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int bat_get_level()
|
|||
|
|
{
|
|||
|
|
/* 如果未初始化,返回0 */
|
|||
|
|
if (!g_bat_det_priv_data) {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 使用 ADC 阈值表
|
|||
|
|
阈值单位为 ADC 读数,避免浮点运算。加入整型 hysteresis 防跳变。 */
|
|||
|
|
uint8_t res = 0;
|
|||
|
|
static uint8_t first_count = 1;
|
|||
|
|
static const uint16_t thresholds_adc[] = {1125, 1185, 1245, 1305, 1365};
|
|||
|
|
const int max_level = sizeof(thresholds_adc) / sizeof(thresholds_adc[0]);
|
|||
|
|
const uint16_t hysteresis_adc = 10; /* ADC 单位去抖 */
|
|||
|
|
|
|||
|
|
uint32_t adc = g_bat_det_priv_data->adc_raw;
|
|||
|
|
|
|||
|
|
/* 计算候选等级 */
|
|||
|
|
int cand = 0;
|
|||
|
|
if(g_bat_det_priv_data->get_value == 0) {
|
|||
|
|
return 4;
|
|||
|
|
}
|
|||
|
|
while (cand < max_level && adc > thresholds_adc[cand]) {
|
|||
|
|
cand++;
|
|||
|
|
}
|
|||
|
|
if (cand > (max_level - 1)) {
|
|||
|
|
cand = max_level - 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (first_count) {
|
|||
|
|
first_count = 0;
|
|||
|
|
g_bat_det_priv_data->level = (uint8_t)cand;
|
|||
|
|
return cand;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int prev = (int)g_bat_det_priv_data->level;
|
|||
|
|
if (cand == prev) {
|
|||
|
|
return (uint8_t)prev;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cand > prev) {
|
|||
|
|
/* 上升:需要超过阈值 + hysteresis 才更新 */
|
|||
|
|
if (adc >= (uint32_t)thresholds_adc[prev] + hysteresis_adc) {
|
|||
|
|
g_bat_det_priv_data->level = (uint8_t)cand;
|
|||
|
|
res = (uint8_t)cand;
|
|||
|
|
} else {
|
|||
|
|
res = (uint8_t)prev;
|
|||
|
|
}
|
|||
|
|
} else { /* cand < prev */
|
|||
|
|
/* 下降:需要低于阈值 - hysteresis 才更新 */
|
|||
|
|
if (adc <= (uint32_t)thresholds_adc[prev] - hysteresis_adc) {
|
|||
|
|
g_bat_det_priv_data->level = (uint8_t)cand;
|
|||
|
|
res = (uint8_t)cand;
|
|||
|
|
} else {
|
|||
|
|
res = (uint8_t)prev;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return res;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void bat_ad_init()
|
|||
|
|
{
|
|||
|
|
struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv*)os_zalloc(sizeof(struct bat_det_priv));
|
|||
|
|
|
|||
|
|
if (!bat_det_priv_data) {
|
|||
|
|
os_printf("bat ad init err!!!!!!!!!!!!!\n");
|
|||
|
|
return ;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
g_bat_det_priv_data = bat_det_priv_data;
|
|||
|
|
|
|||
|
|
bat_det_priv_data->adc_dev = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
|
|||
|
|
bat_det_priv_data->bat_det_io = MACRO_PIN(BAT_ADC_IO);
|
|||
|
|
|
|||
|
|
adc_open((struct adc_device *)bat_det_priv_data->adc_dev);
|
|||
|
|
|
|||
|
|
gpio_set_mode(bat_det_priv_data->bat_det_io, GPIO_PULL_NONE, GPIO_PULL_LEVEL_NONE);
|
|||
|
|
|
|||
|
|
adc_add_channel((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io);
|
|||
|
|
|
|||
|
|
OS_WORK_INIT(&bat_det_priv_data->work, bat_detect_work, 0);
|
|||
|
|
os_run_work_delay(&bat_det_priv_data->work, 1000);
|
|||
|
|
}
|