nuttx: add mcp23009 gpio driver

This commit is contained in:
Beat Küng 2021-01-14 13:35:43 +01:00 committed by Daniel Agar
parent e1983381e7
commit 3e4b8763a5
7 changed files with 435 additions and 0 deletions

View File

@ -62,3 +62,5 @@ else()
add_library(px4_layer ${PX4_SOURCE_DIR}/platforms/common/empty.c)
endif()
add_dependencies(px4_layer prebuild_targets)
add_subdirectory(gpio)

View File

@ -0,0 +1,35 @@
############################################################################
#
# Copyright (c) 2020 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
add_subdirectory(mcp23009)

View File

@ -0,0 +1,35 @@
############################################################################
#
# Copyright (c) 2020 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_library(platform_gpio_mcp23009
mcp23009.cpp
)

View File

@ -0,0 +1,212 @@
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include <drivers/drv_sensor.h>
#include <px4_platform/gpio/mcp23009.hpp>
#include "mcp23009_registers.hpp"
using namespace Microchip_MCP23009;
const struct gpio_operations_s MCP23009::gpio_ops = {
go_read : MCP23009::go_read,
go_write : MCP23009::go_write,
go_attach : nullptr,
go_enable : nullptr,
go_setpintype : MCP23009::go_setpintype,
};
MCP23009::MCP23009(int bus, int address, int first_minor, int bus_frequency) :
I2C(DRV_GPIO_DEVTYPE_MCP23009, "MCP23009", bus, address, bus_frequency),
_first_minor(first_minor)
{
}
MCP23009::~MCP23009()
{
/* set all as input & unregister */
for (int i = 0; i < num_gpios; ++i) {
go_setpintype(i, GPIO_INPUT_PIN);
gpio_pin_unregister(&_gpio[i].gpio, _first_minor + i);
}
}
int MCP23009::go_read(struct gpio_dev_s *dev, bool *value)
{
mcp23009_gpio_dev_s *gpio = (struct mcp23009_gpio_dev_s *)dev;
return gpio->obj->go_read(gpio->id, value);
}
int MCP23009::go_write(struct gpio_dev_s *dev, bool value)
{
mcp23009_gpio_dev_s *gpio = (struct mcp23009_gpio_dev_s *)dev;
return gpio->obj->go_write(gpio->id, value);
}
int MCP23009::go_setpintype(struct gpio_dev_s *dev, enum gpio_pintype_e pintype)
{
mcp23009_gpio_dev_s *gpio = (struct mcp23009_gpio_dev_s *)dev;
return gpio->obj->go_setpintype(gpio->id, pintype);
}
int MCP23009::read_reg(Register address, uint8_t &data)
{
return transfer((uint8_t *)&address, 1, &data, 1);
}
int MCP23009::write_reg(Register address, uint8_t value)
{
uint8_t data[2] = {(uint8_t)address, value};
return transfer(data, sizeof(data), nullptr, 0);
}
int MCP23009::init(uint8_t direction, uint8_t intital, uint8_t pull_up)
{
/* do I2C init (and probe) first */
int ret = I2C::init();
if (ret != PX4_OK) {
return ret;
}
/* Use this state as the out puts */
ret = write_reg(Register::OLAT, intital);
ret |= write_reg(Register::IODIR, direction);
ret |= write_reg(Register::GPPU, pull_up);
if (ret != PX4_OK) {
return ret;
}
/* register the pins */
for (int i = 0; i < num_gpios; ++i) {
_gpio[i].gpio.gp_pintype = GPIO_INPUT_PIN;
_gpio[i].gpio.gp_ops = &gpio_ops;
_gpio[i].id = i;
_gpio[i].obj = this;
ret = gpio_pin_register(&_gpio[i].gpio, _first_minor + i);
if (ret != PX4_OK) {
return ret;
}
}
return ret;
}
int MCP23009::probe()
{
// no whoami, try to read IOCON
uint8_t data;
return read_reg(Register::IOCON, data);
}
int MCP23009::go_read(int id, bool *value)
{
uint8_t data;
int ret = read_reg(Register::GPIO, data);
if (ret != 0) {
return ret;
}
*value = data & (1 << id);
return 0;
}
int MCP23009::go_write(int id, bool value)
{
uint8_t data;
int ret = read_reg(Register::GPIO, data);
if (ret != 0) {
return ret;
}
if (value) {
data |= (1 << id);
} else {
data &= ~(1 << id);
}
return write_reg(Register::GPIO, data);
}
int MCP23009::go_setpintype(int id, enum gpio_pintype_e pintype)
{
uint8_t direction;
int ret = read_reg(Register::IODIR, direction);
if (ret != 0) {
return ret;
}
uint8_t pullup;
ret = read_reg(Register::GPPU, pullup);
if (ret != 0) {
return ret;
}
switch (pintype) {
case GPIO_INPUT_PIN:
direction |= (1 << id);
pullup &= ~(1 << id);
break;
case GPIO_INPUT_PIN_PULLUP:
direction |= (1 << id);
pullup |= (1 << id);
break;
case GPIO_OUTPUT_PIN:
direction &= ~(1 << id);
break;
default:
return -EINVAL;
}
_gpio[id].gpio.gp_pintype = pintype;
ret = write_reg(Register::GPPU, pullup);
if (ret != 0) {
return ret;
}
return write_reg(Register::IODIR, direction);
}

