-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
2,839 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/******************************************************************************/ | ||
/* */ | ||
/* FrequencyCounter -- Frequency Counter Module */ | ||
/* */ | ||
/* Copyright (c) 2021 Rick Groome */ | ||
/* */ | ||
/* Permission is hereby granted, free of charge, to any person obtaining a */ | ||
/* copy of this software and associated documentation files (the "Software"), */ | ||
/* to deal in the Software without restriction, including without limitation */ | ||
/* the rights to use, copy, modify, merge, publish, distribute, sublicense, */ | ||
/* and/or sell copies of the Software, and to permit persons to whom the */ | ||
/* Software is furnished to do so, subject to the following conditions: */ | ||
/* */ | ||
/* The above copyright notice and this permission notice shall be included in */ | ||
/* all copies or substantial portions of the Software. */ | ||
/* */ | ||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ | ||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ | ||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL */ | ||
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ | ||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | ||
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ | ||
/* DEALINGS IN THE SOFTWARE. */ | ||
/* */ | ||
/* PROCESSOR: ATmega32U4 COMPILER: Arduino/GNU C for AVR Vers 1.8.5 */ | ||
/* Written by: Rick Groome 2021 */ | ||
/* */ | ||
/******************************************************************************/ | ||
|
||
// See .cpp file for a description of this module and it's functions. | ||
|
||
#ifndef _FREQCTR_H | ||
#define _FREQCTR_H | ||
|
||
#define sbyte int8_t // also char | ||
|
||
class FrequencyCounter | ||
{ | ||
public: | ||
sbyte mode(sbyte Resolution); | ||
// Starts or stops the frequency counter function and sets the gate time. | ||
// "GateTime" is one of the following: | ||
// -1= Return current frequency counter gate time, 0= Freq counter off, | ||
// 1= 1 Sec gate time, 2= 10mS gate time, 3= 100mS gate time, | ||
// 4= 10 Sec gate time 5= 100 Sec gate time, 6= Ext Gate (low going). | ||
// 7= Period mode (1 period), 8= Period mode (average 10 periods) | ||
// 9= Period mode (average 100 periods) | ||
// GateTime values 6..9 are available only if compile option is enabled. | ||
// Function returns the current gate time or -1 if error. | ||
|
||
sbyte mode(void); | ||
// Returns the current gate mode/time. (0..9) | ||
|
||
byte available(void); | ||
// Returns true after each new update. False after reading the value. | ||
|
||
char *read(char *St, bool Wait); | ||
// Reads the value of the frequency counter and returns a string of the | ||
// value, corrected for gatetime or period averaging. | ||
// "St" is a string buffer in which this function will create a string that | ||
// is the frequency read. It should be big enough to hold the frequency | ||
// read. (15 characters?) | ||
// "Wait" is non-zero to wait for the next (a "fresh") frequency count, or | ||
// 0 to return the last frequency read. | ||
// The function returns a string of the frequency read or NULL. | ||
// This function returns a string instead of an integer or floating point | ||
// value so that floating point library functions are not required and | ||
// gate times that are over one second and period measurements return the | ||
// fractional part of the frequency read. | ||
// Be aware that if "Wait" is true then this function will not return until | ||
// the gate time has passed and a "fresh" frequency count is available. | ||
// This could be up to 100 seconds. | ||
// When in a period measure mode, the period measured is converted to a | ||
// frequency and that value is returned. In this period measure mode, if the | ||
// frequency is too high then '999999' is returned and if the frequency is | ||
// too low (or 0Hz) or the software times out then '0.00000' is returned. | ||
// The input signal must provide 2 (a complete wave), 11 or 101 transitions | ||
// within the timeout period or '0.00000' is returned. The timeout period | ||
// is configurable and defaults to 5 seconds. | ||
|
||
unsigned long read(bool Wait); | ||
// Read the frequency counter and return the value as an unsigned long. | ||
// Function returns the raw frequency read. IT IS NOT SCALED FOR GATE | ||
// OR NUMBER OF AVERAGES!! It is presumed a higher level function will | ||
// do this or use the string version of this function for a corrected value. | ||
// 'Wait' is non-zero to wait for the next (a "fresh") frequency count, or | ||
// 0 to return the last frequency read. | ||
}; | ||
|
||
|
||
/******************************************************************************/ | ||
/* Externally available support functions */ | ||
/******************************************************************************/ | ||
|
||
extern void FreqCtrGateISR(void); | ||
// This function implements the "gating" function of the frequency counter. | ||
// A "gate time" has finished. Move collected count to a holding register | ||
// and restart the counting for the new "gate time". | ||
// This function should be called every 10 milliseconds (preferably by an | ||
// accurate timer) when FCGateTime is not zero. | ||
// This is normally done in the ISR of one of the timers in the micro. | ||
|
||
|
||
/******************************************************************************/ | ||
/* User configurable options */ | ||
/* Changing these options controls which features the module contains */ | ||
/******************************************************************************/ | ||
|
||
// Does this module take over the SysTimerIntFunc function ? | ||
#define FCINCLUDESYSTIMERLINK 1 // define as non-zero to take over function | ||
|
||
// Allow Ext Gate mode? (adds 244 flash bytes ) | ||
#define FCEXTERN 1 // 1= ext gate mode enabled | ||
|
||
// Arduino pin number to use for external gate | ||
#define FCEXTGATEMSK PCINTMASK9 // PB5 isr index (Arduino Digital 9) | ||
|
||
// Allow period measure mode? (adds 1030 flash bytes) | ||
#define FCPERIOD 1 // 1= Period measure mode enabled | ||
|
||
// for period measure it must occur within this many mS | ||
#define PERIODTIMOUT 5000 | ||
|
||
// If there is a prescaler, put prescale value here | ||
#define FCPRESCALER 1 | ||
|
||
// Enable this for debug messages. | ||
//#define FRQCTRDEBUG 1 // For debug... show debug messages. | ||
|
||
|
||
#endif // _FREQCTR_H | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/******************************************************************************/ | ||
/* */ | ||
/* PCInterrupt -- Pin change/external interrupt functions */ | ||
/* */ | ||
/* Copyright (c) 2021 Rick Groome */ | ||
/* */ | ||
/* Permission is hereby granted, free of charge, to any person obtaining a */ | ||
/* copy of this software and associated documentation files (the "Software"), */ | ||
/* to deal in the Software without restriction, including without limitation */ | ||
/* the rights to use, copy, modify, merge, publish, distribute, sublicense, */ | ||
/* and/or sell copies of the Software, and to permit persons to whom the */ | ||
/* Software is furnished to do so, subject to the following conditions: */ | ||
/* */ | ||
/* The above copyright notice and this permission notice shall be included in */ | ||
/* all copies or substantial portions of the Software. */ | ||
/* */ | ||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ | ||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ | ||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL */ | ||
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ | ||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | ||
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ | ||
/* DEALINGS IN THE SOFTWARE. */ | ||
/* */ | ||
/* PROCESSOR: ATmega32U4 COMPILER: Arduino/GNU C for AVR Vers 1.8.5 */ | ||
/* Written by: Rick Groome 2021 */ | ||
/* */ | ||
/******************************************************************************/ | ||
|
||
/* | ||
This module/class implements a pin change or external interrupt handler and | ||
the setup for same. It determines which pins have changed state and then | ||
sets bits in a variable that can either be checked via polled logic in some | ||
mainline program or via a user written function that is called during the | ||
actual pin change interrupt routine. The pins include port B, bits 0 to 6, | ||
and external interrupt 6. | ||
When using in the polled mode, three functions 'rising','falling' and | ||
'change', can be used in mainline code to determine if the pin just | ||
changed state to a 1 (rising), a 0 (falling), or any change (change). | ||
If the user defines a function named 'PCChangeIntFunc', then that function | ||
will be called when a pin change interrupt occurs. When using this user | ||
function that is called during the interrupt, a variable is passed to the | ||
function that can be examined to indicate which bits have changed state, | ||
or the function can also use the rising/falling/change methods as mentioned | ||
previously to determine which bits have changed. | ||
In either case, when the user code has acted on the changed pins it should | ||
then call the member function 'clear' to clear the bits in the modules | ||
"changed bits" variable so it will be ready for the next time. | ||
Pin change interupts are enabled/disabled via the enable and disable methods. | ||
In all cases where a 'mask' variable is used, the user should use the | ||
'PCINTMASKxx' constants found in the header file. You can enable/disable | ||
multiple pin change bits by OR'ing the mask constants to the enable/disable | ||
functions as in "PCH.enable(PCINTMASK7|PCINTMASK8|PCINTMASK9)". This same | ||
OR'ing technique can be used in the other functions also to check for or | ||
clear multiple pins. | ||
The class 'PCH' is instantised in this module. To use the member functions, | ||
use PCH as the variable as in PCH.rising(PCINTMASK8). Do not instantise | ||
another variable of this class as this is a hardware based class. | ||
*/ | ||
|
||
/* | ||
Revision log: | ||
1.0.0 3-2-21 REG | ||
Reworked from another file | ||
Reworked to use ISR_ALIASOF and weak function instead of a function vector. | ||
1.0.1 6-20-21 REG | ||
Reworked to use a class interface and added disable and change functions | ||
*/ | ||
|
||
#include <arduino.h> | ||
#include "pcinterrupt.h" | ||
|
||
// This is the last state of the PC change pins | ||
volatile byte LastPINB = 0; | ||
// This is the pins that went low(falling) [0] and pins that went high(rising) [1] | ||
volatile byte Changes[2]= {0,0}; | ||
|
||
// This is the one (and only) instance of this class | ||
// if you don't define it here, you can call it whatever name you like | ||
// PCInterrupt PCH; | ||
|
||
// The following implements a hook into the ISR for the pin change interrupt. | ||
// If you define | ||
// extern "C" void PCChangeIntFunc(byte Changes[]) { <some code> } | ||
// then that function will be called on each pin change interrupt. If you | ||
// don't define it, then no code will be generated for it in the ISR. | ||
extern "C" void __PCChangeISREmpty(byte Changes[] __attribute__((unused))) { } | ||
extern "C" void PCChangeIntFunc(byte Changes[]) __attribute__ ((weak, alias("__PCChangeISREmpty"))); | ||
|
||
ISR(PCINT0_vect) | ||
{ | ||
// This routine called when the interrupt on change occurs on | ||
// any of PB0..7. The routine checks for each bit that changed, | ||
// and if it's now zero (falling) then call the routine specified. | ||
byte i, NewPINB; | ||
|
||
NewPINB = (PINB&0x7f)|((PINE&0x40)<<1); // Read the IO ports | ||
// i= changes to the bits that are enabled | ||
i = ((LastPINB ^ NewPINB) & ((PCMSK0 &0x7f)|((EIMSK<<1)&0x80))); | ||
Changes[0] |= i & ~NewPINB; // pins that just went low | ||
Changes[1] |= i & NewPINB; // pins that just went high | ||
PCChangeIntFunc((byte *)Changes); | ||
LastPINB=NewPINB; // Save current state for next time. | ||
} | ||
|
||
// Both the pin change and the external interrupt use the same ISR routine, | ||
// so just point them both to the same routine. Saves lots of code bytes!! | ||
ISR(INT6_vect, ISR_ALIASOF(PCINT0_vect)); | ||
// This routine called when the external interrupt 6 occurs | ||
|
||
// These three functions return true if the pin change event occured. | ||
boolean PCInterrupt::falling(byte mask) { return(Changes[0] & mask); } | ||
boolean PCInterrupt::rising(byte mask) { return(Changes[1] & mask); } | ||
boolean PCInterrupt::change(byte mask) { return((Changes[0]|Changes[1]) & mask); } | ||
|
||
void PCInterrupt::clear(byte mask) | ||
// Clear the bits specified by 'mask' in the Changes array. | ||
{ | ||
noInterrupts(); | ||
mask=~mask; Changes[0]&=mask; Changes[1]&=mask; | ||
interrupts(); | ||
} | ||
|
||
void PCInterrupt::enable(byte mask) | ||
// Enable the interrupt on pin change interrupt for the pins specified in 'mask'. | ||
// (Set selected pin change pins to input mode with pull up) | ||
{ | ||
if (mask) // Enable interrupts specified in mask | ||
{ | ||
byte x; | ||
// set Port B pins to input mode w/ pullup | ||
x=mask&0x7F; DDRB&=~x; PORTB|=x; | ||
if (mask & 0x80) | ||
{ | ||
// set ExtInt.6 to input mode w/ pullup | ||
DDRE&=~0x40; PORTE|=0x40; | ||
EICRB |= 0x10; // sets the interrupt type (any change) | ||
EIMSK |= 0x40; // activates the interrupt | ||
} | ||
// initialize LastPINB variable | ||
LastPINB=(PINB&0x7f)|((PINE&0x40)<<1); | ||
// setup the Pin change hardware | ||
if (x) { PCMSK0|=x; PCICR=1; } | ||
interrupts(); | ||
} | ||
} | ||
|
||
void PCInterrupt::disable(byte mask) | ||
// Disable the interrupt on pin change interrupt for the pins specified in 'mask'. | ||
// (Do not alter the direction of the pin change IO pins [leave as input w/PUP]) | ||
{ | ||
if (mask) // Disable interrupts specified in mask | ||
{ | ||
if (mask&0x7F) { PCMSK0&=(mask&0x7f); if (!PCMSK0) PCICR=0; } | ||
if (mask&0x80) EIMSK &= ~((mask & 0x80)>>1); | ||
Changes[0]&=~mask; Changes[1]&=~mask; | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/******************************************************************************/ | ||
/* */ | ||
/* E M B E D D E D C O N T R O L L E R */ | ||
/* */ | ||
/* PC Interrupt (pin change interrupts) */ | ||
/* */ | ||
/* C I R C U I T C H E C K, I N C . */ | ||
/* */ | ||
/* Copyright (c) 2014 Circuit Check, Inc. All rights reserved. */ | ||
/* */ | ||
/* CONFIDENTIAL AND PROPRIETARY */ | ||
/* */ | ||
/* THIS WORK CONTAINS VALUABLE, CONFIDENTIAL AND PROPRIETARY INFORMATION */ | ||
/* OF THE AUTHOR. DISCLOSURE, USE OR PRODUCTION WITHOUT THE WRITTEN */ | ||
/* AUTHORIZATION OF THE AUTHOR IS STRICTLY PROHIBITED. THIS WORK BY */ | ||
/* THE AUTHOR IS PROTECTED BY THE LAWS OF THE UNITED STATES AND OTHER */ | ||
/* COUNTRIES. */ | ||
/* */ | ||
/* PROCESSOR: Atmel ATmega32U4 COMPILER: Arduino / GNU C for AVR */ | ||
/* */ | ||
/* Written by: Rick Groome 2014 */ | ||
/* */ | ||
/* */ | ||
/******************************************************************************/ | ||
|
||
#ifndef _PCINTERRUPT_H | ||
#define _PCINTERRUPT_H | ||
|
||
#include <arduino.h> | ||
|
||
// Pin numbers for each bit position (e.g. arduino pin number) | ||
// Use these constants for 'mask' values below in the class. | ||
#define PCINTMASK8 0x10 /* Digital 8 [PB4] */ | ||
#define PCINTMASK9 0x20 /* Digital 9 [PB5] */ | ||
#define PCINTMASK10 0x40 /* Digital 10 [PB6] */ | ||
#define PCINTMASK14 0x01 /* Digital 14 [PB0] */ | ||
#define PCINTMASK15 0x02 /* Digital 15 [PB1] */ | ||
#define PCINTMASK16 0x04 /* Digital 16 [PB2] */ | ||
#define PCINTMASK17 0x08 /* Digital 17 [PB3] */ | ||
#define PCINTMASK7 0x80 /* Digital 7 [PE6] (use this instead of PB7) */ | ||
|
||
// Use rising/falling/change to determine if a Pin Change interrupt occured. | ||
// e.g if (PCH.rising(PCINTMASK10)) { dosomething } | ||
// Then don't forget to call PCH.clear(PCINTMASK10); | ||
|
||
class PCInterrupt | ||
{ | ||
public: | ||
boolean falling(byte mask); // Return true if falling interrupt detected on mask bit | ||
boolean rising(byte mask); // Return true if rising interrupt detected on mask bit | ||
boolean change(byte mask); // Return true if any change detected on mask bit | ||
void clear(byte mask); // Clear the interrupt bits in mask | ||
void enable(byte mask); // Enable interrupts on pins in mask | ||
void disable(byte mask); // Disable interrupts on pins in mask | ||
}; | ||
|
||
extern PCInterrupt PCH; // This is the one (and only) instance of this class | ||
// You can rename this to whatever you like, if desired. | ||
|
||
// If you define this function, then it will be called as part of | ||
// the pin change interrupt service routine | ||
extern "C" { void PCChangeIntFunc(byte Changes[]); } | ||
|
||
#endif //_PCINTERRUPT_H | ||
|
||
|
Oops, something went wrong.