diff --git a/README.md b/README.md index e649638..e739947 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,70 @@ # Avdweb_SAMDtimer -SAMD21 Timer library for the SAM15x15 and Arduino Zero -http://www.avdweb.nl/arduino/libraries/samd21-timer.html -Attention: The new libraries Adafruit_ASFcore and Adafruit_ZeroTimer don't work anymore with the avdweb_SAMDtimer library. -Therefore, install the older libraries, see the zip files. +SAMD21 Timer library for the SAM15x15 and Arduino Zero compatible boards. + +This library needs the [Adafruit_ZeroTimer](https://github.com/adafruit/Adafruit_ZeroTimer/) library to run. + +For more information visit http://www.avdweb.nl/arduino/libraries/samd21-timer.html + +## Basic usage + +### 1. Using a timer with an output pin + +The library is easy to use; the following code generates a square wave of 1Hz to pin 5 of the Arduino Zero: + + SAMDtimer mytimer1 = SAMDtimer(3, TC_COUNTER_SIZE_16BIT, 5, 1e6,true); + +**Explanation:** + +- `Mytimer1`: this is the object name of you choice. +- `3`: the pin-table shows that timer3 should be used for output pin 5. +- `TC_COUNTER_SIZE_16BIT`: don't change. This parameter exists just to make the library expandable. +- `5`: output pin 5 +- `1e6`: we need to specify the period time in microseconds. +- `true`: optional parameter, specifie if the timer should be enabled (started) or not. + +Alert readers might notice that the first two parameters are not strictly necessary because these could be derived from the used pin and period time. However, this would make the timer library less expandable and there will be occur more mistakes with the pin assignments, if more timers are used. + +**Notes** + +- The maximum period time is 1398080us (0.7Hz). +- The minimum period time is = 2us (500kHz). +- For now, the library has three timers available (number 3, 4, 5), only in 16-bit mode. +- There is no check on the proper parameters values. +- Without specifying the pulse width, it is the half of the period time (duty cycle 50%). + +### 2. Timer interrupts + +A timer can also be used for calling interrupts, without using a timer output pin. To periodically execute an ISR, simply use this code: + + SAMDtimer mytimer2 = SAMDtimer(4, myISR, 5e5, true); + +**Explanation:** + +- `Mytimer2`: this is the object name of you choice. +- `4`: take any free timer +- `myISR`: the name of the ISR of you choice. +- `5e5`: the period time in microseconds. +- `true`: optional parameter, specifie if the timer should be enabled (started) or not. + +The ISR should look as follows: + + void myISR () + { + //your code here + } + +### 3. Attaching interrupts to a timer with an output pin + +A timer can be used for both calling an interrupt and steering its output pin at the same time. This has to be carried out in two steps: first create a timer with an output pin, and than attach an ISR to it. + + Mytimer3.attachInterrupt(myISR); + +**Explanation:** + +- `Mytimer3`: an existing timer with an output pin, see paragraph 1. +- `myISR`: the name of the ISR, see paragraph 2. + +**Notes** + +- If the timer is disabled, then the ISR is disabled also. diff --git a/avdweb_SAMDtimer.cpp b/avdweb_SAMDtimer.cpp index 34c8928..47ee035 100644 --- a/avdweb_SAMDtimer.cpp +++ b/avdweb_SAMDtimer.cpp @@ -26,7 +26,19 @@ SAMDtimer 4 16bit D16/A2 D21/SCL d[3] d[25] SAMDtimer 5 16bit D24/SCK*1 d[13] */ -#include "avdweb_SAMDtimer.h" +#include "avdweb_SAMDtimer.h" + +void TC3_Handler(){ + Adafruit_ZeroTimer::timerHandler(3); +} + +void TC4_Handler(){ + Adafruit_ZeroTimer::timerHandler(4); +} + +void TC5_Handler(){ + Adafruit_ZeroTimer::timerHandler(5); +} SAMDtimer::SAMDtimer(byte timerNr, tc_counter_size countersize, byte pin, unsigned period_us, int pulseWidth_us, bool timerEnable): Adafruit_ZeroTimer(timerNr), pin(pin), countersize(countersize), period_us(period_us) @@ -35,13 +47,14 @@ Adafruit_ZeroTimer(timerNr), pin(pin), countersize(countersize), period_us(perio init(timerEnable); } -SAMDtimer::SAMDtimer(byte timerNr, tc_callback_t _ISR, unsigned period_us, bool ISRenable): +SAMDtimer::SAMDtimer(byte timerNr, void (*_ISR)(), unsigned period_us, bool ISRenable): Adafruit_ZeroTimer(timerNr) -{ ISR = _ISR; +{ ISR = _ISR; + pin=-1; countersize = TC_COUNTER_SIZE_16BIT; calc(period_us, period_us/2); - init(1); - setCallback(ISRenable, TC_CALLBACK_CC_CHANNEL1, ISR); + init(1); + setCallback(ISRenable, TC_CALLBACK_CC_CHANNEL0, ISR); } void SAMDtimer::setPulseWidth(unsigned pulseWidth_us) @@ -49,9 +62,9 @@ void SAMDtimer::setPulseWidth(unsigned pulseWidth_us) setPeriodMatch(periodCounter, PWcounter, 1); } -void SAMDtimer::attachInterrupt(tc_callback_t _ISR, bool interruptEnable) +void SAMDtimer::attachInterrupt(void (*_ISR)(), bool interruptEnable) { ISR = _ISR; - setCallback(interruptEnable, TC_CALLBACK_CC_CHANNEL1, ISR); + setCallback(interruptEnable, TC_CALLBACK_CC_CHANNEL0, ISR); } void SAMDtimer::enableTimer(bool timerEnable) @@ -59,12 +72,12 @@ void SAMDtimer::enableTimer(bool timerEnable) } void SAMDtimer::enableInterrupt(bool interruptEnable) -{ setCallback(interruptEnable, TC_CALLBACK_CC_CHANNEL1, ISR); +{ setCallback(interruptEnable, TC_CALLBACK_CC_CHANNEL0, ISR); } void SAMDtimer::init(bool enabled) { configure(prescale, countersize, TC_WAVE_GENERATION_MATCH_PWM); - PWMout(true, 1, pin); // must be ch1 for 16bit + if(pin>0)PWMout(true, 1, pin); // must be ch1 for 16bit setPeriodMatch(periodCounter, PWcounter, 1); enable(enabled); } @@ -80,9 +93,4 @@ void SAMDtimer::calc(unsigned period_us, unsigned pulseWidth_us) else if((PWcounter >>= 2, periodCounter >>= 2) < 65536) prescale = TC_CLOCK_PRESCALER_DIV64; else if((PWcounter >>= 2, periodCounter >>= 2) < 65536) prescale = TC_CLOCK_PRESCALER_DIV256; else if((PWcounter >>= 2, periodCounter >>= 2) < 65536) prescale = TC_CLOCK_PRESCALER_DIV1024; -} - - - - - +} \ No newline at end of file diff --git a/avdweb_SAMDtimer.h b/avdweb_SAMDtimer.h index 05fc06c..cd5a244 100644 --- a/avdweb_SAMDtimer.h +++ b/avdweb_SAMDtimer.h @@ -14,9 +14,9 @@ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Publ class SAMDtimer : public Adafruit_ZeroTimer { public: SAMDtimer(byte timerNr, tc_counter_size countersize, byte pin, unsigned period_us, int pulseWidth_us=-1, bool timerEnable=1); // For timer with output - SAMDtimer(byte timerNr, tc_callback_t _ISR, unsigned period_us, bool ISRenable=1); // For timer interrupt, without output + SAMDtimer(byte timerNr, void (*_ISR)(), unsigned period_us, bool ISRenable=1); // For timer interrupt, without output - void attachInterrupt(tc_callback_t _ISR, bool interruptEnable=1); // attach ISR to a timer with output, or exchange the ISR + void attachInterrupt(void (*_ISR)(), bool interruptEnable=1); // attach ISR to a timer with output, or exchange the ISR void enableTimer(bool timerEnable); void enableInterrupt(bool interruptEnable); void setPulseWidth(unsigned pulseWidth_us); @@ -26,7 +26,7 @@ class SAMDtimer : public Adafruit_ZeroTimer void calc(unsigned period_us, unsigned pulseWidth_us); byte pin; - tc_callback_t ISR; + void (*ISR)(); unsigned period_us, periodCounter, PWcounter; tc_clock_prescaler prescale; tc_counter_size countersize; diff --git a/examples/SAMDtimer_examples/SAMDtimer_examples.ino b/examples/SAMDtimer_examples/SAMDtimer_examples.ino index 883b93e..e43fdb8 100644 --- a/examples/SAMDtimer_examples/SAMDtimer_examples.ino +++ b/examples/SAMDtimer_examples/SAMDtimer_examples.ino @@ -8,19 +8,19 @@ const byte LED2 = 0; const byte LED3 = 2; const byte LED4 = 5; // timer3 16bit has 2 pins: 5 12 -void ISR_timer3_LED1(struct tc_module *const module_inst) +void ISR_timer3_LED1() { static bool b; pinMode(LED1, OUTPUT); digitalWrite(LED1, b=!b); } -void ISR_timer4_LED2(struct tc_module *const module_inst) +void ISR_timer4_LED2() { static bool b; pinMode(LED2, OUTPUT); digitalWrite(LED2, b=!b); } -void ISR_timer4_LED3(struct tc_module *const module_inst) +void ISR_timer4_LED3() { static bool b; pinMode(LED3, OUTPUT); digitalWrite(LED3, b=!b); @@ -53,4 +53,4 @@ void setup() // test out the several functions: void loop() { } - +