View File

@ -0,0 +1,68 @@
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include <stdint.h>
// TODO: move to a central header
static constexpr uint8_t Bit0 = (1 << 0);
static constexpr uint8_t Bit1 = (1 << 1);
static constexpr uint8_t Bit2 = (1 << 2);
static constexpr uint8_t Bit3 = (1 << 3);
static constexpr uint8_t Bit4 = (1 << 4);
static constexpr uint8_t Bit5 = (1 << 5);
static constexpr uint8_t Bit6 = (1 << 6);
static constexpr uint8_t Bit7 = (1 << 7);
namespace Microchip_MCP23009
{
enum class
Register : uint8_t {
IODIR = 0x00,
IPOL = 0x01,
GPINTEN = 0x02,
DEFVAL = 0x03,
INTCON = 0x04,
IOCON = 0x05,
GPPU = 0x06,
INTF = 0x07,
INTCAP = 0x08,
GPIO = 0x09,
OLAT = 0x0a
};
} // namespace Microchip_MCP23009

View File

@ -0,0 +1,81 @@
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include <drivers/device/i2c.h>
#include <nuttx/ioexpander/gpio.h>
using namespace time_literals;
namespace Microchip_MCP23009
{
enum class Register : uint8_t;
}
class MCP23009 : public device::I2C
{
public:
MCP23009(int bus, int address, int first_minor = 0, int bus_frequency = 400000);
virtual ~MCP23009();
int init(uint8_t direction, uint8_t intital = 0, uint8_t pull_up = 0);
protected:
int probe() override;
private:
static constexpr int num_gpios = 8;
static const gpio_operations_s gpio_ops;
struct mcp23009_gpio_dev_s {
struct gpio_dev_s gpio;
uint8_t id;
MCP23009 *obj;
};
static int go_read(struct gpio_dev_s *dev, bool *value);
static int go_write(struct gpio_dev_s *dev, bool value);
static int go_setpintype(struct gpio_dev_s *dev, enum gpio_pintype_e pintype);
int go_read(int id, bool *value);
int go_write(int id, bool value);
int go_setpintype(int id, enum gpio_pintype_e pintype);
int read_reg(Microchip_MCP23009::Register address, uint8_t &data);
int write_reg(Microchip_MCP23009::Register address, uint8_t data);
const int _first_minor;
mcp23009_gpio_dev_s _gpio[num_gpios] {};
};

View File

@ -163,6 +163,8 @@
#define DRV_ADC_DEVTYPE_ADS1115 0x90
#define DRV_DIST_DEVTYPE_VL53L1X 0x91
#define DRV_GPIO_DEVTYPE_MCP23009 0x99
#define DRV_DEVTYPE_UNUSED 0xff
#endif /* _DRV_SENSOR_H */