/* p5_9.c Input Capture of PB04 using TC4 * * This program uses TC4 to do input capture of PB04. * Captured time is store in the variable timestamp. * Period of input signal is calculated and stored in variable period. * Both variables are put in global for ease of observation in debugger. * * Test signal generation: * TC6 is used to generate signal to test input capture * The output at PB02 is 1 Hz. * * Signal capture: * A jumper is installed between PB02 and PB04. PB04 acts as the input * for EXTINT4. * * Event generation: * EXTINT4 is used to generate events. * * Event channel: * Event generated by EXTINT4 is fed into channel 8 of EVSYS. * Event user TC4 takes events from channel 8. * * Event consumption: * TC4 is configured to do capture to CC0. * When event occurs, the captured clock counts are stored * in global variables "timestamp" to be observed in debugger. * The event frequency is 1 Hz, the TC4 prescaler divides by 256, * the period should be 1,000,000/256=3,906. * The LED0 is also toggled when capture occurs. * * Tested with Atmel Studio 7 v7.0.1006 and Keil MDK-ARM v5.21a. */ #include "samd21.h" unsigned char* ARRAY_PORT_PINCFG1 = (unsigned char*)®_PORT_PINCFG1; unsigned char* ARRAY_PORT_PMUX1 = (unsigned char*)®_PORT_PMUX1; void TC6_init(void); uint16_t timestamp; uint16_t period; int main (void) { uint16_t reading; /* TC4 is configured to do event capture channel 0. * Counter is 16-bit mode, prescaler div by 256. */ REG_PM_APBCMASK |= 0x00001000; /* enable bus clock for TC4 */ REG_GCLK_CLKCTRL = 0x401C; /* GCLK0 -> TC4/TC5 */ REG_TC4_CTRLA = 1; /* reset */ while (REG_TC4_CTRLA & 1) {} /* wait till out of reset */ REG_TC4_CTRLA = 0x0600; /* div by 256, 16-bit mode */ REG_TC4_CTRLC = 0x10; /* enable capture ch 0 */ REG_TC4_EVCTRL = 0x0020; /* event input enabled */ REG_TC4_INTFLAG = 0xFF; /* clear all flags */ REG_TC4_CTRLA |= 2; /* enable TC4 */ /* Configure PB04 as input for EXTINT4. * EXTINT4 is used to generate event on rising edge of PB04. */ ARRAY_PORT_PINCFG1[4] |= 7; /* enable PMUX function, input, pull */ ARRAY_PORT_PMUX1[2] = 0; /* PB04 = EXTINT4 */ REG_PORT_DIRCLR1 = 0x10; /* PB04 input */ REG_PORT_OUTSET1 = 0x10; /* PB04 pull-up */ REG_GCLK_CLKCTRL = 0x4005; /* GCLK0 -> EIC */ REG_EIC_CONFIG0 |= 0x00010000; /* EXTINT4 rising edge */ REG_EIC_EVCTRL |= 0x10; /* enable EXTINT4 event */ REG_EIC_CTRL = 2; /* enable EIC */ /* EXTINT4 event feeds to channel 8. * TC4 uses events from channel 8. */ REG_PM_APBCMASK |= 2; /* clock to EVSYS */ REG_EVSYS_CTRL = 1; /* reset event system */ REG_EVSYS_CHANNEL = 0x02100008; /* channel 8 <- EXTINT4 asynch */ REG_EVSYS_USER = 0x0913; /* channel 8 used by TC4 */ /* TC6 is used to generate test signal */ TC6_init(); /* make PB30 output for LED */ REG_PORT_DIRSET1 = 0x40000000; while(1) { if (REG_TC4_INTFLAG & 0x10) { /* if capture occurs */ REG_TC4_INTFLAG = 0x10; /* clear capture flags */ reading = REG_TC4_COUNT16_CC0; /* read the timestamp */ period = reading - timestamp; /* calculate the period */ timestamp = reading; /* the timestamp is stored */ REG_PORT_OUTTGL1 = 1 << 30; /* toggle LED */ } } } /* TC6 is used to generate signal to test input capture. * In 16-bit match frequency mode, output toggles and * counter reset at CC0 match. * The output toggles at 1,000,000/256/1,953 = 2 Hz * and the output 1 Hz. * PB02 is used as output pin. */ void TC6_init(void) { REG_GCLK_CLKCTRL = 0x401D; /* GCLK0 -> TC6/TC7 */ REG_PM_APBCMASK |= 0x00004000; /* enable TC6 Clock in PM */ REG_TC6_CTRLA = 1; /* reset */ while (REG_TC6_CTRLA & 1) {} /* wait till out of reset */ REG_TC6_CTRLA = 0x0620; /* div by 256, 16-bit mode, match frequency mode */ REG_TC6_COUNT16_CC0 = 1953; /* match value 0, top count, output toggle on match */ REG_TC6_CTRLA |= 2; /* enable */ ARRAY_PORT_PINCFG1[2] |= 1; /* make PB02 output for TC6/WO[0] */ ARRAY_PORT_PMUX1[1] = 0x04; /* PB02 = TC6 */ }