Skip to content

Commit 2c550a8

Browse files
authored
fix #47 (mcp23S17), enable interrupts (#39)
- fix #47 (MCP23S17), interrupt handling. Kudos to GlibSkunk! - update readme.md - minor edits. - add address table to readme.md`
1 parent 8a59909 commit 2c550a8

File tree

6 files changed

+142
-52
lines changed

6 files changed

+142
-52
lines changed

CHANGELOG.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88

9+
## [0.8.0] - 2024-11-19
10+
- fix #47 (MCP23S17), interrupt handling. Kudos to GlibSkunk!
11+
- update readme.md
12+
- minor edits.
13+
- add address table to readme.md`
14+
15+
----
16+
917
## [0.7.1] 2024-06-06
10-
- Fix #36, documentation bug.
18+
- fix #36, documentation bug.
1119

1220
## [0.7.0] 2024-06-06
1321
- fix #33 bug, kudos to JelleWilbrink
@@ -22,16 +30,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2230
- update keywords.txt
2331

2432
## [0.6.2] 2024-03-02
25-
- Fix #29, add parameter to **begin(bool pullup)**
33+
- fix #29, add parameter to **begin(bool pullup)**
2634
- remove DATE field from examples as it adds no value.
2735
- update GitHub/actions to version v4 in workflows.
2836

2937
## [0.6.1] 2024-01-05
30-
- Fix URL in examples
38+
- fix URL in examples
3139
- minor edits
3240

3341
## [0.6.0] 2023-12-24
34-
- Fix #26, support for Arduino ESP32 S3 - breaking change
42+
- fix #26, support for Arduino ESP32 S3 - breaking change
3543
- update readme.md
3644
- update examples.
3745

MCP23017.cpp

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// FILE: MCP23017.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.7.1
4+
// VERSION: 0.8.0
55
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
66
// DATE: 2019-10-12
77
// URL: https://github.com/RobTillaart/MCP23017_RT
@@ -95,6 +95,8 @@ bool MCP23017::pinMode1(uint8_t pin, uint8_t mode)
9595
// only work with valid
9696
if ((mode == INPUT) || (mode == INPUT_PULLUP))
9797
{
98+
// REV D
99+
// if (pin == 7) return false;
98100
val |= mask;
99101
}
100102
else if (mode == OUTPUT)
@@ -169,7 +171,6 @@ uint8_t MCP23017::read1(uint8_t pin)
169171
IOR = MCP23x17_GPIO_B;
170172
pin -= 8;
171173
}
172-
173174
uint8_t val = readReg(IOR);
174175
if (_error != MCP23017_OK)
175176
{
@@ -512,10 +513,7 @@ bool MCP23017::getPullup16(uint16_t &mask)
512513
//
513514
// INTERRUPTS (experimental, see MCP23S17 - #40)
514515
//
515-
// TODO, catch writeReg errors
516516
// TODO, MCP23x17_INT_MODE_ERROR?
517-
// TODO, if register not changed no need to update?
518-
// TODO, 8 bits optimize? more code vs speed?
519517
//
520518
// pin = 0..15, mode = { RISING, FALLING, CHANGE }
521519
bool MCP23017::enableInterrupt(uint8_t pin, uint8_t mode)
@@ -526,34 +524,75 @@ bool MCP23017::enableInterrupt(uint8_t pin, uint8_t mode)
526524
return false;
527525
}
528526

529-
// right mode
530-
uint16_t intcon = readReg16(MCP23x17_INTCON_A);
527+
uint8_t INTCONREG = MCP23x17_INTCON_A;
528+
uint8_t DEFVALREG = MCP23x17_DEFVAL_A;
529+
uint8_t GPINTENREG = MCP23x17_GPINTEN_A;
530+
if (pin > 7)
531+
{
532+
INTCONREG = MCP23x17_INTCON_B;
533+
DEFVALREG = MCP23x17_DEFVAL_B;
534+
GPINTENREG = MCP23x17_GPINTEN_B;
535+
pin -= 8;
536+
}
537+
uint8_t mask = 1 << pin;
538+
539+
uint8_t intcon = readReg(INTCONREG);
540+
uint8_t pre_intcon = intcon;
541+
if (_error != MCP23017_OK)
542+
{
543+
return false;
544+
}
545+
531546
if (mode == CHANGE)
532547
{
533-
// compare to previous value.
534-
intcon &= ~(1 << pin);
548+
// Compare to previous value
549+
intcon &= ~mask;
535550
}
536551
else
537552
{
538-
uint16_t defval = readReg16(MCP23x17_DEFVAL_A);
553+
// Compare to DEFVALREG
554+
intcon |= mask;
555+
556+
// Get and Modify Pin's Value in DEFVALREG
557+
uint8_t defval = readReg(DEFVALREG);
558+
uint8_t pre_defval = defval;
539559
if (mode == RISING)
540560
{
541-
intcon |= (1 << pin);
542-
defval &= ~(1 << pin); // RISING == compare to 0
561+
defval &= ~mask; // RISING == compare to 0
543562
}
544563
else if (mode == FALLING)
545564
{
546-
intcon |= (1 << pin);
547-
defval |= ~(1 << pin); // FALLING == compare to 1
565+
defval |= mask; // FALLING == compare to 1
566+
}
567+
// only write when changed.
568+
if (pre_defval != defval)
569+
{
570+
writeReg(DEFVALREG, defval);
571+
if (_error != MCP23017_OK)
572+
{
573+
return false;
574+
}
575+
}
576+
}
577+
// only write when changed.
578+
if (pre_intcon != intcon)
579+
{
580+
writeReg(INTCONREG, intcon);
581+
if (_error != MCP23017_OK)
582+
{
583+
return false;
548584
}
549-
writeReg16(MCP23x17_DEFVAL_A, defval);
550585
}
551-
writeReg16(MCP23x17_INTCON_A, intcon);
552586

553587
// enable interrupt
554-
uint16_t value = readReg16(MCP23x17_GPINTEN_A);
555-
value |= (1 << pin);
556-
return writeReg16(MCP23x17_GPINTEN_A, value);
588+
uint8_t gpinten = readReg(GPINTENREG);
589+
uint8_t pre_gpinten = gpinten;
590+
gpinten |= mask;
591+
if (pre_gpinten != gpinten)
592+
{
593+
return writeReg(GPINTENREG, gpinten);
594+
}
595+
return true; // Already enabled for pin
557596
}
558597

559598

@@ -564,10 +603,28 @@ bool MCP23017::disableInterrupt(uint8_t pin)
564603
_error = MCP23017_PIN_ERROR;
565604
return false;
566605
}
606+
607+
uint8_t GPINTENREG = MCP23x17_GPINTEN_A;
608+
if (pin > 7)
609+
{
610+
GPINTENREG = MCP23x17_GPINTEN_B;
611+
pin -= 8;
612+
}
613+
uint8_t mask = 1 << pin;
614+
567615
// disable interrupt
568-
uint16_t value = readReg16(MCP23x17_GPINTEN_A);
569-
value &= ~(1 << pin);
570-
return writeReg16(MCP23x17_GPINTEN_A, value);
616+
uint8_t gpinten = readReg(GPINTENREG);
617+
uint8_t pre_gpinten = gpinten;
618+
if (_error != MCP23017_OK)
619+
{
620+
return false;
621+
}
622+
gpinten &= ~mask;
623+
if (pre_gpinten != gpinten)
624+
{
625+
return writeReg(GPINTENREG, gpinten);
626+
}
627+
return true; // Already disabled for pin
571628
}
572629

573630

MCP23017.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22
//
33
// FILE: MCP23017.h
44
// AUTHOR: Rob Tillaart
5-
// VERSION: 0.7.1
5+
// VERSION: 0.8.0
66
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
77
// DATE: 2019-10-12
88
// URL: https://github.com/RobTillaart/MCP23017_RT
99
//
10-
// WARNING: please read REV D note in readme.md.
10+
// WARNING: please read REV D note in readme.md
11+
// about pin 7 and 15 and INPUT mode.
1112

1213

1314
#include "Arduino.h"
1415
#include "Wire.h"
1516
#include "MCP23x17_registers.h"
1617

1718

18-
#define MCP23017_LIB_VERSION (F("0.7.1"))
19+
#define MCP23017_LIB_VERSION (F("0.8.0"))
1920

2021
#define MCP23017_OK 0x00
2122
#define MCP23017_PIN_ERROR 0x81
@@ -39,6 +40,7 @@ class MCP23017
3940
// single pin interface
4041
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
4142
// do not use 0, 1 for mode.
43+
// See readme.md section REV D
4244
bool pinMode1(uint8_t pin, uint8_t mode);
4345
bool write1(uint8_t pin, uint8_t value);
4446
uint8_t read1(uint8_t pin);
@@ -51,7 +53,7 @@ class MCP23017
5153

5254
// 8 pins interface
5355
// port = 0..1
54-
// mask = 0x00..0xFF bit pattern,
56+
// mask = 0x00..0xFF bit pattern,
5557
// bit 0 = output mode, bit 1 = input mode
5658
// value = bit pattern.
5759
bool pinMode8(uint8_t port, uint8_t mask);
@@ -82,7 +84,7 @@ class MCP23017
8284
// pin = 0..15, mode = { RISING, FALLING, CHANGE }
8385
bool enableInterrupt(uint8_t pin, uint8_t mode);
8486
bool disableInterrupt(uint8_t pin);
85-
87+
8688
// mask = 0x0000..0xFFFF (overrides all earlier settings.
8789
bool enableInterrupt16(uint16_t mask, uint8_t mode);
8890
bool disableInterrupt16(uint16_t mask);
@@ -121,7 +123,7 @@ class MCP23017
121123
};
122124

123125

124-
/*
126+
/*
125127
TODO
126128
- can it protect the user
127129
- can we detect REV D chips (over I2C)
@@ -130,7 +132,7 @@ class MCP23017_REVD : public MCP23017
130132
{
131133
public:
132134
MCP23017_REVD(uint8_t address, TwoWire *wire = &Wire);
133-
135+
134136
- GPA7 and GPB7 should be set to output in constructor
135137
- GPA7 and GPB7 output mode may not change in any call
136138
- GPA7 and GPB7 should return last written value for read.

0 commit comments

Comments
 (0)