diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/Readme.md b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/Readme.md new file mode 100644 index 0000000..cce1f76 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/Readme.md @@ -0,0 +1,385 @@ +PinChangeInterrupt Library 1.2.9 +================================ + +![Header Picture](header.png) + +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) + +Buy Me A Coffee + +#### 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 +``` + + +License and Copyright +===================== +If you use this library for any cool project let me know! + +``` +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. +``` diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_HowItWorks/PinChangeInterrupt_HowItWorks.ino b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_HowItWorks/PinChangeInterrupt_HowItWorks.ino new file mode 100644 index 0000000..e23743e --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_HowItWorks/PinChangeInterrupt_HowItWorks.ino @@ -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(); +} diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino new file mode 100644 index 0000000..21a7cb4 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino @@ -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 +} diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_LowLevel/PinChangeInterrupt_LowLevel.ino b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_LowLevel/PinChangeInterrupt_LowLevel.ino new file mode 100644 index 0000000..615f3bb --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_LowLevel/PinChangeInterrupt_LowLevel.ino @@ -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 +} diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_TickTock/PinChangeInterrupt_TickTock.ino b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_TickTock/PinChangeInterrupt_TickTock.ino new file mode 100644 index 0000000..622c34d --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/examples/PinChangeInterrupt_TickTock/PinChangeInterrupt_TickTock.ino @@ -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--; +} diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/header.png b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/header.png new file mode 100644 index 0000000..67818fc Binary files /dev/null and b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/header.png differ diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/keywords.txt b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/keywords.txt new file mode 100644 index 0000000..1af2b5d --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/keywords.txt @@ -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) +####################################### diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/library.properties b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/library.properties new file mode 100644 index 0000000..bb3a6e0 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/library.properties @@ -0,0 +1,10 @@ +name=PinChangeInterrupt +version=1.2.9 +author=NicoHood +maintainer=NicoHood +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 diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.cpp b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.cpp new file mode 100644 index 0000000..d83ef6b --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.cpp @@ -0,0 +1,336 @@ +/* +Copyright (c) 2014-2015 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 + // Special case for Attinyx4 where PCMSK1 and PCMSK0 are not next to each other + if(&PCMSK1 - &PCMSK0 == 1){ +#endif + // 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 PCMSK3 + case 3: + // disable the mask. + PCMSK3 &= ~pcintMask; + + // if that's the last one, disable the interrupt. + if (!PCMSK3) + disable = true; + break; +#endif + } + } +#endif +#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 + 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 +} +*/ diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.h b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.h new file mode 100644 index 0000000..b30fb62 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt.h @@ -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 +#include + +#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; +} diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt0.cpp b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt0.cpp new file mode 100644 index 0000000..c8dfba8 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt0.cpp @@ -0,0 +1,149 @@ +/* +Copyright (c) 2014-2015 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 diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt1.cpp b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt1.cpp new file mode 100644 index 0000000..e9953cd --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt1.cpp @@ -0,0 +1,149 @@ +/* +Copyright (c) 2014-2015 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 diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt2.cpp b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt2.cpp new file mode 100644 index 0000000..a3bd72e --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt2.cpp @@ -0,0 +1,149 @@ +/* +Copyright (c) 2014-2015 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 \ No newline at end of file diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt3.cpp b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt3.cpp new file mode 100644 index 0000000..71d2ea6 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterrupt3.cpp @@ -0,0 +1,149 @@ +/* +Copyright (c) 2014-2015 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 \ No newline at end of file diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptBoards.h b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptBoards.h new file mode 100644 index 0000000..fdcfa65 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptBoards.h @@ -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 diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptPins.h b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptPins.h new file mode 100644 index 0000000..832b6bd --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptPins.h @@ -0,0 +1,926 @@ +/* +Copyright (c) 2014-2017 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) diff --git a/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptSettings.h b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptSettings.h new file mode 100644 index 0000000..c485b84 --- /dev/null +++ b/Display Code/mbraidsv3/Libraries/PinChangeInterrupt/src/PinChangeInterruptSettings.h @@ -0,0 +1,230 @@ +/* +Copyright (c) 2014-2015 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 diff --git a/Display Code/mbraidsv3/mbraidsv3.ino b/Display Code/mbraidsv3/mbraidsv3.ino index 9ec54a9..b54d613 100644 --- a/Display Code/mbraidsv3/mbraidsv3.ino +++ b/Display Code/mbraidsv3/mbraidsv3.ino @@ -1,5 +1,5 @@ #include - +#include #include #include #include @@ -22,12 +22,17 @@ elapsedMillis sinceMux; #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif +constexpr int NUM_SEGMENTS = 14; void setup() { //char select inputs - pinMode(2, INPUT); - pinMode(3, INPUT); - pinMode(4, INPUT); - pinMode(5, INPUT); + pinMode(readIndex[0], INPUT); + attachPCINT(digitalPinToPCINT(readIndex[0]), dispcharISR0, RISING); + pinMode(readIndex[1], INPUT); + attachPCINT(digitalPinToPCINT(readIndex[1]), dispcharISR1, RISING); + pinMode(readIndex[2], INPUT); + attachPCINT(digitalPinToPCINT(readIndex[2]), dispcharISR2, RISING); + pinMode(readIndex[3], INPUT); + attachPCINT(digitalPinToPCINT(readIndex[3]), dispcharISR3, RISING); // pinMode(A0, INPUT); //mux in pinMode(A1, OUTPUT); //s0 @@ -43,7 +48,6 @@ void setup() { void loop() { - multiplexer(); if (sinceDisplay > 20) { testOutput(); @@ -149,4 +153,24 @@ void multiplexer() digitalWrite(A4, muxCount & 0b1000); inputDetect(); muxCount = (muxCount + 1) % 14; +} + +inline void dispcharISR(int selected) { + for (uint8_t mux_count = 0; mux_count < NUM_SEGMENTS; mux_count++) { + PORTC = mux_count << 1; + bitWrite(character[selected], mux_count, PINC & 0b1); + } +} + +void dispcharISR0(){ + dispcharISR(0); +} +void dispcharISR1(){ + dispcharISR(1); +} +void dispcharISR2(){ + dispcharISR(2); +} +void dispcharISR3(){ + dispcharISR(3); }