emul: Add sbs_gauge emulator
Add an initial bare-bones functionality sbs_gauge emulator that only supports register reads tested by the current sbs_gauge driver tests and what the sbs_driver currently supports. Signed-off-by: Aaron Massey <aaronmassey@google.com>
This commit is contained in:
parent
f2204b552b
commit
c01b4d8106
|
@ -45,6 +45,12 @@ config EMUL_BMI160
|
|||
It supports both I2C and SPI which is why it is not in one of the
|
||||
i2c/ or spi/ directories.
|
||||
|
||||
config EMUL_SBS_GAUGE
|
||||
bool "Emulate an SBS 1.1 compliant smart battery fuel gauge"
|
||||
help
|
||||
It provides readings which follow a simple sequence, thus allowing
|
||||
test code to check that things are working as expected.
|
||||
|
||||
source "subsys/emul/i2c/Kconfig"
|
||||
source "subsys/emul/espi/Kconfig"
|
||||
|
||||
|
|
|
@ -3,3 +3,6 @@
|
|||
# Once we have more than 10 devices we should consider splitting them into
|
||||
# subdirectories to match the drivers/ structure.
|
||||
zephyr_library_sources_ifdef(CONFIG_EMUL_EEPROM_AT2X emul_atmel_at24.c)
|
||||
|
||||
zephyr_include_directories_ifdef(CONFIG_EMUL_SBS_GAUGE ${ZEPHYR_BASE}/drivers/sensor/sbs_gauge)
|
||||
zephyr_library_sources_ifdef(CONFIG_EMUL_SBS_GAUGE emul_sbs_gauge.c)
|
||||
|
|
157
subsys/emul/i2c/emul_sbs_gauge.c
Normal file
157
subsys/emul/i2c/emul_sbs_gauge.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Emulator for SBS 1.1 compliant smart battery fuel gauge.
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT sbs_sbs_gauge
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(sbs_sbs_gauge);
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/emul.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/i2c_emul.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include <sbs_gauge.h>
|
||||
|
||||
/** Run-time data used by the emulator */
|
||||
struct sbs_gauge_emul_data {
|
||||
/* Stub */
|
||||
};
|
||||
|
||||
/** Static configuration for the emulator */
|
||||
struct sbs_gauge_emul_cfg {
|
||||
/** I2C address of emulator */
|
||||
uint16_t addr;
|
||||
};
|
||||
|
||||
static void reg_write(const struct emul *target, int reg, int val)
|
||||
{
|
||||
ARG_UNUSED(target);
|
||||
|
||||
LOG_INF("write %x = %x", reg, val);
|
||||
switch (reg) {
|
||||
default:
|
||||
LOG_INF("Unknown write %x", reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int reg_read(const struct emul *target, int reg)
|
||||
{
|
||||
int val;
|
||||
|
||||
ARG_UNUSED(target);
|
||||
|
||||
switch (reg) {
|
||||
case SBS_GAUGE_CMD_VOLTAGE:
|
||||
case SBS_GAUGE_CMD_AVG_CURRENT:
|
||||
case SBS_GAUGE_CMD_TEMP:
|
||||
case SBS_GAUGE_CMD_ASOC:
|
||||
case SBS_GAUGE_CMD_FULL_CAPACITY:
|
||||
case SBS_GAUGE_CMD_REM_CAPACITY:
|
||||
case SBS_GAUGE_CMD_NOM_CAPACITY:
|
||||
case SBS_GAUGE_CMD_AVG_TIME2EMPTY:
|
||||
case SBS_GAUGE_CMD_AVG_TIME2FULL:
|
||||
case SBS_GAUGE_CMD_CYCLE_COUNT:
|
||||
case SBS_GAUGE_CMD_DESIGN_VOLTAGE:
|
||||
/* Arbitrary stub value. */
|
||||
val = 1;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unknown register 0x%x read", reg);
|
||||
return -EIO;
|
||||
}
|
||||
LOG_INF("read 0x%x = 0x%x", reg, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs,
|
||||
int num_msgs, int addr)
|
||||
{
|
||||
/* Largely copied from emul_bmi160.c */
|
||||
struct sbs_gauge_emul_data *data;
|
||||
unsigned int val;
|
||||
int reg;
|
||||
|
||||
data = target->data;
|
||||
|
||||
__ASSERT_NO_MSG(msgs && num_msgs);
|
||||
|
||||
i2c_dump_msgs("emul", msgs, num_msgs, addr);
|
||||
switch (num_msgs) {
|
||||
case 2:
|
||||
if (msgs->flags & I2C_MSG_READ) {
|
||||
LOG_ERR("Unexpected read");
|
||||
return -EIO;
|
||||
}
|
||||
if (msgs->len != 1) {
|
||||
LOG_ERR("Unexpected msg0 length %d", msgs->len);
|
||||
return -EIO;
|
||||
}
|
||||
reg = msgs->buf[0];
|
||||
|
||||
/* Now process the 'read' part of the message */
|
||||
msgs++;
|
||||
if (msgs->flags & I2C_MSG_READ) {
|
||||
switch (msgs->len - 1) {
|
||||
case 1:
|
||||
val = reg_read(target, reg);
|
||||
msgs->buf[0] = val;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unexpected msg1 length %d", msgs->len);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (msgs->len != 1) {
|
||||
LOG_ERR("Unexpected msg1 length %d", msgs->len);
|
||||
}
|
||||
reg_write(target, reg, msgs->buf[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid number of messages: %d", num_msgs);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_emul_api sbs_gauge_emul_api_i2c = {
|
||||
.transfer = sbs_gauge_emul_transfer_i2c,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up a new SBS_GAUGE emulator (I2C)
|
||||
*
|
||||
* @param emul Emulation information
|
||||
* @param parent Device to emulate (must use sbs_gauge driver)
|
||||
* @return 0 indicating success (always)
|
||||
*/
|
||||
static int emul_sbs_sbs_gauge_init(const struct emul *target, const struct device *parent)
|
||||
{
|
||||
ARG_UNUSED(target);
|
||||
ARG_UNUSED(parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Main instantiation macro. SBS Gauge Emulator only implemented for I2C
|
||||
*/
|
||||
#define SBS_GAUGE_EMUL(n) \
|
||||
static struct sbs_gauge_emul_data sbs_gauge_emul_data_##n; \
|
||||
static const struct sbs_gauge_emul_cfg sbs_gauge_emul_cfg_##n = { \
|
||||
.addr = DT_INST_REG_ADDR(n), \
|
||||
}; \
|
||||
EMUL_DEFINE(emul_sbs_sbs_gauge_init, DT_DRV_INST(n), &sbs_gauge_emul_cfg_##n, \
|
||||
&sbs_gauge_emul_data_##n, &sbs_gauge_emul_api_i2c)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_EMUL)
|
Loading…
Reference in a new issue