#ifndef _LowLevel_h #define _LowLevel_h #include #ifdef VS_INTELLISENSE #define __attribute__(...) #define digitalPinToPort(pin) 0 #define digitalPinToBitMask(pin) 0 #define portInputRegister(arg1) 0 #endif #if ARDUINO >= 100 #include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc #else #include "WProgram.h" // for delayMicroseconds #include "pins_arduino.h" // for digitalPinToBitMask, etc #endif #if defined(__AVR__) #define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) #define IO_REG_TYPE uint8_t #define IO_REG_ASM asm("r30") #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) #define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) #if defined (__AVR_ATtiny85__) /* Note : The attiny85 clock speed = 16mhz (fuses L 0xF1, H 0xDF. E oxFF OSCCAL VALUE must also be calibrated to 16mhz */ #define CLEARINTERRUPT GIFR |= (1 << INTF0) | (1<PIO_PER)) #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) #define IO_REG_TYPE uint32_t #define IO_REG_ASM #define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) #define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) #define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) #ifndef PROGMEM #define PROGMEM #endif #ifndef pgm_read_byte #define pgm_read_byte(addr) (*(const uint8_t *)(addr)) #endif #elif defined(__PIC32MX__) #define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) #define IO_REG_TYPE uint32_t #define IO_REG_ASM #define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 #define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 #define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 #define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 #else #error "Please define I/O register types here" #endif class Pin { private: volatile IO_REG_TYPE *reg_; IO_REG_TYPE mask_; byte interruptNumber_; byte pinNumber_; public: Pin() : mask_(0) , reg_(0) , interruptNumber_((byte) - 1) , pinNumber_(255) { } Pin(uint8_t pin) { pinNumber_ = pin; mask_ = PIN_TO_BITMASK(pin); reg_ = PIN_TO_BASEREG(pin); switch (pin) { case 2: interruptNumber_ = 0; break; case 3: interruptNumber_ = 1; break; default: interruptNumber_ = (byte) - 1; } } inline byte getPinNumber() { return pinNumber_; } inline void inputMode() { DIRECT_MODE_INPUT(reg_, mask_); } inline void outputMode() { DIRECT_MODE_OUTPUT(reg_, mask_); } inline bool read() { return DIRECT_READ(reg_, mask_) == 1; } inline void writeLow() { DIRECT_WRITE_LOW(reg_, mask_); } inline void writeHigh() { DIRECT_WRITE_HIGH(reg_, mask_); } inline void write(bool value) { if (value) writeHigh(); else writeLow(); } inline void attachInterrupt(void (*handler)(), int mode) { CLEARINTERRUPT; // clear any pending interrupt (we want to call the handler only for interrupts happening after it is attached) ::attachInterrupt(interruptNumber_, handler, mode); } inline void detachInterrupt() { ::detachInterrupt(interruptNumber_); } }; #endif