fix: sensor: add factory test driver for ak09919c.

CHAMPION-139

Add read id and selftest interface in ioctl, it will
be called in the factory test. Fix some bugs in driver.

Change-Id: Ie57a78ec2c2fee65efdb5f8bd7073f9a8c788bb8
Signed-off-by: xiatian6 <xiatian6@xiaomi.com>
This commit is contained in:
xiatian6 2021-09-30 16:32:16 +08:00
parent b82c943d92
commit aaf9d3c760

View file

@ -26,6 +26,7 @@
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <nuttx/nuttx.h>
#include <nuttx/wqueue.h>
@ -37,69 +38,108 @@
* Pre-processor Definitions
****************************************************************************/
#define AK09919C_DEVID 0x0E48 /* Device ID. */
#define AK09919C_DEVID 0x0E48 /* Device ID. */
/* Mag resolution. */
#define AK09919C_RESOLUTION 0.15f /* uT/LSB. */
#define AK09919C_RESOLUTION 0.15f /* uT/LSB. */
/* default ODR */
#define AK09919C_DEFAULT_ODR 20000 /* default 50 ms */
#define AK09919C_DEFAULT_ODR 20000 /* default 50 ms */
/* Register address. */
#define AK09919C_REG_WIA1 0x00 /* Company ID. */
#define AK09919C_REG_WIA2 0x01 /* Device ID. */
#define AK09919C_REG_ST1 0x10 /* Status 1 register. */
#define AK09919C_REG_HXH 0x11 /* X-axis data high byte. */
#define AK09919C_REG_HXL 0x12 /* X-axis data low byte. */
#define AK09919C_REG_HYH 0x13 /* Y-axis data high byte. */
#define AK09919C_REG_HYL 0x14 /* Y-axis data low byte. */
#define AK09919C_REG_HZH 0x15 /* Z-axis data high byte. */
#define AK09919C_REG_HZL 0x16 /* Z-axis data low byte. */
#define AK09919C_REG_TMPS 0x17 /* Dummy. */
#define AK09919C_REG_ST2 0x18 /* Status 2 register. */
#define AK09919C_REG_CNTL1 0x30 /* Control settings 1 register. */
#define AK09919C_REG_CNTL2 0x31 /* Control settings 2 register. */
#define AK09919C_REG_CNTL3 0x32 /* Control settings 3 register. */
#define AK09919C_REG_WIA1 0x00 /* Company ID. */
#define AK09919C_REG_WIA2 0x01 /* Device ID. */
#define AK09919C_REG_ST1 0x10 /* Status 1 register. */
#define AK09919C_REG_HXH 0x11 /* X-axis data high byte. */
#define AK09919C_REG_HXL 0x12 /* X-axis data low byte. */
#define AK09919C_REG_HYH 0x13 /* Y-axis data high byte. */
#define AK09919C_REG_HYL 0x14 /* Y-axis data low byte. */
#define AK09919C_REG_HZH 0x15 /* Z-axis data high byte. */
#define AK09919C_REG_HZL 0x16 /* Z-axis data low byte. */
#define AK09919C_REG_TMPS 0x17 /* Dummy. */
#define AK09919C_REG_ST2 0x18 /* Status 2 register. */
#define AK09919C_REG_CNTL1 0x30 /* Control settings 1 register. */
#define AK09919C_REG_CNTL2 0x31 /* Control settings 2 register. */
#define AK09919C_REG_CNTL3 0x32 /* Control settings 3 register. */
/* Noise Suppression Filter. */
#define AK09919C_NSF_NONE 0x00 /* No noise suppression filter. */
#define AK09919C_NSF_LOW 0x01 /* Low noise suppression filter. */
#define AK09919C_NSF_MIDDLE 0x02 /* Middle noise suppression filter. */
#define AK09919C_NSF_HIGH 0x03 /* High noise suppression filter. */
#define AK09919C_NSF_NONE 0x00 /* No noise suppression filter. */
#define AK09919C_NSF_LOW 0x01 /* Low noise suppression filter. */
#define AK09919C_NSF_MIDDLE 0x02 /* Middle noise suppression filter. */
#define AK09919C_NSF_HIGH 0x03 /* High noise suppression filter. */
/* Power mode. */
#define AK09919C_POWER_DOWN_MODE 0x00 /* Powerdown mode(default). */
#define AK09919C_SINGLESHOT_MODE 0x01 /* Single-shot mode. */
#define AK09919C_CONTINUOUS_MODE1 0x02 /* Continuous conversion mode 1. */
#define AK09919C_CONTINUOUS_MODE2 0x04 /* Continuous conversion mode 2. */
#define AK09919C_CONTINUOUS_MODE3 0x06 /* Continuous conversion mode 3. */
#define AK09919C_CONTINUOUS_MODE4 0x08 /* Continuous conversion mode 4. */
#define AK09919C_CONTINUOUS_MODE5 0x0E /* Continuous conversion mode 5. */
#define AK09919C_SELF_TEST_MODE 0x10 /* Self test mode. */
#define AK09919C_POWER_DOWN_MODE 0x00 /* Powerdown mode(default). */
#define AK09919C_SINGLESHOT_MODE 0x01 /* Single-shot mode. */
#define AK09919C_CONTINUOUS_MODE1 0x02 /* Continuous conversion mode 1. */
#define AK09919C_CONTINUOUS_MODE2 0x04 /* Continuous conversion mode 2. */
#define AK09919C_CONTINUOUS_MODE3 0x06 /* Continuous conversion mode 3. */
#define AK09919C_CONTINUOUS_MODE4 0x08 /* Continuous conversion mode 4. */
#define AK09919C_CONTINUOUS_MODE5 0x0E /* Continuous conversion mode 5. */
#define AK09919C_SELF_TEST_MODE 0x10 /* Self test mode. */
/* single mode register value threshold. */
#define AK09919C_LOLIMIT_SNG_ST1 1 /* low limit of st1 in single mode. */
#define AK09919C_HILIMIT_SNG_ST1 1 /* high limit of st1 in single mode. */
#define AK09919C_LOLIMIT_SNG_HX -32751 /* low limit of x-axis in single mode. */
#define AK09919C_HILIMIT_SNG_HX 32751 /* high limit of x-axis in single mode. */
#define AK09919C_LOLIMIT_SNG_HY -32751 /* low limit of y-axis in single mode. */
#define AK09919C_HILIMIT_SNG_HY 32751 /* high limit of y-axis in single mode. */
#define AK09919C_LOLIMIT_SNG_HZ -32751 /* low limit of z-axis in single mode. */
#define AK09919C_HILIMIT_SNG_HZ 32751 /* high limit of z-axis in single mode. */
#define AK09919C_LOLIMIT_SNG_ST2 4 /* low limit of st2 in single mode. */
#define AK09919C_HILIMIT_SNG_ST2 116 /* high limit of st2 in single mode. */
/* selftest mode register value threshold. */
#define AK09919C_LOLIMIT_SLF_ST1 1 /* low limit of st1 in selftest mode. */
#define AK09919C_HILIMIT_SLF_ST1 1 /* high limit of st1 in selftest mode. */
#define AK09919C_LOLIMIT_SLF_HX -200 /* low limit of x-axis in selftest mode. */
#define AK09919C_HILIMIT_SLF_HX 200 /* high limit of x-axis in selftest mode. */
#define AK09919C_LOLIMIT_SLF_HY -200 /* low limit of y-axis in selftest mode. */
#define AK09919C_HILIMIT_SLF_HY 200 /* high limit of y-axis in selftest mode. */
#define AK09919C_LOLIMIT_SLF_HZ -1000 /* low limit of z-axis in selftest mode. */
#define AK09919C_HILIMIT_SLF_HZ -150 /* high limit of z-axis in selftest mode. */
#define AK09919C_LOLIMIT_SLF_ST2 4 /* low limit of st2 in selftest mode. */
#define AK09919C_HILIMIT_SLF_ST2 116 /* high limit of st2 in selftest mode. */
/* Factory test instructions. */
#define AK09919C_SIMPLE_CHECK 0x00 /* Simple communication check. */
#define AK09919C_FULL_CHECK 0x01 /* Fully functional check. */
/* Reset control bit. */
#define AK09919C_SOFT_RESET 0x01
/* Device delay(us) control. */
#define AK09919C_SOFT_RESET_DELAY 1000 /* Soft reset delay time(us). */
#define AK09919C_MODE_SWITCH_DELAY 8000 /* Mode switching delay time(us). */
/* Noise suppresion level control bit. */
#define AK09919C_NOISE_SUPPRESION 0x60
#define SET_BITSLICE(s, v, offset, mask) \
do \
{ \
s &= mask; \
s |= (v << offset) & mask; \
} \
while(0) \
#define SET_BITSLICE(s, v, offset, mask) \
do \
{ \
s &= mask; \
s |= (v << offset) & mask; \
} \
while(0) \
#define MAKE_S16(u8h, u8l) \
(int16_t)(((uint16_t)(u8h) << 8) | (uint16_t)(u8l))
#define MAKE_S16(u8h, u8l) \
(int16_t)(((uint16_t)(u8h) << 8) | (uint16_t)(u8l))
#define PARAMETER_VERIFY(data, lolimit, hilimit) \
( data >= lolimit && data <= hilimit ) ? 0 : -EINVAL
/****************************************************************************
* Private Type Definitions
@ -109,22 +149,53 @@ while(0) \
struct ak09919c_dev_s
{
struct sensor_lowerhalf_s lower; /* The struct of lower half driver. */
FAR struct ak09919c_config_s *config; /* The board config function. */
uint64_t start_timestamp; /* Start timestamp(us). */
uint64_t sample_count; /* The count of sampling */
bool activated; /* Sensor working state. */
unsigned int interval; /* Sensor acquisition interval. */
uint8_t workmode; /* Sensor work mode. */
struct work_s work; /* Work queue for reading data. */
struct sensor_lowerhalf_s lower; /* The struct of lower half driver. */
FAR struct ak09919c_config_s *config; /* The board config function. */
uint64_t start_timestamp; /* Start timestamp(us). */
uint64_t sample_count; /* The count of sampling */
bool activated; /* Sensor working state. */
unsigned int interval; /* Sensor acquisition interval. */
uint8_t workmode; /* Sensor work mode. */
struct work_s work; /* Work queue for reading data. */
};
/* Structure for ak09919C odr. */
struct ak09919c_odr_s
{
uint8_t regval; /* the data of register */
unsigned int odr; /* the unit is us */
uint8_t regval; /* the data of register. */
unsigned int odr; /* the unit is us. */
};
/* Structure for ak09919c data threshold. */
struct ak09919c_threshold_s
{
uint8_t st1_lolimit; /* low limit of st1. */
uint8_t st1_hilimit; /* high limit of st1. */
uint8_t st2_lolimit; /* low limit of st2. */
uint8_t st2_hilimit; /* high limit of st2. */
int xdata_lolimit; /* low limit of x-axis data. */
int xdata_hilimit; /* high limit of x-axis data. */
int ydata_lolimit; /* low limit of y-axis data. */
int ydata_hilimit; /* high limit of y-axis data. */
int zdata_lolimit; /* low limit of z-axis data. */
int zdata_hilimit; /* high limit of z-axis data. */
};
/* Structure for ak09919c data. */
struct ak09919c_magdata_s
{
uint8_t st1; /* data of AK09919C_REG_ST1. */
uint8_t xdata_hi; /* data of AK09919C_REG_HXH. */
uint8_t xdata_lo; /* data of AK09919C_REG_HXL. */
uint8_t ydata_hi; /* data of AK09919C_REG_HYH. */
uint8_t ydata_lo; /* data of AK09919C_REG_HYL. */
uint8_t zdata_hi; /* data of AK09919C_REG_HZH. */
uint8_t zdata_lo; /* data of AK09919C_REG_HZL. */
uint8_t res; /* data of AK09919C_REG_TMPS. */
uint8_t st2; /* data of AK09919C_REG_ST2. */
};
/****************************************************************************
@ -146,6 +217,7 @@ static int ak09919c_i2c_read(FAR struct ak09919c_dev_s *priv,
static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable);
static int ak09919c_init(FAR struct ak09919c_dev_s *priv);
static int ak09919c_checkid(FAR struct ak09919c_dev_s *priv);
static int ak09919c_checkdev(FAR struct ak09919c_dev_s *priv);
static int ak09919c_setmode(FAR struct ak09919c_dev_s *priv, uint8_t mode);
static int ak09919c_setnoisefilter(FAR struct ak09919c_dev_s *priv,
uint32_t nsf);
@ -153,6 +225,8 @@ static int ak09919c_readmag(FAR struct ak09919c_dev_s *priv,
FAR struct sensor_event_mag *data);
static int ak09919c_softreset(FAR struct ak09919c_dev_s *priv);
static int ak09919c_findodr(FAR unsigned int *expect_period_us);
static int ak09919c_verifyparam(FAR struct ak09919c_magdata_s *magdata,
FAR struct ak09919c_threshold_s *threshold);
/* Sensor ops functions. */
@ -160,6 +234,8 @@ static int ak09919c_activate(FAR struct sensor_lowerhalf_s *lower,
bool enable);
static int ak09919c_set_interval(FAR struct sensor_lowerhalf_s *lower,
FAR unsigned int * interval_us);
static int ak09919c_selftest(FAR struct sensor_lowerhalf_s *lower,
unsigned long arg);
/* Sensor poll functions. */
@ -182,6 +258,35 @@ static const struct sensor_ops_s g_ak09919c_ops =
{
.activate = ak09919c_activate, /* Enable/disable snesor. */
.set_interval = ak09919c_set_interval, /* Set output data period. */
.selftest = ak09919c_selftest /* Sensor selftest function. */
};
static const struct ak09919c_threshold_s g_ak09919c_sngthr =
{
.st1_lolimit = AK09919C_LOLIMIT_SNG_ST1, /* low limit of st1 in single mode. */
.st1_hilimit = AK09919C_HILIMIT_SNG_ST1, /* high limit of st1 in single mode. */
.st2_lolimit = AK09919C_LOLIMIT_SNG_ST2, /* low limit of st2 in single mode. */
.st2_hilimit = AK09919C_HILIMIT_SNG_ST2, /* high limit of st2 in single mode. */
.xdata_lolimit = AK09919C_LOLIMIT_SNG_HX, /* low limit of x-axis in single mode. */
.xdata_hilimit = AK09919C_HILIMIT_SNG_HX, /* high limit of x-axis in single mode. */
.ydata_lolimit = AK09919C_LOLIMIT_SNG_HY, /* low limit of y-axis in single mode. */
.ydata_hilimit = AK09919C_HILIMIT_SNG_HY, /* high limit of y-axis in single mode. */
.zdata_lolimit = AK09919C_LOLIMIT_SNG_HZ, /* low limit of z-axis in single mode. */
.zdata_hilimit = AK09919C_HILIMIT_SNG_HZ /* high limit of z-axis in single mode. */
};
static const struct ak09919c_threshold_s g_ak09919c_slfthr =
{
.st1_lolimit = AK09919C_LOLIMIT_SLF_ST1, /* low limit of st1 in selftest mode. */
.st1_hilimit = AK09919C_HILIMIT_SLF_ST1, /* high limit of st1 in selftest mode. */
.st2_lolimit = AK09919C_LOLIMIT_SLF_ST2, /* low limit of st2 in selftest mode. */
.st2_hilimit = AK09919C_HILIMIT_SLF_ST2, /* high limit of st2 in selftest mode. */
.xdata_lolimit = AK09919C_LOLIMIT_SLF_HX, /* low limit of x-axis in selftest mode. */
.xdata_hilimit = AK09919C_HILIMIT_SLF_HX, /* high limit of x-axis in selftest mode. */
.ydata_lolimit = AK09919C_LOLIMIT_SLF_HY, /* low limit of y-axis in selftest mode. */
.ydata_hilimit = AK09919C_HILIMIT_SLF_HY, /* high limit of y-axis in selftest mode. */
.zdata_lolimit = AK09919C_LOLIMIT_SLF_HZ, /* low limit of z-axis in selftest mode. */
.zdata_hilimit = AK09919C_HILIMIT_SLF_HZ /* high limit of z-axis in selftest mode. */
};
/****************************************************************************
@ -207,7 +312,7 @@ static const struct sensor_ops_s g_ak09919c_ops =
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -255,7 +360,7 @@ static int ak09919c_i2c_read(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -281,7 +386,7 @@ static int ak09919c_i2c_readreg(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -327,7 +432,7 @@ static int ak09919c_i2c_writereg(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -343,7 +448,7 @@ static int ak09919c_setmode(FAR struct ak09919c_dev_s *priv,
}
else
{
up_udelay(1000);
up_udelay(AK09919C_MODE_SWITCH_DELAY);
}
return ret;
@ -364,7 +469,7 @@ static int ak09919c_setmode(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -406,7 +511,7 @@ static int ak09919c_setnoisefilter(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -457,7 +562,7 @@ static int ak09919c_readmag(FAR struct ak09919c_dev_s *priv,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -467,7 +572,13 @@ static int ak09919c_checkid(FAR struct ak09919c_dev_s *priv)
uint16_t devid;
ret = ak09919c_i2c_read(priv, AK09919C_REG_WIA1, (uint8_t *)&devid, 2);
if (ret < 0 || devid != AK09919C_DEVID)
if (ret < 0 )
{
snerr("Failed to read device id: %d\n", ret);
return ret;
}
if (devid != AK09919C_DEVID)
{
snerr("Wrong Device ID! %02x\n", devid);
ret = -ENODEV;
@ -490,7 +601,7 @@ static int ak09919c_checkid(FAR struct ak09919c_dev_s *priv)
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -506,7 +617,86 @@ static int ak09919c_softreset(FAR struct ak09919c_dev_s *priv)
}
else
{
up_udelay(1000);
up_udelay(AK09919C_SOFT_RESET_DELAY);
}
return ret;
}
/****************************************************************************
* Name: ak09919c_verifyparam
*
* Description:
* Parameter verification
*
* Input Parameters
* magdata - Data of mag
* threshold - Threshold of mag data
*
* Returned Value
* Return 0 if the driver was success; A negated errno
* value is returned on any failure;
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
static int ak09919c_verifyparam(FAR struct ak09919c_magdata_s *magdata,
FAR struct ak09919c_threshold_s *threshold)
{
int xdata;
int ydata;
int zdata;
int ret;
xdata = MAKE_S16(magdata->xdata_hi, magdata->xdata_lo);
ydata = MAKE_S16(magdata->ydata_hi, magdata->ydata_lo);
zdata = MAKE_S16(magdata->zdata_hi, magdata->zdata_lo);
ret = PARAMETER_VERIFY(magdata->st1,
threshold->st1_lolimit,
threshold->st1_hilimit);
if (ret < 0)
{
snerr("ST1 data is abnormal: %d\n", ret);
return ret;
}
ret = PARAMETER_VERIFY(magdata->st2,
threshold->st2_lolimit,
threshold->st2_hilimit);
if (ret < 0)
{
snerr("ST2 data is abnormal: %d\n", ret);
return ret;
}
ret = PARAMETER_VERIFY(xdata,
threshold->xdata_lolimit,
threshold->xdata_hilimit);
if (ret < 0)
{
snerr("X-axis data is abnormal: %d\n", ret);
return ret;
}
ret = PARAMETER_VERIFY(ydata,
threshold->ydata_lolimit,
threshold->ydata_hilimit);
if (ret < 0)
{
snerr("Y-axis data is abnormal: %d\n", ret);
return ret;
}
ret = PARAMETER_VERIFY(zdata,
threshold->zdata_lolimit,
threshold->zdata_hilimit);
if (ret < 0)
{
snerr("Z-axis data is abnormal: %d\n", ret);
return ret;
}
return ret;
@ -526,7 +716,7 @@ static int ak09919c_softreset(FAR struct ak09919c_dev_s *priv)
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -536,7 +726,7 @@ static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable)
if (enable)
{
/* Reset soft device */
/* Reset soft device. */
ret = ak09919c_softreset(priv);
if (ret < 0)
@ -545,7 +735,7 @@ static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable)
return ret;
}
/* Set noise filter */
/* Set noise filter. */
ret = ak09919c_setnoisefilter(priv, AK09919C_NSF_LOW);
if (ret < 0)
@ -554,7 +744,7 @@ static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable)
return ret;
}
/* Set work mode */
/* Set work mode. */
ret = ak09919c_setmode(priv, priv->workmode);
if (ret < 0)
@ -562,12 +752,20 @@ static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable)
snerr("Failed set work mode: %d\n", ret);
return ret;
}
priv->start_timestamp = sensor_get_timestamp();
priv->sample_count = 1;
work_queue(HPWORK, &priv->work,
ak09919c_worker, priv,
priv->interval / USEC_PER_TICK);
}
else
{
/* Reset soft device */
work_cancel(HPWORK, &priv->work);
/* Reset soft device. */
priv->workmode = AK09919C_POWER_DOWN_MODE;
ret = ak09919c_softreset(priv);
if (ret < 0)
{
@ -589,10 +787,10 @@ static int ak09919c_enable(FAR struct ak09919c_dev_s *priv, bool enable)
* expect_period_us -the time(expext) between report data, in us.
*
* Returned Value
* index of odr param.
* Index of odr param.
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -626,7 +824,7 @@ static int ak09919c_findodr(FAR unsigned int *expect_period_us)
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -634,7 +832,7 @@ static int ak09919c_init(FAR struct ak09919c_dev_s *priv)
{
int ret;
/* Reset soft device */
/* Reset soft device. */
ret = ak09919c_softreset(priv);
if (ret < 0)
@ -643,7 +841,7 @@ static int ak09919c_init(FAR struct ak09919c_dev_s *priv)
return ret;
}
/* Set noise suppression level */
/* Set noise suppression level. */
ret = ak09919c_setnoisefilter(priv, AK09919C_NSF_LOW);
if (ret < 0)
@ -652,7 +850,7 @@ static int ak09919c_init(FAR struct ak09919c_dev_s *priv)
return ret;
}
/* Set power down mode */
/* Set power down mode. */
ret = ak09919c_setmode(priv, priv->workmode);
if (ret < 0)
@ -664,6 +862,117 @@ static int ak09919c_init(FAR struct ak09919c_dev_s *priv)
return ret;
}
/****************************************************************************
* Name: ak09919c_checkdev
*
* Description:
* Check if the device is working properly.
*
* Input Parameters
* priv -Device struct
*
* Returned Value
* Return 0 if the driver was success; A negated errno
* value is returned on any failure;
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
static int ak09919c_checkdev(FAR struct ak09919c_dev_s *priv)
{
struct ak09919c_magdata_s magdata;
int ret;
/* Reset soft device. */
ret = ak09919c_softreset(priv);
if (ret < 0)
{
snerr("Failed reset device: %d\n", ret);
return ret;
}
/* Set to single measurement mode. */
ret = ak09919c_setmode(priv, AK09919C_SINGLESHOT_MODE);
if (ret < 0)
{
snerr("Failed set single measurement mode: %d\n", ret);
return ret;
}
/* AK09919C_REG_ST1 must be read separately before reading data. */
ret = ak09919c_i2c_readreg(priv, AK09919C_REG_ST1, &magdata.st1);
if (ret < 0)
{
snerr("Failed to read state: %d\n", ret);
return ret;
}
/* New data can be unlocked only when AK09919C_REG_ST2(8th byte) is read. */
ret = ak09919c_i2c_read(priv, AK09919C_REG_HXH,
&magdata.xdata_hi, 8);
if (ret < 0)
{
snerr("Failed to read mag: %d\n", ret);
return ret;
}
/* Check whether single mode data is right. */
ret = ak09919c_verifyparam(&magdata,
&g_ak09919c_sngthr);
if (ret < 0)
{
snerr("The data of single mode is error: %d\n", ret);
return ret;
}
/* Set to selftest mode. */
ret = ak09919c_setmode(priv, AK09919C_SELF_TEST_MODE);
if (ret < 0)
{
snerr("Failed set selftest mode: %d\n", ret);
return ret;
}
/* AK09919C_REG_ST1 must be read separately before reading data. */
ret = ak09919c_i2c_readreg(priv, AK09919C_REG_ST1, &magdata.st1);
if (ret < 0)
{
snerr("Failed to read state: %d\n", ret);
return ret;
}
/* New data can be unlocked only when AK09919C_REG_ST2(8th byte) is read. */
ret = ak09919c_i2c_read(priv, AK09919C_REG_HXH,
&magdata.xdata_hi, 8);
if (ret < 0)
{
snerr("Failed to read mag: %d\n", ret);
return ret;
}
/* Check whether selftest mode data is right. */
ret = ak09919c_verifyparam(&magdata,
&g_ak09919c_slfthr);
if (ret < 0)
{
snerr("The data of selftest mode is error: %d\n", ret);
return ret;
}
return ret;
}
/* Sensor ops functions */
/****************************************************************************
@ -681,7 +990,7 @@ static int ak09919c_init(FAR struct ak09919c_dev_s *priv)
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -724,7 +1033,7 @@ static int ak09919c_set_interval(FAR struct sensor_lowerhalf_s *lower,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -750,25 +1059,74 @@ static int ak09919c_activate(FAR struct sensor_lowerhalf_s *lower,
}
priv->activated = enable;
if (enable)
{
priv->start_timestamp = sensor_get_timestamp();
priv->sample_count = 1;
work_queue(HPWORK, &priv->work,
ak09919c_worker, priv,
priv->interval / USEC_PER_TICK);
}
else
{
work_cancel(HPWORK, &priv->work);
}
}
return OK;
}
/****************************************************************************
* Name: ak09919c_selftest
*
* Description:
* Mainly used in the self-test link, including device ID inspection
* and device functional inspection.
*
* Input Parameters:
* lower - The instance of lower half sensor driver.
* arg - The parameters associated with cmd.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
* -ENOTTY - The cmd don't support.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
static int ak09919c_selftest(FAR struct sensor_lowerhalf_s *lower,
unsigned long arg)
{
FAR struct ak09919c_dev_s *priv = (FAR struct ak09919c_dev_s *)lower;
int ret;
DEBUGASSERT(lower != NULL);
/* Process ioctl commands. */
switch (arg)
{
case AK09919C_SIMPLE_CHECK: /* Simple communication check. */
{
ret = ak09919c_checkid(priv);
if (ret < 0)
{
snerr("Failed to get DeviceID: %d\n", ret);
}
}
break;
case AK09919C_FULL_CHECK: /* Fully functional check. */
{
ret = ak09919c_checkdev(priv);
if (ret < 0)
{
snerr("Failed to selftest: %d\n", ret);
}
}
break;
default: /* Other cmd tag. */
{
ret = -ENOTTY;
snerr("The cmd don't support: %d\n", ret);
}
break;
}
return ret;
}
/****************************************************************************
* Name: ak09919c_worker
*
@ -783,7 +1141,7 @@ static int ak09919c_activate(FAR struct sensor_lowerhalf_s *lower,
* value is returned on any failure;
*
* Assumptions/Limitations:
* none.
* None.
*
****************************************************************************/
@ -844,6 +1202,9 @@ static void ak09919c_worker(FAR void *arg)
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int ak09919c_register(int devno, FAR const struct ak09919c_config_s *config)