counts digital frequency based on interrupt and timer, triggers on rising edge

FrequencyCounter.cpp

Committer:
awmiller
Date:
2016-08-09
Revision:
0:91a906dbf731

File content as of revision 0:91a906dbf731:

#include "FrequencyCounter.h"
#include <mbed.h>

#ifndef INF
#define INF ((double)(1.0/0.0))
#endif

/*
 * Class constructor initializes interrupt and starts rising edge triggering
 */
FrequencyCounter::FrequencyCounter(PinName pin) : _cPin(pin){  
    this->_cPin.rise(this,&FrequencyCounter::_irqs);
    this->_cPin.disable_irq(); //justin case
    this->_iircoef = 0.9f;
    this->_lastTime =0;
    this->_fq = 0;
}

/*
 *  Getter method for reading the averaged freqency
 */
double FrequencyCounter::getFrequency() {
    return this->_fq;
}

/*
 *  Getter method for reading the averaged freqency
 */
double FrequencyCounter::getTime() {
    return this->_lastTime;
}

/*
 * Setter for modifying the coefficient of the averaging IIR filter
 * the IIR Coefficient is the fraction of old data to keep, typically 0.9
 * Incoming data is multiplied by (1 - coeff) and added to (coeff * old_data)
 */    
void FrequencyCounter::setIIRCoeff(double D) {
    this->_iircoef = D;
}

/*
 * Starts the IRQ service
 */
void FrequencyCounter::start() {
    this->_lastTime = 0;
    this->_cPin.enable_irq();  
    this->_fq = 0.0f;
    this->_mtime.start();
}

/*
 * Stops the IRQ service
 */
void FrequencyCounter::stop() {
    this->_cPin.disable_irq(); //justin case
    this->_mtime.stop();
}

/*
 * IRQ service (private) implements a simple IIR LPF
 */
void FrequencyCounter::_irqs() {
    //written long-hand for clarity, should get optimized out
    double delta = (double)(this->_mtime.read_us());
    delta = delta/(10^6);
    double nfq = 1/delta;
    if(nfq == INF){
        nfq=0;
    }else if(nfq < 0.01){
        nfq = 0.01;
    }
    this->_fq = this->_fq*this->_iircoef + (1-this->_iircoef)*nfq; // basic LPF    
    this->_mtime.reset();
    this->_lastTime = delta;
}