Support for MCP3021 I2C ADC from Microchip
authorNathael Pajani <nathael.pajani@ed3l.fr>
Sun, 3 Jan 2021 14:19:26 +0000 (15:19 +0100)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:05 +0000 (17:03 +0100)
extdrv/mcp3021_adc_i2c.c [new file with mode: 0644]
include/extdrv/mcp3021_adc_i2c.h [new file with mode: 0644]

diff --git a/extdrv/mcp3021_adc_i2c.c b/extdrv/mcp3021_adc_i2c.c
new file mode 100644 (file)
index 0000000..b2bae23
--- /dev/null
@@ -0,0 +1,103 @@
+/****************************************************************************
+ *   extdrv/mcp3021_adc_i2c.c
+ *
+ *
+ * Copyright 2021 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+
+#include "core/system.h"
+#include "lib/errno.h"
+#include "lib/utils.h"
+#include "drivers/i2c.h"
+#include "extdrv/mcp3021_adc_i2c.h"
+
+
+/***************************************************************************** */
+/*          Support for MCP3021 I2C ADC from Microchip                         */
+/***************************************************************************** */
+
+/* The MCP3021 has no internal registers.
+ * Data sampling is triggered by reading from the device
+ *  (triggering occurs on the R/W bit of the address byte set to Read)
+ * Continuous sampling is triggered by continuous reading.
+ * Samples are received on two contiguous bytes, with the four upper bits on the
+ *   four lower bits of the first byte and the six lower bits on the six upper
+ *   bits of the second byte.
+ */
+
+
+/* Check the sensor presence, return 1 if sensor was found.
+ * This is a basic check, it could be anything with the same address ...
+ * This check can be made either by trying to write nothing, or by reading a sample.
+ */
+int mcp3021_probe(struct mcp3021_config* conf)
+{
+       char cmd_buf = (conf->addr | I2C_WRITE_BIT);
+
+       /* Did we already probe the sensor ? */
+       if (conf->probe_ok != 1) {
+               conf->probe_ok = i2c_write(conf->bus_num, &cmd_buf, 1, NULL);
+       }
+       return conf->probe_ok;
+}
+
+/* ADC Read
+ * Read _len_ samples from the ADC, put the shifted samples into _values_
+ * Return value(s):
+ *   Upon successfull completion, returns the number of samples read.
+ *   On error, returns a negative integer equivalent to errors from glibc.
+ */
+#define CMD_BUF_SIZE 1
+int mcp3021_read(struct mcp3021_config* conf, uint16_t* values, int len)
+{
+       int ret = 0, i = 0;
+       char cmd_buf[CMD_BUF_SIZE] = { (conf->addr | I2C_READ_BIT), };
+       char ctrl_buf[CMD_BUF_SIZE] = { I2C_CONT, };
+
+       if (mcp3021_probe(conf) != 1) {
+               return -ENODEV;
+       }
+       if (values == NULL) {
+               return -EINVAL;
+       }
+
+       /* Read the requested data */
+       ret = i2c_read(conf->bus_num, cmd_buf, CMD_BUF_SIZE, ctrl_buf, (char*)values, (len * 2));
+
+       if (ret != (len * 2)) {
+               conf->probe_ok = 0;
+               return ret;
+       }
+
+       /* Shift all values */
+       for (i = 0; i < len; i++) {
+               values[i] = ntohs(values[i]) >> 2;
+       }
+       return len;
+}
+
+int mcp3021_config(struct mcp3021_config* conf)
+{
+       if (mcp3021_probe(conf) != 1) {
+               return -ENODEV;
+       }
+       return 0; /* Config success */
+}
+
+
diff --git a/include/extdrv/mcp3021_adc_i2c.h b/include/extdrv/mcp3021_adc_i2c.h
new file mode 100644 (file)
index 0000000..0b1e3fb
--- /dev/null
@@ -0,0 +1,58 @@
+/****************************************************************************
+ *   extdrv/mcp3021_adc_i2c.h
+ *
+ *
+ * Copyright 2021 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#ifndef MCP3021_ADC_H
+#define MCP3021_ADC_H
+
+
+/***************************************************************************** */
+/*          Support for MCP3021 I2C ADC from Microchip                         */
+/***************************************************************************** */
+
+/* The MCP3021 has no internal registers.
+ * Data sampling is triggered by reading from the device
+ *  (triggering occurs on the R/W bit of the address byte set to Read)
+ * Continuous sampling is triggered by continuous reading.
+ * Samples are received on two contiguous bytes, with the four upper bits on the
+ *   four lower bits of the first byte and the six lower bits on the six upper
+ *   bits of the second byte.
+ */
+
+struct mcp3021_config {
+       uint8_t bus_num;
+       uint8_t addr;
+       uint8_t probe_ok;
+};
+
+/* ADC Read
+ * Read _len_ samples from the ADC, put the shifted samples into _values_
+ * Return value(s):
+ *   Upon successfull completion, returns the number of samples read.
+ *   On error, returns a negative integer equivalent to errors from glibc.
+ */
+int mcp3021_read(struct mcp3021_config* conf, uint16_t* values, int len);
+
+int mcp3021_config(struct mcp3021_config* conf);
+
+
+#endif /* MCP3021_ADC_H */
+