arduino/libraries/PinChangeInt/Examples/PinChangeIntSpeedTest/PinChangeIntSpeedTest.pde

265 lines
9.4 KiB
Text
Raw Normal View History

// PinChangeIntSpeedTest by GreyGnome aka Mike Schwager. Version numbers here refer to this sketch.
// Version 1.0 - initial version
// Version 1.1 - added code to test digitalRead()
// Version 1.2 - added new comments for the #define's for the NO_PORTx_PINCHANGES.
// Version 1.3 - includes cbiface.h with ooPinChangeInt, rather than cb.h
// Version 1.4 - testing version 2.10Beta with robtillaart's optimization
// Also added a #define/#undef INLINE_PCINTFUNC for inlining of the function called by the interrupt.
// Default: #undef for using the function as per usual. Changed PCIVERSION so that
// ooPinChangeInt starts at 1000 instead of 200. Modified the "Start" message to show "Start..", pause
// for 1 second, show "*\n" (where \n is a newline), pause for 1 second, then run the test.
// Version 1.4 - made this compatible with version 1.5 of PinChangeInt
// Version 1.5 - modified it to use #define OOPCIVERSION for ooPinChangeInt
// This version number is for ooPinChangeInt
//#define OOPCIVERSION 1030
#ifndef OOPCIVERSION
#define PCIVERSION 217 // 110 if using PinChangeInt-1.1, 120 for version 1.2
// 1000 for ooPinChangeIntversion 1.00, 1001 for ooPinChangeInt version 1.01, etc.
#endif
//-------- define these in your sketch, if applicable ----------------------------------------------------------
// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts
// on any one or two of the three ports. If only a single port remains, the handler will be declared inline
// reducing the size and latency of the handler.
#undef NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts
#undef NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts
// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts
// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine
// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or
// PCintPort::arduinoPin are set and made available to your interrupt routine.
// #define NO_PIN_STATE // to indicate that you don't need the pinState
// #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin
// if there is only one PCInt vector in use the code can be inlined
// reducing latency and code size
// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation.
//#define DISABLE_PCINT_MULTI_SERVICE
//-------- define the above in your sketch, if applicable ------------------------------------------------------
#if defined(OOPCIVERSION)
#define LIBRARYUNDERTEST "ooPinChangeInt"
#include <ooPinChangeInt.h>
#if PCIVERSION == 1001
#include <cb.h>
#else
#include <cbiface.h>
#endif
#else
#define LIBRARYUNDERTEST "PinChangeInt"
#include <PinChangeInt.h>
#endif
#define SERIALSTUFF // undef to take out all serial statements. Default: #define for measuring time.
#undef MEMTEST // undef to take out memory tests. Default: #undef for measuring time.
#undef INLINE_PCINTFUNC // define to inline the function called from the interrupt. This should have no effect,
// because the compiler will store the registers upon calling the interrupt routine, just
// like calling a function. Still, we test all assumptions.
//-----------------------
// NOTE: BECAUSE OF COLLISIONS in these libraries, you CANNOT have both libraries: PinChangeInt
// and ooPinChangeInt in the libraries directory at the same time. That said, under UNIX-y operating
// systems, it's easy to move the library directory to a name such as "PinChangeInt-1.3", which the
// Arduino will not recognize, and then create a symbolic link when you want to use a library. Such as:
// cd ~/Documents/Arduino/libaries
// mv PinChangeInt PinChangeInt-1.30
// mv ooPinChangeInt ooPinChangeInt-1.00
// ln -s PinChangeInt-1.30 PinChangeInt
#undef FLASH // to flash LED on pin 13 during test
#ifdef MEMTEST
#include <MemoryFree.h>
#endif
#define TEST 6
#if TEST == 1
#define PTEST 2 // pin to trigger interrupt. pins 0 and 1 are used
#define PLOW 2 // by Serial, so steer clear of them!
#define PHIGH 2 // Interrupts are attached to these pins
#elif TEST == 2 // see the #if TEST == 2 || TEST == 3 code, below
#define PTEST 2
#define PLOW 2
#define PHIGH 2 // need to attachInterrupt to 5 in the code
#elif TEST == 3 // see the #if TEST == 2 || TEST == 3 code, below
#define PTEST 5
#define PLOW 2
#define PHIGH 2 // need to attachInterrupt to 5 in the code
#elif TEST == 4
#define PTEST 2
#define PLOW 2
#define PHIGH 5
#elif TEST == 5
#define PTEST 3
#define PLOW 2
#define PHIGH 5
#elif TEST == 6
#define PTEST 4
#define PLOW 2
#define PHIGH 5
#elif TEST == 7
#define PTEST 5
#define PLOW 2
#define PHIGH 5
#endif
uint8_t qf0;
#ifdef INLINE_PCINTFUNC
#define INLINE_PCINTFUNC inline
#else
#define INLINE_PCINTFUNC
#endif
INLINE_PCINTFUNC void quicfunc();
void quicfunc() {
qf0=TCNT0;
}
#if defined(OOPCIVERSION)
class speedy : public CallBackInterface
{
public:
uint8_t id;
static uint8_t var0;
speedy () { id=0; };
speedy (uint8_t _i): id(_i) {};
void cbmethod() {
speedy::var0=TCNT0;
//Serial.print("Speedy method "); // debugging
//Serial.println(id, DEC);
};
};
uint8_t speedy::var0=0;
#endif
volatile uint8_t *led_port;
volatile uint8_t *pinT_OP;
volatile uint8_t *pinT_IP;
uint8_t led_mask, not_led_mask;
uint8_t pinT_M, not_pinT_M;
volatile uint8_t pintest, pinIntLow, pinIntHigh;
uint8_t totalpins;
#if defined(OOPCIVERSION)
speedy speedster[8]={speedy(0), speedy(1), speedy(2), speedy(3), speedy(4), speedy(5), speedy(6), speedy(7) };
#endif
#ifdef MEMTEST
int freemem;
#endif
int i=0;
#define PINLED 13
void setup()
{
#ifdef SERIALSTUFF
Serial.begin(115200); Serial.println("---------------------------------------");
#endif // SERIALSTUFF
// set up ports for trigger
pinMode(0, OUTPUT); digitalWrite(0, HIGH);
pinMode(1, OUTPUT); digitalWrite(1, HIGH);
pinMode(2, OUTPUT); digitalWrite(2, HIGH);
pinMode(3, OUTPUT); digitalWrite(3, HIGH);
pinMode(4, OUTPUT); digitalWrite(4, HIGH);
pinMode(5, OUTPUT); digitalWrite(5, HIGH);
pinMode(6, OUTPUT); digitalWrite(6, HIGH);
pinMode(7, OUTPUT); digitalWrite(7, HIGH);
#ifdef FLASH
led_port=portOutputRegister(digitalPinToPort(PINLED));
led_mask=digitalPinToBitMask(PINLED);
not_led_mask=led_mask^0xFF;
pinMode(PINLED, OUTPUT); digitalWrite(PINLED, LOW);
#endif
// *****************************************************************************
// set up ports for output ************ PIN TO TEST IS GIVEN HERE **************
// *****************************************************************************
pintest=PTEST;
pinIntLow=PLOW; pinIntHigh=PHIGH; // Interrupts are attached to these pins
// *****************************************************************************
// *****************************************************************************
pinT_OP=portOutputRegister(digitalPinToPort(pintest)); // output port
pinT_IP=portInputRegister(digitalPinToPort(pintest)); // input port
pinT_M=digitalPinToBitMask(pintest); // mask
not_pinT_M=pinT_M^0xFF; // not-mask
*pinT_OP|=pinT_M;
for (i=pinIntLow; i <= pinIntHigh; i++) {
#if defined(OOPCIVERSION)
PCintPort::attachInterrupt(i, &speedster[i], CHANGE); // C++ technique; v1.3 or better
#endif
#if defined(PCIVERSION)
PCintPort::attachInterrupt((uint8_t) i, &quicfunc, CHANGE); // C technique; v1.2 or earlier
#endif
}
#if TEST == 2 || TEST == 3
i=5; totalpins=2;
#if defined(OOPCIVERSION)
PCintPort::attachInterrupt(i, &speedster[i], CHANGE); // C++ technique; v1.3 or better
#endif
#if defined(PCIVERSION)
PCintPort::attachInterrupt(i, &quicfunc, CHANGE); // C technique; v1.2 or earlier
#endif
#else
totalpins=pinIntHigh - pinIntLow + 1;
#endif
i=0;
} // end setup()
uint8_t k=0;
unsigned long milliStart, milliEnd, elapsed;
void loop() {
k=0;
*pinT_OP|=pinT_M; // pintest to 1
#ifdef SERIALSTUFF
Serial.print(LIBRARYUNDERTEST); Serial.print(" ");
Serial.print("TEST: "); Serial.print(TEST, DEC); Serial.print(" ");
#ifndef MEMTEST
Serial.print("test pin mask: "); Serial.print(pinT_M, HEX);
Serial.print(". Total of "); Serial.print(totalpins, DEC); Serial.println(" pins enabled.");
#endif
#ifdef MEMTEST
freemem=freeMemory(); Serial.print("Free memory: "); Serial.println(freemem, DEC);
#endif
#endif
delay(1000);
Serial.print("Start..");
delay(1000); Serial.print("*");
#ifdef FLASH
*led_port|=led_mask;
#endif
milliStart=millis();
while (k < 10) {
i=0;
while (i < 10000) {
*pinT_OP&=not_pinT_M; // pintest to 0 ****************************** 16.8 us
*pinT_OP|=pinT_M; // pintest to 1 ****************************** ...to get here
i++;
}
k++;
}
milliEnd=millis();
#ifdef FLASH
*led_port&=not_led_mask;
#endif
elapsed=milliEnd-milliStart;
#ifndef MEMTEST
Serial.print(" Elapsed: ");
Serial.println(elapsed, DEC);
#endif
#ifdef SERIALSTUFF
Serial.print("Interrupted pin: ");
#if defined(OOPCIVERSION)
Serial.println(speedster[pintest].id, DEC);
#else
Serial.println(PCintPort::arduinoPin, DEC);
#endif
#ifdef MEMTEST
freemem=freeMemory(); Serial.print("END-Free memory: "); Serial.println(freemem, DEC);
#endif
#endif
delay(500);
}