Go Down

Topic: How to use Timer function with Arduino Due (Read 2 times) previous topic - next topic

kohlmeise

Hi guys,
today my new Arduino Due arrived and iam a little bit helpless.
For a project of mine I want to detect frequencies in the range of several MHz. Therefore i worked with a sketch which was written for atmega328. As newbe I thought that I could use this sketch as well for the Arduino Due .... but computer says no ....

Here is my sketch:
Code: [Select]

#include <Stdio.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#define CLEAR_ALL_TIMER1_INT_FLAGS    (TIFR1 = TIFR1)


int pinFreq = 5;

void setup()
{

  pinMode(pinFreq, INPUT);


  Serial.begin(115200);        // connect to the serial port

  // hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1)
  TCLK1=0;                   // reset timer/counter1 control register A
  TC_RB=0;                  // reset timer/counter1 control register A
  TCNT1=0;                    // counter value = 0
  // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino pin 5)
  // normal mode, wgm10 .. wgm13 = 0
  sbi (TCCR1B ,CS10);         // External clock source on T1 pin. Clock on rising edge.
  sbi (TCCR1B ,CS11);
  sbi (TCCR1B ,CS12);

  // timer2 setup / is used for frequency measurement gatetime generation
  // timer 2 presaler set to 256 / timer 2 clock = 16Mhz / 256 = 62500 Hz
  cbi (TCCR2B ,CS20);
  sbi (TCCR2B ,CS21);
  sbi (TCCR2B ,CS22);

  //set timer2 to CTC Mode
  cbi (TCCR2A ,WGM20);
  sbi (TCCR2A ,WGM21);
  cbi (TCCR2B ,WGM22);
  OCR2A = 31;                  // CTC at top of OCR2A / timer2 interrupt when coun value reaches OCR2A value

  // interrupt control

  sbi (TIMSK2,OCIE2A);          // enable Timer2 Interrupt

}

long freq_in;

void loop()
{

}

// Timer2 Interrupt Service is invoked by hardware Timer2 every 2ms = 500 Hz
//  16Mhz / 256 / 125 / 500 Hz
// here the gatetime generation for freq. measurement takes place:

ISR(TIMER2_COMPA_vect) {

  freq_in=TCNT1;
  TCNT1=0;
  TCNT2=0;
 
  Serial.write(highByte(freq_in));
  Serial.write(lowByte(freq_in));

}


While uploading there appear a lot of "xxx is not declaired in the scope " errors.
Is this because i use the wrong commands to control the timers / Do i need a special libary? Is there anyway to go on working with this sketch and the arduino due ? Or do i need to write a total new program?
Would be happy about some help :=)

Kind regards
Kohlmeise


OllieK

I am also new in Arduino development and my plan is to build a Due based robot (standing two-wheeler with huge number of sensors).  For that I need both timer controlled interrupts and timer controlled output pins.  After quite extensive web searches, I did realize that there were no libraries available matching my needs and expectations.  The solution was to read the Atmel manual and do Arduino Due specific Timer Control solution making all three timer blocks and I/O pins available for user applications.

You can use this in your applications by adding line #include "DueTC,h" in your application and adding the files DueTC.h and DueTC.h to the tabs in IDE.  If you add these files in your library folder DueTC then you can use them with line #include <DueTC.h>.

To get the a 27.3 kHz square wave in Pin5, the only thing you have to do is the following line in your setup() code

  setupTC_Pin5_Timing(1536,0);

Where 1536 is the period for the clock number 0.  In Due, this clock is running at 42 MHz (MCL/2).

You can generate a S/W driven 27.3 kHz square wave in Pin6 by having the following lines in setup()

  pinMode(6,OUTPUT);
  setupTC2_Interrupt(384,1,togglePin6);  // 384 = period, clock = 1, int handler = togglePin6


and the following lines before setup() to define the interrupt handler

void togglePin6(){
  static byte flg;
  digitalWrite(6,flg=!flg);
}


There is some additional documentation in the following INO, CPP, and H files.  The DueTC demo program shows how to change the frequencies in the loop().

DueTC_Demo.ino

Code: [Select]

#include <DueTC.h>

