From: Nathael Pajani Date: Sun, 3 Jan 2021 14:19:26 +0000 (+0100) Subject: Support for MCP3021 I2C ADC from Microchip X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=5e50ad79fe946b8f2ceecbb68845de7f282d6637;p=soft%2Flpc122x%2Fcore Support for MCP3021 I2C ADC from Microchip --- diff --git a/extdrv/mcp3021_adc_i2c.c b/extdrv/mcp3021_adc_i2c.c new file mode 100644 index 0000000..b2bae23 --- /dev/null +++ b/extdrv/mcp3021_adc_i2c.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * extdrv/mcp3021_adc_i2c.c + * + * + * Copyright 2021 Nathael Pajani + * + * + * 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 . + * + *************************************************************************** */ + + +#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 index 0000000..0b1e3fb --- /dev/null +++ b/include/extdrv/mcp3021_adc_i2c.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * extdrv/mcp3021_adc_i2c.h + * + * + * Copyright 2021 Nathael Pajani + * + * + * 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 . + * + *************************************************************************** */ + +#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 */ +