初始化提交
This commit is contained in:
7
arduino-cli/libraries/PinChangeInterrupt/.editorconfig
Normal file
7
arduino-cli/libraries/PinChangeInterrupt/.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
19
arduino-cli/libraries/PinChangeInterrupt/LICENSE
Normal file
19
arduino-cli/libraries/PinChangeInterrupt/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
|
||||
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.
|
||||
357
arduino-cli/libraries/PinChangeInterrupt/Readme.md
Normal file
357
arduino-cli/libraries/PinChangeInterrupt/Readme.md
Normal file
@@ -0,0 +1,357 @@
|
||||
PinChangeInterrupt Library 1.2.9
|
||||
================================
|
||||
|
||||

|
||||
|
||||
PinChangeInterrupt library with a resource friendly implementation (API and LowLevel).
|
||||
PinChangeInterrupts are different than normal Interrupts. See detail below.
|
||||
|
||||
##### Features:
|
||||
* PinChangeInterrupt for a lot of pins
|
||||
* Rising, Falling or Change detection for every pin separately
|
||||
* Usable on a lot Arduino compatible boards
|
||||
* Implementation is fast, compact and resource friendly
|
||||
* Ports/Pins can be manually deactivated in the Settings file
|
||||
* API and LowLevel option
|
||||
* Full Port0-3 support
|
||||
* .a linkage optimization (Arduino IDE)
|
||||
|
||||
<a href="https://www.buymeacoffee.com/nicohood"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
|
||||
|
||||
#### Supported pins for PinChangeInterrupt:
|
||||
See [PCINT pin table](https://github.com/NicoHood/PinChangeInterrupt/#pinchangeinterrupt-table) at the bottom for more details.
|
||||
|
||||
```
|
||||
Arduino Uno/Nano/Mini: All pins are usable
|
||||
Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
|
||||
A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)
|
||||
Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)
|
||||
HoodLoader2: All (broken out 1-7) pins are usable
|
||||
Attiny24/44/84: All pins are usable
|
||||
Attiny25/45/85: All pins are usable
|
||||
Attiny13: All pins are usable
|
||||
Attiny441/841: All pins are usable
|
||||
Attiny261/461/861: All pins are usable
|
||||
Attiny2313/2313A/4313: PORTB is usable
|
||||
ATmega644/ATmega644P/ATmega1284P: All pins are usable
|
||||
ATmega162: PORTA and PORTC usable
|
||||
ATmega48/88/168/328/328PB: All pins are usable
|
||||
```
|
||||
|
||||
Contact information can be found here:
|
||||
|
||||
www.nicohood.de
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Download the zip, extract and remove the "-master" of the folder.
|
||||
Install the library [as described here](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries).
|
||||
|
||||
This library can also be used with the [DMBS AVR Library Collection](https://github.com/NicoHood/avr) and a pure makefile.
|
||||
|
||||
How to use
|
||||
==========
|
||||
|
||||
It is important that you know at least the basic difference between **PinInterrupts** and **PinChangeInterrupts**.
|
||||
I will explain the basics of **PinChangeInterrupts** (PCINTs) based on an Arduino Uno.
|
||||
|
||||
On a standard Arduino Uno Pin 2 and 3 have **PinInterrupts**. Those are exclusively for a single pin and can detect RISING, FALLING and CHANGE.
|
||||
|
||||
**PinChangeInterrupts** instead are used for a whole port (they should have better named them PortChangeInterrupts) and can only detect CHANGE for a whole port.
|
||||
Each pin row (0-7, 8-13, A0-A5) represents a port. If an interrupt (ISR) occurs on one pin of a port
|
||||
it is still unclear what pin of the port caused this interrupt. Therefore this library saves the state of the whole port and compares with the last state.
|
||||
This way we can also see if it was a RISING or FALLING edge instead of only knowing the CHANGE.
|
||||
|
||||
A **PinChangeInterrupt** will only be triggered for the attached pins per port.
|
||||
Meaning if you set PCINT for a pin and another pin on the same port is changing a lot
|
||||
it will not interrupt your code.
|
||||
|
||||
**PinChangeInterrupts** might be a tiny bit slower and not that reliable because of that detection overhead (talking about micro seconds).
|
||||
Make sure to not use longer function calls inside the ISR or Serial print.
|
||||
You have the same issues on normal **PinInterrupts** and interrupts in general.
|
||||
|
||||
The library is coded to get maximum speed and minimum code size. The LowLevel example without the API takes 4uS to enter the interrupt function in the worst case
|
||||
which is pretty good and might be even better than the **PinInterrupt** code from the official Arduino core due to high optimization.
|
||||
If you need very precise interrupts you better use **PinInterrupts** without the Arduino IDE at all.
|
||||
|
||||
### Examples
|
||||
To see how the code works just check the Led and TickTock example.
|
||||
The LowLevel example is for advanced users with more optimization and more direct access.
|
||||
The HowItWorks example shows the basic PinChangeInterrupt setup and decoding routine, similar to the library.
|
||||
See the notes in the examples about more details.
|
||||
|
||||
An useful "real use" example of the PinChangeInterrupt library can be found here:
|
||||
https://github.com/NicoHood/IRLremote
|
||||
|
||||
### API Reference
|
||||
|
||||
##### Attach a PinChangeInterrupt
|
||||
```cpp
|
||||
// The pin has to be a PCINT number. Use the makro to convert a pin to a PCINT number.
|
||||
// Enables event functions which need to be defined in the sketch.
|
||||
// Valid interrupt modes are: RISING, FALLING or CHANGE
|
||||
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick), tick, RISING);
|
||||
|
||||
// You can also input the PCINT number (see table below)
|
||||
attachPinChangeInterrupt(5, tock, FALLING);
|
||||
|
||||
// PinChangeInterrupt can always be abbreviated with PCINT
|
||||
attachPCINT(digitalPinToPCINT(pinBlink), blinkLed, CHANGE);
|
||||
```
|
||||
|
||||
##### Detach a PinChangeInterrupt
|
||||
```cpp
|
||||
// Similar usage as the attachPCINT function.
|
||||
// Interrupts will no longer occur.
|
||||
detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
detachPinChangeInterrupt(5);
|
||||
detachPCINT(digitalPinToPCINT(pinTock));
|
||||
```
|
||||
|
||||
##### Enable/Disable a PinChangeInterrupt
|
||||
```cpp
|
||||
// Similar usage as the attachPCINT function.
|
||||
// Use this to temporary enable/disable the Interrupt
|
||||
disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
disablePinChangeInterrupt(5);
|
||||
disablePCINT(digitalPinToPCINT(pinBlink));
|
||||
|
||||
// Enable the PCINT with the old settings again (function + mode)
|
||||
enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
enablePinChangeInterrupt(5);
|
||||
enablePCINT(digitalPinToPCINT(pinBlink));
|
||||
```
|
||||
|
||||
##### Get Trigger on mode CHANGE
|
||||
```cpp
|
||||
// Differenciate between RISING and FALLING on mode CHANGE.
|
||||
// Only use this in the attached interrupt function.
|
||||
uint8_t trigger = getPinChangeInterruptTrigger(digitalPinToPCINT(pinTick));
|
||||
if(trigger == RISING)
|
||||
// Do something
|
||||
else if(trigger == FALLING)
|
||||
// Do something
|
||||
else
|
||||
// Wrong usage (trigger == CHANGE)
|
||||
```
|
||||
|
||||
##### LowLevel API
|
||||
See [LowLevel example](examples/PinChangeInterrupt_LowLevel/PinChangeInterrupt_LowLevel.ino) for more details.
|
||||
```cpp
|
||||
// Use the attach function as you are used to, just leave out the function name
|
||||
attachPinChangeInterrupt(interruptBlink, CHANGE);
|
||||
|
||||
// LowLevel function that is called when an interrupt occurs for a specific PCINT.
|
||||
// It is required to know the exact PCINT number, no Arduino pin number will work here.
|
||||
void PinChangeInterruptEvent(5)(void) {
|
||||
// Do something
|
||||
}
|
||||
```
|
||||
|
||||
PinchangeInterrupt Table
|
||||
========================
|
||||
Pins with * are not broken out/deactivated by default.
|
||||
You may activate them in the [setting file](https://github.com/NicoHood/PinChangeInterrupt/blob/master/src/PinChangeInterruptSettings.h#L98) (advanced).
|
||||
|
||||
Each row section represents a port(0-3).
|
||||
Not all MCUs have all Ports/Pins physically available.
|
||||
|
||||
**Note: Not all supported AVRs are listed here. There are way more supported, please refer to the shorter list above.**
|
||||
|
||||
#### Official Arduinos
|
||||
```
|
||||
| PCINT | Uno/Nano/Mini | Mega/2560 | Leonardo/Micro | HL2 (8/16/32u2) |
|
||||
| ----- | --------------- | -------------- | -------------- | --------------- |
|
||||
| 0 | 8 (PB0) | 53 SS (PB0) | SS (PB0)* | 0 SS (PB0)* |
|
||||
| 1 | 9 (PB1) | 52 SCK (PB1) | SCK (PB1) | 1 SCK (PB1) |
|
||||
| 2 | 10 SS (PB2) | 51 MOSI (PB2) | MOSI (PB2) | 2 MOSI (PB2) |
|
||||
| 3 | 11 MISO (PB3) | 50 MISO (PB3) | MISO (PB3) | 3 MISO (PB3) |
|
||||
| 4 | 12 MOSI (PB4) | 10 (PB4) | 8/A8 (PB4) | 4 (PB4) |
|
||||
| 5 | 13 SCK (PB5) | 11 (PB5) | 9/A9 (PB5) | 5 (PB5) |
|
||||
| 6 | XTAL1 (PB6)* | 12 (PB6) | 10/A10 (PB6) | 6 (PB6) |
|
||||
| 7 | XTAL2 (PB7)* | 13 (PB7) | 11 (PB7) | 7 (PB7) |
|
||||
| ----- | --------------- | -------------- | -------------- | --------------- |
|
||||
| 8 | A0 (PC0) | 0 RX (PE0)* | | (PC6)* |
|
||||
| 9 | A1 (PC1) | 15 RX3 (PJ0)* | | (PC5)* |
|
||||
| 10 | A2 (PC2) | 14 TX3 (PJ1)* | | (PC4)* |
|
||||
| 11 | A3 (PC3) | NC (PJ2)* | | (PC2)* |
|
||||
| 12 | A4 SDA (PC4) | NC (PJ3)* | | (PD5)* |
|
||||
| 13 | A5 SDC (PC5) | NC (PJ4)* | | |
|
||||
| 14 | RST (PC6)* | NC (PJ5)* | | |
|
||||
| 15 | | NC (PJ6)* | | |
|
||||
| ----- | --------------- | -------------- | -------------- | --------------- |
|
||||
| 16 | 0 RX (PD0) | A8 (PK0) | | |
|
||||
| 17 | 1 TX (PD1) | A9 (PK1) | | |
|
||||
| 18 | 2 INT0 (PD2) | A10 (PK2) | | |
|
||||
| 19 | 3 INT1 (PD3) | A11 (PK3) | | |
|
||||
| 20 | 4 (PD4) | A12 (PK4) | | |
|
||||
| 21 | 5 (PD5) | A13 (PK5) | | |
|
||||
| 22 | 6 (PD6) | A14 (PK6) | | |
|
||||
| 23 | 7 (PD7) | A15 (PK7) | | |
|
||||
| ----- | --------------- | -------------- | -------------- | --------------- |
|
||||
```
|
||||
|
||||
#### Atmel Attinys
|
||||
```
|
||||
| PCINT | Attiny13 | Attiny x4 | Attiny x5 | Attiny x41 |
|
||||
| ----- | ------------ | --------------- | ------------- | ------------------- |
|
||||
| 0 | 0 MOSI (PB0) | 0 (PA0) | 0 MOSI (PB0) | A0/D0 (PA0) |
|
||||
| 1 | 1 MISO (PB1) | 1 (PA1) | 1 MISO (PB1) | A1/D1 (PA1) |
|
||||
| 2 | 2 SCK (PB2) | 2 (PA2) | 2 SCK (PB2) | A2/D2 (PA2) |
|
||||
| 3 | 3 (PB3) | 3 (PA3) | 3 XTAL1 (PB3) | A3/D3 (PA3) |
|
||||
| 4 | 4 (PB4) | 4 SCK (PA4) | 4 XTAL2 (PB4) | A4/D4 (PA4) |
|
||||
| 5 | 5 RST (PB5) | 5 MISO (PA5) | 5 RST (PB5) | A5/D5 PWM (PA5) |
|
||||
| 6 | | 6 MOSI (PA6) | | A7/D7 PWM (PA6) |
|
||||
| 7 | | 7 (PA7) | | A6/D6 PWM (PA7) |
|
||||
| ----- | ------------ | --------------- | ------------- | ------------------- |
|
||||
| 8 | | 10 XTAL1 (PB0)* | | A10/D10 XTAL1 (PB0) |
|
||||
| 9 | | 9 XTAL2 (PB1)* | | A9/D9 XTAL2 (PB1) |
|
||||
| 10 | | 8 INT0 (PB2)* | | A8/D8 PWM (PB2) |
|
||||
| 11 | | RST (PB3)* | | RST (PB3) |
|
||||
| 12 | | | | |
|
||||
| 13 | | | | |
|
||||
| 14 | | | | |
|
||||
| 15 | | | | |
|
||||
| ----- | ------------ | --------------- | ------------- | ------------------- |
|
||||
```
|
||||
|
||||
#### Other Atmel MCUs
|
||||
```
|
||||
| PCINT | ATmega644P/1284P |
|
||||
| ----- | ----------------- |
|
||||
| 0 | A0/D24 (PA0) |
|
||||
| 1 | A1/D25 (PA1) |
|
||||
| 2 | A2/D26 (PA2) |
|
||||
| 3 | A3/D27 (PA3) |
|
||||
| 4 | A4/D28 (PA4) |
|
||||
| 5 | A5/D29 (PA5) |
|
||||
| 6 | A6/D30 (PA6) |
|
||||
| 7 | A7/D31 (PA7) |
|
||||
| ----- | ----------------- |
|
||||
| 8 | 0 (PB0) |
|
||||
| 9 | 1 (PB1) |
|
||||
| 10 | 2 INT2 (PB2) |
|
||||
| 11 | 3 PWM (PB3) |
|
||||
| 12 | 4 SS/PWM (PB4) |
|
||||
| 13 | 5 MOSI/PWM (PB5) |
|
||||
| 14 | 6 MISO/PWM (PB6) |
|
||||
| 15 | 7 SCK (PB7) |
|
||||
| ----- | ----------------- |
|
||||
| 16 | 16 SCL (PC0) |
|
||||
| 17 | 17 SDA (PC1) |
|
||||
| 18 | 18 TCK (PC2) |
|
||||
| 19 | 19 TMS (PC3) |
|
||||
| 20 | 20 TDO (PC4) |
|
||||
| 21 | 21 TDI (PC5) |
|
||||
| 22 | 22 (PC6) |
|
||||
| 23 | 23 (PC7) |
|
||||
| ----- | ----------------- |
|
||||
| 24 | 8 RX0 (PD0) |
|
||||
| 25 | 9 TX0 (PD1) |
|
||||
| 26 | 10 RX1/INT0 (PD2) |
|
||||
| 27 | 11 TX1/INT1 (PD3) |
|
||||
| 28 | 12 PWM (PD4) |
|
||||
| 29 | 13 PWM (PD5) |
|
||||
| 30 | 14 PWM (PD6) |
|
||||
| 31 | 15 PWM (PD7) |
|
||||
| ----- | ----------------- |
|
||||
```
|
||||
|
||||
Developer Information
|
||||
=====================
|
||||
If a PinChangeInterrupt occurs it will determine the triggered pin(s).
|
||||
The library uses weak callback functions that are called for the triggered pins(s).
|
||||
This way we can easily skip not triggered pins (I looked at the assembler) and also implement a fast LowLevel version.
|
||||
|
||||
Also the order of the function execution is (normally) ordered from the lower pin number to the higher.
|
||||
Meaning pin 8 will be checked faster as pin 13 (Arduino Uno). Talking about micro seconds here! You can change the order in the settings.
|
||||
For example by default pin 0-3 have a low priority order than pin 4-7 (Arduino Uno). Because they are used for Serial and normal PinInterrupts.
|
||||
I don't expect anyone to use those pins at all with PCINT but at least the priority is lowered compared to the other pins.
|
||||
|
||||
The API takes those weak functions and just overwrites all of them and call the function pointers of the attached functions instead.
|
||||
This way the function can be changed at runtime and its also easier to integrate into other libraries.
|
||||
The function pointers take a bit flash though (LowLevel: 1526/18, API: 1790/58 for Led example).
|
||||
|
||||
You can get better performance and less code size if you deactivate the not used pins/ports manually in the settings file.
|
||||
This way only the needed pins get compiled and the code is optimized by the preprocessor.
|
||||
For a bit more comfortable/automatic optimization you can [install the library into the core](https://github.com/NicoHood/PinChangeInterrupt/#optional-installation)
|
||||
to get use of the .a linkage. This way only the used ports get compiled.
|
||||
So if you only use pins on a single port (eg 8-13) then only this port gets compiled. This only works with the core installation.
|
||||
|
||||
|
||||
That's it! I hope you like the library. I tried to make it as simple and small as possible.
|
||||
Keep in mind that PCINTs are not useful for every project but in most cases
|
||||
the new PinChangeInterrupts may help you a lot.
|
||||
|
||||
|
||||
Version History
|
||||
===============
|
||||
```
|
||||
1.2.9 Release (18.05.2021)
|
||||
* Added Attiny261/461/861 support #39
|
||||
* Added Attiny2313/2313A/4313 support #37
|
||||
* Added ATMega328PB support #30
|
||||
* Added ATMega48 support #38
|
||||
* Fixed ATMega88/168 support #38
|
||||
|
||||
1.2.8 Release (22.11.2020)
|
||||
* Add support for ATmega644 #34
|
||||
|
||||
1.2.7 Release (07.10.2018)
|
||||
* Add support for ATmega162 #21
|
||||
|
||||
1.2.6 Release (10.02.2018)
|
||||
* Fix makefile compilation problems
|
||||
|
||||
1.2.5 Release (02.09.2017)
|
||||
* Fixed makefile compilation
|
||||
* Added support to disable pcint/port via -DPCINT_DISABLE_PORT0 etc.
|
||||
* Added ATtinyX313 support
|
||||
* Fix ATmega1284P
|
||||
|
||||
1.2.4 Release (16.04.2016)
|
||||
* Fixed Attinyx4/x5 Issue #8
|
||||
|
||||
1.2.3 Release (24.12.2015)
|
||||
* Added Attiny441/841 support
|
||||
|
||||
1.2.2 Release (05.12.2015)
|
||||
* Fixed initial value when enabled issue
|
||||
* Enabled official dot_a_linkage
|
||||
* Added Attiny13 support Issue #4
|
||||
* Updated documentation
|
||||
* Improved detaching function
|
||||
* Improved attaching and enabling
|
||||
|
||||
1.2.1 Release (24.05.2015)
|
||||
* Fix Attiny Issue #1
|
||||
* Added enable/disable function
|
||||
* Added getPinChangeInterruptTrigger() function
|
||||
* Added to Arduino IDE library manager
|
||||
|
||||
1.2 Release (19.04.2015)
|
||||
* Added weak interrupt function
|
||||
* Improved interrupt function calls
|
||||
* Fixed attach/detach array position when ports are deactivated
|
||||
* Improved manual PCINT deactivation by user
|
||||
* Improved definitions for different boards
|
||||
* HoodLoader2 definition fixes
|
||||
* Improved speed
|
||||
* Improved specific boards
|
||||
* Moved attach function to .cpp file
|
||||
* Updated examples
|
||||
* Added API and LowLevel
|
||||
* Added Port3 support (ATmega644P/ATmega1284P)
|
||||
* Added PCINT_VERSION definition
|
||||
|
||||
1.1 Release (06.12.2014)
|
||||
* Added port deactivation
|
||||
* Ram usage improvements for AVRs with <3 PCINT ports
|
||||
|
||||
1.0 Release (04.12.2014)
|
||||
* Added general PinChangeInterrupt functions
|
||||
* Added support for most Arduino boards
|
||||
* Added basic example
|
||||
* Added an example with IRLremote
|
||||
```
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
PinChangeInterrupt_HowItWorks
|
||||
Shows how to manually setup a single PCINT function with a few helper functions.
|
||||
|
||||
Connect a button/cable to pin 7 and ground.
|
||||
The led will change its state if pin 7 changes.
|
||||
|
||||
PinChangeInterrupts are different than normal Interrupts.
|
||||
See readme for more information.
|
||||
Dont use Serial or delay inside interrupts!
|
||||
This library is not compatible with SoftSerial.
|
||||
|
||||
The following pins are usable for PinChangeInterrupt:
|
||||
Arduino Uno/Nano/Mini: All pins are usable
|
||||
Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
|
||||
A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)
|
||||
Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)
|
||||
HoodLoader2: All (broken out 1-7) pins are usable
|
||||
Attiny 24/44/84: All pins are usable
|
||||
Attiny 25/45/85: All pins are usable
|
||||
Attiny 13: All pins are usable
|
||||
Attiny 441/841: All pins are usable
|
||||
ATmega644P/ATmega1284P: All pins are usable
|
||||
*/
|
||||
|
||||
//================================================================================
|
||||
// User Settings
|
||||
//================================================================================
|
||||
|
||||
// choose a valid PinChangeInterrupt pin of your Arduino board
|
||||
#define PCINT_PIN 7
|
||||
#define PCINT_MODE CHANGE
|
||||
#define PCINT_FUNCTION blinkLed
|
||||
|
||||
void setup()
|
||||
{
|
||||
// set pins to input with a pullup, led to output
|
||||
pinMode(PCINT_PIN, INPUT_PULLUP);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// attach the new PinChangeInterrupt
|
||||
attachPinChangeInterrupt();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// empty
|
||||
}
|
||||
|
||||
void blinkLed(void) {
|
||||
// switch Led state
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PCINT Definitions
|
||||
//================================================================================
|
||||
|
||||
#define PCMSK *digitalPinToPCMSK(PCINT_PIN)
|
||||
#define PCINT digitalPinToPCMSKbit(PCINT_PIN)
|
||||
#define PCIE digitalPinToPCICRbit(PCINT_PIN)
|
||||
#define PCPIN *portInputRegister(digitalPinToPort(PCINT_PIN))
|
||||
|
||||
#if (PCIE == 0)
|
||||
#define PCINT_vect PCINT0_vect
|
||||
#elif (PCIE == 1)
|
||||
#define PCINT_vect PCINT1_vect
|
||||
#elif (PCIE == 2)
|
||||
#define PCINT_vect PCINT2_vect
|
||||
#else
|
||||
#error This board doesnt support PCINT ?
|
||||
#endif
|
||||
|
||||
volatile uint8_t oldPort = 0x00;
|
||||
|
||||
void attachPinChangeInterrupt(void) {
|
||||
// update the old state to the actual state
|
||||
oldPort = PCPIN;
|
||||
|
||||
// pin change mask registers decide which pins are enabled as triggers
|
||||
PCMSK |= (1 << PCINT);
|
||||
|
||||
// PCICR: Pin Change Interrupt Control Register - enables interrupt vectors
|
||||
PCICR |= (1 << PCIE);
|
||||
}
|
||||
|
||||
void detachPinChangeInterrupt(void) {
|
||||
// disable the mask.
|
||||
PCMSK &= ~(1 << PCINT);
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (PCMSK == 0)
|
||||
PCICR &= ~(0x01 << PCIE);
|
||||
}
|
||||
|
||||
ISR(PCINT_vect) {
|
||||
// get the new and old pin states for port
|
||||
uint8_t newPort = PCPIN;
|
||||
|
||||
// compare with the old value to detect a rising or falling
|
||||
uint8_t change = newPort ^ oldPort;
|
||||
|
||||
// check which pins are triggered, compared with the settings
|
||||
uint8_t trigger = 0x00;
|
||||
#if (PCINT_MODE == RISING) || (PCINT_MODE == CHANGE)
|
||||
uint8_t rising = change & newPort;
|
||||
trigger |= (rising & (1 << PCINT));
|
||||
#endif
|
||||
#if (PCINT_MODE == FALLING) || (PCINT_MODE == CHANGE)
|
||||
uint8_t falling = change & oldPort;
|
||||
trigger |= (falling & (1 << PCINT));
|
||||
#endif
|
||||
|
||||
// save the new state for next comparison
|
||||
oldPort = newPort;
|
||||
|
||||
// if our needed pin has changed, call the IRL interrupt function
|
||||
if (trigger & (1 << PCINT))
|
||||
PCINT_FUNCTION();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
PinChangeInterrupt_TickTock
|
||||
Demonstrates how to use the library
|
||||
|
||||
Connect a button/cable to pin 7 and ground.
|
||||
The Led state will change if the pin state does.
|
||||
|
||||
PinChangeInterrupts are different than normal Interrupts.
|
||||
See readme for more information.
|
||||
Dont use Serial or delay inside interrupts!
|
||||
This library is not compatible with SoftSerial.
|
||||
|
||||
The following pins are usable for PinChangeInterrupt:
|
||||
Arduino Uno/Nano/Mini: All pins are usable
|
||||
Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
|
||||
A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)
|
||||
Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)
|
||||
HoodLoader2: All (broken out 1-7) pins are usable
|
||||
Attiny 24/44/84: All pins are usable
|
||||
Attiny 25/45/85: All pins are usable
|
||||
Attiny 13: All pins are usable
|
||||
Attiny 441/841: All pins are usable
|
||||
ATmega644P/ATmega1284P: All pins are usable
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
// Choose a valid PinChangeInterrupt pin of your Arduino board
|
||||
#define pinBlink 7
|
||||
|
||||
void setup() {
|
||||
// set pin to input with a pullup, led to output
|
||||
pinMode(pinBlink, INPUT_PULLUP);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// Manually blink once to test if LED is functional
|
||||
blinkLed();
|
||||
delay(1000);
|
||||
blinkLed();
|
||||
|
||||
// Attach the new PinChangeInterrupt and enable event function below
|
||||
attachPCINT(digitalPinToPCINT(pinBlink), blinkLed, CHANGE);
|
||||
}
|
||||
|
||||
void blinkLed(void) {
|
||||
// Switch Led state
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Nothing to do here
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
PinChangeInterrupt_LowLevel
|
||||
Demonstrates how to use the library without the API
|
||||
|
||||
Make sure to comment "//#define PCINT_API" in the settings file.
|
||||
|
||||
To maximize speed and size also uncomment all not used pins above.
|
||||
Then you could also uncomment "#define PCINT_COMPILE_ENABLED_ISR"
|
||||
to get away the .a linkage overhead.
|
||||
|
||||
Connect a button/cable to pin 7 and ground (Uno).
|
||||
Strong overwritten callback functions are called when an interrupt occurs.
|
||||
The Led state will change if the pin state does.
|
||||
|
||||
PinChangeInterrupts are different than normal Interrupts.
|
||||
See readme for more information.
|
||||
Dont use Serial or delay inside interrupts!
|
||||
This library is not compatible with SoftSerial.
|
||||
|
||||
The following pins are usable for PinChangeInterrupt:
|
||||
Arduino Uno/Nano/Mini: All pins are usable
|
||||
Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
|
||||
A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)
|
||||
Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)
|
||||
HoodLoader2: All (broken out 1-7) pins are usable
|
||||
Attiny 24/44/84: All pins are usable
|
||||
Attiny 25/45/85: All pins are usable
|
||||
Attiny 13: All pins are usable
|
||||
Attiny 441/841: All pins are usable
|
||||
ATmega644P/ATmega1284P: All pins are usable
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
// choose a valid PinChangeInterrupt pin of your Arduino board
|
||||
// manually defined pcint number
|
||||
#define pinBlink 7
|
||||
#define interruptBlink 23
|
||||
|
||||
void setup()
|
||||
{
|
||||
// set pin to input with a pullup, led to output
|
||||
pinMode(pinBlink, INPUT_PULLUP);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// attach the new PinChangeInterrupts and enable event functions below
|
||||
attachPinChangeInterrupt(interruptBlink, CHANGE);
|
||||
}
|
||||
|
||||
void PinChangeInterruptEvent(interruptBlink)(void) {
|
||||
// switch Led state
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// nothing to do here
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
PinChangeInterrupt_TickTock
|
||||
Demonstrates how to use the library
|
||||
|
||||
Connect a button/cable to pin 10/11 and ground.
|
||||
The value printed on the serial port will increase
|
||||
if pin 10 is rising and decrease if pin 11 is falling.
|
||||
|
||||
PinChangeInterrupts are different than normal Interrupts.
|
||||
See readme for more information.
|
||||
Dont use Serial or delay inside interrupts!
|
||||
This library is not compatible with SoftSerial.
|
||||
|
||||
The following pins are usable for PinChangeInterrupt:
|
||||
Arduino Uno/Nano/Mini: All pins are usable
|
||||
Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
|
||||
A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)
|
||||
Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)
|
||||
HoodLoader2: All (broken out 1-7) pins are usable
|
||||
Attiny 24/44/84: All pins are usable
|
||||
Attiny 25/45/85: All pins are usable
|
||||
Attiny 13: All pins are usable
|
||||
Attiny 441/841: All pins are usable
|
||||
ATmega644P/ATmega1284P: All pins are usable
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
// choose a valid PinChangeInterrupt pin of your Arduino board
|
||||
#define pinTick 10
|
||||
#define pinTock 11
|
||||
|
||||
volatile long ticktocks = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
// start serial debug output
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("Startup"));
|
||||
|
||||
// set pins to input with a pullup
|
||||
pinMode(pinTick, INPUT_PULLUP);
|
||||
pinMode(pinTock, INPUT_PULLUP);
|
||||
|
||||
// attach the new PinChangeInterrupts and enable event functions below
|
||||
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick), tick, RISING);
|
||||
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock), tock, FALLING);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// integer to count the number of prints
|
||||
static int i = 0;
|
||||
delay(1000);
|
||||
|
||||
// print values
|
||||
Serial.print(i, DEC);
|
||||
Serial.print(F(" "));
|
||||
Serial.println(ticktocks);
|
||||
|
||||
// abort if we printed 100 times
|
||||
if (i >= 100) {
|
||||
Serial.println(F("Detaching Interrupts."));
|
||||
detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock));
|
||||
return;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
||||
// Temporary pause interrupts
|
||||
if (ticktocks > 500) {
|
||||
Serial.println(F("Disabling Tick Interrupt."));
|
||||
disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock));
|
||||
}
|
||||
else if (ticktocks < -500) {
|
||||
Serial.println(F("Disabling Tock Interrupt."));
|
||||
disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock));
|
||||
enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
}
|
||||
else {
|
||||
enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
|
||||
enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock));
|
||||
}
|
||||
}
|
||||
|
||||
void tick(void) {
|
||||
// increase value
|
||||
ticktocks++;
|
||||
}
|
||||
|
||||
void tock(void) {
|
||||
// decrease value
|
||||
ticktocks--;
|
||||
}
|
||||
BIN
arduino-cli/libraries/PinChangeInterrupt/header.png
Normal file
BIN
arduino-cli/libraries/PinChangeInterrupt/header.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
32
arduino-cli/libraries/PinChangeInterrupt/keywords.txt
Normal file
32
arduino-cli/libraries/PinChangeInterrupt/keywords.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For PinChangeInterrupt
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
attachPinChangeInterrupt KEYWORD2
|
||||
detachPinChangeInterrupt KEYWORD2
|
||||
attachPCINT KEYWORD2
|
||||
detachPCINT KEYWORD2
|
||||
PinChangeInterruptEvent KEYWORD2
|
||||
PCINTEvent KEYWORD2
|
||||
enablePCINT KEYWORD2
|
||||
enablePinChangeInterrupt KEYWORD2
|
||||
disablePCINT KEYWORD2
|
||||
disablePinChangeInterrupt KEYWORD2
|
||||
getPCINTTrigger KEYWORD2
|
||||
getPinChangeInterruptTrigger KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
10
arduino-cli/libraries/PinChangeInterrupt/library.properties
Normal file
10
arduino-cli/libraries/PinChangeInterrupt/library.properties
Normal file
@@ -0,0 +1,10 @@
|
||||
name=PinChangeInterrupt
|
||||
version=1.2.9
|
||||
author=NicoHood
|
||||
maintainer=NicoHood <blog@NicoHood.de>
|
||||
sentence=A simple & compact PinChangeInterrupt library for Arduino.
|
||||
paragraph=PinChangeInterrupt library with a resource friendly implementation (API and LowLevel). PinChangeInterrupts are different than normal Interrupts. See readme for more information.
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/NicoHood/PinChangeInterrupt
|
||||
architectures=avr
|
||||
dot_a_linkage=true
|
||||
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
// manually include cpp files here to save flash if only 1 ISR is present
|
||||
// or if the user knows he just wants to compile all enabled ports.
|
||||
#if defined(PCINT_ALINKAGE) && defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
#define PCINT_INCLUDE_FROM_CPP
|
||||
#include "PinChangeInterrupt0.cpp"
|
||||
#include "PinChangeInterrupt1.cpp"
|
||||
#include "PinChangeInterrupt2.cpp"
|
||||
#include "PinChangeInterrupt3.cpp"
|
||||
#else
|
||||
|
||||
//================================================================================
|
||||
// Weak Callbacks
|
||||
//================================================================================
|
||||
|
||||
// create all weak functions which are all (if not used) alias of the pcint_null_callback above
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("void PinChangeInterruptEventPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("(void) __attribute__((weak, alias(\"pcint_null_callback\")));");
|
||||
}
|
||||
*/
|
||||
void PinChangeInterruptEventPCINT0(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT1(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT2(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT3(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT4(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT5(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT6(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT7(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT8(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT9(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT10(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT11(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT12(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT13(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT14(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT15(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT16(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT17(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT18(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT19(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT20(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT21(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT22(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT23(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT24(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT25(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT26(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT27(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT28(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT29(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT30(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
void PinChangeInterruptEventPCINT31(void) __attribute__((weak, alias("pcint_null_callback")));
|
||||
|
||||
#endif // PCINT_INCLUDE_FROM_CPP
|
||||
|
||||
// useless function for weak implemented/not used functions, extern c needed for the alias
|
||||
extern "C" {
|
||||
void pcint_null_callback(void) {
|
||||
// useless
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PinChangeInterrupt User Functions
|
||||
//================================================================================
|
||||
|
||||
// variables to save the last port states and the interrupt settings
|
||||
uint8_t oldPorts[PCINT_NUM_USED_PORTS] = { 0 };
|
||||
uint8_t fallingPorts[PCINT_NUM_USED_PORTS] = { 0 };
|
||||
uint8_t risingPorts[PCINT_NUM_USED_PORTS] = { 0 };
|
||||
|
||||
void enablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcintMask, const uint8_t arrayPos){
|
||||
// Update the old state to the actual state
|
||||
switch(pcintPort){
|
||||
#ifdef PCINT_INPUT_PORT0_USED
|
||||
case 0:
|
||||
oldPorts[arrayPos] = PCINT_INPUT_PORT0;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PCINT_INPUT_PORT1_USED
|
||||
case 1:
|
||||
oldPorts[arrayPos] = PCINT_INPUT_PORT1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PCINT_INPUT_PORT2_USED
|
||||
case 2:
|
||||
oldPorts[arrayPos] = PCINT_INPUT_PORT2;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PCINT_INPUT_PORT3_USED
|
||||
case 3:
|
||||
oldPorts[arrayPos] = PCINT_INPUT_PORT3;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Pin change mask registers decide which pins are ENABLE as triggers
|
||||
#ifdef PCMSK0
|
||||
#ifdef PCMSK1
|
||||
#ifdef PCMSK3
|
||||
// Special case for ATmega1284P where PCMSK3 is not directly after PCMSK2
|
||||
if(false){
|
||||
#else
|
||||
// Special case for Attinyx4 where PCMSK1 and PCMSK0 are not next to each other
|
||||
if(&PCMSK1 - &PCMSK0 == 1){
|
||||
#endif
|
||||
#endif
|
||||
*(&PCMSK0 + pcintPort) |= pcintMask;
|
||||
#ifdef PCMSK1
|
||||
}
|
||||
else{
|
||||
switch(pcintPort){
|
||||
case 0:
|
||||
PCMSK0 |= pcintMask;
|
||||
break;
|
||||
case 1:
|
||||
PCMSK1 |= pcintMask;
|
||||
break;
|
||||
#ifdef PCMSK2
|
||||
case 2:
|
||||
PCMSK2 |= pcintMask;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PCMSK3
|
||||
case 3:
|
||||
PCMSK3 |= pcintMask;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#elif defined(PCMSK)
|
||||
*(&PCMSK + pcintPort) |= pcintMask;
|
||||
#endif
|
||||
|
||||
// PCICR: Pin Change Interrupt Control Register - enables interrupt vectors
|
||||
#ifdef PCICR
|
||||
PCICR |= (1 << (pcintPort + PCIE0));
|
||||
#elif defined(GICR) /* e.g. ATmega162 */
|
||||
GICR |= (1 << (pcintPort + PCIE0));
|
||||
#elif defined(GIMSK) && defined(PCIE0) /* e.g. ATtiny X4 */
|
||||
GIMSK |= (1 << (pcintPort + PCIE0));
|
||||
#elif defined(GIMSK) && defined(PCIE) /* e.g. ATtiny X5 */
|
||||
GIMSK |= (1 << (pcintPort + PCIE));
|
||||
#else
|
||||
#error MCU has no such a register
|
||||
#endif
|
||||
}
|
||||
|
||||
void disablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcintMask) {
|
||||
bool disable = false;
|
||||
#ifdef PCMSK0
|
||||
#ifdef PCMSK1
|
||||
#ifdef PCMSK3
|
||||
// Special case for ATmega1284P where PCMSK3 is not directly after PCMSK2
|
||||
if (false){
|
||||
#else
|
||||
// Special case for Attinyx4 where PCMSK1 and PCMSK0 are not next to each other
|
||||
if (&PCMSK1 - &PCMSK0 == 1) {
|
||||
#endif // ifdef PCMSK3
|
||||
#endif // ifdef PCMSK1
|
||||
// disable the mask.
|
||||
*(&PCMSK0 + pcintPort) &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (*(&PCMSK0 + pcintPort) == 0) {
|
||||
disable = true;
|
||||
}
|
||||
#ifdef PCMSK1
|
||||
}
|
||||
else {
|
||||
switch (pcintPort) {
|
||||
case 0:
|
||||
// disable the mask.
|
||||
PCMSK0 &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (!PCMSK0) {
|
||||
disable = true;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// disable the mask.
|
||||
PCMSK1 &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (!PCMSK1) {
|
||||
disable = true;
|
||||
}
|
||||
break;
|
||||
#ifdef PCMSK2
|
||||
case 2:
|
||||
// disable the mask.
|
||||
PCMSK2 &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (!PCMSK2) {
|
||||
disable = true;
|
||||
}
|
||||
break;
|
||||
#endif // ifdef PCMSK2
|
||||
#ifdef PCMSK3
|
||||
case 3:
|
||||
// disable the mask.
|
||||
PCMSK3 &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (!PCMSK3) {
|
||||
disable = true;
|
||||
}
|
||||
break;
|
||||
#endif // ifdef PCMSK3
|
||||
}
|
||||
}
|
||||
#endif // ifdef PCMSK1
|
||||
#elif defined(PCMSK)
|
||||
// disable the mask.
|
||||
*(&PCMSK + pcintPort) &= ~pcintMask;
|
||||
|
||||
// if that's the last one, disable the interrupt.
|
||||
if (*(&PCMSK + pcintPort) == 0) {
|
||||
disable = true;
|
||||
}
|
||||
#endif // ifdef PCMSK0
|
||||
|
||||
if(disable)
|
||||
{
|
||||
#ifdef PCICR
|
||||
PCICR &= ~(1 << (pcintPort + PCIE0));
|
||||
#elif defined(GICR) /* e.g. ATmega162 */
|
||||
GICR &= ~(1 << (pcintPort + PCIE0));
|
||||
#elif defined(GIMSK) && defined(PCIE0) /* e.g. ATtiny X4 */
|
||||
GIMSK &= ~(1 << (pcintPort + PCIE0));
|
||||
#elif defined(GIMSK) && defined(PCIE) /* e.g. ATtiny X5 */
|
||||
GIMSK &= ~(1 << (pcintPort + PCIE));
|
||||
#else
|
||||
#error MCU has no such a register
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
asm output (nothing to optimize here)
|
||||
|
||||
ISR(PCINT0_vect) {
|
||||
push r1
|
||||
push r0
|
||||
in r0, 0x3f ; 63
|
||||
push r0
|
||||
eor r1, r1
|
||||
push r18
|
||||
push r19
|
||||
push r20
|
||||
push r21
|
||||
push r22
|
||||
push r23
|
||||
push r24
|
||||
push r25
|
||||
push r26
|
||||
push r27
|
||||
push r28
|
||||
push r30
|
||||
push r31
|
||||
|
||||
// get the new and old pin states for port
|
||||
// uint8_t newPort = pinChangeInterruptPortToInput(port);
|
||||
in r24, 0x03; 3 //(1) loads byte into newPort from I/O register
|
||||
|
||||
// loads old port and high + low setting
|
||||
lds r18, 0x011E //(1 or 2) loads oldPorts into register
|
||||
lds r28, 0x011B //(1 or 2) loads fallingPorts into register
|
||||
lds r25, 0x0118 //(1 or 2) loads risingPorts into register
|
||||
|
||||
and r28, r18 // oldPorts & fallingPorts
|
||||
and r25, r24 // newPort & risingPorts
|
||||
or r28, r25 // (oldPorts & fallingPorts) | (newPort & risingPorts)
|
||||
eor r18, r24 // oldPorts^newPort
|
||||
and r28, r18 // ((oldPorts & fallingPorts) | (newPort & risingPorts)) & (oldPorts^newPort)
|
||||
|
||||
// save the new state for next comparison
|
||||
// oldPorts[arrayPos] = newPort;
|
||||
sts 0x011E, r24
|
||||
|
||||
// Execute all functions that should be triggered
|
||||
sbrc r28, 0
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
sbrc r28, 1
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
sbrc r28, 2
|
||||
call 0x318 ; 0x318 <_Z20PinChangeInterruptEventPCINT2v>
|
||||
sbrc r28, 3
|
||||
call 0x340 ; 0x340 <_Z20PinChangeInterruptEventPCINT3v>
|
||||
sbrc r28, 4
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
sbrc r28, 5
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
sbrc r28, 6
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
sbrc r28, 7
|
||||
call 0x37c ; 0x37c <_Z20PinChangeInterruptEventPCINT0v>
|
||||
|
||||
pop r31
|
||||
pop r30
|
||||
pop r28
|
||||
pop r27
|
||||
pop r26
|
||||
pop r25
|
||||
pop r24
|
||||
pop r23
|
||||
pop r22
|
||||
pop r21
|
||||
pop r20
|
||||
pop r19
|
||||
pop r18
|
||||
pop r0
|
||||
out 0x3f, r0 ; 63
|
||||
pop r0
|
||||
pop r1
|
||||
reti
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,898 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Include Guard
|
||||
#pragma once
|
||||
|
||||
// Software Version
|
||||
#define PCINT_VERSION 129
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifndef ARDUINO_ARCH_AVR
|
||||
#error This library can only be used with AVR
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LOW
|
||||
#define LOW 0x0
|
||||
#endif
|
||||
#ifndef CHANGE
|
||||
#define CHANGE 0x1
|
||||
#endif
|
||||
#ifndef FALLING
|
||||
#define FALLING 0x2
|
||||
#endif
|
||||
#ifndef RISING
|
||||
#define RISING 0x3
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//================================================================================
|
||||
// General Helper Definitions and Mappings
|
||||
//================================================================================
|
||||
|
||||
// Settings and Board definitions are seperated to get an better overview.
|
||||
// The order and position of the inclusion is important!
|
||||
#include "PinChangeInterruptSettings.h"
|
||||
#include "PinChangeInterruptBoards.h"
|
||||
#include "PinChangeInterruptPins.h"
|
||||
|
||||
#if !PCINT_NUM_USED_PORTS
|
||||
#error Please enable at least one PCINT port and pin!
|
||||
#endif
|
||||
|
||||
// manually include cpp files to save flash if only 1 ISR is present
|
||||
// it includes all ISR files but only the 1 available ISR will/can be compiled
|
||||
#if (PCINT_NUM_USED_PORTS == 1)
|
||||
#ifndef PCINT_COMPILE_ENABLED_ISR
|
||||
#define PCINT_COMPILE_ENABLED_ISR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//================================================================================
|
||||
// Makro Definitions
|
||||
//================================================================================
|
||||
|
||||
// generates the callback for easier reordering in Settings
|
||||
#define PCINT_MACRO_BRACKETS ()
|
||||
#define PCINT_MACRO_TRUE == true)
|
||||
#define PCINT_CALLBACK(bit, pcint) \
|
||||
if (PCINT_USE_PCINT ## pcint PCINT_MACRO_TRUE \
|
||||
if (trigger & (1 << bit)) \
|
||||
PinChangeInterruptEventPCINT ## pcint PCINT_MACRO_BRACKETS
|
||||
|
||||
// definition used by the user to create custom LowLevel PCINT Events
|
||||
#define PinChangeInterruptEvent_Wrapper(n) PinChangeInterruptEventPCINT ## n
|
||||
#define PinChangeInterruptEvent(n) PinChangeInterruptEvent_Wrapper(n)
|
||||
|
||||
// missing 1.0.6 definition workaround
|
||||
#ifndef NOT_AN_INTERRUPT
|
||||
#define NOT_AN_INTERRUPT -1
|
||||
#endif
|
||||
|
||||
// convert a normal pin to its PCINT number (0 - max 23), used by the user
|
||||
// calculates the pin by the Arduino definitions
|
||||
#if defined(PCIE0)
|
||||
#define digitalPinToPinChangeInterrupt(p) (digitalPinToPCICR(p) ? ((8 * (digitalPinToPCICRbit(p) - PCIE0)) + digitalPinToPCMSKbit(p)) : NOT_AN_INTERRUPT)
|
||||
#elif defined(PCIE)
|
||||
#define digitalPinToPinChangeInterrupt(p) (digitalPinToPCICR(p) ? ((8 * (digitalPinToPCICRbit(p) - PCIE)) + digitalPinToPCMSKbit(p)) : NOT_AN_INTERRUPT)
|
||||
#else
|
||||
#error MCU has no such a register
|
||||
#endif
|
||||
|
||||
// alias for shorter writing
|
||||
#define PCINTEvent(n) PinChangeInterruptEvent_Wrapper(n)
|
||||
#define digitalPinToPCINT digitalPinToPinChangeInterrupt
|
||||
#define attachPCINT attachPinChangeInterrupt
|
||||
#define enablePCINT enablePinChangeInterrupt
|
||||
#define detachPCINT detachPinChangeInterrupt
|
||||
#define disablePCINT disablePinChangeInterrupt
|
||||
#define getPCINTTrigger getPinChangeInterruptTrigger
|
||||
|
||||
//================================================================================
|
||||
// Function Prototypes + Variables
|
||||
//================================================================================
|
||||
|
||||
// typedef for our callback function pointers
|
||||
typedef void(*callback)(void);
|
||||
|
||||
// useless function for weak implemented/not used functions, extern c needed for the alias
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void pcint_null_callback(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void PinChangeInterruptEventPCINT0(void);
|
||||
void PinChangeInterruptEventPCINT1(void);
|
||||
void PinChangeInterruptEventPCINT2(void);
|
||||
void PinChangeInterruptEventPCINT3(void);
|
||||
void PinChangeInterruptEventPCINT4(void);
|
||||
void PinChangeInterruptEventPCINT5(void);
|
||||
void PinChangeInterruptEventPCINT6(void);
|
||||
void PinChangeInterruptEventPCINT7(void);
|
||||
void PinChangeInterruptEventPCINT8(void);
|
||||
void PinChangeInterruptEventPCINT9(void);
|
||||
void PinChangeInterruptEventPCINT10(void);
|
||||
void PinChangeInterruptEventPCINT11(void);
|
||||
void PinChangeInterruptEventPCINT12(void);
|
||||
void PinChangeInterruptEventPCINT13(void);
|
||||
void PinChangeInterruptEventPCINT14(void);
|
||||
void PinChangeInterruptEventPCINT15(void);
|
||||
void PinChangeInterruptEventPCINT16(void);
|
||||
void PinChangeInterruptEventPCINT17(void);
|
||||
void PinChangeInterruptEventPCINT18(void);
|
||||
void PinChangeInterruptEventPCINT19(void);
|
||||
void PinChangeInterruptEventPCINT20(void);
|
||||
void PinChangeInterruptEventPCINT21(void);
|
||||
void PinChangeInterruptEventPCINT22(void);
|
||||
void PinChangeInterruptEventPCINT23(void);
|
||||
void PinChangeInterruptEventPCINT24(void);
|
||||
void PinChangeInterruptEventPCINT25(void);
|
||||
void PinChangeInterruptEventPCINT26(void);
|
||||
void PinChangeInterruptEventPCINT27(void);
|
||||
void PinChangeInterruptEventPCINT28(void);
|
||||
void PinChangeInterruptEventPCINT29(void);
|
||||
void PinChangeInterruptEventPCINT30(void);
|
||||
void PinChangeInterruptEventPCINT31(void);
|
||||
|
||||
extern uint8_t oldPorts[PCINT_NUM_USED_PORTS];
|
||||
extern uint8_t fallingPorts[PCINT_NUM_USED_PORTS];
|
||||
extern uint8_t risingPorts[PCINT_NUM_USED_PORTS];
|
||||
|
||||
|
||||
static inline uint8_t getArrayPosPCINT(uint8_t pcintPort) __attribute__((always_inline));
|
||||
uint8_t getArrayPosPCINT(uint8_t pcintPort) {
|
||||
/*
|
||||
Maps the port to the array.
|
||||
This is needed since you can deactivate ports
|
||||
and the array will dynamically resize to save ram.
|
||||
|
||||
The function does not need that much flash since the if and else
|
||||
are known at compile time, so the compiler removes all the complex logic.
|
||||
The return is is the input if all pins are activated for example.
|
||||
That's why the function is inline.
|
||||
*/
|
||||
|
||||
if (PCINT_NUM_USED_PORTS == 1) {
|
||||
// only the first element is used for a single port
|
||||
return 0;
|
||||
}
|
||||
else if (PCINT_NUM_USED_PORTS == PCINT_NUM_PORTS) {
|
||||
// use all ports and down remap the array position.
|
||||
return pcintPort;
|
||||
}
|
||||
else if (PCINT_NUM_PORTS - PCINT_NUM_USED_PORTS == 1) {
|
||||
// one port is not used
|
||||
if (PCINT_USE_PORT0 == 0) {
|
||||
// first port is not used, decrease all port numbers
|
||||
return (pcintPort - 1);
|
||||
}
|
||||
else if (PCINT_HAS_PORT3 == 0) {
|
||||
// 3 ports (standard)
|
||||
if (PCINT_USE_PORT2 == 0) {
|
||||
// last port not used, no mapping needed
|
||||
return pcintPort;
|
||||
}
|
||||
else {
|
||||
// worst case, port in the middle not used, remap
|
||||
return ((pcintPort >> 1) & 0x01);
|
||||
//if (pcintPort == 0) return 0;
|
||||
//else return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 4 ports (special case for a few AVRs)
|
||||
if (PCINT_USE_PORT3 == 0) {
|
||||
// last port not used, no mapping needed
|
||||
return pcintPort;
|
||||
}
|
||||
else {
|
||||
// worst case, one of two ports in the middle not used, remap
|
||||
if (PCINT_USE_PORT1 == 0) {
|
||||
// port1 not used, mapping needed
|
||||
if (pcintPort == 0)
|
||||
return 0;
|
||||
else
|
||||
return pcintPort - 1;
|
||||
}
|
||||
else if (PCINT_USE_PORT2 == 0) {
|
||||
// port2 not used, mapping needed
|
||||
if (pcintPort == 3)
|
||||
return 2;
|
||||
else
|
||||
return pcintPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use all ports and down remap the array position.
|
||||
return pcintPort;
|
||||
}
|
||||
else if (PCINT_NUM_PORTS - PCINT_NUM_USED_PORTS == 2) {
|
||||
if (PCINT_USE_PORT2 == 0 && PCINT_USE_PORT3 == 0) {
|
||||
// no need for mapping
|
||||
return pcintPort;
|
||||
}
|
||||
else if (PCINT_USE_PORT0 == 0 && PCINT_USE_PORT3 == 0) {
|
||||
// 1 offset
|
||||
return (pcintPort - 1);
|
||||
}
|
||||
else if (PCINT_USE_PORT0 == 0 && PCINT_USE_PORT1 == 0) {
|
||||
// 2 offset
|
||||
return (pcintPort - 2);
|
||||
}
|
||||
else if (PCINT_USE_PORT0 == 0 && PCINT_USE_PORT2 == 0) {
|
||||
// 2 -> 1
|
||||
return (pcintPort >> 1);
|
||||
}
|
||||
else if (PCINT_USE_PORT1 == 0 && PCINT_USE_PORT2 == 0) {
|
||||
// 3 -> 1
|
||||
return (pcintPort >> 1);
|
||||
}
|
||||
else if (PCINT_USE_PORT1 == 0 && PCINT_USE_PORT3 == 0) {
|
||||
// 3 -> 1, 1 -> 0
|
||||
return (pcintPort >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
return 0;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// Attach Function (partly inlined)
|
||||
//================================================================================
|
||||
|
||||
void enablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcintMask, const uint8_t arrayPos);
|
||||
void attachPinChangeInterrupt0(void);
|
||||
void attachPinChangeInterrupt1(void);
|
||||
void attachPinChangeInterrupt2(void);
|
||||
void attachPinChangeInterrupt3(void);
|
||||
|
||||
#if defined(PCINT_API)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("extern volatile callback callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(";");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_USE_PCINT0 == true)
|
||||
extern volatile callback callbackPCINT0;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT1 == true)
|
||||
extern volatile callback callbackPCINT1;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT2 == true)
|
||||
extern volatile callback callbackPCINT2;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT3 == true)
|
||||
extern volatile callback callbackPCINT3;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT4 == true)
|
||||
extern volatile callback callbackPCINT4;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT5 == true)
|
||||
extern volatile callback callbackPCINT5;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT6 == true)
|
||||
extern volatile callback callbackPCINT6;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT7 == true)
|
||||
extern volatile callback callbackPCINT7;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT8 == true)
|
||||
extern volatile callback callbackPCINT8;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT9 == true)
|
||||
extern volatile callback callbackPCINT9;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT10 == true)
|
||||
extern volatile callback callbackPCINT10;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT11 == true)
|
||||
extern volatile callback callbackPCINT11;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT12 == true)
|
||||
extern volatile callback callbackPCINT12;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT13 == true)
|
||||
extern volatile callback callbackPCINT13;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT14 == true)
|
||||
extern volatile callback callbackPCINT14;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT15 == true)
|
||||
extern volatile callback callbackPCINT15;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT16 == true)
|
||||
extern volatile callback callbackPCINT16;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT17 == true)
|
||||
extern volatile callback callbackPCINT17;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT18 == true)
|
||||
extern volatile callback callbackPCINT18;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT19 == true)
|
||||
extern volatile callback callbackPCINT19;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT20 == true)
|
||||
extern volatile callback callbackPCINT20;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT21 == true)
|
||||
extern volatile callback callbackPCINT21;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT22 == true)
|
||||
extern volatile callback callbackPCINT22;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT23 == true)
|
||||
extern volatile callback callbackPCINT23;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT24 == true)
|
||||
extern volatile callback callbackPCINT24;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT25 == true)
|
||||
extern volatile callback callbackPCINT25;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT26 == true)
|
||||
extern volatile callback callbackPCINT26;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT27 == true)
|
||||
extern volatile callback callbackPCINT27;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT28 == true)
|
||||
extern volatile callback callbackPCINT28;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT29 == true)
|
||||
extern volatile callback callbackPCINT29;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT30 == true)
|
||||
extern volatile callback callbackPCINT30;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT31 == true)
|
||||
extern volatile callback callbackPCINT31;
|
||||
#endif
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("if (pcintNum == ");
|
||||
Serial.print(i);
|
||||
Serial.println(")");
|
||||
Serial.print("callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" = userFunc;");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
|
||||
// API attach function
|
||||
static inline void attachPinChangeInterrupt(const uint8_t pcintNum, void(*userFunc)(void), const uint8_t mode) __attribute__((always_inline));
|
||||
void attachPinChangeInterrupt(const uint8_t pcintNum, void(*userFunc)(void), const uint8_t mode) {
|
||||
#else // no API attach function
|
||||
static inline void attachPinChangeInterrupt(const uint8_t pcintNum, const uint8_t mode) __attribute__((always_inline));
|
||||
void attachPinChangeInterrupt(const uint8_t pcintNum, const uint8_t mode) {
|
||||
#endif // PCINT_API
|
||||
|
||||
// check if pcint is a valid pcint, exclude deactivated ports
|
||||
uint8_t pcintPort = pcintNum / 8;
|
||||
uint8_t pcintBit = pcintNum % 8;
|
||||
|
||||
// port 0
|
||||
if (pcintPort == 0 && PCINT_USE_PORT0 == true) {
|
||||
// use fake functions to make the ISRs compile with .a linkage
|
||||
#if defined(PCINT_ALINKAGE) && !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
attachPinChangeInterrupt0();
|
||||
#endif
|
||||
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT0 == true)
|
||||
if (pcintNum == 0)
|
||||
callbackPCINT0 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT1 == true)
|
||||
if (pcintNum == 1)
|
||||
callbackPCINT1 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT2 == true)
|
||||
if (pcintNum == 2)
|
||||
callbackPCINT2 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT3 == true)
|
||||
if (pcintNum == 3)
|
||||
callbackPCINT3 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT4 == true)
|
||||
if (pcintNum == 4)
|
||||
callbackPCINT4 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT5 == true)
|
||||
if (pcintNum == 5)
|
||||
callbackPCINT5 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT6 == true)
|
||||
if (pcintNum == 6)
|
||||
callbackPCINT6 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT7 == true)
|
||||
if (pcintNum == 7)
|
||||
callbackPCINT7 = userFunc;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 1
|
||||
else if (pcintPort == 1 && PCINT_USE_PORT1 == true) {
|
||||
// use fake functions to make the ISRs compile with .a linkage
|
||||
#if defined(PCINT_ALINKAGE) && !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
attachPinChangeInterrupt1();
|
||||
#endif
|
||||
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT8 == true)
|
||||
if (pcintNum == 8)
|
||||
callbackPCINT8 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT9 == true)
|
||||
if (pcintNum == 9)
|
||||
callbackPCINT9 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT10 == true)
|
||||
if (pcintNum == 10)
|
||||
callbackPCINT10 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT11 == true)
|
||||
if (pcintNum == 11)
|
||||
callbackPCINT11 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT12 == true)
|
||||
if (pcintNum == 12)
|
||||
callbackPCINT12 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT13 == true)
|
||||
if (pcintNum == 13)
|
||||
callbackPCINT13 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT14 == true)
|
||||
if (pcintNum == 14)
|
||||
callbackPCINT14 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT15 == true)
|
||||
if (pcintNum == 15)
|
||||
callbackPCINT15 = userFunc;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 2
|
||||
else if (pcintPort == 2 && PCINT_USE_PORT2 == true) {
|
||||
// use fake functions to make the ISRs compile with .a linkage
|
||||
#if defined(PCINT_ALINKAGE) && !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
attachPinChangeInterrupt2();
|
||||
#endif
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT16 == true)
|
||||
if (pcintNum == 16)
|
||||
callbackPCINT16 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT17 == true)
|
||||
if (pcintNum == 17)
|
||||
callbackPCINT17 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT18 == true)
|
||||
if (pcintNum == 18)
|
||||
callbackPCINT18 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT19 == true)
|
||||
if (pcintNum == 19)
|
||||
callbackPCINT19 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT20 == true)
|
||||
if (pcintNum == 20)
|
||||
callbackPCINT20 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT21 == true)
|
||||
if (pcintNum == 21)
|
||||
callbackPCINT21 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT22 == true)
|
||||
if (pcintNum == 22)
|
||||
callbackPCINT22 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT23 == true)
|
||||
if (pcintNum == 23)
|
||||
callbackPCINT23 = userFunc;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 3
|
||||
else if (pcintPort == 3 && PCINT_USE_PORT3 == true) {
|
||||
// use fake functions to make the ISRs compile with .a linkage
|
||||
#if defined(PCINT_ALINKAGE) && !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
attachPinChangeInterrupt3();
|
||||
#endif
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT24 == true)
|
||||
if (pcintNum == 24)
|
||||
callbackPCINT24 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT25 == true)
|
||||
if (pcintNum == 25)
|
||||
callbackPCINT25 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT26 == true)
|
||||
if (pcintNum == 26)
|
||||
callbackPCINT26 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT27 == true)
|
||||
if (pcintNum == 27)
|
||||
callbackPCINT27 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT28 == true)
|
||||
if (pcintNum == 28)
|
||||
callbackPCINT28 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT29 == true)
|
||||
if (pcintNum == 29)
|
||||
callbackPCINT29 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT30 == true)
|
||||
if (pcintNum == 30)
|
||||
callbackPCINT30 = userFunc;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT31 == true)
|
||||
if (pcintNum == 31)
|
||||
callbackPCINT31 = userFunc;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
else return;
|
||||
|
||||
// get bitmask and array position
|
||||
uint8_t pcintMask = (1 << pcintBit);
|
||||
uint8_t arrayPos = getArrayPosPCINT(pcintPort);
|
||||
|
||||
// save settings related to mode and registers
|
||||
if (mode == CHANGE || mode == RISING)
|
||||
risingPorts[arrayPos] |= pcintMask;
|
||||
if (mode == CHANGE || mode == FALLING)
|
||||
fallingPorts[arrayPos] |= pcintMask;
|
||||
|
||||
// call the actual hardware attach function
|
||||
enablePinChangeInterruptHelper(pcintPort, pcintMask, arrayPos);
|
||||
}
|
||||
|
||||
// enable interrupt again if temporary disabled
|
||||
static inline void enablePinChangeInterrupt(const uint8_t pcintNum) __attribute__((always_inline));
|
||||
void enablePinChangeInterrupt(const uint8_t pcintNum) {
|
||||
// get PCINT registers
|
||||
uint8_t pcintPort = pcintNum / 8;
|
||||
uint8_t pcintBit = pcintNum % 8;
|
||||
|
||||
// check if pcint is a valid pcint, exclude deactivated ports
|
||||
if (pcintPort == 0) {
|
||||
if (PCINT_USE_PORT0 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 1) {
|
||||
if (PCINT_USE_PORT1 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 2) {
|
||||
if (PCINT_USE_PORT2 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 3) {
|
||||
if (PCINT_USE_PORT3 == false)
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
|
||||
// call the actual hardware attach function
|
||||
uint8_t pcintMask = (1 << pcintBit);
|
||||
uint8_t arrayPos = getArrayPosPCINT(pcintPort);
|
||||
enablePinChangeInterruptHelper(pcintPort, pcintMask, arrayPos);
|
||||
}
|
||||
|
||||
|
||||
//================================================================================
|
||||
// Detach Function (partly inlined)
|
||||
//================================================================================
|
||||
|
||||
void disablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcintMask);
|
||||
static inline void detachPinChangeInterrupt(const uint8_t pcintNum) __attribute__((always_inline));
|
||||
|
||||
void detachPinChangeInterrupt(const uint8_t pcintNum) {
|
||||
// get PCINT registers
|
||||
uint8_t pcintPort = pcintNum / 8;
|
||||
uint8_t pcintBit = pcintNum % 8;
|
||||
|
||||
// check if pcint is a valid pcint, exclude deactivated ports
|
||||
// port 0
|
||||
if (pcintPort == 0 && PCINT_USE_PORT0 == true) {
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT0 == true)
|
||||
if (pcintNum == 0)
|
||||
callbackPCINT0 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT1 == true)
|
||||
if (pcintNum == 1)
|
||||
callbackPCINT1 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT2 == true)
|
||||
if (pcintNum == 2)
|
||||
callbackPCINT2 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT3 == true)
|
||||
if (pcintNum == 3)
|
||||
callbackPCINT3 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT4 == true)
|
||||
if (pcintNum == 4)
|
||||
callbackPCINT4 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT5 == true)
|
||||
if (pcintNum == 5)
|
||||
callbackPCINT5 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT6 == true)
|
||||
if (pcintNum == 6)
|
||||
callbackPCINT6 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT7 == true)
|
||||
if (pcintNum == 7)
|
||||
callbackPCINT7 = pcint_null_callback;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 1
|
||||
else if (pcintPort == 1 && PCINT_USE_PORT1 == true) {
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT8 == true)
|
||||
if (pcintNum == 8)
|
||||
callbackPCINT8 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT9 == true)
|
||||
if (pcintNum == 9)
|
||||
callbackPCINT9 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT10 == true)
|
||||
if (pcintNum == 10)
|
||||
callbackPCINT10 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT11 == true)
|
||||
if (pcintNum == 11)
|
||||
callbackPCINT11 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT12 == true)
|
||||
if (pcintNum == 12)
|
||||
callbackPCINT12 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT13 == true)
|
||||
if (pcintNum == 13)
|
||||
callbackPCINT13 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT14 == true)
|
||||
if (pcintNum == 14)
|
||||
callbackPCINT14 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT15 == true)
|
||||
if (pcintNum == 15)
|
||||
callbackPCINT15 = pcint_null_callback;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 2
|
||||
else if (pcintPort == 2 && PCINT_USE_PORT2 == true) {
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT16 == true)
|
||||
if (pcintNum == 16)
|
||||
callbackPCINT16 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT17 == true)
|
||||
if (pcintNum == 17)
|
||||
callbackPCINT17 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT18 == true)
|
||||
if (pcintNum == 18)
|
||||
callbackPCINT18 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT19 == true)
|
||||
if (pcintNum == 19)
|
||||
callbackPCINT19 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT20 == true)
|
||||
if (pcintNum == 20)
|
||||
callbackPCINT20 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT21 == true)
|
||||
if (pcintNum == 21)
|
||||
callbackPCINT21 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT22 == true)
|
||||
if (pcintNum == 22)
|
||||
callbackPCINT22 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT23 == true)
|
||||
if (pcintNum == 23)
|
||||
callbackPCINT23 = pcint_null_callback;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
|
||||
// port 3
|
||||
else if (pcintPort == 3 && PCINT_USE_PORT3 == true) {
|
||||
// attache the function pointers for the API
|
||||
#if defined(PCINT_API)
|
||||
#if (PCINT_USE_PCINT24 == true)
|
||||
if (pcintNum == 24)
|
||||
callbackPCINT24 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT25 == true)
|
||||
if (pcintNum == 25)
|
||||
callbackPCINT25 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT26 == true)
|
||||
if (pcintNum == 26)
|
||||
callbackPCINT26 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT27 == true)
|
||||
if (pcintNum == 27)
|
||||
callbackPCINT27 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT28 == true)
|
||||
if (pcintNum == 28)
|
||||
callbackPCINT28 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT29 == true)
|
||||
if (pcintNum == 29)
|
||||
callbackPCINT29 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT30 == true)
|
||||
if (pcintNum == 30)
|
||||
callbackPCINT30 = pcint_null_callback;
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT31 == true)
|
||||
if (pcintNum == 31)
|
||||
callbackPCINT31 = pcint_null_callback;
|
||||
#endif
|
||||
#endif // PCINT_API
|
||||
}
|
||||
else return;
|
||||
|
||||
// get bitmask and array position
|
||||
uint8_t pcintMask = (1 << pcintBit);
|
||||
uint8_t arrayPos = getArrayPosPCINT(pcintPort);
|
||||
|
||||
// delete setting
|
||||
risingPorts[arrayPos] &= ~pcintMask;
|
||||
fallingPorts[arrayPos] &= ~pcintMask;
|
||||
|
||||
// call the actual hardware disable function
|
||||
disablePinChangeInterruptHelper(pcintPort, pcintMask);
|
||||
}
|
||||
|
||||
static inline void disablePinChangeInterrupt(const uint8_t pcintNum) __attribute__((always_inline));
|
||||
void disablePinChangeInterrupt(const uint8_t pcintNum) {
|
||||
// get PCINT registers
|
||||
uint8_t pcintPort = pcintNum / 8;
|
||||
uint8_t pcintBit = pcintNum % 8;
|
||||
|
||||
// check if pcint is a valid pcint, exclude deactivated ports
|
||||
if (pcintPort == 0) {
|
||||
if (PCINT_USE_PORT0 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 1) {
|
||||
if (PCINT_USE_PORT1 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 2) {
|
||||
if (PCINT_USE_PORT2 == false)
|
||||
return;
|
||||
}
|
||||
else if (pcintPort == 3) {
|
||||
if (PCINT_USE_PORT3 == false)
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
|
||||
// get bitmask
|
||||
uint8_t pcintMask = (1 << pcintBit);
|
||||
|
||||
// Do not delete mode settings nor detach the user function
|
||||
// Just turn off interrupts
|
||||
|
||||
// call the actual hardware disable function
|
||||
disablePinChangeInterruptHelper(pcintPort, pcintMask);
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// getTrigger Function (inlined)
|
||||
//================================================================================
|
||||
|
||||
static inline uint8_t getPinChangeInterruptTrigger(const uint8_t pcintNum) __attribute__((always_inline));
|
||||
uint8_t getPinChangeInterruptTrigger(const uint8_t pcintNum) {
|
||||
// get PCINT registers
|
||||
uint8_t pcintPort = pcintNum / 8;
|
||||
uint8_t pcintBit = pcintNum % 8;
|
||||
|
||||
// check if pcint is a valid pcint, exclude deactivated ports
|
||||
if (pcintPort == 0) {
|
||||
if (PCINT_USE_PORT0 == false)
|
||||
return CHANGE;
|
||||
}
|
||||
else if (pcintPort == 1) {
|
||||
if (PCINT_USE_PORT1 == false)
|
||||
return CHANGE;
|
||||
}
|
||||
else if (pcintPort == 2) {
|
||||
if (PCINT_USE_PORT2 == false)
|
||||
return CHANGE;
|
||||
}
|
||||
else if (pcintPort == 3) {
|
||||
if (PCINT_USE_PORT3 == false)
|
||||
return CHANGE;
|
||||
}
|
||||
else return CHANGE;
|
||||
|
||||
uint8_t arrayPos = getArrayPosPCINT(pcintPort);
|
||||
|
||||
// Check if no mode was set, return an error
|
||||
if(!(risingPorts[arrayPos] & (1 << pcintBit)) && !(fallingPorts[arrayPos] & (1 << pcintBit)))
|
||||
return CHANGE;
|
||||
|
||||
// specify the CHANGE mode
|
||||
if (oldPorts[arrayPos] & (1 << pcintBit))
|
||||
return RISING;
|
||||
else
|
||||
return FALLING;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
//================================================================================
|
||||
// Interrupt Handler
|
||||
//================================================================================
|
||||
|
||||
// prevent compilation twice if included from the .cpp to force compile all ISRs
|
||||
#if defined(PCINT_ALINKAGE) && defined(PCINT_COMPILE_ENABLED_ISR) && defined(PCINT_INCLUDE_FROM_CPP) \
|
||||
|| !defined(PCINT_ALINKAGE) || !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
|
||||
#if (PCINT_USE_PORT0 == true)
|
||||
|
||||
void attachPinChangeInterrupt0(void) {
|
||||
// fake function to make the IDE link this file
|
||||
}
|
||||
|
||||
ISR(PCINT0_vect) {
|
||||
// get the new and old pin states for port
|
||||
uint8_t newPort = PCINT_INPUT_PORT0;
|
||||
|
||||
// compare with the old value to detect a rising or falling
|
||||
uint8_t arrayPos = getArrayPosPCINT(0);
|
||||
uint8_t change = newPort ^ oldPorts[arrayPos];
|
||||
uint8_t rising = change & newPort;
|
||||
uint8_t falling = change & oldPorts[arrayPos];
|
||||
|
||||
// check which pins are triggered, compared with the settings
|
||||
uint8_t risingTrigger = rising & risingPorts[arrayPos];
|
||||
uint8_t fallingTrigger = falling & fallingPorts[arrayPos];
|
||||
uint8_t trigger = risingTrigger | fallingTrigger;
|
||||
|
||||
// save the new state for next comparison
|
||||
oldPorts[arrayPos] = newPort;
|
||||
|
||||
// Execute all functions that should be triggered
|
||||
// This way we can exclude a single function
|
||||
// and the calling is also much faster
|
||||
// We may also reorder the pins for different priority
|
||||
#if !defined(PCINT_CALLBACK_PORT0)
|
||||
PCINT_CALLBACK(0, 0);
|
||||
PCINT_CALLBACK(1, 1);
|
||||
PCINT_CALLBACK(2, 2);
|
||||
PCINT_CALLBACK(3, 3);
|
||||
PCINT_CALLBACK(4, 4);
|
||||
PCINT_CALLBACK(5, 5);
|
||||
PCINT_CALLBACK(6, 6);
|
||||
PCINT_CALLBACK(7, 7);
|
||||
#else
|
||||
PCINT_CALLBACK_PORT0
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCINT_API)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("volatile callback callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" = pcint_null_callback;");
|
||||
Serial.print("void PinChangeInterruptEventPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("(void){");
|
||||
Serial.print(" callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("();");
|
||||
Serial.println("}");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_USE_PCINT0 == true)
|
||||
volatile callback callbackPCINT0 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT0(void) {
|
||||
callbackPCINT0();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT1 == true)
|
||||
volatile callback callbackPCINT1 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT1(void) {
|
||||
callbackPCINT1();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT2 == true)
|
||||
volatile callback callbackPCINT2 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT2(void) {
|
||||
callbackPCINT2();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT3 == true)
|
||||
volatile callback callbackPCINT3 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT3(void) {
|
||||
callbackPCINT3();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT4 == true)
|
||||
volatile callback callbackPCINT4 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT4(void) {
|
||||
callbackPCINT4();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT5 == true)
|
||||
volatile callback callbackPCINT5 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT5(void) {
|
||||
callbackPCINT5();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT6 == true)
|
||||
volatile callback callbackPCINT6 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT6(void) {
|
||||
callbackPCINT6();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT7 == true)
|
||||
volatile callback callbackPCINT7 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT7(void) {
|
||||
callbackPCINT7();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PCINT_API
|
||||
|
||||
#endif // PCINT_USE_PORT0
|
||||
|
||||
#endif // PCINT_INCLUDE_FROM_CPP
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
//================================================================================
|
||||
// Interrupt Handler
|
||||
//================================================================================
|
||||
|
||||
// prevent compilation twice if included from the .cpp to force compile all ISRs
|
||||
#if defined(PCINT_ALINKAGE) && defined(PCINT_COMPILE_ENABLED_ISR) && defined(PCINT_INCLUDE_FROM_CPP) \
|
||||
|| !defined(PCINT_ALINKAGE) || !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
|
||||
#if (PCINT_USE_PORT1 == true)
|
||||
|
||||
void attachPinChangeInterrupt1(void) {
|
||||
// fake function to make the IDE link this file
|
||||
}
|
||||
|
||||
ISR(PCINT1_vect) {
|
||||
// get the new and old pin states for port
|
||||
uint8_t newPort = PCINT_INPUT_PORT1;
|
||||
|
||||
// compare with the old value to detect a rising or falling
|
||||
uint8_t arrayPos = getArrayPosPCINT(1);
|
||||
uint8_t change = newPort ^ oldPorts[arrayPos];
|
||||
uint8_t rising = change & newPort;
|
||||
uint8_t falling = change & oldPorts[arrayPos];
|
||||
|
||||
// check which pins are triggered, compared with the settings
|
||||
uint8_t risingTrigger = rising & risingPorts[arrayPos];
|
||||
uint8_t fallingTrigger = falling & fallingPorts[arrayPos];
|
||||
uint8_t trigger = risingTrigger | fallingTrigger;
|
||||
|
||||
// save the new state for next comparison
|
||||
oldPorts[arrayPos] = newPort;
|
||||
|
||||
// Execute all functions that should be triggered
|
||||
// This way we can exclude a single function
|
||||
// and the calling is also much faster
|
||||
// We may also reorder the pins for different priority
|
||||
#if !defined(PCINT_CALLBACK_PORT1)
|
||||
PCINT_CALLBACK(0, 8);
|
||||
PCINT_CALLBACK(1, 9);
|
||||
PCINT_CALLBACK(2, 10);
|
||||
PCINT_CALLBACK(3, 11);
|
||||
PCINT_CALLBACK(4, 12);
|
||||
PCINT_CALLBACK(5, 13);
|
||||
PCINT_CALLBACK(6, 14);
|
||||
PCINT_CALLBACK(7, 15);
|
||||
#else
|
||||
PCINT_CALLBACK_PORT1
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCINT_API)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("volatile callback callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" = pcint_null_callback;");
|
||||
Serial.print("void PinChangeInterruptEventPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("(void){");
|
||||
Serial.print(" callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("();");
|
||||
Serial.println("}");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_USE_PCINT8 == true)
|
||||
volatile callback callbackPCINT8 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT8(void) {
|
||||
callbackPCINT8();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT9 == true)
|
||||
volatile callback callbackPCINT9 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT9(void) {
|
||||
callbackPCINT9();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT10 == true)
|
||||
volatile callback callbackPCINT10 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT10(void) {
|
||||
callbackPCINT10();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT11 == true)
|
||||
volatile callback callbackPCINT11 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT11(void) {
|
||||
callbackPCINT11();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT12 == true)
|
||||
volatile callback callbackPCINT12 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT12(void) {
|
||||
callbackPCINT12();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT13 == true)
|
||||
volatile callback callbackPCINT13 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT13(void) {
|
||||
callbackPCINT13();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT14 == true)
|
||||
volatile callback callbackPCINT14 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT14(void) {
|
||||
callbackPCINT14();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT15 == true)
|
||||
volatile callback callbackPCINT15 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT15(void) {
|
||||
callbackPCINT15();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PCINT_API
|
||||
|
||||
#endif // PCINT_USE_PORT1
|
||||
|
||||
#endif // PCINT_INCLUDE_FROM_CPP
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
//================================================================================
|
||||
// Interrupt Handler
|
||||
//================================================================================
|
||||
|
||||
// prevent compilation twice if included from the .cpp to force compile all ISRs
|
||||
#if defined(PCINT_ALINKAGE) && defined(PCINT_COMPILE_ENABLED_ISR) && defined(PCINT_INCLUDE_FROM_CPP) \
|
||||
|| !defined(PCINT_ALINKAGE) || !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
|
||||
#if (PCINT_USE_PORT2 == true)
|
||||
|
||||
void attachPinChangeInterrupt2(void) {
|
||||
// fake function to make the IDE link this file
|
||||
}
|
||||
|
||||
ISR(PCINT2_vect) {
|
||||
// get the new and old pin states for port
|
||||
uint8_t newPort = PCINT_INPUT_PORT2;
|
||||
|
||||
// compare with the old value to detect a rising or falling
|
||||
uint8_t arrayPos = getArrayPosPCINT(2);
|
||||
uint8_t change = newPort ^ oldPorts[arrayPos];
|
||||
uint8_t rising = change & newPort;
|
||||
uint8_t falling = change & oldPorts[arrayPos];
|
||||
|
||||
// check which pins are triggered, compared with the settings
|
||||
uint8_t risingTrigger = rising & risingPorts[arrayPos];
|
||||
uint8_t fallingTrigger = falling & fallingPorts[arrayPos];
|
||||
uint8_t trigger = risingTrigger | fallingTrigger;
|
||||
|
||||
// save the new state for next comparison
|
||||
oldPorts[arrayPos] = newPort;
|
||||
|
||||
// Execute all functions that should be triggered
|
||||
// This way we can exclude a single function
|
||||
// and the calling is also much faster
|
||||
// We may also reorder the pins for different priority
|
||||
#if !defined(PCINT_CALLBACK_PORT2)
|
||||
PCINT_CALLBACK(0, 16);
|
||||
PCINT_CALLBACK(1, 17);
|
||||
PCINT_CALLBACK(2, 18);
|
||||
PCINT_CALLBACK(3, 19);
|
||||
PCINT_CALLBACK(4, 20);
|
||||
PCINT_CALLBACK(5, 21);
|
||||
PCINT_CALLBACK(6, 22);
|
||||
PCINT_CALLBACK(7, 23);
|
||||
#else
|
||||
PCINT_CALLBACK_PORT2
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCINT_API)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("volatile callback callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" = pcint_null_callback;");
|
||||
Serial.print("void PinChangeInterruptEventPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("(void){");
|
||||
Serial.print(" callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("();");
|
||||
Serial.println("}");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_USE_PCINT16 == true)
|
||||
volatile callback callbackPCINT16 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT16(void) {
|
||||
callbackPCINT16();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT17 == true)
|
||||
volatile callback callbackPCINT17 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT17(void) {
|
||||
callbackPCINT17();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT18 == true)
|
||||
volatile callback callbackPCINT18 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT18(void) {
|
||||
callbackPCINT18();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT19 == true)
|
||||
volatile callback callbackPCINT19 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT19(void) {
|
||||
callbackPCINT19();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT20 == true)
|
||||
volatile callback callbackPCINT20 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT20(void) {
|
||||
callbackPCINT20();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT21 == true)
|
||||
volatile callback callbackPCINT21 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT21(void) {
|
||||
callbackPCINT21();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT22 == true)
|
||||
volatile callback callbackPCINT22 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT22(void) {
|
||||
callbackPCINT22();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT23 == true)
|
||||
volatile callback callbackPCINT23 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT23(void) {
|
||||
callbackPCINT23();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PCINT_API
|
||||
|
||||
#endif // PCINT_USE_PORT2
|
||||
|
||||
#endif // PCINT_INCLUDE_FROM_CPP
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "PinChangeInterrupt.h"
|
||||
|
||||
//================================================================================
|
||||
// Interrupt Handler
|
||||
//================================================================================
|
||||
|
||||
// prevent compilation twice if included from the .cpp to force compile all ISRs
|
||||
#if defined(PCINT_ALINKAGE) && defined(PCINT_COMPILE_ENABLED_ISR) && defined(PCINT_INCLUDE_FROM_CPP) \
|
||||
|| !defined(PCINT_ALINKAGE) || !defined(PCINT_COMPILE_ENABLED_ISR)
|
||||
|
||||
#if (PCINT_USE_PORT3 == true)
|
||||
|
||||
void attachPinChangeInterrupt3(void) {
|
||||
// fake function to make the IDE link this file
|
||||
}
|
||||
|
||||
ISR(PCINT3_vect) {
|
||||
// get the new and old pin states for port
|
||||
uint8_t newPort = PCINT_INPUT_PORT3;
|
||||
|
||||
// compare with the old value to detect a rising or falling
|
||||
uint8_t arrayPos = getArrayPosPCINT(3);
|
||||
uint8_t change = newPort ^ oldPorts[arrayPos];
|
||||
uint8_t rising = change & newPort;
|
||||
uint8_t falling = change & oldPorts[arrayPos];
|
||||
|
||||
// check which pins are triggered, compared with the settings
|
||||
uint8_t risingTrigger = rising & risingPorts[arrayPos];
|
||||
uint8_t fallingTrigger = falling & fallingPorts[arrayPos];
|
||||
uint8_t trigger = risingTrigger | fallingTrigger;
|
||||
|
||||
// save the new state for next comparison
|
||||
oldPorts[arrayPos] = newPort;
|
||||
|
||||
// Execute all functions that should be triggered
|
||||
// This way we can exclude a single function
|
||||
// and the calling is also much faster
|
||||
// We may also reorder the pins for different priority
|
||||
#if !defined(PCINT_CALLBACK_PORT3)
|
||||
PCINT_CALLBACK(0, 24);
|
||||
PCINT_CALLBACK(1, 25);
|
||||
PCINT_CALLBACK(2, 26);
|
||||
PCINT_CALLBACK(3, 27);
|
||||
PCINT_CALLBACK(4, 28);
|
||||
PCINT_CALLBACK(5, 29);
|
||||
PCINT_CALLBACK(6, 30);
|
||||
PCINT_CALLBACK(7, 31);
|
||||
#else
|
||||
PCINT_CALLBACK_PORT3
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCINT_API)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" == true)");
|
||||
Serial.print("volatile callback callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" = pcint_null_callback;");
|
||||
Serial.print("void PinChangeInterruptEventPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("(void){");
|
||||
Serial.print(" callbackPCINT");
|
||||
Serial.print(i);
|
||||
Serial.println("();");
|
||||
Serial.println("}");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_USE_PCINT24 == true)
|
||||
volatile callback callbackPCINT24 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT24(void) {
|
||||
callbackPCINT24();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT25 == true)
|
||||
volatile callback callbackPCINT25 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT25(void) {
|
||||
callbackPCINT25();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT26 == true)
|
||||
volatile callback callbackPCINT26 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT26(void) {
|
||||
callbackPCINT26();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT27 == true)
|
||||
volatile callback callbackPCINT27 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT27(void) {
|
||||
callbackPCINT27();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT28 == true)
|
||||
volatile callback callbackPCINT28 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT28(void) {
|
||||
callbackPCINT28();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT29 == true)
|
||||
volatile callback callbackPCINT29 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT29(void) {
|
||||
callbackPCINT29();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT30 == true)
|
||||
volatile callback callbackPCINT30 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT30(void) {
|
||||
callbackPCINT30();
|
||||
}
|
||||
#endif
|
||||
#if (PCINT_USE_PCINT31 == true)
|
||||
volatile callback callbackPCINT31 = pcint_null_callback;
|
||||
void PinChangeInterruptEventPCINT31(void) {
|
||||
callbackPCINT31();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PCINT_API
|
||||
|
||||
#endif // PCINT_USE_PORT3
|
||||
|
||||
#endif // PCINT_INCLUDE_FROM_CPP
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// include guard
|
||||
#pragma once
|
||||
|
||||
//================================================================================
|
||||
// Board Definitions
|
||||
//================================================================================
|
||||
|
||||
// Microcontroller specific definitions
|
||||
// Avr Variants are defined here: https://svn.savannah.gnu.org/viewvc/avr-libc/trunk/avr-libc/include/avr/io.h?view=markup
|
||||
|
||||
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328A__) || defined(__AVR_ATmega328PA__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
|
||||
|| defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PB__) \
|
||||
|| defined(__AVR_ATmega88__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
|
||||
|| defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__)
|
||||
// Arduino Uno
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
#define PCINT_INPUT_PORT1 PINC
|
||||
#define PCINT_INPUT_PORT2 PIND
|
||||
|
||||
#if defined(__AVR_ATmega328PB__)
|
||||
#define PCINT_INPUT_PORT3 PINE
|
||||
#endif
|
||||
|
||||
#elif defined(__AVR_ATmega162__)
|
||||
|
||||
#define PCINT_INPUT_PORT0 PINA
|
||||
#define PCINT_INPUT_PORT1 PINC
|
||||
|
||||
#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega640__)
|
||||
// Arduino Mega/Mega2560
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
#define PCINT_INPUT_PORT2 PINK
|
||||
|
||||
// special Port1 case, pins are on 2 HW Pin Ports (E,J)
|
||||
#if defined(PCINT_ENABLE_PCINT16) // PortE
|
||||
#if defined(PCINT_ENABLE_PCINT17) || defined(PCINT_ENABLE_PCINT18) \
|
||||
|| defined(PCINT_ENABLE_PCINT19) || defined(PCINT_ENABLE_PCINT20) \
|
||||
|| defined(PCINT_ENABLE_PCINT21) || defined(PCINT_ENABLE_PCINT22) \
|
||||
|| defined(PCINT_ENABLE_PCINT23) // PortJ
|
||||
// PortE and PortJ selected
|
||||
#define PCINT_INPUT_PORT1 ((PINE & 0x01) | (PINJ << 1))
|
||||
#else
|
||||
// PortE only selected
|
||||
#define PCINT_INPUT_PORT1 PINE
|
||||
#endif
|
||||
#else
|
||||
// PortJ only selected
|
||||
// we still have to do the shift because the attach
|
||||
// function is not designed for this optimization
|
||||
#define PCINT_INPUT_PORT1 (PINJ << 1)
|
||||
#endif
|
||||
|
||||
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
|
||||
// Arduino Leonardo/Micro
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
|
||||
#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
|
||||
// u2 Series/HoodLoader2
|
||||
// u2 Series has crappy pin mappings for port 1
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
#define PCINT_INPUT_PORT1 (((PINC >> 6) & (1 << 0)) | ((PINC >> 4) & (1 << 1)) | ((PINC >> 2) & (1 << 2)) | ((PINC << 1) & (1 << 3)) | ((PIND >> 1) & (1 << 4)))
|
||||
|
||||
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
// Attiny x5
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
|
||||
#elif defined(__AVR_ATtiny13__)
|
||||
// Attiny 13A
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
// This is just a workaround for the missing definition in the following core: https://sourceforge.net/projects/ard-core13/
|
||||
// It should work fine with: https://github.com/MCUdude/MicroCore
|
||||
#ifndef portInputRegister
|
||||
#define portInputRegister(P) ( (volatile uint8_t *)(PINB) )
|
||||
#endif
|
||||
|
||||
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
// Attiny x4
|
||||
#define PCINT_INPUT_PORT0 PINA
|
||||
#define PCINT_INPUT_PORT1 PINB
|
||||
|
||||
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||
// 1284p and 644p, special 4 port case
|
||||
#define PCINT_INPUT_PORT0 PINA
|
||||
#define PCINT_INPUT_PORT1 PINB
|
||||
#define PCINT_INPUT_PORT2 PINC
|
||||
#define PCINT_INPUT_PORT3 PIND
|
||||
|
||||
#elif defined(__AVR_ATtinyX41__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__)
|
||||
// Attiny x41
|
||||
#define PCINT_INPUT_PORT0 PINA
|
||||
#define PCINT_INPUT_PORT1 PINB
|
||||
|
||||
// "iotn841.h" is missing those definitions, so we add them here
|
||||
#define PCINT0 0
|
||||
#define PCINT1 1
|
||||
#define PCINT2 2
|
||||
#define PCINT3 3
|
||||
#define PCINT4 4
|
||||
#define PCINT5 5
|
||||
#define PCINT6 6
|
||||
#define PCINT7 7
|
||||
|
||||
#define PCINT8 0
|
||||
#define PCINT9 1
|
||||
#define PCINT10 2
|
||||
#define PCINT11 3
|
||||
|
||||
#elif defined(__AVR_ATtiny2313__)
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
|
||||
#elif defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny4313__)
|
||||
// All 8 pins
|
||||
#define PCINT_INPUT_PORT0 PINB
|
||||
// PinA has 3 PCINTs on the reset and clock lines, we do not use this port
|
||||
// PIND has 7 pins available, but the pin ordering is so messed up,
|
||||
// that it does not work with the current library structure.
|
||||
|
||||
#elif defined(__AVR_ATtiny261__) || defined(__AVR_ATtiny461__) || defined(__AVR_ATtiny861__)
|
||||
// PORTB has Reset, clock and SPI while PORTA has I2C and Analog Pins. We just enable all pins.
|
||||
#define PCINT_INPUT_PORT0 PINA
|
||||
#define PCINT_INPUT_PORT1 PINB
|
||||
|
||||
#else // Microcontroller not supported
|
||||
#error PinChangeInterrupt library does not support this MCU.
|
||||
#endif
|
||||
|
||||
//================================================================================
|
||||
// Add missing definitions
|
||||
//================================================================================
|
||||
|
||||
// add fakes if ports are not used
|
||||
#ifndef PCINT_INPUT_PORT0
|
||||
#define PCINT_INPUT_PORT0 0
|
||||
#else
|
||||
#define PCINT_INPUT_PORT0_USED
|
||||
#endif
|
||||
#ifndef PCINT_INPUT_PORT1
|
||||
#define PCINT_INPUT_PORT1 0
|
||||
#else
|
||||
#define PCINT_INPUT_PORT1_USED
|
||||
#endif
|
||||
#ifndef PCINT_INPUT_PORT2
|
||||
#define PCINT_INPUT_PORT2 0
|
||||
#else
|
||||
#define PCINT_INPUT_PORT2_USED
|
||||
#endif
|
||||
#ifndef PCINT_INPUT_PORT3
|
||||
#define PCINT_INPUT_PORT3 0
|
||||
#else
|
||||
#define PCINT_INPUT_PORT3_USED
|
||||
#endif
|
||||
@@ -0,0 +1,926 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// include guard
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
The strategy in this file:
|
||||
|
||||
0. Makefile optimization:
|
||||
To disable PCINT/PORTs via makefile use -DPCINT_DISABLE_PORT0 etc.
|
||||
This will undef a previously defined PCINT_ENABLE_PORT0.
|
||||
|
||||
1. Reduce the user settings to the enabled pins.
|
||||
If the whole port is deactivated, also disable all pins on this port.
|
||||
|
||||
2. Define the hardware available pins/ports.
|
||||
|
||||
3. Compare the hardware definition with the enabled pin definitions.
|
||||
If the pin is available and enabled, create a makro to use the pin.
|
||||
|
||||
4. Count all used pins (for each port).
|
||||
|
||||
5. If there are no pins used on a port, do not use the port
|
||||
|
||||
6. Finally we have a clear defintion of the used pins/ports like this:
|
||||
PCINT_USE_PCINT0 (true/false)
|
||||
PCINT_USE_PORT0 (true/false)
|
||||
|
||||
Other definitions that can be used:
|
||||
PCINT_HAS_PORT0 (true/false)
|
||||
PCINT_HAS_PCINT0 (true/false)
|
||||
PCINT_NUM_PINS_PORT0 (0-8)
|
||||
PCINT_NUM_USED_PINS_PORT0 (0-8)
|
||||
EXTERNAL_NUM_PINCHANGEINTERRUPT (0-24)
|
||||
EXTERNAL_NUM_USED_PINCHANGEINTERRUPT (0-24)
|
||||
PCINT_NUM_PORTS (0-3)
|
||||
PCINT_NUM_USED_PORTS (0-3)
|
||||
*/
|
||||
|
||||
//================================================================================
|
||||
// Disabled Pins
|
||||
//================================================================================
|
||||
/*
|
||||
for (int port = 0; port < 4; port++) {
|
||||
Serial.print("#if defined(PCINT_ENABLE_PORT");
|
||||
Serial.print(port);
|
||||
Serial.print(") && defined(PCINT_DISABLE_PORT");
|
||||
Serial.print(port);
|
||||
Serial.println(")");
|
||||
Serial.print("#undef PCINT_ENABLE_PORT");
|
||||
Serial.println(port);
|
||||
Serial.println("#endif");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if defined(PCINT_ENABLE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.print(") && defined(PCINT_DISABLE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(")");
|
||||
Serial.print("#undef PCINT_ENABLE_PCINT");
|
||||
Serial.println(i);
|
||||
Serial.println("#endif");
|
||||
Serial.println();
|
||||
}
|
||||
*/
|
||||
#if defined(PCINT_ENABLE_PORT0) && defined(PCINT_DISABLE_PORT0)
|
||||
#undef PCINT_ENABLE_PORT0
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PORT1) && defined(PCINT_DISABLE_PORT1)
|
||||
#undef PCINT_ENABLE_PORT1
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PORT2) && defined(PCINT_DISABLE_PORT2)
|
||||
#undef PCINT_ENABLE_PORT2
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PORT3) && defined(PCINT_DISABLE_PORT3)
|
||||
#undef PCINT_ENABLE_PORT3
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT0) && defined(PCINT_DISABLE_PCINT0)
|
||||
#undef PCINT_ENABLE_PCINT0
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT1) && defined(PCINT_DISABLE_PCINT1)
|
||||
#undef PCINT_ENABLE_PCINT1
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT2) && defined(PCINT_DISABLE_PCINT2)
|
||||
#undef PCINT_ENABLE_PCINT2
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT3) && defined(PCINT_DISABLE_PCINT3)
|
||||
#undef PCINT_ENABLE_PCINT3
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT4) && defined(PCINT_DISABLE_PCINT4)
|
||||
#undef PCINT_ENABLE_PCINT4
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT5) && defined(PCINT_DISABLE_PCINT5)
|
||||
#undef PCINT_ENABLE_PCINT5
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT6) && defined(PCINT_DISABLE_PCINT6)
|
||||
#undef PCINT_ENABLE_PCINT6
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT7) && defined(PCINT_DISABLE_PCINT7)
|
||||
#undef PCINT_ENABLE_PCINT7
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT8) && defined(PCINT_DISABLE_PCINT8)
|
||||
#undef PCINT_ENABLE_PCINT8
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT9) && defined(PCINT_DISABLE_PCINT9)
|
||||
#undef PCINT_ENABLE_PCINT9
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT10) && defined(PCINT_DISABLE_PCINT10)
|
||||
#undef PCINT_ENABLE_PCINT10
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT11) && defined(PCINT_DISABLE_PCINT11)
|
||||
#undef PCINT_ENABLE_PCINT11
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT12) && defined(PCINT_DISABLE_PCINT12)
|
||||
#undef PCINT_ENABLE_PCINT12
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT13) && defined(PCINT_DISABLE_PCINT13)
|
||||
#undef PCINT_ENABLE_PCINT13
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT14) && defined(PCINT_DISABLE_PCINT14)
|
||||
#undef PCINT_ENABLE_PCINT14
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT15) && defined(PCINT_DISABLE_PCINT15)
|
||||
#undef PCINT_ENABLE_PCINT15
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT16) && defined(PCINT_DISABLE_PCINT16)
|
||||
#undef PCINT_ENABLE_PCINT16
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT17) && defined(PCINT_DISABLE_PCINT17)
|
||||
#undef PCINT_ENABLE_PCINT17
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT18) && defined(PCINT_DISABLE_PCINT18)
|
||||
#undef PCINT_ENABLE_PCINT18
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT19) && defined(PCINT_DISABLE_PCINT19)
|
||||
#undef PCINT_ENABLE_PCINT19
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT20) && defined(PCINT_DISABLE_PCINT20)
|
||||
#undef PCINT_ENABLE_PCINT20
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT21) && defined(PCINT_DISABLE_PCINT21)
|
||||
#undef PCINT_ENABLE_PCINT21
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT22) && defined(PCINT_DISABLE_PCINT22)
|
||||
#undef PCINT_ENABLE_PCINT22
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT23) && defined(PCINT_DISABLE_PCINT23)
|
||||
#undef PCINT_ENABLE_PCINT23
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT24) && defined(PCINT_DISABLE_PCINT24)
|
||||
#undef PCINT_ENABLE_PCINT24
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT25) && defined(PCINT_DISABLE_PCINT25)
|
||||
#undef PCINT_ENABLE_PCINT25
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT26) && defined(PCINT_DISABLE_PCINT26)
|
||||
#undef PCINT_ENABLE_PCINT26
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT27) && defined(PCINT_DISABLE_PCINT27)
|
||||
#undef PCINT_ENABLE_PCINT27
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT28) && defined(PCINT_DISABLE_PCINT28)
|
||||
#undef PCINT_ENABLE_PCINT28
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT29) && defined(PCINT_DISABLE_PCINT29)
|
||||
#undef PCINT_ENABLE_PCINT29
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT30) && defined(PCINT_DISABLE_PCINT30)
|
||||
#undef PCINT_ENABLE_PCINT30
|
||||
#endif
|
||||
|
||||
#if defined(PCINT_ENABLE_PCINT31) && defined(PCINT_DISABLE_PCINT31)
|
||||
#undef PCINT_ENABLE_PCINT31
|
||||
#endif
|
||||
|
||||
|
||||
//================================================================================
|
||||
// Enabled Pins
|
||||
//================================================================================
|
||||
|
||||
/* Disable all pins on a port, if port is deactivated
|
||||
We could then check every pin -> port definition
|
||||
But that'd be a mess and doesnt help
|
||||
Users who deactivate stuff should know
|
||||
what the are doing.
|
||||
So we use the enabled pins for all next definitions*/
|
||||
/*
|
||||
for (int port = 0; port < 4; port++) {
|
||||
Serial.print("#if !defined(PCINT_ENABLE_PORT");
|
||||
Serial.print(port);
|
||||
Serial.println(")");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print("#if defined(PCINT_ENABLE_PCINT");
|
||||
Serial.print(port * 8 + i);
|
||||
Serial.println(")");
|
||||
Serial.print("#undef PCINT_ENABLE_PCINT");
|
||||
Serial.println(port * 8 + i);
|
||||
Serial.println("#endif");
|
||||
}
|
||||
Serial.println("#endif");
|
||||
Serial.println();
|
||||
}
|
||||
*/
|
||||
#if !defined(PCINT_ENABLE_PORT0)
|
||||
#if defined(PCINT_ENABLE_PCINT0)
|
||||
#undef PCINT_ENABLE_PCINT0
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT1)
|
||||
#undef PCINT_ENABLE_PCINT1
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT2)
|
||||
#undef PCINT_ENABLE_PCINT2
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT3)
|
||||
#undef PCINT_ENABLE_PCINT3
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT4)
|
||||
#undef PCINT_ENABLE_PCINT4
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT5)
|
||||
#undef PCINT_ENABLE_PCINT5
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT6)
|
||||
#undef PCINT_ENABLE_PCINT6
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT7)
|
||||
#undef PCINT_ENABLE_PCINT7
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PCINT_ENABLE_PORT1)
|
||||
#if defined(PCINT_ENABLE_PCINT8)
|
||||
#undef PCINT_ENABLE_PCINT8
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT9)
|
||||
#undef PCINT_ENABLE_PCINT9
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT10)
|
||||
#undef PCINT_ENABLE_PCINT10
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT11)
|
||||
#undef PCINT_ENABLE_PCINT11
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT12)
|
||||
#undef PCINT_ENABLE_PCINT12
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT13)
|
||||
#undef PCINT_ENABLE_PCINT13
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT14)
|
||||
#undef PCINT_ENABLE_PCINT14
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT15)
|
||||
#undef PCINT_ENABLE_PCINT15
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PCINT_ENABLE_PORT2)
|
||||
#if defined(PCINT_ENABLE_PCINT16)
|
||||
#undef PCINT_ENABLE_PCINT16
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT17)
|
||||
#undef PCINT_ENABLE_PCINT17
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT18)
|
||||
#undef PCINT_ENABLE_PCINT18
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT19)
|
||||
#undef PCINT_ENABLE_PCINT19
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT20)
|
||||
#undef PCINT_ENABLE_PCINT20
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT21)
|
||||
#undef PCINT_ENABLE_PCINT21
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT22)
|
||||
#undef PCINT_ENABLE_PCINT22
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT23)
|
||||
#undef PCINT_ENABLE_PCINT23
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PCINT_ENABLE_PORT3)
|
||||
#if defined(PCINT_ENABLE_PCINT24)
|
||||
#undef PCINT_ENABLE_PCINT24
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT25)
|
||||
#undef PCINT_ENABLE_PCINT25
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT26)
|
||||
#undef PCINT_ENABLE_PCINT26
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT27)
|
||||
#undef PCINT_ENABLE_PCINT27
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT28)
|
||||
#undef PCINT_ENABLE_PCINT28
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT29)
|
||||
#undef PCINT_ENABLE_PCINT29
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT30)
|
||||
#undef PCINT_ENABLE_PCINT30
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT31)
|
||||
#undef PCINT_ENABLE_PCINT31
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//================================================================================
|
||||
// Hardware Definitions
|
||||
//================================================================================
|
||||
|
||||
#if defined(PCINT0_vect)
|
||||
#define PCINT_HAS_PORT0 true
|
||||
#else
|
||||
#define PCINT_HAS_PORT0 false
|
||||
#endif
|
||||
#if defined(PCINT1_vect)
|
||||
#define PCINT_HAS_PORT1 true
|
||||
#else
|
||||
#define PCINT_HAS_PORT1 false
|
||||
#endif
|
||||
#if defined(PCINT2_vect)
|
||||
#define PCINT_HAS_PORT2 true
|
||||
#else
|
||||
#define PCINT_HAS_PORT2 false
|
||||
#endif
|
||||
#if defined(PCINT3_vect)
|
||||
#define PCINT_HAS_PORT3 true
|
||||
#else
|
||||
#define PCINT_HAS_PORT3 false
|
||||
#endif
|
||||
|
||||
// number of available ports
|
||||
#define PCINT_NUM_PORTS ( \
|
||||
PCINT_HAS_PORT0 + \
|
||||
PCINT_HAS_PORT1 + \
|
||||
PCINT_HAS_PORT2 + \
|
||||
PCINT_HAS_PORT3)
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#ifdef PCINT");
|
||||
Serial.println(i);
|
||||
Serial.print("#define PCINT_HAS_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" true");
|
||||
Serial.println("#else");
|
||||
Serial.print("#define PCINT_HAS_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" false");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#ifdef PCINT0
|
||||
#define PCINT_HAS_PCINT0 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT0 false
|
||||
#endif
|
||||
#ifdef PCINT1
|
||||
#define PCINT_HAS_PCINT1 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT1 false
|
||||
#endif
|
||||
#ifdef PCINT2
|
||||
#define PCINT_HAS_PCINT2 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT2 false
|
||||
#endif
|
||||
#ifdef PCINT3
|
||||
#define PCINT_HAS_PCINT3 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT3 false
|
||||
#endif
|
||||
#ifdef PCINT4
|
||||
#define PCINT_HAS_PCINT4 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT4 false
|
||||
#endif
|
||||
#ifdef PCINT5
|
||||
#define PCINT_HAS_PCINT5 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT5 false
|
||||
#endif
|
||||
#ifdef PCINT6
|
||||
#define PCINT_HAS_PCINT6 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT6 false
|
||||
#endif
|
||||
#ifdef PCINT7
|
||||
#define PCINT_HAS_PCINT7 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT7 false
|
||||
#endif
|
||||
#ifdef PCINT8
|
||||
#define PCINT_HAS_PCINT8 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT8 false
|
||||
#endif
|
||||
#ifdef PCINT9
|
||||
#define PCINT_HAS_PCINT9 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT9 false
|
||||
#endif
|
||||
#ifdef PCINT10
|
||||
#define PCINT_HAS_PCINT10 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT10 false
|
||||
#endif
|
||||
#ifdef PCINT11
|
||||
#define PCINT_HAS_PCINT11 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT11 false
|
||||
#endif
|
||||
#ifdef PCINT12
|
||||
#define PCINT_HAS_PCINT12 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT12 false
|
||||
#endif
|
||||
#ifdef PCINT13
|
||||
#define PCINT_HAS_PCINT13 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT13 false
|
||||
#endif
|
||||
#ifdef PCINT14
|
||||
#define PCINT_HAS_PCINT14 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT14 false
|
||||
#endif
|
||||
#ifdef PCINT15
|
||||
#define PCINT_HAS_PCINT15 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT15 false
|
||||
#endif
|
||||
#ifdef PCINT16
|
||||
#define PCINT_HAS_PCINT16 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT16 false
|
||||
#endif
|
||||
#ifdef PCINT17
|
||||
#define PCINT_HAS_PCINT17 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT17 false
|
||||
#endif
|
||||
#ifdef PCINT18
|
||||
#define PCINT_HAS_PCINT18 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT18 false
|
||||
#endif
|
||||
#ifdef PCINT19
|
||||
#define PCINT_HAS_PCINT19 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT19 false
|
||||
#endif
|
||||
#ifdef PCINT20
|
||||
#define PCINT_HAS_PCINT20 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT20 false
|
||||
#endif
|
||||
#ifdef PCINT21
|
||||
#define PCINT_HAS_PCINT21 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT21 false
|
||||
#endif
|
||||
#ifdef PCINT22
|
||||
#define PCINT_HAS_PCINT22 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT22 false
|
||||
#endif
|
||||
#ifdef PCINT23
|
||||
#define PCINT_HAS_PCINT23 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT23 false
|
||||
#endif
|
||||
#ifdef PCINT24
|
||||
#define PCINT_HAS_PCINT24 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT24 false
|
||||
#endif
|
||||
#ifdef PCINT25
|
||||
#define PCINT_HAS_PCINT25 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT25 false
|
||||
#endif
|
||||
#ifdef PCINT26
|
||||
#define PCINT_HAS_PCINT26 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT26 false
|
||||
#endif
|
||||
#ifdef PCINT27
|
||||
#define PCINT_HAS_PCINT27 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT27 false
|
||||
#endif
|
||||
#ifdef PCINT28
|
||||
#define PCINT_HAS_PCINT28 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT28 false
|
||||
#endif
|
||||
#ifdef PCINT29
|
||||
#define PCINT_HAS_PCINT29 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT29 false
|
||||
#endif
|
||||
#ifdef PCINT30
|
||||
#define PCINT_HAS_PCINT30 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT30 false
|
||||
#endif
|
||||
#ifdef PCINT31
|
||||
#define PCINT_HAS_PCINT31 true
|
||||
#else
|
||||
#define PCINT_HAS_PCINT31 false
|
||||
#endif
|
||||
|
||||
|
||||
// count numbers of available pins on each port
|
||||
/*
|
||||
for (int port = 0; port < 4; port++) {
|
||||
Serial.print("#define PCINT_NUM_PINS_PORT");
|
||||
Serial.print(port);
|
||||
Serial.println(" ( \\");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print("PCINT_HAS_PCINT");
|
||||
Serial.print(port * 8 + i);
|
||||
if (i != 7)
|
||||
Serial.println(" + \\");
|
||||
}
|
||||
Serial.println(")");
|
||||
Serial.println();
|
||||
}
|
||||
*/
|
||||
#define PCINT_NUM_PINS_PORT0 ( \
|
||||
PCINT_HAS_PCINT0 + \
|
||||
PCINT_HAS_PCINT1 + \
|
||||
PCINT_HAS_PCINT2 + \
|
||||
PCINT_HAS_PCINT3 + \
|
||||
PCINT_HAS_PCINT4 + \
|
||||
PCINT_HAS_PCINT5 + \
|
||||
PCINT_HAS_PCINT6 + \
|
||||
PCINT_HAS_PCINT7)
|
||||
|
||||
#define PCINT_NUM_PINS_PORT1 ( \
|
||||
PCINT_HAS_PCINT8 + \
|
||||
PCINT_HAS_PCINT9 + \
|
||||
PCINT_HAS_PCINT10 + \
|
||||
PCINT_HAS_PCINT11 + \
|
||||
PCINT_HAS_PCINT12 + \
|
||||
PCINT_HAS_PCINT13 + \
|
||||
PCINT_HAS_PCINT14 + \
|
||||
PCINT_HAS_PCINT15)
|
||||
|
||||
#define PCINT_NUM_PINS_PORT2 ( \
|
||||
PCINT_HAS_PCINT16 + \
|
||||
PCINT_HAS_PCINT17 + \
|
||||
PCINT_HAS_PCINT18 + \
|
||||
PCINT_HAS_PCINT19 + \
|
||||
PCINT_HAS_PCINT20 + \
|
||||
PCINT_HAS_PCINT21 + \
|
||||
PCINT_HAS_PCINT22 + \
|
||||
PCINT_HAS_PCINT23)
|
||||
|
||||
#define PCINT_NUM_PINS_PORT3 ( \
|
||||
PCINT_HAS_PCINT24 + \
|
||||
PCINT_HAS_PCINT25 + \
|
||||
PCINT_HAS_PCINT26 + \
|
||||
PCINT_HAS_PCINT27 + \
|
||||
PCINT_HAS_PCINT28 + \
|
||||
PCINT_HAS_PCINT29 + \
|
||||
PCINT_HAS_PCINT30 + \
|
||||
PCINT_HAS_PCINT31)
|
||||
|
||||
|
||||
// number of available hardware pins
|
||||
#define EXTERNAL_NUM_PINCHANGEINTERRUPT ( \
|
||||
PCINT_NUM_PINS_PORT0 + \
|
||||
PCINT_NUM_PINS_PORT1 + \
|
||||
PCINT_NUM_PINS_PORT2 + \
|
||||
PCINT_NUM_PINS_PORT3)
|
||||
|
||||
|
||||
//================================================================================
|
||||
// Used Pins
|
||||
//================================================================================
|
||||
|
||||
// check if pins are physically available and enabled
|
||||
/*
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.print("#if (PCINT_HAS_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.print(" == true) && defined(PCINT_ENABLE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(")");
|
||||
Serial.print("#define PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" true");
|
||||
Serial.println("#else");
|
||||
Serial.print("#define PCINT_USE_PCINT");
|
||||
Serial.print(i);
|
||||
Serial.println(" false");
|
||||
Serial.println("#endif");
|
||||
}
|
||||
*/
|
||||
#if (PCINT_HAS_PCINT0 == true) && defined(PCINT_ENABLE_PCINT0)
|
||||
#define PCINT_USE_PCINT0 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT0 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT1 == true) && defined(PCINT_ENABLE_PCINT1)
|
||||
#define PCINT_USE_PCINT1 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT1 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT2 == true) && defined(PCINT_ENABLE_PCINT2)
|
||||
#define PCINT_USE_PCINT2 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT2 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT3 == true) && defined(PCINT_ENABLE_PCINT3)
|
||||
#define PCINT_USE_PCINT3 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT3 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT4 == true) && defined(PCINT_ENABLE_PCINT4)
|
||||
#define PCINT_USE_PCINT4 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT4 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT5 == true) && defined(PCINT_ENABLE_PCINT5)
|
||||
#define PCINT_USE_PCINT5 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT5 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT6 == true) && defined(PCINT_ENABLE_PCINT6)
|
||||
#define PCINT_USE_PCINT6 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT6 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT7 == true) && defined(PCINT_ENABLE_PCINT7)
|
||||
#define PCINT_USE_PCINT7 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT7 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT8 == true) && defined(PCINT_ENABLE_PCINT8)
|
||||
#define PCINT_USE_PCINT8 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT8 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT9 == true) && defined(PCINT_ENABLE_PCINT9)
|
||||
#define PCINT_USE_PCINT9 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT9 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT10 == true) && defined(PCINT_ENABLE_PCINT10)
|
||||
#define PCINT_USE_PCINT10 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT10 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT11 == true) && defined(PCINT_ENABLE_PCINT11)
|
||||
#define PCINT_USE_PCINT11 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT11 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT12 == true) && defined(PCINT_ENABLE_PCINT12)
|
||||
#define PCINT_USE_PCINT12 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT12 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT13 == true) && defined(PCINT_ENABLE_PCINT13)
|
||||
#define PCINT_USE_PCINT13 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT13 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT14 == true) && defined(PCINT_ENABLE_PCINT14)
|
||||
#define PCINT_USE_PCINT14 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT14 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT15 == true) && defined(PCINT_ENABLE_PCINT15)
|
||||
#define PCINT_USE_PCINT15 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT15 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT16 == true) && defined(PCINT_ENABLE_PCINT16)
|
||||
#define PCINT_USE_PCINT16 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT16 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT17 == true) && defined(PCINT_ENABLE_PCINT17)
|
||||
#define PCINT_USE_PCINT17 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT17 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT18 == true) && defined(PCINT_ENABLE_PCINT18)
|
||||
#define PCINT_USE_PCINT18 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT18 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT19 == true) && defined(PCINT_ENABLE_PCINT19)
|
||||
#define PCINT_USE_PCINT19 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT19 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT20 == true) && defined(PCINT_ENABLE_PCINT20)
|
||||
#define PCINT_USE_PCINT20 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT20 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT21 == true) && defined(PCINT_ENABLE_PCINT21)
|
||||
#define PCINT_USE_PCINT21 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT21 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT22 == true) && defined(PCINT_ENABLE_PCINT22)
|
||||
#define PCINT_USE_PCINT22 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT22 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT23 == true) && defined(PCINT_ENABLE_PCINT23)
|
||||
#define PCINT_USE_PCINT23 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT23 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT24 == true) && defined(PCINT_ENABLE_PCINT24)
|
||||
#define PCINT_USE_PCINT24 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT24 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT25 == true) && defined(PCINT_ENABLE_PCINT25)
|
||||
#define PCINT_USE_PCINT25 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT25 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT26 == true) && defined(PCINT_ENABLE_PCINT26)
|
||||
#define PCINT_USE_PCINT26 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT26 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT27 == true) && defined(PCINT_ENABLE_PCINT27)
|
||||
#define PCINT_USE_PCINT27 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT27 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT28 == true) && defined(PCINT_ENABLE_PCINT28)
|
||||
#define PCINT_USE_PCINT28 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT28 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT29 == true) && defined(PCINT_ENABLE_PCINT29)
|
||||
#define PCINT_USE_PCINT29 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT29 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT30 == true) && defined(PCINT_ENABLE_PCINT30)
|
||||
#define PCINT_USE_PCINT30 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT30 false
|
||||
#endif
|
||||
#if (PCINT_HAS_PCINT31 == true) && defined(PCINT_ENABLE_PCINT31)
|
||||
#define PCINT_USE_PCINT31 true
|
||||
#else
|
||||
#define PCINT_USE_PCINT31 false
|
||||
#endif
|
||||
|
||||
|
||||
//================================================================================
|
||||
// Number Used Pins
|
||||
//================================================================================
|
||||
|
||||
// count numbers of used pins on each port
|
||||
/*
|
||||
for (int port = 0; port < 4; port++) {
|
||||
Serial.print("#define PCINT_NUM_USED_PINS_PORT");
|
||||
Serial.print(port);
|
||||
Serial.println(" ( \\");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print("PCINT_USE_PCINT");
|
||||
Serial.print(port * 8 + i);
|
||||
if (i != 7)
|
||||
Serial.println(" + \\");
|
||||
}
|
||||
Serial.println(")");
|
||||
Serial.println();
|
||||
}
|
||||
*/
|
||||
#define PCINT_NUM_USED_PINS_PORT0 ( \
|
||||
PCINT_USE_PCINT0 + \
|
||||
PCINT_USE_PCINT1 + \
|
||||
PCINT_USE_PCINT2 + \
|
||||
PCINT_USE_PCINT3 + \
|
||||
PCINT_USE_PCINT4 + \
|
||||
PCINT_USE_PCINT5 + \
|
||||
PCINT_USE_PCINT6 + \
|
||||
PCINT_USE_PCINT7)
|
||||
|
||||
#define PCINT_NUM_USED_PINS_PORT1 ( \
|
||||
PCINT_USE_PCINT8 + \
|
||||
PCINT_USE_PCINT9 + \
|
||||
PCINT_USE_PCINT10 + \
|
||||
PCINT_USE_PCINT11 + \
|
||||
PCINT_USE_PCINT12 + \
|
||||
PCINT_USE_PCINT13 + \
|
||||
PCINT_USE_PCINT14 + \
|
||||
PCINT_USE_PCINT15)
|
||||
|
||||
#define PCINT_NUM_USED_PINS_PORT2 ( \
|
||||
PCINT_USE_PCINT16 + \
|
||||
PCINT_USE_PCINT17 + \
|
||||
PCINT_USE_PCINT18 + \
|
||||
PCINT_USE_PCINT19 + \
|
||||
PCINT_USE_PCINT20 + \
|
||||
PCINT_USE_PCINT21 + \
|
||||
PCINT_USE_PCINT22 + \
|
||||
PCINT_USE_PCINT23)
|
||||
|
||||
#define PCINT_NUM_USED_PINS_PORT3 ( \
|
||||
PCINT_USE_PCINT24 + \
|
||||
PCINT_USE_PCINT25 + \
|
||||
PCINT_USE_PCINT26 + \
|
||||
PCINT_USE_PCINT27 + \
|
||||
PCINT_USE_PCINT28 + \
|
||||
PCINT_USE_PCINT29 + \
|
||||
PCINT_USE_PCINT30 + \
|
||||
PCINT_USE_PCINT31)
|
||||
|
||||
|
||||
// number of used hardware pins
|
||||
#define EXTERNAL_NUM_USED_PINCHANGEINTERRUPT ( \
|
||||
PCINT_NUM_USED_PINS_PORT0 + \
|
||||
PCINT_NUM_USED_PINS_PORT1 + \
|
||||
PCINT_NUM_USED_PINS_PORT2 + \
|
||||
PCINT_NUM_USED_PINS_PORT3)
|
||||
|
||||
//================================================================================
|
||||
// Used Ports
|
||||
//================================================================================
|
||||
|
||||
// check if ports are used
|
||||
#if PCINT_NUM_USED_PINS_PORT0
|
||||
#define PCINT_USE_PORT0 true
|
||||
#else
|
||||
#define PCINT_USE_PORT0 false
|
||||
#endif
|
||||
#if PCINT_NUM_USED_PINS_PORT1
|
||||
#define PCINT_USE_PORT1 true
|
||||
#else
|
||||
#define PCINT_USE_PORT1 false
|
||||
#endif
|
||||
#if PCINT_NUM_USED_PINS_PORT2
|
||||
#define PCINT_USE_PORT2 true
|
||||
#else
|
||||
#define PCINT_USE_PORT2 false
|
||||
#endif
|
||||
#if PCINT_NUM_USED_PINS_PORT3
|
||||
#define PCINT_USE_PORT3 true
|
||||
#else
|
||||
#define PCINT_USE_PORT3 false
|
||||
#endif
|
||||
|
||||
// number of used ports
|
||||
#define PCINT_NUM_USED_PORTS ( \
|
||||
PCINT_USE_PORT0 + \
|
||||
PCINT_USE_PORT1 + \
|
||||
PCINT_USE_PORT2 + \
|
||||
PCINT_USE_PORT3)
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 NicoHood
|
||||
See the readme for credit to other people.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// include guard
|
||||
#pragma once
|
||||
|
||||
//================================================================================
|
||||
// General Settings
|
||||
//================================================================================
|
||||
|
||||
/* Settings to de/activate ports/pins
|
||||
This will save you flash and ram because the arrays
|
||||
are managed dynamically with the definitions below.
|
||||
Make sure you still have all needed ports activated.
|
||||
Each deactivated port saves 3 bytes of ram.
|
||||
If you deactivate the whole port,
|
||||
you dont need to deactivate the pins.
|
||||
Same for the port if you deactivate all 8 pins.
|
||||
You dont have to deactivate pins/ports that dont exist.
|
||||
That is done by the macros. */
|
||||
|
||||
#ifndef PCINT_ENABLE_MANUAL
|
||||
|
||||
#define PCINT_ENABLE_PORT0
|
||||
#define PCINT_ENABLE_PORT1
|
||||
#define PCINT_ENABLE_PORT2
|
||||
#define PCINT_ENABLE_PORT3
|
||||
|
||||
#define PCINT_ENABLE_PCINT0
|
||||
#define PCINT_ENABLE_PCINT1
|
||||
#define PCINT_ENABLE_PCINT2
|
||||
#define PCINT_ENABLE_PCINT3
|
||||
#define PCINT_ENABLE_PCINT4
|
||||
#define PCINT_ENABLE_PCINT5
|
||||
#define PCINT_ENABLE_PCINT6
|
||||
#define PCINT_ENABLE_PCINT7
|
||||
#define PCINT_ENABLE_PCINT8
|
||||
#define PCINT_ENABLE_PCINT9
|
||||
#define PCINT_ENABLE_PCINT10
|
||||
#define PCINT_ENABLE_PCINT11
|
||||
#define PCINT_ENABLE_PCINT12
|
||||
#define PCINT_ENABLE_PCINT13
|
||||
#define PCINT_ENABLE_PCINT14
|
||||
#define PCINT_ENABLE_PCINT15
|
||||
#define PCINT_ENABLE_PCINT16
|
||||
#define PCINT_ENABLE_PCINT17
|
||||
#define PCINT_ENABLE_PCINT18
|
||||
#define PCINT_ENABLE_PCINT19
|
||||
#define PCINT_ENABLE_PCINT20
|
||||
#define PCINT_ENABLE_PCINT21
|
||||
#define PCINT_ENABLE_PCINT22
|
||||
#define PCINT_ENABLE_PCINT23
|
||||
#define PCINT_ENABLE_PCINT24
|
||||
#define PCINT_ENABLE_PCINT25
|
||||
#define PCINT_ENABLE_PCINT26
|
||||
#define PCINT_ENABLE_PCINT27
|
||||
#define PCINT_ENABLE_PCINT28
|
||||
#define PCINT_ENABLE_PCINT29
|
||||
#define PCINT_ENABLE_PCINT30
|
||||
#define PCINT_ENABLE_PCINT31
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO
|
||||
// use API with function pointers (better optimized with .a linkage)
|
||||
#define PCINT_API
|
||||
|
||||
// is the library compiled via .a file?
|
||||
// see readme for more information
|
||||
#define PCINT_ALINKAGE
|
||||
|
||||
// force compile all enabled port ISRs (with .a linkage)
|
||||
//#define PCINT_COMPILE_ENABLED_ISR
|
||||
|
||||
#endif
|
||||
|
||||
//================================================================================
|
||||
// Suggested Settings
|
||||
//================================================================================
|
||||
|
||||
// Arduino Uno (328)
|
||||
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega88__)
|
||||
/* Reordering interrupt callbacks priority
|
||||
Port0 has SPI on higher pins, ordering is fine
|
||||
Port1 has I2C on higher pins, ordering is fine
|
||||
Port2 has USART and Pin Interrupt on lower pins,
|
||||
move the priority down
|
||||
Its more likely the user will use pin 4-7
|
||||
*/
|
||||
#if !defined(PCINT_CALLBACK_PORT2)
|
||||
#define PCINT_CALLBACK_PORT2 \
|
||||
PCINT_CALLBACK(4, 20); \
|
||||
PCINT_CALLBACK(5, 21); \
|
||||
PCINT_CALLBACK(6, 22); \
|
||||
PCINT_CALLBACK(7, 23); \
|
||||
PCINT_CALLBACK(0, 16); /* USART RX */ \
|
||||
PCINT_CALLBACK(1, 17); /* USART TX */ \
|
||||
PCINT_CALLBACK(2, 18); /* Pin Interrupt 0 */ \
|
||||
PCINT_CALLBACK(3, 19); /* Pin Interrupt 1 */
|
||||
#endif
|
||||
|
||||
// deactivate crystal and reset pins by default
|
||||
#if defined(PCINT_ENABLE_PCINT6)
|
||||
#undef PCINT_ENABLE_PCINT6 // crystal
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT7)
|
||||
#undef PCINT_ENABLE_PCINT7 // crystal
|
||||
#endif
|
||||
#if defined(PCINT_ENABLE_PCINT14)
|
||||
#undef PCINT_ENABLE_PCINT14 // reset
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Arduino Mega (2560)
|
||||
#if defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA)
|
||||
/* Port1 is structured a bit more complicated
|
||||
Also only 3 pins are connected on standard boards
|
||||
Seeeduino Mega has these pins optional!
|
||||
Disabling Port1 gives more speed and uses less flash
|
||||
Pins: 0(RX0), 14(TX3), 15(RX3) */
|
||||
#if defined(PCINT_ENABLE_PORT1)
|
||||
#undef PCINT_ENABLE_PORT1 // better performence
|
||||
#endif
|
||||
|
||||
/* Reordering interrupt callbacks priority
|
||||
Port2 has SPI on lower pins, move the priority down
|
||||
Its more likely the user will use pin 10-13
|
||||
Port1 by default deactivated, ordering is fine
|
||||
Port2 only has ADCs, ordering is fine
|
||||
*/
|
||||
#if !defined(PCINT_CALLBACK_PORT0)
|
||||
#define PCINT_CALLBACK_PORT0 \
|
||||
PCINT_CALLBACK(4, 4); \
|
||||
PCINT_CALLBACK(5, 5); \
|
||||
PCINT_CALLBACK(6, 6); \
|
||||
PCINT_CALLBACK(7, 7); \
|
||||
PCINT_CALLBACK(0, 0); /* SPI SS */ \
|
||||
PCINT_CALLBACK(1, 1); /* SPI SCK */ \
|
||||
PCINT_CALLBACK(2, 2); /* SPI MISO */ \
|
||||
PCINT_CALLBACK(3, 3); /* SPI MOSI */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Arduino Leonardo/Micro (32u4)
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
|
||||
/* Reordering interrupt callbacks priority
|
||||
Port0 has SPI on lower pins, move the priority down
|
||||
Its more likely the user will use pin 8-11 */
|
||||
#if !defined(PCINT_CALLBACK_PORT0)
|
||||
#define PCINT_CALLBACK_PORT0 \
|
||||
PCINT_CALLBACK(4, 4); \
|
||||
PCINT_CALLBACK(5, 5); \
|
||||
PCINT_CALLBACK(6, 6); \
|
||||
PCINT_CALLBACK(7, 7); \
|
||||
PCINT_CALLBACK(0, 0); /* SPI SS / RX LED */ \
|
||||
PCINT_CALLBACK(1, 1); /* SPI SCK */ \
|
||||
PCINT_CALLBACK(2, 2); /* SPI MISO */ \
|
||||
PCINT_CALLBACK(3, 3); /* SPI MOSI */
|
||||
#endif
|
||||
|
||||
// RX LED on normal leonardo/micro
|
||||
#if defined(PCINT_ENABLE_PCINT0) && (defined(ARDUINO_AVR_LEONARDO) || defined(ARDUINO_AVR_MICRO))
|
||||
#undef PCINT_ENABLE_PCINT0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Hoodloader2 (u2 Series)
|
||||
#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
|
||||
#if defined(ARDUINO_HOODLOADER2)
|
||||
// on HoodLoader2 Arduino boards only PB1-7 (port0) is broken out, save this flash
|
||||
#if defined(PCINT_ENABLE_PORT1)
|
||||
#undef PCINT_ENABLE_PORT1
|
||||
#endif
|
||||
|
||||
// SS (PB0) is not connected on normal Arduino boards
|
||||
#if defined(PCINT_ENABLE_PCINT0)
|
||||
#undef PCINT_ENABLE_PCINT0
|
||||
#endif
|
||||
|
||||
/* Reordering interrupt callbacks priority
|
||||
Port0 has SPI on lower pins, move the priority down
|
||||
Its more likely the user will use PB4-7
|
||||
Pretend the User has not soldered the 4 Pinheader
|
||||
so only do this for non Arduino boards. */
|
||||
#else
|
||||
#if !defined(PCINT_CALLBACK_PORT0)
|
||||
#define PCINT_CALLBACK_PORT0 \
|
||||
PCINT_CALLBACK(4, 4); \
|
||||
PCINT_CALLBACK(5, 5); \
|
||||
PCINT_CALLBACK(6, 6); \
|
||||
PCINT_CALLBACK(7, 7); \
|
||||
PCINT_CALLBACK(0, 0); /* SPI SS */ \
|
||||
PCINT_CALLBACK(1, 1); /* SPI SCK */ \
|
||||
PCINT_CALLBACK(2, 2); /* SPI MISO */ \
|
||||
PCINT_CALLBACK(3, 3); /* SPI MOSI */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Attiny 25/45/85 only has a very few pins
|
||||
activate all by default
|
||||
The order is also okay. */
|
||||
|
||||
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
// Port1 is connected to reset, crystal and Pin Interrupt 0
|
||||
// Deactivate it by default
|
||||
#if defined(PCINT_ENABLE_PORT1)
|
||||
#undef PCINT_ENABLE_PORT1
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user