/**********************************************************/
+/* this structure is filled when cmd_rc_proto_timers is parsed successfully */
+struct cmd_rc_proto_timers_result {
+ fixed_string_t arg0;
+ fixed_string_t arg1;
+ uint16_t servo_min;
+ uint16_t servo_max;
+ uint16_t power_probe;
+ uint16_t autobypass;
+};
+
+static void cmd_rc_proto_timers_parsed(void *parsed_result, void *data)
+{
+ struct cmd_rc_proto_timers_result *res = parsed_result;
+ (void)data;
+
+ if (!strcmp_P(res->arg1, PSTR("set"))) {
+ rc_proto_timers.send_servo_min_ms = res->servo_min;
+ rc_proto_timers.send_servo_max_ms = res->servo_max;
+ rc_proto_timers.send_power_probe_ms = res->power_probe;
+ rc_proto_timers.autobypass_ms = res->autobypass;
+ }
+
+ printf_P(PSTR("rc_proto_timers: min=%d, max=%d, "
+ "power_probe=%d autobypass=%d\n"),
+ rc_proto_timers.send_servo_min_ms,
+ rc_proto_timers.send_servo_max_ms,
+ rc_proto_timers.send_power_probe_ms,
+ rc_proto_timers.autobypass_ms);
+}
+
+const char PROGMEM str_rc_proto_timers_arg0[] = "rc_proto_timers";
+const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg0 =
+ TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg0,
+ str_rc_proto_timers_arg0);
+const char PROGMEM str_rc_proto_timers_arg1[] = "set";
+const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1,
+ str_rc_proto_timers_arg1);
+const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_min =
+ TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_min,
+ UINT16);
+const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_max =
+ TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_max,
+ UINT16);
+const parse_token_num_t PROGMEM cmd_rc_proto_timers_power_probe =
+ TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, power_probe,
+ UINT16);
+const parse_token_num_t PROGMEM cmd_rc_proto_timers_autobypass =
+ TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, autobypass,
+ UINT16);
+
+const char PROGMEM help_rc_proto_timers[] = "set rc_proto_timers (servo_min, "
+ "servo_max, pow_probe, autobypass)";
+const parse_inst_t PROGMEM cmd_rc_proto_timers = {
+ .f = cmd_rc_proto_timers_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = help_rc_proto_timers,
+ .tokens = { /* token list, NULL terminated */
+ (PGM_P)&cmd_rc_proto_timers_arg0,
+ (PGM_P)&cmd_rc_proto_timers_arg1,
+ (PGM_P)&cmd_rc_proto_timers_servo_min,
+ (PGM_P)&cmd_rc_proto_timers_servo_max,
+ (PGM_P)&cmd_rc_proto_timers_power_probe,
+ (PGM_P)&cmd_rc_proto_timers_autobypass,
+ NULL,
+ },
+};
+
+const char PROGMEM str_rc_proto_timers_show_arg1[] = "show";
+const parse_token_string_t PROGMEM cmd_rc_proto_timers_show_arg1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1,
+ str_rc_proto_timers_show_arg1);
+
+const char PROGMEM help_rc_proto_timers_show[] = "show rc_proto timers value";
+const parse_inst_t PROGMEM cmd_rc_proto_timers_show = {
+ .f = cmd_rc_proto_timers_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = help_rc_proto_timers_show,
+ .tokens = { /* token list, NULL terminated */
+ (PGM_P)&cmd_rc_proto_timers_arg0,
+ (PGM_P)&cmd_rc_proto_timers_show_arg1,
+ NULL,
+ },
+};
+
+/**********************************************************/
+
/* this structure is filled when cmd_rc_proto_mode is parsed successfully */
struct cmd_rc_proto_mode_result {
fixed_string_t arg0;
&cmd_test_spi,
&cmd_dump_xbee_stats,
&cmd_rc_proto_stats,
+ &cmd_rc_proto_timers,
+ &cmd_rc_proto_timers_show,
&cmd_rc_proto_mode,
&cmd_rc_proto_mode2,
&cmd_rc_proto_mode3,
#define RX_DB_THRESHOLD 65 /* mean -65 dB */
-/* XXX make it configurable */
-/* min time between 2 servo_send */
-#define SEND_SERVO_MIN_TIME_MS 50
-/* max time between 2 servo_send */
-#define SEND_SERVO_MAX_TIME_MS 300
-/* time before switching into bypass mode when no servo command received */
-#define AUTO_BYPASS_TIME_MS 500
+/* default values */
+struct rc_proto_timers rc_proto_timers = {
+ .send_servo_min_ms = 50,
+ .send_servo_max_ms = 300,
+ .send_power_probe_ms = 500,
+ .autobypass_ms = 500,
+};
/* rc_proto statistics, accessed with sched_prio=XBEE_PRIO */
struct rc_proto_stats_data {
/* if we transmitted servos values recently, nothing to do */
ms = get_time_ms();
diff = ms - servo_tx.time;
- if (diff < SEND_SERVO_MIN_TIME_MS)
+ if (diff < rc_proto_timers.send_servo_min_ms)
return 0;
/* prepare values to send */
/* if no value changed and last message is acknowledged, don't transmit
* if we already transmitted quite recently */
if (updated == 0 && ack == servo_tx.seq &&
- diff < SEND_SERVO_MAX_TIME_MS)
+ diff < rc_proto_timers.send_servo_max_ms)
return 0;
/* ok, we need to transmit */
/* send power probe periodically */
if (rc_proto_flags & RC_PROTO_FLAGS_TX_POW_PROBE) {
diff = t - prev_power_probe;
- if (diff > AUTO_BYPASS_TIME_MS) {
+ if (diff > rc_proto_timers.send_power_probe_ms) {
pow_probe++;
if (pow_probe > 4)
pow_probe = 0;
/* on wing, auto bypass servos if no commands since some time */
if (rc_proto_flags & RC_PROTO_FLAGS_RX_AUTOBYPASS) {
diff = t - servo_rx.time;
- if (diff > AUTO_BYPASS_TIME_MS)
+ if (diff > rc_proto_timers.autobypass_ms)
spi_servo_set_bypass(1);
}
struct rc_proto_echo_req {
uint8_t type;
int8_t power;
+ uint16_t timestamp; /* copied as-is in answer */
uint8_t datalen; /* len of data excluding header */
uint8_t data[];
} __attribute__((packed));
#define RC_PROTO_ECHO_ANS 0x02
struct rc_proto_echo_ans {
uint8_t type;
+ uint16_t timestamp;
uint8_t datalen; /* len of data excluding header */
uint8_t data[];
} __attribute__((packed));
uint8_t stats[]; /* format is struct rc_proto_stats_data */
} __attribute__((packed));
+/* rc_proto timers configuration */
+struct rc_proto_timers {
+ uint16_t send_servo_min_ms;
+ uint16_t send_servo_max_ms;
+ uint16_t send_power_probe_ms;
+ uint16_t autobypass_ms;
+};
+extern struct rc_proto_timers rc_proto_timers;
+
/* send a Hello message to a peer */
int8_t rc_proto_send_hello(uint64_t addr, void *data, uint8_t data_len,
int8_t power);