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 
7 void 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.