Skip to content

Commit

Permalink
Fix #28, refactor interface (#29)
Browse files Browse the repository at this point in the history
- refactor constructor interface - breaking changes.
  - minimize conditional code. -- create SPI_CLASS macro to solve it.
- update readme.md
- update examples
  • Loading branch information
RobTillaart authored Dec 1, 2023
1 parent 343935a commit 0a785c1
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 128 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.3.0] - 2023-12-01
- refactor constructor interface - breaking changes.
- minimize conditional code. -- create SPI_CLASS macro to solve it.
- update readme.md
- update examples

----

## [0.2.7] - 2023-11-13
- update readme.md
- add ledbar example


## [0.2.6] - 2023-08-15
- optimize 16 bit interface
- add readReg16() + writeReg16()
Expand Down
64 changes: 2 additions & 62 deletions MCP23S17.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ MCP23S17::MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t cloc


// HARDWARE SPI
MCP23S17::MCP23S17(uint8_t select, SPIClass* spi)
MCP23S17::MCP23S17(uint8_t select, __SPI_CLASS__ * spi)
{
MCP23S17(select, 0x00, spi);
}


MCP23S17::MCP23S17(uint8_t select, uint8_t address, SPIClass* spi)
MCP23S17::MCP23S17(uint8_t select, uint8_t address, __SPI_CLASS__ * spi)
{
_address = (address << 1);
_select = select;
Expand All @@ -50,24 +50,8 @@ bool MCP23S17::begin()

if (_hwSPI)
{
#if defined(ESP32)
if (_useHSPI) // HSPI
{
_mySPI = new SPIClass(HSPI);
_mySPI->end();
_mySPI->begin(14, 12, 13, _select); // CLK=14 MISO=12 MOSI=13
}
else // VSPI
{
_mySPI = new SPIClass(VSPI);
_mySPI->end();
_mySPI->begin(18, 19, 23, _select); // CLK=18 MISO=19 MOSI=23
}
#else // generic hardware SPI
_mySPI = &SPI;
_mySPI->end();
_mySPI->begin();
#endif
}
else
{
Expand Down Expand Up @@ -596,50 +580,6 @@ void MCP23S17::disableHardwareAddress()
}


#if defined(ESP32)

void MCP23S17::selectHSPI()
{
_useHSPI = true;
}


void MCP23S17::selectVSPI()
{
_useHSPI = false;
}


bool MCP23S17::usesHSPI()
{
return _useHSPI;
}


bool MCP23S17::usesVSPI()
{
return !_useHSPI;
}


void MCP23S17::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)
{
_clock = clk;
_dataOut = mosi;
_dataIn = miso;
_select = select;
pinMode(_select, OUTPUT);
digitalWrite(_select, HIGH);

_mySPI->end(); // disable old SPI

_mySPI->begin(clk, miso, mosi, select); // enable new pins
}

#endif



////////////////////////////////////////////////////
//
// PRIVATE
Expand Down
40 changes: 15 additions & 25 deletions MCP23S17.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: MCP23S17.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.7
// VERSION: 0.3.0
// PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander
// DATE: 2021-12-30
// URL: https://github.com/RobTillaart/MCP23S17
Expand All @@ -13,7 +13,7 @@
#include "MCP23S17_registers.h"


#define MCP23S17_LIB_VERSION (F("0.2.7"))
#define MCP23S17_LIB_VERSION (F("0.3.0"))

// ERROR CODES
#define MCP23S17_OK 0x00
Expand All @@ -24,20 +24,27 @@
#define MCP23S17_REGISTER_ERROR 0xFF
#define MCP23S17_INVALID_READ 0xFF

#ifndef __SPI_CLASS__
#if defined(ARDUINO_ARCH_RP2040)
#define __SPI_CLASS__ SPIClassRP2040
#else
#define __SPI_CLASS__ SPIClass
#endif
#endif


const uint32_t MCP23S17_TYP_SPI_SPEED = 8000000;
const uint32_t MCP23S17_MAX_SPI_SPEED = 10000000;



class MCP23S17
{
public:
// SOFTWARE SPI
MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00);
// HARDWARE SPI
MCP23S17(uint8_t select, SPIClass* spi);
MCP23S17(uint8_t select, uint8_t address = 0x00, SPIClass* spi = &SPI);
MCP23S17(uint8_t select, __SPI_CLASS__ * spi);
MCP23S17(uint8_t select, uint8_t address = 0x00, __SPI_CLASS__ * spi = &SPI);

bool begin();
bool isConnected();
Expand Down Expand Up @@ -96,19 +103,6 @@ class MCP23S17
void enableHardwareAddress();
void disableHardwareAddress();

// ESP32 specific
#if defined(ESP32)

void selectHSPI();
void selectVSPI();
bool usesHSPI();
bool usesVSPI();

// to overrule the ESP32s default hardware pins
void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);

#endif


private:
// access to low level registers (just make these two functions public).
Expand All @@ -126,18 +120,14 @@ class MCP23S17
uint8_t _clock = 0;
uint8_t _error = MCP23S17_OK;

bool _hwSPI = true;
bool _hwSPI = true;

// 10 MHz is maximum, 8 is a better clock divider on AVR.
uint32_t _SPIspeed = MCP23S17_TYP_SPI_SPEED;
SPIClass * _mySPI;
SPISettings _spi_settings;
__SPI_CLASS__ * _mySPI;
SPISettings _spi_settings;

uint8_t swSPI_transfer(uint8_t val);

#if defined(ESP32)
bool _useHSPI = true;
#endif
};


Expand Down
42 changes: 10 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ This IC is strongly related to the MCP23017 I2C port expander - https://github.c
Programming Interface is kept the same as much as possible.


