3 #if defined(PLATFORM_ESP32) && defined(TARGET_TX)
5 #include "PPMHandset.h"
7 #include "crsf_protocol.h"
10 #include <driver/rmt.h>
12 constexpr auto RMT_TICKS_PER_US
= 4;
14 void PPMHandset::Begin()
16 constexpr auto divisor
= 80 / RMT_TICKS_PER_US
;
18 rmt_config_t rmt_rx_config
= RMT_DEFAULT_CONFIG_RX(static_cast<gpio_num_t
>(GPIO_PIN_RCSIGNAL_RX
), PPM_RMT_CHANNEL
);
19 rmt_rx_config
.clk_div
= divisor
;
20 rmt_rx_config
.rx_config
.idle_threshold
= min(65000, RMT_TICKS_PER_US
* 4000); // greater than 4ms triggers end of frame
21 rmt_config(&rmt_rx_config
);
22 rmt_driver_install(PPM_RMT_CHANNEL
, 1000, 0);
24 rmt_get_ringbuf_handle(PPM_RMT_CHANNEL
, &rb
);
25 rmt_rx_start(PPM_RMT_CHANNEL
, true);
34 void PPMHandset::End()
36 rmt_driver_uninstall(PPM_RMT_CHANNEL
);
39 bool PPMHandset::IsArmed()
41 bool maybeArmed
= numChannels
< 5 || CRSF_to_BIT(ChannelData
[4]);
42 return maybeArmed
&& lastPPM
;
45 void PPMHandset::handleInput()
47 const auto now
= millis();
50 auto *items
= static_cast<rmt_item32_t
*>(xRingbufferReceive(rb
, &length
, 0));
53 length
/= 4; // one RMT = 4 Bytes
55 for (int i
= 0; i
< length
; i
++)
57 const auto item
= items
[i
];
58 // Stop if there is a 0 duration
59 if (item
.duration0
== 0 || item
.duration1
== 0)
64 const auto ppm
= (item
.duration0
+ item
.duration1
) / RMT_TICKS_PER_US
;
65 ChannelData
[i
] = fmap(ppm
, 988, 2012, CRSF_CHANNEL_VALUE_MIN
, CRSF_CHANNEL_VALUE_MAX
);
67 numChannels
= channelCount
;
68 vRingbufferReturnItem(rb
, static_cast<void *>(items
));
71 else if (lastPPM
&& now
- 1000 > lastPPM
)
73 DBGLN("PPM signal lost, disarming");