/*
  DueTC_Demo.ino - Testing and demonstration of DUE Timer Control implemented in DueTC.cpp

Created by Olavi Kamppari, October 2013.

Test the following routines
- setupTC_Pin_Timing      with commandline       Sp period clock
- changeTC_Pin_Period     with commandline       Cp period
- setupTC_Interrupt       with commandline       In period clock
- changeTC2_Period        with commandline       Pn period
- NVIC_SetPendingIRQ      with commandline       Fn                (this is an inline macro and not specified in DueTC.cpp)

where
      Pin number p is 2,3,5, or 11
      Period is 1-65535
      Clock is 0-4
      Interrupt number n is 2,3,4,5

In the test program the user specified interrupt handlers are toggling outputs in pins 6, 7, 8, and 9

In the setup routine the Pin5 setting and the TC2-TC5 settings the times are set equal using different master clock dividers.
With a scope connected to pins 5-9, it can be observed that pins 5-8 are are providing the same timing and are staying in synch.
Pin 9 has the "same" timing, but the SLCK based timing is not staying in synch with MCK.

Released into the public domain.
*/



void togglePin4(){
  static byte flg;
  digitalWrite(4,flg=!flg);
}

void togglePin6(){
  static byte flg;
  digitalWrite(6,flg=!flg);
}

void togglePin7(){
  static byte flg;
  digitalWrite(7,flg=!flg);
}

void togglePin8(){
  static byte flg;
  digitalWrite(8,flg=!flg);
}

void togglePin9(){
  static byte flg;
  digitalWrite(9,flg=!flg);
}

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(100);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);

                                           // Target toggling frequency: 84,000 kHz/3,072 = 27.3 kHz
  setupTC_Pin5_Timing(1536,0);             // 84,000,000/(2*1536) = 27,343.75 Hz (36.57 us pulse)
  setupTC2_Interrupt(384,1,togglePin6);    // 84,000,000/(8*384)  = 27,343.75 Hz (36.57 us pulse)
  setupTC3_Interrupt(96,2,togglePin7);     // 84,000,000/(32*96)  = 27,343.75 Hz (36.57 us pulse)
  setupTC4_Interrupt(24,3,togglePin8);     // 84,000,000/(128*24) = 27,343.75 Hz (36.57 us pulse)
  setupTC5_Interrupt(1,4,togglePin9);      // 84,000,000/(32*96)  = 27,343.75 Hz (36.57 us pulse)
}

