Simplify gateway code (handles interrupts internally) and remove external dependencies. Ledmode is now always "enabled".
Remove unused libraries. Add default CS/CE pin to Config.h Add new variebles for voltage and current. Add new internal command sent to controller when gateway is ready and online
This commit is contained in:
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
ByteBuffer.cpp - 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.
|
||||
Also made the capacity, position, length, and fillError variables volatile, for safe use by interrupts.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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(char *in){
|
||||
uint8_t count=0;
|
||||
char *inString;
|
||||
|
||||
inString=in;
|
||||
uint8_t oldSREG = SREG; cli();
|
||||
while(length <= capacity){
|
||||
if (length == capacity) {
|
||||
fillError=true;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#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
|
||||
@@ -1,77 +0,0 @@
|
||||
// PinChangeIntExample, version 1.1 Sun Jan 15 06:24:19 CST 2012
|
||||
// See the Wiki at http://code.google.com/p/arduino-pinchangeint/wiki for more information.
|
||||
//-------- 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.
|
||||
//#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
|
||||
// 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 ------------------------------------------------------
|
||||
#include <PinChangeInt.h>
|
||||
|
||||
// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions.
|
||||
// All interrupts are serviced immediately, but one of the pins (pin 4) will show you immediately
|
||||
// on the Terminal. The other function connected to 2 pins sets an array member that is queried in loop().
|
||||
// You can then query the array at your leisure.
|
||||
// This makes loop timing non-critical.
|
||||
|
||||
// Add more Pins at your leisure.
|
||||
// For the Analog Input pins used as digital input pins, and you can use 14, 15, 16, etc.
|
||||
// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's
|
||||
// for the Analog Input pins and will properly recognize e.g., pinMode(A0, INPUT);
|
||||
#define PIN1 2
|
||||
#define PIN2 3
|
||||
#define PIN3 4
|
||||
|
||||
uint8_t latest_interrupted_pin;
|
||||
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
|
||||
void quicfunc() {
|
||||
latest_interrupted_pin=PCintPort::arduinoPin;
|
||||
interrupt_count[latest_interrupted_pin]++;
|
||||
};
|
||||
|
||||
// You can assign any number of functions to any number of pins.
|
||||
// How cool is that?
|
||||
void pin3func() {
|
||||
Serial.print("Pin "); Serial.print(PIN3, DEC); Serial.println("!");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(PIN1, INPUT); digitalWrite(PIN1, HIGH);
|
||||
PCintPort::attachInterrupt(PIN1, &quicfunc, FALLING); // add more attachInterrupt code as required
|
||||
pinMode(PIN2, INPUT); digitalWrite(PIN2, HIGH);
|
||||
PCintPort::attachInterrupt(PIN2, &quicfunc, FALLING);
|
||||
pinMode(PIN3, INPUT); digitalWrite(PIN3, HIGH);
|
||||
PCintPort::attachInterrupt(PIN3, &pin3func, CHANGE);
|
||||
Serial.begin(115200);
|
||||
Serial.println("---------------------------------------");
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
void loop() {
|
||||
uint8_t count;
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
// PinChangeIntTest
|
||||
// version 1.0 Wed Feb 15 07:25:09 CST 2012
|
||||
// Version 1.1 Fri Jun 22 19:10:50 CDT 2012 minor tweaks to eliminate compiler warnings. Also, there were bugfixes in ByteBuffer.
|
||||
// I had some "cli()" without "sei()" in there.
|
||||
// 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.
|
||||
//-------- 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>
|
||||
|
||||
// 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
|
||||
// All pins send interrupts. Arduino pins 2 and A4 (tPIN1,6) interrupt on FALLING.
|
||||
// Arduino pins 3 and 12 (tPIN2,4) interrupt on RISING.
|
||||
// Arduino pins 11 and A3 (tPIN5) interrupts on CHANGE.
|
||||
// quicfunc0 is attached to Arduino pins 2, 3, 11, and 12 (tPIN1-4)
|
||||
// quicfunc1 is attached to Arduino pin A3 (tPIN5)
|
||||
// quicfunc2 is attached to Arduino pin A4 (tPIN6).
|
||||
// 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));
|
||||
|
||||
// HOW IT WORKS
|
||||
// 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 *) "\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((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 *) "\n");
|
||||
};
|
||||
|
||||
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 *) ")\n");
|
||||
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 *) "\n");
|
||||
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");
|
||||
delay(500);
|
||||
for (i=0; i < 7; i++) {
|
||||
pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH);
|
||||
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:
|
||||
PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
//#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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user