|
@@ -1,5 +1,7 @@
|
|
|
/*
|
|
|
- * srf08.c - Support for Devantech SRF08 ultrasonic ranger
|
|
|
+ * srf08.c - Support for Devantech SRFxx ultrasonic ranger
|
|
|
+ * with i2c interface
|
|
|
+ * actually supported are srf08, srf10
|
|
|
*
|
|
|
* Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
|
|
|
*
|
|
@@ -9,6 +11,7 @@
|
|
|
*
|
|
|
* For details about the device see:
|
|
|
* http://www.robot-electronics.co.uk/htm/srf08tech.html
|
|
|
+ * http://www.robot-electronics.co.uk/htm/srf10tech.htm
|
|
|
*/
|
|
|
|
|
|
#include <linux/err.h>
|
|
@@ -33,9 +36,20 @@
|
|
|
|
|
|
#define SRF08_CMD_RANGING_CM 0x51 /* Ranging Mode - Result in cm */
|
|
|
|
|
|
-#define SRF08_DEFAULT_GAIN 1025 /* default analogue value of Gain */
|
|
|
#define SRF08_DEFAULT_RANGE 6020 /* default value of Range in mm */
|
|
|
|
|
|
+enum srf08_sensor_type {
|
|
|
+ SRF08,
|
|
|
+ SRF10,
|
|
|
+ SRF_MAX_TYPE
|
|
|
+};
|
|
|
+
|
|
|
+struct srf08_chip_info {
|
|
|
+ const int *sensitivity_avail;
|
|
|
+ int num_sensitivity_avail;
|
|
|
+ int sensitivity_default;
|
|
|
+};
|
|
|
+
|
|
|
struct srf08_data {
|
|
|
struct i2c_client *client;
|
|
|
|
|
@@ -54,6 +68,12 @@ struct srf08_data {
|
|
|
* 1x16-bit channel + 3x16 padding + 4x16 timestamp
|
|
|
*/
|
|
|
s16 buffer[8];
|
|
|
+
|
|
|
+ /* Sensor-Type */
|
|
|
+ enum srf08_sensor_type sensor_type;
|
|
|
+
|
|
|
+ /* Chip-specific information */
|
|
|
+ const struct srf08_chip_info *chip_info;
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -63,11 +83,30 @@ struct srf08_data {
|
|
|
* But with ADC's this term is already used differently and that's why it
|
|
|
* is called "Sensitivity" here.
|
|
|
*/
|
|
|
-static const int srf08_sensitivity[] = {
|
|
|
+static const int srf08_sensitivity_avail[] = {
|
|
|
94, 97, 100, 103, 107, 110, 114, 118,
|
|
|
123, 128, 133, 139, 145, 152, 159, 168,
|
|
|
177, 187, 199, 212, 227, 245, 265, 288,
|
|
|
- 317, 352, 395, 450, 524, 626, 777, 1025 };
|
|
|
+ 317, 352, 395, 450, 524, 626, 777, 1025
|
|
|
+ };
|
|
|
+
|
|
|
+static const struct srf08_chip_info srf08_chip_info = {
|
|
|
+ .sensitivity_avail = srf08_sensitivity_avail,
|
|
|
+ .num_sensitivity_avail = ARRAY_SIZE(srf08_sensitivity_avail),
|
|
|
+ .sensitivity_default = 1025,
|
|
|
+};
|
|
|
+
|
|
|
+static const int srf10_sensitivity_avail[] = {
|
|
|
+ 40, 40, 50, 60, 70, 80, 100, 120,
|
|
|
+ 140, 200, 250, 300, 350, 400, 500, 600,
|
|
|
+ 700,
|
|
|
+ };
|
|
|
+
|
|
|
+static const struct srf08_chip_info srf10_chip_info = {
|
|
|
+ .sensitivity_avail = srf10_sensitivity_avail,
|
|
|
+ .num_sensitivity_avail = ARRAY_SIZE(srf10_sensitivity_avail),
|
|
|
+ .sensitivity_default = 700,
|
|
|
+};
|
|
|
|
|
|
static int srf08_read_ranging(struct srf08_data *data)
|
|
|
{
|
|
@@ -264,9 +303,13 @@ static ssize_t srf08_show_sensitivity_available(struct device *dev,
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
{
|
|
|
int i, len = 0;
|
|
|
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
|
+ struct srf08_data *data = iio_priv(indio_dev);
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++)
|
|
|
- len += sprintf(buf + len, "%d ", srf08_sensitivity[i]);
|
|
|
+ for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
|
|
|
+ if (data->chip_info->sensitivity_avail[i])
|
|
|
+ len += sprintf(buf + len, "%d ",
|
|
|
+ data->chip_info->sensitivity_avail[i]);
|
|
|
|
|
|
len += sprintf(buf + len, "\n");
|
|
|
|
|
@@ -295,19 +338,21 @@ static ssize_t srf08_write_sensitivity(struct srf08_data *data,
|
|
|
int ret, i;
|
|
|
u8 regval;
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++)
|
|
|
- if (val == srf08_sensitivity[i]) {
|
|
|
+ if (!val)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
|
|
|
+ if (val && (val == data->chip_info->sensitivity_avail[i])) {
|
|
|
regval = i;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (i >= ARRAY_SIZE(srf08_sensitivity))
|
|
|
+ if (i >= data->chip_info->num_sensitivity_avail)
|
|
|
return -EINVAL;
|
|
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
|
|
- ret = i2c_smbus_write_byte_data(client,
|
|
|
- SRF08_WRITE_MAX_GAIN, regval);
|
|
|
+ ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
|
|
|
if (ret < 0) {
|
|
|
dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
|
|
|
mutex_unlock(&data->lock);
|
|
@@ -399,8 +444,20 @@ static int srf08_probe(struct i2c_client *client,
|
|
|
data = iio_priv(indio_dev);
|
|
|
i2c_set_clientdata(client, indio_dev);
|
|
|
data->client = client;
|
|
|
+ data->sensor_type = (enum srf08_sensor_type)id->driver_data;
|
|
|
+
|
|
|
+ switch (data->sensor_type) {
|
|
|
+ case SRF08:
|
|
|
+ data->chip_info = &srf08_chip_info;
|
|
|
+ break;
|
|
|
+ case SRF10:
|
|
|
+ data->chip_info = &srf10_chip_info;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- indio_dev->name = "srf08";
|
|
|
+ indio_dev->name = id->name;
|
|
|
indio_dev->dev.parent = &client->dev;
|
|
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
|
|
indio_dev->info = &srf08_info;
|
|
@@ -425,7 +482,8 @@ static int srf08_probe(struct i2c_client *client,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- ret = srf08_write_sensitivity(data, SRF08_DEFAULT_GAIN);
|
|
|
+ ret = srf08_write_sensitivity(data,
|
|
|
+ data->chip_info->sensitivity_default);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
@@ -433,14 +491,16 @@ static int srf08_probe(struct i2c_client *client,
|
|
|
}
|
|
|
|
|
|
static const struct of_device_id of_srf08_match[] = {
|
|
|
- { .compatible = "devantech,srf08", 0},
|
|
|
+ { .compatible = "devantech,srf08", (void *)SRF08},
|
|
|
+ { .compatible = "devantech,srf10", (void *)SRF10},
|
|
|
{},
|
|
|
};
|
|
|
|
|
|
MODULE_DEVICE_TABLE(of, of_srf08_match);
|
|
|
|
|
|
static const struct i2c_device_id srf08_id[] = {
|
|
|
- { "srf08", 0 },
|
|
|
+ { "srf08", SRF08 },
|
|
|
+ { "srf10", SRF10 },
|
|
|
{ }
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(i2c, srf08_id);
|