Device/event framework optimisation (#3049)
[ExpressLRS.git] / src / lib / Handset / PPMHandset.cpp
blob9e9cc41560973139f295be7dc3ed6497f9a35ee0
1 #include "targets.h"
3 #if defined(PLATFORM_ESP32) && defined(TARGET_TX)
5 #include "PPMHandset.h"
6 #include "common.h"
7 #include "crsf_protocol.h"
8 #include "logging.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);
26 lastPPM = 0;
28 if (connected)
30 connected();
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();
48 size_t length = 0;
50 auto *items = static_cast<rmt_item32_t *>(xRingbufferReceive(rb, &length, 0));
51 if (items)
53 length /= 4; // one RMT = 4 Bytes
54 int channelCount = 0;
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)
61 break;
63 channelCount ++;
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));
69 lastPPM = now;
71 else if (lastPPM && now - 1000 > lastPPM)
73 DBGLN("PPM signal lost, disarming");
74 if (disconnected)
76 disconnected();
78 lastPPM = 0;
82 #endif