From d288b8870dee950b6cf8b69a7fc59f2356b96e3e Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Sun, 13 Nov 2011 14:02:24 +1100 Subject: [PATCH] purple: added PeriodicProcess library this library provides a clean API for drivers to request periodic timer driven calls at whatever rate they need --- .../AP_PeriodicProcess/AP_PeriodicProcess.h | 9 ++++ .../AP_TimerAperiodicProcess.cpp | 39 +++++++++++++++++ .../AP_TimerAperiodicProcess.h | 19 ++++++++ .../AP_PeriodicProcess/AP_TimerProcess.cpp | 43 +++++++++++++++++++ .../AP_PeriodicProcess/AP_TimerProcess.h | 23 ++++++++++ .../AP_PeriodicProcess/PeriodicProcess.h | 11 +++++ 6 files changed, 144 insertions(+) create mode 100644 libraries/AP_PeriodicProcess/AP_PeriodicProcess.h create mode 100644 libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.cpp create mode 100644 libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.h create mode 100644 libraries/AP_PeriodicProcess/AP_TimerProcess.cpp create mode 100644 libraries/AP_PeriodicProcess/AP_TimerProcess.h create mode 100644 libraries/AP_PeriodicProcess/PeriodicProcess.h diff --git a/libraries/AP_PeriodicProcess/AP_PeriodicProcess.h b/libraries/AP_PeriodicProcess/AP_PeriodicProcess.h new file mode 100644 index 0000000000..c54b531dde --- /dev/null +++ b/libraries/AP_PeriodicProcess/AP_PeriodicProcess.h @@ -0,0 +1,9 @@ + +#ifndef __AP_PERIODIC_PROCESS_H__ +#define __AP_PERIODIC_PROCESS_H__ + +#include "PeriodicProcess.h" +#include "AP_TimerProcess.h" +#include "AP_TimerAperiodicProcess.h" + +#endif // __AP_PERIODIC_PROCESS_H__ diff --git a/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.cpp b/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.cpp new file mode 100644 index 0000000000..0918b4e727 --- /dev/null +++ b/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.cpp @@ -0,0 +1,39 @@ + +#include "AP_TimerAperiodicProcess.h" + +extern "C" { +#include +#include +#include "WConstants.h" +} +// TCNT2 values for various interrupt rates, +// assuming 256 prescaler. Note that these values +// assume a zero-time ISR. The actual rate will be a +// bit lower than this +#define TCNT2_781_HZ (256-80) +#define TCNT2_1008_HZ (256-62) +#define TCNT2_1302_HZ (256-48) + +uint8_t AP_TimerAperiodicProcess::_timer_offset; + +void AP_TimerAperiodicProcess::init( Arduino_Mega_ISR_Registry * isr_reg ) +{ + // Enable Timer2 Overflow interrupt to trigger process. + TIMSK2 = 0; // Disable interrupts + TCCR2A = 0; // normal counting mode + TCCR2B = _BV(CS21) | _BV(CS22); // Set prescaler of clk/256 + TCNT2 = 0; // Set count to zero, so it goes off right away. + TIFR2 = _BV(TOV2); // clear pending interrupts; + TIMSK2 = _BV(TOIE2); // enable the overflow interrupt + + isr_reg->register_signal(ISR_REGISTRY_TIMER2_OVF, AP_TimerAperiodicProcess::run); +} + +void AP_TimerAperiodicProcess::run(void) +{ + _timer_offset = (_timer_offset + 49) % 32; + _period = TCNT2_781_HZ + _timer_offset; + TCNT2 = _period; + if (_proc != NULL) + _proc(); +} diff --git a/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.h b/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.h new file mode 100644 index 0000000000..1242104fd1 --- /dev/null +++ b/libraries/AP_PeriodicProcess/AP_TimerAperiodicProcess.h @@ -0,0 +1,19 @@ + +#ifndef __AP_TIMER_APERIODIC_PROCESS_H__ +#define __AP_TIMER_APERIODIC_PROCESS_H__ + +#include + +#include "../Arduino_Mega_ISR_Registry/Arduino_Mega_ISR_Registry.h" +#include "AP_TimerProcess.h" + +class AP_TimerAperiodicProcess : public AP_TimerProcess +{ + public: + void init( Arduino_Mega_ISR_Registry * isr_reg ); + static void run(void); + private: + static uint8_t _timer_offset; +}; + +#endif // __AP_TIMER_APERIODIC_PROCESS_H__ diff --git a/libraries/AP_PeriodicProcess/AP_TimerProcess.cpp b/libraries/AP_PeriodicProcess/AP_TimerProcess.cpp new file mode 100644 index 0000000000..cc120d2926 --- /dev/null +++ b/libraries/AP_PeriodicProcess/AP_TimerProcess.cpp @@ -0,0 +1,43 @@ + +#include "AP_TimerProcess.h" + +extern "C" { +#include +#include +#include "WConstants.h" +} + +int AP_TimerProcess::_period; +void (*AP_TimerProcess::_proc)(void); + +AP_TimerProcess::AP_TimerProcess(int period) +{ + _period = period; + _proc = NULL; +} + +void AP_TimerProcess::init( Arduino_Mega_ISR_Registry * isr_reg ) +{ + // Enable Timer2 Overflow interrupt to trigger process. + TIMSK2 = 0; // Disable interrupts + TCCR2A = 0; // normal counting mode + TCCR2B = _BV(CS21) | _BV(CS22); // Set prescaler of clk/256 + TCNT2 = 0; // Set count to zero, so it goes off right away. + TIFR2 = _BV(TOV2); // clear pending interrupts; + TIMSK2 = _BV(TOIE2); // enable the overflow interrupt + + isr_reg->register_signal( ISR_REGISTRY_TIMER2_OVF, AP_TimerProcess::run); +} + +void AP_TimerProcess::register_process(void (*proc)(void) ) +{ + _proc = proc; + TCNT2 = 1; // Should go off almost immediately. +} + +void AP_TimerProcess::run(void) +{ + TCNT2 = _period; + if (_proc != NULL) + _proc(); +} diff --git a/libraries/AP_PeriodicProcess/AP_TimerProcess.h b/libraries/AP_PeriodicProcess/AP_TimerProcess.h new file mode 100644 index 0000000000..6dd13da0da --- /dev/null +++ b/libraries/AP_PeriodicProcess/AP_TimerProcess.h @@ -0,0 +1,23 @@ + +#ifndef __AP_TIMERPROCESS_H__ +#define __AP_TIMERPROCESS_H__ + +#include "PeriodicProcess.h" +#include "../Arduino_Mega_ISR_Registry/Arduino_Mega_ISR_Registry.h" + +/* XXX this value is a total guess, will look up. */ +#define TIMERPROCESS_PER_DEFAULT (256) + +class AP_TimerProcess : public AP_PeriodicProcess +{ + public: + AP_TimerProcess(int period = TIMERPROCESS_PER_DEFAULT); + void init( Arduino_Mega_ISR_Registry * isr_reg ); + void register_process(void (* proc)(void)); + static void run(void); + protected: + static int _period; + static void (*_proc)(void); +}; + +#endif // __AP_TIMERPROCESS_H__ diff --git a/libraries/AP_PeriodicProcess/PeriodicProcess.h b/libraries/AP_PeriodicProcess/PeriodicProcess.h new file mode 100644 index 0000000000..6213698521 --- /dev/null +++ b/libraries/AP_PeriodicProcess/PeriodicProcess.h @@ -0,0 +1,11 @@ + +#ifndef __PERIODICPROCESS_H__ +#define __PERIODICPROCESS_H__ + +class AP_PeriodicProcess +{ + public: + virtual void register_process(void (* proc)(void)) = 0; +}; + +#endif // __PERIODICPROCESS_H__