#### 0.3.0 Breaking change

The version 0.3.0 has breaking changes in the interface.
The essence is removal of ESP32 specific code from the library.
This makes it possible to support the ESP32-S3 and other processors in the future.
Also it makes the library a bit simpler to maintain.


#### Related

16 bit port expanders
Expand All @@ -47,7 +55,9 @@ Programming Interface is kept the same as much as possible.
### Constructor

- **MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00)** constructor SOFTWARE SPI.
- **MCP23S17(uint8_t select, SPIClassRP2040\* spi)** constructor HARDWARE SPI with explicit SPI interface selected.
- **MCP23S17(uint8_t select, SPIClass\* spi)** constructor HARDWARE SPI with explicit SPI interface selected.
- **MCP23S17(uint8_t select, uint8_t address = 0x00, SPIClassRP2040\* spi = &SPI)** constructor HARDWARE SPI with optional address pins and SPI interface.
- **MCP23S17(uint8_t select, uint8_t address = 0x00, SPIClass\* spi = &SPI)** constructor HARDWARE SPI with optional address pins and SPI interface.
- **bool begin()** returns true if successful.
- **bool isConnected()** returns true if connected, false otherwise. (dummy for compatibility reasons)
Expand Down Expand Up @@ -161,38 +171,6 @@ Two dedicated functions are added since 0.2.5.
- **void disableHardwareAddress()** clear IOCR_HAEN bit.


### ESP32 HW SPI port selection

This functionality is new in 0.2.5.

- **void selectHSPI()** in case hardware SPI, the ESP32 has two options HSPI and VSPI.
- **void selectVSPI()** see above.
- **bool usesHSPI()** returns true if HSPI is used.
- **bool usesVSPI()** returns true if VSPI is used.

The **selectVSPI()** or the **selectHSPI()** needs to be called
BEFORE the **begin()** function.


#### Experimental

- **void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)**
overrule GPIO pins of ESP32 for hardware SPI.
Needs to be called AFTER the **begin()** function.

```cpp
void setup()
{
MCP.selectVSPI();
MCP.begin(15);
MCP.setGPIOpins(CLK, MISO, MOSI, SELECT); // SELECT should match the param of begin()
}
```

This interface can change in the future as the **select** pin is known
in the code.


### Error codes

If one of the above functions return false, there might be an error.
Expand Down
100 changes: 100 additions & 0 deletions examples/MCP23S17_four_ADDRESS_array/MCP23S17_four_ADDRESS_array.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// FILE: MCP23S17_four_ADDRESS_array.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo two MCP23S17 devices
// URL: https://github.com/RobTillaart/MCP23S17
//
// #27, experimental, not tested with hardware yet


#include "MCP23S17.h"
#include "SPI.h"


MCP23S17 MCP_A(10, 12, 11, 13, 0); // SW SPI, address 0
MCP23S17 MCP_B(10, 12, 11, 13, 1); // SW SPI, address 1
MCP23S17 MCP_C(10, 12, 11, 13, 2); // SW SPI, address 2
MCP23S17 MCP_D(10, 12, 11, 13, 3); // SW SPI, address 3

// MCP23S17 MCP_A(10, 0); // HW SPI, address 0
// MCP23S17 MCP_B(10, 1); // HW SPI, address 1
// MCP23S17 MCP_C(10, 2); // HW SPI, address 2
// MCP23S17 MCP_D(10, 3); // HW SPI, address 3

MCP23S17 MCP[4] = { MCP_A, MCP_B, MCP_C, MCP_D };


void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
Serial.println();
delay(100);

SPI.begin();
for (int addr = 0; addr < 4; addr++)
{
MCP[addr].begin();
MCP[addr].enableHardwareAddress();
}

// test connected
for (int addr = 0; addr < 4; addr++)
{
Serial.print(addr);
Serial.print("\t");
Serial.println(testConnection(MCP[addr]));
}

// set all pins OUTPUT => LOW
for (int addr = 0; addr < 4; addr++)
{
MCP[addr].pinMode16(0);
MCP[addr].write16(0x0000);
}
}


void loop()
{
int pin = random(64);
int addr = random(4);
MCP[addr].digitalWrite(pin, HIGH);
delay(100);
MCP[addr].digitalWrite(pin, LOW);
delay(100);
}



//
// the connection test tries to write a magic number to a register
// and read it back. If it is the same it is assumed to be connected
//
int testConnection(MCP23S17 & mcp)
{
uint16_t magic_test_number = 0xABCD;

// Read the current polarity config to restore later
uint16_t old_value;
if (! mcp.getPolarity16(old_value)) return -1;

// Write the magic number to polarity register
if (! mcp.setPolarity16(magic_test_number)) return -2;

// Read back the magic number from polarity register
uint16_t temp;
if (! mcp.getPolarity16(temp)) return -3;

// Write old config to polarity register
if (! mcp.setPolarity16(old_value)) return -4;

// Check the magic connection test
if (temp != magic_test_number) return -5;

return 0; // OK
}

// -- END OF FILE --
6 changes: 0 additions & 6 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ disableControlRegister KEYWORD2
enableHardwareAddress KEYWORD2
disableHardwareAddress KEYWORD2

selectHSPI KEYWORD2
selectVSPI KEYWORD2
usesHSPI KEYWORD2
usesVSPI KEYWORD2
setGPIOpins KEYWORD2


# Instances (KEYWORD2)

Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/MCP23S17.git"
},
"version": "0.2.7",
"version": "0.3.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=MCP23S17
version=0.2.7
version=0.3.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for SPI MCP23S17 16 channel port expander 16 IO-lines
Expand Down

0 comments on commit 0a785c1

Please sign in to comment.