/* 五路输出电压的换算与设定。与硬件无关,宿主机与 ESP32-S3 上编的是同一份。 */ #include "rail.h" #include #include #include "dac63204.h" #include "phonerail.h" /* 五路数与 DAC 侧的映射表必须是同一个数 —— 分家的那天就是错一路的那天。 */ _Static_assert(PHONERAIL_RAIL_COUNT == DAC63204_RAIL_COUNT, "五路数对不上"); bool rail_mv_in_range(int mv) { return mv >= RAIL_MV_MIN && mv <= RAIL_MV_MAX; } uint16_t rail_mv_to_code(int mv) { assert(rail_mv_in_range(mv)); /* 越界要在 rail_set_mv() 里被拒掉,不该走到这儿 */ /* code = (Vout0 − Vout) / 486416 µV × 4096,四舍五入。 **减法在这里**:Vout 越低,差越大,码越大 —— 反向关系只此一处。 */ int64_t diff_uv = (int64_t)RAIL_VOUT0_UV - (int64_t)mv * 1000; int64_t code = (diff_uv * DAC63204_CODE_SPAN + RAIL_DAC_SPAN_UV / 2) / RAIL_DAC_SPAN_UV; if (code < 0) { code = 0; } if (code > DAC63204_CODE_MAX) { code = DAC63204_CODE_MAX; } return (uint16_t)code; } int rail_code_to_mv(uint16_t code) { int64_t drop_uv = ((int64_t)code * RAIL_DAC_SPAN_UV + DAC63204_CODE_SPAN / 2) / DAC63204_CODE_SPAN; int64_t uv = (int64_t)RAIL_VOUT0_UV - drop_uv; return (int)((uv + 500) / 1000); } int32_t rail_code_to_vd_uv(uint16_t code) { return dac63204_code_to_uv(code); } hal_err_t rail_volt_init_one(uint8_t addr) { hal_err_t err = dac63204_probe(addr); if (err != HAL_OK) { return err; } /* init 自己就把用到的通道写成 safe 了(上电之前写,见 dac63204_init 的 ③)。 */ return dac63204_init(addr, rail_mv_to_code(RAIL_MV_SAFE)); } hal_err_t rail_volt_init(void) { /* ⚠️ 一片失败**不放弃另一片**(A15):U6 不应答时 U7 那两路照样该被初始化, 而不是也停在 NVM 默认值上 —— 那样一片坏件就「降级」了五路。 */ hal_err_t first = HAL_OK; for (int i = 0; i < DAC63204_COUNT; i++) { const hal_err_t err = rail_volt_init_one(dac63204_all_addr[i]); if (err != HAL_OK && first == HAL_OK) { first = err; } } return first; } /* 五路设定值的影子(契约见 rail.h)。初值就是 DAC 的 NVM 出厂默认, 所以 `rail_volt_init()` 跑之前它也说的是实话。 */ static int s_set_mv[PHONERAIL_RAIL_COUNT] = { RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE, RAIL_MV_SAFE, }; _Static_assert(PHONERAIL_RAIL_COUNT == 5, "s_set_mv 的初值列表要跟着改"); int rail_setpoint_mv(int rail) { if (rail < 1 || rail > PHONERAIL_RAIL_COUNT) { return RAIL_MV_SAFE; } return s_set_mv[rail - 1]; } void rail_setpoint_reset(void) { for (int i = 0; i < PHONERAIL_RAIL_COUNT; i++) { s_set_mv[i] = RAIL_MV_SAFE; } } hal_err_t rail_set_mv(int rail, int mv) { if (rail < 1 || rail > PHONERAIL_RAIL_COUNT) { return HAL_ERR_ARG; } if (!rail_mv_in_range(mv)) { return HAL_ERR_ARG; /* SR-13。TODO(A11):这里要记一条事件 */ } const hal_err_t err = dac63204_write_code(dac63204_rail_addr(rail), dac63204_rail_ch(rail), rail_mv_to_code(mv)); if (err == HAL_OK) { /* 记的是**请求的 mV**,不是 `rail_code_to_mv(码)` —— 两者差不到一个码 (118.75 µV),但 A10 的判据是拿它当「设定值」用的,回读换算会让 「设成 3900」在判据眼里变成 3899,白白吃掉 1 mV 的余量。 */ s_set_mv[rail - 1] = mv; } return err; } hal_err_t rail_get_mv(int rail, int *mv) { if (rail < 1 || rail > PHONERAIL_RAIL_COUNT || mv == NULL) { return HAL_ERR_ARG; } uint16_t code = 0; hal_err_t err = dac63204_read_code(dac63204_rail_addr(rail), dac63204_rail_ch(rail), &code); if (err != HAL_OK) { return err; } *mv = rail_code_to_mv(code); return HAL_OK; }