63static const char *
const TAG =
"ld2420";
66static constexpr uint16_t REFRESH_RATE_MS = 1000;
69static constexpr uint16_t CMD_DISABLE_CONF = 0x00FE;
70static constexpr uint16_t CMD_ENABLE_CONF = 0x00FF;
71static constexpr uint16_t CMD_PARM_HIGH_TRESH = 0x0012;
72static constexpr uint16_t CMD_PARM_LOW_TRESH = 0x0021;
73static constexpr uint16_t CMD_PROTOCOL_VER = 0x0002;
74static constexpr uint16_t CMD_READ_ABD_PARAM = 0x0008;
75static constexpr uint16_t CMD_READ_REG_ADDR = 0x0020;
76static constexpr uint16_t CMD_READ_REGISTER = 0x0002;
77static constexpr uint16_t CMD_READ_SERIAL_NUM = 0x0011;
78static constexpr uint16_t CMD_READ_SYS_PARAM = 0x0013;
79static constexpr uint16_t CMD_READ_VERSION = 0x0000;
80static constexpr uint16_t CMD_RESTART = 0x0068;
81static constexpr uint16_t CMD_SYSTEM_MODE = 0x0000;
82static constexpr uint16_t CMD_SYSTEM_MODE_GR = 0x0003;
83static constexpr uint16_t CMD_SYSTEM_MODE_MTT = 0x0001;
84static constexpr uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064;
85static constexpr uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000;
86static constexpr uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004;
87static constexpr uint16_t CMD_SYSTEM_MODE_VS = 0x0002;
88static constexpr uint16_t CMD_WRITE_ABD_PARAM = 0x0007;
89static constexpr uint16_t CMD_WRITE_REGISTER = 0x0001;
90static constexpr uint16_t CMD_WRITE_SYS_PARAM = 0x0012;
92static constexpr uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04;
93static constexpr uint8_t CMD_ABD_DATA_REPLY_START = 0x0A;
94static constexpr uint8_t CMD_MAX_BYTES = 0x64;
95static constexpr uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02;
97static constexpr uint8_t LD2420_ERROR_NONE = 0x00;
98static constexpr uint8_t LD2420_ERROR_TIMEOUT = 0x02;
99static constexpr uint8_t LD2420_ERROR_UNKNOWN = 0x01;
102static constexpr uint16_t CMD_MIN_GATE_REG = 0x0000;
103static constexpr uint16_t CMD_MAX_GATE_REG = 0x0001;
104static constexpr uint16_t CMD_TIMEOUT_REG = 0x0004;
105static constexpr uint16_t CMD_GATE_MOVE_THRESH[TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015,
106 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B,
107 0x001C, 0x001D, 0x001E, 0x001F};
108static constexpr uint16_t CMD_GATE_STILL_THRESH[TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025,
109 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B,
110 0x002C, 0x002D, 0x002E, 0x002F};
111static constexpr uint32_t FACTORY_MOVE_THRESH[TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250,
112 250, 250, 250, 250, 250, 250, 250, 250};
113static constexpr uint32_t FACTORY_STILL_THRESH[TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150,
114 150, 100, 100, 100, 100, 100, 100, 100};
115static constexpr uint16_t FACTORY_TIMEOUT = 120;
116static constexpr uint16_t FACTORY_MIN_GATE = 1;
117static constexpr uint16_t FACTORY_MAX_GATE = 12;
120static constexpr uint32_t CMD_FRAME_FOOTER = 0x01020304;
121static constexpr uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD;
122static constexpr uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD;
123static constexpr uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA;
124static constexpr uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8;
125static constexpr uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4;
126static constexpr int CALIBRATE_VERSION_MIN = 154;
127static constexpr uint8_t CMD_FRAME_COMMAND = 6;
128static constexpr uint8_t CMD_FRAME_DATA_LENGTH = 4;
129static constexpr uint8_t CMD_FRAME_STATUS = 7;
130static constexpr uint8_t CMD_ERROR_WORD = 8;
131static constexpr uint8_t ENERGY_SENSOR_START = 9;
132static constexpr uint8_t CALIBRATE_REPORT_INTERVAL = 4;
133static const char *
const OP_NORMAL_MODE_STRING =
"Normal";
134static const char *
const OP_SIMPLE_MODE_STRING =
"Simple";
137struct StringToUint8 {
142static constexpr StringToUint8 OP_MODE_BY_STR[] = {
148static constexpr const char *ERR_MESSAGE[] = {
155template<
size_t N> uint8_t
find_uint8(
const StringToUint8 (&arr)[N],
const std::string &str) {
156 for (
const auto &entry : arr) {
157 if (str == entry.str) {
164static uint8_t calc_checksum(
void *data,
size_t size) {
166 uint8_t *data_bytes = (uint8_t *) data;
167 for (
size_t i = 0; i <
size; i++) {
173static int get_firmware_int(
const char *version_string) {
174 std::string version_str = version_string;
175 if (version_str[0] ==
'v') {
176 version_str.erase(0, 1);
178 version_str.erase(remove(version_str.begin(), version_str.end(),
'.'), version_str.end());
179 int version_integer =
stoi(version_str);
180 return version_integer;
188 " Firmware version: %7s",
191 ESP_LOGCONFIG(TAG,
"Number:");
196 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
208 ESP_LOGCONFIG(TAG,
"Select:");
211 if (ld2420::get_firmware_int(this->
firmware_ver_) < CALIBRATE_VERSION_MIN) {
212 ESP_LOGW(TAG,
"Firmware version %s and older supports Simple Mode only", this->
firmware_ver_);
218 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
228 std::string fw_str(pfw);
231 listener->on_fw_version(fw_str);
234 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
240 if (ld2420::get_firmware_int(this->
firmware_ver_) < CALIBRATE_VERSION_MIN) {
248 ESP_LOGW(TAG,
"Firmware version %s and older supports Simple Mode only", this->
firmware_ver_);
267 ESP_LOGD(TAG,
"No configuration change detected");
270 ESP_LOGD(TAG,
"Reconfiguring");
272 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
277 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
291 ESP_LOGD(TAG,
"Setting factory defaults");
293 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
303 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
319 ESP_LOGD(TAG,
"Restarting");
333 ESP_LOGD(TAG,
"Reverted config number edits");
345 for (uint8_t gate = 0; gate < TOTAL_GATES; ++gate) {
346 this->
radar_data[gate][sample_number] = gate_energy[gate];
355 for (uint8_t gate = 0; gate < TOTAL_GATES; ++gate) {
359 for (uint8_t sample_number = 0; sample_number < CALIBRATE_SAMPLES; ++sample_number) {
364 if (this->
radar_data[gate][sample_number] > peak) {
370 this->
gate_avg[gate] = sum / CALIBRATE_SAMPLES;
375 uint32_t calculated_value =
376 (
static_cast<uint32_t
>(this->
gate_peak[gate]) + (move_factor *
static_cast<uint32_t
>(this->
gate_peak[gate])));
377 this->
new_config.
move_thresh[gate] =
static_cast<uint16_t
>(calculated_value <= 65535 ? calculated_value : 65535);
379 (
static_cast<uint32_t
>(this->
gate_peak[gate]) + (still_factor *
static_cast<uint32_t
>(this->
gate_peak[gate])));
380 this->
new_config.
still_thresh[gate] =
static_cast<uint16_t
>(calculated_value <= 65535 ? calculated_value : 65535);
385 for (uint8_t gate = 0; gate < TOTAL_GATES; ++gate) {
387 ESP_LOGI(TAG,
"Gate: %2d Avg: %5d Peak: %5d", gate, this->
gate_avg[gate], this->
gate_peak[gate]);
394 if (ld2420::get_firmware_int(
firmware_ver_) >= CALIBRATE_VERSION_MIN) {
404 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
407 for (uint8_t i = 0; i < CALIBRATE_SAMPLES; i++) {
438 ESP_LOGW(TAG,
"Max command length exceeded; ignoring");
444 if (memcmp(&buffer[this->
buffer_pos_ - 4], &CMD_FRAME_FOOTER,
sizeof(CMD_FRAME_FOOTER)) == 0) {
449 (this->
get_mode_() == CMD_SYSTEM_MODE_SIMPLE)) {
452 }
else if ((memcmp(&buffer[this->
buffer_pos_ - 4], &ENERGY_FRAME_FOOTER,
sizeof(ENERGY_FRAME_FOOTER)) == 0) &&
453 (this->
get_mode_() == CMD_SYSTEM_MODE_ENERGY)) {
465 memcpy(&
range, &buffer[index],
sizeof(
range));
466 index +=
sizeof(
range);
468 for (uint8_t i = 0; i < elements; i++) {
500 const uint8_t bufsize = 16;
503 char *endptr{
nullptr};
504 char outbuf[bufsize]{0};
506 if (inbuf[
pos - 2] ==
'O' && inbuf[
pos - 1] ==
'F' && inbuf[
pos] ==
'F') {
508 }
else if (inbuf[
pos - 1] ==
'O' && inbuf[
pos] ==
'N') {
511 if (inbuf[
pos] >=
'0' && inbuf[
pos] <=
'9') {
512 if (index < bufsize - 1) {
513 outbuf[index++] = inbuf[
pos];
524 outbuf[index] =
'\0';
529 if (this->
get_mode_() == CMD_SYSTEM_MODE_SIMPLE) {
538 for (
auto &listener : this->listeners_)
546 uint8_t buf[MAX_LINE_LENGTH];
548 size_t to_read = std::min(avail,
sizeof(buf));
554 for (
size_t i = 0; i < to_read; i++) {
555 this->
readline_(buf[i], buffer.data(), buffer.size());
563 uint16_t data_pos = 0;
565 ESP_LOGW(TAG,
"Reply frame too long");
568 ESP_LOGW(TAG,
"Command frame too short");
571 memcpy(&this->
cmd_reply_.
error, &buffer[CMD_ERROR_WORD],
sizeof(this->cmd_reply_.error));
578 case (CMD_ENABLE_CONF):
579 ESP_LOGV(TAG,
"Set config enable: CMD = %2X %s", CMD_ENABLE_CONF, result);
581 case (CMD_DISABLE_CONF):
582 ESP_LOGV(TAG,
"Set config disable: CMD = %2X %s", CMD_DISABLE_CONF, result);
584 case (CMD_READ_REGISTER): {
585 ESP_LOGV(TAG,
"Read register: CMD = %2X %s", CMD_READ_REGISTER, result);
588 uint16_t reg_count = std::min<uint16_t>((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_REG_DATA_REPLY_SIZE,
589 sizeof(this->
cmd_reply_.
data) /
sizeof(this->cmd_reply_.data[0]));
590 for (uint16_t i = 0; i < reg_count; i++) {
591 memcpy(&this->
cmd_reply_.
data[i], &buffer[data_pos + i * CMD_REG_DATA_REPLY_SIZE], CMD_REG_DATA_REPLY_SIZE);
595 case (CMD_WRITE_REGISTER):
596 ESP_LOGV(TAG,
"Write register: CMD = %2X %s", CMD_WRITE_REGISTER, result);
598 case (CMD_WRITE_ABD_PARAM):
599 ESP_LOGV(TAG,
"Write gate parameter(s): %2X %s", CMD_WRITE_ABD_PARAM, result);
601 case (CMD_READ_ABD_PARAM): {
602 ESP_LOGV(TAG,
"Read gate parameter(s): %2X %s", CMD_READ_ABD_PARAM, result);
603 data_pos = CMD_ABD_DATA_REPLY_START;
604 uint16_t abd_count = std::min<uint16_t>((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_ABD_DATA_REPLY_SIZE,
605 sizeof(this->
cmd_reply_.
data) /
sizeof(this->cmd_reply_.data[0]));
606 for (uint16_t i = 0; i < abd_count; i++) {
607 memcpy(&this->
cmd_reply_.
data[i], &buffer[data_pos + i * CMD_ABD_DATA_REPLY_SIZE],
608 sizeof(this->cmd_reply_.data[i]));
612 case (CMD_WRITE_SYS_PARAM):
613 ESP_LOGV(TAG,
"Set system parameter(s): %2X %s", CMD_WRITE_SYS_PARAM, result);
615 case (CMD_READ_VERSION): {
616 uint8_t ver_len = std::min<uint8_t>(buffer[10],
sizeof(this->
firmware_ver_) - 1);
619 ESP_LOGV(TAG,
"Firmware version: %s %s", this->
firmware_ver_, result);
628 uint32_t start_millis =
millis();
630 uint8_t ack_buffer[MAX_LINE_LENGTH];
631 uint8_t cmd_buffer[MAX_LINE_LENGTH];
633 if (frame.
command != CMD_RESTART) {
650 for (uint16_t index = 0; index < frame.
data_length; index++) {
651 memcpy(&cmd_buffer[frame.
length], &frame.
data[index],
sizeof(frame.
data[index]));
660 if (frame.
command == CMD_RESTART) {
666 this->
readline_(this->
read(), ack_buffer,
sizeof(ack_buffer));
670 if ((
millis() - start_millis) > 1000) {
672 error = LD2420_ERROR_TIMEOUT;
690 cmd_frame.
header = CMD_FRAME_HEADER;
691 cmd_frame.
command = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
693 memcpy(&cmd_frame.
data[0], &CMD_PROTOCOL_VER,
sizeof(CMD_PROTOCOL_VER));
696 cmd_frame.
footer = CMD_FRAME_FOOTER;
697 ESP_LOGV(TAG,
"Sending set config %s command: %2X", enable ?
"enable" :
"disable", cmd_frame.
command);
707 cmd_frame.
header = CMD_FRAME_HEADER;
708 cmd_frame.
command = CMD_RESTART;
709 cmd_frame.
footer = CMD_FRAME_FOOTER;
710 ESP_LOGV(TAG,
"Sending restart command: %2X", cmd_frame.
command);
717 cmd_frame.
header = CMD_FRAME_HEADER;
718 cmd_frame.
command = CMD_READ_REGISTER;
719 cmd_frame.
data[1] = reg;
721 cmd_frame.
footer = CMD_FRAME_FOOTER;
722 ESP_LOGV(TAG,
"Sending read register %4X command: %2X", reg, cmd_frame.
command);
729 cmd_frame.
header = CMD_FRAME_HEADER;
730 cmd_frame.
command = CMD_WRITE_REGISTER;
731 memcpy(&cmd_frame.
data[cmd_frame.
data_length], ®, CMD_REG_DATA_REPLY_SIZE);
733 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &value, CMD_REG_DATA_REPLY_SIZE);
735 cmd_frame.
footer = CMD_FRAME_FOOTER;
736 ESP_LOGV(TAG,
"Sending write register %4X command: %2X data = %4X", reg, cmd_frame.
command, value);
746 cmd_frame.
header = CMD_FRAME_HEADER;
747 cmd_frame.
command = CMD_READ_ABD_PARAM;
748 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &CMD_GATE_MOVE_THRESH[gate],
sizeof(CMD_GATE_MOVE_THRESH[gate]));
750 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &CMD_GATE_STILL_THRESH[gate],
sizeof(CMD_GATE_STILL_THRESH[gate]));
752 cmd_frame.
footer = CMD_FRAME_FOOTER;
753 ESP_LOGV(TAG,
"Sending read gate %d high/low threshold command: %2X", gate, cmd_frame.
command);
766 cmd_frame.
header = CMD_FRAME_HEADER;
767 cmd_frame.
command = CMD_READ_ABD_PARAM;
769 sizeof(CMD_MIN_GATE_REG));
772 sizeof(CMD_MAX_GATE_REG));
775 sizeof(CMD_TIMEOUT_REG));
777 cmd_frame.
footer = CMD_FRAME_FOOTER;
778 ESP_LOGV(TAG,
"Sending read gate min max and timeout command: %2X", cmd_frame.
command);
790 uint16_t unknown_parm = 0x0000;
792 cmd_frame.
header = CMD_FRAME_HEADER;
793 cmd_frame.
command = CMD_WRITE_SYS_PARAM;
794 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &CMD_SYSTEM_MODE,
sizeof(CMD_SYSTEM_MODE));
798 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &unknown_parm,
sizeof(unknown_parm));
800 cmd_frame.
footer = CMD_FRAME_FOOTER;
801 ESP_LOGV(TAG,
"Sending write system mode command: %2X", cmd_frame.
command);
810 cmd_frame.
header = CMD_FRAME_HEADER;
811 cmd_frame.
command = CMD_READ_VERSION;
812 cmd_frame.
footer = CMD_FRAME_FOOTER;
814 ESP_LOGV(TAG,
"Sending read firmware version command: %2X", cmd_frame.
command);
827 cmd_frame.
header = CMD_FRAME_HEADER;
828 cmd_frame.
command = CMD_WRITE_ABD_PARAM;
830 sizeof(CMD_MIN_GATE_REG));
832 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &min_gate_distance,
sizeof(min_gate_distance));
833 cmd_frame.
data_length +=
sizeof(min_gate_distance);
835 sizeof(CMD_MAX_GATE_REG));
837 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &max_gate_distance,
sizeof(max_gate_distance));
838 cmd_frame.
data_length +=
sizeof(max_gate_distance);
840 sizeof(CMD_TIMEOUT_REG));
842 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &timeout,
sizeof(timeout));
845 cmd_frame.
footer = CMD_FRAME_FOOTER;
847 ESP_LOGV(TAG,
"Sending write gate min max and timeout command: %2X", cmd_frame.
command);
856 uint16_t move_threshold_gate = CMD_GATE_MOVE_THRESH[gate];
857 uint16_t still_threshold_gate = CMD_GATE_STILL_THRESH[gate];
860 cmd_frame.
header = CMD_FRAME_HEADER;
861 cmd_frame.
command = CMD_WRITE_ABD_PARAM;
862 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &move_threshold_gate,
sizeof(move_threshold_gate));
863 cmd_frame.
data_length +=
sizeof(move_threshold_gate);
864 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &this->new_config.move_thresh[gate],
865 sizeof(this->new_config.move_thresh[gate]));
867 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &still_threshold_gate,
sizeof(still_threshold_gate));
868 cmd_frame.
data_length +=
sizeof(still_threshold_gate);
869 memcpy(&cmd_frame.
data[cmd_frame.
data_length], &this->new_config.still_thresh[gate],
870 sizeof(this->new_config.still_thresh[gate]));
872 cmd_frame.
footer = CMD_FRAME_FOOTER;
873 ESP_LOGV(TAG,
"Sending set gate %4X sensitivity command: %2X", gate, cmd_frame.
command);
897 for (uint8_t gate = 0; gate < TOTAL_GATES; gate++) {
BedjetMode mode
BedJet operating mode.
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void mark_failed()
Mark this component as failed.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
void dump_config() override
void init_gate_config_numbers()
void readline_(int rx_data, uint8_t *buffer, int len)
void set_system_mode(uint16_t mode)
void handle_ack_data_(uint8_t *buffer, int len)
void revert_config_action()
float gate_still_sensitivity_factor
int32_t last_periodic_millis
void restart_module_action()
std::vector< number::Number * > gate_still_threshold_numbers_
number::Number * gate_select_number_
uint8_t set_config_mode(bool enable)
button::Button * factory_reset_button_
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number)
float get_setup_priority() const override
void send_module_restart()
void set_distance_(uint16_t distance)
void set_min_max_distances_timeout(uint32_t max_gate_distance, uint32_t min_gate_distance, uint32_t timeout)
void set_gate_threshold(uint8_t gate)
void handle_energy_mode_(uint8_t *buffer, int len)
button::Button * revert_config_button_
void auto_calibrate_sensitivity()
void set_calibration_(bool state)
number::Number * min_gate_distance_number_
button::Button * apply_config_button_
int32_t report_periodic_millis
uint16_t gate_peak[TOTAL_GATES]
std::vector< LD2420Listener * > listeners_
void get_firmware_version_()
std::vector< number::Number * > gate_move_threshold_numbers_
float gate_move_sensitivity_factor
void set_mode_(uint16_t mode)
void apply_config_action()
uint16_t gate_avg[TOTAL_GATES]
void read_batch_(std::span< uint8_t, MAX_LINE_LENGTH > buffer)
RegConfigT current_config
uint8_t buffer_data_[MAX_LINE_LENGTH]
int get_gate_threshold_(uint8_t gate)
number::Number * gate_still_sensitivity_factor_number_
void handle_cmd_error(uint8_t error)
void factory_reset_action()
int send_cmd_from_array(CmdFrameT cmd_frame)
void get_reg_value_(uint16_t reg)
void refresh_gate_config_numbers()
uint16_t gate_energy_[TOTAL_GATES]
int32_t last_normal_periodic_millis
void handle_simple_mode_(const uint8_t *inbuf, int len)
number::Number * max_gate_distance_number_
select::Select * operating_selector_
button::Button * restart_module_button_
int get_min_max_distances_timeout_()
number::Number * gate_timeout_number_
uint16_t total_sample_number_counter
void set_operating_mode(const char *state)
uint8_t current_operating_mode
uint16_t radar_data[TOTAL_GATES][CALIBRATE_SAMPLES]
uint8_t sample_number_counter
void set_presence_(bool presence)
number::Number * gate_move_sensitivity_factor_number_
void set_reg_value(uint16_t reg, uint16_t value)
void publish_state(float state)
void publish_state(const std::string &state)
optional< std::array< uint8_t, N > > read_array()
void write_array(const uint8_t *data, size_t len)
uint8_t find_uint8(const StringToUint8(&arr)[N], const std::string &str)
constexpr float BUS
For communication buses like i2c/spi.
void IRAM_ATTR HOT delay_microseconds_safe(uint32_t us)
Delay for the given amount of microseconds, possibly yielding to other processes during the wait.
int stoi(const StringRef &str, size_t *pos=nullptr, int base=10)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
uint32_t move_thresh[TOTAL_GATES]
uint32_t still_thresh[TOTAL_GATES]