Skip to content

Commit 5f84be6

Browse files
franckduriezcfriedt
authored andcommitted
driver: fuel_gauge/sy24561: add emulator
Add emulator for fuel gauge SY24561 Signed-off-by: Franck Duriez <[email protected]>
1 parent 8ef13d0 commit 5f84be6

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
zephyr_library_sources(sy24561.c)
2+
3+
zephyr_include_directories_ifdef(CONFIG_EMUL_SY24561 .)
4+
zephyr_library_sources_ifdef(CONFIG_EMUL_SY24561 emul_sy24561.c)

drivers/fuel_gauge/sy24561/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,12 @@ config SY24561
1010
select I2C
1111
help
1212
Enable driver for the silergy sy24561 fuel gauge device.
13+
14+
config EMUL_SY24561
15+
bool "Emulate a SY24561 fuel gauge"
16+
default y
17+
depends on EMUL
18+
depends on SY24561
19+
help
20+
It provides readings which follow a simple sequence, thus allowing
21+
test code to check that things are working as expected.
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright (c) 2025 Romain Paupe <[email protected]>, Franck Duriez <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Emulator for sy24561 fuel gauge
7+
*/
8+
9+
#include <stdint.h>
10+
11+
#include <zephyr/logging/log.h>
12+
13+
#include <zephyr/device.h>
14+
#include <zephyr/drivers/emul.h>
15+
#include <zephyr/drivers/i2c.h>
16+
#include <zephyr/drivers/i2c_emul.h>
17+
#include <zephyr/sys/byteorder.h>
18+
19+
#include "sy24561.h"
20+
21+
#define DT_DRV_COMPAT silergy_sy24561
22+
23+
LOG_MODULE_REGISTER(EMUL_SY24561, CONFIG_FUEL_GAUGE_LOG_LEVEL);
24+
25+
static uint8_t const version = 0x42;
26+
static uint8_t const soc = 75;
27+
static uint16_t const vbat_mV = 3200;
28+
static uint8_t const charging = 1;
29+
30+
/** Static configuration for the emulator */
31+
struct sy24561_emul_cfg {
32+
/** I2C address of emulator */
33+
uint16_t addr;
34+
};
35+
36+
static int emul_sy24561_reg_write(const struct emul *target, uint8_t reg, uint16_t val)
37+
{
38+
return 0;
39+
}
40+
41+
static int emul_sy24561_reg_read(const struct emul *target, uint8_t reg, uint16_t *val)
42+
{
43+
switch (reg) {
44+
case SY24561_REG_VERSION:
45+
*val = version;
46+
break;
47+
case SY24561_REG_SOC:
48+
*val = soc * 0xffff / 100;
49+
break;
50+
case SY24561_REG_STATUS:
51+
*val = charging << 8;
52+
break;
53+
case SY24561_REG_VBAT:
54+
*val = (vbat_mV - 2500) * 0x1000 / 2500;
55+
break;
56+
case SY24561_REG_CONFIG:
57+
*val = 0x3C1C;
58+
break;
59+
case SY24561_REG_RESET:
60+
*val = 0x0333;
61+
break;
62+
case SY24561_REG_POR:
63+
*val = 0xffff;
64+
break;
65+
case SY24561_REG_MODE:
66+
LOG_ERR("Attempt to read write only register 0x%x", reg);
67+
return -EINVAL;
68+
default:
69+
LOG_ERR("Unknown register 0x%x read", reg);
70+
return -EIO;
71+
}
72+
LOG_INF("read 0x%x = 0x%x", reg, *val);
73+
74+
return 0;
75+
}
76+
77+
static int sy24561_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, int num_msgs,
78+
int addr)
79+
{
80+
int ret;
81+
82+
__ASSERT_NO_MSG(msgs && num_msgs);
83+
84+
i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false);
85+
switch (num_msgs) {
86+
case 1:
87+
if (msgs->flags & I2C_MSG_READ) {
88+
LOG_ERR("Unexpected read");
89+
return -EIO;
90+
}
91+
92+
if (msgs->len != 3) {
93+
LOG_ERR("Unexpected msg0 length %d", msgs->len);
94+
return -EIO;
95+
}
96+
97+
ret = emul_sy24561_reg_write(target, *msgs->buf, sys_get_be16(msgs->buf + 1));
98+
if (ret) {
99+
LOG_ERR("emul_sy24561_reg_write returned %d", ret);
100+
}
101+
break;
102+
case 2:
103+
if (msgs->flags & I2C_MSG_READ) {
104+
LOG_ERR("Unexpected read");
105+
return -EIO;
106+
}
107+
if (msgs->len != 1) {
108+
LOG_ERR("Unexpected msg0 length %d", msgs->len);
109+
return -EIO;
110+
}
111+
112+
if (msgs[1].flags & I2C_MSG_WRITE) {
113+
LOG_ERR("Unexpected write");
114+
return -EIO;
115+
}
116+
if (msgs[1].len != 2) {
117+
LOG_ERR("Unexpected msg1 length %d", msgs[1].len);
118+
return -EIO;
119+
}
120+
121+
uint16_t val;
122+
123+
ret = emul_sy24561_reg_read(target, *msgs->buf, &val);
124+
if (ret) {
125+
LOG_ERR("emul_sy24561_reg_read returned %d", ret);
126+
return ret;
127+
}
128+
129+
sys_put_be16(val, msgs->buf);
130+
break;
131+
default:
132+
LOG_ERR("Invalid number of messages: %d", num_msgs);
133+
return -EIO;
134+
}
135+
136+
return ret;
137+
}
138+
139+
static const struct i2c_emul_api sy24561_emul_api_i2c = {
140+
.transfer = sy24561_emul_transfer_i2c,
141+
};
142+
143+
static int emul_sy24561_init(const struct emul *target, const struct device *parent)
144+
{
145+
ARG_UNUSED(target);
146+
ARG_UNUSED(parent);
147+
148+
return 0;
149+
}
150+
151+
#define SY24561_EMUL(n) \
152+
static const struct sy24561_emul_cfg sy24561_emul_cfg_##n = { \
153+
.addr = DT_INST_REG_ADDR(n), \
154+
}; \
155+
EMUL_DT_INST_DEFINE(n, emul_sy24561_init, NULL, &sy24561_emul_cfg_##n, \
156+
&sy24561_emul_api_i2c, NULL)
157+
158+
DT_INST_FOREACH_STATUS_OKAY(SY24561_EMUL)

0 commit comments

Comments
 (0)