/* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2017 PJRC.COM, LLC. * * 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: * * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. * * 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. */ #ifndef _avr_emulation_h_ #define _avr_emulation_h_ #include "kinetis.h" #include "core_pins.h" #include "pins_arduino.h" #ifdef __cplusplus #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) #define CONFIG_PULLUP (PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS) #define CONFIG_NOPULLUP (PORT_PCR_MUX(1)) #if defined(KINETISK) // bitband addressing for atomic access to data direction register #define GPIO_SETBIT_ATOMIC(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)) = 1) #define GPIO_CLRBIT_ATOMIC(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)) = 0) #elif defined(KINETISL) // bit manipulation engine for atomic access to data direction register #define GPIO_SETBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x480FF000) = 1 << (bit)) #define GPIO_CLRBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x440FF000) = ~(1 << (bit))) #endif class PORTDemulation { public: inline PORTDemulation & operator = (int val) __attribute__((always_inline)) { digitalWriteFast(0, (val & (1<<0))); if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(1, (val & (1<<1))); if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(2, (val & (1<<2))); if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(3, (val & (1<<3))); if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(4, (val & (1<<4))); if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(5, (val & (1<<5))); if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(6, (val & (1<<6))); if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = ((val & (1<<6)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(7, (val & (1<<7))); if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = ((val & (1<<7)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); return *this; } inline PORTDemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) { digitalWriteFast(0, HIGH); if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_PULLUP; } if (val & (1<<1)) { digitalWriteFast(1, HIGH); if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_PULLUP; } if (val & (1<<2)) { digitalWriteFast(2, HIGH); if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_PULLUP; } if (val & (1<<3)) { digitalWriteFast(3, HIGH); if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_PULLUP; } if (val & (1<<4)) { digitalWriteFast(4, HIGH); if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_PULLUP; } if (val & (1<<5)) { digitalWriteFast(5, HIGH); if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_PULLUP; } if (val & (1<<6)) { digitalWriteFast(6, HIGH); if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_PULLUP; } if (val & (1<<7)) { digitalWriteFast(7, HIGH); if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_PULLUP; } return *this; } inline PORTDemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) { digitalWriteFast(0, LOW); if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<1))) { digitalWriteFast(1, LOW); if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<2))) { digitalWriteFast(2, LOW); if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<3))) { digitalWriteFast(3, LOW); if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<4))) { digitalWriteFast(4, LOW); if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<5))) { digitalWriteFast(5, LOW); if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<6))) { digitalWriteFast(6, LOW); if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<7))) { digitalWriteFast(7, LOW); if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_NOPULLUP; } return *this; } }; extern PORTDemulation PORTD; class PINDemulation { public: inline int operator & (int val) const __attribute__((always_inline)) { int ret = 0; if ((val & (1<<0)) && digitalReadFast(0)) ret |= (1<<0); if ((val & (1<<1)) && digitalReadFast(1)) ret |= (1<<1); if ((val & (1<<2)) && digitalReadFast(2)) ret |= (1<<2); if ((val & (1<<3)) && digitalReadFast(3)) ret |= (1<<3); if ((val & (1<<4)) && digitalReadFast(4)) ret |= (1<<4); if ((val & (1<<5)) && digitalReadFast(5)) ret |= (1<<5); if ((val & (1<<6)) && digitalReadFast(6)) ret |= (1<<6); if ((val & (1<<7)) && digitalReadFast(7)) ret |= (1<<7); return ret; } operator int () const __attribute__((always_inline)) { int ret = 0; if (digitalReadFast(0)) ret |= (1<<0); if (digitalReadFast(1)) ret |= (1<<1); if (digitalReadFast(2)) ret |= (1<<2); if (digitalReadFast(3)) ret |= (1<<3); if (digitalReadFast(4)) ret |= (1<<4); if (digitalReadFast(5)) ret |= (1<<5); if (digitalReadFast(6)) ret |= (1<<6); if (digitalReadFast(7)) ret |= (1<<7); return ret; } }; extern PINDemulation PIND; class DDRDemulation { public: inline DDRDemulation & operator = (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); else clr0(); if (val & (1<<1)) set1(); else clr1(); if (val & (1<<2)) set2(); else clr2(); if (val & (1<<3)) set3(); else clr3(); if (val & (1<<4)) set4(); else clr4(); if (val & (1<<5)) set5(); else clr5(); if (val & (1<<6)) set6(); else clr6(); if (val & (1<<7)) set7(); else clr7(); return *this; } inline DDRDemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); if (val & (1<<1)) set1(); if (val & (1<<2)) set2(); if (val & (1<<3)) set3(); if (val & (1<<4)) set4(); if (val & (1<<5)) set5(); if (val & (1<<6)) set6(); if (val & (1<<7)) set7(); return *this; } inline DDRDemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) clr0(); if (!(val & (1<<1))) clr1(); if (!(val & (1<<2))) clr2(); if (!(val & (1<<3))) clr3(); if (!(val & (1<<4))) clr4(); if (!(val & (1<<5))) clr5(); if (!(val & (1<<6))) clr6(); if (!(val & (1<<7))) clr7(); return *this; } private: inline void set0() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN0_DDRREG, CORE_PIN0_BIT); CORE_PIN0_CONFIG = CONFIG_PULLUP; } inline void set1() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN1_DDRREG, CORE_PIN1_BIT); CORE_PIN1_CONFIG = CONFIG_PULLUP; } inline void set2() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN2_DDRREG, CORE_PIN2_BIT); CORE_PIN2_CONFIG = CONFIG_PULLUP; } inline void set3() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN3_DDRREG, CORE_PIN3_BIT); CORE_PIN3_CONFIG = CONFIG_PULLUP; } inline void set4() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN4_DDRREG, CORE_PIN4_BIT); CORE_PIN4_CONFIG = CONFIG_PULLUP; } inline void set5() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN5_DDRREG, CORE_PIN5_BIT); CORE_PIN5_CONFIG = CONFIG_PULLUP; } inline void set6() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN6_DDRREG, CORE_PIN6_BIT); CORE_PIN6_CONFIG = CONFIG_PULLUP; } inline void set7() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN7_DDRREG, CORE_PIN7_BIT); CORE_PIN7_CONFIG = CONFIG_PULLUP; } inline void clr0() __attribute__((always_inline)) { CORE_PIN0_CONFIG = ((CORE_PIN0_PORTREG & CORE_PIN0_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN0_DDRREG, CORE_PIN0_BIT); } inline void clr1() __attribute__((always_inline)) { CORE_PIN1_CONFIG = ((CORE_PIN1_PORTREG & CORE_PIN1_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN1_DDRREG, CORE_PIN1_BIT); } inline void clr2() __attribute__((always_inline)) { CORE_PIN2_CONFIG = ((CORE_PIN2_PORTREG & CORE_PIN2_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN2_DDRREG, CORE_PIN2_BIT); } inline void clr3() __attribute__((always_inline)) { CORE_PIN3_CONFIG = ((CORE_PIN3_PORTREG & CORE_PIN3_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN3_DDRREG, CORE_PIN3_BIT); } inline void clr4() __attribute__((always_inline)) { CORE_PIN4_CONFIG = ((CORE_PIN4_PORTREG & CORE_PIN4_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN4_DDRREG, CORE_PIN4_BIT); } inline void clr5() __attribute__((always_inline)) { CORE_PIN5_CONFIG = ((CORE_PIN5_PORTREG & CORE_PIN5_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN5_DDRREG, CORE_PIN5_BIT); } inline void clr6() __attribute__((always_inline)) { CORE_PIN6_CONFIG = ((CORE_PIN6_PORTREG & CORE_PIN6_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN6_DDRREG, CORE_PIN6_BIT); } inline void clr7() __attribute__((always_inline)) { CORE_PIN7_CONFIG = ((CORE_PIN7_PORTREG & CORE_PIN7_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN7_DDRREG, CORE_PIN7_BIT); } }; extern DDRDemulation DDRD; class PORTBemulation { public: inline PORTBemulation & operator = (int val) __attribute__((always_inline)) { digitalWriteFast(8, (val & (1<<0))); if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT)) CORE_PIN8_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(9, (val & (1<<1))); if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT)) CORE_PIN9_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(10, (val & (1<<2))); if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(11, (val & (1<<3))); if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(12, (val & (1<<4))); if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(13, (val & (1<<5))); if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); return *this; } inline PORTBemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) { digitalWriteFast(8, HIGH); if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN8_CONFIG = CONFIG_PULLUP; } if (val & (1<<1)) { digitalWriteFast(9, HIGH); if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN9_CONFIG = CONFIG_PULLUP; } if (val & (1<<2)) { digitalWriteFast(10, HIGH); if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_PULLUP; } if (val & (1<<3)) { digitalWriteFast(11, HIGH); if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_PULLUP; } if (val & (1<<4)) { digitalWriteFast(12, HIGH); if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_PULLUP; } if (val & (1<<5)) { digitalWriteFast(13, HIGH); if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_PULLUP; } return *this; } inline PORTBemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) { digitalWriteFast(8, LOW); if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT)) CORE_PIN8_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<1))) { digitalWriteFast(9, LOW); if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT)) CORE_PIN9_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<2))) { digitalWriteFast(10, LOW); if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<3))) { digitalWriteFast(11, LOW); if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<4))) { digitalWriteFast(12, LOW); if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<5))) { digitalWriteFast(13, LOW); if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_NOPULLUP; } return *this; } }; extern PORTBemulation PORTB; class PINBemulation { public: inline int operator & (int val) const __attribute__((always_inline)) { int ret = 0; if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0); if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1); if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2); if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3); if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4); if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5); return ret; } operator int () const __attribute__((always_inline)) { int ret = 0; if (digitalReadFast(8)) ret |= (1<<0); if (digitalReadFast(9)) ret |= (1<<1); if (digitalReadFast(10)) ret |= (1<<2); if (digitalReadFast(11)) ret |= (1<<3); if (digitalReadFast(12)) ret |= (1<<4); if (digitalReadFast(13)) ret |= (1<<5); return ret; } }; extern PINBemulation PINB; class DDRBemulation { public: inline DDRBemulation & operator = (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); else clr0(); if (val & (1<<1)) set1(); else clr1(); if (val & (1<<2)) set2(); else clr2(); if (val & (1<<3)) set3(); else clr3(); if (val & (1<<4)) set4(); else clr4(); if (val & (1<<5)) set5(); else clr5(); return *this; } inline DDRBemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); if (val & (1<<1)) set1(); if (val & (1<<2)) set2(); if (val & (1<<3)) set3(); if (val & (1<<4)) set4(); if (val & (1<<5)) set5(); return *this; } inline DDRBemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) clr0(); if (!(val & (1<<1))) clr1(); if (!(val & (1<<2))) clr2(); if (!(val & (1<<3))) clr3(); if (!(val & (1<<4))) clr4(); if (!(val & (1<<5))) clr5(); return *this; } private: inline void set0() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN8_DDRREG, CORE_PIN8_BIT); CORE_PIN8_CONFIG = CONFIG_PULLUP; } inline void set1() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN9_DDRREG, CORE_PIN9_BIT); CORE_PIN9_CONFIG = CONFIG_PULLUP; } inline void set2() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN10_DDRREG, CORE_PIN10_BIT); CORE_PIN10_CONFIG = CONFIG_PULLUP; } inline void set3() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN11_DDRREG, CORE_PIN11_BIT); CORE_PIN11_CONFIG = CONFIG_PULLUP; } inline void set4() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN12_DDRREG, CORE_PIN12_BIT); CORE_PIN12_CONFIG = CONFIG_PULLUP; } inline void set5() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN13_DDRREG, CORE_PIN13_BIT); CORE_PIN13_CONFIG = CONFIG_PULLUP; } inline void clr0() __attribute__((always_inline)) { CORE_PIN8_CONFIG = ((CORE_PIN8_PORTREG & CORE_PIN8_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN8_DDRREG, CORE_PIN8_BIT); } inline void clr1() __attribute__((always_inline)) { CORE_PIN9_CONFIG = ((CORE_PIN9_PORTREG & CORE_PIN9_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN9_DDRREG, CORE_PIN9_BIT); } inline void clr2() __attribute__((always_inline)) { CORE_PIN10_CONFIG = ((CORE_PIN10_PORTREG & CORE_PIN10_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN10_DDRREG, CORE_PIN10_BIT); } inline void clr3() __attribute__((always_inline)) { CORE_PIN11_CONFIG = ((CORE_PIN11_PORTREG & CORE_PIN11_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN11_DDRREG, CORE_PIN11_BIT); } inline void clr4() __attribute__((always_inline)) { CORE_PIN12_CONFIG = ((CORE_PIN12_PORTREG & CORE_PIN12_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN12_DDRREG, CORE_PIN12_BIT); } inline void clr5() __attribute__((always_inline)) { CORE_PIN13_CONFIG = ((CORE_PIN13_PORTREG & CORE_PIN13_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN13_DDRREG, CORE_PIN13_BIT); } }; extern DDRBemulation DDRB; class PORTCemulation { public: inline PORTCemulation & operator = (int val) __attribute__((always_inline)) { digitalWriteFast(14, (val & (1<<0))); if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(15, (val & (1<<1))); if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(16, (val & (1<<2))); if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(17, (val & (1<<3))); if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(18, (val & (1<<4))); if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); digitalWriteFast(19, (val & (1<<5))); if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP); return *this; } inline PORTCemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) { digitalWriteFast(14, HIGH); if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_PULLUP; } if (val & (1<<1)) { digitalWriteFast(15, HIGH); if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_PULLUP; } if (val & (1<<2)) { digitalWriteFast(16, HIGH); if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_PULLUP; } if (val & (1<<3)) { digitalWriteFast(17, HIGH); if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_PULLUP; } if (val & (1<<4)) { digitalWriteFast(18, HIGH); if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_PULLUP; } if (val & (1<<5)) { digitalWriteFast(19, HIGH); if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_PULLUP; } return *this; } inline PORTCemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) { digitalWriteFast(14, LOW); if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<1))) { digitalWriteFast(15, LOW); if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<2))) { digitalWriteFast(16, LOW); if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<3))) { digitalWriteFast(17, LOW); if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<4))) { digitalWriteFast(18, LOW); if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_NOPULLUP; } if (!(val & (1<<5))) { digitalWriteFast(19, LOW); if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_NOPULLUP; } return *this; } }; extern PORTCemulation PORTC; class PINCemulation { public: inline int operator & (int val) const __attribute__((always_inline)) { int ret = 0; if ((val & (1<<0)) && digitalReadFast(14)) ret |= (1<<0); if ((val & (1<<1)) && digitalReadFast(15)) ret |= (1<<1); if ((val & (1<<2)) && digitalReadFast(16)) ret |= (1<<2); if ((val & (1<<3)) && digitalReadFast(17)) ret |= (1<<3); if ((val & (1<<4)) && digitalReadFast(18)) ret |= (1<<4); if ((val & (1<<5)) && digitalReadFast(19)) ret |= (1<<5); return ret; } operator int () const __attribute__((always_inline)) { int ret = 0; if (digitalReadFast(14)) ret |= (1<<0); if (digitalReadFast(15)) ret |= (1<<1); if (digitalReadFast(16)) ret |= (1<<2); if (digitalReadFast(17)) ret |= (1<<3); if (digitalReadFast(18)) ret |= (1<<4); if (digitalReadFast(19)) ret |= (1<<5); return ret; } }; extern PINCemulation PINC; class DDRCemulation { public: inline DDRCemulation & operator = (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); else clr0(); if (val & (1<<1)) set1(); else clr1(); if (val & (1<<2)) set2(); else clr2(); if (val & (1<<3)) set3(); else clr3(); if (val & (1<<4)) set4(); else clr4(); if (val & (1<<5)) set5(); else clr5(); return *this; } inline DDRCemulation & operator |= (int val) __attribute__((always_inline)) { if (val & (1<<0)) set0(); if (val & (1<<1)) set1(); if (val & (1<<2)) set2(); if (val & (1<<3)) set3(); if (val & (1<<4)) set4(); if (val & (1<<5)) set5(); return *this; } inline DDRCemulation & operator &= (int val) __attribute__((always_inline)) { if (!(val & (1<<0))) clr0(); if (!(val & (1<<1))) clr1(); if (!(val & (1<<2))) clr2(); if (!(val & (1<<3))) clr3(); if (!(val & (1<<4))) clr4(); if (!(val & (1<<5))) clr5(); return *this; } private: inline void set0() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN14_DDRREG, CORE_PIN14_BIT); CORE_PIN14_CONFIG = CONFIG_PULLUP; } inline void set1() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN15_DDRREG, CORE_PIN15_BIT); CORE_PIN15_CONFIG = CONFIG_PULLUP; } inline void set2() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN16_DDRREG, CORE_PIN16_BIT); CORE_PIN16_CONFIG = CONFIG_PULLUP; } inline void set3() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN17_DDRREG, CORE_PIN17_BIT); CORE_PIN17_CONFIG = CONFIG_PULLUP; } inline void set4() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN18_DDRREG, CORE_PIN18_BIT); CORE_PIN18_CONFIG = CONFIG_PULLUP; } inline void set5() __attribute__((always_inline)) { GPIO_SETBIT_ATOMIC(CORE_PIN19_DDRREG, CORE_PIN19_BIT); CORE_PIN19_CONFIG = CONFIG_PULLUP; } inline void clr0() __attribute__((always_inline)) { CORE_PIN14_CONFIG = ((CORE_PIN14_PORTREG & CORE_PIN14_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN14_DDRREG, CORE_PIN14_BIT); } inline void clr1() __attribute__((always_inline)) { CORE_PIN15_CONFIG = ((CORE_PIN15_PORTREG & CORE_PIN15_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN15_DDRREG, CORE_PIN15_BIT); } inline void clr2() __attribute__((always_inline)) { CORE_PIN16_CONFIG = ((CORE_PIN16_PORTREG & CORE_PIN16_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN16_DDRREG, CORE_PIN16_BIT); } inline void clr3() __attribute__((always_inline)) { CORE_PIN17_CONFIG = ((CORE_PIN17_PORTREG & CORE_PIN17_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN17_DDRREG, CORE_PIN17_BIT); } inline void clr4() __attribute__((always_inline)) { CORE_PIN18_CONFIG = ((CORE_PIN18_PORTREG & CORE_PIN18_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN18_DDRREG, CORE_PIN18_BIT); } inline void clr5() __attribute__((always_inline)) { CORE_PIN19_CONFIG = ((CORE_PIN19_PORTREG & CORE_PIN19_BITMASK) ? CONFIG_PULLUP : CONFIG_NOPULLUP); GPIO_CLRBIT_ATOMIC(CORE_PIN19_DDRREG, CORE_PIN19_BIT); } }; extern DDRCemulation DDRC; #define PINB0 0 #define PINB1 1 #define PINB2 2 #define PINB3 3 #define PINB4 4 #define PINB5 5 #define PINB6 6 #define PINB7 7 #define DDB0 0 #define DDB1 1 #define DDB2 2 #define DDB3 3 #define DDB4 4 #define DDB5 5 #define DDB6 6 #define DDB7 7 #define PORTB0 0 #define PORTB1 1 #define PORTB2 2 #define PORTB3 3 #define PORTB4 4 #define PORTB5 5 #define PORTB6 6 #define PORTB7 7 #define PINC0 0 #define PINC1 1 #define PINC2 2 #define PINC3 3 #define PINC4 4 #define PINC5 5 #define PINC6 6 #define DDC0 0 #define DDC1 1 #define DDC2 2 #define DDC3 3 #define DDC4 4 #define DDC5 5 #define DDC6 6 #define PORTC0 0 #define PORTC1 1 #define PORTC2 2 #define PORTC3 3 #define PORTC4 4 #define PORTC5 5 #define PORTC6 6 #define PIND0 0 #define PIND1 1 #define PIND2 2 #define PIND3 3 #define PIND4 4 #define PIND5 5 #define PIND6 6 #define PIND7 7 #define DDD0 0 #define DDD1 1 #define DDD2 2 #define DDD3 3 #define DDD4 4 #define DDD5 5 #define DDD6 6 #define DDD7 7 #define PORTD0 0 #define PORTD1 1 #define PORTD2 2 #define PORTD3 3 #define PORTD4 4 #define PORTD5 5 #define PORTD6 6 #define PORTD7 7 #if 0 extern "C" { void serial_print(const char *p); void serial_phex(uint32_t n); void serial_phex16(uint32_t n); void serial_phex32(uint32_t n); } #endif // SPI Control Register ­ SPCR #define SPIE 7 // SPI Interrupt Enable - not supported #define SPE 6 // SPI Enable #define DORD 5 // DORD: Data Order #define MSTR 4 // MSTR: Master/Slave Select #define CPOL 3 // CPOL: Clock Polarity #define CPHA 2 // CPHA: Clock Phase #define SPR1 1 // Clock: 3 = 125 kHz, 2 = 250 kHz, 1 = 1 MHz, 0->4 MHz #define SPR0 0 // SPI Status Register ­ SPSR #define SPIF 7 // SPIF: SPI Interrupt Flag #define WCOL 6 // WCOL: Write COLlision Flag - not implemented #define SPI2X 0 // SPI2X: Double SPI Speed Bit // SPI Data Register ­ SPDR class SPCRemulation; class SPSRemulation; class SPDRemulation; #if defined(KINETISK) class SPCRemulation { public: inline SPCRemulation & operator = (int val) __attribute__((always_inline)) { uint32_t ctar, mcr, sim6; //serial_print("SPCR="); //serial_phex(val); //serial_print("\n"); sim6 = SIM_SCGC6; if (!(sim6 & SIM_SCGC6_SPI0)) { //serial_print("init1\n"); SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0; SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1); } if (!(val & (1<4 MHz //#define SPR0 0 // SPI Status Register ­ SPSR //#define SPIF 7 // SPIF: SPI Interrupt Flag //#define WCOL 6 // WCOL: Write COLlision Flag - not implemented //#define SPI2X 0 // SPI2X: Double SPI Speed Bit // SPI Data Register ­ SPDR class SPCRemulation { public: inline SPCRemulation & operator = (int val) __attribute__((always_inline)) { uint32_t sim4 = SIM_SCGC4; if (!(sim4 & SIM_SCGC4_SPI0)) { SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0; SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1); } uint32_t c1 = 0; if (val & (1<> 5] & (1 << (IRQ_PORTA & 31))) mask |= EIMSK_pA; if (icer[IRQ_PORTB >> 5] & (1 << (IRQ_PORTB & 31))) mask |= EIMSK_pB; if (icer[IRQ_PORTC >> 5] & (1 << (IRQ_PORTC & 31))) mask |= EIMSK_pC; if (icer[IRQ_PORTD >> 5] & (1 << (IRQ_PORTD & 31))) mask |= EIMSK_pD; if (icer[IRQ_PORTE >> 5] & (1 << (IRQ_PORTE & 31))) mask |= EIMSK_pE; return mask; } inline EIMSKemulation & operator |= (int val) __attribute__((always_inline)) { if (val & EIMSK_pA) NVIC_ENABLE_IRQ(IRQ_PORTA); if (val & EIMSK_pB) NVIC_ENABLE_IRQ(IRQ_PORTB); if (val & EIMSK_pC) NVIC_ENABLE_IRQ(IRQ_PORTC); if (val & EIMSK_pD) NVIC_ENABLE_IRQ(IRQ_PORTD); if (val & EIMSK_pE) NVIC_ENABLE_IRQ(IRQ_PORTE); return *this; } inline EIMSKemulation & operator &= (int val) __attribute__((always_inline)) { uint32_t n = val; if ((n | ~EIMSK_pA) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTA); if ((n | ~EIMSK_pB) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTB); if ((n | ~EIMSK_pC) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTC); if ((n | ~EIMSK_pD) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTD); if ((n | ~EIMSK_pE) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTE); return *this; } }; extern EIMSKemulation EIMSK; #elif defined(__MKL26Z64__) #define EIMSK_pA 0x00000018 // pins 3, 4, 24 #define EIMSK_pC 0x00C0BE00 // pins 9-13, 15, 22, 23 #define EIMSK_pD 0x003041E4 // pins 2, 5-8, 14, 20, 21 class EIMSKemulation // used by Adafruit_nRF8001 { public: operator int () const __attribute__((always_inline)) { int mask = 0; volatile const uint32_t *icer = &NVIC_ICER0; if (icer[IRQ_PORTA >> 5] & (1 << (IRQ_PORTA & 31))) mask |= EIMSK_pA; if (icer[IRQ_PORTCD >> 5] & (1 << (IRQ_PORTCD & 31))) mask |= (EIMSK_pC | EIMSK_pD); return mask; } inline EIMSKemulation & operator |= (int val) __attribute__((always_inline)) { if (val & EIMSK_pA) NVIC_ENABLE_IRQ(IRQ_PORTA); if (val & (EIMSK_pC | EIMSK_pD)) NVIC_ENABLE_IRQ(IRQ_PORTCD); return *this; } inline EIMSKemulation & operator &= (int val) __attribute__((always_inline)) { uint32_t n = val; if ((n | ~EIMSK_pA) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTA); if ((n | ~(EIMSK_pC | EIMSK_pD)) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTCD); return *this; } }; extern EIMSKemulation EIMSK; #endif // these are not intended for public consumption... #undef GPIO_BITBAND_ADDR #undef CONFIG_PULLUP #undef CONFIG_NOPULLUP #undef GPIO_SETBIT_ATOMIC #undef GPIO_CLRBIT_ATOMIC #endif // __cplusplus #endif