From b0d88122db6738137eee92f744bf5a9e86e154f8 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Mon, 10 Jan 2022 12:58:20 +0100 Subject: [PATCH] 0.1.1 MCP23S17 --- libraries/MCP23S17/MCP23S17.cpp | 99 ++++++++++++++++++- libraries/MCP23S17/MCP23S17.h | 85 +++++++--------- libraries/MCP23S17/README.md | 19 +++- .../MCP23S17_performance.ino | 26 ++++- .../MCP23S17_performance/performance_0.1.1.md | 34 +++++++ libraries/MCP23S17/library.json | 2 +- libraries/MCP23S17/library.properties | 2 +- 7 files changed, 205 insertions(+), 62 deletions(-) create mode 100644 libraries/MCP23S17/examples/MCP23S17_performance/performance_0.1.1.md diff --git a/libraries/MCP23S17/MCP23S17.cpp b/libraries/MCP23S17/MCP23S17.cpp index c612a1ce..286fe5f8 100644 --- a/libraries/MCP23S17/MCP23S17.cpp +++ b/libraries/MCP23S17/MCP23S17.cpp @@ -1,14 +1,15 @@ // // FILE: MCP23S17.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 +// VERSION: 0.1.1 // PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander // DATE: 2021-12-30 -// URL: https://github.com/RobTillaart/MCP23S17_RT +// URL: https://github.com/RobTillaart/MCP23S17 // // HISTORY: // 0.1.0 2021-12-30 initial version (a 2019 version did not make it) +// 0.1.1 2022-01-10 add 16 bit interface #include "Arduino.h" @@ -476,6 +477,94 @@ bool MCP23S17::getPullup8(uint8_t port, uint8_t &mask) } +/////////////////////////////////////////////////////////////////////// +// 16 pins interface +// two register at once +// value = 0..0xFFFF bit pattern +bool MCP23S17::pinMode16(uint16_t value) +{ + writeReg(MCP23S17_DDR_A, value >> 8); + writeReg(MCP23S17_DDR_B, value & 8); + _error = MCP23S17_OK; + return true; +} + + +// value = 0..0xFFFF bit pattern +bool MCP23S17::write16(uint16_t value) +{ + writeReg(MCP23S17_GPIO_A, value >> 8); + writeReg(MCP23S17_GPIO_B, value & 8); + _error = MCP23S17_OK; + return true; +} + + +// return = 0..0xFFFF bit pattern +uint16_t MCP23S17::read16() +{ + _error = MCP23S17_OK; + uint16_t value = readReg(MCP23S17_GPIO_A); + value <<= 8; + value += readReg(MCP23S17_GPIO_B); + return value; +} + + +// mask = 0..0xFFFF bit pattern +bool MCP23S17::setPolarity16(uint16_t mask) +{ + writeReg(MCP23S17_POL_A, mask >> 8); + writeReg(MCP23S17_POL_B, mask & 8); + if (_error != MCP23S17_OK) + { + return false; + } + return true; +} + + +// mask = 0..0xFFFF bit pattern +bool MCP23S17::getPolarity16(uint16_t &mask) +{ + mask = readReg(MCP23S17_POL_A); + mask <<= 8; + mask += readReg(MCP23S17_POL_B); + if (_error != MCP23S17_OK) + { + return false; + } + return true; +} + + +// mask = 0..0xFFFF bit pattern +bool MCP23S17::setPullup16(uint16_t mask) +{ + writeReg(MCP23S17_PUR_A, mask >> 8); + writeReg(MCP23S17_PUR_B, mask & 8); + if (_error != MCP23S17_OK) + { + return false; + } + return true; +} + + +// mask = 0..0xFFFF bit pattern +bool MCP23S17::getPullup16(uint16_t &mask) +{ + mask = readReg(MCP23S17_PUR_A); + mask <<= 8; + mask += readReg(MCP23S17_PUR_B); + if (_error != MCP23S17_OK) + { + return false; + } + return true; +} + + int MCP23S17::lastError() { int e = _error; @@ -487,13 +576,13 @@ int MCP23S17::lastError() //////////////////////////////////////////////////// // // PRIVATE -// +// bool MCP23S17::writeReg(uint8_t reg, uint8_t value) { _error = MCP23S17_OK; - if (reg > MCP23S17_OLAT_B) + if (reg > MCP23S17_OLAT_B) { _error = 0xFF; // TODO MAGIC NR return false; @@ -524,7 +613,7 @@ uint8_t MCP23S17::readReg(uint8_t reg) _error = MCP23S17_OK; - if (reg > MCP23S17_OLAT_B) + if (reg > MCP23S17_OLAT_B) { _error = 0xFF; // TODO MAGIC NR return false; diff --git a/libraries/MCP23S17/MCP23S17.h b/libraries/MCP23S17/MCP23S17.h index 2ce04988..5c5484ea 100644 --- a/libraries/MCP23S17/MCP23S17.h +++ b/libraries/MCP23S17/MCP23S17.h @@ -5,28 +5,7 @@ // VERSION: 0.1.1 // PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander // DATE: 2021-12-30 -// URL: https://github.com/RobTillaart/MCP23S17_RT -// -// dip layout -// -// +-----||-----+ -// GPB0 | o o | GPA7 -// GPB1 | o o | GPA6 -// GPB2 | o o | GPA5 -// GPB3 | o o | GPA4 -// GPB4 | o o | GPA3 -// GPB5 | o o | GPA2 -// GPB6 | o o | GPA1 -// GPB7 | o o | GPA0 -// +5V | o o | INTA -// GND | o o | INTB -// _CS_ | o o | _RESET_ -// CLK | o o | A2 -// SI | o o | A1 -// SO | o o | A0 -// +------------+ -// -// note: Connect Address pins (default GND == address 0x00) +// URL: https://github.com/RobTillaart/MCP23S17 #include "Arduino.h" @@ -48,39 +27,49 @@ class MCP23S17 { public: - // MCP23S17(); - MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00); MCP23S17(uint8_t select, uint8_t address = 0x00); - bool begin(); - bool isConnected(); // needed ? + bool begin(); + bool isConnected(); // needed ? // 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 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); + 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 // port = 0..1 // value = bit pattern - bool pinMode8(uint8_t port, uint8_t value); - bool write8(uint8_t port, uint8_t value); - int read8(uint8_t port); + bool pinMode8(uint8_t port, uint8_t value); + bool write8(uint8_t port, uint8_t value); + int read8(uint8_t port); + + bool setPolarity8(uint8_t port, uint8_t mask); + bool getPolarity8(uint8_t port, uint8_t &mask); + bool setPullup8(uint8_t port, uint8_t mask); + bool getPullup8(uint8_t port, uint8_t &mask); - bool setPolarity8(uint8_t port, uint8_t mask); - bool getPolarity8(uint8_t port, uint8_t &mask); - bool setPullup8(uint8_t port, uint8_t mask); - bool getPullup8(uint8_t port, uint8_t &mask); + // 16 pins interface + // value = bit pattern + bool pinMode16(uint16_t value); + bool write16(uint16_t value); + uint16_t read16(); + + bool setPolarity16(uint16_t mask); + bool getPolarity16(uint16_t &mask); + bool setPullup16(uint16_t mask); + bool getPullup16(uint16_t &mask); + // speed in Hz void setSPIspeed(uint32_t speed); @@ -91,15 +80,15 @@ public: int lastError(); private: - bool writeReg(uint8_t reg, uint8_t value); - uint8_t readReg(uint8_t reg); + bool writeReg(uint8_t reg, uint8_t value); + uint8_t readReg(uint8_t reg); - uint8_t _address = 0; - uint8_t _select = 0; - uint8_t _dataOut = 0; - uint8_t _dataIn = 0; - uint8_t _clock = 0; - uint8_t _error = MCP23S17_OK; + uint8_t _address = 0; + uint8_t _select = 0; + uint8_t _dataOut = 0; + uint8_t _dataIn = 0; + uint8_t _clock = 0; + uint8_t _error = MCP23S17_OK; bool _hwSPI = false; uint32_t _SPIspeed = 8000000UL; // 1MHz is a safe value TODO CHECK datasheet diff --git a/libraries/MCP23S17/README.md b/libraries/MCP23S17/README.md index 14f18532..e6e5b02c 100644 --- a/libraries/MCP23S17/README.md +++ b/libraries/MCP23S17/README.md @@ -15,7 +15,7 @@ Arduino library for MCP23S17 16 channel SPI port expander. This experimental library gives easy control over the 16 pins of a (SPI) MCP23S17 chip. -This IC is strongly related tot the MCP23017 I2C port expander - https://github.com/RobTillaart/MCP23017_RT +This IC is strongly related to the MCP23017 I2C port expander - https://github.com/RobTillaart/MCP23017_RT Programming Interface is kept the same as much as possible. @@ -26,7 +26,7 @@ Programming Interface is kept the same as much as possible. - **MCP23S17(uint8_t select, uint8_t data, uint8_t clock)** constructor SW SPI - **MCP23S17(uint8_t select)** constructor HW SPI - **bool begin()** returns true if successful. -- **bool isConnected()** returns true if connected, false otherwise. +- **bool isConnected()** returns true if connected, false otherwise. (dummy) ### Single pin interface @@ -47,10 +47,21 @@ Programming Interface is kept the same as much as possible. - **uint8_t read8(uint8_t port)** port = 0..1, reads 8 pins into one byte. - **bool setPolarity8(uint8_t port, uint8_t mask)** port = 0..1, sets polarity for 8 channels at once. - **bool getPolarity8(uint8_t port, uint8_t &mask)** port = 0..1, reads polarity of 8 channels at once. -- **bool setPullup8(uint8_t port, uint8_t mask)** port = 0..1,, sets pull-up for 8 channels at once. +- **bool setPullup8(uint8_t port, uint8_t mask)** port = 0..1, sets pull-up for 8 channels at once. - **bool getPullup8(uint8_t port, uint8_t &mask)** port = 0..1, reads pull-up for 8 channels at once. +### 16 pins interface + +- **bool pinMode16(uint16_t value)** value = 0..0xFFFF, returns true if successful. +- **bool write16(uint16_t value)** value = 0..0xFFFF, returns true if successful. +- **uint16_t read16()** reads 16 pins into an uint16_t. +- **bool setPolarity16(uint16_t mask)** sets polarity for 16 channels. +- **bool getPolarity16(uint16_t &mask)** reads polarity of 16 channels. +- **bool setPullup16(uint16_t mask)** sets pull-up for 16 channels. +- **bool getPullup16(uint16_t &mask)** reads pull-up for 16 channels. + + ### Error codes - **int lastError()** Above functions set an error flag that can be read with this function. @@ -73,4 +84,4 @@ See examples. ## Future - keep functional in sync with MCP23017_RT - +- **isConnected()** is not really needed diff --git a/libraries/MCP23S17/examples/MCP23S17_performance/MCP23S17_performance.ino b/libraries/MCP23S17/examples/MCP23S17_performance/MCP23S17_performance.ino index 351f81d8..0d029eac 100644 --- a/libraries/MCP23S17/examples/MCP23S17_performance/MCP23S17_performance.ino +++ b/libraries/MCP23S17/examples/MCP23S17_performance/MCP23S17_performance.ino @@ -86,8 +86,29 @@ void setup() Serial.print("TEST read8(port):\t"); delay(100); start = micros(); - volatile int val = MCP.read8(0); - val = MCP.read8(1); + volatile int val8 = MCP.read8(0); + val8 = MCP.read8(1); + stop = micros(); + Serial.println((stop - start) / 2.0); + Serial.println(); + + + ////////////////////////////////////////////////// + // + // write16 read16 interface + // + Serial.print("TEST write16(mask):\t"); + delay(100); + start = micros(); + MCP.write16(0xAAAA); // alternating HIGH/LOW + stop = micros(); + Serial.println((stop - start) / 2.0); + + + Serial.print("TEST read16():\t"); + delay(100); + start = micros(); + volatile uint16_t val16 = MCP.read16(); stop = micros(); Serial.println((stop - start) / 2.0); Serial.println(); @@ -102,4 +123,3 @@ void loop() // -- END OF FILE -- - diff --git a/libraries/MCP23S17/examples/MCP23S17_performance/performance_0.1.1.md b/libraries/MCP23S17/examples/MCP23S17_performance/performance_0.1.1.md new file mode 100644 index 00000000..c4fde9f9 --- /dev/null +++ b/libraries/MCP23S17/examples/MCP23S17_performance/performance_0.1.1.md @@ -0,0 +1,34 @@ + + +# Performance test + +Test sketch MCP23S17_performance.ino + +Max clock frequency 10 MHz, for an UNO this is 8 MHz (divider of CPU clock) + +### Library version: 0.1.1 + +| Action | SW SPI | HW 1 MHz | HW 2 MHz | HW 4 MHz | HW 8 MHz | notes | +|:------------------------------|--------:|---------:|---------:|---------:|---------:|:---------:| +| TEST digitalWrite(0, value) | 892.25 | 87.75 | 64.00 | 52.25 | 46.25 | +| TEST digitalWrite(pin, value) | 893.75 | 89.75 | 65.25 | 53.00 | 47.50 | +| TEST digitalRead(pin) | 447.75 | 44.75 | 32.75 | 26.75 | 24.25 | +| | | | | | | +| TEST write8(port, mask) | 446.00 | 44.00 | 32.00 | 26.00 | 22.00 | +| TEST read8(port) | 446.00 | 44.00 | 32.00 | 26.00 | 22.00 | +| TEST write16(mask) | 446.00 | 46.00 | 34.00 | 28.00 | 22.00 | since 0.1.1 +| TEST read16() | 446.00 | 44.00 | 32.00 | 26.00 | 22.00 | since 0.1.1 + + + +### Notes + +Performance as expected. + + +### Future + +- test ESP32 and other platforms +- register based IO version for the SW SPI on AVR ? + + diff --git a/libraries/MCP23S17/library.json b/libraries/MCP23S17/library.json index 4ba02cc2..86f63358 100644 --- a/libraries/MCP23S17/library.json +++ b/libraries/MCP23S17/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/MCP23S17.git" }, - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/MCP23S17/library.properties b/libraries/MCP23S17/library.properties index b52bab41..587f7bac 100644 --- a/libraries/MCP23S17/library.properties +++ b/libraries/MCP23S17/library.properties @@ -1,5 +1,5 @@ name=MCP23S17 -version=0.1.0 +version=0.1.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for SPI MCP23S17 16 channel port expander 16 IO-lines