void loop() {
  char buffer[255];
  byte bLen;
  byte delimPos[10];
  int arg[10];
  byte argCount;
  byte i;
  char command;
  char delim;
  int pinNr;
  int timerNr;
  unsigned int period;
  byte tcClock;

  bLen=Serial.readBytesUntil('\n', buffer, sizeof(buffer));
  if (bLen>0) {
    buffer[bLen]=0;                     // set end of string marker after last character
    command=buffer[0];
    delimPos[0]=0;                      // mark first argument to start after command
    argCount=1;
    for (i=1;i<bLen;i++) {              // replace all delimitesr with zeroes
      delim=buffer[i];
      if (delim<'0' || delim>'9') {
        buffer[i]=0;
        delimPos[argCount++]=i;
        if (argCount>=sizeof(delimPos)) break;
      }
    }
                                        // get argument values
    for (i=0;i<argCount;i++) arg[i]=atoi(&buffer[delimPos[i]+1]);
    Serial.print(command);
    for (i=0;i<argCount;i++) {          // echo the command line back
      Serial.print(arg[i]);
      Serial.print(" ");
    }
    Serial.println();
    switch (command) {
    case 's':
    case 'S':
      pinNr=arg[0];
      period=(argCount>1)?arg[1]:0;
      tcClock=(argCount>2)?arg[2]:0;
      switch (pinNr) {
      case 2: 
        setupTC_Pin2_Timing(period,tcClock);
        break;
      case 5: 
        setupTC_Pin5_Timing(period,tcClock);
        break;
      case 3: 
        setupTC_Pin3_Timing(period,tcClock);
        break;
      case 11:
        setupTC_Pin11_Timing(period,tcClock);
        break;
      default:
        Serial.print("Not supported pin ");
        Serial.println(pinNr);
        Serial.println("Available pins are: 2, 3, 5, 11");
      }
      break;
    case 'c':
    case 'C':
      pinNr=arg[0];
      period=(argCount>1)?arg[1]:0;
      switch (pinNr) {
      case 2: 
        changeTC_Pin2_Period(period);
        break;
      case 5: 
        changeTC_Pin5_Period(period);
        break;
      case 3: 
        changeTC_Pin3_Period(period);
        break;
      case 11:
        changeTC_Pin11_Period(period);
        break;
      default:
        Serial.print("Not supported pin ");
        Serial.println(pinNr);
        Serial.println("Available pins are: 2, 3, 5, 11");
      }
      break;
    case 'i':
    case 'I':
      timerNr=arg[0];
      period=(argCount>1)?arg[1]:0;
      tcClock=(argCount>2)?arg[2]:0;
      switch (timerNr) {
      case 2: 
        setupTC2_Interrupt(period,tcClock,togglePin6);
        break;
      case 3: 
        setupTC3_Interrupt(period,tcClock,togglePin7);
        break;
      case 4: 
        setupTC4_Interrupt(period,tcClock,togglePin8);
        break;
      case 5: 
        setupTC5_Interrupt(period,tcClock,togglePin9);
        break;
      default:
        Serial.print("Not supported timer ");
        Serial.println(timerNr);
        Serial.println("Available interrupts are: 2, 3, 4, 5");
      }     
      break;
    case 'p':
    case 'P':
      timerNr=arg[0];
      period=(argCount>1)?arg[1]:0;
      switch (timerNr) {
      case 2: 
        changeTC2_Period(period);
        break;
      case 3: 
        changeTC3_Period(period);
        break;
      case 4: 
        changeTC4_Period(period);
        break;
      case 5: 
        changeTC5_Period(period);
        break;
      default:
        Serial.print("Not supported timer ");
        Serial.println(timerNr);
        Serial.println("Available interrupts are: 2, 3, 4, 5");
      }     
      break;
    case 'f':
    case 'F':
      timerNr=arg[0];
      switch (timerNr) {
      case 2: 
        NVIC_SetPendingIRQ(TC2_IRQn);
        break;
      case 3: 
        NVIC_SetPendingIRQ(TC3_IRQn);
        break;
      case 4: 
        NVIC_SetPendingIRQ(TC4_IRQn);
        break;
      case 5: 
        NVIC_SetPendingIRQ(TC5_IRQn);
        break;
      default:
        Serial.print("Not supported timer ");
        Serial.println(timerNr);
        Serial.println("Available interrupts are: 2, 3, 4, 5");
      }
      break;
    default:
      Serial.print("Unknown command");
      Serial.println(command);
      Serial.println("Available commands are:");
      Serial.println("   Sp period clock      to setup pin p (2,3,5,11) for period (1-65535) with clock (0-4)");
      Serial.println("   Cp period            to change pin p (2,3,5,11) period (1-65535)");
      Serial.println("   In period clock      to init interrupt n (2,3,4,5) for period (1-65535) with clock (0-4)");
      Serial.println("   Pn period            to change interrupt n (2,3,4,5) period (1-65535)");
      Serial.println("   Fn                   to force an interrupt n (2,3,4,5)");
    }
  }
}


I will show the H and CPP files in separate message due 9500 character limitation.

OllieK

Here are the Due Timer Control function definitions:

DueTC.h

Code: [Select]
/*
  DueTC.h - Interface for Arduino DUE Timer Control implemented in DueTC.cpp

Created by Olavi Kamppari, October 2013.
Released into the public domain.
*/

#ifdef __arm__

#ifndef DueTC_h
#define DueTC_h

#include "Arduino.h"

// tcClock values for Master Clock (MCK) frequency 84 MHz
//
// Duty cycle with different settings
//
//  0: MCK/2     = 42 MhZ,  period 1 = 48 ns,   period 0xffff = 3.1 ms,  320 Hz - 21 MHz
//  1: MCK/8     = 10.5 MhZ,period 1 = 190 ns,  period 0xffff = 12 ms,    80 Hz - 5.3 MHz
//  2: MCK/32    = 2.6 MhZ, period 1 = 762 ns,  period 0xffff = 50 ms,    20 Hz - 1.3 MHz
//  3: MCK/128   = 656 khZ, period 1 = 3.0 us,  period 0xffff = 200 ms,    5 Hz - 328 kHz
//  4: MCK/3072  = 28 khZ,  period 1 = 72 us,   period 0xffff = 4.7 s,   0.2 Hz - 14 kHz
//
// The option 4 is also known as SLCK (slow clock) which is supposed to be at 32 kHz

