diff --git a/CapacitiveSensor.cpp b/CapacitiveSensor.cpp index f570cd7..4447847 100644 --- a/CapacitiveSensor.cpp +++ b/CapacitiveSensor.cpp @@ -1,6 +1,7 @@ /* CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring Copyright (c) 2009 Paul Bagder All right reserved. + Version 05 by Paul Stoffregen - Support Teensy 3.0, 3.1 Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix vim: set ts=4: */ @@ -20,8 +21,6 @@ CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin) { - uint8_t sPort, rPort; - // initialize this instance's variables // Serial.begin(9600); // for debugging error = 1; @@ -42,17 +41,13 @@ CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin) pinMode(sendPin, OUTPUT); // sendpin to OUTPUT pinMode(receivePin, INPUT); // receivePin to INPUT + digitalWrite(sendPin, LOW); sBit = digitalPinToBitMask(sendPin); // get send pin's ports and bitmask - sPort = digitalPinToPort(sendPin); - sReg = portModeRegister(sPort); - sOut = portOutputRegister(sPort); // get pointer to output register + sReg = PIN_TO_BASEREG(sendPin); // get pointer to output register rBit = digitalPinToBitMask(receivePin); // get receive pin's ports and bitmask - rPort = digitalPinToPort(receivePin); - rReg = portModeRegister(rPort); - rIn = portInputRegister(rPort); - rOut = portOutputRegister(rPort); + rReg = PIN_TO_BASEREG(receivePin); // get pin mapping and port for receive Pin - from digital pin functions in Wiring.c leastTotal = 0x0FFFFFFFL; // input large value for autocalibrate begin @@ -139,22 +134,20 @@ void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){ int CapacitiveSensor::SenseOneCycle(void) { noInterrupts(); - *sOut &= ~sBit; // sendPin Register low - - *rReg &= ~rBit; // receivePin to input - *rOut &= ~rBit; // receivePin Register low to make sure pullups are off - - *rReg |= rBit; // receivePin to OUTPUT - pin is now LOW AND OUTPUT - *rReg &= ~rBit; // receivePin to INPUT - - *sOut |= sBit; // sendPin High + DIRECT_WRITE_LOW(sReg, sBit); // sendPin Register low + DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off) + DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT + DIRECT_WRITE_LOW(rReg, rBit); // pin is now LOW AND OUTPUT + delayMicroseconds(10); + DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off) + DIRECT_WRITE_HIGH(sReg, sBit); // sendPin High interrupts(); - while ( !(*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value + while ( !DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value total++; } - Serial.print("SenseOneCycle(1): "); - Serial.println(total); + //Serial.print("SenseOneCycle(1): "); + //Serial.println(total); if (total > CS_Timeout_Millis) { return -2; // total variable over timeout @@ -162,19 +155,25 @@ int CapacitiveSensor::SenseOneCycle(void) // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V noInterrupts(); - *rOut |= rBit; // receivePin - turns on pullup - *rReg |= rBit; // receivePin to OUTPUT - pin is now HIGH AND OUTPUT - *rReg &= ~rBit; // receivePin to INPUT - *rOut &= ~rBit; // receivePin turn off pullup - - *sOut &= ~sBit; // sendPin LOW + DIRECT_WRITE_HIGH(rReg, rBit); + DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT - pin is now HIGH AND OUTPUT + DIRECT_WRITE_HIGH(rReg, rBit); + DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off) + DIRECT_WRITE_LOW(sReg, sBit); // sendPin LOW interrupts(); - while ( (*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout +#ifdef FIVE_VOLT_TOLERANCE_WORKAROUND + DIRECT_MODE_OUTPUT(rReg, rBit); + DIRECT_WRITE_LOW(rReg, rBit); + delayMicroseconds(10); + DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off) +#else + while ( DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout total++; } - Serial.print("SenseOneCycle(2): "); - Serial.println(total); +#endif + //Serial.print("SenseOneCycle(2): "); + //Serial.println(total); if (total >= CS_Timeout_Millis) { return -2; // total variable over timeout diff --git a/CapacitiveSensor.h b/CapacitiveSensor.h index 45424b1..dc686fb 100644 --- a/CapacitiveSensor.h +++ b/CapacitiveSensor.h @@ -15,6 +15,59 @@ #include "WProgram.h" #endif +// Direct I/O through registers and bitmask (from OneWire library) + +#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 DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask), (*((base)+2)) &= ~(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)) + +#elif defined(__MK20DX128__) || defined(__MK20DX256__) +#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) +#define PIN_TO_BITMASK(pin) (1) +#define IO_REG_TYPE uint8_t +#define IO_REG_ASM +#define DIRECT_READ(base, mask) (*((base)+512)) +#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) +#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) +#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) +#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) + +#elif defined(__SAM3X8E__) +#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->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)) + +#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 + +#endif + +// some 3.3V chips with 5V tolerant pins need this workaround +// +#if defined(__MK20DX256__) +#define FIVE_VOLT_TOLERANCE_WORKAROUND +#endif + // library interface description class CapacitiveSensor { @@ -37,13 +90,10 @@ class CapacitiveSensor unsigned long CS_AutocaL_Millis; unsigned long lastCal; unsigned long total; - uint8_t sBit; // send pin's ports and bitmask - volatile uint8_t *sReg; - volatile uint8_t *sOut; - uint8_t rBit; // receive pin's ports and bitmask - volatile uint8_t *rReg; - volatile uint8_t *rIn; - volatile uint8_t *rOut; + IO_REG_TYPE sBit; // send pin's ports and bitmask + volatile IO_REG_TYPE *sReg; + IO_REG_TYPE rBit; // receive pin's ports and bitmask + volatile IO_REG_TYPE *rReg; // methods int SenseOneCycle(void); };