12
// channel sequence order
13
static const int channel_order_[] = { CHANNEL_ORDER };
15
// set to the time of the last pulse edges
16
static unsigned long new_pulse_up_[2] = { 0, 0 };
17
static unsigned long new_pulse_down_ = 0;
18
static char new_pulse_interrupt_;
21
// ISR to handle the PPM signals
22
inline void signal_handler( int interrupt, int pin )
24
// record rising/falling edge
25
if( digitalRead( pin ) )
26
new_pulse_up_[ interrupt ] = micros();
28
new_pulse_down_ = micros();
30
// record which interrupt just had a falling edge
31
new_pulse_interrupt_ = interrupt;
36
static void signal_handler_0()
38
signal_handler( 0, 2 );
42
static void signal_handler_1()
44
signal_handler( 1, 3 );
48
void Receiver::setup()
50
// set up an interrupts
51
attachInterrupt( 0, signal_handler_0, CHANGE );
52
attachInterrupt( 1, signal_handler_1, CHANGE );
53
digitalWrite( 2, LOW );
54
digitalWrite( 3, LOW );
58
static unsigned long calculate_duration( unsigned long then, unsigned long now )
63
return now + ( ULONG_MAX - then );
69
bool Receiver::read_channels( int channel_values[] )
71
static unsigned long last_pulse_down = 0;
72
static int next_channel = 0;
74
// capture pulse values atomically
76
unsigned long pulse_up = new_pulse_up_[ (int)new_pulse_interrupt_ ];
77
unsigned long pulse_down = new_pulse_down_;
78
char new_pulse_interrupt = new_pulse_interrupt_;
81
// if the amount of time that has passed since the last falling edge is
82
// greater than the frame gap, reset the next channel so that we can start
85
new_pulse_interrupt == 1 &&
86
calculate_duration( pulse_down, micros() ) > MIN_FRAME_GAP_WIDTH )
88
// reset the next channel (which restarts reading them)
92
// check for a new complete pulse
93
if( pulse_down != last_pulse_down )
95
// are there still pulses to read?
96
if( next_channel < NUM_CHANNELS )
98
unsigned long duration =
99
calculate_duration( pulse_up, pulse_down );
101
// does this pulse look ok?
102
if( duration >= MIN_PULSE_WIDTH &&
103
duration <= MAX_PULSE_WIDTH )
105
// store channel value
106
int channel = channel_order_[ next_channel ] - 1;
107
channel_values[ channel ] = MAX_CHANNEL_VALUE *
108
( duration - MIN_PULSE_WIDTH ) /
109
( MAX_PULSE_WIDTH - MIN_PULSE_WIDTH );
115
// set invalid channel number (to indicate error)
116
next_channel = NUM_CHANNELS + 1;
120
last_pulse_down = pulse_down;
123
// if we've read a frame, invalidate the frame (so we don't report it a
124
// second time) and return true
125
if( next_channel == NUM_CHANNELS ) {