// Digital Output Pins for square waves
// ++++++++++++++++++++++++++++++++++++
// Timer 0
//      TC0 in channel 0: A on PWM2,   B on PWM13
void setupTC_Pin2_Timing(unsigned int period, byte tcClock);
void changeTC_Pin2_Period(unsigned int period);

// Timer 1, no channels awailable for square waves

// Timer 2
//      TC 6 in channel 0: A on PWM5,   B on PWM4
//      TC 7 in channel 1: A on PWM3,   B on PWM10
//      TC 8 in channel 0: A on PWM11,  B on PWM12
void setupTC_Pin5_Timing(unsigned int period, byte tcClock);
void setupTC_Pin3_Timing(unsigned int period, byte tcClock);
void setupTC_Pin11_Timing(unsigned int period, byte tcClock);

void changeTC_Pin5_Period(unsigned int period);
void changeTC_Pin3_Period(unsigned int period);
void changeTC_Pin11_Period(unsigned int period);

// Timers for interrupts
// +++++++++++++++++++++
//
// Timer 1 is used for system services (such as milli, micros, and delay)
// Timers 0, 6, 7, and 8 are reserved for square wave generation
// Timers 2-5 are available for timed interrupts
//
void setupTC2_Interrupt(unsigned int period, byte tcClock, void (*isr)());
void setupTC3_Interrupt(unsigned int period, byte tcClock, void (*isr)());
void setupTC4_Interrupt(unsigned int period, byte tcClock, void (*isr)());
void setupTC5_Interrupt(unsigned int period, byte tcClock, void (*isr)());

void changeTC2_Period(unsigned int period);
void changeTC3_Period(unsigned int period);
void changeTC4_Period(unsigned int period);
void changeTC5_Period(unsigned int period);

#endif

#else
#error DueTC works only on Arduino DUE ARM based processor
#endif


OllieK

Here are the Due Timer Control function implementations:

DueTC.cpp  PART 1

Code: [Select]
/*
  DueTC.cpp - Local code of Arduino DUE Timer Control defined on DueTC.h

Created by Olavi Kamppari, October 2013.
Reference to Atmel documentation 11057B-ATARM-28-May-12
for SAM3X and SAM3A Series

Programming principles:
- avoid unecessary S/W layers that are just complicating things
- use only one bit manipulation routine (encodeTC_WaveformMode) to calculate a value for Channel Mode Register (TC_CMR)
- use naming conventions specified by Atmel, such as
       TCx,  where x=indivudal timer number (0-8)
       REG_TCi_<reg>j, where
          i     = timer block number (0-2),
          j     = timer channel number in the block (0-2),
          <reg> = register name (CCR, CMR, SMMR, CV, RA, RB, RC, SR, IER, IDR, IMR, BCR, BMR,
                  QIER, QIDR, QIMR. QISR, FMR, WPMR)
- define pin connected timers and interrupts that are not conflicting with system timers and eachothers
- define all available connected timers and interrupts
- verify the results with an oscilloscope
       > observe the common false assumption that TIMER_CLOCK5 divider is 1024, when it actually is 3072

The main information that is not evident is in routine

       pmc_enable_periph_clk(TCx_IRQn);

It connects the interrupt ID number (TCx_IRQn) to a predefined interrupt handler (TCx_Handler).  The handler code is in this
module and it calls a user defined interrupt handler that is defined in the setup call (setupTC2_Interrupt). 

Released into the public domain.
*/

#include "DueTC.h"

