Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Rick-G1 committed Jun 23, 2021
1 parent 980d898 commit d139ec2
Show file tree
Hide file tree
Showing 8 changed files with 2,839 additions and 0 deletions.
516 changes: 516 additions & 0 deletions examples/FreqCtrApp/FreqCtrApp.ino

Large diffs are not rendered by default.

516 changes: 516 additions & 0 deletions examples/FreqGenCtrApp/FreqGenCtrApp.ino

Large diffs are not rendered by default.

700 changes: 700 additions & 0 deletions src/FrequencyCounter.cpp

Large diffs are not rendered by default.

132 changes: 132 additions & 0 deletions src/FrequencyCounter.h
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

169 changes: 169 additions & 0 deletions src/PCInterrupt.cpp
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;
}
}


66 changes: 66 additions & 0 deletions src/PCInterrupt.h
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


0 comments on commit d139ec2

Please sign in to comment.