[SAMD21] TCC - Periodically generate two sequential pulses? ("PWM" with two pulses?)

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I need is to generate a waveform of the following shape with very precise timing:

+----+       +----+                  +----+       +----+
|    |       |    |                  |    |       |    |
|    |       |    |                  |    |       |    |
|    |       |    |                  |    |       |    |     
+    +-------+    +------------------+    +-------+    +------------------

I've been staring at the TCC section of the datasheet for hours but there's tons of functionality, and I can't figure out what I need, or if it is even possible to do what I want.

 

How would you go about doing this?

Last Edited: Fri. Oct 18, 2019 - 09:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very precise but completely unknown timing?

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which processor? How precise? Exact description of the pulse sequence (period sequence, pulse width and positions within the sequence), which parameters need to be exact?

If one defines a problem it's half way to being solved

The best way to get exact timing is to use events, they are independent of interrupt service times. Look at the TCC descriptions

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which processor?

I am using the SAM D21 family ATSAMD21G18, as indicated in the topic title and tags.

 

How precise? Exact description of the pulse sequence (period sequence, pulse width and positions within the sequence), which parameters need to be exact?

Since you asked, the two pulses need to have an identical duration of around 100 nanoseconds. The exact duration is not particularly important, but it needs to be consistent. The time between pulses is configurable and in the order of 5-100 microseconds, while the duration of an entire cycle is configurable and in the order of 1-10 milliseconds.

 

The best way to get exact timing is to use events, they are independent of interrupt service times.

 

Thank you for suggesting events, although I did look into them. As far as I am aware there is not a way to directly toggle a pin in PORT using the event system - DMA may be an option, but it adds complexity and, if my understanding is correct, a potentially inconsistent APB bus delay that may be acceptable for my application but I'd rather do without.

 

I feel there's likely a cleaner solution using the TCC's waveform output. I'm looking at updating CC registers using DMA, though I am not yet sure whether this is a good way to do it or even if it will work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a short suggestion in general terms. I leave the code generation to you

No guarantee for correctness!

You could use TCC0. The period is determined by the CC0 value and setting TCC0->WAVE.WAVEGEN = MFRQ, see the description of this field in the datasheet. Set the pulse positions using the MC1 and MC2 values with MC2 > MC1

Set up TCC0 so that when the COUNT register reaches either of the MC1 or MC2 values it generates an event.

The event user is TC3, which is set up as follows:

Use a clock frequency of 10MHz or a multiple thereof so that the pulse length of 100ns is possible

The event action is START, we use the output WO[1] for the pulse output

TC3 is set up to run in NFRQ mode (see section 30.6.2.6.2 of the datasheet). The value of CC1 (must not be 0) determines the delay between the event from TCC0 and the rising flank of WO[1]

The value of MC0 - MC1 determines the pulse length, at the end of the pulse the COUNT value returns to 0, and TC3 waits until the next event is generated by TCC0

Sequence:

  • TCC0 starts at COUNT=0
  • Generates an event after TCC0->MC1 TCC0 clock pulses
  • After a further delay of TC3->MC1 clock pulses the WO[1] output is logical 1
  • W0[1] remains high for TC3->MC0 - TC3->MC1 TC3 clock pulses
  • At TCC0->MC2 TCC0 clock cycles after the start the same WO[1] pulse as above is generated
  • TCC0->COUNT clocks upwards until a value of TCC0->CC0 and recycles to 0
  • The sequence repeats

 

 

The pulse times are uncertain by event synchronisation delays - may be about 2 CPU clock periods

Hope this is correct!

 

Best wishes, Jerry

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, it turns out the TCC has a circular buffering feature which makes it very easy to generate the pulse I wanted.

 

When WAVE.CIPEREN is set*, PER and PERB are switched on every update condition - meaning when the counter has counted up to PER (or counted down to zero, depending on how the TCC was configured).

 

The gist of it is that I just switch between the times between pulses. If I wanted to do three pulses I am almost certain I would require DMA, but luckily I don't need to. Because I need to do a tad more than just generate the output waveform, I still had to use DMA for some other stuff, but at least this way I could get a waveform simply and with clean timings!

 

* and control B's LUPD is not set