unsigned long encodeTC_WaveformMode(
    byte BSWTRG, byte BEEVT, byte BCPC, byte BCPB,
    byte ASWTRG, byte AEEVT, byte ACPC, byte ACPA,
    byte WAVSEL, byte ENETRG, byte EEVT, byte EEVTEDG,
    byte CPCDIS, byte CPCSTOP, byte BURST, byte CLKI, byte TCCLKS) {
  // See Atmel doc 11057, section 37.7.11 on page 906
  /*
BSWTRG(30-31), Software Trigger Effect on TIOB
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   BEEVT(28-29), External Event Effect on TIOB
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   BCPC(26-27), RC Compare Effect on TIOB
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   BCPB(24-25), RB Compare Effect on TIOB
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   ASWTRG(22-23), Software Trigger Effect on TIOA
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   AEEVT(20-21), External Event Effect on TIOA
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   ACPC(18-19), RC Compare Effect on TIOA
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   ACPA(16-17), RA Compare Effect on TIOA
       0 NONE      None
       1 SET       Set
       2 CLEAR     Clear
       3 TOGGLE    Toggle
   
   WAVE(15), This is always 1 in waform generation mode
       0: Capture Mode is enabled (Measure signals).
       1: Capture Mode is disabled (Generate wave).
   
   WAVSEL(13-14)
       0 UP        UP mode without automatic trigger on RC Compare
       1 UPDOWN    UPDOWN mode without automatic trigger on RC Compare
       2 UP_RC     UP mode with automatic trigger on RC Compare
       3 UPDOWN_RC UPDOWN mode with automatic trigger on RC Compare
   
   ENETRG(12), External Event Trigger Enable
       0: the external event has no effect on the counter and its clock.
           In this case, the selected external event only controls the TIOA output.
       1: the external event resets the counter and starts the counter clock
   
   EEVT(10-11), External Event Selection
       0 TIOB       TIOB   TIOB is input
       1 XC0        XC0    TIOB is output
       2 XC1        XC1    TIOB is output
       3 XC2        XC2    TIOB is output
   
   EEVTEDG(8-9),  External Event Edge Selection
       0 NONE      None
       1 RISING    Rising edge
       2 FALLING   Falling edge
       3 EDGE      Each edge
   
   CPCDIS(7)
       0: counter clock is not disabled when RB loading occurs.
       1: counter clock is disabled when RB loading occurs
   
   CPCSTOP(6)
       0: counter clock is not stopped when RB loading occurs.
       1: counter clock is stopped when RB loading occurs
   
   BURST(4-5)
       0 NONE       The clock is not gated by an external signal.
       1 XC0        XC0 is ANDed with the selected clock.
       2 XC1        XC1 is ANDed with the selected clock.
       3 XC2        XC2 is ANDed with the selected clock
   
   CLKI(3)
       0: counter is incremented on rising edge of the clock.
       1: counter is incremented on falling edge of the clock.   
   
   TCCLKS(0-2)
       0 TIMER_CLOCK1    Clock selected: TCLK1    divider = 2 (1<<1)    42,000 kHz
       1 TIMER_CLOCK2    Clock selected: TCLK2    divider = 8 (1<<3)    10,500 kHz
       2 TIMER_CLOCK3    Clock selected: TCLK3    divider = 32 (1<<5)    2,625 kHz
       3 TIMER_CLOCK4    Clock selected: TCLK4    divider = 128 (1<<7)    656.25 Hz
       4 TIMER_CLOCK5    Clock selected: TCLK5    divider = 3*1024     0.027 Hz
       5 XC0        Clock selected: XC0
       6 XC1        Clock selected: XC1
       7 XC2        Clock selected: XC2
       
   */
  unsigned long encodedValue;
  byte WAVE=1;                        // Force wave generation
  encodedValue=(TCCLKS & 7) +
    ((CLKI & 1) << 3) +
    ((BURST & 3) << 4) +
    ((CPCSTOP & 1) << 6) +
    ((CPCDIS & 1) << 7) +
    ((EEVTEDG & 3) << 8) +
    ((EEVT & 3) << 10) +
    ((ENETRG & 1) << 12) +
    ((WAVSEL & 3) << 13) +
    ((WAVE & 1) << 15) +
    ((ACPA &3) << 16) +
    ((ACPC &3) << 18) +
    ((AEEVT &3) << 20) +
    ((ASWTRG &3) << 22) +
    ((BCPB &3) << 24) +
    ((BCPC &3) << 26) +
    ((BEEVT &3) << 28) +
    ((BSWTRG &3) << 30);
  return (encodedValue);
}

unsigned long getTC_Waveform(byte tcClock){
  return (encodeTC_WaveformMode(
  0,0,0,0,
  0,0,0,0,
  2,0,0,0,
  0,0,0,0,tcClock));
}
unsigned long getTC_Waveform_A(byte tcClock){
  return (encodeTC_WaveformMode(
  0,0,0,0,
  0,0,3,0,
  2,0,0,0,
  0,0,0,0,tcClock));
}

unsigned long getTC_Waveform_B(byte tcClock){
  return (encodeTC_WaveformMode(
  0,0,3,0,
  0,0,0,0,
  2,0,0,0,
  0,0,0,0,tcClock));
}

