1
1
//
2
2
// FILE: MCP23017.cpp
3
3
// AUTHOR: Rob Tillaart
4
- // VERSION: 0.7.1
4
+ // VERSION: 0.8.0
5
5
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
6
6
// DATE: 2019-10-12
7
7
// URL: https://github.com/RobTillaart/MCP23017_RT
@@ -95,6 +95,8 @@ bool MCP23017::pinMode1(uint8_t pin, uint8_t mode)
95
95
// only work with valid
96
96
if ((mode == INPUT) || (mode == INPUT_PULLUP))
97
97
{
98
+ // REV D
99
+ // if (pin == 7) return false;
98
100
val |= mask;
99
101
}
100
102
else if (mode == OUTPUT)
@@ -169,7 +171,6 @@ uint8_t MCP23017::read1(uint8_t pin)
169
171
IOR = MCP23x17_GPIO_B;
170
172
pin -= 8 ;
171
173
}
172
-
173
174
uint8_t val = readReg (IOR);
174
175
if (_error != MCP23017_OK)
175
176
{
@@ -512,10 +513,7 @@ bool MCP23017::getPullup16(uint16_t &mask)
512
513
//
513
514
// INTERRUPTS (experimental, see MCP23S17 - #40)
514
515
//
515
- // TODO, catch writeReg errors
516
516
// TODO, MCP23x17_INT_MODE_ERROR?
517
- // TODO, if register not changed no need to update?
518
- // TODO, 8 bits optimize? more code vs speed?
519
517
//
520
518
// pin = 0..15, mode = { RISING, FALLING, CHANGE }
521
519
bool MCP23017::enableInterrupt (uint8_t pin, uint8_t mode)
@@ -526,34 +524,75 @@ bool MCP23017::enableInterrupt(uint8_t pin, uint8_t mode)
526
524
return false ;
527
525
}
528
526
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
+
531
546
if (mode == CHANGE)
532
547
{
533
- // compare to previous value.
534
- intcon &= ~( 1 << pin) ;
548
+ // Compare to previous value
549
+ intcon &= ~mask ;
535
550
}
536
551
else
537
552
{
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;
539
559
if (mode == RISING)
540
560
{
541
- intcon |= (1 << pin);
542
- defval &= ~(1 << pin); // RISING == compare to 0
561
+ defval &= ~mask; // RISING == compare to 0
543
562
}
544
563
else if (mode == FALLING)
545
564
{
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 ;
548
584
}
549
- writeReg16 (MCP23x17_DEFVAL_A, defval);
550
585
}
551
- writeReg16 (MCP23x17_INTCON_A, intcon);
552
586
553
587
// 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
557
596
}
558
597
559
598
@@ -564,10 +603,28 @@ bool MCP23017::disableInterrupt(uint8_t pin)
564
603
_error = MCP23017_PIN_ERROR;
565
604
return false ;
566
605
}
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
+
567
615
// 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
571
628
}
572
629
573
630
0 commit comments