Zumo32U4 library
Zumo32U4IRPulses.cpp
1// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2
3#include <Zumo32U4IRPulses.h>
4#include <avr/io.h>
5#include <avr/interrupt.h>
6
7void Zumo32U4IRPulses::start(Direction direction, uint16_t brightness, uint16_t period)
8{
9 // Disable Timer 3's interrupts. This should be done first because another
10 // library might be using the timer and its ISR might be modifying timer
11 // registers.
12 TIMSK3 = 0;
13
14 // Make sure brightness is not larger than period because then the compare
15 // match would never happen and the pulse count would always be zero.
16 if (brightness > period)
17 {
18 brightness = period;
19 }
20
21 // Set the PWM pin to be an input temporarily. Otherwise, when we configure
22 // the COM3A<1:0> bits, the OC03A signal might be high from previous
23 // activity of the timer and result in a glitch on the pin.
24 PORTC &= ~(1 << 6);
25 DDRC &= ~(1 << 6);
26
27 // Put the timer into a known state that should not cause any trouble while
28 // we are reconfiguring it.
29 // COM3A<1:0> = 10 : Clear OC3A on match, set at top.
30 TCCR3A = (1 << COM3A1);
31 TCCR3B = 0;
32
33 // Simulate a compare match, which makes the OC3A PWM signal (which is not
34 // connected to the I/O pin yet) go low. We must do this after configuring
35 // COM3A<1:0>.
36 TCCR3C = (1 << FOC3A);
37
38 // Make the PWM pin be an output. The OC03A signal will control its value.
39 DDRC |= (1 << 6);
40
41 // Drive PF6/A1 high or low to select which LEDs to use.
42 if (direction)
43 {
44 // Right
45 PORTF |= (1 << 6);
46 }
47 else
48 {
49 // Left
50 PORTF &= ~(1 << 6);
51 }
52 DDRF |= (1 << 6);
53
54 // Set frequency/period.
55 ICR3 = period;
56
57 // Set the count to be one less than ICR3 so that the new duty cycle
58 // will take effect very soon.
59 TCNT3 = period - 1;
60
61 // Set the duty cycle.
62 OCR3A = brightness;
63
64 // Start the timer. It will start running once the clock source bits
65 // in TCCR3B are set.
66 //
67 // COM3A<1:0> = 10 : Set OC3A on match, clear at top.
68 // WGM3<3:0> = 1110 : Fast PWM, with ICR3 as the TOP.
69 // CS3<3:0> = 001 : Internal clock with no prescaler
70 TCCR3A = (1 << COM3A1) | (1 << WGM31);
71 TCCR3B = (1 << WGM33) | (1 << WGM32) | (1 << CS30);
72}
73
75{
76 // Prepare the PWM pin to drive low. We don't want to just set it as an
77 // input because then it might decay from high to low gradually and the
78 // LEDs would not turn off immediately.
79 PORTC &= ~(1 << 6);
80 DDRC |= (1 << 6);
81
82 // Disconnect the PWM signal from the pin, causing it to drive low. We must
83 // do this before stopping the timer to avoid glitches.
84 TCCR3A = (1 << WGM31);
85
86 // Turn off the timer.
87 TCCR3B = 0;
88
89 // Restore the timer's default settings to help avoid compatibilty issues
90 // with other libraries.
91 TIMSK3 = 0;
92 TCCR3A = 0;
93 OCR3A = 0;
94 ICR3 = 0;
95 TCNT3 = 0;
96
97 // Change the IR LED direction pin (A1) back to an input so it
98 // can be used for measuring the battery level.
99 DDRF &= ~(1 << 6);
100 PORTF &= ~(1 << 6);
101}
static void stop()
Stops emitting IR pulses.
static void start(Direction direction, uint16_t brightness, uint16_t period=defaultPeriod)
Starts emitting IR pulses.