{"id":22566,"date":"2024-11-02T15:38:05","date_gmt":"2024-11-02T15:38:05","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/?p=22566"},"modified":"2024-12-01T17:18:03","modified_gmt":"2024-12-01T17:18:03","slug":"tinyavr-series-part-2-timer-a-b-ccl-slpctrl","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl","title":{"rendered":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this Post<\/h2>\n\n<p>This is the second part of my article about the tinyAVR series 0, 1 and 2. <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1\" target=\"_blank\" rel=\"noopener\">In the first part<\/a> I explained how register programming for the tinyAVR series works in principle and went into some modules. This sequel deals with Timers A and B, the Configurable Custom Logic (CCL) and the Sleep Control Module (SLPCTRL). Timer D, which is used in the tinyAVR Series 1, is still missing. I will deal with this in the third part.   <\/p>\r\n<p>Here is an overview and links to all topics:<\/p>\r\n<ul>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#reg_programming_tinyavr\" target=\"_blank\" rel=\"noopener\">Register programming of the tinyAVR series (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#portx_module\" target=\"_blank\" rel=\"noopener\">I\/O control &#8211; PORTx module (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#portmux_module\">Reassigning inputs \/ outputs &#8211; PORTMUX module (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#evsys_module\" target=\"_blank\" rel=\"noopener\">The Event System &#8211; EVSYS module (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#rtc_module\" target=\"_blank\" rel=\"noopener\">Real-Time Counter &#8211; RTC module (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#wdt_module\" target=\"_blank\" rel=\"noopener\">Watchdog Timer &#8211; WDT module (Part 1)<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#adc_module\" target=\"_blank\" rel=\"noopener\">A\/D Converter &#8211; ADCn module (Part 1)<\/a><\/li>\r\n<li><a href=\"#timer_a\">Timer A &#8211; TCAn module<\/a> <\/li>\r\n<li><a href=\"#timer_b\">Timer B &#8211; TCBn module<\/a> <\/li>\r\n<li><a href=\"#ccl_module\">Configurable Custom Logic &#8211; CCL module<\/a><\/li>\r\n<li><a href=\"#slpctrl_module\">The tinyAVR MCUs go to sleep &#8211; SLPCTRL module<\/a><\/li>\r\n<li><a href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-3-timer-d\" target=\"_blank\" rel=\"noopener\">Timer D &#8211; TCDn module (Part 3)<\/a><\/li>\r\n<\/ul>\r\n\n<h2 class=\"wp-block-heading\" id=\"timer_a\">Timer A &#8211; TCAn module<\/h2>\n\n<p>First, a few general comments on Timer A:<\/p>\r\n<ol>\r\n<li>All representatives of the tinyAVR series have exactly one Timer A (TCA0).<\/li>\r\n<li>TCA0 can be operated as a 16-bit timer (single mode) or split into two 8-bit Timers (split mode).<\/li>\r\n<li>TCA0 is coupled to the system clock, but it can be slowed down with a divider (prescaler) in the TCA0.SINGLE.CTRLA or TCA.SPLIT.CTRLA register.<\/li>\r\n<li>In the default setting of the megaTinyCore board package, the TCA0 prescaler is set to 64. In addition, the Timer A is in split mode to get the maximum number of PWM pins. Changes to the settings can affect the PWM function accordingly. In addition, the representatives of the tinyAVR 0 series use TCA0 for <code>millis()<\/code>, <code>micros()<\/code> and <code>delay()<\/code> by default. Changes to the prescaler make these functions unusable. However, you can assign <code>millis()<\/code> \/ <code>micros()<\/code> to other Timers or deactivate them (Arduino IDE \u2192 Tools).     <\/li>\r\n<li>TCA0 counts up to the maximum value PER in Normal (Single) Mode. Three compare channels are available.  The Compare Values are CMP0, CMP1 and CMP2.<\/li>\r\n<li>In Split Mode, the 16-bit Timer A turns into two 8-bit Timers with 3 compare values each. With this, you can generate up to 6 PWM outputs. The PWM frequency is identical for each of the three outputs.  <\/li>\r\n<li>You address the registers for the Normal Mode with TCA0.SINGLE.<em>registername<\/em>, and the registers for Split Mode with TCA0.SPLIT.<em>registername<\/em>.<\/li>\r\n<\/ol>\r\n<p>This is an ultra-short summary. I recommend reading the documentation by Spence Konde on the subject of <a href=\"https:\/\/github.com\/SpenceKonde\/megaTinyCore\/blob\/master\/megaavr\/extras\/Ref_Timers.md#pwm-and-timers-on-modern-avrs-and-their-usage-in-this-core\" target=\"_blank\" rel=\"noopener\">Timers and PWM<\/a>. <\/p>\r\n\n<h3 class=\"wp-block-heading\">Timer A Registers for Normal (Single) Mode<\/h3>\n\n<p>Some registers are identical in Normal and Split Mode. I have highlighted this accordingly.<\/p>\r\n<p>This article is not a complete register documentation, but rather a starting aid. It is best to consult the data sheet at the same time. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Control A Register TCAn.CTRLA<\/h4>\n\n<p>In the Control Register CTRLA you set the clock divider and enable Timer Counter A.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla-1024x77.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"77\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla-1024x77.png\" alt=\"tinyAVR - TCAn.CTRLA Register\" class=\"wp-image-22223\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla-1024x77.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla-300x22.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla-768x58.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/reg_tca_ctrla.png 1254w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCAn.CTRLA Register<\/figcaption><\/figure>\n\n<p>The CLKSEL (Clock Select) bit group defines the divider. The following bit group configuration masks are available for selection:<\/p>\r\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_CLKSEL_options.png\"><img loading=\"lazy\" decoding=\"async\" width=\"702\" height=\"329\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_CLKSEL_options.png\" alt=\"tinyAVR - CLKSEL Options for TCA0\" class=\"wp-image-19087\" style=\"aspect-ratio:2.127659574468085;object-fit:cover;width:496px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_CLKSEL_options.png 702w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_CLKSEL_options-300x141.png 300w\" sizes=\"auto, (max-width: 702px) 100vw, 702px\" \/><\/a><figcaption class=\"wp-element-caption\">CLKSEL &#8211; Options<\/figcaption><\/figure>\n<\/div>\n<p>Use the ENABLE bit to enable TCA0. You can check the setting of CTRLA with <code>Serial.println(TCA0.SPLIT.CTRLA, BIN)<\/code>. The output should be 0b1011, i.e. the Timer A is enabled, and the divider is 64, so you do not need to enable the timer yourself. And once again: When using the megaTinyCore package, you must be aware of the side effects when changing the TCA0 settings.<\/p>\r\n\n<p><strong>The RUNSTDBY bit is only available for the tinyAVR series 2<\/strong>. If you set it, you send the Timer\/Counter A into standby mode. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Control B Register TCAn.CTRLB<\/h4>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB-1024x83.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"83\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB-1024x83.png\" alt=\"TCAn.CTRLB Register\" class=\"wp-image-19074\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB-1024x83.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB-300x24.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB-768x62.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLB.png 1236w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCAn.CTRLB Register<\/figcaption><\/figure>\n\n<p>You set the Compare-n-Enable bits (CMPnEN) to activate the Compare Channel outputs. You can find out where the outputs are located in the &#8220;I\/O Multiplexing and Considerations&#8221; section of the data sheet. The outputs are called WOx and correspond to CMPx. In some cases, the outputs can be assigned to alternative pins (PORTMUX module). However, not all tinyAVR representatives have all outputs (and the alternatives) actually implemented as pins.    <\/p>\r\n<p>I will not go into the Auto Lock Update Bit (ALUPD) here. The bit group WGMODE[2:0] defines the Wave Form Generation Mode:<\/p>\r\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1106\" height=\"352\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES.png\" alt=\"tinyAVR series: WGMODE options for TCA0 in Normal Mode\" class=\"wp-image-19093\" style=\"aspect-ratio:3.1578947368421053;object-fit:cover;width:722px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES.png 1106w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES-300x95.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES-1024x326.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_WGMODES-768x244.png 768w\" sizes=\"auto, (max-width: 1106px) 100vw, 1106px\" \/><\/a><figcaption class=\"wp-element-caption\">Wave Form Generation Mode Options<\/figcaption><\/figure>\n<\/div>\n<h4 class=\"wp-block-heading\">Control D Register TCAn.CTRLD<\/h4>\n\n<p>The Split Mode is set in the Control D register. It is not relevant whether you make the setting via TCA0.SINGLE.CTRLD or TCA0.SPLIT.CTRLD.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD-1024x78.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"78\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD-1024x78.png\" alt=\"tinyAVR Register: TCAn.SINGLE.CTRLD\" class=\"wp-image-19078\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD-1024x78.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD-300x23.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD-768x58.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_CTRLD.png 1249w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register TCAn.SINGLE.CTRLD \/ TCAn.SPLIT.CTRLD<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Interrupt Control Register TCAn.INTCTRL<\/h4>\n\n<p>In the Interrupt Control register, you define which interrupts are to be activated. Interrupts are available for Compare Matches and Overflow:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL-1024x79.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"79\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL-1024x79.png\" alt=\"tinyAVR Register: TCAn.SINGLE.INTCTRL \/ TCAn.SINGLE.INTFLAGS\" class=\"wp-image-19076\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL-1024x79.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL-300x23.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL-768x60.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/Reg_TCA_INTCTRL.png 1251w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCAn.SINGLE.INTCTRL \/ TCAn.SINGLE.INTFLAGS<\/figcaption><\/figure>\n\n<p>The Interrupt Flag Register INTFLAGS is similar to INTCTRL and uses the same bit names and positions.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Event Control Register TCAn.EVCTRL<\/h4>\n\n<p>You can set Timer A so that it is not controlled by the system clock but by external events. To do this, set the &#8220;Enable Count On Event Input&#8221; bit CNTEI in the Event Control Register EVCTRL.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL-1024x89.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"89\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL-1024x89.webp\" alt=\"tinyAVR Register: TCAn.SINGLE.EVCTRL\" class=\"wp-image-19221\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL-1024x89.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL-300x26.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL-768x66.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_EVCTRL.webp 1259w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCAn.SINGLE.EVCTRL<\/figcaption><\/figure>\n\n<p>You can use the Bit Group Configuration EVACT to determine which events are counted and how they are counted:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1148\" height=\"263\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table.webp\" alt=\"EVACT Bit Group Configurations\" class=\"wp-image-19214\" style=\"width:746px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table.webp 1148w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table-300x69.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table-1024x235.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCA0_EVCTRL_EVACT_table-768x176.webp 768w\" sizes=\"auto, (max-width: 1148px) 100vw, 1148px\" \/><\/a><figcaption class=\"wp-element-caption\">EVACT Bit Group Configurations<\/figcaption><\/figure>\n\n<p>With the first two settings, you count the edges, i.e. the number of events. With the other two settings, the system clock (with divider if necessary) is used to count for as long as the state caused by the event lasts.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Further Registers<\/h4>\n\n<p>Then there are a number of other registers that only contain numbers:<\/p>\r\n<ul>\r\n<li><strong>CNT<\/strong> (16 bit): is the Counter Register for Timer A.<\/li>\r\n<li><strong>PER<\/strong> (16 bit): is the TOP value for most Wave Form Generation Modes.<\/li>\r\n<li><strong>CMP0<\/strong>, <strong>CMP1<\/strong>, <strong>CMP2<\/strong> (16 bit): contain the Compare Values.<\/li>\r\n<li><strong>PERBUF<\/strong>: you can write PER directly to the PER register. Under certain circumstances, however, an immediate change of PER (e.g. in the middle of a PWM period) is undesirable. If you write PER in PERBUF, the new PER is only applied when the old PER is reached.  <\/li>\r\n<li><strong>CMP0BUF<\/strong>, <strong>CMP1BUF<\/strong>, <strong>CMP2BUF<\/strong>: see PERBUF.<\/li>\r\n<\/ul>\r\n\n<p>In Normal (Single) Mode, the Timer\/Counter A has a size of 16 bits. However, it can also be split into two 8-bit Timers (Split Mode).  In Normal Mode there are three Compare Channels available, in Split Mode there are six. Accordingly, 3 or 6 PWM outputs can be realized using Timer A (provided the output pins are available).<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example sketches for Timer A in Normal Mode<\/h3>\n\n<p>After all the theory, let&#8217;s have some example sketches.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Overflow Interrupt<\/h4>\n\n<p>We start quite simply with an Overflow Interrupt. We use this to toggle an LED attached to PA2.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_a_simple_ovf_interrupt.ino\" data-enlighter-title=\"timer_a_simple_ovf_interrupt.ino\">ISR(TCA0_OVF_vect){  \/\/ ISR for Timer A overflow\r\n    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; \/\/ Clear the interrupt flag (needed!)\r\n    PORTA.OUTTGL = PIN2_bm; \/\/ Toggle PA2 \r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN2_bm; \/\/ PA2 auf OUTPUT\r\n    TCA0.SINGLE.CTRLD = 0; \/\/ change to Single Mode\r\n    TCA0.SINGLE.PERBUF = 62499; \/\/ Set TOP for Timer A \r\n    \/\/ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV64_gc | TCA_SINGLE_ENABLE_bm; \/\/ redundant\r\n    TCA0.SINGLE.CTRLB = 0; \/\/ no output, wave form: normal;\r\n    TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; \/\/ enable Timer A overflow interrupt\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<p>With a clock rate of 20 MHz, a divider of 64 and a PER of 62499 (= 62500 steps), the overflow frequency is 20000000 \/ (64 * 62500) = 5 Hz.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Single Slope PWM<\/h4>\n\n<p>In the next example, we generate a PWM signal with a frequency of 250 Hz and a duty cycle of 20% at WO2 (output for CMP2). You can find out which pin WO2 is assigned to in the data sheet. We achieve the 250 Hz by setting PER to 1249 (at 20 MHz).   The duty cycle is CMPn \/ (PER +1).<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_a_single_slope_pwm.ino\" data-enlighter-title=\"timer_a_single_slope_pwm.ino\">void setup() {\r\n    PORTB.DIRSET = PIN2_bm;  \/\/ PB2 = WO2 for many tinyAVR MCUs, please adjust if necessary!\r\n    TCA0.SINGLE.CTRLD = 0; \r\n    \/\/ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV64_gc | TCA_SINGLE_ENABLE_bm; \/\/ redundant\r\n    TCA0.SINGLE.PERBUF = 1249;\r\n    TCA0.SINGLE.CMP2BUF = 250;\r\n    TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<p>On an ATtiny202\/402, WO2 is assigned to pin PA2 (just as an example). Accordingly, you need to replace PORTB with PORTA in the example. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Frequency Mode<\/h4>\n\n<p>In Frequency Mode, the TCA0 Counter counts up to CMP0 instead of PER. When CMP0 is reached, the CMP0 output (WO0) is toggled. This sets the duty cycle in this mode to 50&nbsp;%.   Here is a small example:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_a_single_frq_pwm.ino\" data-enlighter-title=\"timer_a_single_frq_pwm.ino\">void setup() {\r\n    PORTB.DIRSET = PIN0_bm;  \/\/ PB0 = WO0 for many tinyAVR MCUs, please adjust if necessary!\r\n    TCA0.SINGLE.CTRLD = 0; \r\n    TCA0.SINGLE.CMP0 = 1249;\r\n    TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc;\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<p>At 20 MHz, the toggle frequency is 250 Hz, i.e. the PWM frequency is 125 Hz.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Dual Slope Modes<\/h4>\n\n<p>In Dual Slope Modes, TCA0.CNT counts up from 0 to PER and then back down to 0. In the event of a Compare Match when counting up, the CMPx output goes LOW and when counting down it goes HIGH. As a result, the PWM frequency is halved compared to single slope mode.  <\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setup() {\r\n    PORTB.DIRSET = PIN0_bm;  \/\/ PB0 = WO0 for many tinyAVR MCUs, please adjust if necessary!\r\n    TCA0.SINGLE.CTRLD = 0; \r\n    \/\/ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV64_gc | TCA_SINGLE_ENABLE_bm; \/\/ redundant\r\n    TCA0.SINGLE.PERBUF = 1249;\r\n    TCA0.SINGLE.CMP0BUF = 250;\r\n    TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_DSBOTTOM_gc;\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<p>The only difference between the WG modes DSTOP, DSBOTTOM&nbsp; and DSBOTH is their Overflow behavior. In the case of DSTOP, the Overflow is reached at PER, for DSBOTTOM it is 0 and for DSBOTH at 0 and PER. The PWM signal is identical for all Dual Slope Modes, provided that all other parameters are also identical.  <\/p>\r\n\n<h4 class=\"wp-block-heading\">Counting Events<\/h4>\n\n<p>In this example, we control Timer A via events. I have written the sketch for the ATtiny1614. Since the Event Modules of the different tinyAVR series differ quite a lot from each other (see <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/programming-the-tinyavr-series-0-1-2-part-1#evsys_module\" target=\"_blank\" rel=\"noopener\">part 1<\/a> of the article), some adjustments may be necessary for the tinyAVR representative of your choice (good practice!).  <\/p>\r\n<p>A rising edge at PB1 serves as an event here. To do this, connect PB1 to GND via a push-button. PB1 is pulled to HIGH level via the internal pull-up resistor. The event is therefore generated when the button is released. You can also invert the logic, but then you will need an additional external pull-down resistor.<\/p>\r\n<p>The sketch informs us when the button has been pressed 10 or 20 times:<\/p>\r\n\n<div class=\"scroll-paragraph\">\r\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_a_single_event_count.ino\" data-enlighter-title=\"timer_a_single_event_count.ino\">volatile bool tca0Ovf = false;  \/\/ Flag for TCA OVF\r\nvolatile bool cmp0Match = false;  \/\/ Flag for CMP0 Match\r\n\r\nISR(TCA0_OVF_vect){  \/\/ TCA0 Overflow ISR\r\n    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; \/* Clear the interrupt flag *\/\r\n    tca0Ovf = true;\r\n}\r\n\r\nISR(TCA0_CMP0_vect){  \/\/ TCA0\/CMP0 compare match ISR\r\n    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm; \/* Clear the interrupt flag *\/\r\n    cmp0Match = true;\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    PORTB.DIRCLR = PIN1_bm; \/\/ PB1 as input \r\n    PORTB.PIN1CTRL = PORT_PULLUPEN_bm; \/\/ Pullup enable\r\n    EVSYS.SYNCCH1 = EVSYS_SYNCCH1_PORTB_PIN1_gc; \/\/ PB1 is sync. event generator\r\n    EVSYS.SYNCUSER0 = EVSYS_SYNCUSER0_SYNCCH1_gc;  \/\/ TCA0 is sync. event user\r\n    TCA0.SINGLE.CTRLD = 0; \/\/ set single mode\r\n    TCA0.SINGLE.CTRLA = 0;  \/\/ switch off the timer, set clock divider to DIV1 \r\n    TCA0.SINGLE.PER = 19;  \/\/ TCA0 counter limit\r\n    TCA0.SINGLE.CMP0 = 9;  \/\/ Compare match value\r\n    TCA0.SINGLE.CNT = 0;  \/\/ Set TCA0 counter to 0\r\n    TCA0.SINGLE.EVCTRL = TCA_SINGLE_EVACT_POSEDGE_gc | TCA_SINGLE_CNTEI_bm; \/\/ count pos. edge of events (RISING) &amp; enable event count\r\n    TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc; \/\/ normal mode =&gt; TOP = PER\r\n    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; \/\/ clear the overflow interrupt flag\r\n    TCA0.SINGLE.INTCTRL = TCA_SINGLE_CMP0_bm | TCA_SINGLE_OVF_bm; \/\/ enable CMP0 and OVF interrupts \r\n    TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm;\r\n}\r\n\r\nvoid loop(){\r\n    if(cmp0Match){\r\n        Serial.println(\"Key has been pressed 10 times\");\r\n        cmp0Match = false;\r\n    }\r\n    \r\n    if(tca0Ovf){\r\n        Serial.println(\"Key has been pressed another 10 times\");\r\n        Serial.println(\"Timer\/Counter A restarts\");\r\n        tca0Ovf = false;\r\n    }\r\n    \/\/ Serial.println(TCA0.SINGLE.CNT);  \/\/ uncomment to see the TCA0 Counter\r\n    \/\/delay(100); \r\n}<\/pre>\r\n<p>&nbsp;<\/p>\r\n<\/div>\r\n\n<p>I have tried to explain the code in the comments. I hope that is sufficiently understandable. However, a few annotations are still necessary:<\/p>\r\n<ul>\r\n<li>We switch off Timer A so that it does not disturb us during the settings.<\/li>\r\n<li>We are informed via Compare 0 Interrupt and Overflow Interrupt when the button has been pressed ten or twenty times.\r\n<ul>\r\n<li>The interrupts are only triggered when CMP0 and PER are <em>exceeded<\/em>. This is why CMP0 is 9 and PER is 19.<\/li>\r\n<\/ul>\r\n<\/li>\r\n<li>Setting the Compare 0 Register and the PER Register via the Buffer Registers (CMP0BUF, PERBUF) is not suitable here. You would have to press the button repeatedly until you reach the previously set PER. Only then will the new PER be cpoied from PERBUF. This can take a long time with a 16-bit counter!   <\/li>\r\n<li>Because of the button bounce, you probably have to press the button less than ten times to reach the limits.<\/li>\r\n<\/ul>\r\n\n<h3 class=\"wp-block-heading\">Timer A Register in Split Mode<\/h3>\n\n<p>In Split Mode, Timer A is divided into a high and a low section. Accordingly, the 16-bit CNT register is split into an 8-bit HCNT and an 8-bit LCNT register. These two counter registers count in the same clock, but independently of each other.  The PER register and the Compare registers are also split. PER becomes HPER and LPER, CMPn becomes HCMPn and LCMPn and so on.<\/p>\r\n\n<p>The outputs for Timer A in Split Mode are activated in the Control B register (TCA0.SPLIT.CTRLB):<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1-1024x86.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"86\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1-1024x86.png\" alt=\"tinyAVR Register: TCAn.SPLIT.CTRLB\" class=\"wp-image-19113\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1-1024x86.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1-300x25.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1-768x65.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_CTRLB_SPLIT-1.png 1238w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register TCAn.SPLIT.CTRLB<\/figcaption><\/figure>\n\n<p>The LCMPnEN bits are responsible for the WOn outputs, the HCMPnEN bits for the WO(n+2) outputs.<\/p>\r\n\n<p>You can set interrupts for the Low Compare Channels in the Control D register. No interrupts are available for the high Compare Channels.<\/p>\r\n<p>In Split Mode, the HCNT and LCNT registers count downwards. Accordingly, there are no Overflow Interrupts, but Underflow Interrupts (&#8220;UNF&#8221;). The bits for activating the interrupts are HUNF and LUNF.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT-1024x87.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"87\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT-1024x87.png\" alt=\"tinyAVR Register: TCAn.SPLIT.CTRLB\" class=\"wp-image-19111\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT-1024x87.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT-300x26.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT-768x65.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCA_INTCTRL_SPLIT.png 1258w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register TCAn.SPLIT.CTRLB<\/figcaption><\/figure>\n\n<p>The corresponding names of the Interrupt Vectors are created according to the scheme <em>TCA0_Interruptbit_vector<\/em>, e.g. TCA0_LCMP1_vector.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example sketch for Timer A in Split Mode<\/h3>\n\n<p>Let us try Timer A in Split Mode. The aim is to generate a PWM signal with a duty cycle of 25% at WO3 (HCMP0). The high part of the Counter Register of Compare Channel 0 is responsible for this. WO3 should be assigned to PA3 for all tinyAVR representatives. But if in doubt, check this. I have not looked at every data sheet!     <\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_a_split_mode_pwm.ino\" data-enlighter-title=\"timer_a_split_mode_pwm.ino\">void setup() {\r\n    PORTA.DIRSET = PIN3_bm;  \/\/ PA3 = WO3 for many tinyAVR MCUs, please adjust\r\n    TCA0.SPLIT.CTRLD = TCA_SPLIT_SPLITM_bm; \/\/ needed for the Arduino board package\r\n    TCA0.SPLIT.HPER = 255; \/\/ PWM frequency = 20 MHz\/(64 * 256) = ~1.22 kHz\r\n    TCA0.SPLIT.HCMP0 = 64; \/\/ Duty cycle = 64 \/ (255 + 1) * 100 = 25 %\r\n    TCA0.SPLIT.CTRLA = TCA_SPLIT_CLKSEL_DIV64_gc | TCA_SPLIT_ENABLE_bm; \/\/ redundant for megaTinyCore\r\n    TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP0EN_bm; \/\/ enable output HCMP0 (WO3)\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<h2 class=\"wp-block-heading\" id=\"timer_b\">Timer B &#8211; TCBn Module<\/h2>\n\n<p>The tinyAVR MCUs have either one or two 16-bit Timers B (TCB0 \/ TCB1):<\/p>\r\n<ul>\r\n<li><strong>0-series<\/strong>: 1 Timer B<\/li>\r\n<li><strong>1-series up to 8 kB Flash<\/strong>: 1 Timer B<\/li>\r\n<li><strong>1-series from 16 kB Flash<\/strong>: 2 Timer B<\/li>\r\n<li><strong>2-series<\/strong>: 2 Timer B<\/li>\r\n<\/ul>\r\n<p>The megaTinyCore board package uses Timer(s) B for <code>millis()<\/code>, <code>micros()<\/code>, <code>delay()<\/code>, <code>tone()<\/code> or the Servo. Changes to the TCBn settings can render these functions unusable. However, you can also assign some of the functions to other timers. Look in the Arduino IDE under the menu item &#8220;Tools&#8221;.   <\/p>\r\n<p>You can find out to which pins the outputs for the TCBn Compare Matches are assigned and which alternatives are available in the data sheet under &#8220;I\/O Multiplexing and Considerations&#8221;. Unfortunately, the designation of the outputs is inconsistent. For example, you will find &#8220;TCBn WO&#8221;, &#8220;n, WO&#8221; or &#8220;WOn&#8221;. You can assign outputs to alternative pins via the PORTMUX module.   <\/p>\r\n\n<h3 class=\"wp-block-heading\">Timer B Registers<\/h3>\n\n<p>Here, too, I would first like to point out once again that my article does not cover all available registers.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Control A Register TCBn.CTRLA<\/h4>\n\n<p>The most important settings in the Control A registers of Timer B are the clock rate (CLKSEL[2:0]) and ENABLE. The system clock, the system clock divided by two or the clock of Timer A can be selected as clock source.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example-1024x268.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"268\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example-1024x268.png\" alt=\"tinyAVR Register: TCBn.CTRLA\" class=\"wp-image-19060\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example-1024x268.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example-300x78.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example-768x201.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/10\/TCBn_CTRLA_example.png 1266w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register TCBn.CTRLA<\/figcaption><\/figure>\n\n<p>The default setting in the megaTinyCore package for CLKSEL is CLKTCA, i.e. the system clock with a divider of 64 is used. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Control B Register TCBn.CTRLB<\/h4>\n\n<p>In the Control B Register, you specify one of the eight Count Modes that make Timer B a versatile tool. I will only list the Count Modes here for now, as they are best explained using the following examples. <\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1-1024x81.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"81\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1-1024x81.png\" alt=\"tinyAVR Register TCBn.CTRLB\" class=\"wp-image-19131\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1-1024x81.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1-300x24.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1-768x60.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_CTRLB-1.png 1181w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register TCBn.CTRLB<\/figcaption><\/figure>\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1033\" height=\"327\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE.png\" alt=\"CTNMODE[2:0] Bit Group Configurations\" class=\"wp-image-19124\" style=\"aspect-ratio:3.1604938271604937;width:641px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE.png 1033w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE-300x95.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE-1024x324.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/TCB_CTRLB_CNTMODE_TABLE-768x243.png 768w\" sizes=\"auto, (max-width: 1033px) 100vw, 1033px\" \/><\/a><figcaption class=\"wp-element-caption\">CTNMODE[2:0] Bit Group Configurations<\/figcaption><\/figure>\n\n<p>The other bits have the following effect:<\/p>\r\n<ul>\r\n<li>ASYNC (Asynchronous Enable): allows asynchronous updates of the TCB output signal in Single Shot Mode.<\/li>\r\n<li>CCMPINIT (Compare \/ Capture Pin Initial Value): sets the initial level of the output pin (0 = LOW, 1 = HIGH).<\/li>\r\n<li>CCMPEN (Compare \/ Capture Output Enable): activates the Compare \/ Capture Output. In contrast to timer A, there is only one compare output per Timer B.<\/li>\r\n<\/ul>\r\n\n<h4 class=\"wp-block-heading\">Interrupt Control Register TCBn.INTCTRL <\/h4>\n\n<p>The Interrupt Control Register is simple. You can activate the Capture Interrupt there, that&#8217;s all. The condition for triggering the interrupt depends on the Count Mode. I will come back to this in the examples. You can find an overview in the data sheet in the register description of TCBn.INTFLAGS.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL-1024x87.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"87\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL-1024x87.png\" alt=\"tinyAVR Register: TCBn.INTCTRL\" class=\"wp-image-19126\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL-1024x87.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL-300x25.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL-768x65.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_INTCTRL.png 1204w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCBn.INTCTRL \/ TCBn.INTFLAGS<\/figcaption><\/figure>\n\n<p>The Interrupt Vector is called TCBn_INT_vect and not &#8211; as one would expect &#8211; TCBn_CAPT_vect. That&#8217;s a bit confusing.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Event Control Register TCBn.EVCTRL<\/h4>\n\n<p>The effect of the EDGE bit in the Event Control Register EVCTRL also depends on the Count Mode. Wait for the examples or have a look at the overview in the data sheet in the register description of TCBn.EVTCTRL.<\/p>\r\n<p>The FILTER bit activates a noise filter that ensures that the event status must be constant for four clock cycles before the event is considered valid.<\/p>\r\n<p>The Capture Event Input Enable Bit CAPTEI activates the Input Capture Event. In contrast to Timer A, Timer B cannot count edges (events), but the edge starts or stops the counter.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL-1024x87.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"87\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL-1024x87.png\" alt=\"tinyAVR Register: &#13;&#10;TCBn.EVCTRL\" class=\"wp-image-19122\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL-1024x87.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL-300x25.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL-768x65.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_TCB_EVCTRL.png 1193w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">TCBn.EVCTRL<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Further registers <\/h4>\n\n<p>The 16-bit register CNT contains &#8211; unsurprisingly &#8211; the counter value of Timer B. Strictly speaking, there are two registers that you can address together via TCBn.CNT or separately via TCBn.CNTL and TCBn.CNTH.<\/p>\r\n<p>As the name suggests, the Capture \/ Compare Register CCMP has various tasks. As a Compare Register, it controls interrupts and PWM, as a Capture Register it records counter readings as measured values.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example sketches for Timer B<\/h3>\n\n<p>We will now go through example sketches for each Count Mode. The sketches may have to be adapted for the tinyAVR representative of your choice regarding the pins and possibly also regarding the Event Module.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Periodic Interrupt<\/h4>\n\n<p>In Periodic Interrupt Mode, Timer B counts up to CCMP, triggers the CAPT Interrupt (if activated) and starts again from the beginning. In the following example sketch, we use the CAPT Interrupt to toggle the board LED. Since the megaTinyCore package uses the Timer A clock (default setting DIV64) and we set the CCMP to 62500, the toggle frequency at 20 MHz is: 20 MHz \/ (64 * 62500) = 5 Hertz.&nbsp;<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_periodic_interrupt.ino\" data-enlighter-title=\"timer_b_periodic_interrupt.ino\">ISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n    PORTA.OUTTGL = PIN2_bm; \/* Toggle PA2 *\/\r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN2_bm;\r\n    PORTA.OUTSET = PIN2_bm;\r\n    \/\/ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc | TCA_SINGLE_ENABLE_bm;\r\n    TCB0.CCMP = 62500; \/\/ Toggle frequency = 5 Hz @ 20 MHz\r\n    TCB0.INTCTRL = TCB_CAPT_bm;\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; \/\/ use TCA clock \/ enable\r\n}\r\n\r\nvoid loop() {}<\/pre>\r\n\n<p>If you uncomment line 9, you increase the clock divider from 64 to 1024, i.e. by a factor of 16. This reduces the toggle frequency to 0.3125 Hz (\u2192 period 3.2 s). But don&#8217;t forget: changing the Timer A clock may have an effect on <code>millis()<\/code> &amp; Co. when using the megaTinyCore package. <\/p>\r\n<p>This sketch should work unchanged on any tinyAVR microcontroller.<\/p>\r\n\n<h4 class=\"wp-block-heading\">8-Bit PWM Mode<\/h4>\n\n<p>PWM signals are easy to create using Timer B. The lower byte of the Compare Register CCMP, namely CCMPL, defines the PWM frequency together with the clock. The duty cycle results from the ratio of CCMPH (i.e. the upper byte) to CCMPL.   You can write to the CCMPH and CCMPL registers separately or together.<\/p>\r\n\n<p><\/p>\r\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 41px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/ql-cache\/quicklatex.com-e61bda66ba26d7761f4f6797cafd587e_l3.png\" height=\"41\" width=\"301\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91; &#68;&#117;&#116;&#121;&#67;&#121;&#99;&#108;&#101;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#116;&#101;&#120;&#116;&#123;&#67;&#67;&#77;&#80;&#72;&#125;&#125;&#123;&#92;&#116;&#101;&#120;&#116;&#123;&#67;&#67;&#77;&#80;&#76;&#32;&#43;&#32;&#49;&#125;&#125;&#32;&#92;&#99;&#100;&#111;&#116;&#32;&#49;&#48;&#48;&#92;&#59;&#92;&#59;&#32;&#91;&#92;&#37;&#93; &#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_8_bit_pwm.ino\" data-enlighter-title=\"timer_b_8_bit_pwm.ino\">void setup() {\r\n    PORTA.DIRSET = PIN5_bm; \/\/ PA5 = TCB0 WO for ATtiny1614, please adjust\r\n    TCB0.CCMP = 0x40FF;\r\n    \/* Alternative:\r\n    TCB0.CCMPL = 0xFF; \/\/ 255\r\n    TCB0.CCMPH = 0x40; *\/ \/\/ 64\r\n    TCB0.CTRLB |= TCB_CCMPEN_bm | TCB_CNTMODE_PWM8_gc;\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm;\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>In this example, we use the Timer A clock. This means that the frequency is 20 MHz \/ (64 * 256) = ~1.22 kHz. The duty cycle is 25%.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Single Shot Mode<\/h4>\n\n<p>In Single Shot Mode, the Timer counts up to CCMP and then stops until it is reset to a value less than CCMP. To try out the following sketch, connect an LED to the output for TCB0 (= PA5 for ATtiny1614).<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_single_shot_simple.ino\" data-enlighter-title=\"timer_b_single_shot_simple.ino\">void setup() {\r\n    PORTA.DIRSET = PIN5_bm; \/\/&nbsp;PA5&nbsp;=&nbsp;TCB0&nbsp;WO&nbsp;for&nbsp;ATtiny1614,&nbsp;please&nbsp;adjust\r\n    TCB0.CTRLA = 0; \/\/ disable TCB0\r\n    TCB0.CCMP = 62500; \/\/ 0.2s signal length\r\n    TCB0.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc; \/\/ enable output \/ single shot mode\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; \/\/ enable TCB0, use TCA clock\r\n}\r\n\r\nvoid loop(){\r\n    delay(1000);\r\n    TCB0.CNT = 0; \/\/ restarts the counter\r\n}<\/pre>\r\n\n<p>If your ATtiny is running at 20 MHz and you have not changed the Timer A clock, the LED will light up every second for 0.2 seconds.<\/p>\r\n<p>Now we combine this with the Event System. To do this, connect a push-button to a suitable pin. The other side of the button is connected to GND. I have written the following sketch for an ATtiny1614 and selected PB1 as the push-button pin.   Pushing the button (Event Generator) will start the TCB0 (Event User).<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_single_shot_extended.ino\" data-enlighter-title=\"timer_b_single_shot_extended.ino\">ISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN5_bm; \/\/ PA5 (TCB0 WO \/ ATtiny1614) as output\r\n    PORTB.DIRCLR = PIN1_bm; \/\/ PB1 as input\r\n    PORTB.PIN1CTRL = PORT_PULLUPEN_bm;\r\n    TCB0.CTRLA = 0; \/\/ disable TCB0\r\n    EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_PORTB_PIN1_gc; \/\/ PB1 as event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH1_gc; \/\/ TCB0 WO (PA5 on the ATtiny1614)\r\n    TCB0.CCMP = 62500; \/\/ 0.2s signal length\r\n    TCB0.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc; \/\/ single shot mode\r\n    TCB0.EVCTRL = TCB_EDGE_bm | TCB_CAPTEI_bm; \/\/ counter starts at both edges(?) \/ enable capture event input\r\n    TCB0.INTCTRL = TCB_CAPT_bm; \/\/ enable interrupt\r\n    TCB0.CNT = 62500; \/\/ prevents an unwanted, initial signal at PA5\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; \/\/ enable TCB0, use TCA clock\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>According to the data sheet, chapter 21.5.3, the timer should only be triggered on a falling (negative) edge when the EDGE bit is set, i.e. when the button is pressed and not when it is released. However, the LED lights up for both events. Perhaps simply an error in the data sheet? If the EDGE bit is not set, the LED does what it should: it only lights up when it is released (rising edge). At least this applies as long as your button does not bounce.<\/p>\r\n<p>If you comment out line 16, you will see that the LED lights up briefly each time the MCU is reset. Starting the Timer causes it to start counting at 0 and the LED lights up accordingly. If you set the Timer Counter to the value of CCMP, this will not happen. <\/p>\r\n\n<h5 class=\"wp-block-heading\">Adaptations for other tinyAVR MCUs<\/h5>\n\n<p>As already mentioned, several times: the sketches may have to be adapted depending on the ATtiny used. Here are a few examples:<\/p>\r\n<ul>\r\n<li>The sketch runs unchanged on an ATtiny1604.<\/li>\r\n<li>On an ATtiny402, for example, there is no PORTB. It worked with the following adjustments: <\/li>\r\n<\/ul>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"changes_for_ATtiny402\" data-enlighter-title=\"changes_for_ATtiny402\">.....    \r\nPORTA.DIRSET = PIN6_bm; \/\/ PA6 (= WO0 \/ ATtiny402) as output\r\nPORTA.DIRCLR = PIN1_bm; \/\/ PA1 as input\r\n.....\r\nEVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_PORTA_PIN1_gc; \/\/ PA1 as event generator\r\nEVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc; \/\/ TCB0 as event user\r\n.....<\/pre>\r\n\n<ul>\r\n<li>On the tinyAVR MCUs of series 2, major adjustments are necessary (see also Part 1 of the article). With these changes, it worked on an ATtiny3226: <\/li>\r\n<\/ul>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"changes_for_ATtiny3226\" data-enlighter-title=\"changes_for_ATtiny3226\">.....\r\nPORTA.DIRSET = PIN5_bm; \/\/ PA5 (0,WO0 \/ ATtiny3226) as output\r\nPORTA.DIRCLR = PIN1_bm; \/\/ PA1 as input\r\n.....\r\nEVSYS.CHANNEL0 = EVSYS_CHANNEL0_PORTA_PIN1_gc; \/\/ PA1 as event generator\r\nEVSYS.USERTCB0CAPT = EVSYS_USER_CHANNEL0_gc; \/\/ TCB0 as event user\r\n.....<\/pre>\r\n\n<p>This should put you on the right track to adapt the following example sketches yourself. I will limit myself to the ATtiny1614. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Input Capture Time-Out Check Mode<\/h4>\n\n<p>The Time-Out Check Mode is controlled by the Event System. In this mode, an event signal starts the timer at 0 and the next signal stops it.  If EDGE is set, the falling edge starts the Timer and the rising edge stops it. If EDGE is not set, the opposite applies. If the Timer Counter reaches CCMP, an interrupt is triggered and the Timer Counter continues to run. <\/p>\r\n\n<p>We try this out as follows: a button on a suitable pin (here: PA1) serves as an Event Generator that starts TCB0 in Time-Out Mode. As long as the button is pressed, TCB0 counts up. CCMP and the timer clock are set so that CCMP is reached after one second. If this occurs, an interrupt is triggered and the ISR toggles an LED on another suitable pin (here: PA2). If the button is released before CCMP is reached, there is no interrupt and the board LED does not toggle. The next time the button is pressed, the Timer restarts at zero.<\/p>\r\n<p>Under default conditions, CCMP is reached quickly. I have therefore slowed down Timer A and used it as the clock source for Timer B. And once again: Changes to the TCA0 and TCB0 settings can have side effects on <code>millis()<\/code> and Co.<\/p>\r\n<p>Here is the sketch reduced to the essentials (tested on an ATtiny1614):<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_time_out.ino\" data-enlighter-title=\"timer_b_time_out.ino\">#define TCB_TIMEOUT_VALUE (19531) \/\/ = 1s with the settings below\r\n\r\nISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n    PORTA.OUTTGL = PIN2_bm; \/* Toggle PA2 *\/\r\n}\r\n\r\nvoid setup() {\r\n    PORTA.DIRSET = PIN2_bm; \/\/ PA2 as output\r\n    PORTA.DIRCLR = PIN1_bm; \/\/ PA1 as input\r\n    PORTA.PIN1CTRL = PORT_PULLUPEN_bm; \/\/ enable pull-up at PA1\r\n        \r\n    EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_PORTA_PIN1_gc; \/\/ PA1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc; \/\/ TCB0 is event user\r\n\r\n    TCB0.CCMP = TCB_TIMEOUT_VALUE;\r\n    TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc | TCA_SINGLE_ENABLE_bm; \/\/ slow down Timer A\r\n    TCB0.CTRLB = TCB_CNTMODE_TIMEOUT_gc; \/\/ set time-out mode\r\n    TCB0.INTCTRL = TCB_CAPT_bm; \/\/ enable capture interrupt\r\n    TCB0.EVCTRL = TCB_EDGE_bm | TCB_CAPTEI_bm; \/\/ start counter on negative edge\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; \/\/ use timer A clock, enable TCB0\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>With a 20 MHz system clock, a divider of 1024 and a CCMP of 19531, the counter reaches CCMP after 19531 * 1024 \/ 20000000 = ~1 second. If you keep the button pressed permanently, the counter continues to run and reaches CCMP every 65536 * 1024 \/ 20000000 = ~3.36 seconds. <\/p>\r\n<p>To make it easier for you to keep track of which counter value you released the button at, I have an extended version of the sketch here:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_time_out_extended.ino\" data-enlighter-title=\"timer_b_time_out_extended.ino\">#define TCB_TIMEOUT_VALUE (19531) \/\/ = 1s with the settings below\r\nvolatile bool keyReleased = false;\r\n\r\nISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n    PORTA.OUTTGL = PIN2_bm; \/* Toggle PA2 *\/\r\n}\r\n\r\nISR(PORTA_PORT_vect){ \/\/ ISR for button release\r\n    PORTA.INTFLAGS = PIN1_bm;\r\n    keyReleased = true;\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    PORTA.DIRSET = PIN2_bm; \/\/ PA2 as output\r\n    PORTA.DIRCLR = PIN1_bm; \/\/ PA1 as input\r\n    PORTA.PIN1CTRL = PORT_PULLUPEN_bm | PORT_ISC_RISING_gc; \/\/ pull-up \/ interrupt\r\n        \r\n    EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_PORTA_PIN1_gc; \/\/ PA1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH0_gc; \/\/ TCB0 is event use\r\n\r\n    TCB0.CCMP = TCB_TIMEOUT_VALUE;\r\n    TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc | TCA_SINGLE_ENABLE_bm; \/\/ slow down Timer A\r\n    TCB0.CTRLB = TCB_CNTMODE_TIMEOUT_gc; \/\/ enable compare\/capture output, time-out mode\r\n    TCB0.INTCTRL = TCB_CAPT_bm; \/\/ enable capture interrupt\r\n    TCB0.EVCTRL = TCB_EDGE_bm | TCB_CAPTEI_bm; \/\/ start counter on negative edge\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; \/\/ use timer A clock, enable TCB0\r\n}\r\n\r\nvoid loop(){\r\n    if(keyReleased){\r\n        Serial.println(TCB0.CNT);\r\n        keyReleased = false;\r\n    }\r\n}<\/pre>\r\n\n<p>If the value displayed on the serial monitor is less than 19351, the LED is not toggled.<\/p>\r\n\n<h4 class=\"wp-block-heading\">Input Capture On Event Mode<\/h4>\n\n<p>Now, we come to the four Input Capture Modes that you can use to measure pulse widths and \/ or frequencies. For all examples, we use a PWM signal with a duty cycle of ~75% at PB1 as the object to be measured, which we generate on an ATtiny1614 with <code>analogWrite(6, 192)<\/code> (192 \/ 255 * 100 = ~75.29 %). PB1 is the Event Generator, Timer B is the Event User. <\/p>\r\n<p>First, let&#8217;s look at the Input Capture On Event Mode. In this mode, the counter permanently counts from 0 to 65535, overflows and starts again from the beginning. RDepending on whether you have set the EDGE bit or not, the Timer writes the current Counter value to the CCMP register on a falling or rising edge and triggers an interrupt. We read the CCMP Register in the ISR of the Capture Interrupt. The difference to the last value is the period of the PWM signal in Timer Counter counting steps.<\/p>\r\n<p>In the event of a Counter Overflow between two interrupts, the difference is negative, and we have to add 65636.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_capture_on_event.ino\" data-enlighter-title=\"timer_b_capture_on_event.ino\">volatile long cnt = 0;\r\nvolatile long lastCnt = 0;\r\n\r\nISR(TCB0_INT_vect){\r\n    cnt = TCB0.CCMP - lastCnt; \/\/ Read the period\r\n    lastCnt = TCB0.CCMP;\r\n    if(cnt &lt; 0){   \/\/ period is neg. when TCB0 was overflowed\r\n        cnt += 65536;\r\n    }\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    analogWrite(6, 192); \/\/ the event source \r\n    EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_PORTB_PIN1_gc; \/\/ PB1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH1_gc; \/\/ TCB0 is event user\r\n    TCB0.CTRLA = 0; \/\/ Stop TCB0\r\n    TCB0.CTRLB = TCB_CNTMODE_CAPT_gc;  \/\/ use input capture on event mode\r\n    TCB0.EVCTRL =  TCB_CAPTEI_bm; \/\/ enable capture event input\r\n    TCB0.INTCTRL = TCB_CAPT_bm;  \/\/ enable capture interrupt\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; \/\/ use system clock, enable TCB0\r\n    delay(10);\r\n}\r\n\r\nvoid loop(){\r\n    Serial.println(cnt);\r\n    delay(1000);\r\n}<\/pre>\r\n\n<p>The result was 16320. <code>analogWrite()<\/code> is controlled via the Timer A clock, which uses the divider 64. Regardless of the duty cycle, a rising edge and a falling edge are generated every 255 counters (not 256!).<\/p>\r\n<p><strong>A brief digression:<\/strong> <code>analogWrite()<\/code> is generated by a PWM signal from Timer A in Split Mode. If you check the top value with <code>Serial.println(TCA0.SPLIT.HPER)<\/code> or <code>Serial.println(TCA0.SPLIT.LPER)<\/code>, the result is 254 (= 255 steps). A <code>analogWrite(x, 255)<\/code> generates a <code>digitalWrite(x, HIGH)<\/code>. This ensures that a duty cycle of 100 % can be created.    <\/p>\r\n<p>The PWM signal therefore has a frequency of 20 MHz \/ (64 * 255) = ~1225.5 Hz or a period of 0.000816 seconds. The clock of Timer B corresponds to the system clock. This means that 16320 counting steps correspond to a frequency of 20 MHz \/ 16320 = ~1225.5 Hz. So it fits perfectly!<\/p>\r\n\n<h4 class=\"wp-block-heading\">Input Capture Frequency Measurement Mode<\/h4>\n\n<p>The Input Capture Frequency Measurement Mode basically does the same as the Input Capture On Event Mode, except that the Counter is reset to 0 after the event signal has been received. This has the advantage that CCMP provides us with the period directly, and we do not have to calculate differences.<\/p>\r\n<p>The term &#8220;frequency measurement&#8221; is actually misleading. It should be called &#8220;period measurement&#8221;.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_input_capture_frq.ino\" data-enlighter-title=\"timer_b_input_capture_frq.ino\">ISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    analogWrite(6, 192); \/\/ the event source\r\n    EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_PORTB_PIN1_gc; \/\/ PB1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH1_gc; \/\/ TCB0 is event user\r\n    TCB0.CTRLA = 0;\r\n    TCB0.CTRLB = TCB_CNTMODE_FRQ_gc; \/\/ enable input capture frequency mode\r\n    TCB0.EVCTRL = TCB_EDGE_bm | TCB_CAPTEI_bm; \/\/ enable capture event input \r\n    TCB0.INTCTRL = TCB_CAPT_bm;  \/\/ enable capture event input\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; \/\/ use system clock, enable TCB0\r\n  \r\n}\r\n\r\nvoid loop(){\r\n    Serial.print(\"Period in TCB0 counts: \");\r\n    Serial.println(TCB0.CCMP + 1);\r\n    float frq = 20000000.0 \/ ((TCB0.CCMP + 1) * 1.0);\r\n    Serial.print(\"Frequency [Hz]: \");\r\n    Serial.println(frq);\r\n    delay(1000);\r\n}<\/pre>\r\n\n<p>In this example sketch, I have integrated the calculation of the frequency into the sketch. It is interesting to note that you have to add 1 to the CCMP value to get the correct result. A CCMP value of 16319 is 16320 steps &#8211; that actually makes sense. The only thing that hasn&#8217;t really become clear, at least to me, is why you <em>don&#8217;t<\/em> have to add 1 when using the Input Capture On Event Mode.<\/p>\r\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq.png\"><img loading=\"lazy\" decoding=\"async\" width=\"402\" height=\"120\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq.png\" alt=\"Output timer_b_input_capture_frq.ino\" class=\"wp-image-22284\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq.png 402w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq-300x90.png 300w\" sizes=\"auto, (max-width: 402px) 100vw, 402px\" \/><\/a><figcaption class=\"wp-element-caption\">Output timer_b_input_capture_frq.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Input Capture Pulse-Width Measurement Mode<\/h4>\n\n<p>The Input Capture Pulse-Width Measurement Mode allows you to measure the pulse width of signals. In contrast to Frequency Measurement Mode, in which only the rising or falling edge had an effect, in this mode the counter is &#8220;zeroed&#8221; on one edge and the input capture, i.e. writing the counter reading to CCMP, takes place on the other edge.<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_input_capture_pw.ino\" data-enlighter-title=\"timer_b_input_capture_pw.ino\">ISR(TCB0_INT_vect){\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    analogWrite(6, 192); \/\/ the event source\r\n    EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_PORTB_PIN1_gc; \/\/ PB1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH1_gc; \/\/ TCB0 is event user\r\n    TCB0.CTRLA = 0;\r\n    TCB0.CTRLB = TCB_CNTMODE_PW_gc; \/\/ enable pulse width measurement mode\r\n    TCB0.EVCTRL = TCB_CAPTEI_bm; \/\/ enable capture event input\r\n    TCB0.INTCTRL = TCB_CAPT_bm; \r\n    TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; \/\/ use system clock, enable TCB0\r\n    delay(10);\r\n}\r\n\r\nvoid loop(){\r\n    Serial.print(\"High Period in TCB0 counts: \");\r\n    unsigned int highCnt = (TCB0.CCMP + 1);\r\n    Serial.println(highCnt);\r\n    float pw = (highCnt * 1.0) \/ 20.0;  \/\/ cnt divided by 20 MHz\r\n    Serial.print(\"Pulse width [\u00b5s]: \");\r\n    Serial.println(pw);\r\n    Serial.println();\r\n    delay(1000);\r\n}<\/pre>\r\n\n<p>As a result, I received:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_pw.png\"><img loading=\"lazy\" decoding=\"async\" width=\"438\" height=\"148\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_pw.png\" alt=\"Output timer_b_input_capture_pw.ino\" class=\"wp-image-22288\" style=\"width:441px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_pw.png 438w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_pw-300x101.png 300w\" sizes=\"auto, (max-width: 438px) 100vw, 438px\" \/><\/a><figcaption class=\"wp-element-caption\">Output timer_b_input_capture_pw.ino<\/figcaption><\/figure>\n\n<p>This corresponds exactly to expectations. The PWM period comprised 16320 counters in 255 steps. 192 steps correspond to 16320 * 192 \/ 255 = 12288. <\/p>\r\n<p>If you set the EDGE bit in the Event Control Register (line 12), the sketch evaluates the LOW phase. <\/p>\r\n\n<h4 class=\"wp-block-heading\">Input Capture Frequency and Pulse-Width Measurement Mode<\/h4>\n\n<p>The Input Capture Frequency and Pulse-Width Measurement Mode combines frequency and pulse-width measurement. Of course, not both values can be saved in CCMP. Instead, the mode works as follows (if the EDGE bit is not set):<\/p>\r\n<ul>\r\n<li>At the first positive edge (pulse begins): The counter is reset and starts.<\/li>\r\n<li>Next negative edge (pulse ends): Input Capture, i.e. the counter reading is written to CCMP.<\/li>\r\n<li>Second positive edge (period ends): Counter stops, an interrupt is triggered.<\/li>\r\n<\/ul>\r\n<p>Since we know the period (from CCMP) and the pulse width (counter status at interrupt), we can calculate the duty cycle. And that&#8217;s precisely what the next sketch does:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"timer_b_input_capture_frq_and_pw.ino\" data-enlighter-title=\"timer_b_input_capture_frq_and_pw.ino\">volatile unsigned int period = 0;\r\n\r\nISR(TCB0_INT_vect){\r\n    period = TCB0.CNT + 1; \/\/ Read the period\r\n    TCB0.INTFLAGS = TCB_CAPT_bm; \/* Clear the interrupt flag *\/\r\n}\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    analogWrite(6, 192); \/\/ the event source\r\n    EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_PORTB_PIN1_gc; \/\/ PB1 is event generator\r\n    EVSYS.ASYNCUSER0 = EVSYS_ASYNCUSER0_ASYNCCH1_gc; \/\/ TCB0 is event user\r\n    TCB0.CTRLA = 0;\r\n    TCB0.CTRLB = TCB_CNTMODE_FRQPW_gc;\r\n    TCB0.EVCTRL = TCB_CAPTEI_bm; \/\/ TCB_EDGE_bm | TCB_CAPTEI_bm;\r\n    TCB0.INTCTRL = TCB_CAPT_bm;\r\n    TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; \/\/ use system clock, enable TCB0\r\n}\r\n\r\nvoid loop(){\r\n    Serial.print(\"Period in TCB0 counts: \");\r\n    Serial.println(period);\r\n    Serial.print(\"High Period in TCB0 counts: \");\r\n    Serial.println(TCB0.CCMP + 1);\r\n    float frq = 20000000.0 \/ (period * 1.0);\r\n    Serial.print(\"Frequency [Hz]: \");\r\n    Serial.println(frq);\r\n    float dc = (TCB0.CCMP + 1) * 1.0 \/ (period * 1.0) * 100.0;\r\n    Serial.print(\"Duty Cycle [%]: \");\r\n    Serial.println(dc);\r\n    Serial.println();\r\n    delay(1000);\r\n}<\/pre>\r\n\n<p>Here is the result:<\/p>\r\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq_and_pw.png\"><img loading=\"lazy\" decoding=\"async\" width=\"442\" height=\"76\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq_and_pw.png\" alt=\"Output timer_b_input_capture_frq_and_pw.ino\" class=\"wp-image-22292\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq_and_pw.png 442w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/10\/output_timer_b_input_capture_frq_and_pw-300x52.png 300w\" sizes=\"auto, (max-width: 442px) 100vw, 442px\" \/><\/a><figcaption class=\"wp-element-caption\">Output timer_b_input_capture_frq_and_pw.ino<\/figcaption><\/figure>\n\n<h2 class=\"wp-block-heading\" id=\"ccl_module\">Configurable Custom Logic &#8211; CCL Module<\/h2>\n\n<p>The Configurable Custom Logic Module CCL gives the tinyAVR MCUs capabilities that you would otherwise have to use external logic ICs for. But it goes far beyond that.<\/p>\r\n<p>The CCL module is organized in so-called Look-Up Tables (LUTs). Each LUT has three inputs and one output.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Register of the CCL Module<\/h3>\n\n<p>I will only give a rough overview of this module. Here is the register overview:<\/p>\r\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/regsum_ccl.png\"><img loading=\"lazy\" decoding=\"async\" width=\"931\" height=\"285\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/regsum_ccl.png\" alt=\"Register Summary Module CCL, example ATtiny1614\" class=\"wp-image-22487\" style=\"width:732px;height:auto\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/regsum_ccl.png 931w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/regsum_ccl-300x92.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/regsum_ccl-768x235.png 768w\" sizes=\"auto, (max-width: 931px) 100vw, 931px\" \/><\/a><figcaption class=\"wp-element-caption\">Register Summary Module CCL, example ATtiny1614<\/figcaption><\/figure>\n\n<p>Each LUT has its own TRUTH register. This is where you define which input level combination is true. Example: For LUT0, we define that LUT0-IN2 = HIGH, LUT0-IN1 = LOW and LUT0-IN0 = LOW should be the &#8220;true&#8221; state. I.e: HIGH\/LOW\/LOW \u21d2 0b100 = 4. This in turn means that bit no. 4 must be set in TRUTH0 (and not that TRUTH0 = 4!).<\/p>\r\n<p>Now comes the ingenious part: The inputs do not have to be just I\/O pins, but can also be Events, Timers, USARTs or the output of another LUT, for example. So if certain states of different modules in your program require an action, you can save yourself the trouble of querying these states and some if and switch combinations with the CCL. You define the inputs via the Input Select Bitgroups (INSELn[3:0]).<\/p>\r\n<p>If the &#8220;true&#8221; state occurs, you can be notified by an interrupt. Alternatively or additionally, you can set the OUTEN bit so that the corresponding output goes from LOW to HIGH when &#8220;true&#8221;.<\/p>\r\n<p>You can combine 2 LUTs using the SEQSELn[3:0] bit groups.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example Sketch for the CCL Module<\/h3>\n\n<p>As a simple example, we check the status of the I\/O pins assigned to LUT0. The following applies to the ATtiny1614 (and many others): <\/p>\r\n<ul>\r\n<li>LUT0-IN2 = PA2<\/li>\r\n<li>LUT0-IN1 = PA1<\/li>\r\n<li>LUT0-IN0 = PA0<\/li>\r\n<li>LUT0-OUT = PA4<\/li>\r\n<\/ul>\r\n<p>Our true condition should be: 2LUT0-IN2 = HIGH, LUT0-IN1 = LOW and LUT0-IN0 = LOW. We pull the inputs to HIGH with the internal pull-up resistors. Pressing the button should bring them to LOW. If the buttons on LUT0-IN1 and LUT0-IN0 are pressed, the true condition is fulfilled and the LUT0-OUT output goes HIGH. This is indicated by an LED. This is the circuit:<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test-1024x432.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"432\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test-1024x432.png\" alt=\"Circuit for ccl_basic.ino, example ATtiny1614\" class=\"wp-image-22489\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test-1024x432.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test-300x127.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test-768x324.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2024\/11\/ccl_test.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Circuit for ccl_basic.ino using ATtiny1614 as an example<\/figcaption><\/figure>\n\n<p>And here is the corresponding sketch:<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"ccl_basic.ino\" data-enlighter-title=\"ccl_basic.ino\">void setup() {\r\n    PORTA.DIRCLR = PIN2_bm | PIN1_bm | PIN0_bm; \/\/ PA0 = LUT0-IN0 as input, etc.\r\n    \/\/PORTA.DIRSET = PIN4_bm; \/\/ not necessary!     \r\n    PORTA.PIN0CTRL = PORT_PULLUPEN_bm; \/\/ PULLUP for PA0 = LUT0-IN0\r\n    PORTA.PIN1CTRL = PORT_PULLUPEN_bm; \/\/ PULLUP for PA1 = LUT0-IN1\r\n    PORTA.PIN2CTRL = PORT_PULLUPEN_bm; \/\/ PULLUP for PA2 = LUT0-IN2\r\n    CCL.LUT0CTRLB = CCL_INSEL0_IO_gc | CCL_INSEL1_IO_gc; \/\/ select I\/O as input\r\n    CCL.LUT0CTRLC = CCL_INSEL2_IO_gc; \/\/ select I\/O as Input\r\n    CCL.TRUTH0 = 0x10; \/\/ LUT2-IN2 = HIGH, LUT1-IN2 = LOW, LUT0-IN2 = LOW ==&gt; TRUE\r\n    CCL.LUT0CTRLA = CCL_OUTEN_bm | CCL_ENABLE_bm; \/\/ OUT Enable \/ LUT0 enable\r\n    CCL.CTRLA = CCL_ENABLE_bm; \/\/ CCL_ENABLE\r\n}\r\n\r\nvoid loop(){}<\/pre>\r\n\n<p>The status check and the output bypass the CPU. This is extremely resource-efficient. <\/p>\r\n<p>The megaTinyCore board package has implemented its own library called <a href=\"https:\/\/github.com\/SpenceKonde\/megaTinyCore\/tree\/master\/megaavr\/libraries\/Logic\" target=\"_blank\" rel=\"noopener\">Logic<\/a> for the CCL module. Perhaps this is easier for some than register programming. You will also find some example sketches as part of the board package.   <\/p>\r\n\n<h2 class=\"wp-block-heading\" id=\"slpctrl_module\">The tinyAVR MCUs go to sleep &#8211; SLPCTRL Module<\/h2>\n\n<p>Going to sleep &#8211; I think this is a good topic for the last chapter!<\/p>\r\n\n<h3 class=\"wp-block-heading\">Register Settings for SLPCTRL<\/h3>\n\n<p>he SLPCTRL module only has the CTRLA register, in which you select the Sleep mode (SMODE[1:0]) and enable the SLPCTRL module using the SEN bit. However, setting the SEN bit alone does not put the microcontroller to sleep. To do this, use <code>sleep_cpu()<\/code> from avr\/sleep.h.<\/p>\r\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA-1024x85.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"85\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA-1024x85.webp\" alt=\"tinyAVR Register: SLPCTRL.CTRLA\" class=\"wp-image-19377\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA-1024x85.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA-300x25.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA-768x64.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2023\/11\/Reg_SLPCTRL_CTRLA.webp 1185w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Register: SLPCTRL.CTRLA<\/figcaption><\/figure>\n\n<p>You can select from the following options for Bit Group Configurations for SMODE[1:0]:<\/p>\r\n<ul>\r\n<li>IDLE: Idle &#8211; the lightest sleep; everything is active except the CPU.<\/li>\r\n<li>STDBY: Stand-by &#8211; the most flexible setting.<\/li>\r\n<li>PDOWN: Power Down &#8211; deep sleep.<\/li>\r\n<\/ul>\r\n<p>The deeper the sleep, the lower the power consumption and the more limited the wake-up methods. Which peripherals are available in which Sleep Mode can be found in the SLPCTRL section of the data sheet. Stand-by mode is the most flexible. Many modules have a RUNSTBY bit that determines whether the module should be available in standby mode or not.<\/p>\r\n\n<h3 class=\"wp-block-heading\">Example sketch for SLPCTRL <\/h3>\n\n<p>In the following example we send the tinyAVR into power down mode and wake it up after one second using the Periodic Timer Interrupt (PIT).<\/p>\r\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"power_down_pit_wake_up.ino\" data-enlighter-title=\"power_down_pit_wake_up.ino\"> #include&lt;avr\/sleep.h&gt;\r\n\r\nISR(RTC_PIT_vect){\r\n    RTC.PITINTFLAGS = 1;\r\n}\r\n\r\nvoid setup(){\r\n    Serial.begin(115200);\r\n    RTC.CLKSEL = RTC_CLKSEL_INT32K_gc;\r\n    RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm;\r\n    RTC.PITINTCTRL = RTC_PI_bm;   \r\n    SLPCTRL.CTRLA = SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm;  \r\n}\r\n\r\nvoid loop(){\r\n    Serial.println(\"Going to sleep...\");\r\n    Serial.flush();\r\n    sleep_cpu();\r\n}<\/pre>\r\n","protected":false},"excerpt":{"rendered":"<p>In this sequel of my article about the tinyAVR series 0, 1 and 2, I cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLPCTRL).<\/p>\n","protected":false},"author":1,"featured_media":15558,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[543],"tags":[2256,2265,2587,2261,1886,983,1958,2586,1059,2260,2583,2585,2584,2258,2259,1885,2588],"class_list":["post-22566","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-boards-and-microcontrollers","tag-ccl-en","tag-configurable-custom-logic-en","tag-count-mode-en","tag-input-capture-en","tag-megatinycore-en","tag-pwm-en","tag-register-en","tag-single-mode-en-2","tag-sleep-en","tag-split-mode","tag-tca0-en","tag-tcb0-en","tag-tcbn-en","tag-timer-a-en","tag-timer-b-en","tag-tinyavr-en","tag-wave-form-generation-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2024-11-02T15:38:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-12-01T17:18:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"1200\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"33 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"tinyAVR Series Part 2: Timer A\\\/B, CCL, SLPCTRL\",\"datePublished\":\"2024-11-02T15:38:05+00:00\",\"dateModified\":\"2024-12-01T17:18:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\"},\"wordCount\":4702,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"keywords\":[\"CCL\",\"configurable custom logic\",\"count mode\",\"Input Capture\",\"megaTinyCore\",\"PWM\",\"Register\",\"single mode\",\"sleep\",\"split mode\",\"TCA0\",\"TCB0\",\"TCBn\",\"Timer A\",\"Timer B\",\"tinyAVR\",\"wave form generation\"],\"articleSection\":[\"Boards and Microcontrollers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\",\"name\":\"tinyAVR Series Part 2: Timer A\\\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"datePublished\":\"2024-11-02T15:38:05+00:00\",\"dateModified\":\"2024-12-01T17:18:03+00:00\",\"description\":\"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/mega_tiny_core_post_image.jpg\",\"width\":1200,\"height\":1200},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"tinyAVR Series Part 2: Timer A\\\/B, CCL, SLPCTRL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste","description":"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl","og_locale":"en_US","og_type":"article","og_title":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste","og_description":"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl","og_site_name":"Wolles Elektronikkiste","article_published_time":"2024-11-02T15:38:05+00:00","article_modified_time":"2024-12-01T17:18:03+00:00","og_image":[{"width":1200,"height":1200,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","type":"image\/jpeg"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"33 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL","datePublished":"2024-11-02T15:38:05+00:00","dateModified":"2024-12-01T17:18:03+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl"},"wordCount":4702,"commentCount":4,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","keywords":["CCL","configurable custom logic","count mode","Input Capture","megaTinyCore","PWM","Register","single mode","sleep","split mode","TCA0","TCB0","TCBn","Timer A","Timer B","tinyAVR","wave form generation"],"articleSection":["Boards and Microcontrollers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl","url":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl","name":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","datePublished":"2024-11-02T15:38:05+00:00","dateModified":"2024-12-01T17:18:03+00:00","description":"In this sequel I will cover the topics Timer A, Timer B, the Configurable Custom Logic (CCL) and the Sleep Control module (SLRCTRL).","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2022\/07\/mega_tiny_core_post_image.jpg","width":1200,"height":1200},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/tinyavr-series-part-2-timer-a-b-ccl-slpctrl#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"tinyAVR Series Part 2: Timer A\/B, CCL, SLPCTRL"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=22566"}],"version-history":[{"count":2,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22566\/revisions"}],"predecessor-version":[{"id":22952,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/22566\/revisions\/22952"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/15558"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=22566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=22566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=22566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}