void start_TC0()  {
  REG_TC0_CCR0=5;
}
void start_TC1()  {
  REG_TC0_CCR1=5;
}
void start_TC2()  {
  REG_TC0_CCR2=5;
}
void start_TC3()  {
  REG_TC1_CCR0=5;
}
void start_TC4()  {
  REG_TC1_CCR1=5;
}
void start_TC5()  {
  REG_TC1_CCR2=5;
}
void start_TC6()  {
  REG_TC2_CCR0=5;
}
void start_TC7()  {
  REG_TC2_CCR1=5;
}
void start_TC8()  {
  REG_TC2_CCR2=5;
}

void stop_TC0()  {
  REG_TC0_CCR0=2;
}
void stop_TC1()  {
  REG_TC0_CCR1=2;
}
void stop_TC2()  {
  REG_TC0_CCR2=2;
}
void stop_TC3()  {
  REG_TC1_CCR0=2;
}
void stop_TC4()  {
  REG_TC1_CCR1=2;
}
void stop_TC5()  {
  REG_TC1_CCR2=2;
}
void stop_TC6()  {
  REG_TC2_CCR0=2;
}
void stop_TC7()  {
  REG_TC2_CCR1=2;
}
void stop_TC8()  {
  REG_TC2_CCR2=2;
}

OllieK

Here are the Due Timer Control function implementations:

DueTC.cpp  PART 2

Code: [Select]


void setupTC_Pin2_Timing(unsigned int period, byte tcClock){
  analogWrite(2,128);                             // Start with PWM setting
  REG_TC0_CMR0=getTC_Waveform_A(tcClock);         // Update Command Register
  REG_TC0_RC0=period;                             // Set period (1 - 0xFFFF)
  start_TC0();                                    // Start timer and generate square wave
}

void setupTC_Pin5_Timing(unsigned int period, byte tcClock){
  analogWrite(5,128);                             // Start with PWM setting
  REG_TC2_CMR0=getTC_Waveform_A(tcClock);         // Update Command Register
  REG_TC2_RC0=period;                             // Set period (1 - 0xFFFF)
  start_TC6();                                    // Start timer and generate square wave
}

void setupTC_Pin3_Timing(unsigned int period, byte tcClock){
  analogWrite(3,128);                             // Start with PWM setting
  REG_TC2_CMR1=getTC_Waveform_A(tcClock);         // Update Command Register
  REG_TC2_RC1=period;                             // Set period (1 - 0xFFFF)
  start_TC7();                                    // Start timer and generate square wave
}

void setupTC_Pin11_Timing(unsigned int period, byte tcClock){
  analogWrite(11,128);                            // Start with PWM setting
  REG_TC2_CMR2=getTC_Waveform_A(tcClock);         // Update Command Register
  REG_TC2_RC2=period;                             // Set period (1 - 0xFFFF)
  start_TC8();                                    // Start timer and generate square wave
}

void changeTC_Pin2_Period(unsigned int period){
  stop_TC0();
  REG_TC0_RC0=period;
  start_TC0();
}

void changeTC_Pin5_Period(unsigned int period){
  stop_TC6();
  REG_TC2_RC0=period;
  start_TC6();
}

void changeTC_Pin3_Period(unsigned int period){
  stop_TC7();
  REG_TC2_RC1=period;
  start_TC7();
}

void changeTC_Pin11_Period(unsigned int period){
  stop_TC8();
  REG_TC2_RC2=period;
  start_TC8();
}

void (*TC2_CallBack)();
void (*TC3_CallBack)();
void (*TC4_CallBack)();
void (*TC5_CallBack)();

void TC2_Handler() {
  TC_GetStatus(TC0, 2);
  TC2_CallBack();
}
void TC3_Handler() {
  TC_GetStatus(TC1, 0);
  TC3_CallBack();
}
void TC4_Handler() {
  TC_GetStatus(TC1, 1);
  TC4_CallBack();
}
void TC5_Handler() {
  TC_GetStatus(TC1, 2);
  TC5_CallBack();
}

void setupTC2_Interrupt(unsigned int period, byte tcClock, void (*isr)()){
  pmc_set_writeprotect(false);                    // Enavle direct TC register manipulation
  pmc_enable_periph_clk(TC2_IRQn);                // Enable predefined interrupt handler
  TC2_CallBack=isr;                               // Route the call to user interrupt handler
  REG_TC0_CMR2=getTC_Waveform(tcClock);           // Update Command Register
  REG_TC0_RC2=period;                             // Set period (1 - 0xFFFF)
  start_TC2();                                    // Start timer and generate square wave
  REG_TC0_IER2= TC_IER_CPCS;                      // Enable RC compare interrupt
  REG_TC0_IDR2=~TC_IER_CPCS;                      // Disable all other timer interrpts 
  NVIC_EnableIRQ(TC2_IRQn);                       // Enable interrupt vector
}

