Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated for the latest Adafruit_ZeroTimer library (version 2.0). #2

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
38 changes: 23 additions & 15 deletions avdweb_SAMDtimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -35,36 +47,37 @@ 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)
{ calc(period_us, 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)
{ enable(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);
}
Expand All @@ -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;
}





}
6 changes: 3 additions & 3 deletions avdweb_SAMDtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions examples/SAMDtimer_examples/SAMDtimer_examples.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -53,4 +53,4 @@ void setup() // test out the several functions:
void loop()
{
}