Initial commit
This is just the 2018 code configured for PlatformIO
This commit is contained in:
308
lib/DueTimer/DueTimer.cpp
Normal file
308
lib/DueTimer/DueTimer.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
DueTimer.cpp - Implementation of Timers defined on DueTimer.h
|
||||
For instructions, go to https://github.com/ivanseidel/DueTimer
|
||||
|
||||
Created by Ivan Seidel Gomes, March, 2013.
|
||||
Modified by Philipp Klaus, June 2013.
|
||||
Thanks to stimmer (from Arduino forum), for coding the "timer soul" (Register stuff)
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(_SAM3XA_)
|
||||
#include "DueTimer.h"
|
||||
|
||||
const DueTimer::Timer DueTimer::Timers[NUM_TIMERS] = {
|
||||
{TC0,0,TC0_IRQn},
|
||||
{TC0,1,TC1_IRQn},
|
||||
{TC0,2,TC2_IRQn},
|
||||
{TC1,0,TC3_IRQn},
|
||||
{TC1,1,TC4_IRQn},
|
||||
{TC1,2,TC5_IRQn},
|
||||
{TC2,0,TC6_IRQn},
|
||||
{TC2,1,TC7_IRQn},
|
||||
{TC2,2,TC8_IRQn},
|
||||
};
|
||||
|
||||
// Fix for compatibility with Servo library
|
||||
#ifdef USING_SERVO_LIB
|
||||
// Set callbacks as used, allowing DueTimer::getAvailable() to work
|
||||
void (*DueTimer::callbacks[NUM_TIMERS])() = {
|
||||
(void (*)()) 1, // Timer 0 - Occupied
|
||||
(void (*)()) 0, // Timer 1
|
||||
(void (*)()) 1, // Timer 2 - Occupied
|
||||
(void (*)()) 1, // Timer 3 - Occupied
|
||||
(void (*)()) 1, // Timer 4 - Occupied
|
||||
(void (*)()) 1, // Timer 5 - Occupied
|
||||
(void (*)()) 0, // Timer 6
|
||||
(void (*)()) 0, // Timer 7
|
||||
(void (*)()) 0 // Timer 8
|
||||
};
|
||||
#else
|
||||
void (*DueTimer::callbacks[NUM_TIMERS])() = {};
|
||||
#endif
|
||||
double DueTimer::_frequency[NUM_TIMERS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
|
||||
|
||||
/*
|
||||
Initializing all timers, so you can use them like this: Timer0.start();
|
||||
*/
|
||||
DueTimer Timer(0);
|
||||
|
||||
DueTimer Timer1(1);
|
||||
// Fix for compatibility with Servo library
|
||||
#ifndef USING_SERVO_LIB
|
||||
DueTimer Timer0(0);
|
||||
DueTimer Timer2(2);
|
||||
DueTimer Timer3(3);
|
||||
DueTimer Timer4(4);
|
||||
DueTimer Timer5(5);
|
||||
#endif
|
||||
DueTimer Timer6(6);
|
||||
DueTimer Timer7(7);
|
||||
DueTimer Timer8(8);
|
||||
|
||||
DueTimer::DueTimer(unsigned short _timer) : timer(_timer){
|
||||
/*
|
||||
The constructor of the class DueTimer
|
||||
*/
|
||||
}
|
||||
|
||||
DueTimer DueTimer::getAvailable(void){
|
||||
/*
|
||||
Return the first timer with no callback set
|
||||
*/
|
||||
|
||||
for(int i = 0; i < NUM_TIMERS; i++){
|
||||
if(!callbacks[i])
|
||||
return DueTimer(i);
|
||||
}
|
||||
// Default, return Timer0;
|
||||
return DueTimer(0);
|
||||
}
|
||||
|
||||
DueTimer& DueTimer::attachInterrupt(void (*isr)()){
|
||||
/*
|
||||
Links the function passed as argument to the timer of the object
|
||||
*/
|
||||
|
||||
callbacks[timer] = isr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DueTimer& DueTimer::detachInterrupt(void){
|
||||
/*
|
||||
Links the function passed as argument to the timer of the object
|
||||
*/
|
||||
|
||||
stop(); // Stop the currently running timer
|
||||
|
||||
callbacks[timer] = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DueTimer& DueTimer::start(long microseconds){
|
||||
/*
|
||||
Start the timer
|
||||
If a period is set, then sets the period and start the timer
|
||||
*/
|
||||
|
||||
if(microseconds > 0)
|
||||
setPeriod(microseconds);
|
||||
|
||||
if(_frequency[timer] <= 0)
|
||||
setFrequency(1);
|
||||
|
||||
NVIC_ClearPendingIRQ(Timers[timer].irq);
|
||||
NVIC_EnableIRQ(Timers[timer].irq);
|
||||
|
||||
TC_Start(Timers[timer].tc, Timers[timer].channel);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DueTimer& DueTimer::stop(void){
|
||||
/*
|
||||
Stop the timer
|
||||
*/
|
||||
|
||||
NVIC_DisableIRQ(Timers[timer].irq);
|
||||
|
||||
TC_Stop(Timers[timer].tc, Timers[timer].channel);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t DueTimer::bestClock(double frequency, uint32_t& retRC){
|
||||
/*
|
||||
Pick the best Clock, thanks to Ogle Basil Hall!
|
||||
|
||||
Timer Definition
|
||||
TIMER_CLOCK1 MCK / 2
|
||||
TIMER_CLOCK2 MCK / 8
|
||||
TIMER_CLOCK3 MCK / 32
|
||||
TIMER_CLOCK4 MCK /128
|
||||
*/
|
||||
const struct {
|
||||
uint8_t flag;
|
||||
uint8_t divisor;
|
||||
} clockConfig[] = {
|
||||
{ TC_CMR_TCCLKS_TIMER_CLOCK1, 2 },
|
||||
{ TC_CMR_TCCLKS_TIMER_CLOCK2, 8 },
|
||||
{ TC_CMR_TCCLKS_TIMER_CLOCK3, 32 },
|
||||
{ TC_CMR_TCCLKS_TIMER_CLOCK4, 128 }
|
||||
};
|
||||
float ticks;
|
||||
float error;
|
||||
int clkId = 3;
|
||||
int bestClock = 3;
|
||||
float bestError = 9.999e99;
|
||||
do
|
||||
{
|
||||
ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[clkId].divisor;
|
||||
// error = abs(ticks - round(ticks));
|
||||
error = clockConfig[clkId].divisor * abs(ticks - round(ticks)); // Error comparison needs scaling
|
||||
if (error < bestError)
|
||||
{
|
||||
bestClock = clkId;
|
||||
bestError = error;
|
||||
}
|
||||
} while (clkId-- > 0);
|
||||
ticks = (float) VARIANT_MCK / frequency / (float) clockConfig[bestClock].divisor;
|
||||
retRC = (uint32_t) round(ticks);
|
||||
return clockConfig[bestClock].flag;
|
||||
}
|
||||
|
||||
|
||||
DueTimer& DueTimer::setFrequency(double frequency){
|
||||
/*
|
||||
Set the timer frequency (in Hz)
|
||||
*/
|
||||
|
||||
// Prevent negative frequencies
|
||||
if(frequency <= 0) { frequency = 1; }
|
||||
|
||||
// Remember the frequency — see below how the exact frequency is reported instead
|
||||
//_frequency[timer] = frequency;
|
||||
|
||||
// Get current timer configuration
|
||||
Timer t = Timers[timer];
|
||||
|
||||
uint32_t rc = 0;
|
||||
uint8_t clock;
|
||||
|
||||
// Tell the Power Management Controller to disable
|
||||
// the write protection of the (Timer/Counter) registers:
|
||||
pmc_set_writeprotect(false);
|
||||
|
||||
// Enable clock for the timer
|
||||
pmc_enable_periph_clk((uint32_t)t.irq);
|
||||
|
||||
// Find the best clock for the wanted frequency
|
||||
clock = bestClock(frequency, rc);
|
||||
|
||||
switch (clock) {
|
||||
case TC_CMR_TCCLKS_TIMER_CLOCK1:
|
||||
_frequency[timer] = (double)VARIANT_MCK / 2.0 / (double)rc;
|
||||
break;
|
||||
case TC_CMR_TCCLKS_TIMER_CLOCK2:
|
||||
_frequency[timer] = (double)VARIANT_MCK / 8.0 / (double)rc;
|
||||
break;
|
||||
case TC_CMR_TCCLKS_TIMER_CLOCK3:
|
||||
_frequency[timer] = (double)VARIANT_MCK / 32.0 / (double)rc;
|
||||
break;
|
||||
default: // TC_CMR_TCCLKS_TIMER_CLOCK4
|
||||
_frequency[timer] = (double)VARIANT_MCK / 128.0 / (double)rc;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set up the Timer in waveform mode which creates a PWM
|
||||
// in UP mode with automatic trigger on RC Compare
|
||||
// and sets it up with the determined internal clock as clock input.
|
||||
TC_Configure(t.tc, t.channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | clock);
|
||||
// Reset counter and fire interrupt when RC value is matched:
|
||||
TC_SetRC(t.tc, t.channel, rc);
|
||||
// Enable the RC Compare Interrupt...
|
||||
t.tc->TC_CHANNEL[t.channel].TC_IER=TC_IER_CPCS;
|
||||
// ... and disable all others.
|
||||
t.tc->TC_CHANNEL[t.channel].TC_IDR=~TC_IER_CPCS;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DueTimer& DueTimer::setPeriod(unsigned long microseconds){
|
||||
/*
|
||||
Set the period of the timer (in microseconds)
|
||||
*/
|
||||
|
||||
// Convert period in microseconds to frequency in Hz
|
||||
double frequency = 1000000.0 / microseconds;
|
||||
setFrequency(frequency);
|
||||
return *this;
|
||||
}
|
||||
|
||||
double DueTimer::getFrequency(void) const {
|
||||
/*
|
||||
Get current time frequency
|
||||
*/
|
||||
|
||||
return _frequency[timer];
|
||||
}
|
||||
|
||||
long DueTimer::getPeriod(void) const {
|
||||
/*
|
||||
Get current time period
|
||||
*/
|
||||
|
||||
return 1.0/getFrequency()*1000000;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Implementation of the timer callbacks defined in
|
||||
arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h
|
||||
*/
|
||||
// Fix for compatibility with Servo library
|
||||
#ifndef USING_SERVO_LIB
|
||||
void TC0_Handler(void){
|
||||
TC_GetStatus(TC0, 0);
|
||||
DueTimer::callbacks[0]();
|
||||
}
|
||||
#endif
|
||||
void TC1_Handler(void){
|
||||
TC_GetStatus(TC0, 1);
|
||||
DueTimer::callbacks[1]();
|
||||
}
|
||||
// Fix for compatibility with Servo library
|
||||
#ifndef USING_SERVO_LIB
|
||||
void TC2_Handler(void){
|
||||
TC_GetStatus(TC0, 2);
|
||||
DueTimer::callbacks[2]();
|
||||
}
|
||||
void TC3_Handler(void){
|
||||
TC_GetStatus(TC1, 0);
|
||||
DueTimer::callbacks[3]();
|
||||
}
|
||||
void TC4_Handler(void){
|
||||
TC_GetStatus(TC1, 1);
|
||||
DueTimer::callbacks[4]();
|
||||
}
|
||||
void TC5_Handler(void){
|
||||
TC_GetStatus(TC1, 2);
|
||||
DueTimer::callbacks[5]();
|
||||
}
|
||||
#endif
|
||||
void TC6_Handler(void){
|
||||
TC_GetStatus(TC2, 0);
|
||||
DueTimer::callbacks[6]();
|
||||
}
|
||||
void TC7_Handler(void){
|
||||
TC_GetStatus(TC2, 1);
|
||||
DueTimer::callbacks[7]();
|
||||
}
|
||||
void TC8_Handler(void){
|
||||
TC_GetStatus(TC2, 2);
|
||||
DueTimer::callbacks[8]();
|
||||
}
|
||||
#endif
|
||||
109
lib/DueTimer/DueTimer.h
Normal file
109
lib/DueTimer/DueTimer.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
DueTimer.h - DueTimer header file, definition of methods and attributes...
|
||||
For instructions, go to https://github.com/ivanseidel/DueTimer
|
||||
|
||||
Created by Ivan Seidel Gomes, March, 2013.
|
||||
Modified by Philipp Klaus, June 2013.
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#ifdef __arm__
|
||||
|
||||
#ifndef DueTimer_h
|
||||
#define DueTimer_h
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
This fixes compatibility for Arduono Servo Library.
|
||||
Uncomment to make it compatible.
|
||||
|
||||
Note that:
|
||||
+ Timers: 0,2,3,4,5 WILL NOT WORK, and will
|
||||
neither be accessible by Timer0,...
|
||||
*/
|
||||
// #define USING_SERVO_LIB true
|
||||
|
||||
#ifdef USING_SERVO_LIB
|
||||
#warning "HEY! You have set flag USING_SERVO_LIB. Timer0, 2,3,4 and 5 are not available"
|
||||
#endif
|
||||
|
||||
|
||||
#define NUM_TIMERS 9
|
||||
|
||||
class DueTimer
|
||||
{
|
||||
protected:
|
||||
|
||||
// Represents the timer id (index for the array of Timer structs)
|
||||
const unsigned short timer;
|
||||
|
||||
// Stores the object timer frequency
|
||||
// (allows to access current timer period and frequency):
|
||||
static double _frequency[NUM_TIMERS];
|
||||
|
||||
// Picks the best clock to lower the error
|
||||
static uint8_t bestClock(double frequency, uint32_t& retRC);
|
||||
|
||||
// Make Interrupt handlers friends, so they can use callbacks
|
||||
friend void TC0_Handler(void);
|
||||
friend void TC1_Handler(void);
|
||||
friend void TC2_Handler(void);
|
||||
friend void TC3_Handler(void);
|
||||
friend void TC4_Handler(void);
|
||||
friend void TC5_Handler(void);
|
||||
friend void TC6_Handler(void);
|
||||
friend void TC7_Handler(void);
|
||||
friend void TC8_Handler(void);
|
||||
|
||||
static void (*callbacks[NUM_TIMERS])();
|
||||
|
||||
struct Timer
|
||||
{
|
||||
Tc *tc;
|
||||
uint32_t channel;
|
||||
IRQn_Type irq;
|
||||
};
|
||||
|
||||
// Store timer configuration (static, as it's fixed for every object)
|
||||
static const Timer Timers[NUM_TIMERS];
|
||||
|
||||
public:
|
||||
|
||||
static DueTimer getAvailable(void);
|
||||
|
||||
DueTimer(unsigned short _timer);
|
||||
DueTimer& attachInterrupt(void (*isr)());
|
||||
DueTimer& detachInterrupt(void);
|
||||
DueTimer& start(long microseconds = -1);
|
||||
DueTimer& stop(void);
|
||||
DueTimer& setFrequency(double frequency);
|
||||
DueTimer& setPeriod(unsigned long microseconds);
|
||||
|
||||
double getFrequency(void) const;
|
||||
long getPeriod(void) const;
|
||||
};
|
||||
|
||||
// Just to call Timer.getAvailable instead of Timer::getAvailable() :
|
||||
extern DueTimer Timer;
|
||||
|
||||
extern DueTimer Timer1;
|
||||
// Fix for compatibility with Servo library
|
||||
#ifndef USING_SERVO_LIB
|
||||
extern DueTimer Timer0;
|
||||
extern DueTimer Timer2;
|
||||
extern DueTimer Timer3;
|
||||
extern DueTimer Timer4;
|
||||
extern DueTimer Timer5;
|
||||
#endif
|
||||
extern DueTimer Timer6;
|
||||
extern DueTimer Timer7;
|
||||
extern DueTimer Timer8;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error Oops! Trying to include DueTimer on another device?
|
||||
#endif
|
||||
21
lib/DueTimer/LICENSE.txt
Normal file
21
lib/DueTimer/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Ivan Seidel
|
||||
|
||||
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.
|
||||
119
lib/DueTimer/README.md
Normal file
119
lib/DueTimer/README.md
Normal file
@ -0,0 +1,119 @@
|
||||
# DueTimer
|
||||
|
||||
Timer Library to work with Arduino DUE
|
||||
|
||||
## Installation
|
||||
|
||||
1. [Download](https://github.com/ivanseidel/DueTimer/releases) the Latest release from GitHub.
|
||||
2. Unzip and modify the Folder name to "DueTimer" (Remove the '-version')
|
||||
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
|
||||
4. Re-open Arduino Software
|
||||
|
||||
## Getting Started
|
||||
|
||||
To call a function `handler` every `1000` microseconds:
|
||||
|
||||
```c++
|
||||
Timer3.attachInterrupt(handler).start(1000);
|
||||
// or:
|
||||
Timer3.attachInterrupt(handler).setPeriod(1000).start();
|
||||
// or, to select whichever available timer:
|
||||
Timer.getAvailable().attachInterrupt(handler).start(1000);
|
||||
```
|
||||
|
||||
To call a function `handler` `10` times a second:
|
||||
|
||||
```c++
|
||||
Timer3.attachInterrupt(handler).setFrequency(10).start();
|
||||
```
|
||||
|
||||
In case you need to stop a timer, just do like this:
|
||||
|
||||
```c++
|
||||
Timer3.stop();
|
||||
```
|
||||
|
||||
And to continue running:
|
||||
|
||||
```c++
|
||||
Timer3.start();
|
||||
```
|
||||
|
||||
There are `9` Timer objects already instantiated for you:
|
||||
`Timer0`, `Timer1`, `Timer2`, `Timer3`, `Timer4`, `Timer5`, `Timer6`, `Timer7` and `Timer8`.
|
||||
|
||||
### TIPs and Warnings
|
||||
|
||||
```c++
|
||||
Timer4.attachInterrupt(handler).setFrequency(10).start();
|
||||
// Is the same as:
|
||||
Timer4.attachInterrupt(handler);
|
||||
Timer4.setFrequency(10);
|
||||
Timer4.start();
|
||||
|
||||
// To create a custom timer, refer to:
|
||||
DueTimer myTimer = DueTimer(0); // Creates a Timer 0 object.
|
||||
DueTimer myTimer = DueTimer(3); // Creates a Timer 3 object.
|
||||
DueTimer myTimer = DueTimer(t); // Creates a Timer t object.
|
||||
// Note: Maximum t allowed is 8, as there is only 9 timers [0..8];
|
||||
|
||||
Timer1.attachInterrupt(handler1).start(10);
|
||||
Timer1.attachInterrupt(handler2).start(10);
|
||||
DueTimer myTimer = DueTimer(1);
|
||||
myTimer.attachInterrupt(handler3).start(20);
|
||||
// Will run only handle3, on Timer 1 (You are just overriding the callback)
|
||||
|
||||
Timer.getAvailable().attachInterrupt(callback1).start(10);
|
||||
// Start timer on first available timer
|
||||
DueTimer::getAvailable().attachInterrupt(callback2).start(10);
|
||||
// Start timer on second available timer
|
||||
// And so on...
|
||||
```
|
||||
|
||||
### Compatibility with Servo.h
|
||||
|
||||
Because Servo Library uses the same callbacks of DueTimer, we provides a custom solution for working with both of them. However, Timers 0,2,3,4 and 5 will not Work anymore.
|
||||
|
||||
You will need uncommend the line in `DueTimer.h` in `DueTimer` folder inside the `Libraries` folder. Uncomment the following line in `DueTimer.h`:
|
||||
|
||||
```
|
||||
#define USING_SERVO_LIB true
|
||||
```
|
||||
|
||||
## Library Reference
|
||||
|
||||
### You should know:
|
||||
|
||||
- `getAvailable()` - Get the first available Timer.
|
||||
|
||||
- `attachInterrupt(void (*isr)())` - Attach a interrupt (callback function) for the timer of the object.
|
||||
|
||||
- `detachInterrupt()` - Detach current callback of timer.
|
||||
|
||||
- `start(long microseconds = -1)` - Start the timer with an optional period parameter.
|
||||
|
||||
- `stop()` - Stop the timer
|
||||
|
||||
- `setFrequency(long frequency)` - Set the timer frequency
|
||||
|
||||
- `long getFrequency()` - Get the timer frequency
|
||||
|
||||
- `setPeriod(long microseconds)` - Set the timer period (in microseconds)
|
||||
|
||||
- `long getPeriod()` - Get the timer period (in microseconds)
|
||||
|
||||
### You don't need to know:
|
||||
|
||||
- `unsigned short timer` - Stores the object timer id (to access Timers struct array).
|
||||
|
||||
- `DueTimer(unsigned short _timer)` - Instantiate a new DueTimer object for Timer _timer (NOTE: All objects are already instantiated!).
|
||||
|
||||
- `static const Timer Timers[]` - Stores all timers information
|
||||
|
||||
- `static void (*callbacks[])()` - Stores all callbacks for all timers
|
||||
|
||||
|
||||
### Hardware Information
|
||||
|
||||
More information on the Timer Counter module of the µC on the Arduino Due
|
||||
can be found in the documentation file [TimerCounter](TimerCounter.md).
|
||||
106
lib/DueTimer/TimerCounter.md
Normal file
106
lib/DueTimer/TimerCounter.md
Normal file
@ -0,0 +1,106 @@
|
||||
# The Timer Counter blocks of Arduino Due's AT91SAM3X8E
|
||||
|
||||
The AT91SAM3X8E embedds nine general-purpose 32-bit timers/counters. They are organized in three blocks (`TC0`, `TC1`, `TC2`) each containing three channels (`0`, `1`, `2`).
|
||||
Each block and channel has input lines for their clock and input/output lines which can be used in different ways, such as PWM pins etc.
|
||||
|
||||
|
||||
### Resources
|
||||
|
||||
Information on the Timer Counter and its I/O signals pins can be found here:
|
||||
|
||||
* Section **37 Timer Counter (TC)** in the [Atmel SAM3X Datasheet][]
|
||||
You find this chapter on the pages 869 through 920. It explains in detail how to operate the counter in different modes and has nice diagrams that show you how the clock input works and how to set up interrupts based on counter values etc.
|
||||
* [Arduino Due's SAM3X Pin Mapping][] and the
|
||||
* [Arduino Due pinout diagram][].
|
||||
|
||||
### The Timer Counter Signals / Pins
|
||||
|
||||
Many of the I/O lines of the Timer Counter are directly accessible on pin headers of the Arduino Due board. This section helps you to find out which of them are and which are not.
|
||||
|
||||
In order to actually connect those signals (`TCLKx`, `TIOAx` and `TIOBx`) to the pins on the Arduino Due, you must tell the Parallel I/O Controllers (`PIOA`, `PIOB`, `PIOC` or `PIOD`) to set up their mux (multiplexer) accordingly.<br />
|
||||
A useful resource to find out how to set the PIOs is
|
||||
[Arduino's const array of PinDescriptions](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/variants/arduino_due_x/variant.cpp#L117) and the
|
||||
[definition of PinDescription](https://github.com/arduino/Arduino/blob/ide-1.5.x/hardware/arduino/sam/cores/arduino/Arduino.h#L166), the data type of its entries.
|
||||
|
||||
#### Overview of the I/O lines of the Timer Counter
|
||||
|
||||
Here is a table of the Timer Counter channels and their `TCLKx` (external clock input), `TIOAx` (I/O Line _A_) and `TIOBx` (I/O Line _B_) signals:
|
||||
|
||||
Instance | TC | Channel| External Clock Input | I/O Line A | I/O Line B
|
||||
---------|-----|--------|----------------------|------------|-----------
|
||||
T0 | TC0 | 0 | TCLK0 | TIOA0 | TIOB0
|
||||
T1 | TC0 | 1 | TCLK1 | TIOA1 | TIOB1
|
||||
T2 | TC0 | 2 | TCLK2 | TIOA2 | TIOB2
|
||||
T3 | TC1 | 0 | TCLK3 | TIOA3 | TIOB3
|
||||
T4 | TC1 | 1 | TCLK4 | TIOA4 | TIOB4
|
||||
T5 | TC1 | 2 | TCLK5 | TIOA5 | TIOB5
|
||||
T6 | TC2 | 0 | TCLK6 | TIOA6 | TIOB6
|
||||
T7 | TC2 | 1 | TCLK7 | TIOA7 | TIOB7
|
||||
T8 | TC2 | 2 | TCLK8 | TIOA8 | TIOB8
|
||||
|
||||
##### TCLKx
|
||||
|
||||
Here is how the **external clock inputs** are routed to pins on the Arduino Due board:
|
||||
|
||||
Clock Input | Port Pin of µC | Pin on Arduino Due Board
|
||||
------------|------------|-----------------------------
|
||||
TCLK0 | PB 26 | Digital Pin 22
|
||||
TCLK1 | PA 4 | Analog In 5
|
||||
TCLK2 | PA 7 | Digital Pin 31
|
||||
TCLK3 | PA 22 | Analog In 3
|
||||
TCLK4 | PA 23 | Analog In 2
|
||||
TCLK5 | PB 16 | DAC1
|
||||
TCLK6 | PC 27 | /
|
||||
TCLK7 | PC 30 | LED "RX"
|
||||
TCLK8 | PD 9 | Digital Pin 30
|
||||
|
||||
##### TIOAx
|
||||
|
||||
Here is how the **I/O Lines _A_** are routed to pins on the Arduino Due board:
|
||||
|
||||
I/O Line A | Port Pin of µC | Pin on Arduino Due Board
|
||||
-----------|----------------|-----------------------------
|
||||
TIOA0 | PB 25 | Digital Pin 2
|
||||
TIOA1 | PA 2 | Analog In 7
|
||||
TIOA2 | PA 5 | /
|
||||
TIOA3 | PE 9 | /
|
||||
TIOA4 | PE 11 | /
|
||||
TIOA5 | PE 13 | /
|
||||
TIOA6 | PC 25 | Digital Pin 5
|
||||
TIOA7 | PC 28 | Digital Pin 3
|
||||
TIOA8 | PD 7 | Digital Pin 11
|
||||
|
||||
##### TIOBx
|
||||
|
||||
Here is how the **I/O Lines _B_** are routed to pins on the Arduino Due board:
|
||||
|
||||
I/O Line B|Port Pin of µC| Pin on Arduino Due Board
|
||||
----------|--------------|------------------------------------------
|
||||
TIOB0 | PB 27 | Digital Pin 13 / Amber LED "L"
|
||||
TIOB1 | PA 3 | Analog In 6
|
||||
TIOB2 | PA 6 | Analog In 4
|
||||
TIOB3 | PE 10 | /
|
||||
TIOB4 | PE 12 | /
|
||||
TIOB5 | PE 14 | /
|
||||
TIOB6 | PC 26 | Digital Pin 4 (also connected to PA29)
|
||||
TIOB7 | PC 29 | Digital Pin 10 (also connected to PA28)
|
||||
TIOB8 | PD 8 | Digital Pin 12
|
||||
|
||||
#### TC Clock Source Selection
|
||||
|
||||
The *clock of the counters* can be set very flexibly to internal or external signals. To *use the channel as a timer*, it makes sense to connect its clock input to an internal timer clock. Here are the options:
|
||||
|
||||
Name | Definition
|
||||
-------------|-----------
|
||||
TIMER_CLOCK1 | `MCK / 2`
|
||||
TIMER_CLOCK2 | `MCK / 8`
|
||||
TIMER_CLOCK3 | `MCK / 32`
|
||||
TIMER_CLOCK4 | `MCK / 128`
|
||||
TIMER_CLOCK5 | `SLCK`
|
||||
|
||||
|
||||
Where `MCK` is the master clock (84 MHz for the Arduino Due) and SLCK is the slow clock (which can be clocked at 32.768 kHz by Y2 on the Arduino Due).
|
||||
|
||||
[Atmel SAM3X Datasheet]: http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf
|
||||
[Arduino Due's SAM3X Pin Mapping]: http://arduino.cc/en/Hacking/PinMappingSAM3X
|
||||
[Arduino Due pinout diagram]: http://www.robgray.com/temp/Due-pinout.pdf
|
||||
60
lib/DueTimer/examples/AvaliableTimer/AvaliableTimer.pde
Normal file
60
lib/DueTimer/examples/AvaliableTimer/AvaliableTimer.pde
Normal file
@ -0,0 +1,60 @@
|
||||
#include <DueTimer.h>
|
||||
|
||||
void playVideogame(){
|
||||
Serial.println("[- ] I'm playing Videogame!");
|
||||
}
|
||||
|
||||
void drinkWater(){
|
||||
Serial.println("[ - ] I'm driking water!");
|
||||
}
|
||||
|
||||
void makeSushi(){
|
||||
Serial.println("[ - ] Slicing Salmon...");
|
||||
}
|
||||
|
||||
void singOnShower(){
|
||||
Serial.println("[ - ] Hello World! Hello world!");
|
||||
}
|
||||
|
||||
void studyMath(){
|
||||
int x = random(1, 40), y = random(1,40);
|
||||
Serial.print("[ - ] ");
|
||||
Serial.print(x); Serial.print(" x "); Serial.print(y); Serial.print(" = ");
|
||||
Serial.println(x*y);
|
||||
}
|
||||
|
||||
void watchStarTrek(){
|
||||
Serial.println("[ - ] Long live and prosper \\\\//_");
|
||||
}
|
||||
|
||||
void eatSushi(){
|
||||
Serial.println("[ - ] ...");
|
||||
}
|
||||
|
||||
void readTextMessage(){
|
||||
Serial.println("[ - ] [Unlock ---->>]");
|
||||
}
|
||||
|
||||
void goToSleep(){
|
||||
Serial.println("[ -] zzzzzz");
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
Timer.getAvailable().attachInterrupt(playVideogame).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(drinkWater).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(makeSushi).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(singOnShower).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(studyMath).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(watchStarTrek).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(eatSushi).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(readTextMessage).start(); delay(50);
|
||||
Timer.getAvailable().attachInterrupt(goToSleep).start(); delay(50);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
while(1){
|
||||
// ...
|
||||
}
|
||||
}
|
||||
29
lib/DueTimer/examples/MultipleTimers/MultipleTimers.pde
Normal file
29
lib/DueTimer/examples/MultipleTimers/MultipleTimers.pde
Normal file
@ -0,0 +1,29 @@
|
||||
#include <DueTimer.h>
|
||||
|
||||
void firstHandler(){
|
||||
Serial.println("[- ] First Handler!");
|
||||
}
|
||||
|
||||
void secondHandler(){
|
||||
Serial.println("[ - ] Second Handler!");
|
||||
}
|
||||
|
||||
void thirdHandler(){
|
||||
Serial.println("[ -] Third Handler!");
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
Timer3.attachInterrupt(firstHandler).start(500000); // Every 500ms
|
||||
Timer4.attachInterrupt(secondHandler).setFrequency(1).start();
|
||||
Timer5.attachInterrupt(thirdHandler).setFrequency(10);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
delay(2000);
|
||||
Timer5.start();
|
||||
|
||||
delay(2000);
|
||||
Timer5.stop();
|
||||
}
|
||||
25
lib/DueTimer/examples/SimpleTimer/SimpleTimer.pde
Normal file
25
lib/DueTimer/examples/SimpleTimer/SimpleTimer.pde
Normal file
@ -0,0 +1,25 @@
|
||||
#include <DueTimer.h>
|
||||
|
||||
int myLed = 13;
|
||||
|
||||
bool ledOn = false;
|
||||
void myHandler(){
|
||||
ledOn = !ledOn;
|
||||
|
||||
digitalWrite(myLed, ledOn); // Led on, off, on, off...
|
||||
}
|
||||
|
||||
void setup(){
|
||||
pinMode(myLed, OUTPUT);
|
||||
|
||||
Timer3.attachInterrupt(myHandler);
|
||||
Timer3.start(50000); // Calls every 50ms
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
while(1){
|
||||
// I'm stuck in here! help me...
|
||||
}
|
||||
|
||||
}
|
||||
20
lib/DueTimer/keywords.txt
Normal file
20
lib/DueTimer/keywords.txt
Normal file
@ -0,0 +1,20 @@
|
||||
DueTimer KEYWORD2
|
||||
start KEYWORD2
|
||||
stop KEYWORD2
|
||||
attachInterrupt KEYWORD2
|
||||
detachInterrupt KEYWORD2
|
||||
setPeriod KEYWORD2
|
||||
setFrequency KEYWORD2
|
||||
getFrequency KEYWORD2
|
||||
getPeriod KEYWORD2
|
||||
|
||||
Timer KEYWORD1
|
||||
Timer0 KEYWORD1
|
||||
Timer1 KEYWORD1
|
||||
Timer2 KEYWORD1
|
||||
Timer3 KEYWORD1
|
||||
Timer4 KEYWORD1
|
||||
Timer5 KEYWORD1
|
||||
Timer6 KEYWORD1
|
||||
Timer7 KEYWORD1
|
||||
|
||||
12
lib/DueTimer/library.json
Normal file
12
lib/DueTimer/library.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "DueTimer",
|
||||
"keywords": "timer",
|
||||
"description": "Timer Library fully implemented for Arduino DUE",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ivanseidel/DueTimer.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelsam"
|
||||
}
|
||||
9
lib/DueTimer/library.properties
Normal file
9
lib/DueTimer/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=DueTimer
|
||||
version=1.4.7
|
||||
author=Ivan Seidel <ivanseidel@gmail.com>
|
||||
maintainer=Ivan Seidel <ivanseidel@gmail.com>
|
||||
sentence=Timer Library fully implemented for Arduino DUE
|
||||
paragraph=There are 9 Timer objects already instantiated for you: Timer0, Timer1, Timer2, Timer3, Timer4, Timer5, Timer6, Timer7 and Timer8.
|
||||
category=Timing
|
||||
url=https://github.com/ivanseidel/DueTimer
|
||||
architectures=sam
|
||||
Reference in New Issue
Block a user