forked from schinken/PPMEncoder
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPPMEncoder.h
More file actions
101 lines (74 loc) · 2.49 KB
/
Copy pathPPMEncoder.h
File metadata and controls
101 lines (74 loc) · 2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#ifndef _PPMEncoder_h_
#define _PPMEncoder_h_
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
template<uint8_t numChannels = 8>
class PPMEncoder {
public:
const uint16_t minValue;
const uint16_t maxValue;
const uint16_t pulseLength;
const uint16_t frameLength;
PPMEncoder() : minValue(1000), maxValue(3000), pulseLength(500), frameLength(22500) {}
PPMEncoder(const uint16_t minValue, const uint16_t maxValue, const uint16_t frameLength, const uint16_t pulseLength)
: minValue(minValue), maxValue(maxValue), pulseLength(pulseLength), frameLength(frameLength) {}
void setChannel(uint8_t channel, uint16_t value) {
channels[channel] = constrain(value, minValue, maxValue);
};
void setChannelPercent(uint8_t channel, uint8_t percent) {
percent = constrain(percent, 0, 100);
setChannel(channel, map(percent, 0, 100, minValue, maxValue));
};
void begin(uint8_t pin, boolean inverted = false) {
cli();
// Store on/off-State in variable to avoid another if in timing-critical interrupt
onState = (inverted) ? HIGH : LOW;
offState = (inverted) ? LOW : HIGH;
pinMode(pin, OUTPUT);
digitalWrite(pin, offState);
state = true;
elapsedUs = 0;
currentChannel = 0;
outputPin = pin;
for (uint8_t ch = 0; ch < numChannels; ch++) {
setChannelPercent(ch, 0);
}
TCCR1A = 0;
OCR1A = 100;
TCCR1B = (1 << WGM12) | (1 << CS11);
TIMSK1 = (1 << OCIE1A); // enable timer compare interrupt
sei();
};
void interrupt() {
TCNT1 = 0;
if (state) {
digitalWrite(outputPin, onState);
OCR1A = pulseLength * 2;
} else {
digitalWrite(outputPin, offState);
if (currentChannel >= numChannels) {
currentChannel = 0;
elapsedUs = elapsedUs + pulseLength;
OCR1A = (frameLength - elapsedUs) * 2;
elapsedUs = 0;
} else {
OCR1A = (channels[currentChannel] - pulseLength) * 2;
elapsedUs = elapsedUs + channels[currentChannel];
currentChannel++;
}
}
state = !state;
};
private:
int16_t channels[numChannels]{};
uint16_t elapsedUs{};
uint8_t currentChannel{};
byte outputPin{};
boolean state{};
uint8_t onState{};
uint8_t offState{};
};
#endif