void setupTC3_Interrupt(unsigned int period, byte tcClock, void (*isr)()){
  pmc_set_writeprotect(false);                    // Enavle direct TC register manipulation
  pmc_enable_periph_clk(TC3_IRQn);                // Enable predefined interrupt handler
  TC3_CallBack=isr;                               // Route the call to user interrupt handler
  REG_TC1_CMR0=getTC_Waveform(tcClock);           // Update Command Register
  REG_TC1_RC0=period;                             // Set period (1 - 0xFFFF)
  start_TC3();                                    // Start timer and generate square wave
  REG_TC1_IER0= TC_IER_CPCS;                      // Enable RC compare interrupt
  REG_TC1_IDR0=~TC_IER_CPCS;                      // Disable all other timer interrpts 
  NVIC_EnableIRQ(TC3_IRQn);                       // Enable interrupt vector
}

void setupTC4_Interrupt(unsigned int period, byte tcClock, void (*isr)()){
  pmc_set_writeprotect(false);                    // Enavle direct TC register manipulation
  pmc_enable_periph_clk(TC4_IRQn);                // Enable predefined interrupt handler
  TC4_CallBack=isr;                               // Route the call to user interrupt handler
  REG_TC1_CMR1=getTC_Waveform(tcClock);           // Update Command Register
  REG_TC1_RC1=period;                             // Set period (1 - 0xFFFF)
  start_TC4();                                    // Start timer and generate square wave
  REG_TC1_IER1= TC_IER_CPCS;                      // Enable RC compare interrupt
  REG_TC1_IDR1=~TC_IER_CPCS;                      // Disable all other timer interrpts 
  NVIC_EnableIRQ(TC4_IRQn);                       // Enable interrupt vector
}

void setupTC5_Interrupt(unsigned int period, byte tcClock, void (*isr)()){
  pmc_set_writeprotect(false);                    // Enavle direct TC register manipulation
  pmc_enable_periph_clk(TC5_IRQn);                // Enable predefined interrupt handler
  TC5_CallBack=isr;                               // Route the call to user interrupt handler
  REG_TC1_CMR2=getTC_Waveform(tcClock);           // Update Command Register
  REG_TC1_RC2=period;                             // Set period (1 - 0xFFFF)
  start_TC5();                                    // Start timer and generate square wave
  REG_TC1_IER2= TC_IER_CPCS;                      // Enable RC compare interrupt
  REG_TC1_IDR2=~TC_IER_CPCS;                      // Disable all other timer interrpts 
  NVIC_EnableIRQ(TC5_IRQn);                       // Enable interrupt vector
}

void changeTC2_Period(unsigned int period) {
  stop_TC2();
  REG_TC0_RC2=period;
  start_TC2();
}

void changeTC3_Period(unsigned int period) {
  stop_TC3();
  REG_TC1_RC0=period;
  start_TC3();
}

void changeTC4_Period(unsigned int period) {
  stop_TC4();
  REG_TC1_RC1=period;
  start_TC4();
}

void changeTC5_Period(unsigned int period) {
  stop_TC5();
  REG_TC1_RC2=period;
  start_TC5();
}

garygid

OllieK,
Thanks a bunch for sharing, I am going to try
your "library" asap.
Cheers, Gary
Cheers, Gary
Due for controlling Electric car charging.
Nissan LEAF - Mini Quick Charge (mQC)

OllieK

Gary,

I am still new in Arduino development community and learning the right ways to collaborate with other developers.  Since I published the three DueTC files here in four messages, I did open my GitHub account.  The easiest way to get the involved files is to download them from

https://github.com/OliviliK/DueTC

In that place, I will update the library based on the comments from other developers.

Cheers, Ollie

garygid

Thanks,
I got it from here, and set up one interrupt for 2 ms, and
it seems to work fine.
I will send you my "cleaned up" version later, if you wish.
Cheers, Gary
Cheers, Gary
Due for controlling Electric car charging.
Nissan LEAF - Mini Quick Charge (mQC)

kohlmeise

Thanks a lot Ollie,

I will also give it a try !

Go Up