Atmega4808/4809 Input capture example

Hi,

I'm trying measure the frequency of an external signal using my arduino every board... unfortunatly all the existing libraries I've found are not yet ported on the ATmega4809... before struggling with the datasheets I wonder if there is an example of the TCB working in input capture mode...

I've seen an APPNOTE - Getting started with TCB from Microchip regarding the PCB but it does not cover the input capture mode:

Any hints ?

Best Regards

Giampaolo

Here's an example program that uses TCB0 to measure the frequency (actually the period) of a signal on pin 3. Modify as needed!

void setup() {
  Serial.begin(9600);
  EVSYS.CHANNEL4 = EVSYS_GENERATOR_PORT1_PIN5_gc; // Route pin 3, PF5
  EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL4_gc; // to TCB0
  TCB0.CTRLA = 0; // Turn off channel for configuring
  TCB0.CTRLB = 0x3; // Frequency mode
  TCB0.EVCTRL = 0x41; // Enable input capture, positive edge
  TCB0.INTCTRL = 1; // Enable interrupt
  TCB0.CTRLA = 1; // Enable and use system clock
}
volatile uint16_t period;

void loop() {
  uint16_t tempVal;
  delay(1000);
  cli();
  tempVal = period;
  sei();
  Serial.println((tempVal + 8) / 16);
}

ISR(TCB0_INT_vect) {
  period = TCB0.CCMP; // reading CCMP clears interrupt flag
}

Hi,

thanks a lot for your help! last week I went-up with something similar, switching from PERF or PERF/2 to the 250kHz TCA clock in order to measure frequencies starting from 3,8Hz…

thanks again

Giampaolo

volatile uint8_t TCB1_isr_count = 0;


ISR(TCB1_INT_vect)
{
   uint16_t value;
   static bool toggle;
   
   TCB1_isr_count++;

   value =  TCB1.CCMP;

// meanFilter.AddValue(value);

   digitalWrite(FREQ_TOGGLE_PIN , toggle ? HIGH : LOW); // diagnostic only

   toggle = !toggle;
}

void initTCB(void)
{
// pinMode(3, INPUT);                       // Port F, Pin 5 = Arduino ~D3       
   pinMode(9, INPUT);                       // Port B, Pin 0 = Arduino ~D9       

   PORTMUX.TCBROUTEA |= PORTMUX_TCB1_bm;    // PORTMUX Control for TCB: Route TCB1 signal to PF5 aka D3 (default is PA3/SCL aka D19)

// ~~~ 

   TCB1.CTRLB = 0 << TCB_ASYNC_bp           // TCBn.CTRLB: Asynchronous Enable: disabled 
           // | 1 << TCB_CCMPEN_bp          // TCBn.CTRLB: Pin Output Enable: enabled 
           // | 0 << TCB_CCMPINIT_bp        // TCBn.CTRLB: Pin Initial State: disabled 
           // | TCB_CNTMODE_PWM8_gc;        // TCBn.CTRLB: 8-bit PWM 
              | TCB_CNTMODE_FRQ_gc;         // TCBn.CTRLB: Input Capture Frequency measurement

// ~~~ 

// TCB1.DBGCTRL = 0 << TCB_DBGRUN_bp;       // TCBn.DBGCTRL: Debug Run (disabled) 

// ~~~ 

   TCB1.EVCTRL = 1 << TCB_CAPTEI_bp         // TCBn.EVCTRL: Event Input Enable (enabled) 
               | 0 << TCB_EDGE_bp           // TCBn.EVCTRL: Event Edge: (positive edge) 
               | 1 << TCB_FILTER_bp;        // TCBn.EVCTRL: Input Capture Noise Cancellation Filter (enabled)

// ~~~ 

// TCB1.CTRLA = TCB_CLKSEL_CLKDIV1_gc       // TCBn.CTRLA: CLK_PER (CLKDIV1 aka No-Prescaling) 
// TCB1.CTRLA = TCB_CLKSEL_CLKDIV2_gc       // TCBn.CTRLA: CLK_PER/2 (CLKDIV2) 
   TCB1.CTRLA = TCB_CLKSEL_CLKTCA_gc        // TCBn.CTRLA: Use Clock from TCA 
               | 1 << TCB_ENABLE_bp         // TCBn.CTRLA: Enable bit position (enabled) 
               | 0 << TCB_RUNSTDBY_bp       // TCBn.CTRLA: Run Standby bit position (disabled)
               | 0 << TCB_SYNCUPD_bp;       // TCBn.CTRLA: Synchronize Update bit position (disabled)

               

// ~~~ 

   TCB1.INTCTRL = 1 << TCB_CAPT_bp;         // TCBn.INTCTRL: Capture Interrupt Enable (enabled)

// ~~~ 

// WARNING!
// By using the EVSYS, any event source, such as an external clock signal on any I/O pin, may be used as a control logic input.
// When an event action controlled operation is used, the clock selection must be set to use an event channel as the counter input.

// EVSYS.CHANNEL3 = 0b01001100;             // event channel 3 connects to pin PD4
// EVSYS.USERTCB1 = 4;                      // connect the counter to event channel 3 (4-1)

// EVSYS.CHANNEL5 = 0b01001101;             // event channel 5 connects to pin PF5 (Port F, Pin 5 = Arduino ~D3) WARNING! Not all generators can be connected to all channels! 
// EVSYS.USERTCB1 = 6;                      // connect the counter to event channel 5 (6-1)

// EVSYS.CHANNEL0 = 0b01001000;             // event channel 0 connects to pin PB0 (Port B, Pin 0 = Arduino ~D9) WARNING! Not all generators can be connected to all channels! 
// EVSYS.USERTCB1 = 1;                      // connect the counter to event channel 0 (1-1)

   EVSYS.CHANNEL1 = 0b01001000;             // event channel 1 connects to pin PB0 (Port B, Pin 0 = Arduino ~D9) WARNING! Not all generators can be connected to all channels! 
   EVSYS.USERTCB1 = 2;                      // connect the counter to event channel 1 (2-1)

// ~~~ 

   TCB1.CTRLA |= TCB_ENABLE_bm;             // TCBn.CTRLA: bit0=Enable bit mask  
}