Added some more projects and libraries.
This commit is contained in:
parent
f7151392ab
commit
1e1459fa50
94 changed files with 11904 additions and 0 deletions
324
libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp
Executable file
324
libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.cpp
Executable file
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
ByteBuffer.cpp - A circular buffer implementation for Arduino
|
||||
Created by Sigurdur Orn, July 19, 2010.
|
||||
siggi@mit.edu
|
||||
Updated by GreyGnome (aka Mike Schwager) Mon Apr 8 21:11:15 CDT 2013
|
||||
Fixed putString() so it reenables inputs correctly. In the if (length == capacity) section,
|
||||
it was missing this line:
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
Updated by GreyGnome (aka Mike Schwager) Thu Feb 23 17:25:14 CST 2012
|
||||
added the putString() method and the fillError variable.
|
||||
added the checkError() and resetError() methods. The checkError() method resets the fillError variable
|
||||
to false as a side effect.
|
||||
added the ByteBuffer(unsigned int buf_size) constructor.
|
||||
added the init() method, and had the constructor call it automagically.
|
||||
Also made the capacity, position, length, and fillError variables volatile, for safe use by interrupts.
|
||||
Mon Dec 3 07:55:04 CST 2012
|
||||
Added the putHex() and putDec() methods.
|
||||
*/
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
void ByteBuffer::init(){
|
||||
ByteBuffer::init(DEFAULTBUFSIZE);
|
||||
}
|
||||
|
||||
void ByteBuffer::init(unsigned int buf_length){
|
||||
data = (byte*)malloc(sizeof(byte)*buf_length);
|
||||
capacity = buf_length;
|
||||
position = 0;
|
||||
length = 0;
|
||||
fillError=false;
|
||||
}
|
||||
|
||||
// Arduino 1.0: free() doesn't free. :-( This is a no-op as of 11/2012.
|
||||
void ByteBuffer::deAllocate(){
|
||||
free(data);
|
||||
}
|
||||
|
||||
void ByteBuffer::clear(){
|
||||
position = 0;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
void ByteBuffer::resetError(){
|
||||
fillError=false;
|
||||
}
|
||||
|
||||
boolean ByteBuffer::checkError(){
|
||||
/*
|
||||
if (fillError) {
|
||||
Serial.print("E: checkError: length ");
|
||||
Serial.println(length, DEC);
|
||||
}
|
||||
*/
|
||||
|
||||
boolean result=fillError;
|
||||
fillError=false;
|
||||
return(result);
|
||||
}
|
||||
|
||||
int ByteBuffer::getSize(){
|
||||
return length;
|
||||
}
|
||||
|
||||
int ByteBuffer::getCapacity(){
|
||||
return capacity;
|
||||
}
|
||||
|
||||
byte ByteBuffer::peek(unsigned int index){
|
||||
byte b = data[(position+index)%capacity];
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t ByteBuffer::put(byte in){
|
||||
if(length < capacity){
|
||||
// save data byte at end of buffer
|
||||
data[(position+length) % capacity] = in;
|
||||
// increment the length
|
||||
length++;
|
||||
return 1;
|
||||
}
|
||||
// return failure
|
||||
//Serial.print("E: put: ");
|
||||
//Serial.println(length, DEC);
|
||||
fillError=true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ByteBuffer::putString(const char *in) {
|
||||
return(putString((char *) in));
|
||||
}
|
||||
|
||||
uint8_t ByteBuffer::putString(char *in){
|
||||
uint8_t count=0;
|
||||
char *inString;
|
||||
|
||||
inString=in;
|
||||
uint8_t oldSREG = SREG; cli();
|
||||
while(length <= capacity){
|
||||
if (length == capacity) {
|
||||
fillError=true;
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return count;
|
||||
}
|
||||
// save data byte at end of buffer
|
||||
data[(position+length) % capacity] = *inString;
|
||||
// increment the length
|
||||
length++;
|
||||
inString++;
|
||||
count++;
|
||||
if (*inString == 0) {
|
||||
if (count==0) fillError=true; // Serial.println("E: putString"); };
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return count;
|
||||
}
|
||||
}
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t ByteBuffer::putInFront(byte in){
|
||||
uint8_t oldSREG = SREG; cli();
|
||||
if(length < capacity){
|
||||
// save data byte at end of buffer
|
||||
if( position == 0 )
|
||||
position = capacity-1;
|
||||
else
|
||||
position = (position-1)%capacity;
|
||||
data[position] = in;
|
||||
// increment the length
|
||||
length++;
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return 1;
|
||||
}
|
||||
// return failure
|
||||
//Serial.println("E: putInFront");
|
||||
fillError=true;
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns 0 if length of data is 0.
|
||||
byte ByteBuffer::get(){
|
||||
uint8_t oldSREG = SREG; cli();
|
||||
byte b = 0;
|
||||
|
||||
if(length > 0){
|
||||
b = data[position];
|
||||
// move index down and decrement length
|
||||
position = (position+1)%capacity;
|
||||
length--;
|
||||
}
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
return b;
|
||||
}
|
||||
|
||||
byte ByteBuffer::getFromBack(){
|
||||
byte b = 0;
|
||||
if(length > 0){
|
||||
uint8_t oldSREG = SREG; cli();
|
||||
b = data[(position+length-1)%capacity];
|
||||
length--;
|
||||
SREG = oldSREG; // Restore register; reenables interrupts
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
//
|
||||
// Ints
|
||||
//
|
||||
|
||||
void ByteBuffer::putIntInFront(int in){
|
||||
byte *pointer = (byte *)∈
|
||||
putInFront(pointer[0]);
|
||||
putInFront(pointer[1]);
|
||||
}
|
||||
|
||||
void ByteBuffer::putInt(int in){
|
||||
byte *pointer = (byte *)∈
|
||||
put(pointer[1]);
|
||||
put(pointer[0]);
|
||||
}
|
||||
|
||||
|
||||
int ByteBuffer::getInt(){
|
||||
int ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[1] = get();
|
||||
pointer[0] = get();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ByteBuffer::getIntFromBack(){
|
||||
int ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[0] = getFromBack();
|
||||
pointer[1] = getFromBack();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ByteBuffer::putHex(uint8_t theByte) {
|
||||
put('0'); put('x');
|
||||
uint8_t hinybble=theByte>>4;
|
||||
uint8_t lonybble=theByte & 0x0F;
|
||||
uint8_t addend=0;
|
||||
if (hinybble >= 0x0a) addend=7;
|
||||
put(hinybble+48+addend);
|
||||
if (lonybble >= 0x0a) addend=7;
|
||||
else addend=0;
|
||||
put(lonybble+48+addend);
|
||||
}
|
||||
|
||||
void ByteBuffer::putDec(uint8_t number) {
|
||||
uint8_t hundreds=0;
|
||||
uint8_t tens=0;
|
||||
uint8_t ones=0;
|
||||
uint8_t tmp=number;
|
||||
|
||||
while (tmp >= 100 ) {
|
||||
hundreds++;
|
||||
tmp-=100;
|
||||
}
|
||||
while (tmp >= 10 ) {
|
||||
tens++;
|
||||
tmp-=10;
|
||||
}
|
||||
ones=tmp;
|
||||
hundreds+=48; tens+=48; ones+=48;
|
||||
if (number >= 100) { put(hundreds); }
|
||||
if (number >= 10) { put(tens); }
|
||||
put(ones);
|
||||
}
|
||||
|
||||
void ByteBuffer::putDec(int8_t number) {
|
||||
uint8_t absNumber=abs(number);
|
||||
if (number < 0) put('-');
|
||||
putDec(absNumber);
|
||||
}
|
||||
|
||||
//
|
||||
// Longs
|
||||
//
|
||||
|
||||
void ByteBuffer::putLongInFront(long in){
|
||||
byte *pointer = (byte *)∈
|
||||
putInFront(pointer[0]);
|
||||
putInFront(pointer[1]);
|
||||
putInFront(pointer[2]);
|
||||
putInFront(pointer[3]);
|
||||
}
|
||||
|
||||
void ByteBuffer::putLong(long in){
|
||||
byte *pointer = (byte *)∈
|
||||
put(pointer[3]);
|
||||
put(pointer[2]);
|
||||
put(pointer[1]);
|
||||
put(pointer[0]);
|
||||
}
|
||||
|
||||
|
||||
long ByteBuffer::getLong(){
|
||||
long ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[3] = get();
|
||||
pointer[2] = get();
|
||||
pointer[1] = get();
|
||||
pointer[0] = get();
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ByteBuffer::getLongFromBack(){
|
||||
long ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[0] = getFromBack();
|
||||
pointer[1] = getFromBack();
|
||||
pointer[2] = getFromBack();
|
||||
pointer[3] = getFromBack();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Floats
|
||||
//
|
||||
|
||||
void ByteBuffer::putFloatInFront(float in){
|
||||
byte *pointer = (byte *)∈
|
||||
putInFront(pointer[0]);
|
||||
putInFront(pointer[1]);
|
||||
putInFront(pointer[2]);
|
||||
putInFront(pointer[3]);
|
||||
}
|
||||
|
||||
void ByteBuffer::putFloat(float in){
|
||||
byte *pointer = (byte *)∈
|
||||
put(pointer[3]);
|
||||
put(pointer[2]);
|
||||
put(pointer[1]);
|
||||
put(pointer[0]);
|
||||
}
|
||||
|
||||
float ByteBuffer::getFloat(){
|
||||
float ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[3] = get();
|
||||
pointer[2] = get();
|
||||
pointer[1] = get();
|
||||
pointer[0] = get();
|
||||
return ret;
|
||||
}
|
||||
|
||||
float ByteBuffer::getFloatFromBack(){
|
||||
float ret;
|
||||
byte *pointer = (byte *)&ret;
|
||||
pointer[0] = getFromBack();
|
||||
pointer[1] = getFromBack();
|
||||
pointer[2] = getFromBack();
|
||||
pointer[3] = getFromBack();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
104
libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h
Executable file
104
libraries/PinChangeInt/Examples/ByteBuffer/ByteBuffer.h
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
ByteBuffer.h - A circular buffer implementation for Arduino
|
||||
Created by Sigurdur Orn, July 19, 2010. siggi@mit.edu
|
||||
Updated by GreyGnome (aka Mike Schwager) Thu Feb 23 17:25:14 CST 2012
|
||||
added the putString() method and the fillError variable.
|
||||
added the checkError() and resetError() methods. The checkError() method resets the fillError variable
|
||||
to false as a side effect.
|
||||
added the ByteBuffer(unsigned int buf_size) constructor.
|
||||
added the init() method, and had the constructor call it automagically.
|
||||
protected certain sections of the code with cli()/sei() calls, for safe use by interrupts.
|
||||
Also made the capacity, position, length, and fillError variables volatile, for safe use by interrupts.
|
||||
*/
|
||||
|
||||
#ifndef ByteBuffer_h
|
||||
#define ByteBuffer_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
//#include <util/atomic.h>
|
||||
|
||||
#define DEFAULTBUFSIZE 32
|
||||
class ByteBuffer
|
||||
{
|
||||
public:
|
||||
ByteBuffer() {
|
||||
init();
|
||||
};
|
||||
ByteBuffer(unsigned int buf_size) {
|
||||
init(buf_size);
|
||||
};
|
||||
|
||||
// This method initializes the datastore of the buffer to a certain size.
|
||||
void init(unsigned int buf_size);
|
||||
|
||||
// This method initializes the datastore of the buffer to the default size.
|
||||
void init();
|
||||
|
||||
// This method resets the buffer into an original state (with no data)
|
||||
void clear();
|
||||
|
||||
// This method resets the fillError variable to false.
|
||||
void resetError();
|
||||
|
||||
// This method tells you if your buffer overflowed at some time since the last
|
||||
// check. The error state will be reset to false.
|
||||
boolean checkError();
|
||||
|
||||
// This releases resources for this buffer, after this has been called the buffer should NOT be used
|
||||
void deAllocate();
|
||||
|
||||
// Returns how much space is used in the buffer
|
||||
int getSize();
|
||||
|
||||
// Returns the maximum capacity of the buffer
|
||||
int getCapacity();
|
||||
|
||||
// This method returns the byte that is located at index in the buffer but doesn't modify the buffer like the get methods (doesn't remove the retured byte from the buffer)
|
||||
byte peek(unsigned int index);
|
||||
|
||||
//
|
||||
// Put methods, either a regular put in back or put in front
|
||||
//
|
||||
uint8_t putInFront(byte in);
|
||||
uint8_t put(byte in);
|
||||
uint8_t putString(char *in);
|
||||
|
||||
void putIntInFront(int in);
|
||||
void putInt(int in);
|
||||
|
||||
void putLongInFront(long in);
|
||||
void putLong(long in);
|
||||
|
||||
void putFloatInFront(float in);
|
||||
void putFloat(float in);
|
||||
|
||||
//
|
||||
// Get methods, either a regular get from front or from back
|
||||
//
|
||||
byte get();
|
||||
byte getFromBack();
|
||||
|
||||
int getInt();
|
||||
int getIntFromBack();
|
||||
|
||||
long getLong();
|
||||
long getLongFromBack();
|
||||
|
||||
float getFloat();
|
||||
float getFloatFromBack();
|
||||
|
||||
private:
|
||||
byte* data;
|
||||
|
||||
volatile unsigned int capacity;
|
||||
volatile unsigned int position;
|
||||
volatile unsigned int length;
|
||||
volatile boolean fillError;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
21
libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h
Normal file
21
libraries/PinChangeInt/Examples/GetPSTR/GetPSTR.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef INCLUDE_GETPSTR
|
||||
#define INCLUDE_GETPSTR
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include "pins_arduino.h"
|
||||
#include "WProgram.h"
|
||||
#include "wiring.h"
|
||||
#endif
|
||||
|
||||
#define getPSTR(s) pgmStrToRAM(PSTR(s))
|
||||
|
||||
char *_pstr_to_print;
|
||||
char *pgmStrToRAM(PROGMEM char *theString) {
|
||||
free(_pstr_to_print);
|
||||
_pstr_to_print=(char *) malloc(strlen_P(theString));
|
||||
strcpy_P(_pstr_to_print, theString);
|
||||
return (_pstr_to_print);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
// PinChangeIntDebug
|
||||
// version 1.0 Wed Jul 9 16:20:56 CDT 2014
|
||||
// Lean project for debugging. Don't expect a lot of commentary in here. This is for hacking.
|
||||
// This code taken from Examples/PinChangeIntTest, so refer there for more information and commentary.
|
||||
|
||||
#define PINMODE
|
||||
#define FLASH
|
||||
#include <ByteBuffer.h>
|
||||
#include <MemoryFree.h>
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// This example demonstrates a configuration of 6 interrupting pins and 3 interrupt functions.
|
||||
// A variety of interrupting pins have been chosen, so as to test all PORTs on the Arduino.
|
||||
// The pins are as follows:
|
||||
#define INTERRUPT_PIN1 2 // port D
|
||||
#define INTERRUPT_PIN2 3
|
||||
#define INTERRUPT_PIN3 11 // Port B
|
||||
#define INTERRUPT_PIN4 12
|
||||
#define INTERRUPT_PIN5 A3 // Port C, also can be given as "17"
|
||||
#define INTERRUPT_PIN6 A4
|
||||
|
||||
uint8_t pins[6]={ INTERRUPT_PIN1, INTERRUPT_PIN2, INTERRUPT_PIN3, INTERRUPT_PIN4, INTERRUPT_PIN5, INTERRUPT_PIN6 };
|
||||
uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
uint8_t latest_interrupted_pin;
|
||||
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
|
||||
uint8_t port;
|
||||
uint8_t mode;
|
||||
|
||||
ByteBuffer printBuffer(200);
|
||||
char charArray[16];
|
||||
char numBuffer[5] = { 0, 0, 0, 0, 0 };
|
||||
uint8_t printFull=0;
|
||||
|
||||
volatile boolean start=0;
|
||||
volatile boolean initial=true;
|
||||
long begintime=0;
|
||||
long now=0;
|
||||
|
||||
void smallIntToString(char *outString, int number) {
|
||||
uint8_t thousands=0;
|
||||
uint8_t hundreds=0;
|
||||
uint8_t tens=0;
|
||||
uint8_t ones=0;
|
||||
|
||||
if (number > 9999) {
|
||||
outString[0]='S'; outString[1]='I'; outString[2]='Z'; outString[3]='E'; outString[4]=0;
|
||||
return;
|
||||
}
|
||||
while (number >= 1000 ) {
|
||||
thousands++;
|
||||
number-=1000;
|
||||
}
|
||||
while (number >= 100 ) {
|
||||
hundreds++;
|
||||
number-=100;
|
||||
}
|
||||
while (number >= 10 ) {
|
||||
tens++;
|
||||
number-=10;
|
||||
}
|
||||
ones=number;
|
||||
ones+=48;
|
||||
if (thousands > 0) {
|
||||
thousands+=48; hundreds+=48; tens+=48;
|
||||
outString[0]=thousands; outString[1]=hundreds; outString[2]=tens;
|
||||
outString[3]=ones; outString[4]=0;
|
||||
}
|
||||
else if (hundreds > 0) {
|
||||
hundreds+=48; tens+=48;
|
||||
outString[0]=hundreds; outString[1]=tens; outString[2]=ones; outString[3]=0;
|
||||
}
|
||||
else if (tens > 0) {
|
||||
tens+=48;
|
||||
outString[0]=tens; outString[1]=ones; outString[2]=0;
|
||||
}
|
||||
else { outString[0]=ones; outString[1]=0; };
|
||||
}
|
||||
|
||||
void showMode() {
|
||||
switch (mode) {
|
||||
case FALLING:
|
||||
printBuffer.putString((char *) "-F-");
|
||||
break;
|
||||
case RISING:
|
||||
printBuffer.putString((char *) "+R+");
|
||||
break;
|
||||
case CHANGE:
|
||||
printBuffer.putString((char *) "*C*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void quicfunc0() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start==1) {
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
}
|
||||
smallIntToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString((char *) "f0p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
smallIntToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) "\n");
|
||||
};
|
||||
|
||||
#define MAXPINCOUNT 6
|
||||
void attachInterrupts() {
|
||||
uint8_t i;
|
||||
for (i=0; i < MAXPINCOUNT; i++) {
|
||||
pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH);
|
||||
ports[i]=digitalPinToPort(pins[i]);
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
void detachInterrupts() {
|
||||
uint8_t i;
|
||||
for (i=0; i < MAXPINCOUNT; i++) {
|
||||
PCintPort::detachInterrupt(pins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
bool interrupts_are_attached=false;
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(250);
|
||||
Serial.println("Test");
|
||||
delay(250);
|
||||
Serial.print("*---*");
|
||||
begintime=millis();
|
||||
attachInterrupts(); interrupts_are_attached=true;
|
||||
Serial.println("NOTICE: Interrupts ATTACHED.");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#define LOOPDELAY 2000
|
||||
now=millis();
|
||||
uint8_t count;
|
||||
char outChar;
|
||||
uint8_t pinState;
|
||||
while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar);
|
||||
if ((now - begintime) > LOOPDELAY) {
|
||||
Serial.print(".");
|
||||
pinState=digitalRead(INTERRUPT_PIN1);
|
||||
if (pinState == HIGH){
|
||||
Serial.print("H");
|
||||
}
|
||||
else { Serial.print("L");
|
||||
}
|
||||
if (printBuffer.checkError()) {
|
||||
Serial.println("NOTICE: Some output lost due to filled buffer.");
|
||||
}
|
||||
for (i=0; i < 20; i++) {
|
||||
if (interrupt_count[i] != 0) {
|
||||
count=interrupt_count[i];
|
||||
interrupt_count[i]=0;
|
||||
Serial.print("Count for pin ");
|
||||
if (i < 14) {
|
||||
Serial.print("D");
|
||||
Serial.print(i, DEC);
|
||||
} else {
|
||||
Serial.print("A");
|
||||
Serial.print(i-14, DEC);
|
||||
}
|
||||
Serial.print(" is ");
|
||||
Serial.println(count, DEC);
|
||||
}
|
||||
}
|
||||
begintime=millis();
|
||||
if (interrupts_are_attached) {
|
||||
detachInterrupts(); interrupts_are_attached=false;
|
||||
Serial.print("NOTICE: Interrupts DETACHED. Memory: ");
|
||||
Serial.print(freeMemory(), DEC);
|
||||
Serial.println(" bytes");
|
||||
}
|
||||
else {
|
||||
Serial.print("NOTICE: ATTACHING Interrupts. Memory: ");
|
||||
Serial.print(freeMemory(), DEC);
|
||||
Serial.println(" bytes");
|
||||
attachInterrupts(); interrupts_are_attached=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// PinChangeIntExample2560
|
||||
// This only works for ATMega2560-based boards.
|
||||
// See the Arduino and the chip documentation for more details.
|
||||
|
||||
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
|
||||
// for vim editing: :set et ts=2 sts=2 sw=2
|
||||
|
||||
// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions.
|
||||
// The functions set the values of some global variables. All interrupts are serviced immediately,
|
||||
// and the sketch can then query the values at our leisure. This makes loop timing non-critical.
|
||||
|
||||
// The interrupt functions are a simple count of the number of times the pin was brought high.
|
||||
// For 2 of the pins, the values are stored and retrieved from an array and they are reset after
|
||||
// every read. For one of the pins ("MYPIN3"), there is a monotonically increasing count; that is,
|
||||
// until the 8-bit value reaches 255. Then it will go back to 0.
|
||||
|
||||
// For a more introductory sketch, see the SimpleExample328.ino sketch in the PinChangeInt
|
||||
// library distribution.
|
||||
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// PIN NAMING
|
||||
// For the Analog Input pins used as digital input pins, you can call them 14, 15, 16, etc.
|
||||
// or you can use A0, A1, A2, etc. (the Arduino code will properly recognize the symbolic names,
|
||||
// for example, pinMode(A0, INPUT_PULLUP);
|
||||
|
||||
// For Arduino MEGA (AT2560-based), besides the regular pins and the A (analog) pins,
|
||||
// you have 4 more pins with defined names:
|
||||
// SS = 53
|
||||
// MOSI = 51
|
||||
// MISO = 50
|
||||
// SCK = 52
|
||||
|
||||
// NOW CHOOSE PINS
|
||||
#if ! ( defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__ || defined __AVR_ATmega640__ )
|
||||
#error "This sketch only works on chips in the ATmega2560 family."
|
||||
#endif
|
||||
|
||||
#define FIRST_ANALOG_PIN 54
|
||||
#define TOTAL_PINS 69 // But only 18 of them (not including RX0) are PinChangeInt-compatible
|
||||
// Don't use RX0 (Arduino pin 0) in this program- it won't work this is the
|
||||
// pin that Serial.print() uses!
|
||||
// See the Arduino and the chip documentation for more details.
|
||||
#define MYPIN1 SS
|
||||
#define MYPIN2 SCK
|
||||
#define MYPIN3 MOSI
|
||||
#define PIN3TEXT "MOSI" // This will say what MYPIN3 is, on the serial monitor
|
||||
|
||||
volatile uint8_t latest_interrupted_pin;
|
||||
volatile uint8_t interrupt_count[TOTAL_PINS]={0}; // possible arduino pins
|
||||
volatile uint8_t pin3Count=0;
|
||||
|
||||
// Do not use any Serial.print() in this function. Serial.print() uses interrupts, and is not compatible
|
||||
// with an interrupt routine...!
|
||||
void quicfunc() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
};
|
||||
|
||||
// You can assign any number of functions to different pins. How cool is that?
|
||||
void pin3func() {
|
||||
pin3Count++;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(MYPIN1, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN1, quicfunc, FALLING); // add more attachInterrupt code as required
|
||||
pinMode(MYPIN2, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN2, quicfunc, FALLING);
|
||||
pinMode(MYPIN3, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN3, pin3func, CHANGE);
|
||||
Serial.begin(115200);
|
||||
Serial.println("---------------------------------------");
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
uint8_t currentPIN3Count=0;
|
||||
void loop() {
|
||||
uint8_t count;
|
||||
Serial.print(".");
|
||||
delay(1000); // every second,
|
||||
for (i=0; i < TOTAL_PINS; i++) {
|
||||
if (interrupt_count[i] != 0) { // look at all the interrupted pins
|
||||
count=interrupt_count[i]; // store its count since the last iteration
|
||||
interrupt_count[i]=0; // and reset it to 0.
|
||||
Serial.print("Count for pin ");
|
||||
if (i == 50) { Serial.print("MISO"); } // then tell the user what it was, in a friendly way.
|
||||
else if (i == 51) { Serial.print("MOSI"); }
|
||||
else if (i == 52) { Serial.print("SCK"); }
|
||||
else if (i == 53) { Serial.print("SS"); }
|
||||
else if (i < FIRST_ANALOG_PIN) {
|
||||
Serial.print("D");
|
||||
Serial.print(i, DEC);
|
||||
} else {
|
||||
Serial.print("A");
|
||||
Serial.print(i-FIRST_ANALOG_PIN, DEC);
|
||||
}
|
||||
Serial.print(" is ");
|
||||
Serial.println(count, DEC);
|
||||
}
|
||||
}
|
||||
if (currentPIN3Count != pin3Count) { // Print our monotonically increasing counter (no reset to 0)
|
||||
Serial.print(PIN3TEXT);
|
||||
Serial.print(" count update: "); Serial.print(pin3Count, DEC); Serial.println();
|
||||
currentPIN3Count=pin3Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// PinChangeIntExample
|
||||
// This only works for ATMega328-compatibles; ie, Leonardo is not covered here.
|
||||
// See the Arduino and the chip documentation for more details.
|
||||
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
|
||||
|
||||
// for vim editing: :set et ts=2 sts=2 sw=2
|
||||
|
||||
// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions.
|
||||
// The functions set the values of some global variables. All interrupts are serviced immediately,
|
||||
// and the sketch can then query the values at our leisure. This makes loop timing non-critical.
|
||||
|
||||
// The interrupt functions are a simple count of the number of times the pin was brought high.
|
||||
// For 2 of the pins, the values are stored and retrieved from an array and they are reset after
|
||||
// every read. For one of the pins ("MYPIN3"), there is a monotonically increasing count; that is,
|
||||
// until the 8-bit value reaches 255. Then it will go back to 0.
|
||||
|
||||
// For a more introductory sketch, see the SimpleExample328.ino sketch in the PinChangeInt
|
||||
// library distribution.
|
||||
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// Modify these at your leisure.
|
||||
#define MYPIN1 A3
|
||||
#define MYPIN2 A4
|
||||
#define MYPIN3 A5
|
||||
|
||||
// Don't change these.
|
||||
#define FIRST_ANALOG_PIN 14
|
||||
#define TOTAL_PINS 19
|
||||
// Notice that anything that gets modified inside an interrupt, that I wish to access
|
||||
// outside the interrupt, is marked "volatile". That tells the compiler not to optimize
|
||||
// them.
|
||||
volatile uint8_t latest_interrupted_pin;
|
||||
volatile uint8_t interrupt_count[TOTAL_PINS]={0}; // possible arduino pins
|
||||
volatile uint8_t pin3Count=0;
|
||||
|
||||
// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,
|
||||
// and by default interrupts are off in interrupt subroutines.
|
||||
// Here we update a counter corresponding to whichever pin interrupted.
|
||||
void quicfunc() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
};
|
||||
|
||||
// You can assign any number of functions to different pins. How cool is that?
|
||||
// Here we have a global variable that we increment. We can access this variable outside the interrupt,
|
||||
// and we know it will be valid because it was declared "volatile"- meaning, the compiler performs
|
||||
// no optimizations on it.
|
||||
void pin3func() {
|
||||
pin3Count++;
|
||||
}
|
||||
|
||||
// Attach the interrupts in setup()
|
||||
void setup() {
|
||||
pinMode(MYPIN1, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN1, quicfunc, RISING);
|
||||
pinMode(MYPIN2, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN2, quicfunc, RISING);
|
||||
pinMode(MYPIN3, INPUT_PULLUP);
|
||||
attachPinChangeInterrupt(MYPIN3, pin3func, CHANGE); // Any state change will trigger the interrupt.
|
||||
Serial.begin(115200);
|
||||
Serial.println("---------------------------------------");
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
uint8_t currentPIN3Count=0;
|
||||
|
||||
void loop() {
|
||||
uint8_t count;
|
||||
Serial.print(".");
|
||||
delay(1000); // every second,
|
||||
for (i=0; i < TOTAL_PINS; i++) {
|
||||
if (interrupt_count[i] != 0) { // look at all the interrupted pins
|
||||
count=interrupt_count[i]; // store its count since the last iteration
|
||||
interrupt_count[i]=0; // and reset it to 0
|
||||
Serial.print("Count for pin ");
|
||||
if (i < FIRST_ANALOG_PIN) { // then tell the user what it was, in a friendly way
|
||||
Serial.print("D");
|
||||
Serial.print(i, DEC);
|
||||
} else {
|
||||
Serial.print("A");
|
||||
Serial.print(i-FIRST_ANALOG_PIN, DEC);
|
||||
}
|
||||
Serial.print(" is ");
|
||||
Serial.println(count, DEC);
|
||||
}
|
||||
}
|
||||
if (currentPIN3Count != pin3Count) { // Print our monotonically increasing counter (no reset to 0).
|
||||
Serial.print("Pin 3 count update: "); Serial.print(pin3Count, DEC); Serial.println();
|
||||
currentPIN3Count=pin3Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
// 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);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
// PinChangeIntTest
|
||||
//
|
||||
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
|
||||
// This sketch requires the ByteBuffer library, which is found in the PinChangeInt zipfile.
|
||||
// for vim editing: :set et ts=2 sts=2 sw=2
|
||||
//-------- define these in your sketch, if applicable ----------------------------------------------------------
|
||||
//-------- This must go ahead of the #include statement --------------------------------------------------------
|
||||
// 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.
|
||||
// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts
|
||||
// #define 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
|
||||
// The following is intended for testing purposes. If defined, then a variable PCintPort::pinMode can be read
|
||||
// in your interrupt subroutine. It is not defined by default:
|
||||
// #define PINMODE
|
||||
//-------- define the above in your sketch, if applicable ------------------------------------------------------
|
||||
#define PINMODE
|
||||
#define FLASH
|
||||
#include <ByteBuffer.h>
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
#define NEWLINE "\r\n" // Programs like "screen" in Linux don't return with a "\n" character.
|
||||
|
||||
// This example demonstrates a configuration of 6 interrupting pins and 3 interrupt functions.
|
||||
// A variety of interrupting pins have been chosen, so as to test all PORTs on the Arduino.
|
||||
// The pins are as follows:
|
||||
// quicfunc0 is attached to tPIN1-4.
|
||||
// quicfunc1 is attached to tPIN5.
|
||||
// quicfunc2 is attached to tPIN6.
|
||||
// Pins tPIN1 and tPIN6 interrupt on FALLING.
|
||||
// tPIN2 and tPIN4 interrupt on RISING.
|
||||
// tPIN3 and tPIN5 interrupt on CHANGE.
|
||||
// NOTE:
|
||||
// For the Analog Input pins used as digital input pins, you can use numbers such as 14, 15, 16, etc.
|
||||
// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's for the Analog Input pin
|
||||
// names and will properly recognize e.g., pinMode(A0, INPUT_PULLUP));
|
||||
#if defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__ || defined __AVR_ATmega640__
|
||||
#define tPIN1 14 // port J
|
||||
#define tPIN2 15
|
||||
#define tPIN3 A8 // Port K
|
||||
#define tPIN4 A12
|
||||
#define tPIN5 SS // Port B, also can be given as "57"
|
||||
#define tPIN6 MOSI // This pin starts and stops the count
|
||||
#else
|
||||
// These only work for ATMega328-compatibles; ie, Leonardo is not covered here.
|
||||
#define tPIN1 2 // port D
|
||||
#define tPIN2 3
|
||||
#define tPIN3 11 // Port B
|
||||
#define tPIN4 12
|
||||
#define tPIN5 A3 // Port C, also can be given as "17"
|
||||
#define tPIN6 A4 // This pin starts and stops the count
|
||||
#endif
|
||||
|
||||
// HOW IT WORKS (ATmega328-specific; replace the references with the proper pins for the other chip types)
|
||||
// The interrupt on Arduino pin A4 (tPIN6) will, when triggered, start the counting of interrupts.
|
||||
// The array interrupt_count0[20] is updated in the interrupts; each cell keeps track of the number
|
||||
// of interrupts on one of the 20 available interrupt pins on the Arduino. Every second in the main
|
||||
// loop the array is scanned and registered interrupts are reported for all pins interrupted since
|
||||
// the previous second. If no interrupts, the output is quiet.
|
||||
|
||||
// tPIN6 is special. Not only does it start the counting of the interrups, but it turns on and off
|
||||
// interrupts on pins 2, 11, and A3/17 (tPIN1, tPIN3, tPIN5). All pins start by interrupting, but after
|
||||
// the count is turned on and then turned off, the 3 pins are detached from interrupts.
|
||||
// Everytime thereafter when the count is turned off the 3 pins are detached. They are reattached
|
||||
// when turned on.
|
||||
|
||||
// Output is copied to a buffer, because we can't do a Serial.print() statement in an interrupt
|
||||
// routine. The main loop checks for entries in the buffer and prints them if found.
|
||||
// Output looks like this:
|
||||
// -F- - an interrupt triggered by a falling signal occurred.
|
||||
// +R+ - an interrupt triggered by a rising signal occurred.
|
||||
// *C* - an interrupt triggered by a change in signal occurred.
|
||||
// f#p#-P# - f# shows the interrupt subroutine that was called: 0, 1, or 2
|
||||
// - p# shows the pin number that triggered the interrupt
|
||||
// - P# shows the port that this pin number is attached to. 2 is PORTB, 3 is PORTC, 4 is PORTD
|
||||
|
||||
// HOW TO CONNECT
|
||||
// Each pin gets a momentary contact switch connected to it. One side of the switch should connect
|
||||
// to ground. The other side of the switch connects to the Arduino pin. For my purposes, I am using
|
||||
// two rotary encoders. Each encoder contains 3 switches. But 6 regular pushbuttons would work, too.
|
||||
|
||||
/* WHAT TO LOOK FOR
|
||||
Output is sent to the serial line, so the Arduino IDE's serial terminal should be opened.
|
||||
Upon startup, press tPINS1-5. You will see output like this:
|
||||
-F-f0p2-P4 (counting off)
|
||||
..*C*f0p11-P2 (counting off)
|
||||
+R+f0p3-P4 (counting off)
|
||||
This shows that
|
||||
1. an interrupt was triggered on a falling signal (*F*). It called (f0) function 0, which is quicfunc0.
|
||||
The triggering pin was (p2) Arduuino pin 2, which is on (P4) Port 4 (PORTD). Counting of this interrupt is
|
||||
off, so you will not see any output from the main loop.
|
||||
2. Two dots appeared. Dots came from iterations of loop(), so these 2 dots show that the two interrupts happened 2 seconds apart.
|
||||
3. an interrupt was triggered on a change in signal (*C*). It called quicfunc0, from Arduino pin 11, on Port 2 (PORTB).
|
||||
The interrupt was not counted.
|
||||
4. an interrupt was triggered on a rising signal (+R+). It called quicfunc0, from Arduino pin 3, on Purt 4 (PORTD).
|
||||
The pin should have started out at the high level, so likely the signal fell during onother interrupt, and now
|
||||
the rise has been caught.
|
||||
|
||||
Now press the button attached to tPIN6 (in our case, A4 or D18). You will see something like this:
|
||||
-F-START! f2p18-P3
|
||||
.Count for pin A4 is 1
|
||||
This shows that
|
||||
1. The counting machanism (START!) was triggered by a folling signal (-F-) on pin 18 (p18) which is in Port 3 (P3) (which == PORTC) and
|
||||
function f2 was called (f2).
|
||||
2. A dot appeared, which came from loop() because a second passed.
|
||||
3. The count for p18 or A4 was displayed.
|
||||
|
||||
Now you will see messages for all the pins that you manipulate, for example:
|
||||
*C*f0p11-P2
|
||||
+R+f0p3-P4
|
||||
*C*f0p11-P2
|
||||
+R+f0p3-P4
|
||||
*C*f0p11-P2
|
||||
.Count for pin D3 is 6
|
||||
Count for pin D11 is 9
|
||||
.+R+f0p3-P4
|
||||
-F-f0p2-P4
|
||||
.Count for pin D2 is 1
|
||||
Count for pin D3 is 1
|
||||
These codes reflect the interrupts, as described above. This output will take place until you press tPIN6:
|
||||
-F-f2: STOP! Counting off.
|
||||
Interrupt OFF on tPIN1 (2) tPIN3 (11) tPIN5 (17)
|
||||
Then you will see output like this:
|
||||
.....................+R+f0p12-P2 (counting off)
|
||||
.+R+f0p12-P2 (counting off)
|
||||
+R+f0p12-P2 (counting off)
|
||||
+R+f0p12-P2 (counting off)
|
||||
and tPIN1, tPIN3, and tPIN5 will not trigger interrupts.
|
||||
*/
|
||||
// NOTES
|
||||
// Output overwrites:
|
||||
// It's possible during moderately fast interrupts to see your print output get garbled; eg,
|
||||
// +R+f0p12-P2 (+R+f0p12-P2 (counting +R+f0p12-P2 (cou+R+f0p12-P+R+f0p12
|
||||
// This is because the print of the buffer takes place inside a while loop, and it can
|
||||
// be interrupted and new data inserted into the buffer at a midpoint of the buffer's text.
|
||||
// Just by spinning my rotary encoders I can readily generate over 200 interrupts per second
|
||||
// on a pin, which is easily fast enough to overrun Serial output at 115,200 bps.
|
||||
// The lesson here? ...Interrupts are tricky, and interrupt service routines should be fast.
|
||||
// Just sayin'.
|
||||
|
||||
// Pins:
|
||||
// We want to use pins from each of ports B, C and D. So choose wisely. Ports are shown in
|
||||
// this diagram of the ATmega328P chip. PD0 means "Port D, pin 0". PC3 means "Port C, Pin 3",
|
||||
// PB2 means "Port B, pin 2" and so on. The corresponding Arduino pins are in parentheses.
|
||||
// So PB2 is Arduino pin D 10, for example.
|
||||
/*
|
||||
+-\/-+
|
||||
PC6 1| |28 PC5 (AI 5)
|
||||
(D 0) PD0 2| |27 PC4 (AI 4)
|
||||
(D 1) PD1 3| |26 PC3 (AI 3)
|
||||
(D 2) PD2 4| |25 PC2 (AI 2)
|
||||
PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
|
||||
(D 4) PD4 6| |23 PC0 (AI 0)
|
||||
VCC 7| |22 GND
|
||||
GND 8| |21 AREF
|
||||
PB6 9| |20 AVCC
|
||||
PB7 10| |19 PB5 (D 13)
|
||||
PWM+ (D 5) PD5 11| |18 PB4 (D 12)
|
||||
PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
|
||||
(D 7) PD7 13| |16 PB2 (D 10) PWM
|
||||
(D 8) PB0 14| |15 PB1 (D 9) PWM
|
||||
+----+
|
||||
*/
|
||||
|
||||
uint8_t pins[6]={ tPIN1, tPIN2, tPIN3, tPIN4, tPIN5, tPIN6 };
|
||||
uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
uint8_t latest_interrupted_pin;
|
||||
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
|
||||
uint8_t port;
|
||||
uint8_t mode;
|
||||
|
||||
ByteBuffer printBuffer(80);
|
||||
char charArray[16];
|
||||
char numBuffer[4] = { 0, 0, 0, 0 };
|
||||
uint8_t printFull=0;
|
||||
|
||||
volatile boolean start=0;
|
||||
volatile boolean initial=true;
|
||||
long begintime=0;
|
||||
long now=0;
|
||||
|
||||
void uint8ToString(char *outString, uint8_t number) {
|
||||
uint8_t hundreds=0;
|
||||
uint8_t tens=0;
|
||||
uint8_t ones=0;
|
||||
|
||||
while (number >= 100 ) {
|
||||
hundreds++;
|
||||
number-=100;
|
||||
}
|
||||
while (number >= 10 ) {
|
||||
tens++;
|
||||
number-=10;
|
||||
}
|
||||
ones=number;
|
||||
ones+=48;
|
||||
if (hundreds > 0) { hundreds+=48; tens+=48; outString[0]=hundreds; outString[1]=tens; outString[2]=ones; outString[3]=0; }
|
||||
else if (tens > 0) { tens+=48; outString[0]=tens; outString[1]=ones; outString[2]=0; }
|
||||
else { outString[0]=ones; outString[1]=0; };
|
||||
}
|
||||
|
||||
void showMode() {
|
||||
switch (mode) {
|
||||
case FALLING:
|
||||
printBuffer.putString((char *) "-F-");
|
||||
break;
|
||||
case RISING:
|
||||
printBuffer.putString((char *) "+R+");
|
||||
break;
|
||||
case CHANGE:
|
||||
printBuffer.putString((char *) "*C*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void quicfunc0() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start==1) {
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
}
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString((char *) "f0p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer);
|
||||
if (start !=1) printBuffer.putString((char *) " (counting off)");
|
||||
printBuffer.putString((char *) NEWLINE);
|
||||
};
|
||||
|
||||
void quicfunc1() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start==1) {
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
}
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString((char *) "f1p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer);
|
||||
if (start !=1) printBuffer.putString((char *) " (counting off)");
|
||||
printBuffer.putString((char *) NEWLINE);
|
||||
};
|
||||
|
||||
void quicfunc2() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start == 1) {
|
||||
printBuffer.putString((char *) "f2: STOP! Counting off.\n");
|
||||
printBuffer.putString((char *) "Interrupt OFF on tPIN1 ("); uint8ToString(numBuffer, tPIN1), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) ") tPIN3 (");uint8ToString(numBuffer, tPIN3), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) ") tPIN5 (");uint8ToString(numBuffer, tPIN5), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) ")");
|
||||
printBuffer.putString((char *) NEWLINE);
|
||||
PCintPort::detachInterrupt(tPIN1); PCintPort::detachInterrupt(tPIN3); PCintPort::detachInterrupt(tPIN5);
|
||||
start=0;
|
||||
} else {
|
||||
start=1;
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
printBuffer.putString((char *) "START! f2p");
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer); printBuffer.putString((char *) NEWLINE);
|
||||
if (! initial) {
|
||||
PCintPort::attachInterrupt(tPIN1, &quicfunc0, FALLING);
|
||||
PCintPort::attachInterrupt(tPIN3, &quicfunc0, CHANGE);
|
||||
PCintPort::attachInterrupt(tPIN5, &quicfunc1, CHANGE);
|
||||
} else {
|
||||
initial=false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t i;
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(250);
|
||||
Serial.println("Test");
|
||||
for (i=0; i < 6; i++) {
|
||||
pinMode(pins[i], INPUT_PULLUP);
|
||||
ports[i]=digitalPinToPort(pins[i]);
|
||||
switch (pins[i]) {
|
||||
case tPIN1:
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING);
|
||||
break;
|
||||
case tPIN3:
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE);
|
||||
break;
|
||||
case tPIN2:
|
||||
case tPIN4:
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING);
|
||||
break;
|
||||
case tPIN5:
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE);
|
||||
break;
|
||||
case tPIN6:
|
||||
attachPinChangeInterrupt(pins[i], quicfunc2, FALLING); // attachPinChangeInterrupt is a #define
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Serial.println(printBuffer.getCapacity(), DEC);
|
||||
//Serial.println("*---------------------------------------*");
|
||||
Serial.print("*---*");
|
||||
delay(250);
|
||||
begintime=millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
now=millis();
|
||||
uint8_t count;
|
||||
char outChar;
|
||||
// uint8_t bufsize;
|
||||
//if (printBuffer.getSize() != 0) { Serial.print("SZ:"); Serial.println (printBuffer.getSize(), DEC); };
|
||||
//bufsize=printBuffer.getSize();
|
||||
//if (bufsize > 0) { Serial.print("S:"); Serial.println(bufsize); }
|
||||
while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar);
|
||||
if ((now - begintime) > 1000) {
|
||||
Serial.print(".");
|
||||
if (printBuffer.checkError()) {
|
||||
Serial.println("NOTICE: Some output lost due to filled buffer.");
|
||||
}
|
||||
for (i=0; i < 20; i++) {
|
||||
if (interrupt_count[i] != 0) {
|
||||
count=interrupt_count[i];
|
||||
interrupt_count[i]=0;
|
||||
Serial.print("Count for pin ");
|
||||
if (i < 14) {
|
||||
Serial.print("D");
|
||||
Serial.print(i, DEC);
|
||||
} else {
|
||||
Serial.print("A");
|
||||
Serial.print(i-14, DEC);
|
||||
}
|
||||
Serial.print(" is ");
|
||||
Serial.println(count, DEC);
|
||||
}
|
||||
}
|
||||
begintime=millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
//#define DISABLE_PCINT_MULTI_SERVICE
|
||||
#define PINMODE
|
||||
#define FLASH
|
||||
#include <GetPSTR.h>
|
||||
#include <ByteBuffer.h>
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// This example demonstrates a configuration of 6 interrupting pins and 3 interrupt functions.
|
||||
// A variety of interrupting pins have been chosen, so as to test all PORTs on the Arduino.
|
||||
// The pins are as follows:
|
||||
#define tPIN1 2 // port D
|
||||
#define tPIN2 3
|
||||
#define tPIN3 11 // Port B
|
||||
#define tPIN4 12
|
||||
#define tPIN5 A3 // Port C, also can be given as "17"
|
||||
#define tPIN6 A4 // starts and stops the count
|
||||
|
||||
uint8_t pins[6]={ tPIN1, tPIN2, tPIN3, tPIN4, tPIN5, tPIN6 };
|
||||
uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
uint8_t latest_interrupted_pin;
|
||||
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
|
||||
uint8_t port;
|
||||
uint8_t mode;
|
||||
|
||||
ByteBuffer printBuffer(200);
|
||||
char charArray[16];
|
||||
char numBuffer[5] = { 0, 0, 0, 0, 0 };
|
||||
uint8_t printFull=0;
|
||||
|
||||
volatile boolean start=0;
|
||||
volatile boolean initial=true;
|
||||
long begintime=0;
|
||||
long now=0;
|
||||
|
||||
void uint8ToHexString(char *outString, uint8_t theByte) {
|
||||
outString[0]='0'; outString[1]='x';
|
||||
uint8_t hinybble=theByte>>4;
|
||||
uint8_t lonybble=theByte & 0x0F;
|
||||
if (hinybble < 0x0a) outString[2]=hinybble+48;
|
||||
else outString[2]=hinybble+55;
|
||||
if (lonybble < 0x0a) outString[3]=lonybble+48;
|
||||
else outString[3]=lonybble+55;
|
||||
outString[4]=0;
|
||||
}
|
||||
|
||||
void uint8ToString(char *outString, uint8_t number) {
|
||||
uint8_t hundreds=0;
|
||||
uint8_t tens=0;
|
||||
uint8_t ones=0;
|
||||
|
||||
while (number >= 100 ) {
|
||||
hundreds++;
|
||||
number-=100;
|
||||
}
|
||||
while (number >= 10 ) {
|
||||
tens++;
|
||||
number-=10;
|
||||
}
|
||||
ones=number;
|
||||
ones+=48;
|
||||
if (hundreds > 0) { hundreds+=48; tens+=48; outString[0]=hundreds; outString[1]=tens; outString[2]=ones; outString[3]=0; }
|
||||
else if (tens > 0) { tens+=48; outString[0]=tens; outString[1]=ones; outString[2]=0; }
|
||||
else { outString[0]=ones; outString[1]=0; };
|
||||
}
|
||||
|
||||
void showMode() {
|
||||
switch (mode) {
|
||||
case FALLING:
|
||||
printBuffer.putString(getPSTR("-F-"));
|
||||
break;
|
||||
case RISING:
|
||||
printBuffer.putString(getPSTR("+R+"));
|
||||
break;
|
||||
case CHANGE:
|
||||
printBuffer.putString(getPSTR("*C*"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void quicfunc0() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start==1) {
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
}
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString((char *) "f0p"); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer);
|
||||
if (start !=1) printBuffer.putString(getPSTR(" no count"));
|
||||
printBuffer.putString((char *) "\n");
|
||||
};
|
||||
|
||||
void quicfunc1() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
if (start==1) {
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
}
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString(getPSTR("f1p")); printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer);
|
||||
if (start !=1) printBuffer.putString(getPSTR(" (counting off)"));
|
||||
printBuffer.putString((char *) "\n");
|
||||
};
|
||||
*/
|
||||
|
||||
void quicfunc2() {
|
||||
//*led_port|=led_mask;
|
||||
//*led_port&=not_led_mask; // 2 micros to here (ie, 2 micros used to push registers and call subroutine)
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
mode=PCintPort::pinmode;
|
||||
showMode();
|
||||
*led_port|=led_mask; // 73 micros to get here from above. Used in "Rigol Timing Example"
|
||||
*led_port&=not_led_mask;
|
||||
//uint8ToString(numBuffer, PCintPort::s_count); printBuffer.putString(numBuffer);
|
||||
*led_port|=led_mask; // 73 micros to get here from above. Second pulse in "Rigol Timing Example"
|
||||
*led_port&=not_led_mask;
|
||||
printBuffer.putString(getPSTR(" f2: P"));/*
|
||||
uint8ToHexString(numBuffer, *portInputRegister(3)); printBuffer.putString(numBuffer);// C port
|
||||
printBuffer.putString(getPSTR(" pin:")); uint8ToString(numBuffer, latest_interrupted_pin); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" c")); uint8ToHexString(numBuffer, PCintPort::curr); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" l")); uint8ToHexString(numBuffer, PCintPort::s_lastPinView); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" r")); uint8ToHexString(numBuffer, PCintPort::s_portRisingPins); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" f")); uint8ToHexString(numBuffer, PCintPort::s_portFallingPins); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" m")); uint8ToHexString(numBuffer, PCintPort::s_pmask); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" P")); printBuffer.put(PCintPort::s_PORT); printBuffer.putString("\r\n");
|
||||
printBuffer.putString(getPSTR("cp")); uint8ToHexString(numBuffer, PCintPort::s_changedPins); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" cXORlpv")); uint8ToHexString(numBuffer, PCintPort::s_currXORlastPinView); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" rp_nCurr")); uint8ToHexString(numBuffer, PCintPort::s_portRisingPins_nCurr); printBuffer.putString(numBuffer);
|
||||
printBuffer.putString(getPSTR(" fp_nNCurr")); uint8ToHexString(numBuffer, PCintPort::s_portFallingPins_nNCurr); printBuffer.putString(numBuffer);
|
||||
*/printBuffer.putString("\r\n");
|
||||
if (PCintPort::pcint_multi > 0) {
|
||||
printBuffer.putString("MULTI!\n"); PCintPort::pcint_multi=0;
|
||||
}
|
||||
if (PCintPort::PCIFRbug > 0) { printBuffer.putString("ERROR: BUG- PCIFR should be reset!"); PCintPort::PCIFRbug=0; }
|
||||
//s_registers, if it existed, could be used to keep a running queue of the latest interrupts that have
|
||||
//been serviced by the PCint(). But generally I don't think it's necessary for debugging at this point (famous last words?)
|
||||
/*if (PCintPort::s_count > 2) {
|
||||
for (uint8_t i=0; i < PCintPort::s_count; i++) {
|
||||
uint8ToHexString(numBuffer, PCintPort::s_registers[i]); printBuffer.putString(numBuffer); printBuffer.putString(" ");
|
||||
}
|
||||
}
|
||||
PCintPort::s_count=0;*/
|
||||
/*
|
||||
if (start == 1) {
|
||||
printBuffer.putString(getPSTR("STOP Count off\n"));
|
||||
printBuffer.putString(getPSTR("Intr OFF: (")); uint8ToString(numBuffer, tPIN1), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) " "); uint8ToString(numBuffer, tPIN3), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) " "); uint8ToString(numBuffer, tPIN5), printBuffer.putString(numBuffer);
|
||||
printBuffer.putString((char *) ")\n");
|
||||
PCintPort::detachInterrupt(tPIN1); PCintPort::detachInterrupt(tPIN3); PCintPort::detachInterrupt(tPIN5);
|
||||
start=0;
|
||||
} else {
|
||||
start=1;
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
printBuffer.putString(getPSTR("START! p"));
|
||||
uint8ToString(numBuffer, latest_interrupted_pin);
|
||||
printBuffer.putString(numBuffer); printBuffer.putString((char *) "-P");
|
||||
// MIKE put the REAL PORT HERE
|
||||
uint8ToString(numBuffer, digitalPinToPort(latest_interrupted_pin));
|
||||
printBuffer.putString(numBuffer); printBuffer.putString((char *) "\n");
|
||||
if (! initial) {
|
||||
PCintPort::attachInterrupt(tPIN1, &quicfunc0, FALLING);
|
||||
PCintPort::attachInterrupt(tPIN3, &quicfunc0, CHANGE);
|
||||
PCintPort::attachInterrupt(tPIN5, &quicfunc1, CHANGE);
|
||||
} else {
|
||||
initial=false;
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
uint8_t i;
|
||||
char hexBuffer[5];
|
||||
void setup() {
|
||||
int8_t returncode=1;
|
||||
Serial.begin(115200);
|
||||
Serial.println("Test");
|
||||
delay(500);
|
||||
for (i=5; i < 6; i++) {
|
||||
pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH);
|
||||
ports[i]=digitalPinToPort(pins[i]);
|
||||
switch (pins[i]) {
|
||||
/*case tPIN1:
|
||||
#if PCINT_VERSION > 2100
|
||||
returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING);
|
||||
#else
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING);
|
||||
#endif
|
||||
Serial.println(getPSTR("FIRST FAILURE OK."));
|
||||
break;
|
||||
case tPIN3:
|
||||
#if PCINT_VERSION > 2100
|
||||
returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE);
|
||||
#else
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, CHANGE);
|
||||
#endif
|
||||
break;
|
||||
case tPIN2:
|
||||
case tPIN4:
|
||||
#if PCINT_VERSION > 2100
|
||||
returncode=PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING);
|
||||
#else
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING);
|
||||
#endif
|
||||
break;
|
||||
case tPIN5:
|
||||
#if PCINT_VERSION > 2100
|
||||
returncode=PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE);
|
||||
#else
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE);
|
||||
#endif
|
||||
break;*/
|
||||
case tPIN6:
|
||||
#if PCINT_VERSION > 2100
|
||||
returncode=PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING);
|
||||
#else
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if PCINT_VERSION > 2100
|
||||
Serial.print(getPSTR("setup(): Interrupt attach "));
|
||||
if (returncode != 1) Serial.print(getPSTR("unsuccessful "));
|
||||
else Serial.print(getPSTR("GOOD "));
|
||||
Serial.print(pins[i], DEC);
|
||||
Serial.print(getPSTR(":pin, code: ")); Serial.println(returncode, DEC);
|
||||
#endif
|
||||
}
|
||||
//Serial.println(printBuffer.getCapacity(), DEC);
|
||||
//Serial.println("*---------------------------------------*");
|
||||
Serial.print("*---*");
|
||||
delay(250);
|
||||
begintime=millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
now=millis();
|
||||
uint8_t count;
|
||||
char outChar;
|
||||
// uint8_t bufsize;
|
||||
//if (printBuffer.getSize() != 0) { Serial.print("SZ:"); Serial.println (printBuffer.getSize(), DEC); };
|
||||
//bufsize=printBuffer.getSize();
|
||||
//if (bufsize > 0) { Serial.print("S:"); Serial.println(bufsize); }
|
||||
while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar);
|
||||
if ((now - begintime) > 1000) {
|
||||
Serial.print(".");
|
||||
if (printBuffer.checkError()) {
|
||||
Serial.println(getPSTR("!Some output lost due to full buffer!"));
|
||||
}
|
||||
for (i=0; i < 20; i++) {
|
||||
if (interrupt_count[i] != 0) {
|
||||
count=interrupt_count[i];
|
||||
interrupt_count[i]=0;
|
||||
Serial.print(getPSTR("Count for pin "));
|
||||
if (i < 14) {
|
||||
Serial.print("D");
|
||||
Serial.print(i, DEC);
|
||||
} else {
|
||||
Serial.print("A");
|
||||
Serial.print(i-14, DEC);
|
||||
}
|
||||
Serial.print(" is ");
|
||||
Serial.println(count, DEC);
|
||||
}
|
||||
}
|
||||
begintime=millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// PinChangeInt SimpleExample sketch
|
||||
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
|
||||
|
||||
// for vim editing: :set et ts=2 sts=2 sw=2 et
|
||||
|
||||
// This example demonstrates the use of the PinChangeInt library on a single pin of your choice.
|
||||
// This only works for ATMega328-compatibles; ie, Leonardo is not covered here.
|
||||
// To use:
|
||||
|
||||
// 1. You must be using a fairly recent version of the Arduino IDE software on your PC/Mac,
|
||||
// that is, version 1.0.1 or later. Check Help->About Arduino in the IDE.
|
||||
|
||||
// 2. Wire a simple switch to any Analog or Digital pin (known as ARDUINOPIN, defined below).
|
||||
// Attach the other end to a GND pin. A "single pole single throw momentary contact"
|
||||
// pushbutton switch is best for the best interrupting fun.
|
||||
|
||||
// 3. When pressed, the switch will connect the pin to ground ("low", or "0") voltage, and interrupt the
|
||||
// processor. Don't let it confuse you that a switch press means the pin's voltage goes to 0; it
|
||||
// may seem more intuitive to apply a "1" or high voltage to the pin to represent "pressed".
|
||||
// But the processor is perfectly happy that we've made "0" equal "Pressed". The reason we've done so
|
||||
// is because we are using the "internal pullup resistor" feature of the processor... the chip gives
|
||||
// us a free resistor on every pin!
|
||||
// See http://arduino.cc/en/Tutorial/DigitalPins for a complete explanation.
|
||||
|
||||
// 4. The interrupt is serviced immediately, and the ISR (Interrupt SubRoutine) sets the value of a global
|
||||
// variable. The sketch can then query the value at its leisure. This makes loop timing non-critical.
|
||||
// Open Tools->Serial Monitor in the IDE to see the results of your interrupts.
|
||||
|
||||
// 5. See PinChangeIntExample328.ino (in the PinChangeInt distribution) for a more elaborate example.
|
||||
|
||||
// 6. Create your own sketch using the PinChangeInt library!
|
||||
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// Modify this at your leisure.
|
||||
#define ARDUINOPIN A4
|
||||
|
||||
// Notice that values that get modified inside an interrupt, that I wish to access
|
||||
// outside the interrupt, are marked "volatile". It tells the compiler not to optimize
|
||||
// the variable.
|
||||
volatile uint16_t interruptCount=0; // The count will go back to 0 after hitting 65535.
|
||||
|
||||
// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,
|
||||
// and by default interrupts are off in interrupt subroutines. Interrupt routines should also
|
||||
// be as fast as possible. Here we just increment a counter.
|
||||
void interruptFunction() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
// Attach the interrupt in setup()
|
||||
void setup() {
|
||||
pinMode(ARDUINOPIN, INPUT_PULLUP); // Configure the pin as an input, and turn on the pullup resistor.
|
||||
// See http://arduino.cc/en/Tutorial/DigitalPins
|
||||
attachPinChangeInterrupt(ARDUINOPIN, interruptFunction, FALLING);
|
||||
Serial.begin(115200);
|
||||
Serial.println("---------------------------------------");
|
||||
}
|
||||
|
||||
// In the loop, we just check to see where the interrupt count is at. The value gets updated by the
|
||||
// interrupt routine.
|
||||
void loop() {
|
||||
delay(1000); // Every second,
|
||||
Serial.print("Pin was interrupted: ");
|
||||
Serial.print(interruptCount, DEC); // print the interrupt count.
|
||||
Serial.println(" times so far.");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue