Support for MCP3021 I2C ADC from Microchip

This commit is contained in:
Nathael Pajani 2021-01-03 15:19:26 +01:00
parent e14fa1c471
commit 5e50ad79fe
2 changed files with 161 additions and 0 deletions

103
extdrv/mcp3021_adc_i2c.c Normal file
View File

@ -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 */
}

View File

@ -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 */