diff --git a/libraries/MCP23008/.arduino-ci.yml b/libraries/MCP23008/.arduino-ci.yml new file mode 100644 index 00000000..cecf5850 --- /dev/null +++ b/libraries/MCP23008/.arduino-ci.yml @@ -0,0 +1,11 @@ +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + # - esp8266 + # - mega2560 diff --git a/libraries/MCP23008/.github/workflows/arduino-lint.yml b/libraries/MCP23008/.github/workflows/arduino-lint.yml new file mode 100644 index 00000000..b2ca058c --- /dev/null +++ b/libraries/MCP23008/.github/workflows/arduino-lint.yml @@ -0,0 +1,13 @@ + +name: Arduino-lint + +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict diff --git a/libraries/MCP23008/.github/workflows/arduino_test_runner.yml b/libraries/MCP23008/.github/workflows/arduino_test_runner.yml new file mode 100644 index 00000000..096b975b --- /dev/null +++ b/libraries/MCP23008/.github/workflows/arduino_test_runner.yml @@ -0,0 +1,17 @@ +--- +name: Arduino CI + +on: [push, pull_request] + +jobs: + runTest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/libraries/MCP23008/.github/workflows/jsoncheck.yml b/libraries/MCP23008/.github/workflows/jsoncheck.yml new file mode 100644 index 00000000..04603d08 --- /dev/null +++ b/libraries/MCP23008/.github/workflows/jsoncheck.yml @@ -0,0 +1,18 @@ +name: JSON check + +on: + push: + paths: + - '**.json' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + diff --git a/libraries/MCP23008/LICENSE b/libraries/MCP23008/LICENSE new file mode 100644 index 00000000..cb502675 --- /dev/null +++ b/libraries/MCP23008/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2022 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/MCP23008/MCP23008.cpp b/libraries/MCP23008/MCP23008.cpp new file mode 100644 index 00000000..f2d5edc7 --- /dev/null +++ b/libraries/MCP23008/MCP23008.cpp @@ -0,0 +1,405 @@ +// +// FILE: MCP23008.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: Arduino library for I2C MCP23008 8 channel port expander +// DATE: 2019-10-12 +// URL: https://github.com/RobTillaart/MCP23008 +// +// HISTORY: +// 0.1.0 2022-01-10 initial version + + + +#include "MCP23008.h" + + +// Registers // description datasheet +#define MCP23008_DDR_A 0x00 // Data Direction Register A P +#define MCP23008_POL_A 0x01 // Input Polarity A P +#define MCP23008_GPINTEN_A 0x02 // NOT USED interrupt enable P +#define MCP23008_DEFVAL_A 0x03 // NOT USED interrupt def P +#define MCP23008_INTCON_A 0x04 // NOT USED interrupt control P +#define MCP23008_IOCR 0x05 // IO control register P +#define MCP23008_PUR_A 0x06 // Pull Up Resistors A P +#define MCP23008_INTF_A 0x07 // NOT USED interrupt flag P +#define MCP23008_INTCAP_A 0x08 // NOT USED interrupt capture P +#define MCP23008_GPIO_A 0x09 // General Purpose IO A P +#define MCP23008_OLAT_A 0x0A // NOT USED output latch P + + +MCP23008::MCP23008(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _error = MCP23008_OK; +} + + +#if defined(ESP8266) || defined(ESP32) +bool MCP23008::begin(const uint8_t dataPin, const uint8_t clockPin) +{ + _wire = &Wire; + _wire->begin(dataPin, clockPin); + // check connected + if (! isConnected()) return false; + // disable address increment (datasheet) + if (! writeReg(MCP23008_IOCR, 0b00100000)) return false; + // Force INPUT_PULLUP + if (! writeReg(MCP23008_PUR_A, 0xFF)) return false; + return true; +} +#endif + + +bool MCP23008::begin() +{ + _wire->begin(); + // check connected + if (! isConnected()) return false; + // disable address increment (datasheet) + if (! writeReg(MCP23008_IOCR, 0b00100000)) return false; + // Force INPUT_PULLUP + if (! writeReg(MCP23008_PUR_A, 0xFF)) return false; + return true; +} + + +bool MCP23008::isConnected() +{ + _wire->beginTransmission(_address); + if (_wire->endTransmission() != 0) + { + _error = MCP23008_I2C_ERROR; + return false; + } + _error = MCP23008_OK; + return true; +} + + +// single pin interface +// pin = 0..7 +// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT) +bool MCP23008::pinMode(uint8_t pin, uint8_t mode) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + if ((mode != INPUT) && (mode != INPUT_PULLUP) && (mode != OUTPUT)) + { + _error = MCP23008_VALUE_ERROR; + return false; + } + + uint8_t dataDirectionRegister = MCP23008_DDR_A; + uint8_t val = readReg(dataDirectionRegister); + if (_error != MCP23008_OK) + { + return false; + } + uint8_t mask = 1 << pin; + // only work with valid + if ((mode == INPUT) || (mode == INPUT_PULLUP)) + { + val |= mask; + } + else if (mode == OUTPUT) + { + val &= ~mask; + } + // other values won't change val .... + writeReg(dataDirectionRegister, val); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +// pin = 0..7 +// value = LOW, HIGH +bool MCP23008::digitalWrite(uint8_t pin, uint8_t value) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + uint8_t IOR = MCP23008_GPIO_A; + uint8_t val = readReg(IOR); + if (_error != MCP23008_OK) + { + return false; + } + + uint8_t mask = 1 << pin; + if (value) + { + val |= mask; + } + else + { + val &= ~mask; + } + writeReg(IOR, val); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +uint8_t MCP23008::digitalRead(uint8_t pin) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return MCP23008_INVALID_READ; + } + uint8_t IOR = MCP23008_GPIO_A; + uint8_t val = readReg(IOR); + if (_error != MCP23008_OK) + { + return MCP23008_INVALID_READ; + } + uint8_t mask = 1 << pin; + if (val & mask) return HIGH; + return LOW; +} + + +// pin = 0..7 +// reverse = true or false +bool MCP23008::setPolarity(uint8_t pin, bool reversed) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + uint8_t inputPolarityRegister = MCP23008_POL_A; + uint8_t val = readReg(inputPolarityRegister); + if (_error != MCP23008_OK) + { + return false; + } + uint8_t mask = 1 << pin; + if (reversed) + { + val |= mask; + } + else + { + val &= ~mask; + } + writeReg(inputPolarityRegister, val); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +bool MCP23008::getPolarity(uint8_t pin, bool &reversed) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + uint8_t inputPolarityRegister = MCP23008_POL_A; + uint8_t val = readReg(inputPolarityRegister); + if (_error != MCP23008_OK) + { + return false; + } + uint8_t mask = 1 << pin; + reversed = (val & mask) > 0; + return true; +} + + +// pin = 0..7 +// reverse = true or false +bool MCP23008::setPullup(uint8_t pin, bool pullup) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + uint8_t inputPullupRegister = MCP23008_PUR_A; + uint8_t val = readReg(inputPullupRegister); + if (_error != MCP23008_OK) + { + return false; + } + uint8_t mask = 1 << pin; + if (pullup) + { + val |= mask; + } + else + { + val &= ~mask; + } + writeReg(inputPullupRegister, val); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +bool MCP23008::getPullup(uint8_t pin, bool &pullup) +{ + if (pin > 7) + { + _error = MCP23008_PIN_ERROR; + return false; + } + uint8_t inputPullupRegister = MCP23008_PUR_A; + uint8_t val = readReg(inputPullupRegister); + if (_error != MCP23008_OK) + { + return false; + } + uint8_t mask = 1 << pin; + pullup = (val & mask) > 0; + return true; +} + + +/////////////////////////////////////////////////////////////////////// +// 8 pins interface +// whole register at once +// value = 0..0xFF bit pattern +bool MCP23008::pinMode8(uint8_t value) +{ + writeReg(MCP23008_DDR_A, value); + _error = MCP23008_OK; + return true; +} + + +bool MCP23008::write8(uint8_t value) +{ + writeReg(MCP23008_GPIO_A, value); + _error = MCP23008_OK; + return true; +} + + +int MCP23008::read8() +{ + _error = MCP23008_OK; + return readReg(MCP23008_GPIO_A); +} + + +// mask = 0..0xFF bit pattern +bool MCP23008::setPolarity8(uint8_t mask) +{ + writeReg(MCP23008_POL_A, mask); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +bool MCP23008::getPolarity8(uint8_t &mask) +{ + mask = readReg(MCP23008_POL_A); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +// mask = 0..0xFF bit pattern +bool MCP23008::setPullup8(uint8_t mask) +{ + writeReg(MCP23008_PUR_A, mask); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +bool MCP23008::getPullup8(uint8_t &mask) +{ + mask = readReg(MCP23008_PUR_A); + if (_error != MCP23008_OK) + { + return false; + } + return true; +} + + +int MCP23008::lastError() +{ + int e = _error; + _error = MCP23008_OK; // reset error after read. + return e; +} + + +//////////////////////////////////////////////////// +// +// PRIVATE +// + +bool MCP23008::writeReg(uint8_t reg, uint8_t value) +{ + _wire->beginTransmission(_address); + _wire->write(reg); + _wire->write(value); + if (_wire->endTransmission() != 0) + { + _error = MCP23008_I2C_ERROR; + return false; + } + _error = MCP23008_OK; + return true; +} + + +uint8_t MCP23008::readReg(uint8_t reg) +{ + _wire->beginTransmission(_address); + _wire->write(reg); + if (_wire->endTransmission() != 0) + { + _error = MCP23008_I2C_ERROR; + return 0; + } + else + { + _error = MCP23008_OK; + } + uint8_t n = _wire->requestFrom(_address, (uint8_t)1); + if (n != 1) + { + _error = MCP23008_I2C_ERROR; + return 0; + } + return _wire->read(); +} + + +// -- END OF FILE -- + diff --git a/libraries/MCP23008/MCP23008.h b/libraries/MCP23008/MCP23008.h new file mode 100644 index 00000000..cd8984f5 --- /dev/null +++ b/libraries/MCP23008/MCP23008.h @@ -0,0 +1,76 @@ +#pragma once +// +// FILE: MCP23008.h +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: Arduino library for I2C MCP23008 16 channel port expander +// DATE: 2022-01-10 +// URL: https://github.com/RobTillaart/MCP23008 + + +#include "Arduino.h" +#include "Wire.h" + + +#define MCP23008_LIB_VERSION (F("0.1.0")) + +#define MCP23008_OK 0x00 +#define MCP23008_PIN_ERROR 0x81 +#define MCP23008_I2C_ERROR 0x82 +#define MCP23008_VALUE_ERROR 0x83 +#define MCP23008_PORT_ERROR 0x84 + + +#define MCP23008_INVALID_READ -100 + + +class MCP23008 +{ +public: + MCP23008(uint8_t address, TwoWire *wire = &Wire); + +#if defined(ESP8266) || defined(ESP32) + bool begin(const uint8_t dataPin, const uint8_t clockPin); +#endif + bool begin(); + bool isConnected(); + + + // single pin interface + // mode = INPUT, OUTPUT or INPUT_PULLUP (==INPUT) + bool pinMode(uint8_t pin, uint8_t mode); + bool digitalWrite(uint8_t pin, uint8_t value); + uint8_t digitalRead(uint8_t pin); + + bool setPolarity(uint8_t pin, bool reversed); + bool getPolarity(uint8_t pin, bool &reversed); + bool setPullup(uint8_t pin, bool pullup); + bool getPullup(uint8_t pin, bool &pullup); + + + // 8 pins interface + // value = bit pattern + bool pinMode8(uint8_t value); + bool write8(uint8_t value); + int read8(); + + bool setPolarity8(uint8_t mask); + bool getPolarity8(uint8_t &mask); + bool setPullup8(uint8_t mask); + bool getPullup8(uint8_t &mask); + + + int lastError(); + +private: + bool writeReg(uint8_t reg, uint8_t value); + uint8_t readReg(uint8_t reg); + + uint8_t _address; + TwoWire* _wire; + uint8_t _error; +}; + + +// -- END OF FILE -- + diff --git a/libraries/MCP23008/README.md b/libraries/MCP23008/README.md new file mode 100644 index 00000000..9040748d --- /dev/null +++ b/libraries/MCP23008/README.md @@ -0,0 +1,77 @@ + +[![Arduino CI](https://github.com/RobTillaart/MCP23008/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/MCP23008/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP23008/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/MCP23008/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP23008/actions/workflows/jsoncheck.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP23008/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP23008.svg?maxAge=3600)](https://github.com/RobTillaart/MCP23008/releases) + + +# MCP23008 + +Arduino library for MCP23008 8 channel I2C port expander. + + +## Description + +This library gives easy control over the 8 pins of a (I2C) MCP23008 chip. + +This IC is strongly related tot the MCP23017 I2C port expander - https://github.com/RobTillaart/MCP23017_RT +Programming Interface is kept the same as much as possible. + + +## Interface + +### Constructor + +- **MCP23008(uint8_t address, TwoWire \*wire = &Wire)** constructor, with default Wire interface. +Can be overruled with Wire0..WireN. +- **bool begin()** for UNO, returns true if successful. +- **bool begin(uint8_t sda, uint8_t scl)** for ESP32, returns true if successful. +- **bool isConnected()** returns true if connected, false otherwise. + + +### Single pin interface + +- **bool pinMode(uint8_t pin, uint8_t mode)** pin = 0..7, mode = INPUT, OUTPUT, returns true if successful. +- **bool digitalWrite(uint8_t pin, uint8_t value)** pin = 0..7, value = LOW(0) HIGH (!0), returns true if successful. +- **uint8_t digitalRead(uint8_t pin)** pin = 0..7, returns LOW or HIGH, might set the lastError(); +- **bool setPolarity(uint8_t pin, bool reversed)** pin = 0..7, set reversed flag, returns true if successful. +- **bool getPolarity(uint8_t pin, bool &reversed)** pin = 0..7, reads reversed flag, returns true if successful. +- **bool setPullup(uint8_t pin, bool pullup)** pin = 0..7, set pull-up flag, returns true if successful. +- **bool getPullup(uint8_t pin, bool &pullup)** pin = 0..7, reads pull-up flag, returns true if successful. + + +### 8 pins interface + +- **bool pinMode8(uint8_t value)** value = 0..255, returns true if successful. +- **bool write8(uint8_t value)** value = 0..255, returns true if successful. +- **uint8_t read8()** reads 8 pins into one byte. +- **bool setPolarity8(uint8_t mask)** sets polarity for 8 channels at once. +- **bool getPolarity8(uint8_t &mask)** reads polarity of 8 channels at once. +- **bool setPullup8(uint8_t mask)** sets pull-up for 8 channels at once. +- **bool getPullup8(uint8_t &mask)** reads pull-up for 8 channels at once. + + +### Error codes + +- **int lastError()** Above functions set an error flag that can be read with this function. +Reading it will reset the flag to **MCP23008_OK**. + +| DESCRIPTION | VALUE | +|:----------------------|:-----:| +| MCP23008_OK | 0x00 | +| MCP23008_PIN_ERROR | 0x81 | +| MCP23008_I2C_ERROR | 0x82 | +| MCP23008_VALUE_ERROR | 0x83 | +| MCP23008_PORT_ERROR | 0x84 | + + +## Operation + +See examples. + + +## Future + +- keep in sync with MCP23017 + diff --git a/libraries/MCP23008/documents/MCP23008 I2C to General Parallel IO .pdf b/libraries/MCP23008/documents/MCP23008 I2C to General Parallel IO .pdf new file mode 100644 index 00000000..a3584311 Binary files /dev/null and b/libraries/MCP23008/documents/MCP23008 I2C to General Parallel IO .pdf differ diff --git a/libraries/MCP23008/examples/MCP23008_digitalRead/MCP23008_digitalRead.ino b/libraries/MCP23008/examples/MCP23008_digitalRead/MCP23008_digitalRead.ino new file mode 100644 index 00000000..fb4e8288 --- /dev/null +++ b/libraries/MCP23008/examples/MCP23008_digitalRead/MCP23008_digitalRead.ino @@ -0,0 +1,40 @@ +// +// FILE: MCP23008_digitalRead.ino +// AUTHOR: Rob Tillaart +// DATE: 2019-10-14 +// PUPROSE: test MCP23008 library + + +#include "MCP23008.h" +#include "Wire.h" + + +MCP23008 MCP(0x27); + +void setup() +{ + Serial.begin(230400); + Serial.print("MCP23008_test version: "); + Serial.println(MCP23008_LIB_VERSION); + + Wire.begin(); + MCP.begin(); + + MCP.pinMode8(0x00); + + Serial.println("TEST digitalRead(pin)"); + for (int pin = 0; pin < 8; pin++) + { + int val = MCP.digitalRead(pin); + Serial.print(val); + Serial.print('\t'); + } + Serial.println(); +} + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/MCP23008/examples/MCP23008_digitalWrite/MCP23008_digitalWrite.ino b/libraries/MCP23008/examples/MCP23008_digitalWrite/MCP23008_digitalWrite.ino new file mode 100644 index 00000000..4c8a1ef7 --- /dev/null +++ b/libraries/MCP23008/examples/MCP23008_digitalWrite/MCP23008_digitalWrite.ino @@ -0,0 +1,68 @@ +// +// FILE: MCP23008_digitalWrite.ino +// AUTHOR: Rob Tillaart +// DATE: 2019-10-14 +// PUPROSE: test MCP23008 library + + +#include "MCP23008.h" +#include "Wire.h" + + +MCP23008 MCP(0x27); + + +void setup() +{ + Serial.begin(230400); + Serial.print("MCP23008_test version: "); + Serial.println(MCP23008_LIB_VERSION); + + Wire.begin(); + + MCP.begin(); + + MCP.pinMode8(0x00); // 0 = output , 1 = input + Wire.setClock(100000); + + Serial.println("TEST digitalWrite(0)"); + for (int i = 0; i < 8; i++) + { + MCP.digitalWrite(0, i % 2); // alternating HIGH/LOW + Serial.print(i % 2); + Serial.print('\t'); + delay(250); + } + Serial.println(); + Serial.println(); + + Serial.println("TEST digitalWrite(pin)"); + for (int pin = 0; pin < 8; pin++) + { + MCP.digitalWrite(pin, 1 - pin % 2); // alternating HIGH/LOW + Serial.print(1 - pin % 2); + Serial.print('\t'); + } + Serial.println(); + Serial.println(); + + Serial.println("TEST read back"); + + for (int pin = 0; pin < 8; pin++) + { + int val = MCP.digitalRead(pin); + Serial.print(val); + Serial.print('\t'); + } + Serial.println(); + Serial.println(); +} + + +void loop() +{ +} + + +// -- END OF FILE -- + diff --git a/libraries/MCP23008/examples/MCP23008_performance/MCP23008_performance.ino b/libraries/MCP23008/examples/MCP23008_performance/MCP23008_performance.ino new file mode 100644 index 00000000..5a06c165 --- /dev/null +++ b/libraries/MCP23008/examples/MCP23008_performance/MCP23008_performance.ino @@ -0,0 +1,97 @@ +// +// FILE: MCP23008_performance.ino +// AUTHOR: Rob Tillaart +// DATE: 2022-01-09 +// PUPROSE: test MCP23008 library + + +#include "MCP23008.h" +#include "Wire.h" + +MCP23008 MCP(0x27); + +uint32_t start, stop; + + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.print("MCP23008_LIB_VERSION: "); + Serial.println(MCP23008_LIB_VERSION); + Serial.println(); + delay(100); + + Wire.begin(); + bool b = MCP.begin(); + + MCP.pinMode8(0x00); // 0 = output , 1 = input + + Serial.println("\ntime in microseconds\n"); + delay(100); + + + Serial.print("TEST digitalWrite(0, value):\t"); + delay(100); + start = micros(); + for (int i = 0; i < 8; i++) + { + MCP.digitalWrite(i, i & 0x01); // alternating HIGH/LOW + } + stop = micros(); + Serial.println((stop - start) / 8.0); + + + Serial.print("TEST digitalWrite(pin, value):\t"); + delay(100); + start = micros(); + for (int pin = 0; pin < 8; pin++) + { + MCP.digitalWrite(pin, 1 - pin % 2); // alternating HIGH/LOW + } + stop = micros(); + Serial.println((stop - start) / 8.0); + + + Serial.print("TEST digitalRead(pin):\t"); + delay(100); + start = micros(); + for (int pin = 0; pin < 8; pin++) + { + volatile int val = MCP.digitalRead(pin); + } + stop = micros(); + Serial.println((stop - start) / 8.0); + Serial.println(); + + + ////////////////////////////////////////////////// + // + // write8 read8 interface + // + Serial.print("TEST write8(mask):\t"); + delay(100); + start = micros(); + MCP.write8(0xAA); // alternating HIGH/LOW + stop = micros(); + Serial.println(stop - start); + + + Serial.print("TEST read8():\t"); + delay(100); + start = micros(); + volatile int val8 = MCP.read8(); + stop = micros(); + Serial.println(stop - start); + Serial.println(); + + Serial.println("\ndone..."); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/MCP23008/library.json b/libraries/MCP23008/library.json new file mode 100644 index 00000000..43d2bf36 --- /dev/null +++ b/libraries/MCP23008/library.json @@ -0,0 +1,23 @@ +{ + "name": "MCP23008", + "keywords": "MCP23008,I2C, 8 IO, polarity, pullup", + "description": "Arduino library for I2C MCP23008 8 channel port expander", + "authors": + [ + { + "name": "Rob Tillaart", + "email": "Rob.Tillaart@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/RobTillaart/MCP23008.git" + }, + "version": "0.1.0", + "license": "MIT", + "frameworks": "arduino", + "platforms": "*", + "headers": "MCP23008.h" +} diff --git a/libraries/MCP23008/library.properties b/libraries/MCP23008/library.properties new file mode 100644 index 00000000..894ec0a8 --- /dev/null +++ b/libraries/MCP23008/library.properties @@ -0,0 +1,11 @@ +name=MCP23008 +version=0.1.0 +author=Rob Tillaart +maintainer=Rob Tillaart +sentence=Arduino library for I2C MCP23008 8 channel port expander 8 IO-lines +paragraph= setPolarity, setPullup +category=Signal Input/Output +url=https://github.com/RobTillaart/MCP23008 +architectures=* +includes=MCP23008.h +depends= diff --git a/libraries/MCP23008/test/unit_test_001.cpp b/libraries/MCP23008/test/unit_test_001.cpp new file mode 100644 index 00000000..dece2d06 --- /dev/null +++ b/libraries/MCP23008/test/unit_test_001.cpp @@ -0,0 +1,107 @@ +// +// FILE: unit_test_001.cpp +// AUTHOR: Rob Tillaart +// DATE: 2022-01-10 +// PURPOSE: unit tests for the MCP23008 +// https://github.com/RobTillaart/MCP23008 +// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md +// + +// supported assertions +// ---------------------------- +// assertEqual(expected, actual); // a == b +// assertNotEqual(unwanted, actual); // a != b +// assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b)) +// assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b)) +// assertLess(upperBound, actual); // a < b +// assertMore(lowerBound, actual); // a > b +// assertLessOrEqual(upperBound, actual); // a <= b +// assertMoreOrEqual(lowerBound, actual); // a >= b +// assertTrue(actual); +// assertFalse(actual); +// assertNull(actual); + +// // special cases for floats +// assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon +// assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon +// assertInfinity(actual); // isinf(a) +// assertNotInfinity(actual); // !isinf(a) +// assertNAN(arg); // isnan(a) +// assertNotNAN(arg); // !isnan(a) + +#include + + +#include "Arduino.h" +#include "MCP23008.h" + + +unittest_setup() +{ + fprintf(stderr, "MCP23008_LIB_VERSION: %s\n", (char *) MCP23008_LIB_VERSION); +} + + +unittest_teardown() +{ +} + + +unittest(test_constants) +{ + assertEqual(MCP23008_OK , 0x00); + assertEqual(MCP23008_PIN_ERROR , 0x81); + assertEqual(MCP23008_I2C_ERROR , 0x82); + assertEqual(MCP23008_VALUE_ERROR , 0x83); + assertEqual(MCP23008_PORT_ERROR , 0x84); + assertEqual(MCP23008_INVALID_READ, -100); +} + + +// TODO more tests if godmode->wire works +unittest(test_constructor) +{ + Wire.resetMocks(); + + MCP23008 MCP(0x27); + + assertFalse(Wire.didBegin()); + MCP.begin(); + // in fact invalid ... + assertTrue(Wire.didBegin()); + assertTrue(MCP.isConnected()); +} + + +unittest(test_lastError) +{ + Wire.resetMocks(); + + MCP23008 MCP(0x27); + MCP.begin(); + assertEqual(MCP23008_OK, MCP.lastError()); + + // MCP23008_PIN_ERROR + MCP.pinMode(8, INPUT); + assertEqual(MCP23008_PIN_ERROR, MCP.lastError()); + assertEqual(MCP23008_OK, MCP.lastError()); + + MCP.digitalWrite(8, 1); + assertEqual(MCP23008_PIN_ERROR, MCP.lastError()); + assertEqual(MCP23008_OK, MCP.lastError()); + + uint8_t y = MCP.digitalRead(8); + assertEqual(MCP23008_PIN_ERROR, MCP.lastError()); + assertEqual(MCP23008_OK, MCP.lastError()); + + + // MCP23008_VALUE_ERROR - 3 is not INPUT, INPUT_PULLUP, OUTPUT) + MCP.pinMode(0, 3); + assertEqual(MCP23008_VALUE_ERROR, MCP.lastError()); + assertEqual(MCP23008_OK, MCP.lastError()); +} + + +unittest_main() + +// --------